void JIT::emit_op_add(Instruction* currentInstruction) { unsigned result = currentInstruction[1].u.operand; unsigned op1 = currentInstruction[2].u.operand; unsigned op2 = currentInstruction[3].u.operand; OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); if (!types.first().mightBeNumber() || !types.second().mightBeNumber()) { JITStubCall stubCall(this, cti_op_add); stubCall.addArgument(op1, regT2); stubCall.addArgument(op2, regT2); stubCall.call(result); return; } if (isOperandConstantImmediateInt(op1)) { emitGetVirtualRegister(op2, regT0); emitJumpSlowCaseIfNotImmediateInteger(regT0); addSlowCase(branchAdd32(Overflow, Imm32(getConstantOperandImmediateInt(op1)), regT0)); emitFastArithIntToImmNoCheck(regT0, regT0); } else if (isOperandConstantImmediateInt(op2)) { emitGetVirtualRegister(op1, regT0); emitJumpSlowCaseIfNotImmediateInteger(regT0); addSlowCase(branchAdd32(Overflow, Imm32(getConstantOperandImmediateInt(op2)), regT0)); emitFastArithIntToImmNoCheck(regT0, regT0); } else compileBinaryArithOp(op_add, result, op1, op2, types); emitPutVirtualRegister(result); }
void JIT::compileLoadVarargs(Instruction* instruction) { int thisValue = instruction[2].u.operand; int arguments = instruction[3].u.operand; int firstFreeRegister = instruction[4].u.operand; JumpList slowCase; JumpList end; if (m_codeBlock->usesArguments() && arguments == m_codeBlock->argumentsRegister()) { emitLoadTag(arguments, regT1); slowCase.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::EmptyValueTag))); load32(payloadFor(RegisterFile::ArgumentCount), regT2); slowCase.append(branch32(Above, regT2, TrustedImm32(Arguments::MaxArguments + 1))); // regT2: argumentCountIncludingThis move(regT2, regT3); add32(TrustedImm32(firstFreeRegister + RegisterFile::CallFrameHeaderSize), regT3); lshift32(TrustedImm32(3), regT3); addPtr(callFrameRegister, regT3); // regT3: newCallFrame slowCase.append(branchPtr(Below, AbsoluteAddress(m_globalData->interpreter->registerFile().addressOfEnd()), regT3)); // Initialize ArgumentCount. store32(regT2, payloadFor(RegisterFile::ArgumentCount, regT3)); // Initialize 'this'. emitLoad(thisValue, regT1, regT0); store32(regT0, Address(regT3, OBJECT_OFFSETOF(JSValue, u.asBits.payload) + (CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register))))); store32(regT1, Address(regT3, OBJECT_OFFSETOF(JSValue, u.asBits.tag) + (CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register))))); // Copy arguments. neg32(regT2); end.append(branchAdd32(Zero, TrustedImm32(1), regT2)); // regT2: -argumentCount; Label copyLoop = label(); load32(BaseIndex(callFrameRegister, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload) +(CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register)))), regT0); load32(BaseIndex(callFrameRegister, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag) +(CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register)))), regT1); store32(regT0, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload) +(CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register))))); store32(regT1, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag) +(CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register))))); branchAdd32(NonZero, TrustedImm32(1), regT2).linkTo(copyLoop, this); end.append(jump()); } if (m_codeBlock->usesArguments() && arguments == m_codeBlock->argumentsRegister()) slowCase.link(this); JITStubCall stubCall(this, cti_op_load_varargs); stubCall.addArgument(thisValue); stubCall.addArgument(arguments); stubCall.addArgument(Imm32(firstFreeRegister)); stubCall.call(regT3); if (m_codeBlock->usesArguments() && arguments == m_codeBlock->argumentsRegister()) end.link(this); }
void JIT::emit_op_pre_inc(Instruction* currentInstruction) { unsigned srcDst = currentInstruction[1].u.operand; emitGetVirtualRegister(srcDst, regT0); emitJumpSlowCaseIfNotImmediateInteger(regT0); addSlowCase(branchAdd32(Overflow, Imm32(1), regT0)); emitFastArithIntToImmNoCheck(regT0, regT0); emitPutVirtualRegister(srcDst); }
void JIT::compileBinaryArithOp(OpcodeID opcodeID, unsigned, unsigned op1, unsigned op2, OperandTypes) { emitGetVirtualRegisters(op1, regT0, op2, regT1); emitJumpSlowCaseIfNotImmediateInteger(regT0); emitJumpSlowCaseIfNotImmediateInteger(regT1); if (opcodeID == op_add) addSlowCase(branchAdd32(Overflow, regT1, regT0)); else if (opcodeID == op_sub) addSlowCase(branchSub32(Overflow, regT1, regT0)); else { ASSERT(opcodeID == op_mul); addSlowCase(branchMul32(Overflow, regT1, regT0)); addSlowCase(branchTest32(Zero, regT0)); } emitFastArithIntToImmNoCheck(regT0, regT0); }