From ca52b4eeb67cf2d7fb68eccd1a89d4a343770047 Mon Sep 17 00:00:00 2001 From: "mjs@apple.com" Date: Tue, 23 Sep 2008 07:46:55 +0000 Subject: [PATCH] JavaScriptCore: 2008-09-23 Maciej Stachowiak 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 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 | 2 +- JavaScriptCore/ChangeLog | 31 +++++++++++++++ JavaScriptCore/VM/Machine.cpp | 48 ++++++++++++++++++++++-- JavaScriptCore/kjs/JSImmediate.h | 5 +++ JavaScriptCore/kjs/TypeInfo.h | 7 +++- WebCore/ChangeLog | 14 +++++++ WebCore/bindings/js/JSQuarantinedObjectWrapper.h | 2 +- 7 files changed, 102 insertions(+), 7 deletions(-) diff --git a/JavaScriptCore/API/JSCallbackObject.h b/JavaScriptCore/API/JSCallbackObject.h index bc035f80..7f52c5f 100644 --- a/JavaScriptCore/API/JSCallbackObject.h +++ b/JavaScriptCore/API/JSCallbackObject.h @@ -50,7 +50,7 @@ public: static PassRefPtr createStructureID(JSValue* proto) { - return StructureID::create(proto, TypeInfo(ObjectType, ImplementsHasInstance)); + return StructureID::create(proto, TypeInfo(ObjectType, ImplementsHasInstance | OverridesHasInstance)); } private: diff --git a/JavaScriptCore/ChangeLog b/JavaScriptCore/ChangeLog index a47c254..542deca 100644 --- a/JavaScriptCore/ChangeLog +++ b/JavaScriptCore/ChangeLog @@ -1,3 +1,34 @@ +2008-09-23 Maciej Stachowiak + + 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 Reviewed by Sam Weinig. diff --git a/JavaScriptCore/VM/Machine.cpp b/JavaScriptCore/VM/Machine.cpp index 4f43f43..7662fdd 100644 --- a/JavaScriptCore/VM/Machine.cpp +++ b/JavaScriptCore/VM/Machine.cpp @@ -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(value); + JSCell* baseCell = static_cast(baseVal); + JSCell* protoCell = static_cast(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(static_cast(valueCell)->prototype()); + + if (testPrototype == proto) + return jsBoolean(true); + + while (testPrototype != jsNull()) { + testPrototype = static_cast(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(baseVal); - JSValue* basePrototype = ARG_src3; - JSValue* result = jsBoolean(baseObj->structureID()->typeInfo().implementsHasInstance() ? baseObj->hasInstance(exec, ARG_src1, basePrototype) : false); + baseCell = static_cast(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(baseCell)->hasInstance(exec, value, proto)); VM_CHECK_EXCEPTION_AT_END(); + return result; } diff --git a/JavaScriptCore/kjs/JSImmediate.h b/JavaScriptCore/kjs/JSImmediate.h index aabf2a0..23201d8 100644 --- a/JavaScriptCore/kjs/JSImmediate.h +++ b/JavaScriptCore/kjs/JSImmediate.h @@ -154,6 +154,11 @@ namespace JSC { return (reinterpret_cast(v1) | reinterpret_cast(v2)) & TagMask; } + static ALWAYS_INLINE bool isAnyImmediate(const JSValue* v1, const JSValue* v2, JSValue* v3) + { + return (reinterpret_cast(v1) | reinterpret_cast(v2) | reinterpret_cast(v3)) & TagMask; + } + static ALWAYS_INLINE bool areBothImmediate(const JSValue* v1, const JSValue* v2) { return isImmediate(v1) & isImmediate(v2); diff --git a/JavaScriptCore/kjs/TypeInfo.h b/JavaScriptCore/kjs/TypeInfo.h index 319daa0..ac86d9d 100644 --- a/JavaScriptCore/kjs/TypeInfo.h +++ b/JavaScriptCore/kjs/TypeInfo.h @@ -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; diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog index d099ebc..0be3e39 100644 --- a/WebCore/ChangeLog +++ b/WebCore/ChangeLog @@ -1,3 +1,17 @@ +2008-09-23 Maciej Stachowiak + + 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 Reviewed by Oliver Hunt. diff --git a/WebCore/bindings/js/JSQuarantinedObjectWrapper.h b/WebCore/bindings/js/JSQuarantinedObjectWrapper.h index c76ca0d..82ae489 100644 --- a/WebCore/bindings/js/JSQuarantinedObjectWrapper.h +++ b/WebCore/bindings/js/JSQuarantinedObjectWrapper.h @@ -46,7 +46,7 @@ namespace WebCore { static PassRefPtr 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: -- 1.8.3.1