// This method used to fill a JSValue to a GPR when linking speculative -> non-speculative. void JITCompiler::fillToJS(NodeIndex nodeIndex, GPRReg gpr) { Node& node = graph()[nodeIndex]; if (node.isArgument()) { loadPtr(addressForArgument(node.argumentNumber()), gprToRegisterID(gpr)); return; } if (node.isConstant()) { if (isInt32Constant(nodeIndex)) { JSValue jsValue = jsNumber(valueOfInt32Constant(nodeIndex)); move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gprToRegisterID(gpr)); } else if (isDoubleConstant(nodeIndex)) { JSValue jsValue(JSValue::EncodeAsDouble, valueOfDoubleConstant(nodeIndex)); move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gprToRegisterID(gpr)); } else { ASSERT(isJSConstant(nodeIndex)); JSValue jsValue = valueOfJSConstant(nodeIndex); move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gprToRegisterID(gpr)); } return; } loadPtr(addressFor(node.virtualRegister), gprToRegisterID(gpr)); }
void JITCompiler::jumpFromSpeculativeToNonSpeculative(const SpeculationCheck& check, const EntryLocation& entry, SpeculationRecovery* recovery) { ASSERT(check.m_nodeIndex == entry.m_nodeIndex); // Link the jump from the Speculative path to here. check.m_check.link(this); // Does this speculation check require any additional recovery to be performed, // to restore any state that has been overwritten before we enter back in to the // non-speculative path. if (recovery) { // The only additional recovery we currently support is for integer add operation ASSERT(recovery->type() == SpeculativeAdd); // Revert the add. sub32(recovery->src(), recovery->dest()); } // FIXME: - This is hideously inefficient! // Where a value is live in a register in the speculative path, and is required in a register // on the non-speculative path, we should not need to be spilling it and reloading (we may // need to spill anyway, if the value is marked as spilled on the non-speculative path). // This may also be spilling values that don't need spilling, e.g. are already spilled, // are constants, or are arguments. // Spill all GPRs in use by the speculative path. for (unsigned index = 0; index < GPRInfo::numberOfRegisters; ++index) { NodeIndex nodeIndex = check.m_gprInfo[index].nodeIndex; if (nodeIndex == NoNode) continue; DataFormat dataFormat = check.m_gprInfo[index].format; VirtualRegister virtualRegister = graph()[nodeIndex].virtualRegister(); ASSERT(dataFormat == DataFormatInteger || DataFormatCell || dataFormat & DataFormatJS); if (dataFormat == DataFormatInteger) orPtr(GPRInfo::tagTypeNumberRegister, GPRInfo::toRegister(index)); storePtr(GPRInfo::toRegister(index), addressFor(virtualRegister)); } // Spill all FPRs in use by the speculative path. for (unsigned index = 0; index < FPRInfo::numberOfRegisters; ++index) { NodeIndex nodeIndex = check.m_fprInfo[index]; if (nodeIndex == NoNode) continue; VirtualRegister virtualRegister = graph()[nodeIndex].virtualRegister(); moveDoubleToPtr(FPRInfo::toRegister(index), GPRInfo::regT0); subPtr(GPRInfo::tagTypeNumberRegister, GPRInfo::regT0); storePtr(GPRInfo::regT0, addressFor(virtualRegister)); } // Fill all FPRs in use by the non-speculative path. for (unsigned index = 0; index < FPRInfo::numberOfRegisters; ++index) { NodeIndex nodeIndex = entry.m_fprInfo[index]; if (nodeIndex == NoNode) continue; fillNumericToDouble(nodeIndex, FPRInfo::toRegister(index), GPRInfo::regT0); } // Fill all GPRs in use by the non-speculative path. for (unsigned index = 0; index < GPRInfo::numberOfRegisters; ++index) { NodeIndex nodeIndex = entry.m_gprInfo[index].nodeIndex; if (nodeIndex == NoNode) continue; DataFormat dataFormat = entry.m_gprInfo[index].format; if (dataFormat == DataFormatInteger) fillInt32ToInteger(nodeIndex, GPRInfo::toRegister(index)); else { ASSERT(dataFormat & DataFormatJS || dataFormat == DataFormatCell); // Treat cell as TiValue for now! fillToJS(nodeIndex, GPRInfo::toRegister(index)); // FIXME: For subtypes of DataFormatJS, should jitAssert the subtype? } } // Jump into the non-speculative path. jump(entry.m_entry); }