Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (90034 => 90035)
--- trunk/Source/_javascript_Core/ChangeLog 2011-06-29 19:20:27 UTC (rev 90034)
+++ trunk/Source/_javascript_Core/ChangeLog 2011-06-29 19:46:28 UTC (rev 90035)
@@ -1,3 +1,21 @@
+2011-06-29 Filip Pizlo <[email protected]>
+
+ Reviewed by Gavin Barraclough.
+
+ DFG JIT does not perform get_by_id self list caching.
+ https://bugs.webkit.org/show_bug.cgi?id=63605
+
+ * bytecode/StructureStubInfo.h:
+ * dfg/DFGJITCompiler.cpp:
+ (JSC::DFG::JITCompiler::compileFunction):
+ * dfg/DFGOperations.cpp:
+ * dfg/DFGOperations.h:
+ * dfg/DFGRepatch.cpp:
+ (JSC::DFG::tryCacheGetByID):
+ (JSC::DFG::tryBuildGetByIDList):
+ (JSC::DFG::dfgBuildGetByIDList):
+ * dfg/DFGRepatch.h:
+
2011-06-28 Filip Pizlo <[email protected]>
Reviewed by Gavin Barraclough.
Modified: trunk/Source/_javascript_Core/bytecode/StructureStubInfo.h (90034 => 90035)
--- trunk/Source/_javascript_Core/bytecode/StructureStubInfo.h 2011-06-29 19:20:27 UTC (rev 90034)
+++ trunk/Source/_javascript_Core/bytecode/StructureStubInfo.h 2011-06-29 19:46:28 UTC (rev 90035)
@@ -127,18 +127,21 @@
seen = true;
}
- signed accessType : 31;
- unsigned seen : 1;
+ int8_t accessType;
+ int8_t seen;
+
+#if ENABLE(DFG_JIT)
+ int8_t baseGPR;
+ int8_t valueGPR;
+ int8_t deltaCallToDone;
+ int8_t deltaCallToStructCheck;
+ int8_t deltaCallToSlowCase;
+#endif
union {
struct {
int8_t deltaCheckImmToCall;
- int8_t deltaCallToStructCheck;
int8_t deltaCallToLoadOrStore;
- int8_t deltaCallToSlowCase;
- int8_t deltaCallToDone;
- int8_t baseGPR;
- int8_t valueGPR;
int8_t scratchGPR;
} unset;
struct {
Modified: trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp (90034 => 90035)
--- trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp 2011-06-29 19:20:27 UTC (rev 90034)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp 2011-06-29 19:46:28 UTC (rev 90035)
@@ -388,12 +388,12 @@
StructureStubInfo& info = m_codeBlock->structureStubInfo(i);
info.callReturnLocation = linkBuffer.locationOf(m_propertyAccesses[i].m_functionCall);
info.u.unset.deltaCheckImmToCall = m_propertyAccesses[i].m_deltaCheckImmToCall;
- info.u.unset.deltaCallToStructCheck = m_propertyAccesses[i].m_deltaCallToStructCheck;
+ info.deltaCallToStructCheck = m_propertyAccesses[i].m_deltaCallToStructCheck;
info.u.unset.deltaCallToLoadOrStore = m_propertyAccesses[i].m_deltaCallToLoadOrStore;
- info.u.unset.deltaCallToSlowCase = m_propertyAccesses[i].m_deltaCallToSlowCase;
- info.u.unset.deltaCallToDone = m_propertyAccesses[i].m_deltaCallToDone;
- info.u.unset.baseGPR = m_propertyAccesses[i].m_baseGPR;
- info.u.unset.valueGPR = m_propertyAccesses[i].m_valueGPR;
+ info.deltaCallToSlowCase = m_propertyAccesses[i].m_deltaCallToSlowCase;
+ info.deltaCallToDone = m_propertyAccesses[i].m_deltaCallToDone;
+ info.baseGPR = m_propertyAccesses[i].m_baseGPR;
+ info.valueGPR = m_propertyAccesses[i].m_valueGPR;
info.u.unset.scratchGPR = m_propertyAccesses[i].m_scratchGPR;
}
Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (90034 => 90035)
--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp 2011-06-29 19:20:27 UTC (rev 90034)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp 2011-06-29 19:46:28 UTC (rev 90035)
@@ -244,6 +244,20 @@
return JSValue::encode(result);
}
+EncodedJSValue operationGetByIdBuildListWithReturnAddress(ExecState*, EncodedJSValue, Identifier*, ReturnAddressPtr);
+FUNCTION_WRAPPER_WITH_ARG4_RETURN_ADDRESS(operationGetByIdBuildList);
+EncodedJSValue operationGetByIdBuildListWithReturnAddress(ExecState* exec, EncodedJSValue encodedBase, Identifier* propertyName, ReturnAddressPtr returnAddress)
+{
+ JSValue baseValue = JSValue::decode(encodedBase);
+ PropertySlot slot(baseValue);
+ JSValue result = baseValue.get(exec, *propertyName, slot);
+
+ StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
+ dfgBuildGetByIDList(exec, baseValue, *propertyName, slot, stubInfo);
+
+ return JSValue::encode(result);
+}
+
void operationPutByValStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
{
operationPutByValInternal<true>(exec, encodedBase, encodedProperty, encodedValue);
Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.h (90034 => 90035)
--- trunk/Source/_javascript_Core/dfg/DFGOperations.h 2011-06-29 19:20:27 UTC (rev 90034)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.h 2011-06-29 19:46:28 UTC (rev 90035)
@@ -59,6 +59,7 @@
EncodedJSValue operationArithMod(EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
EncodedJSValue operationGetByVal(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty);
EncodedJSValue operationGetById(ExecState*, EncodedJSValue encodedBase, Identifier*);
+EncodedJSValue operationGetByIdBuildList(ExecState*, EncodedJSValue encodedBase, Identifier*);
EncodedJSValue operationGetByIdOptimize(ExecState*, EncodedJSValue encodedBase, Identifier*);
void operationPutByValStrict(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue);
void operationPutByValNonStrict(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue);
Modified: trunk/Source/_javascript_Core/dfg/DFGRepatch.cpp (90034 => 90035)
--- trunk/Source/_javascript_Core/dfg/DFGRepatch.cpp 2011-06-29 19:20:27 UTC (rev 90034)
+++ trunk/Source/_javascript_Core/dfg/DFGRepatch.cpp 2011-06-29 19:46:28 UTC (rev 90035)
@@ -64,8 +64,8 @@
JSGlobalData* globalData = &exec->globalData();
if (isJSArray(globalData, baseValue) && propertyName == exec->propertyNames().length) {
- GPRReg baseGPR = static_cast<GPRReg>(stubInfo.u.unset.baseGPR);
- GPRReg resultGPR = static_cast<GPRReg>(stubInfo.u.unset.valueGPR);
+ GPRReg baseGPR = static_cast<GPRReg>(stubInfo.baseGPR);
+ GPRReg resultGPR = static_cast<GPRReg>(stubInfo.valueGPR);
GPRReg scratchGPR = static_cast<GPRReg>(stubInfo.u.unset.scratchGPR);
bool needToRestoreScratch = false;
@@ -104,9 +104,9 @@
LinkBuffer patchBuffer(*globalData, &stubJit, codeBlock->executablePool());
- CodeLocationLabel slowCaseBegin = stubInfo.callReturnLocation.labelAtOffset(stubInfo.u.unset.deltaCallToSlowCase);
+ CodeLocationLabel slowCaseBegin = stubInfo.callReturnLocation.labelAtOffset(stubInfo.deltaCallToSlowCase);
- patchBuffer.link(success, stubInfo.callReturnLocation.labelAtOffset(stubInfo.u.unset.deltaCallToDone));
+ patchBuffer.link(success, stubInfo.callReturnLocation.labelAtOffset(stubInfo.deltaCallToDone));
if (needToRestoreScratch)
patchBuffer.link(fail, slowCaseBegin);
@@ -121,7 +121,7 @@
CodeLocationLabel hotPathBegin = stubInfo.hotPathBegin;
RepatchBuffer repatchBuffer(codeBlock);
- repatchBuffer.relink(stubInfo.callReturnLocation.jumpAtOffset(stubInfo.u.unset.deltaCallToStructCheck), entryLabel);
+ repatchBuffer.relink(stubInfo.callReturnLocation.jumpAtOffset(stubInfo.deltaCallToStructCheck), entryLabel);
repatchBuffer.relink(stubInfo.callReturnLocation, operationGetById);
return true;
@@ -144,11 +144,11 @@
if ((slot.cachedPropertyType() != PropertySlot::Value) || ((slot.cachedOffset() * sizeof(JSValue)) > (unsigned)MacroAssembler::MaximumCompactPtrAlignedAddressOffset))
return false;
- dfgRepatchByIdSelfAccess(codeBlock, stubInfo, structure, slot.cachedOffset(), operationGetById, true);
+ dfgRepatchByIdSelfAccess(codeBlock, stubInfo, structure, slot.cachedOffset(), operationGetByIdBuildList, true);
stubInfo.initGetByIdSelf(*globalData, codeBlock->ownerExecutable(), structure);
return true;
}
-
+
// FIXME: should support prototype & chain accesses!
return false;
}
@@ -160,6 +160,84 @@
dfgRepatchCall(exec->codeBlock(), stubInfo.callReturnLocation, operationGetById);
}
+static bool tryBuildGetByIDList(ExecState* exec, JSValue baseValue, const Identifier&, const PropertySlot& slot, StructureStubInfo& stubInfo)
+{
+ if (!baseValue.isCell()
+ || !slot.isCacheable()
+ || baseValue.asCell()->structure()->isUncacheableDictionary()
+ || slot.slotBase() != baseValue
+ || slot.cachedPropertyType() != PropertySlot::Value
+ || (slot.cachedOffset() * sizeof(JSValue)) > (unsigned)MacroAssembler::MaximumCompactPtrAlignedAddressOffset)
+ return false;
+
+ CodeBlock* codeBlock = exec->codeBlock();
+ JSCell* baseCell = baseValue.asCell();
+ Structure* structure = baseCell->structure();
+ JSGlobalData* globalData = &exec->globalData();
+
+ ASSERT(slot.slotBase().isObject());
+
+ PolymorphicAccessStructureList* polymorphicStructureList;
+ int listIndex = 1;
+
+ if (stubInfo.accessType == access_get_by_id_self) {
+ ASSERT(!stubInfo.stubRoutine);
+ polymorphicStructureList = new PolymorphicAccessStructureList(*globalData, codeBlock->ownerExecutable(), stubInfo.callReturnLocation.labelAtOffset(stubInfo.deltaCallToSlowCase), stubInfo.u.getByIdSelf.baseObjectStructure.get());
+ stubInfo.initGetByIdSelfList(polymorphicStructureList, 1);
+ } else {
+ polymorphicStructureList = stubInfo.u.getByIdSelfList.structureList;
+ listIndex = stubInfo.u.getByIdSelfList.listSize;
+ }
+
+ if (listIndex < POLYMORPHIC_LIST_CACHE_SIZE) {
+ stubInfo.u.getByIdSelfList.listSize++;
+
+ GPRReg baseGPR = static_cast<GPRReg>(stubInfo.baseGPR);
+ GPRReg resultGPR = static_cast<GPRReg>(stubInfo.valueGPR);
+
+ MacroAssembler stubJit;
+
+ MacroAssembler::Jump wrongStruct = stubJit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::structureOffset()), MacroAssembler::TrustedImmPtr(structure));
+
+ if (structure->isUsingInlineStorage())
+ stubJit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::offsetOfInlineStorage() + slot.cachedOffset() * sizeof(JSValue)), resultGPR);
+ else {
+ stubJit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::offsetOfPropertyStorage()), resultGPR);
+ stubJit.loadPtr(MacroAssembler::Address(resultGPR, slot.cachedOffset() * sizeof(JSValue)), resultGPR);
+ }
+
+ MacroAssembler::Jump success = stubJit.jump();
+
+ LinkBuffer patchBuffer(*globalData, &stubJit, codeBlock->executablePool());
+
+ CodeLocationLabel lastProtoBegin = polymorphicStructureList->list[listIndex - 1].stubRoutine;
+ ASSERT(!!lastProtoBegin);
+
+ patchBuffer.link(wrongStruct, lastProtoBegin);
+ patchBuffer.link(success, stubInfo.callReturnLocation.labelAtOffset(stubInfo.deltaCallToDone));
+
+ CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum();
+
+ polymorphicStructureList->list[listIndex].set(*globalData, codeBlock->ownerExecutable(), entryLabel, structure);
+
+ CodeLocationJump jumpLocation = stubInfo.callReturnLocation.jumpAtOffset(stubInfo.deltaCallToStructCheck);
+ RepatchBuffer repatchBuffer(codeBlock);
+ repatchBuffer.relink(jumpLocation, entryLabel);
+
+ if (listIndex < (POLYMORPHIC_LIST_CACHE_SIZE - 1))
+ return true;
+ }
+
+ return false;
+}
+
+void dfgBuildGetByIDList(ExecState* exec, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot, StructureStubInfo& stubInfo)
+{
+ bool dontChangeCall = tryBuildGetByIDList(exec, baseValue, propertyName, slot, stubInfo);
+ if (!dontChangeCall)
+ dfgRepatchCall(exec->codeBlock(), stubInfo.callReturnLocation, operationGetById);
+}
+
static V_DFGOperation_EJJI appropriatePutByIdFunction(const PutPropertySlot &slot, PutKind putKind)
{
if (slot.isStrictMode()) {
Modified: trunk/Source/_javascript_Core/dfg/DFGRepatch.h (90034 => 90035)
--- trunk/Source/_javascript_Core/dfg/DFGRepatch.h 2011-06-29 19:20:27 UTC (rev 90034)
+++ trunk/Source/_javascript_Core/dfg/DFGRepatch.h 2011-06-29 19:46:28 UTC (rev 90035)
@@ -34,6 +34,7 @@
namespace JSC { namespace DFG {
void dfgRepatchGetByID(ExecState*, JSValue, const Identifier&, const PropertySlot&, StructureStubInfo&);
+void dfgBuildGetByIDList(ExecState*, JSValue, const Identifier&, const PropertySlot&, StructureStubInfo&);
void dfgRepatchPutByID(ExecState*, JSValue, const Identifier&, const PutPropertySlot&, StructureStubInfo&, PutKind);
} } // namespace JSC::DFG