Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (199685 => 199686)
--- trunk/Source/_javascript_Core/ChangeLog 2016-04-18 20:28:51 UTC (rev 199685)
+++ trunk/Source/_javascript_Core/ChangeLog 2016-04-18 20:33:47 UTC (rev 199686)
@@ -1,5 +1,42 @@
2016-04-18 Filip Pizlo <[email protected]>
+ 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 <[email protected]>
+
Check to see how the perf bots react to megamorphic load being disabled.
Rubber stamped by Chris Dumez.
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (199685 => 199686)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2016-04-18 20:28:51 UTC (rev 199685)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2016-04-18 20:33:47 UTC (rev 199686)
@@ -3842,10 +3842,11 @@
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;
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (199685 => 199686)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2016-04-18 20:28:51 UTC (rev 199685)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2016-04-18 20:33:47 UTC (rev 199686)
@@ -3897,10 +3897,11 @@
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())
Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (199685 => 199686)
--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2016-04-18 20:28:51 UTC (rev 199685)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2016-04-18 20:33:47 UTC (rev 199686)
@@ -1461,7 +1461,11 @@
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;
Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.h (199685 => 199686)
--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.h 2016-04-18 20:28:51 UTC (rev 199685)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.h 2016-04-18 20:33:47 UTC (rev 199686)
@@ -356,7 +356,7 @@
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)
{
Modified: trunk/Source/_javascript_Core/runtime/JSLexicalEnvironment.h (199685 => 199686)
--- trunk/Source/_javascript_Core/runtime/JSLexicalEnvironment.h 2016-04-18 20:28:51 UTC (rev 199685)
+++ trunk/Source/_javascript_Core/runtime/JSLexicalEnvironment.h 2016-04-18 20:33:47 UTC (rev 199686)
@@ -44,7 +44,7 @@
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)
Modified: trunk/Source/_javascript_Core/runtime/JSString.h (199685 => 199686)
--- trunk/Source/_javascript_Core/runtime/JSString.h 2016-04-18 20:28:51 UTC (rev 199685)
+++ trunk/Source/_javascript_Core/runtime/JSString.h 2016-04-18 20:33:47 UTC (rev 199686)
@@ -82,7 +82,7 @@
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*);
Modified: trunk/Source/_javascript_Core/runtime/JSTypeInfo.h (199685 => 199686)
--- trunk/Source/_javascript_Core/runtime/JSTypeInfo.h 2016-04-18 20:28:51 UTC (rev 199685)
+++ trunk/Source/_javascript_Core/runtime/JSTypeInfo.h 2016-04-18 20:33:47 UTC (rev 199686)
@@ -42,7 +42,8 @@
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 @@
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); }
Modified: trunk/Source/_javascript_Core/runtime/StrictEvalActivation.h (199685 => 199686)
--- trunk/Source/_javascript_Core/runtime/StrictEvalActivation.h 2016-04-18 20:28:51 UTC (rev 199685)
+++ trunk/Source/_javascript_Core/runtime/StrictEvalActivation.h 2016-04-18 20:33:47 UTC (rev 199686)
@@ -33,7 +33,7 @@
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)
{
Modified: trunk/Source/_javascript_Core/runtime/Symbol.h (199685 => 199686)
--- trunk/Source/_javascript_Core/runtime/Symbol.h 2016-04-18 20:28:51 UTC (rev 199685)
+++ trunk/Source/_javascript_Core/runtime/Symbol.h 2016-04-18 20:33:47 UTC (rev 199686)
@@ -37,7 +37,7 @@
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;