Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (183112 => 183113)
--- trunk/Source/_javascript_Core/ChangeLog 2015-04-22 17:39:38 UTC (rev 183112)
+++ trunk/Source/_javascript_Core/ChangeLog 2015-04-22 17:39:44 UTC (rev 183113)
@@ -1,3 +1,27 @@
+2015-04-22 Basile Clement <[email protected]>
+
+ Don't de-allocate FunctionRareData
+ https://bugs.webkit.org/show_bug.cgi?id=144000
+
+ Reviewed by Michael Saboff.
+
+ A function rare data (containing most notably its allocation profile) is currently
+ freed and re-allocated each time the function's prototype is cleared.
+ This is not optimal as it means we are invalidating the watchpoint and recompiling the
+ scope each time the prototype is cleared.
+
+ This makes it so that a single rare data is reused, clearing the underlying
+ ObjectAllocationProfile instead of throwing away the whole rare data on
+ .prototype updates.
+
+ * runtime/FunctionRareData.cpp:
+ (JSC::FunctionRareData::create):
+ (JSC::FunctionRareData::finishCreation):
+ * runtime/FunctionRareData.h:
+ * runtime/JSFunction.cpp:
+ (JSC::JSFunction::allocateAndInitializeRareData):
+ (JSC::JSFunction::initializeRareData):
+
2015-04-21 Filip Pizlo <[email protected]>
Unreviewed, fix 32-bit. Forgot to make this simple change to 32_64 as well.
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (183112 => 183113)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2015-04-22 17:39:38 UTC (rev 183112)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2015-04-22 17:39:44 UTC (rev 183113)
@@ -3513,6 +3513,7 @@
slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, rareDataGPR));
m_jit.loadPtr(JITCompiler::Address(rareDataGPR, FunctionRareData::offsetOfAllocationProfile() + ObjectAllocationProfile::offsetOfAllocator()), allocatorGPR);
m_jit.loadPtr(JITCompiler::Address(rareDataGPR, FunctionRareData::offsetOfAllocationProfile() + ObjectAllocationProfile::offsetOfStructure()), structureGPR);
+ slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, allocatorGPR));
emitAllocateJSObject(resultGPR, allocatorGPR, structureGPR, TrustedImmPtr(0), scratchGPR, slowPath);
addSlowPathGenerator(slowPathCall(slowPath, this, operationCreateThis, resultGPR, calleeGPR, node->inlineCapacity()));
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (183112 => 183113)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2015-04-22 17:39:38 UTC (rev 183112)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2015-04-22 17:39:44 UTC (rev 183113)
@@ -3584,6 +3584,7 @@
slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, rareDataGPR));
m_jit.loadPtr(JITCompiler::Address(rareDataGPR, FunctionRareData::offsetOfAllocationProfile() + ObjectAllocationProfile::offsetOfAllocator()), allocatorGPR);
m_jit.loadPtr(JITCompiler::Address(rareDataGPR, FunctionRareData::offsetOfAllocationProfile() + ObjectAllocationProfile::offsetOfStructure()), structureGPR);
+ slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, allocatorGPR));
emitAllocateJSObject(resultGPR, allocatorGPR, structureGPR, TrustedImmPtr(0), scratchGPR, slowPath);
addSlowPathGenerator(slowPathCall(slowPath, this, operationCreateThis, resultGPR, calleeGPR, node->inlineCapacity()));
Modified: trunk/Source/_javascript_Core/jit/JITOpcodes.cpp (183112 => 183113)
--- trunk/Source/_javascript_Core/jit/JITOpcodes.cpp 2015-04-22 17:39:38 UTC (rev 183112)
+++ trunk/Source/_javascript_Core/jit/JITOpcodes.cpp 2015-04-22 17:39:44 UTC (rev 183113)
@@ -706,6 +706,7 @@
addSlowCase(branchTestPtr(Zero, rareDataReg));
loadPtr(Address(rareDataReg, FunctionRareData::offsetOfAllocationProfile() + ObjectAllocationProfile::offsetOfAllocator()), allocatorReg);
loadPtr(Address(rareDataReg, FunctionRareData::offsetOfAllocationProfile() + ObjectAllocationProfile::offsetOfStructure()), structureReg);
+ addSlowCase(branchTestPtr(Zero, allocatorReg));
emitAllocateJSObject(allocatorReg, structureReg, resultReg, scratchReg);
emitPutVirtualRegister(currentInstruction[1].u.operand);
@@ -713,6 +714,7 @@
void JIT::emitSlow_op_create_this(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
+ linkSlowCase(iter); // doesn't have rare data
linkSlowCase(iter); // doesn't have an allocation profile
linkSlowCase(iter); // allocation failed
Modified: trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp (183112 => 183113)
--- trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp 2015-04-22 17:39:38 UTC (rev 183112)
+++ trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp 2015-04-22 17:39:44 UTC (rev 183113)
@@ -925,6 +925,7 @@
addSlowCase(branchTestPtr(Zero, rareDataReg));
loadPtr(Address(rareDataReg, FunctionRareData::offsetOfAllocationProfile() + ObjectAllocationProfile::offsetOfAllocator()), allocatorReg);
loadPtr(Address(rareDataReg, FunctionRareData::offsetOfAllocationProfile() + ObjectAllocationProfile::offsetOfStructure()), structureReg);
+ addSlowCase(branchTestPtr(Zero, allocatorReg));
emitAllocateJSObject(allocatorReg, structureReg, resultReg, scratchReg);
emitStoreCell(currentInstruction[1].u.operand, resultReg);
@@ -932,6 +933,7 @@
void JIT::emitSlow_op_create_this(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
+ linkSlowCase(iter); // doesn't have rare data
linkSlowCase(iter); // doesn't have an allocation profile
linkSlowCase(iter); // allocation failed
Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm (183112 => 183113)
--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm 2015-04-22 17:39:38 UTC (rev 183112)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm 2015-04-22 17:39:44 UTC (rev 183113)
@@ -744,6 +744,7 @@
btpz t4, .opCreateThisSlow
loadp FunctionRareData::m_allocationProfile + ObjectAllocationProfile::m_allocator[t4], t1
loadp FunctionRareData::m_allocationProfile + ObjectAllocationProfile::m_structure[t4], t2
+ btpz t1, .opCreateThisSlow
allocateJSObject(t1, t2, t0, t3, .opCreateThisSlow)
loadi 4[PC], t1
storei CellTag, TagOffset[cfr, t1, 8]
Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm (183112 => 183113)
--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm 2015-04-22 17:39:38 UTC (rev 183112)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm 2015-04-22 17:39:44 UTC (rev 183113)
@@ -630,6 +630,7 @@
btpz t4, .opCreateThisSlow
loadp FunctionRareData::m_allocationProfile + ObjectAllocationProfile::m_allocator[t4], t1
loadp FunctionRareData::m_allocationProfile + ObjectAllocationProfile::m_structure[t4], t2
+ btpz t1, .opCreateThisSlow
allocateJSObject(t1, t2, t0, t3, .opCreateThisSlow)
loadisFromInstruction(1, t1)
storeq t0, [cfr, t1, 8]
Modified: trunk/Source/_javascript_Core/runtime/FunctionRareData.cpp (183112 => 183113)
--- trunk/Source/_javascript_Core/runtime/FunctionRareData.cpp 2015-04-22 17:39:38 UTC (rev 183112)
+++ trunk/Source/_javascript_Core/runtime/FunctionRareData.cpp 2015-04-22 17:39:44 UTC (rev 183113)
@@ -80,7 +80,18 @@
void FunctionRareData::finishCreation(VM& vm, JSObject* prototype, size_t inlineCapacity)
{
Base::finishCreation(vm);
+ initialize(vm, prototype, inlineCapacity);
+}
+
+void FunctionRareData::initialize(VM& vm, JSObject* prototype, size_t inlineCapacity)
+{
m_allocationProfile.initialize(vm, this, prototype, inlineCapacity);
}
+void FunctionRareData::clear(const char* reason)
+{
+ m_allocationProfile.clear();
+ m_allocationProfileWatchpoint.fireAll(reason);
}
+
+}
Modified: trunk/Source/_javascript_Core/runtime/FunctionRareData.h (183112 => 183113)
--- trunk/Source/_javascript_Core/runtime/FunctionRareData.h 2015-04-22 17:39:38 UTC (rev 183112)
+++ trunk/Source/_javascript_Core/runtime/FunctionRareData.h 2015-04-22 17:39:44 UTC (rev 183113)
@@ -77,6 +77,12 @@
return m_allocationProfileWatchpoint;
}
+ void clear(const char* reason);
+
+ void initialize(VM&, JSObject* prototype, size_t inlineCapacity);
+
+ bool isInitialized() { return !m_allocationProfile.isNull(); }
+
protected:
FunctionRareData(VM&);
~FunctionRareData();
Modified: trunk/Source/_javascript_Core/runtime/JSFunction.cpp (183112 => 183113)
--- trunk/Source/_javascript_Core/runtime/JSFunction.cpp 2015-04-22 17:39:38 UTC (rev 183112)
+++ trunk/Source/_javascript_Core/runtime/JSFunction.cpp 2015-04-22 17:39:44 UTC (rev 183113)
@@ -108,8 +108,9 @@
return function;
}
-FunctionRareData* JSFunction::createRareData(ExecState* exec, size_t inlineCapacity)
+FunctionRareData* JSFunction::allocateAndInitializeRareData(ExecState* exec, size_t inlineCapacity)
{
+ ASSERT(!m_rareData);
VM& vm = exec->vm();
JSObject* prototype = jsDynamicCast<JSObject*>(get(exec, vm.propertyNames->prototype));
if (!prototype)
@@ -119,6 +120,17 @@
return m_rareData.get();
}
+FunctionRareData* JSFunction::initializeRareData(ExecState* exec, size_t inlineCapacity)
+{
+ ASSERT(!!m_rareData);
+ VM& vm = exec->vm();
+ JSObject* prototype = jsDynamicCast<JSObject*>(get(exec, vm.propertyNames->prototype));
+ if (!prototype)
+ prototype = globalObject()->objectPrototype();
+ m_rareData->initialize(globalObject()->vm(), prototype, inlineCapacity);
+ return m_rareData.get();
+}
+
String JSFunction::name(ExecState* exec)
{
return get(exec, exec->vm().propertyNames->name).toWTFString(exec);
@@ -389,10 +401,8 @@
// following the rules set out in ECMA-262 8.12.9.
PropertySlot slot(thisObject);
thisObject->methodTable(exec->vm())->getOwnPropertySlot(thisObject, exec, propertyName, slot);
- if (thisObject->m_rareData) {
- thisObject->m_rareData->allocationProfileWatchpointSet().fireAll("Store to prototype property of a function");
- thisObject->m_rareData.clear();
- }
+ if (thisObject->m_rareData)
+ thisObject->m_rareData->clear("Store to prototype property of a function");
// Don't allow this to be cached, since a [[Put]] must clear m_rareData.
PutPropertySlot dontCache(thisObject);
Base::put(thisObject, exec, propertyName, value, dontCache);
@@ -438,10 +448,8 @@
// following the rules set out in ECMA-262 8.12.9.
PropertySlot slot(thisObject);
thisObject->methodTable(exec->vm())->getOwnPropertySlot(thisObject, exec, propertyName, slot);
- if (thisObject->m_rareData) {
- thisObject->m_rareData->allocationProfileWatchpointSet().fireAll("Store to prototype property of a function");
- thisObject->m_rareData.clear();
- }
+ if (thisObject->m_rareData)
+ thisObject->m_rareData->clear("Store to prototype property of a function");
return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
}
Modified: trunk/Source/_javascript_Core/runtime/JSFunction.h (183112 => 183113)
--- trunk/Source/_javascript_Core/runtime/JSFunction.h 2015-04-22 17:39:38 UTC (rev 183112)
+++ trunk/Source/_javascript_Core/runtime/JSFunction.h 2015-04-22 17:39:44 UTC (rev 183113)
@@ -112,7 +112,9 @@
FunctionRareData* rareData(ExecState* exec, unsigned inlineCapacity)
{
if (UNLIKELY(!m_rareData))
- return createRareData(exec, inlineCapacity);
+ return allocateAndInitializeRareData(exec, inlineCapacity);
+ if (UNLIKELY(!m_rareData->isInitialized()))
+ return initializeRareData(exec, inlineCapacity);
return m_rareData.get();
}
@@ -138,7 +140,8 @@
void finishCreation(VM&, NativeExecutable*, int length, const String& name);
using Base::finishCreation;
- FunctionRareData* createRareData(ExecState*, size_t inlineCapacity);
+ FunctionRareData* allocateAndInitializeRareData(ExecState*, size_t inlineCapacity);
+ FunctionRareData* initializeRareData(ExecState*, size_t inlineCapacity);
static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&);
static void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode = EnumerationMode());