DFG should inline prototype chain accesses, and do the right things if the
authorbarraclough@apple.com <barraclough@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 8 Jun 2012 04:25:58 +0000 (04:25 +0000)
committerbarraclough@apple.com <barraclough@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 8 Jun 2012 04:25:58 +0000 (04:25 +0000)
specific function optimization is available
https://bugs.webkit.org/show_bug.cgi?id=88594

Patch by Filip Pizlo <fpizlo@apple.com> on 2012-06-07
Reviewed by Gavin Barraclough.

Looks like a 3% win on V8.

* bytecode/CodeBlock.h:
(JSC::Structure::prototypeForLookup):
(JSC):
* bytecode/GetByIdStatus.cpp:
(JSC::GetByIdStatus::computeFromLLInt):
(JSC):
(JSC::GetByIdStatus::computeForChain):
(JSC::GetByIdStatus::computeFor):
* bytecode/GetByIdStatus.h:
(JSC::GetByIdStatus::GetByIdStatus):
(JSC::GetByIdStatus::isSimple):
(JSC::GetByIdStatus::chain):
(JSC::GetByIdStatus::specificValue):
(GetByIdStatus):
* bytecode/StructureSet.h:
(StructureSet):
(JSC::StructureSet::singletonStructure):
* bytecode/StructureStubInfo.h:
(JSC::StructureStubInfo::initGetByIdProto):
(JSC::StructureStubInfo::initGetByIdChain):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::handleGetById):
* dfg/DFGRepatch.cpp:
(JSC::DFG::tryCacheGetByID):
* jit/JITStubs.cpp:
(JSC::JITThunks::tryCacheGetByID):
* runtime/JSGlobalObject.h:
(JSC::Structure::prototypeForLookup):
(JSC):
* runtime/Structure.h:
(Structure):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@119795 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
Source/JavaScriptCore/jit/JITInlineMethods.h
Source/JavaScriptCore/llint/LowLevelInterpreter.asm
Source/JavaScriptCore/runtime/JSGlobalData.h
Source/JavaScriptCore/runtime/JSGlobalThis.cpp
Source/JavaScriptCore/runtime/JSObject.cpp
Source/JavaScriptCore/runtime/JSObject.h

index e0842dd..296805d 100644 (file)
 
 2012-06-07  Gavin Barraclough  <barraclough@apple.com>
 
+        Remove JSObject::m_inheritorID
+        https://bugs.webkit.org/show_bug.cgi?id=88378
+
+        Reviewed by Geoff Garen.
+
+        This is rarely used, and not performance critical (the commonly accessed copy is cached on JSFunction),
+        and most objects don't need an inheritorID (this value is only used if the object is used as a prototype).
+        Instead use a private named value in the object's property storage.
+
+        * dfg/DFGSpeculativeJIT.h:
+        (JSC::DFG::SpeculativeJIT::emitAllocateBasicJSObject):
+            - No need m_inheritorID to initialize!
+        * jit/JITInlineMethods.h:
+        (JSC::JIT::emitAllocateBasicJSObject):
+            - No need m_inheritorID to initialize!
+        * llint/LowLevelInterpreter.asm:
+            - No need m_inheritorID to initialize!
+        * runtime/JSGlobalData.h:
+        (JSGlobalData):
+            - Added private name 'm_inheritorIDKey'.
+        * runtime/JSGlobalThis.cpp:
+        (JSC::JSGlobalThis::setUnwrappedObject):
+            - resetInheritorID is now passed a JSGlobalData&.
+        * runtime/JSObject.cpp:
+        (JSC::JSObject::visitChildren):
+            - No m_inheritorID to be marked.
+        (JSC::JSObject::createInheritorID):
+            - Store the newly created inheritorID in the property map.
+        * runtime/JSObject.h:
+        (JSC::JSObject::resetInheritorID):
+            - Remove the inheritorID from property storage.
+        (JSC::JSObject::inheritorID):
+            - Read the inheritorID from property storage.
+
+2012-06-07  Gavin Barraclough  <barraclough@apple.com>
+
         Math.pow on iOS does not support denormal numbers.
         https://bugs.webkit.org/show_bug.cgi?id=88592
 
index 74fe706..6ae43ff 100644 (file)
@@ -2131,9 +2131,6 @@ public:
         // Initialize the object's classInfo pointer
         m_jit.storePtr(MacroAssembler::TrustedImmPtr(&ClassType::s_info), MacroAssembler::Address(resultGPR, JSCell::classInfoOffset()));
         
-        // Initialize the object's inheritorID.
-        m_jit.storePtr(MacroAssembler::TrustedImmPtr(0), MacroAssembler::Address(resultGPR, JSObject::offsetOfInheritorID()));
-        
         // Initialize the object's property storage pointer.
         m_jit.addPtr(MacroAssembler::TrustedImm32(sizeof(JSObject)), resultGPR, scratchGPR);
         m_jit.storePtr(scratchGPR, MacroAssembler::Address(resultGPR, ClassType::offsetOfPropertyStorage()));
index 40985ac..db2af04 100644 (file)
@@ -425,9 +425,6 @@ template <typename ClassType, bool destructor, typename StructureType> inline vo
     // initialize the object's classInfo pointer
     storePtr(TrustedImmPtr(&ClassType::s_info), Address(result, JSCell::classInfoOffset()));
 
-    // initialize the inheritor ID
-    storePtr(TrustedImmPtr(0), Address(result, JSObject::offsetOfInheritorID()));
-
     // initialize the object's property storage pointer
     addPtr(TrustedImm32(sizeof(JSObject)), result, storagePtr);
     storePtr(storagePtr, Address(result, ClassType::offsetOfPropertyStorage()));
index e59ddeb..a22317c 100644 (file)
@@ -311,7 +311,6 @@ macro allocateBasicJSObject(sizeClassIndex, classInfoOffset, structure, result,
         loadp classInfoOffset[scratch1], scratch2
         storep scratch2, [result]
         storep structure, JSCell::m_structure[result]
-        storep 0, JSObject::m_inheritorID[result]
         addp sizeof JSObject, result, scratch1
         storep scratch1, JSObject::m_propertyStorage[result]
     end
index f883310..c2af222 100644 (file)
@@ -38,6 +38,7 @@
 #include "JSValue.h"
 #include "LLIntData.h"
 #include "NumericStrings.h"
+#include "PrivateName.h"
 #include "SmallStrings.h"
 #include "Strong.h"
 #include "Terminator.h"
@@ -281,6 +282,8 @@ namespace JSC {
         bool canUseRegExpJIT() { return m_canUseAssembler; }
 #endif
 
+        PrivateName m_inheritorIDKey;
+
         OwnPtr<ParserArena> parserArena;
         OwnPtr<Keywords> keywords;
         Interpreter* interpreter;
index abd31ac..b2bbae5 100644 (file)
@@ -53,7 +53,7 @@ void JSGlobalThis::setUnwrappedObject(JSGlobalData& globalData, JSGlobalObject*
     ASSERT_ARG(globalObject, globalObject);
     m_unwrappedObject.set(globalData, this, globalObject);
     setPrototype(globalData, globalObject->prototype());
-    resetInheritorID();
+    resetInheritorID(globalData);
 }
 
 } // namespace JSC
index 1ef8ba4..ef6dba9 100644 (file)
@@ -98,9 +98,6 @@ void JSObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
         thisObject->m_propertyStorage.set(storage, StorageBarrier::Unchecked);
     }
 
-    if (thisObject->m_inheritorID)
-        visitor.append(&thisObject->m_inheritorID);
-
 #if !ASSERT_DISABLED
     visitor.m_isCheckingForDefaultMarkViolation = wasCheckingForDefaultMarkViolation;
 #endif
@@ -536,15 +533,21 @@ NEVER_INLINE void JSObject::fillGetterPropertySlot(PropertySlot& slot, WriteBarr
 
 Structure* JSObject::createInheritorID(JSGlobalData& globalData)
 {
+    ASSERT(!getDirectLocation(globalData, globalData.m_inheritorIDKey));
+
     JSGlobalObject* globalObject;
     if (isGlobalThis())
         globalObject = static_cast<JSGlobalThis*>(this)->unwrappedObject();
     else
         globalObject = structure()->globalObject();
     ASSERT(globalObject);
-    m_inheritorID.set(globalData, this, createEmptyObjectStructure(globalData, globalObject, this));
-    ASSERT(m_inheritorID->isEmpty());
-    return m_inheritorID.get();
+    
+    Structure* inheritorID = createEmptyObjectStructure(globalData, globalObject, this);
+    ASSERT(inheritorID->isEmpty());
+
+    PutPropertySlot slot;
+    putDirectInternal<PutModeDefineOwnProperty>(globalData, globalData.m_inheritorIDKey, inheritorID, 0, slot, 0);
+    return inheritorID;
 }
 
 PropertyStorage JSObject::growPropertyStorage(JSGlobalData& globalData, size_t oldSize, size_t newSize)
index 67aa151..4756297 100644 (file)
@@ -236,7 +236,6 @@ namespace JSC {
         
         static size_t offsetOfInlineStorage();
         static size_t offsetOfPropertyStorage();
-        static size_t offsetOfInheritorID();
 
         static JS_EXPORTDATA const ClassInfo s_info;
 
@@ -264,9 +263,9 @@ namespace JSC {
         // To create derived types you likely want JSNonFinalObject, below.
         JSObject(JSGlobalData&, Structure*, PropertyStorage inlineStorage);
         
-        void resetInheritorID()
+        void resetInheritorID(JSGlobalData& globalData)
         {
-            m_inheritorID.clear();
+            removeDirect(globalData, globalData.m_inheritorIDKey);
         }
 
     private:
@@ -303,7 +302,13 @@ namespace JSC {
         Structure* createInheritorID(JSGlobalData&);
 
         StorageBarrier m_propertyStorage;
-        WriteBarrier<Structure> m_inheritorID;
+
+#if USE(JSVALUE32_64)
+        // FIXME: keep the size of JSObject a multiple of 64-bits, so that the
+        // internal storage is aligned. We can remove this when we remove JSCell's
+        // direct ClassInfo pointer.
+        void* sixtyFourBitAlign;
+#endif
     };
 
 
@@ -311,8 +316,8 @@ namespace JSC {
 #define JSNonFinalObject_inlineStorageCapacity 4
 #define JSFinalObject_inlineStorageCapacity 6
 #else
-#define JSNonFinalObject_inlineStorageCapacity 2
-#define JSFinalObject_inlineStorageCapacity 4
+#define JSNonFinalObject_inlineStorageCapacity 3
+#define JSFinalObject_inlineStorageCapacity 5
 #endif
 
 COMPILE_ASSERT((JSFinalObject_inlineStorageCapacity >= JSNonFinalObject_inlineStorageCapacity), final_storage_is_at_least_as_large_as_non_final);
@@ -417,11 +422,6 @@ inline size_t JSObject::offsetOfPropertyStorage()
     return OBJECT_OFFSETOF(JSObject, m_propertyStorage);
 }
 
-inline size_t JSObject::offsetOfInheritorID()
-{
-    return OBJECT_OFFSETOF(JSObject, m_inheritorID);
-}
-
 inline bool JSObject::isGlobalObject() const
 {
     return structure()->typeInfo().type() == GlobalObjectType;
@@ -514,9 +514,10 @@ inline void JSObject::setPrototype(JSGlobalData& globalData, JSValue prototype)
 
 inline Structure* JSObject::inheritorID(JSGlobalData& globalData)
 {
-    if (m_inheritorID) {
-        ASSERT(m_inheritorID->isEmpty());
-        return m_inheritorID.get();
+    if (WriteBarrierBase<Unknown>* location = getDirectLocation(globalData, globalData.m_inheritorIDKey)) {
+        Structure* inheritorID = jsCast<Structure*>(location->get());
+        ASSERT(inheritorID->isEmpty());
+        return inheritorID;
     }
     return createInheritorID(globalData);
 }