📄 jitarithmetic.cpp
字号:
/* * Copyright (C) 2008 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */#include "config.h"#include "JIT.h"#if ENABLE(JIT)#include "CodeBlock.h"#include "JITInlineMethods.h"#include "JSArray.h"#include "JSFunction.h"#include "Interpreter.h"#include "ResultType.h"#include "SamplingTool.h"#ifndef NDEBUG#include <stdio.h>#endif#define __ m_assembler.using namespace std;namespace JSC {void JIT::compileFastArith_op_lshift(unsigned result, unsigned op1, unsigned op2){ emitGetVirtualRegisters(op1, regT0, op2, regT2); // FIXME: would we be better using 'emitJumpSlowCaseIfNotImmediateIntegers'? - we *probably* ought to be consistent. emitJumpSlowCaseIfNotImmediateInteger(regT0); emitJumpSlowCaseIfNotImmediateInteger(regT2); emitFastArithImmToInt(regT0); emitFastArithImmToInt(regT2);#if !PLATFORM(X86) // Mask with 0x1f as per ecma-262 11.7.2 step 7. // On 32-bit x86 this is not necessary, since the shift anount is implicitly masked in the instruction. and32(Imm32(0x1f), regT2);#endif lshift32(regT2, regT0);#if !USE(ALTERNATE_JSIMMEDIATE) addSlowCase(branchAdd32(Overflow, regT0, regT0)); signExtend32ToPtr(regT0, regT0);#endif emitFastArithReTagImmediate(regT0, regT0); emitPutVirtualRegister(result);}void JIT::compileFastArithSlow_op_lshift(unsigned result, unsigned op1, unsigned op2, Vector<SlowCaseEntry>::iterator& iter){#if USE(ALTERNATE_JSIMMEDIATE) UNUSED_PARAM(op1); UNUSED_PARAM(op2); linkSlowCase(iter); linkSlowCase(iter);#else // If we are limited to 32-bit immediates there is a third slow case, which required the operands to have been reloaded. Jump notImm1 = getSlowCase(iter); Jump notImm2 = getSlowCase(iter); linkSlowCase(iter); emitGetVirtualRegisters(op1, regT0, op2, regT2); notImm1.link(this); notImm2.link(this);#endif emitPutJITStubArg(regT0, 1); emitPutJITStubArg(regT2, 2); emitCTICall(JITStubs::cti_op_lshift); emitPutVirtualRegister(result);}void JIT::compileFastArith_op_rshift(unsigned result, unsigned op1, unsigned op2){ if (isOperandConstantImmediateInt(op2)) { emitGetVirtualRegister(op1, regT0); emitJumpSlowCaseIfNotImmediateInteger(regT0); // Mask with 0x1f as per ecma-262 11.7.2 step 7.#if USE(ALTERNATE_JSIMMEDIATE) rshift32(Imm32(getConstantOperandImmediateInt(op2) & 0x1f), regT0);#else rshiftPtr(Imm32(getConstantOperandImmediateInt(op2) & 0x1f), regT0);#endif } else { emitGetVirtualRegisters(op1, regT0, op2, regT2); emitJumpSlowCaseIfNotImmediateInteger(regT0); emitJumpSlowCaseIfNotImmediateInteger(regT2); emitFastArithImmToInt(regT2);#if !PLATFORM(X86) // Mask with 0x1f as per ecma-262 11.7.2 step 7. // On 32-bit x86 this is not necessary, since the shift anount is implicitly masked in the instruction. and32(Imm32(0x1f), regT2);#endif#if USE(ALTERNATE_JSIMMEDIATE) rshift32(regT2, regT0);#else rshiftPtr(regT2, regT0);#endif }#if USE(ALTERNATE_JSIMMEDIATE) emitFastArithIntToImmNoCheck(regT0, regT0);#else orPtr(Imm32(JSImmediate::TagTypeNumber), regT0);#endif emitPutVirtualRegister(result);}void JIT::compileFastArithSlow_op_rshift(unsigned result, unsigned, unsigned op2, Vector<SlowCaseEntry>::iterator& iter){ linkSlowCase(iter); if (isOperandConstantImmediateInt(op2)) emitPutJITStubArgFromVirtualRegister(op2, 2, regT2); else { linkSlowCase(iter); emitPutJITStubArg(regT2, 2); } emitPutJITStubArg(regT0, 1); emitCTICall(JITStubs::cti_op_rshift); emitPutVirtualRegister(result);}void JIT::compileFastArith_op_bitand(unsigned result, unsigned op1, unsigned op2){ if (isOperandConstantImmediateInt(op1)) { emitGetVirtualRegister(op2, regT0); emitJumpSlowCaseIfNotImmediateInteger(regT0);#if USE(ALTERNATE_JSIMMEDIATE) int32_t imm = getConstantOperandImmediateInt(op1); andPtr(Imm32(imm), regT0); if (imm >= 0) emitFastArithIntToImmNoCheck(regT0, regT0);#else andPtr(Imm32(static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1)))), regT0);#endif } else if (isOperandConstantImmediateInt(op2)) { emitGetVirtualRegister(op1, regT0); emitJumpSlowCaseIfNotImmediateInteger(regT0);#if USE(ALTERNATE_JSIMMEDIATE) int32_t imm = getConstantOperandImmediateInt(op2); andPtr(Imm32(imm), regT0); if (imm >= 0) emitFastArithIntToImmNoCheck(regT0, regT0);#else andPtr(Imm32(static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)))), regT0);#endif } else { emitGetVirtualRegisters(op1, regT0, op2, regT1); andPtr(regT1, regT0); emitJumpSlowCaseIfNotImmediateInteger(regT0); } emitPutVirtualRegister(result);}void JIT::compileFastArithSlow_op_bitand(unsigned result, unsigned op1, unsigned op2, Vector<SlowCaseEntry>::iterator& iter){ linkSlowCase(iter); if (isOperandConstantImmediateInt(op1)) { emitPutJITStubArgFromVirtualRegister(op1, 1, regT2); emitPutJITStubArg(regT0, 2); } else if (isOperandConstantImmediateInt(op2)) { emitPutJITStubArg(regT0, 1); emitPutJITStubArgFromVirtualRegister(op2, 2, regT2); } else { emitPutJITStubArgFromVirtualRegister(op1, 1, regT2); emitPutJITStubArg(regT1, 2); } emitCTICall(JITStubs::cti_op_bitand); emitPutVirtualRegister(result);}#if PLATFORM(X86) || PLATFORM(X86_64)void JIT::compileFastArith_op_mod(unsigned result, unsigned op1, unsigned op2){ emitGetVirtualRegisters(op1, X86::eax, op2, X86::ecx); emitJumpSlowCaseIfNotImmediateInteger(X86::eax); emitJumpSlowCaseIfNotImmediateInteger(X86::ecx);#if USE(ALTERNATE_JSIMMEDIATE) addSlowCase(branchPtr(Equal, X86::ecx, ImmPtr(JSValuePtr::encode(js0())))); m_assembler.cdq(); m_assembler.idivl_r(X86::ecx);#else emitFastArithDeTagImmediate(X86::eax); addSlowCase(emitFastArithDeTagImmediateJumpIfZero(X86::ecx)); m_assembler.cdq(); m_assembler.idivl_r(X86::ecx); signExtend32ToPtr(X86::edx, X86::edx);#endif emitFastArithReTagImmediate(X86::edx, X86::eax); emitPutVirtualRegister(result);}void JIT::compileFastArithSlow_op_mod(unsigned result, unsigned, unsigned, Vector<SlowCaseEntry>::iterator& iter){#if USE(ALTERNATE_JSIMMEDIATE) linkSlowCase(iter); linkSlowCase(iter); linkSlowCase(iter);#else Jump notImm1 = getSlowCase(iter); Jump notImm2 = getSlowCase(iter); linkSlowCase(iter); emitFastArithReTagImmediate(X86::eax, X86::eax); emitFastArithReTagImmediate(X86::ecx, X86::ecx); notImm1.link(this); notImm2.link(this);#endif emitPutJITStubArg(X86::eax, 1); emitPutJITStubArg(X86::ecx, 2); emitCTICall(JITStubs::cti_op_mod); emitPutVirtualRegister(result);}#elsevoid JIT::compileFastArith_op_mod(unsigned result, unsigned op1, unsigned op2){ emitPutJITStubArgFromVirtualRegister(op1, 1, regT2); emitPutJITStubArgFromVirtualRegister(op2, 2, regT2); emitCTICall(JITStubs::cti_op_mod); emitPutVirtualRegister(result);}void JIT::compileFastArithSlow_op_mod(unsigned, unsigned, unsigned, Vector<SlowCaseEntry>::iterator&){ ASSERT_NOT_REACHED();}#endifvoid JIT::compileFastArith_op_post_inc(unsigned result, unsigned srcDst){ emitGetVirtualRegister(srcDst, regT0); move(regT0, regT1); emitJumpSlowCaseIfNotImmediateInteger(regT0);#if USE(ALTERNATE_JSIMMEDIATE) addSlowCase(branchAdd32(Overflow, Imm32(1), regT1)); emitFastArithIntToImmNoCheck(regT1, regT1);#else addSlowCase(branchAdd32(Overflow, Imm32(1 << JSImmediate::IntegerPayloadShift), regT1)); signExtend32ToPtr(regT1, regT1);#endif emitPutVirtualRegister(srcDst, regT1); emitPutVirtualRegister(result);}void JIT::compileFastArithSlow_op_post_inc(unsigned result, unsigned srcDst, Vector<SlowCaseEntry>::iterator& iter){ linkSlowCase(iter); linkSlowCase(iter); emitPutJITStubArg(regT0, 1); emitCTICall(JITStubs::cti_op_post_inc); emitPutVirtualRegister(srcDst, regT1); emitPutVirtualRegister(result);}void JIT::compileFastArith_op_post_dec(unsigned result, unsigned srcDst){ emitGetVirtualRegister(srcDst, regT0); move(regT0, regT1); emitJumpSlowCaseIfNotImmediateInteger(regT0);#if USE(ALTERNATE_JSIMMEDIATE) addSlowCase(branchSub32(Zero, Imm32(1), regT1)); emitFastArithIntToImmNoCheck(regT1, regT1);#else addSlowCase(branchSub32(Zero, Imm32(1 << JSImmediate::IntegerPayloadShift), regT1)); signExtend32ToPtr(regT1, regT1);#endif emitPutVirtualRegister(srcDst, regT1); emitPutVirtualRegister(result);}void JIT::compileFastArithSlow_op_post_dec(unsigned result, unsigned srcDst, Vector<SlowCaseEntry>::iterator& iter){ linkSlowCase(iter); linkSlowCase(iter); emitPutJITStubArg(regT0, 1); emitCTICall(JITStubs::cti_op_post_dec); emitPutVirtualRegister(srcDst, regT1); emitPutVirtualRegister(result);}void JIT::compileFastArith_op_pre_inc(unsigned srcDst){ emitGetVirtualRegister(srcDst, regT0); emitJumpSlowCaseIfNotImmediateInteger(regT0);#if USE(ALTERNATE_JSIMMEDIATE) addSlowCase(branchAdd32(Overflow, Imm32(1), regT0)); emitFastArithIntToImmNoCheck(regT0, regT0);#else addSlowCase(branchAdd32(Overflow, Imm32(1 << JSImmediate::IntegerPayloadShift), regT0)); signExtend32ToPtr(regT0, regT0);#endif emitPutVirtualRegister(srcDst);}void JIT::compileFastArithSlow_op_pre_inc(unsigned srcDst, Vector<SlowCaseEntry>::iterator& iter){ Jump notImm = getSlowCase(iter); linkSlowCase(iter); emitGetVirtualRegister(srcDst, regT0); notImm.link(this); emitPutJITStubArg(regT0, 1); emitCTICall(JITStubs::cti_op_pre_inc); emitPutVirtualRegister(srcDst);}void JIT::compileFastArith_op_pre_dec(unsigned srcDst){ emitGetVirtualRegister(srcDst, regT0); emitJumpSlowCaseIfNotImmediateInteger(regT0);#if USE(ALTERNATE_JSIMMEDIATE)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -