De-virtualize JSObject::hasInstance
https://bugs.webkit.org/show_bug.cgi?id=71430

Reviewed by Darin Adler.

Added hasInstance to the MethodTable, changed all the virtual
implementations of hasInstance to static ones, and replaced
all call sites with corresponding lookups in the MethodTable.

* API/JSCallbackObject.h:
* API/JSCallbackObjectFunctions.h:
(JSC::::hasInstance):
* API/JSValueRef.cpp:
(JSValueIsInstanceOfConstructor):
* JavaScriptCore.exp:
* JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def:
* interpreter/Interpreter.cpp:
(JSC::Interpreter::privateExecute):
* jit/JITStubs.cpp:
(JSC::DEFINE_STUB_FUNCTION):
* runtime/ClassInfo.h:
* runtime/JSBoundFunction.cpp:
(JSC::JSBoundFunction::hasInstance):
* runtime/JSBoundFunction.h:
* runtime/JSCell.cpp:
(JSC::JSCell::hasInstance):
* runtime/JSCell.h:
* runtime/JSObject.cpp:
(JSC::JSObject::hasInstance):
* runtime/JSObject.h:


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@99312 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/API/JSCallbackObject.h b/Source/JavaScriptCore/API/JSCallbackObject.h
index 625082e..46924a0 100644
--- a/Source/JavaScriptCore/API/JSCallbackObject.h
+++ b/Source/JavaScriptCore/API/JSCallbackObject.h
@@ -185,7 +185,7 @@
     static bool deleteProperty(JSCell*, ExecState*, const Identifier&);
     static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned);
 
-    virtual bool hasInstance(ExecState* exec, JSValue value, JSValue proto);
+    static bool hasInstance(JSObject*, ExecState*, JSValue, JSValue proto);
 
     static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
 
diff --git a/Source/JavaScriptCore/API/JSCallbackObjectFunctions.h b/Source/JavaScriptCore/API/JSCallbackObjectFunctions.h
index 9b100bc..dd5ebd8 100644
--- a/Source/JavaScriptCore/API/JSCallbackObjectFunctions.h
+++ b/Source/JavaScriptCore/API/JSCallbackObjectFunctions.h
@@ -355,12 +355,13 @@
 }
 
 template <class Parent>
-bool JSCallbackObject<Parent>::hasInstance(ExecState* exec, JSValue value, JSValue)
+bool JSCallbackObject<Parent>::hasInstance(JSObject* object, ExecState* exec, JSValue value, JSValue)
 {
+    JSCallbackObject* thisObject = static_cast<JSCallbackObject*>(object);
     JSContextRef execRef = toRef(exec);
-    JSObjectRef thisRef = toRef(this);
+    JSObjectRef thisRef = toRef(thisObject);
     
-    for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass) {
+    for (JSClassRef jsClass = thisObject->classRef(); jsClass; jsClass = jsClass->parentClass) {
         if (JSObjectHasInstanceCallback hasInstance = jsClass->hasInstance) {
             JSValueRef valueRef = toRef(exec, value);
             JSValueRef exception = 0;
diff --git a/Source/JavaScriptCore/API/JSValueRef.cpp b/Source/JavaScriptCore/API/JSValueRef.cpp
index 803ccd9..9b3e7b2 100644
--- a/Source/JavaScriptCore/API/JSValueRef.cpp
+++ b/Source/JavaScriptCore/API/JSValueRef.cpp
@@ -175,7 +175,7 @@
     JSObject* jsConstructor = toJS(constructor);
     if (!jsConstructor->structure()->typeInfo().implementsHasInstance())
         return false;
-    bool result = jsConstructor->hasInstance(exec, jsValue, jsConstructor->get(exec, exec->propertyNames().prototype)); // false if an exception is thrown
+    bool result = jsConstructor->methodTable()->hasInstance(jsConstructor, exec, jsValue, jsConstructor->get(exec, exec->propertyNames().prototype)); // false if an exception is thrown
     if (exec->hadException()) {
         if (exception)
             *exception = toRef(exec, exec->exception());
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog
index a7a3eb9..ecf7f3d28 100644
--- a/Source/JavaScriptCore/ChangeLog
+++ b/Source/JavaScriptCore/ChangeLog
@@ -1,3 +1,36 @@
+2011-11-04  Mark Hahnenberg  <mhahnenberg@apple.com>
+
+        De-virtualize JSObject::hasInstance
+        https://bugs.webkit.org/show_bug.cgi?id=71430
+
+        Reviewed by Darin Adler.
+
+        Added hasInstance to the MethodTable, changed all the virtual 
+        implementations of hasInstance to static ones, and replaced 
+        all call sites with corresponding lookups in the MethodTable.
+
+        * API/JSCallbackObject.h:
+        * API/JSCallbackObjectFunctions.h:
+        (JSC::::hasInstance):
+        * API/JSValueRef.cpp:
+        (JSValueIsInstanceOfConstructor):
+        * JavaScriptCore.exp:
+        * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def:
+        * interpreter/Interpreter.cpp:
+        (JSC::Interpreter::privateExecute):
+        * jit/JITStubs.cpp:
+        (JSC::DEFINE_STUB_FUNCTION):
+        * runtime/ClassInfo.h:
+        * runtime/JSBoundFunction.cpp:
+        (JSC::JSBoundFunction::hasInstance):
+        * runtime/JSBoundFunction.h:
+        * runtime/JSCell.cpp:
+        (JSC::JSCell::hasInstance):
+        * runtime/JSCell.h:
+        * runtime/JSObject.cpp:
+        (JSC::JSObject::hasInstance):
+        * runtime/JSObject.h:
+
 2011-11-04  Tor Arne Vestbø  <tor.arne.vestbo@nokia.com>
 
         [Qt] Refactor and clean up the qmake build system
diff --git a/Source/JavaScriptCore/JavaScriptCore.exp b/Source/JavaScriptCore/JavaScriptCore.exp
index 96a5c06..e801d8e 100644
--- a/Source/JavaScriptCore/JavaScriptCore.exp
+++ b/Source/JavaScriptCore/JavaScriptCore.exp
@@ -303,7 +303,7 @@
 __ZN3JSC8Debugger6detachEPNS_14JSGlobalObjectE
 __ZN3JSC8DebuggerD2Ev
 __ZN3JSC8JSObject10putByIndexEPNS_6JSCellEPNS_9ExecStateEjNS_7JSValueE
-__ZN3JSC8JSObject11hasInstanceEPNS_9ExecStateENS_7JSValueES3_
+__ZN3JSC8JSObject11hasInstanceEPS0_PNS_9ExecStateENS_7JSValueES4_
 __ZN3JSC8JSObject12defineGetterEPS0_PNS_9ExecStateERKNS_10IdentifierES1_j
 __ZN3JSC8JSObject12defaultValueEPKS0_PNS_9ExecStateENS_22PreferredPrimitiveTypeE
 __ZN3JSC8JSObject12defineSetterEPS0_PNS_9ExecStateERKNS_10IdentifierES1_j
diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def
index f615847..c68ec1d 100644
--- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def
+++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def
@@ -211,7 +211,7 @@
     ?globalExec@JSGlobalObject@JSC@@QAEPAVExecState@2@XZ
     ?globalObjectCount@Heap@JSC@@QAEIXZ
     ?grow@HandleHeap@JSC@@AAEXXZ
-    ?hasInstance@JSObject@JSC@@UAE_NPAVExecState@2@VJSValue@2@1@Z
+    ?hasInstance@JSObject@JSC@@SA_NPAV12@PAVExecState@2@VJSValue@2@2@Z
     ?hasProperty@JSObject@JSC@@QBE_NPAVExecState@2@ABVIdentifier@2@@Z
     ?hasProperty@JSObject@JSC@@QBE_NPAVExecState@2@I@Z
     ?heap@Heap@JSC@@SAPAV12@VJSValue@2@@Z
diff --git a/Source/JavaScriptCore/interpreter/Interpreter.cpp b/Source/JavaScriptCore/interpreter/Interpreter.cpp
index 4962384..9bd97a5 100644
--- a/Source/JavaScriptCore/interpreter/Interpreter.cpp
+++ b/Source/JavaScriptCore/interpreter/Interpreter.cpp
@@ -2354,7 +2354,7 @@
 
         ASSERT(!isInvalidParamForInstanceOf(callFrame, baseVal, exceptionValue));
 
-        bool result = asObject(baseVal)->hasInstance(callFrame, callFrame->r(value).jsValue(), callFrame->r(baseProto).jsValue());
+        bool result = asObject(baseVal)->methodTable()->hasInstance(asObject(baseVal), callFrame, callFrame->r(value).jsValue(), callFrame->r(baseProto).jsValue());
         CHECK_FOR_EXCEPTION();
         callFrame->uncheckedR(dst) = jsBoolean(result);
 
diff --git a/Source/JavaScriptCore/jit/JITStubs.cpp b/Source/JavaScriptCore/jit/JITStubs.cpp
index 1b02541..beb051c 100644
--- a/Source/JavaScriptCore/jit/JITStubs.cpp
+++ b/Source/JavaScriptCore/jit/JITStubs.cpp
@@ -2092,7 +2092,7 @@
     if (!typeInfo.overridesHasInstance() && !value.isObject())
         return JSValue::encode(jsBoolean(false));
 
-    JSValue result = jsBoolean(asObject(baseVal)->hasInstance(callFrame, value, proto));
+    JSValue result = jsBoolean(asObject(baseVal)->methodTable()->hasInstance(asObject(baseVal), callFrame, value, proto));
     CHECK_FOR_EXCEPTION_AT_END();
 
     return JSValue::encode(result);
diff --git a/Source/JavaScriptCore/runtime/ClassInfo.h b/Source/JavaScriptCore/runtime/ClassInfo.h
index 1bd4b1f..e4e202d 100644
--- a/Source/JavaScriptCore/runtime/ClassInfo.h
+++ b/Source/JavaScriptCore/runtime/ClassInfo.h
@@ -80,6 +80,9 @@
 
         typedef UString (*ClassNameFunctionPtr)(const JSObject*);
         ClassNameFunctionPtr className;
+
+        typedef bool (*HasInstanceFunctionPtr)(JSObject*, ExecState*, JSValue, JSValue);
+        HasInstanceFunctionPtr hasInstance;
     };
 
 #define CREATE_MEMBER_CHECKER(member) \
@@ -118,6 +121,7 @@
         &ClassName::getOwnPropertyNames, \
         &ClassName::getPropertyNames, \
         &ClassName::className, \
+        &ClassName::hasInstance, \
     }, \
     sizeof(ClassName)
 
diff --git a/Source/JavaScriptCore/runtime/JSBoundFunction.cpp b/Source/JavaScriptCore/runtime/JSBoundFunction.cpp
index fc237ff..845a9f3 100644
--- a/Source/JavaScriptCore/runtime/JSBoundFunction.cpp
+++ b/Source/JavaScriptCore/runtime/JSBoundFunction.cpp
@@ -87,13 +87,14 @@
     return function;
 }
 
-bool JSBoundFunction::hasInstance(ExecState* exec, JSValue value, JSValue)
+bool JSBoundFunction::hasInstance(JSObject* object, ExecState* exec, JSValue value, JSValue)
 {
+    JSBoundFunction* thisObject = static_cast<JSBoundFunction*>(object);
     // FIXME: our instanceof implementation will have already (incorrectly) performed
     // a [[Get]] of .prototype from the bound function object, which is incorrect!
     // https://bugs.webkit.org/show_bug.cgi?id=68656
-    JSValue proto = m_targetFunction->get(exec, exec->propertyNames().prototype);
-    return m_targetFunction->hasInstance(exec, value, proto);
+    JSValue proto = thisObject->m_targetFunction->get(exec, exec->propertyNames().prototype);
+    return thisObject->m_targetFunction->methodTable()->hasInstance(thisObject->m_targetFunction.get(), exec, value, proto);
 }
 
 JSBoundFunction::JSBoundFunction(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, JSObject* targetFunction, JSValue boundThis, JSValue boundArgs)
diff --git a/Source/JavaScriptCore/runtime/JSBoundFunction.h b/Source/JavaScriptCore/runtime/JSBoundFunction.h
index df84f71..c60d7db 100644
--- a/Source/JavaScriptCore/runtime/JSBoundFunction.h
+++ b/Source/JavaScriptCore/runtime/JSBoundFunction.h
@@ -39,7 +39,7 @@
 
     static JSBoundFunction* create(ExecState*, JSGlobalObject*, JSObject* targetFunction, JSValue boundThis, JSValue boundArgs, int, const Identifier&);
 
-    virtual bool hasInstance(ExecState*, JSValue value, JSValue proto);
+    static bool hasInstance(JSObject*, ExecState*, JSValue, JSValue proto);
 
     JSObject* targetFunction() { return m_targetFunction.get(); }
     JSValue boundThis() { return m_boundThis.get(); }
diff --git a/Source/JavaScriptCore/runtime/JSCell.cpp b/Source/JavaScriptCore/runtime/JSCell.cpp
index f1e6c10..931e3da 100644
--- a/Source/JavaScriptCore/runtime/JSCell.cpp
+++ b/Source/JavaScriptCore/runtime/JSCell.cpp
@@ -190,4 +190,10 @@
     ASSERT_NOT_REACHED();
 }
 
+bool JSCell::hasInstance(JSObject*, ExecState*, JSValue, JSValue)
+{
+    ASSERT_NOT_REACHED();
+    return false;
+}
+
 } // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/JSCell.h b/Source/JavaScriptCore/runtime/JSCell.h
index bc1d5ea..974ad59 100644
--- a/Source/JavaScriptCore/runtime/JSCell.h
+++ b/Source/JavaScriptCore/runtime/JSCell.h
@@ -146,6 +146,7 @@
         static NO_RETURN_DUE_TO_ASSERT void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
         static NO_RETURN_DUE_TO_ASSERT void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
         static UString className(const JSObject*);
+        static bool hasInstance(JSObject*, ExecState*, JSValue, JSValue prototypeProperty);
 
     private:
         WriteBarrier<Structure> m_structure;
diff --git a/Source/JavaScriptCore/runtime/JSObject.cpp b/Source/JavaScriptCore/runtime/JSObject.cpp
index e7cad88..6e020b0 100644
--- a/Source/JavaScriptCore/runtime/JSObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSObject.cpp
@@ -456,7 +456,7 @@
     return descriptor.setter();
 }
 
-bool JSObject::hasInstance(ExecState* exec, JSValue value, JSValue proto)
+bool JSObject::hasInstance(JSObject*, ExecState* exec, JSValue value, JSValue proto)
 {
     if (!value.isObject())
         return false;
diff --git a/Source/JavaScriptCore/runtime/JSObject.h b/Source/JavaScriptCore/runtime/JSObject.h
index 3e896e6..e8e508f 100644
--- a/Source/JavaScriptCore/runtime/JSObject.h
+++ b/Source/JavaScriptCore/runtime/JSObject.h
@@ -124,7 +124,7 @@
 
         static JSValue defaultValue(const JSObject*, ExecState*, PreferredPrimitiveType);
 
-        virtual bool hasInstance(ExecState*, JSValue, JSValue prototypeProperty);
+        static bool hasInstance(JSObject*, ExecState*, JSValue, JSValue prototypeProperty);
 
         static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
         static void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);