ToThis should have a fast path based on type info flags
authorfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 18 Apr 2016 20:33:47 +0000 (20:33 +0000)
committerfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 18 Apr 2016 20:33:47 +0000 (20:33 +0000)
https://bugs.webkit.org/show_bug.cgi?id=156712

Reviewed by Geoffrey Garen.

Prior to this change, if we couldn't nail down the type of ToThis to something easy, we'd emit code
that would take slow path if the argument was not a final object. We'd end up taking that slow path
a lot.

This adds a type info flag for ToThis having non-obvious behavior and changes the DFG and FTL paths
to test this flag. This is a sub-1% speed-up on SunSpider and Octane.

* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileToThis):
* runtime/JSGlobalObject.h:
(JSC::JSGlobalObject::create):
* runtime/JSLexicalEnvironment.h:
(JSC::JSLexicalEnvironment::create):
* runtime/JSString.h:
* runtime/JSTypeInfo.h:
(JSC::TypeInfo::overridesGetOwnPropertySlot):
(JSC::TypeInfo::interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero):
(JSC::TypeInfo::structureIsImmortal):
(JSC::TypeInfo::overridesToThis):
(JSC::TypeInfo::overridesGetPropertyNames):
(JSC::TypeInfo::prohibitsPropertyCaching):
(JSC::TypeInfo::getOwnPropertySlotIsImpure):
* runtime/StrictEvalActivation.h:
(JSC::StrictEvalActivation::create):
* runtime/Symbol.h:

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

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
Source/JavaScriptCore/runtime/JSGlobalObject.h
Source/JavaScriptCore/runtime/JSLexicalEnvironment.h
Source/JavaScriptCore/runtime/JSString.h
Source/JavaScriptCore/runtime/JSTypeInfo.h
Source/JavaScriptCore/runtime/StrictEvalActivation.h
Source/JavaScriptCore/runtime/Symbol.h

index 5e5296f..da5470c 100644 (file)
@@ -1,5 +1,42 @@
 2016-04-18  Filip Pizlo  <fpizlo@apple.com>
 
+        ToThis should have a fast path based on type info flags
+        https://bugs.webkit.org/show_bug.cgi?id=156712
+
+        Reviewed by Geoffrey Garen.
+
+        Prior to this change, if we couldn't nail down the type of ToThis to something easy, we'd emit code
+        that would take slow path if the argument was not a final object. We'd end up taking that slow path
+        a lot.
+
+        This adds a type info flag for ToThis having non-obvious behavior and changes the DFG and FTL paths
+        to test this flag. This is a sub-1% speed-up on SunSpider and Octane.
+
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileToThis):
+        * runtime/JSGlobalObject.h:
+        (JSC::JSGlobalObject::create):
+        * runtime/JSLexicalEnvironment.h:
+        (JSC::JSLexicalEnvironment::create):
+        * runtime/JSString.h:
+        * runtime/JSTypeInfo.h:
+        (JSC::TypeInfo::overridesGetOwnPropertySlot):
+        (JSC::TypeInfo::interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero):
+        (JSC::TypeInfo::structureIsImmortal):
+        (JSC::TypeInfo::overridesToThis):
+        (JSC::TypeInfo::overridesGetPropertyNames):
+        (JSC::TypeInfo::prohibitsPropertyCaching):
+        (JSC::TypeInfo::getOwnPropertySlotIsImpure):
+        * runtime/StrictEvalActivation.h:
+        (JSC::StrictEvalActivation::create):
+        * runtime/Symbol.h:
+
+2016-04-18  Filip Pizlo  <fpizlo@apple.com>
+
         Check to see how the perf bots react to megamorphic load being disabled.
 
         Rubber stamped by Chris Dumez.
index fc2524e..dfa938a 100644 (file)
@@ -3842,10 +3842,11 @@ void SpeculativeJIT::compile(Node* node)
         
         MacroAssembler::JumpList slowCases;
         slowCases.append(m_jit.branchIfNotCell(thisValue.jsValueRegs()));
-        slowCases.append(m_jit.branch8(
-            MacroAssembler::NotEqual,
-            MacroAssembler::Address(thisValuePayloadGPR, JSCell::typeInfoTypeOffset()),
-            TrustedImm32(FinalObjectType)));
+        slowCases.append(
+            m_jit.branchTest8(                             
+                MacroAssembler::NonZero,
+                MacroAssembler::Address(thisValuePayloadGPR, JSCell::typeInfoFlagsOffset()),
+                MacroAssembler::TrustedImm32(OverridesToThis)));
         m_jit.move(thisValuePayloadGPR, tempGPR);
         m_jit.move(thisValueTagGPR, tempTagGPR);
         J_JITOperation_EJ function;
index ac2ac2b..2593d77 100644 (file)
@@ -3897,10 +3897,11 @@ void SpeculativeJIT::compile(Node* node)
         
         MacroAssembler::JumpList slowCases;
         slowCases.append(m_jit.branchIfNotCell(JSValueRegs(thisValueGPR)));
-        slowCases.append(m_jit.branch8(
-            MacroAssembler::NotEqual,
-            MacroAssembler::Address(thisValueGPR, JSCell::typeInfoTypeOffset()),
-            TrustedImm32(FinalObjectType)));
+        slowCases.append(
+            m_jit.branchTest8(                             
+                MacroAssembler::NonZero,
+                MacroAssembler::Address(thisValueGPR, JSCell::typeInfoFlagsOffset()),
+                MacroAssembler::TrustedImm32(OverridesToThis)));
         m_jit.move(thisValueGPR, tempGPR);
         J_JITOperation_EJ function;
         if (m_jit.graph().executableFor(node->origin.semantic)->isStrictMode())
index 142202a..692c628 100644 (file)
@@ -1461,7 +1461,11 @@ private:
         
         LBasicBlock lastNext = m_out.appendTo(isCellCase, slowCase);
         ValueFromBlock fastResult = m_out.anchor(value);
-        m_out.branch(isType(value, FinalObjectType), usually(continuation), rarely(slowCase));
+        m_out.branch(
+            m_out.testIsZero32(
+                m_out.load8ZeroExt32(value, m_heaps.JSCell_typeInfoFlags),
+                m_out.constInt32(OverridesToThis)),
+            usually(continuation), rarely(slowCase));
         
         m_out.appendTo(slowCase, continuation);
         J_JITOperation_EJ function;
index dcaa9ba..17f762e 100644 (file)
@@ -356,7 +356,7 @@ protected:
         
 public:
     typedef JSSegmentedVariableObject Base;
-    static const unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | OverridesGetPropertyNames;
+    static const unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | OverridesGetPropertyNames | OverridesToThis;
 
     static JSGlobalObject* create(VM& vm, Structure* structure)
     {
index 5cd4186..b198e03 100644 (file)
@@ -44,7 +44,7 @@ protected:
     
 public:
     typedef JSEnvironmentRecord Base;
-    static const unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | OverridesGetPropertyNames;
+    static const unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | OverridesGetPropertyNames | OverridesToThis;
 
     static JSLexicalEnvironment* create(
         VM& vm, Structure* structure, JSScope* currentScope, SymbolTable* symbolTable, JSValue initialValue)
index 68638de..2bdadf0 100644 (file)
@@ -82,7 +82,7 @@ public:
     friend struct ThunkHelpers;
 
     typedef JSCell Base;
-    static const unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | StructureIsImmortal;
+    static const unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | StructureIsImmortal | OverridesToThis;
 
     static const bool needsDestruction = true;
     static void destroy(JSCell*);
index 9ef49ba..2871150 100644 (file)
@@ -42,7 +42,8 @@ static const unsigned TypeOfShouldCallGetCallData = 1 << 2; // Need this flag if
 static const unsigned OverridesGetOwnPropertySlot = 1 << 3;
 static const unsigned InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero = 1 << 4;
 static const unsigned StructureIsImmortal = 1 << 5;
-// There are two free bits at the end of the InlineTypeFlags.
+static const unsigned OverridesToThis = 1 << 6; // If this is false then this returns something other than 'this'. Non-object cells that are visible to JS have this set as do some exotic objects.
+// There is one free bit at the end of the InlineTypeFlags.
 
 static const unsigned ImplementsHasInstance = 1 << 8;
 static const unsigned OverridesGetPropertyNames = 1 << 9;
@@ -84,6 +85,7 @@ public:
     static bool overridesGetOwnPropertySlot(InlineTypeFlags flags) { return flags & OverridesGetOwnPropertySlot; }
     bool interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero() const { return isSetOnFlags1(InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero); }
     bool structureIsImmortal() const { return isSetOnFlags1(StructureIsImmortal); }
+    bool overridesToThis() const { return isSetOnFlags1(OverridesToThis); }
     bool overridesGetPropertyNames() const { return isSetOnFlags2(OverridesGetPropertyNames); }
     bool prohibitsPropertyCaching() const { return isSetOnFlags2(ProhibitsPropertyCaching); }
     bool getOwnPropertySlotIsImpure() const { return isSetOnFlags2(GetOwnPropertySlotIsImpure); }
index 13157f6..45283b8 100644 (file)
@@ -33,7 +33,7 @@ namespace JSC {
 class StrictEvalActivation : public JSScope {
 public:
     typedef JSScope Base;
-    static const unsigned StructureFlags = Base::StructureFlags | IsEnvironmentRecord;
+    static const unsigned StructureFlags = Base::StructureFlags | IsEnvironmentRecord | OverridesToThis;
 
     static StrictEvalActivation* create(ExecState* exec, JSScope* currentScope)
     {
index cfdabe6..acaa702 100644 (file)
@@ -37,7 +37,7 @@ namespace JSC {
 class Symbol final : public JSCell {
 public:
     typedef JSCell Base;
-    static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
+    static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal | OverridesToThis;
 
     DECLARE_EXPORT_INFO;