Title: [225891] trunk
Revision
225891
Author
sbar...@apple.com
Date
2017-12-13 20:10:02 -0800 (Wed, 13 Dec 2017)

Log Message

Arrow functions need their own structure because they have different properties than sloppy functions
https://bugs.webkit.org/show_bug.cgi?id=180779
<rdar://problem/35814591>

Reviewed by Mark Lam.

JSTests:

* stress/arrow-function-needs-its-own-structure.js: Added.
(assert):
(readPrototype):
(noInline.let.f1):
(noInline):

Source/_javascript_Core:

We were using the same structure for sloppy functions and
arrow functions. This broke our IC caching machinery because
these two types of functions actually have different properties.
This patch gives them different structures.

* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileNewFunction):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileNewFunction):
* runtime/FunctionConstructor.cpp:
(JSC::constructFunctionSkippingEvalEnabledCheck):
* runtime/JSFunction.cpp:
(JSC::JSFunction::selectStructureForNewFuncExp):
(JSC::JSFunction::create):
* runtime/JSFunction.h:
* runtime/JSFunctionInlines.h:
(JSC::JSFunction::createWithInvalidatedReallocationWatchpoint):
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::init):
(JSC::JSGlobalObject::visitChildren):
* runtime/JSGlobalObject.h:
(JSC::JSGlobalObject::arrowFunctionStructure const):

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (225890 => 225891)


--- trunk/JSTests/ChangeLog	2017-12-14 03:05:39 UTC (rev 225890)
+++ trunk/JSTests/ChangeLog	2017-12-14 04:10:02 UTC (rev 225891)
@@ -1,5 +1,19 @@
 2017-12-13  Saam Barati  <sbar...@apple.com>
 
+        Arrow functions need their own structure because they have different properties than sloppy functions
+        https://bugs.webkit.org/show_bug.cgi?id=180779
+        <rdar://problem/35814591>
+
+        Reviewed by Mark Lam.
+
+        * stress/arrow-function-needs-its-own-structure.js: Added.
+        (assert):
+        (readPrototype):
+        (noInline.let.f1):
+        (noInline):
+
+2017-12-13  Saam Barati  <sbar...@apple.com>
+
         Fix how JSFunction handles "caller" and "arguments" for functions that don't have those properties
         https://bugs.webkit.org/show_bug.cgi?id=163579
         <rdar://problem/35455798>

Added: trunk/JSTests/stress/arrow-function-needs-its-own-structure.js (0 => 225891)


--- trunk/JSTests/stress/arrow-function-needs-its-own-structure.js	                        (rev 0)
+++ trunk/JSTests/stress/arrow-function-needs-its-own-structure.js	2017-12-14 04:10:02 UTC (rev 225891)
@@ -0,0 +1,23 @@
+function assert(b) {
+    if (!b)
+        throw new Error;
+}
+
+function readPrototype(f) {
+    return f.prototype;
+}
+noInline(readPrototype);
+
+{
+    let f1 = function () { };
+    let f2 = () => undefined;
+    for (let i = 0; i < 100; ++i) {
+        assert(!f2.hasOwnProperty("prototype"));
+        assert(f1.hasOwnProperty("prototype"));
+    }
+
+    for (let i = 0; i < 100; ++i)
+        assert(readPrototype(f2) === undefined);
+    assert(readPrototype(f1) !== undefined);
+    assert(readPrototype(f1) === f1.prototype);
+}

Modified: trunk/Source/_javascript_Core/ChangeLog (225890 => 225891)


--- trunk/Source/_javascript_Core/ChangeLog	2017-12-14 03:05:39 UTC (rev 225890)
+++ trunk/Source/_javascript_Core/ChangeLog	2017-12-14 04:10:02 UTC (rev 225891)
@@ -1,3 +1,36 @@
+2017-12-13  Saam Barati  <sbar...@apple.com>
+
+        Arrow functions need their own structure because they have different properties than sloppy functions
+        https://bugs.webkit.org/show_bug.cgi?id=180779
+        <rdar://problem/35814591>
+
+        Reviewed by Mark Lam.
+
+        We were using the same structure for sloppy functions and
+        arrow functions. This broke our IC caching machinery because
+        these two types of functions actually have different properties.
+        This patch gives them different structures.
+
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileNewFunction):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileNewFunction):
+        * runtime/FunctionConstructor.cpp:
+        (JSC::constructFunctionSkippingEvalEnabledCheck):
+        * runtime/JSFunction.cpp:
+        (JSC::JSFunction::selectStructureForNewFuncExp):
+        (JSC::JSFunction::create):
+        * runtime/JSFunction.h:
+        * runtime/JSFunctionInlines.h:
+        (JSC::JSFunction::createWithInvalidatedReallocationWatchpoint):
+        * runtime/JSGlobalObject.cpp:
+        (JSC::JSGlobalObject::init):
+        (JSC::JSGlobalObject::visitChildren):
+        * runtime/JSGlobalObject.h:
+        (JSC::JSGlobalObject::arrowFunctionStructure const):
+
 2017-12-12  Filip Pizlo  <fpi...@apple.com>
 
         InferredValue should use IsoSubspace

Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (225890 => 225891)


--- trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2017-12-14 03:05:39 UTC (rev 225890)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2017-12-14 04:10:02 UTC (rev 225891)
@@ -2298,15 +2298,12 @@
             m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->asyncFunctionStructure());
         break;
 
-    case NewFunction:
-        if (node->castOperand<FunctionExecutable*>()->isStrictMode()) {
-            forNode(node).set(
-                m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->strictFunctionStructure());
-        } else {
-            forNode(node).set(
-                m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->sloppyFunctionStructure());
-        }
+    case NewFunction: {
+        JSGlobalObject* globalObject = m_codeBlock->globalObjectFor(node->origin.semantic);
+        Structure* structure = JSFunction::selectStructureForNewFuncExp(globalObject, node->castOperand<FunctionExecutable*>());
+        forNode(node).set(m_graph, structure);
         break;
+    }
         
     case GetCallee:
         if (FunctionExecutable* executable = jsDynamicCast<FunctionExecutable*>(m_vm, m_codeBlock->ownerExecutable())) {

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (225890 => 225891)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2017-12-14 03:05:39 UTC (rev 225890)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2017-12-14 04:10:02 UTC (rev 225891)
@@ -6782,17 +6782,16 @@
 
     RegisteredStructure structure = m_jit.graph().registerStructure(
         [&] () {
+            JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic);
             switch (nodeType) {
             case NewGeneratorFunction:
-                return m_jit.graph().globalObjectFor(node->origin.semantic)->generatorFunctionStructure();
+                return globalObject->generatorFunctionStructure();
             case NewAsyncFunction:
-                return m_jit.graph().globalObjectFor(node->origin.semantic)->asyncFunctionStructure();
+                return globalObject->asyncFunctionStructure();
             case NewAsyncGeneratorFunction:
-                return m_jit.graph().globalObjectFor(node->origin.semantic)->asyncGeneratorFunctionStructure();
+                return globalObject->asyncGeneratorFunctionStructure();
             case NewFunction:
-                if (node->castOperand<FunctionExecutable*>()->isStrictMode())
-                    return m_jit.graph().globalObjectFor(node->origin.semantic)->strictFunctionStructure();
-                return m_jit.graph().globalObjectFor(node->origin.semantic)->sloppyFunctionStructure();
+                return JSFunction::selectStructureForNewFuncExp(globalObject, node->castOperand<FunctionExecutable*>());
             default:
                 RELEASE_ASSERT_NOT_REACHED();
             }

Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (225890 => 225891)


--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2017-12-14 03:05:39 UTC (rev 225890)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2017-12-14 04:10:02 UTC (rev 225891)
@@ -4736,22 +4736,19 @@
             setJSValue(callResult);
             return;
         }
-        
 
         RegisteredStructure structure = m_graph.registerStructure(
             [&] () {
+                JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
                 switch (m_node->op()) {
                 case NewGeneratorFunction:
-                    return m_graph.globalObjectFor(m_node->origin.semantic)->generatorFunctionStructure();
+                    return globalObject->generatorFunctionStructure();
                 case NewAsyncFunction:
-                    return m_graph.globalObjectFor(m_node->origin.semantic)->asyncFunctionStructure();
+                    return globalObject->asyncFunctionStructure();
                 case NewAsyncGeneratorFunction:
-                    return m_graph.globalObjectFor(m_node->origin.semantic)->asyncGeneratorFunctionStructure();
+                    return globalObject->asyncGeneratorFunctionStructure();
                 case NewFunction:
-                    if (m_node->castOperand<FunctionExecutable*>()->isStrictMode())
-                        return m_graph.globalObjectFor(m_node->origin.semantic)->strictFunctionStructure();
-                    return m_graph.globalObjectFor(m_node->origin.semantic)->sloppyFunctionStructure();
-                    break;
+                    return JSFunction::selectStructureForNewFuncExp(globalObject, m_node->castOperand<FunctionExecutable*>());
                 default:
                     RELEASE_ASSERT_NOT_REACHED();
                 }

Modified: trunk/Source/_javascript_Core/runtime/FunctionConstructor.cpp (225890 => 225891)


--- trunk/Source/_javascript_Core/runtime/FunctionConstructor.cpp	2017-12-14 03:05:39 UTC (rev 225890)
+++ trunk/Source/_javascript_Core/runtime/FunctionConstructor.cpp	2017-12-14 04:10:02 UTC (rev 225891)
@@ -175,10 +175,7 @@
     Structure* structure = nullptr;
     switch (functionConstructionMode) {
     case FunctionConstructionMode::Function:
-        if (function->isStrictMode())
-            structure = globalObject->strictFunctionStructure();
-        else
-            structure = globalObject->sloppyFunctionStructure();
+        structure = JSFunction::selectStructureForNewFuncExp(globalObject, function);
         break;
     case FunctionConstructionMode::Generator:
         structure = globalObject->generatorFunctionStructure();

Modified: trunk/Source/_javascript_Core/runtime/JSFunction.cpp (225890 => 225891)


--- trunk/Source/_javascript_Core/runtime/JSFunction.cpp	2017-12-14 03:05:39 UTC (rev 225890)
+++ trunk/Source/_javascript_Core/runtime/JSFunction.cpp	2017-12-14 04:10:02 UTC (rev 225891)
@@ -65,10 +65,18 @@
     return isHostFunction();
 }
 
+Structure* JSFunction::selectStructureForNewFuncExp(JSGlobalObject* globalObject, FunctionExecutable* executable)
+{
+    if (executable->isArrowFunction())
+        return globalObject->arrowFunctionStructure();
+    if (executable->isStrictMode())
+        return globalObject->strictFunctionStructure();
+    return globalObject->sloppyFunctionStructure();
+}
+
 JSFunction* JSFunction::create(VM& vm, FunctionExecutable* executable, JSScope* scope)
 {
-    Structure* structure = executable->isStrictMode() ? scope->globalObject(vm)->strictFunctionStructure() : scope->globalObject(vm)->sloppyFunctionStructure();
-    return create(vm, executable, scope, structure);
+    return create(vm, executable, scope, selectStructureForNewFuncExp(scope->globalObject(vm), executable));
 }
 
 JSFunction* JSFunction::create(VM& vm, FunctionExecutable* executable, JSScope* scope, Structure* structure)

Modified: trunk/Source/_javascript_Core/runtime/JSFunction.h (225890 => 225891)


--- trunk/Source/_javascript_Core/runtime/JSFunction.h	2017-12-14 03:05:39 UTC (rev 225890)
+++ trunk/Source/_javascript_Core/runtime/JSFunction.h	2017-12-14 04:10:02 UTC (rev 225891)
@@ -70,6 +70,8 @@
         return sizeof(JSFunction);
     }
 
+    static Structure* selectStructureForNewFuncExp(JSGlobalObject*, FunctionExecutable*);
+
     JS_EXPORT_PRIVATE static JSFunction* create(VM&, JSGlobalObject*, int length, const String& name, NativeFunction, Intrinsic = NoIntrinsic, NativeFunction nativeConstructor = callHostFunctionAsConstructor, const DOMJIT::Signature* = nullptr);
     
     static JSFunction* createWithInvalidatedReallocationWatchpoint(VM&, FunctionExecutable*, JSScope*);

Modified: trunk/Source/_javascript_Core/runtime/JSFunctionInlines.h (225890 => 225891)


--- trunk/Source/_javascript_Core/runtime/JSFunctionInlines.h	2017-12-14 03:05:39 UTC (rev 225890)
+++ trunk/Source/_javascript_Core/runtime/JSFunctionInlines.h	2017-12-14 04:10:02 UTC (rev 225891)
@@ -35,8 +35,7 @@
     VM& vm, FunctionExecutable* executable, JSScope* scope)
 {
     ASSERT(executable->singletonFunction()->hasBeenInvalidated());
-    Structure* structure = executable->isStrictMode() ? scope->globalObject(vm)->strictFunctionStructure() : scope->globalObject(vm)->sloppyFunctionStructure();
-    return createImpl(vm, executable, scope, structure);
+    return createImpl(vm, executable, scope, selectStructureForNewFuncExp(scope->globalObject(vm), executable));
 }
 
 inline JSFunction::JSFunction(VM& vm, FunctionExecutable* executable, JSScope* scope, Structure* structure)

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp (225890 => 225891)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2017-12-14 03:05:39 UTC (rev 225890)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2017-12-14 04:10:02 UTC (rev 225891)
@@ -388,6 +388,7 @@
 
     m_strictFunctionStructure.set(vm, this, JSFunction::createStructure(vm, this, m_functionPrototype.get()));
     m_sloppyFunctionStructure.set(vm, this, JSFunction::createStructure(vm, this, m_functionPrototype.get()));
+    m_arrowFunctionStructure.set(vm, this, JSFunction::createStructure(vm, this, m_functionPrototype.get()));
     m_customGetterSetterFunctionStructure.initLater(
         [] (const Initializer<Structure>& init) {
             init.set(JSCustomGetterSetterFunction::createStructure(init.vm, init.owner, init.owner->m_functionPrototype.get()));
@@ -1314,6 +1315,7 @@
     visitor.append(thisObject->m_calleeStructure);
     visitor.append(thisObject->m_strictFunctionStructure);
     visitor.append(thisObject->m_sloppyFunctionStructure);
+    visitor.append(thisObject->m_arrowFunctionStructure);
     thisObject->m_customGetterSetterFunctionStructure.visit(visitor);
     thisObject->m_boundFunctionStructure.visit(visitor);
     visitor.append(thisObject->m_getterSetterStructure);

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.h (225890 => 225891)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.h	2017-12-14 03:05:39 UTC (rev 225890)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.h	2017-12-14 04:10:02 UTC (rev 225891)
@@ -322,6 +322,7 @@
     LazyProperty<JSGlobalObject, Structure> m_nullPrototypeObjectStructure;
     WriteBarrier<Structure> m_calleeStructure;
     WriteBarrier<Structure> m_strictFunctionStructure;
+    WriteBarrier<Structure> m_arrowFunctionStructure;
     WriteBarrier<Structure> m_sloppyFunctionStructure;
     LazyProperty<JSGlobalObject, Structure> m_boundFunctionStructure;
     LazyProperty<JSGlobalObject, Structure> m_customGetterSetterFunctionStructure;
@@ -631,6 +632,7 @@
     Structure* calleeStructure() const { return m_calleeStructure.get(); }
     Structure* strictFunctionStructure() const { return m_strictFunctionStructure.get(); }
     Structure* sloppyFunctionStructure() const { return m_sloppyFunctionStructure.get(); }
+    Structure* arrowFunctionStructure() const { return m_arrowFunctionStructure.get(); }
     Structure* boundFunctionStructure() const { return m_boundFunctionStructure.get(this); }
     Structure* customGetterSetterFunctionStructure() const { return m_customGetterSetterFunctionStructure.get(this); }
     Structure* getterSetterStructure() const { return m_getterSetterStructure.get(); }
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to