JavaScriptCore:
authormjs@apple.com <mjs@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 23 Sep 2008 07:46:55 +0000 (07:46 +0000)
committermjs@apple.com <mjs@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 23 Sep 2008 07:46:55 +0000 (07:46 +0000)
2008-09-23  Maciej Stachowiak  <mjs@apple.com>

        Reviewed by Darin.

        - speed up instanceof some more
        https://bugs.webkit.org/show_bug.cgi?id=20818

        ~2% speedup on EarleyBoyer

        The idea here is to record in the StructureID whether the class
        needs a special hasInstance or if it can use the normal logic from
        JSObject.

        Based on this I inlined the real work directly into
        cti_op_instanceof and put the fastest checks up front and the
        error handling at the end (so it should be fairly straightforward
        to split off the beginning to be inlined if desired).

        I only did this for CTI, not the bytecode interpreter.

        * API/JSCallbackObject.h:
        (JSC::JSCallbackObject::createStructureID):
        * ChangeLog:
        * VM/Machine.cpp:
        (JSC::Machine::cti_op_instanceof):
        * kjs/JSImmediate.h:
        (JSC::JSImmediate::isAnyImmediate):
        * kjs/TypeInfo.h:
        (JSC::TypeInfo::overridesHasInstance):
        (JSC::TypeInfo::flags):

WebCore:

2008-09-23  Maciej Stachowiak  <mjs@apple.com>

        Reviewed by Darin.

        - speed up instanceof some more
        https://bugs.webkit.org/show_bug.cgi?id=20818

        ~2% speedup on EarleyBoyer

        (WebCore updates.)

        * bindings/js/JSQuarantinedObjectWrapper.h:
        (WebCore::JSQuarantinedObjectWrapper::createStructureID):

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

JavaScriptCore/API/JSCallbackObject.h
JavaScriptCore/ChangeLog
JavaScriptCore/VM/Machine.cpp
JavaScriptCore/kjs/JSImmediate.h
JavaScriptCore/kjs/TypeInfo.h
WebCore/ChangeLog
WebCore/bindings/js/JSQuarantinedObjectWrapper.h

index bc035f8..7f52c5f 100644 (file)
@@ -50,7 +50,7 @@ public:
 
     static PassRefPtr<StructureID> createStructureID(JSValue* proto) 
     { 
-        return StructureID::create(proto, TypeInfo(ObjectType, ImplementsHasInstance)); 
+        return StructureID::create(proto, TypeInfo(ObjectType, ImplementsHasInstance | OverridesHasInstance)); 
     }
 
 private:
index a47c254..542deca 100644 (file)
@@ -1,3 +1,34 @@
+2008-09-23  Maciej Stachowiak  <mjs@apple.com>
+
+        Reviewed by Darin.
+
+        - speed up instanceof some more
+        https://bugs.webkit.org/show_bug.cgi?id=20818
+        
+        ~2% speedup on EarleyBoyer
+
+        The idea here is to record in the StructureID whether the class
+        needs a special hasInstance or if it can use the normal logic from
+        JSObject. 
+        
+        Based on this I inlined the real work directly into
+        cti_op_instanceof and put the fastest checks up front and the
+        error handling at the end (so it should be fairly straightforward
+        to split off the beginning to be inlined if desired).
+
+        I only did this for CTI, not the bytecode interpreter.
+        
+        * API/JSCallbackObject.h:
+        (JSC::JSCallbackObject::createStructureID):
+        * ChangeLog:
+        * VM/Machine.cpp:
+        (JSC::Machine::cti_op_instanceof):
+        * kjs/JSImmediate.h:
+        (JSC::JSImmediate::isAnyImmediate):
+        * kjs/TypeInfo.h:
+        (JSC::TypeInfo::overridesHasInstance):
+        (JSC::TypeInfo::flags):
+
 2008-09-22  Darin Adler  <darin@apple.com>
 
         Reviewed by Sam Weinig.
index 4f43f43..7662fdd 100644 (file)
@@ -4292,8 +4292,37 @@ JSValue* Machine::cti_op_get_by_id_fail(CTI_ARGS)
 JSValue* Machine::cti_op_instanceof(CTI_ARGS)
 {
     ExecState* exec = ARG_exec;
+    JSValue* value = ARG_src1;
     JSValue* baseVal = ARG_src2;
+    JSValue* proto = ARG_src3;
 
+    if (UNLIKELY(JSImmediate::isAnyImmediate(value, baseVal, proto)))
+        goto slow_cases;
+
+    JSCell* valueCell = static_cast<JSCell*>(value);
+    JSCell* baseCell = static_cast<JSCell*>(baseVal);
+    JSCell* protoCell = static_cast<JSCell*>(proto);
+
+    if (UNLIKELY(!valueCell->isObject() | !baseCell->isObject() | !protoCell->isObject()))
+        goto slow_cases;
+
+    if (UNLIKELY((baseCell->structureID()->typeInfo().flags() & (ImplementsHasInstance | OverridesHasInstance)) != ImplementsHasInstance))
+        goto slow_cases;
+
+    JSObject* testPrototype = static_cast<JSObject*>(static_cast<JSObject*>(valueCell)->prototype());
+
+    if (testPrototype == proto)
+        return jsBoolean(true);
+
+    while (testPrototype != jsNull()) {
+        testPrototype = static_cast<JSObject*>(testPrototype->prototype());
+        if (testPrototype == proto)
+            return jsBoolean(true);
+    }
+
+    return jsBoolean(false);
+
+ slow_cases:     
     if (!baseVal->isObject()) {
         CodeBlock* codeBlock = ARG_codeBlock;
         ASSERT(codeBlock->ctiReturnAddressVPCMap.contains(CTI_RETURN_ADDRESS));
@@ -4302,10 +4331,23 @@ JSValue* Machine::cti_op_instanceof(CTI_ARGS)
         VM_CHECK_EXCEPTION(JSValue*);
     }
 
-    JSObject* baseObj = static_cast<JSObject*>(baseVal);
-    JSValue* basePrototype = ARG_src3;
-    JSValue* result = jsBoolean(baseObj->structureID()->typeInfo().implementsHasInstance() ? baseObj->hasInstance(exec,  ARG_src1, basePrototype) : false);
+    baseCell = static_cast<JSCell*>(baseVal);
+    if (!baseCell->structureID()->typeInfo().implementsHasInstance())
+        return jsBoolean(false);
+
+    if (!proto->isObject()) {
+        throwError(exec, TypeError, "instanceof called on an object with an invalid prototype property.");
+        VM_CHECK_EXCEPTION(JSValue*);
+    }
+        
+    if (!value->isObject())
+        return jsBoolean(false);
+
+    ASSERT(baseCell->structureID()->typeInfo().implementsHasInstance());
+
+    JSValue* result = jsBoolean(static_cast<JSObject*>(baseCell)->hasInstance(exec, value, proto));
     VM_CHECK_EXCEPTION_AT_END();
+
     return result;
 }
 
index aabf2a0..23201d8 100644 (file)
@@ -154,6 +154,11 @@ namespace JSC {
             return (reinterpret_cast<uintptr_t>(v1) | reinterpret_cast<uintptr_t>(v2)) & TagMask;
         }
 
+        static ALWAYS_INLINE bool isAnyImmediate(const JSValue* v1, const JSValue* v2, JSValue* v3)
+        {
+            return (reinterpret_cast<uintptr_t>(v1) | reinterpret_cast<uintptr_t>(v2) | reinterpret_cast<uintptr_t>(v3)) & TagMask;
+        }
+
         static ALWAYS_INLINE bool areBothImmediate(const JSValue* v1, const JSValue* v2)
         {
             return isImmediate(v1) & isImmediate(v2);
index 319daa0..ac86d9d 100644 (file)
@@ -32,8 +32,9 @@
 namespace JSC {
 
     // WebCore uses this to make document.all and style.filter undetectable.
-    static const unsigned MasqueradesAsUndefined = 0x1;
-    static const unsigned ImplementsHasInstance = 0x2;
+    static const unsigned MasqueradesAsUndefined = 1;
+    static const unsigned ImplementsHasInstance = 1 << 1;
+    static const unsigned OverridesHasInstance = 1 << 2;
 
     class TypeInfo {
         friend class CTI;
@@ -44,7 +45,9 @@ namespace JSC {
 
         bool masqueradesAsUndefined() const { return m_flags & MasqueradesAsUndefined; }
         bool implementsHasInstance() const { return m_flags & ImplementsHasInstance; }
+        bool overridesHasInstance() const { return m_flags & OverridesHasInstance; }
 
+        unsigned flags() const { return m_flags; }
     private:
         JSType m_type;
         unsigned m_flags;
index d099ebc..0be3e39 100644 (file)
@@ -1,3 +1,17 @@
+2008-09-23  Maciej Stachowiak  <mjs@apple.com>
+
+        Reviewed by Darin.
+
+        - speed up instanceof some more
+        https://bugs.webkit.org/show_bug.cgi?id=20818
+
+        ~2% speedup on EarleyBoyer
+
+        (WebCore updates.)
+        
+        * bindings/js/JSQuarantinedObjectWrapper.h:
+        (WebCore::JSQuarantinedObjectWrapper::createStructureID):
+
 2008-09-22  Darin Adler  <darin@apple.com>
 
         Reviewed by Oliver Hunt.
index c76ca0d..82ae489 100644 (file)
@@ -46,7 +46,7 @@ namespace WebCore {
 
         static PassRefPtr<JSC::StructureID> createStructureID(JSC::JSValue* proto) 
         { 
-            return JSC::StructureID::create(proto, JSC::TypeInfo(JSC::ObjectType, JSC::ImplementsHasInstance)); 
+            return JSC::StructureID::create(proto, JSC::TypeInfo(JSC::ObjectType, JSC::ImplementsHasInstance | JSC::OverridesHasInstance)); 
         }
 
     protected: