📄 jit.cpp
字号:
emitJumpSlowCaseIfNotImmediateInteger(regT1);#if USE(ALTERNATE_JSIMMEDIATE) // This is technically incorrect - we're zero-extending an int32. On the hot path this doesn't matter. // We check the value as if it was a uint32 against the m_fastAccessCutoff - which will always fail if // number was signed since m_fastAccessCutoff is always less than intmax (since the total allocation // size is always less than 4Gb). As such zero extending wil have been correct (and extending the value // to 64-bits is necessary since it's used in the address calculation. We zero extend rather than sign // extending since it makes it easier to re-tag the value in the slow case. zeroExtend32ToPtr(regT1, regT1);#else emitFastArithImmToInt(regT1);#endif emitJumpSlowCaseIfNotJSCell(regT0); addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsArrayVPtr))); // This is an array; get the m_storage pointer into ecx, then check if the index is below the fast cutoff loadPtr(Address(regT0, FIELD_OFFSET(JSArray, m_storage)), regT2); addSlowCase(branch32(AboveOrEqual, regT1, Address(regT0, FIELD_OFFSET(JSArray, m_fastAccessCutoff)))); // Get the value from the vector loadPtr(BaseIndex(regT2, regT1, ScalePtr, FIELD_OFFSET(ArrayStorage, m_vector[0])), regT0); emitPutVirtualRegister(currentInstruction[1].u.operand); NEXT_OPCODE(op_get_by_val); } case op_resolve_func: { Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand)); emitPutJITStubArgConstant(ident, 1); emitCTICall(JITStubs::cti_op_resolve_func); emitPutVirtualRegister(currentInstruction[2].u.operand, regT1); emitPutVirtualRegister(currentInstruction[1].u.operand); NEXT_OPCODE(op_resolve_func); } case op_sub: { compileFastArith_op_sub(currentInstruction); NEXT_OPCODE(op_sub); } case op_put_by_val: { emitGetVirtualRegisters(currentInstruction[1].u.operand, regT0, currentInstruction[2].u.operand, regT1); emitJumpSlowCaseIfNotImmediateInteger(regT1);#if USE(ALTERNATE_JSIMMEDIATE) // See comment in op_get_by_val. zeroExtend32ToPtr(regT1, regT1);#else emitFastArithImmToInt(regT1);#endif emitJumpSlowCaseIfNotJSCell(regT0); addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsArrayVPtr))); // This is an array; get the m_storage pointer into ecx, then check if the index is below the fast cutoff loadPtr(Address(regT0, FIELD_OFFSET(JSArray, m_storage)), regT2); Jump inFastVector = branch32(Below, regT1, Address(regT0, FIELD_OFFSET(JSArray, m_fastAccessCutoff))); // No; oh well, check if the access if within the vector - if so, we may still be okay. addSlowCase(branch32(AboveOrEqual, regT1, Address(regT2, FIELD_OFFSET(ArrayStorage, m_vectorLength)))); // This is a write to the slow part of the vector; first, we have to check if this would be the first write to this location. // FIXME: should be able to handle initial write to array; increment the the number of items in the array, and potentially update fast access cutoff. addSlowCase(branchTestPtr(Zero, BaseIndex(regT2, regT1, ScalePtr, FIELD_OFFSET(ArrayStorage, m_vector[0])))); // All good - put the value into the array. inFastVector.link(this); emitGetVirtualRegister(currentInstruction[3].u.operand, regT0); storePtr(regT0, BaseIndex(regT2, regT1, ScalePtr, FIELD_OFFSET(ArrayStorage, m_vector[0]))); NEXT_OPCODE(op_put_by_val); } CTI_COMPILE_BINARY_OP(op_lesseq) case op_loop_if_true: { emitTimeoutCheck(); unsigned target = currentInstruction[2].u.operand; emitGetVirtualRegister(currentInstruction[1].u.operand, regT0); Jump isZero = branchPtr(Equal, regT0, ImmPtr(JSValuePtr::encode(js0()))); addJump(emitJumpIfImmediateInteger(regT0), target + 2); addJump(branchPtr(Equal, regT0, ImmPtr(JSValuePtr::encode(jsBoolean(true)))), target + 2); addSlowCase(branchPtr(NotEqual, regT0, ImmPtr(JSValuePtr::encode(jsBoolean(false))))); isZero.link(this); NEXT_OPCODE(op_loop_if_true); }; case op_resolve_base: { Identifier* ident = &(m_codeBlock->identifier(currentInstruction[2].u.operand)); emitPutJITStubArgConstant(ident, 1); emitCTICall(JITStubs::cti_op_resolve_base); emitPutVirtualRegister(currentInstruction[1].u.operand); NEXT_OPCODE(op_resolve_base); } case op_negate: { emitPutJITStubArgFromVirtualRegister(currentInstruction[2].u.operand, 1, regT2); emitCTICall(JITStubs::cti_op_negate); emitPutVirtualRegister(currentInstruction[1].u.operand); NEXT_OPCODE(op_negate); } case op_resolve_skip: { Identifier* ident = &(m_codeBlock->identifier(currentInstruction[2].u.operand)); emitPutJITStubArgConstant(ident, 1); emitPutJITStubArgConstant(currentInstruction[3].u.operand + m_codeBlock->needsFullScopeChain(), 2); emitCTICall(JITStubs::cti_op_resolve_skip); emitPutVirtualRegister(currentInstruction[1].u.operand); NEXT_OPCODE(op_resolve_skip); } case op_resolve_global: { // Fast case void* globalObject = currentInstruction[2].u.jsCell; Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand)); unsigned currentIndex = globalResolveInfoIndex++; void* structureAddress = &(m_codeBlock->globalResolveInfo(currentIndex).structure); void* offsetAddr = &(m_codeBlock->globalResolveInfo(currentIndex).offset); // Check Structure of global object move(ImmPtr(globalObject), regT0); loadPtr(structureAddress, regT1); Jump noMatch = branchPtr(NotEqual, regT1, Address(regT0, FIELD_OFFSET(JSCell, m_structure))); // Structures don't match // Load cached property loadPtr(Address(regT0, FIELD_OFFSET(JSGlobalObject, m_propertyStorage)), regT0); load32(offsetAddr, regT1); loadPtr(BaseIndex(regT0, regT1, ScalePtr), regT0); emitPutVirtualRegister(currentInstruction[1].u.operand); Jump end = jump(); // Slow case noMatch.link(this); emitPutJITStubArgConstant(globalObject, 1); emitPutJITStubArgConstant(ident, 2); emitPutJITStubArgConstant(currentIndex, 3); emitCTICall(JITStubs::cti_op_resolve_global); emitPutVirtualRegister(currentInstruction[1].u.operand); end.link(this); NEXT_OPCODE(op_resolve_global); } CTI_COMPILE_BINARY_OP(op_div) case op_pre_dec: { compileFastArith_op_pre_dec(currentInstruction[1].u.operand); NEXT_OPCODE(op_pre_dec); } case op_jnless: { unsigned op1 = currentInstruction[1].u.operand; unsigned op2 = currentInstruction[2].u.operand; unsigned target = currentInstruction[3].u.operand; if (isOperandConstantImmediateInt(op2)) { emitGetVirtualRegister(op1, regT0); emitJumpSlowCaseIfNotImmediateInteger(regT0);#if USE(ALTERNATE_JSIMMEDIATE) int32_t op2imm = getConstantOperandImmediateInt(op2);#else int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)));#endif addJump(branch32(GreaterThanOrEqual, regT0, Imm32(op2imm)), target + 3); } else { emitGetVirtualRegisters(op1, regT0, op2, regT1); emitJumpSlowCaseIfNotImmediateInteger(regT0); emitJumpSlowCaseIfNotImmediateInteger(regT1); addJump(branch32(GreaterThanOrEqual, regT0, regT1), target + 3); } RECORD_JUMP_TARGET(target + 3); NEXT_OPCODE(op_jnless); } case op_not: { emitGetVirtualRegister(currentInstruction[2].u.operand, regT0); xorPtr(Imm32(static_cast<int32_t>(JSImmediate::FullTagTypeBool)), regT0); addSlowCase(branchTestPtr(NonZero, regT0, Imm32(static_cast<int32_t>(~JSImmediate::ExtendedPayloadBitBoolValue)))); xorPtr(Imm32(static_cast<int32_t>(JSImmediate::FullTagTypeBool | JSImmediate::ExtendedPayloadBitBoolValue)), regT0); emitPutVirtualRegister(currentInstruction[1].u.operand); NEXT_OPCODE(op_not); } case op_jfalse: { unsigned target = currentInstruction[2].u.operand; emitGetVirtualRegister(currentInstruction[1].u.operand, regT0); addJump(branchPtr(Equal, regT0, ImmPtr(JSValuePtr::encode(js0()))), target + 2); Jump isNonZero = emitJumpIfImmediateInteger(regT0); addJump(branchPtr(Equal, regT0, ImmPtr(JSValuePtr::encode(jsBoolean(false)))), target + 2); addSlowCase(branchPtr(NotEqual, regT0, ImmPtr(JSValuePtr::encode(jsBoolean(true))))); isNonZero.link(this); RECORD_JUMP_TARGET(target + 2); NEXT_OPCODE(op_jfalse); }; case op_jeq_null: { unsigned src = currentInstruction[1].u.operand; unsigned target = currentInstruction[2].u.operand; emitGetVirtualRegister(src, regT0); Jump isImmediate = emitJumpIfNotJSCell(regT0); // First, handle JSCell cases - check MasqueradesAsUndefined bit on the structure. loadPtr(Address(regT0, FIELD_OFFSET(JSCell, m_structure)), regT2); addJump(branchTest32(NonZero, Address(regT2, FIELD_OFFSET(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined)), target + 2); Jump wasNotImmediate = jump(); // Now handle the immediate cases - undefined & null isImmediate.link(this); andPtr(Imm32(~JSImmediate::ExtendedTagBitUndefined), regT0); addJump(branchPtr(Equal, regT0, ImmPtr(JSValuePtr::encode(jsNull()))), target + 2); wasNotImmediate.link(this); RECORD_JUMP_TARGET(target + 2); NEXT_OPCODE(op_jeq_null); }; case op_jneq_null: { unsigned src = currentInstruction[1].u.operand; unsigned target = currentInstruction[2].u.operand; emitGetVirtualRegister(src, regT0); Jump isImmediate = emitJumpIfNotJSCell(regT0); // First, handle JSCell cases - check MasqueradesAsUndefined bit on the structure. loadPtr(Address(regT0, FIELD_OFFSET(JSCell, m_structure)), regT2); addJump(branchTest32(Zero, Address(regT2, FIELD_OFFSET(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined)), target + 2); Jump wasNotImmediate = jump(); // Now handle the immediate cases - undefined & null isImmediate.link(this); andPtr(Imm32(~JSImmediate::ExtendedTagBitUndefined), regT0); addJump(branchPtr(NotEqual, regT0, ImmPtr(JSValuePtr::encode(jsNull()))), target + 2); wasNotImmediate.link(this); RECORD_JUMP_TARGET(target + 2); NEXT_OPCODE(op_jneq_null); } case op_post_inc: { compileFastArith_op_post_inc(currentInstruction[1].u.operand, currentInstruction[2].u.operand); NEXT_OPCODE(op_post_inc); } case op_unexpected_load: { JSValuePtr v = m_codeBlock->unexpectedConstant(currentInstruction[2].u.operand); move(ImmPtr(JSValuePtr::encode(v)), regT0); emitPutVirtualRegister(currentInstruction[1].u.operand); NEXT_OPCODE(op_unexpected_load); } case op_jsr: { int retAddrDst = currentInstruction[1].u.operand; int target = currentInstruction[2].u.operand; DataLabelPtr storeLocation = storePtrWithPatch(Address(callFrameRegister, sizeof(Register) * retAddrDst)); addJump(jump(), target + 2); m_jsrSites.append(JSRInfo(storeLocation, label())); killLastResultRegister(); RECORD_JUMP_TARGET(target + 2); NEXT_OPCODE(op_jsr); } case op_sret: { jump(Address(callFrameRegister, sizeof(Register) * currentInstruction[1].u.operand)); killLastResultRegister(); NEXT_OPCODE(op_sret); } case op_eq: { emitGetVirtualRegisters(currentInstruction[2].u.operand, regT0, currentInstruction[3].u.operand, regT1); emitJumpSlowCaseIfNotImmediateIntegers(regT0, regT1, regT2); set32(Equal, regT1, regT0, regT0); emitTagAsBoolImmediate(regT0); emitPutVirtualRegister(currentInstruction[1].u.operand); NEXT_OPCODE(op_eq); } case op_lshift: { compileFastArith_op_lshift(currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand); NEXT_OPCODE(op_lshift); } case op_bitand: { compileFastArith_op_bitand(currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand); NEXT_OPCODE(op_bitand); } case op_rshift: { compileFastArith_op_rshift(currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand); NEXT_OPCODE(op_rshift); } case op_bitnot: { emitGetVirtualRegister(currentInstruction[2].u.operand, regT0); emitJumpSlowCaseIfNotImmediateInteger(regT0);#if USE(ALTERNATE_JSIMMEDIATE) not32(regT0); emitFastArithIntToImmNoCheck(regT0, regT0);#else xorPtr(Imm32(~JSImmediate::TagTypeNumber), regT0);#endif emitPutVirtualRegister(currentInstruction[1].u.operand); NEXT_OPCODE(op_bitnot); } case op_resolve_with_base: { Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand)); emitPutJITStubArgConstant(ident, 1); emitCTICall(JITStubs::cti_op_resolve_with_base); emitPutVirtualRegister(currentInstruction[2].u.operand, regT1); emitPutVirtualRegister(currentInstruction[1].u.operand); NEXT_OPCODE(op_resolve_with_base); } case op_new_func_exp: { FuncExprNode* func = m_codeBlock->functionExpression(currentInstruction[2].u.operand); emitPutJITStubArgConstant(func, 1); emitCTICall(JITStubs::cti_op_new_func_exp); emitPutVirtualRegister(currentInstruction[1].u.operand); NEXT_OPCODE(op_new_func_exp); } case op_mod: { compileFastArith_op_mod(currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand); NEXT_OPCODE(op_mod); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -