void JITCode::reconstruct( ExecState* exec, CodeBlock* codeBlock, CodeOrigin codeOrigin, unsigned streamIndex, Operands<JSValue>& result) { Operands<ValueRecovery> recoveries; reconstruct(codeBlock, codeOrigin, streamIndex, recoveries); result = Operands<JSValue>(OperandsLike, recoveries); for (size_t i = result.size(); i--;) { int operand = result.operandForIndex(i); if (operandIsArgument(operand) && !VirtualRegister(operand).toArgument() && codeBlock->codeType() == FunctionCode && codeBlock->specializationKind() == CodeForConstruct) { // Ugh. If we're in a constructor, the 'this' argument may hold garbage. It will // also never be used. It doesn't matter what we put into the value for this, // but it has to be an actual value that can be grokked by subsequent DFG passes, // so we sanitize it here by turning it into Undefined. result[i] = jsUndefined(); continue; } ValueRecovery recovery = recoveries[i]; JSValue value; switch (recovery.technique()) { case AlreadyInJSStack: case AlreadyInJSStackAsUnboxedCell: case AlreadyInJSStackAsUnboxedBoolean: value = exec->r(operand).jsValue(); break; case AlreadyInJSStackAsUnboxedInt32: value = jsNumber(exec->r(operand).unboxedInt32()); break; case AlreadyInJSStackAsUnboxedInt52: value = jsNumber(exec->r(operand).unboxedInt52()); break; case AlreadyInJSStackAsUnboxedDouble: value = jsDoubleNumber(exec->r(operand).unboxedDouble()); break; case Constant: value = recovery.constant(); break; default: RELEASE_ASSERT_NOT_REACHED(); break; } result[i] = value; } }
void emitSetupVarargsFrameFastCase(CCallHelpers& jit, GPRReg numUsedSlotsGPR, GPRReg scratchGPR1, GPRReg scratchGPR2, GPRReg scratchGPR3, ValueRecovery argCountRecovery, VirtualRegister firstArgumentReg, unsigned firstVarArgOffset, CCallHelpers::JumpList& slowCase) { CCallHelpers::JumpList end; if (argCountRecovery.isConstant()) { // FIXME: We could constant-fold a lot of the computation below in this case. // https://bugs.webkit.org/show_bug.cgi?id=141486 jit.move(CCallHelpers::TrustedImm32(argCountRecovery.constant().asInt32()), scratchGPR1); } else jit.load32(CCallHelpers::payloadFor(argCountRecovery.virtualRegister()), scratchGPR1); if (firstVarArgOffset) { CCallHelpers::Jump sufficientArguments = jit.branch32(CCallHelpers::GreaterThan, scratchGPR1, CCallHelpers::TrustedImm32(firstVarArgOffset + 1)); jit.move(CCallHelpers::TrustedImm32(1), scratchGPR1); CCallHelpers::Jump endVarArgs = jit.jump(); sufficientArguments.link(&jit); jit.sub32(CCallHelpers::TrustedImm32(firstVarArgOffset), scratchGPR1); endVarArgs.link(&jit); } slowCase.append(jit.branch32(CCallHelpers::Above, scratchGPR1, CCallHelpers::TrustedImm32(maxArguments + 1))); emitSetVarargsFrame(jit, scratchGPR1, true, numUsedSlotsGPR, scratchGPR2); slowCase.append(jit.branchPtr(CCallHelpers::Above, CCallHelpers::AbsoluteAddress(jit.vm()->addressOfStackLimit()), scratchGPR2)); // Initialize ArgumentCount. jit.store32(scratchGPR1, CCallHelpers::Address(scratchGPR2, JSStack::ArgumentCount * static_cast<int>(sizeof(Register)) + PayloadOffset)); // Copy arguments. jit.signExtend32ToPtr(scratchGPR1, scratchGPR1); CCallHelpers::Jump done = jit.branchSubPtr(CCallHelpers::Zero, CCallHelpers::TrustedImm32(1), scratchGPR1); // scratchGPR1: argumentCount CCallHelpers::Label copyLoop = jit.label(); int argOffset = (firstArgumentReg.offset() - 1 + firstVarArgOffset) * static_cast<int>(sizeof(Register)); #if USE(JSVALUE64) jit.load64(CCallHelpers::BaseIndex(GPRInfo::callFrameRegister, scratchGPR1, CCallHelpers::TimesEight, argOffset), scratchGPR3); jit.store64(scratchGPR3, CCallHelpers::BaseIndex(scratchGPR2, scratchGPR1, CCallHelpers::TimesEight, CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register)))); #else // USE(JSVALUE64), so this begins the 32-bit case jit.load32(CCallHelpers::BaseIndex(GPRInfo::callFrameRegister, scratchGPR1, CCallHelpers::TimesEight, argOffset + TagOffset), scratchGPR3); jit.store32(scratchGPR3, CCallHelpers::BaseIndex(scratchGPR2, scratchGPR1, CCallHelpers::TimesEight, CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register)) + TagOffset)); jit.load32(CCallHelpers::BaseIndex(GPRInfo::callFrameRegister, scratchGPR1, CCallHelpers::TimesEight, argOffset + PayloadOffset), scratchGPR3); jit.store32(scratchGPR3, CCallHelpers::BaseIndex(scratchGPR2, scratchGPR1, CCallHelpers::TimesEight, CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register)) + PayloadOffset)); #endif // USE(JSVALUE64), end of 32-bit case jit.branchSubPtr(CCallHelpers::NonZero, CCallHelpers::TrustedImm32(1), scratchGPR1).linkTo(copyLoop, &jit); done.link(&jit); }