Title: [183113] trunk/Source/_javascript_Core
Revision
183113
Author
[email protected]
Date
2015-04-22 10:39:44 -0700 (Wed, 22 Apr 2015)

Log Message

Don't de-allocate FunctionRareData
https://bugs.webkit.org/show_bug.cgi?id=144000

Patch by Basile Clement <[email protected]> on 2015-04-22
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):

Modified Paths

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());
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to