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(); }