+2011-09-27 Yuqiang Xian <yuqiang.xian@intel.com>
+
+ Bug fixes for GetById, PutById, and GetByOffset in JSVALUE32_64 DFG JIT
+ https://bugs.webkit.org/show_bug.cgi?id=68755
+
+ Reviewed by Gavin Barraclough.
+
+ We need to load/store and repatch both tag and payload of a property
+ for GetById/PutById. Also reorder the loads of tag and payload for
+ GetByOffset as the result tag GPR could reuse the storage GPR.
+
+ * bytecode/StructureStubInfo.h:
+ * dfg/DFGJITCodeGenerator32_64.cpp:
+ (JSC::DFG::JITCodeGenerator::cachedGetById):
+ (JSC::DFG::JITCodeGenerator::cachedPutById):
+ * dfg/DFGJITCompiler.h:
+ (JSC::DFG::JITCompiler::addPropertyAccess):
+ (JSC::DFG::JITCompiler::PropertyAccessRecord::PropertyAccessRecord):
+ * dfg/DFGJITCompiler32_64.cpp:
+ (JSC::DFG::JITCompiler::link):
+ * dfg/DFGRepatch.cpp:
+ (JSC::DFG::dfgRepatchByIdSelfAccess):
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+
2011-09-24 Gavin Barraclough <barraclough@apple.com>
Macro assembler branch8 & 16 methods vary in treatment of upper bits
union {
struct {
int16_t deltaCheckImmToCall;
+#if USE(JSVALUE64)
int16_t deltaCallToLoadOrStore;
+#elif USE(JSVALUE32_64)
+ int16_t deltaCallToTagLoadOrStore;
+ int16_t deltaCallToPayloadLoadOrStore;
+#endif
} unset;
struct {
WriteBarrierBase<Structure> baseObjectStructure;
JITCompiler::Jump structureCheck = m_jit.branchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(basePayloadGPR, JSCell::structureOffset()), structureToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(-1)));
m_jit.loadPtr(JITCompiler::Address(basePayloadGPR, JSObject::offsetOfPropertyStorage()), resultPayloadGPR);
- JITCompiler::DataLabelCompact loadWithPatch = m_jit.loadPtrWithCompactAddressOffsetPatch(JITCompiler::Address(resultPayloadGPR, 0), resultPayloadGPR);
- m_jit.move(TrustedImm32(JSValue::CellTag), resultTagGPR);
+ JITCompiler::DataLabelCompact tagLoadWithPatch = m_jit.load32WithCompactAddressOffsetPatch(JITCompiler::Address(resultPayloadGPR, OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)), resultTagGPR);
+ JITCompiler::DataLabelCompact payloadLoadWithPatch = m_jit.load32WithCompactAddressOffsetPatch(JITCompiler::Address(resultPayloadGPR, OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)), resultPayloadGPR);
JITCompiler::Jump done = m_jit.jump();
int16_t checkImmToCall = safeCast<int16_t>(m_jit.differenceBetween(structureToCompare, functionCall));
int16_t callToCheck = safeCast<int16_t>(m_jit.differenceBetween(functionCall, structureCheck));
- int16_t callToLoad = safeCast<int16_t>(m_jit.differenceBetween(functionCall, loadWithPatch));
+ int16_t callToTagLoad = safeCast<int16_t>(m_jit.differenceBetween(functionCall, tagLoadWithPatch));
+ int16_t callToPayloadLoad = safeCast<int16_t>(m_jit.differenceBetween(functionCall, payloadLoadWithPatch));
int16_t callToSlowCase = safeCast<int16_t>(m_jit.differenceBetween(functionCall, slowCase));
int16_t callToDone = safeCast<int16_t>(m_jit.differenceBetween(functionCall, doneLabel));
- m_jit.addPropertyAccess(functionCall, checkImmToCall, callToCheck, callToLoad, callToSlowCase, callToDone, safeCast<int8_t>(basePayloadGPR), safeCast<int8_t>(resultTagGPR), safeCast<int8_t>(resultPayloadGPR), safeCast<int8_t>(scratchGPR));
+ m_jit.addPropertyAccess(functionCall, checkImmToCall, callToCheck, callToTagLoad, callToPayloadLoad, callToSlowCase, callToDone, safeCast<int8_t>(basePayloadGPR), safeCast<int8_t>(resultTagGPR), safeCast<int8_t>(resultPayloadGPR), safeCast<int8_t>(scratchGPR));
return functionCall;
}
writeBarrier(basePayloadGPR, valueTagGPR, valueIndex, WriteBarrierForPropertyAccess, scratchGPR);
m_jit.loadPtr(JITCompiler::Address(basePayloadGPR, JSObject::offsetOfPropertyStorage()), scratchGPR);
- JITCompiler::DataLabel32 storeWithPatch = m_jit.storePtrWithAddressOffsetPatch(valuePayloadGPR, JITCompiler::Address(scratchGPR, 0));
+ JITCompiler::DataLabel32 tagStoreWithPatch = m_jit.store32WithAddressOffsetPatch(valueTagGPR, JITCompiler::Address(scratchGPR, OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)));
+ JITCompiler::DataLabel32 payloadStoreWithPatch = m_jit.store32WithAddressOffsetPatch(valuePayloadGPR, JITCompiler::Address(scratchGPR, OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)));
JITCompiler::Jump done = m_jit.jump();
int16_t checkImmToCall = safeCast<int16_t>(m_jit.differenceBetween(structureToCompare, functionCall));
int16_t callToCheck = safeCast<int16_t>(m_jit.differenceBetween(functionCall, structureCheck));
- int16_t callToStore = safeCast<int16_t>(m_jit.differenceBetween(functionCall, storeWithPatch));
+ int16_t callToTagStore = safeCast<int16_t>(m_jit.differenceBetween(functionCall, tagStoreWithPatch));
+ int16_t callToPayloadStore = safeCast<int16_t>(m_jit.differenceBetween(functionCall, payloadStoreWithPatch));
int16_t callToSlowCase = safeCast<int16_t>(m_jit.differenceBetween(functionCall, slowCase));
int16_t callToDone = safeCast<int16_t>(m_jit.differenceBetween(functionCall, doneLabel));
- m_jit.addPropertyAccess(functionCall, checkImmToCall, callToCheck, callToStore, callToSlowCase, callToDone, safeCast<int8_t>(basePayloadGPR), safeCast<int8_t>(valueTagGPR), safeCast<int8_t>(valuePayloadGPR), safeCast<int8_t>(scratchGPR));
+ m_jit.addPropertyAccess(functionCall, checkImmToCall, callToCheck, callToTagStore, callToPayloadStore, callToSlowCase, callToDone, safeCast<int8_t>(basePayloadGPR), safeCast<int8_t>(valueTagGPR), safeCast<int8_t>(valuePayloadGPR), safeCast<int8_t>(scratchGPR));
}
void JITCodeGenerator::cachedGetMethod(GPRReg basePayloadGPR, GPRReg resultTagGPR, GPRReg resultPayloadGPR, GPRReg scratchGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget)
m_propertyAccesses.append(PropertyAccessRecord(functionCall, deltaCheckImmToCall, deltaCallToStructCheck, deltaCallToLoadOrStore, deltaCallToSlowCase, deltaCallToDone, baseGPR, valueGPR, scratchGPR));
}
#elif USE(JSVALUE32_64)
- void addPropertyAccess(JITCompiler::Call functionCall, int16_t deltaCheckImmToCall, int16_t deltaCallToStructCheck, int16_t deltaCallToLoadOrStore, int16_t deltaCallToSlowCase, int16_t deltaCallToDone, int8_t baseGPR, int8_t valueTagGPR, int8_t valueGPR, int8_t scratchGPR)
+ void addPropertyAccess(JITCompiler::Call functionCall, int16_t deltaCheckImmToCall, int16_t deltaCallToStructCheck, int16_t deltaCallToTagLoadOrStore, int16_t deltaCallToPayloadLoadOrStore, int16_t deltaCallToSlowCase, int16_t deltaCallToDone, int8_t baseGPR, int8_t valueTagGPR, int8_t valueGPR, int8_t scratchGPR)
{
- m_propertyAccesses.append(PropertyAccessRecord(functionCall, deltaCheckImmToCall, deltaCallToStructCheck, deltaCallToLoadOrStore, deltaCallToSlowCase, deltaCallToDone, baseGPR, valueTagGPR, valueGPR, scratchGPR));
+ m_propertyAccesses.append(PropertyAccessRecord(functionCall, deltaCheckImmToCall, deltaCallToStructCheck, deltaCallToTagLoadOrStore, deltaCallToPayloadLoadOrStore, deltaCallToSlowCase, deltaCallToDone, baseGPR, valueTagGPR, valueGPR, scratchGPR));
}
#endif
#if USE(JSVALUE64)
PropertyAccessRecord(Call functionCall, int16_t deltaCheckImmToCall, int16_t deltaCallToStructCheck, int16_t deltaCallToLoadOrStore, int16_t deltaCallToSlowCase, int16_t deltaCallToDone, int8_t baseGPR, int8_t valueGPR, int8_t scratchGPR)
#elif USE(JSVALUE32_64)
- PropertyAccessRecord(Call functionCall, int16_t deltaCheckImmToCall, int16_t deltaCallToStructCheck, int16_t deltaCallToLoadOrStore, int16_t deltaCallToSlowCase, int16_t deltaCallToDone, int8_t baseGPR, int8_t valueTagGPR, int8_t valueGPR, int8_t scratchGPR)
+ PropertyAccessRecord(Call functionCall, int16_t deltaCheckImmToCall, int16_t deltaCallToStructCheck, int16_t deltaCallToTagLoadOrStore, int16_t deltaCallToPayloadLoadOrStore, int16_t deltaCallToSlowCase, int16_t deltaCallToDone, int8_t baseGPR, int8_t valueTagGPR, int8_t valueGPR, int8_t scratchGPR)
#endif
: m_functionCall(functionCall)
, m_deltaCheckImmToCall(deltaCheckImmToCall)
, m_deltaCallToStructCheck(deltaCallToStructCheck)
+#if USE(JSVALUE64)
, m_deltaCallToLoadOrStore(deltaCallToLoadOrStore)
+#elif USE(JSVALUE32_64)
+ , m_deltaCallToTagLoadOrStore(deltaCallToTagLoadOrStore)
+ , m_deltaCallToPayloadLoadOrStore(deltaCallToPayloadLoadOrStore)
+#endif
, m_deltaCallToSlowCase(deltaCallToSlowCase)
, m_deltaCallToDone(deltaCallToDone)
, m_baseGPR(baseGPR)
JITCompiler::Call m_functionCall;
int16_t m_deltaCheckImmToCall;
int16_t m_deltaCallToStructCheck;
+#if USE(JSVALUE64)
int16_t m_deltaCallToLoadOrStore;
+#elif USE(JSVALUE32_64)
+ int16_t m_deltaCallToTagLoadOrStore;
+ int16_t m_deltaCallToPayloadLoadOrStore;
+#endif
int16_t m_deltaCallToSlowCase;
int16_t m_deltaCallToDone;
int8_t m_baseGPR;
info.callReturnLocation = linkBuffer.locationOf(m_propertyAccesses[i].m_functionCall);
info.u.unset.deltaCheckImmToCall = m_propertyAccesses[i].m_deltaCheckImmToCall;
info.deltaCallToStructCheck = m_propertyAccesses[i].m_deltaCallToStructCheck;
- info.u.unset.deltaCallToLoadOrStore = m_propertyAccesses[i].m_deltaCallToLoadOrStore;
+ info.u.unset.deltaCallToTagLoadOrStore = m_propertyAccesses[i].m_deltaCallToTagLoadOrStore;
+ info.u.unset.deltaCallToPayloadLoadOrStore = m_propertyAccesses[i].m_deltaCallToPayloadLoadOrStore;
info.deltaCallToSlowCase = m_propertyAccesses[i].m_deltaCallToSlowCase;
info.deltaCallToDone = m_propertyAccesses[i].m_deltaCallToDone;
info.baseGPR = m_propertyAccesses[i].m_baseGPR;
// Patch the structure check & the offset of the load.
repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabelPtrAtOffset(-(intptr_t)stubInfo.u.unset.deltaCheckImmToCall), structure);
+#if USE(JSVALUE64)
if (compact)
repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabelCompactAtOffset(stubInfo.u.unset.deltaCallToLoadOrStore), sizeof(JSValue) * offset);
else
repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabel32AtOffset(stubInfo.u.unset.deltaCallToLoadOrStore), sizeof(JSValue) * offset);
+#elif USE(JSVALUE32_64)
+ if (compact) {
+ repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabelCompactAtOffset(stubInfo.u.unset.deltaCallToTagLoadOrStore), sizeof(JSValue) * offset + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
+ repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabelCompactAtOffset(stubInfo.u.unset.deltaCallToPayloadLoadOrStore), sizeof(JSValue) * offset + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
+ } else {
+ repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabel32AtOffset(stubInfo.u.unset.deltaCallToTagLoadOrStore), sizeof(JSValue) * offset + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
+ repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabel32AtOffset(stubInfo.u.unset.deltaCallToPayloadLoadOrStore), sizeof(JSValue) * offset + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
+ }
+#endif
}
static void emitRestoreScratch(MacroAssembler& stubJit, bool needToRestoreScratch, GPRReg scratchGPR, MacroAssembler::Jump& success, MacroAssembler::Jump& fail, MacroAssembler::JumpList failureCases)
storage.use();
StorageAccessData& storageAccessData = m_jit.graph().m_storageAccessData[node.storageAccessDataIndex()];
- m_jit.load32(JITCompiler::Address(storageGPR, storageAccessData.offset * sizeof(EncodedJSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)), resultTagGPR);
m_jit.load32(JITCompiler::Address(storageGPR, storageAccessData.offset * sizeof(EncodedJSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)), resultPayloadGPR);
+ m_jit.load32(JITCompiler::Address(storageGPR, storageAccessData.offset * sizeof(EncodedJSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)), resultTagGPR);
jsValueResult(resultTagGPR, resultPayloadGPR, m_compileIndex);
break;