📄 jit.cpp
字号:
case op_jtrue: { 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); RECORD_JUMP_TARGET(target + 2); NEXT_OPCODE(op_jtrue); } CTI_COMPILE_BINARY_OP(op_less) case op_neq: { emitGetVirtualRegisters(currentInstruction[2].u.operand, regT0, currentInstruction[3].u.operand, regT1); emitJumpSlowCaseIfNotImmediateIntegers(regT0, regT1, regT2); set32(NotEqual, regT1, regT0, regT0); emitTagAsBoolImmediate(regT0); emitPutVirtualRegister(currentInstruction[1].u.operand); NEXT_OPCODE(op_neq); } case op_post_dec: { compileFastArith_op_post_dec(currentInstruction[1].u.operand, currentInstruction[2].u.operand); NEXT_OPCODE(op_post_dec); } CTI_COMPILE_BINARY_OP(op_urshift) case op_bitxor: { emitGetVirtualRegisters(currentInstruction[2].u.operand, regT0, currentInstruction[3].u.operand, regT1); emitJumpSlowCaseIfNotImmediateIntegers(regT0, regT1, regT2); xorPtr(regT1, regT0); emitFastArithReTagImmediate(regT0, regT0); emitPutVirtualRegister(currentInstruction[1].u.operand); NEXT_OPCODE(op_bitxor); } case op_new_regexp: { RegExp* regExp = m_codeBlock->regexp(currentInstruction[2].u.operand); emitPutJITStubArgConstant(regExp, 1); emitCTICall(JITStubs::cti_op_new_regexp); emitPutVirtualRegister(currentInstruction[1].u.operand); NEXT_OPCODE(op_new_regexp); } case op_bitor: { emitGetVirtualRegisters(currentInstruction[2].u.operand, regT0, currentInstruction[3].u.operand, regT1); emitJumpSlowCaseIfNotImmediateIntegers(regT0, regT1, regT2); orPtr(regT1, regT0); emitPutVirtualRegister(currentInstruction[1].u.operand); NEXT_OPCODE(op_bitor); } case op_throw: { emitPutJITStubArgFromVirtualRegister(currentInstruction[1].u.operand, 1, regT2); emitCTICall(JITStubs::cti_op_throw); ASSERT(regT0 == returnValueRegister);#if PLATFORM(X86_64) addPtr(Imm32(0x48), X86::esp); pop(X86::ebx); pop(X86::r15); pop(X86::r14); pop(X86::r13); pop(X86::r12); pop(X86::ebp); ret();#else addPtr(Imm32(0x1c), X86::esp); pop(X86::ebx); pop(X86::edi); pop(X86::esi); pop(X86::ebp); ret();#endif NEXT_OPCODE(op_throw); } case op_get_pnames: { emitPutJITStubArgFromVirtualRegister(currentInstruction[2].u.operand, 1, regT2); emitCTICall(JITStubs::cti_op_get_pnames); emitPutVirtualRegister(currentInstruction[1].u.operand); NEXT_OPCODE(op_get_pnames); } case op_next_pname: { emitPutJITStubArgFromVirtualRegister(currentInstruction[2].u.operand, 1, regT2); unsigned target = currentInstruction[3].u.operand; emitCTICall(JITStubs::cti_op_next_pname); Jump endOfIter = branchTestPtr(Zero, regT0); emitPutVirtualRegister(currentInstruction[1].u.operand); addJump(jump(), target + 3); endOfIter.link(this); NEXT_OPCODE(op_next_pname); } case op_push_scope: { emitPutJITStubArgFromVirtualRegister(currentInstruction[1].u.operand, 1, regT2); emitCTICall(JITStubs::cti_op_push_scope); emitPutVirtualRegister(currentInstruction[1].u.operand); NEXT_OPCODE(op_push_scope); } case op_pop_scope: { emitCTICall(JITStubs::cti_op_pop_scope); NEXT_OPCODE(op_pop_scope); } CTI_COMPILE_UNARY_OP(op_typeof) CTI_COMPILE_UNARY_OP(op_is_undefined) CTI_COMPILE_UNARY_OP(op_is_boolean) CTI_COMPILE_UNARY_OP(op_is_number) CTI_COMPILE_UNARY_OP(op_is_string) CTI_COMPILE_UNARY_OP(op_is_object) CTI_COMPILE_UNARY_OP(op_is_function) case op_stricteq: { compileOpStrictEq(currentInstruction, OpStrictEq); NEXT_OPCODE(op_stricteq); } case op_nstricteq: { compileOpStrictEq(currentInstruction, OpNStrictEq); NEXT_OPCODE(op_nstricteq); } case op_to_jsnumber: { int srcVReg = currentInstruction[2].u.operand; emitGetVirtualRegister(srcVReg, regT0); Jump wasImmediate = emitJumpIfImmediateInteger(regT0); emitJumpSlowCaseIfNotJSCell(regT0, srcVReg); loadPtr(Address(regT0, FIELD_OFFSET(JSCell, m_structure)), regT2); addSlowCase(branch32(NotEqual, Address(regT2, FIELD_OFFSET(Structure, m_typeInfo.m_type)), Imm32(NumberType))); wasImmediate.link(this); emitPutVirtualRegister(currentInstruction[1].u.operand); NEXT_OPCODE(op_to_jsnumber); } CTI_COMPILE_BINARY_OP(op_in) case op_push_new_scope: { Identifier* ident = &(m_codeBlock->identifier(currentInstruction[2].u.operand)); emitPutJITStubArgConstant(ident, 1); emitPutJITStubArgFromVirtualRegister(currentInstruction[3].u.operand, 2, regT2); emitCTICall(JITStubs::cti_op_push_new_scope); emitPutVirtualRegister(currentInstruction[1].u.operand); NEXT_OPCODE(op_push_new_scope); } case op_catch: { emitGetCTIParam(STUB_ARGS_callFrame, callFrameRegister); emitPutVirtualRegister(currentInstruction[1].u.operand); NEXT_OPCODE(op_catch); } case op_jmp_scopes: { unsigned count = currentInstruction[1].u.operand; emitPutJITStubArgConstant(count, 1); emitCTICall(JITStubs::cti_op_jmp_scopes); unsigned target = currentInstruction[2].u.operand; addJump(jump(), target + 2); RECORD_JUMP_TARGET(target + 2); NEXT_OPCODE(op_jmp_scopes); } case op_put_by_index: { emitPutJITStubArgFromVirtualRegister(currentInstruction[1].u.operand, 1, regT2); emitPutJITStubArgConstant(currentInstruction[2].u.operand, 2); emitPutJITStubArgFromVirtualRegister(currentInstruction[3].u.operand, 3, regT2); emitCTICall(JITStubs::cti_op_put_by_index); NEXT_OPCODE(op_put_by_index); } case op_switch_imm: { unsigned tableIndex = currentInstruction[1].u.operand; unsigned defaultOffset = currentInstruction[2].u.operand; unsigned scrutinee = currentInstruction[3].u.operand; // create jump table for switch destinations, track this switch statement. SimpleJumpTable* jumpTable = &m_codeBlock->immediateSwitchJumpTable(tableIndex); m_switches.append(SwitchRecord(jumpTable, m_bytecodeIndex, defaultOffset, SwitchRecord::Immediate)); jumpTable->ctiOffsets.grow(jumpTable->branchOffsets.size()); emitPutJITStubArgFromVirtualRegister(scrutinee, 1, regT2); emitPutJITStubArgConstant(tableIndex, 2); emitCTICall(JITStubs::cti_op_switch_imm); jump(regT0); NEXT_OPCODE(op_switch_imm); } case op_switch_char: { unsigned tableIndex = currentInstruction[1].u.operand; unsigned defaultOffset = currentInstruction[2].u.operand; unsigned scrutinee = currentInstruction[3].u.operand; // create jump table for switch destinations, track this switch statement. SimpleJumpTable* jumpTable = &m_codeBlock->characterSwitchJumpTable(tableIndex); m_switches.append(SwitchRecord(jumpTable, m_bytecodeIndex, defaultOffset, SwitchRecord::Character)); jumpTable->ctiOffsets.grow(jumpTable->branchOffsets.size()); emitPutJITStubArgFromVirtualRegister(scrutinee, 1, regT2); emitPutJITStubArgConstant(tableIndex, 2); emitCTICall(JITStubs::cti_op_switch_char); jump(regT0); NEXT_OPCODE(op_switch_char); } case op_switch_string: { unsigned tableIndex = currentInstruction[1].u.operand; unsigned defaultOffset = currentInstruction[2].u.operand; unsigned scrutinee = currentInstruction[3].u.operand; // create jump table for switch destinations, track this switch statement. StringJumpTable* jumpTable = &m_codeBlock->stringSwitchJumpTable(tableIndex); m_switches.append(SwitchRecord(jumpTable, m_bytecodeIndex, defaultOffset)); emitPutJITStubArgFromVirtualRegister(scrutinee, 1, regT2); emitPutJITStubArgConstant(tableIndex, 2); emitCTICall(JITStubs::cti_op_switch_string); jump(regT0); NEXT_OPCODE(op_switch_string); } case op_del_by_val: { emitPutJITStubArgFromVirtualRegister(currentInstruction[2].u.operand, 1, regT2); emitPutJITStubArgFromVirtualRegister(currentInstruction[3].u.operand, 2, regT2); emitCTICall(JITStubs::cti_op_del_by_val); emitPutVirtualRegister(currentInstruction[1].u.operand); NEXT_OPCODE(op_del_by_val); } case op_put_getter: { emitPutJITStubArgFromVirtualRegister(currentInstruction[1].u.operand, 1, regT2); Identifier* ident = &(m_codeBlock->identifier(currentInstruction[2].u.operand)); emitPutJITStubArgConstant(ident, 2); emitPutJITStubArgFromVirtualRegister(currentInstruction[3].u.operand, 3, regT2); emitCTICall(JITStubs::cti_op_put_getter); NEXT_OPCODE(op_put_getter); } case op_put_setter: { emitPutJITStubArgFromVirtualRegister(currentInstruction[1].u.operand, 1, regT2); Identifier* ident = &(m_codeBlock->identifier(currentInstruction[2].u.operand)); emitPutJITStubArgConstant(ident, 2); emitPutJITStubArgFromVirtualRegister(currentInstruction[3].u.operand, 3, regT2); emitCTICall(JITStubs::cti_op_put_setter); NEXT_OPCODE(op_put_setter); } case op_new_error: { JSValuePtr message = m_codeBlock->unexpectedConstant(currentInstruction[3].u.operand); emitPutJITStubArgConstant(currentInstruction[2].u.operand, 1); emitPutJITStubArgConstant(JSValuePtr::encode(message), 2); emitPutJITStubArgConstant(m_bytecodeIndex, 3); emitCTICall(JITStubs::cti_op_new_error); emitPutVirtualRegister(currentInstruction[1].u.operand); NEXT_OPCODE(op_new_error); } case op_debug: { emitPutJITStubArgConstant(currentInstruction[1].u.operand, 1); emitPutJITStubArgConstant(currentInstruction[2].u.operand, 2); emitPutJITStubArgConstant(currentInstruction[3].u.operand, 3); emitCTICall(JITStubs::cti_op_debug); NEXT_OPCODE(op_debug); } case op_eq_null: { unsigned dst = currentInstruction[1].u.operand; unsigned src1 = currentInstruction[2].u.operand; emitGetVirtualRegister(src1, regT0); Jump isImmediate = emitJumpIfNotJSCell(regT0); loadPtr(Address(regT0, FIELD_OFFSET(JSCell, m_structure)), regT2); setTest32(NonZero, Address(regT2, FIELD_OFFSET(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined), regT0); Jump wasNotImmediate = jump(); isImmediate.link(this); andPtr(Imm32(~JSImmediate::ExtendedTagBitUndefined), regT0); setPtr(Equal, regT0, Imm32(JSImmediate::FullTagTypeNull), regT0); wasNotImmediate.link(this); emitTagAsBoolImmediate(regT0); emitPutVirtualRegister(dst); NEXT_OPCODE(op_eq_null); } case op_neq_null: { unsigned dst = currentInstruction[1].u.operand; unsigned src1 = currentInstruction[2].u.operand; emitGetVirtualRegister(src1, regT0); Jump isImmediate = emitJumpIfNotJSCell(regT0); loadPtr(Address(regT0, FIELD_OFFSET(JSCell, m_structure)), regT2); setTest32(Zero, Address(regT2, FIELD_OFFSET(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined), regT0); Jump wasNotImmediate = jump(); isImmediate.link(this); andPtr(Imm32(~JSImmediate::ExtendedTagBitUndefined), regT0); setPtr(NotEqual, regT0, Imm32(JSImmediate::FullTagTypeNull), regT0); wasNotImmediate.link(this); emitTagAsBoolImmediate(regT0); emitPutVirtualRegister(dst); NEXT_OPCODE(op_neq_null); } case op_enter: { // Even though CTI doesn't use them, we initialize our constant // registers to zap stale pointers, to avoid unnecessarily prolonging // object lifetime and increasing GC pressure.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -