Diff
Modified: trunk/JSTests/ChangeLog (233425 => 233426)
--- trunk/JSTests/ChangeLog 2018-07-02 17:29:03 UTC (rev 233425)
+++ trunk/JSTests/ChangeLog 2018-07-02 17:51:21 UTC (rev 233426)
@@ -1,3 +1,13 @@
+2018-06-30 Mark Lam <[email protected]>
+
+ Builtins and host functions should get their own structures.
+ https://bugs.webkit.org/show_bug.cgi?id=187211
+ <rdar://problem/41646336>
+
+ Reviewed by Saam Barati.
+
+ * stress/regress-187211.js: Added.
+
2018-06-29 Saam Barati <[email protected]>
We shouldn't recurse into the parser when gathering metadata about various function offsets
Added: trunk/JSTests/stress/regress-187211.js (0 => 233426)
--- trunk/JSTests/stress/regress-187211.js (rev 0)
+++ trunk/JSTests/stress/regress-187211.js 2018-07-02 17:51:21 UTC (rev 233426)
@@ -0,0 +1,80 @@
+function assert(successCondition) {
+ if (!successCondition) {
+ $vm.print("FAILED at:");
+ $vm.dumpStack();
+ throw "FAIL";
+ }
+}
+
+function testNonStrict() {
+ let foo = function () { }
+ let bar = function () { }
+ let arrow = () => { }
+ let arrow2 = () => { }
+ let native = $vm.dataLog;
+ let native2 = $vm.print;
+
+ // This test relies on invoking hasOwnProperty on a builtin first before invoking
+ // it on a regular function. So, the following order is important here.
+ assert(isNaN.hasOwnProperty("prototype") == false);
+ assert(foo.hasOwnProperty("prototype") == true);
+ assert(arrow.hasOwnProperty("prototype") == false);
+ assert(native.hasOwnProperty("prototype") == false);
+
+ assert(isFinite.hasOwnProperty("prototype") == false);
+ assert(bar.hasOwnProperty("prototype") == true);
+ assert(arrow2.hasOwnProperty("prototype") == false);
+ assert(native2.hasOwnProperty("prototype") == false);
+
+ // Repeat to exercise HasOwnPropertyCache.
+ assert(isNaN.hasOwnProperty("prototype") == false);
+ assert(foo.hasOwnProperty("prototype") == true);
+ assert(arrow.hasOwnProperty("prototype") == false);
+ assert(native.hasOwnProperty("prototype") == false);
+
+ assert(isFinite.hasOwnProperty("prototype") == false);
+ assert(bar.hasOwnProperty("prototype") == true);
+ assert(arrow2.hasOwnProperty("prototype") == false);
+ assert(native2.hasOwnProperty("prototype") == false);
+}
+noInline(testNonStrict);
+
+function testStrict() {
+ "use strict";
+
+ let foo = function () { }
+ let bar = function () { }
+ let arrow = () => { }
+ let arrow2 = () => { }
+ let native = $vm.dataLog;
+ let native2 = $vm.print;
+
+ // This test relies on invoking hasOwnProperty on a builtin first before invoking
+ // it on a regular function. So, the following order is important here.
+ assert(isNaN.hasOwnProperty("prototype") == false);
+ assert(foo.hasOwnProperty("prototype") == true);
+ assert(arrow.hasOwnProperty("prototype") == false);
+ assert(native.hasOwnProperty("prototype") == false);
+
+ assert(isFinite.hasOwnProperty("prototype") == false);
+ assert(bar.hasOwnProperty("prototype") == true);
+ assert(arrow2.hasOwnProperty("prototype") == false);
+ assert(native2.hasOwnProperty("prototype") == false);
+
+ // Repeat to exercise HasOwnPropertyCache.
+ assert(isNaN.hasOwnProperty("prototype") == false);
+ assert(foo.hasOwnProperty("prototype") == true);
+ assert(arrow.hasOwnProperty("prototype") == false);
+ assert(native.hasOwnProperty("prototype") == false);
+
+ assert(isFinite.hasOwnProperty("prototype") == false);
+ assert(bar.hasOwnProperty("prototype") == true);
+ assert(arrow2.hasOwnProperty("prototype") == false);
+ assert(native2.hasOwnProperty("prototype") == false);
+}
+noInline(testStrict);
+
+for (var i = 0; i < 10000; ++i) {
+ testNonStrict();
+ testStrict();
+}
Modified: trunk/Source/_javascript_Core/ChangeLog (233425 => 233426)
--- trunk/Source/_javascript_Core/ChangeLog 2018-07-02 17:29:03 UTC (rev 233425)
+++ trunk/Source/_javascript_Core/ChangeLog 2018-07-02 17:51:21 UTC (rev 233426)
@@ -1,3 +1,28 @@
+2018-07-01 Mark Lam <[email protected]>
+
+ Builtins and host functions should get their own structures.
+ https://bugs.webkit.org/show_bug.cgi?id=187211
+ <rdar://problem/41646336>
+
+ Reviewed by Saam Barati.
+
+ JSFunctions do lazy reification of properties, but ordinary functions applies
+ different rules of property reification than builtin and host functions. Hence,
+ we should give builtins and host functions their own structures.
+
+ * runtime/JSFunction.cpp:
+ (JSC::JSFunction::selectStructureForNewFuncExp):
+ (JSC::JSFunction::create):
+ (JSC::JSFunction::getOwnPropertySlot):
+ * runtime/JSGlobalObject.cpp:
+ (JSC::JSGlobalObject::init):
+ (JSC::JSGlobalObject::visitChildren):
+ * runtime/JSGlobalObject.h:
+ (JSC::JSGlobalObject::hostFunctionStructure const):
+ (JSC::JSGlobalObject::arrowFunctionStructure const):
+ (JSC::JSGlobalObject::sloppyFunctionStructure const):
+ (JSC::JSGlobalObject::strictFunctionStructure const):
+
2018-07-01 David Kilzer <[email protected]>
_javascript_Core: Fix clang static analyzer warnings: Assigned value is garbage or undefined
Modified: trunk/Source/_javascript_Core/runtime/JSFunction.cpp (233425 => 233426)
--- trunk/Source/_javascript_Core/runtime/JSFunction.cpp 2018-07-02 17:29:03 UTC (rev 233425)
+++ trunk/Source/_javascript_Core/runtime/JSFunction.cpp 2018-07-02 17:51:21 UTC (rev 233426)
@@ -1,7 +1,7 @@
/*
* Copyright (C) 1999-2002 Harri Porten ([email protected])
* Copyright (C) 2001 Peter Kelly ([email protected])
- * Copyright (C) 2003-2009, 2015-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2003-2018 Apple Inc. All rights reserved.
* Copyright (C) 2007 Cameron Zwarich ([email protected])
* Copyright (C) 2007 Maks Orlovich
* Copyright (C) 2015 Canon Inc. All rights reserved.
@@ -67,11 +67,13 @@
Structure* JSFunction::selectStructureForNewFuncExp(JSGlobalObject* globalObject, FunctionExecutable* executable)
{
+ ASSERT(!executable->isHostFunction());
+ bool isBuiltin = executable->isBuiltinFunction();
if (executable->isArrowFunction())
- return globalObject->arrowFunctionStructure();
+ return globalObject->arrowFunctionStructure(isBuiltin);
if (executable->isStrictMode())
- return globalObject->strictFunctionStructure();
- return globalObject->sloppyFunctionStructure();
+ return globalObject->strictFunctionStructure(isBuiltin);
+ return globalObject->sloppyFunctionStructure(isBuiltin);
}
JSFunction* JSFunction::create(VM& vm, FunctionExecutable* executable, JSScope* scope)
@@ -89,7 +91,7 @@
JSFunction* JSFunction::create(VM& vm, JSGlobalObject* globalObject, int length, const String& name, NativeFunction nativeFunction, Intrinsic intrinsic, NativeFunction nativeConstructor, const DOMJIT::Signature* signature)
{
NativeExecutable* executable = vm.getHostFunction(nativeFunction, intrinsic, nativeConstructor, signature, name);
- Structure* structure = globalObject->strictFunctionStructure();
+ Structure* structure = globalObject->hostFunctionStructure();
JSFunction* function = new (NotNull, allocateCell<JSFunction>(vm.heap)) JSFunction(vm, globalObject, structure);
// Can't do this during initialization because getHostFunction might do a GC allocation.
function->finishCreation(vm, executable, length, name);
@@ -436,9 +438,8 @@
slot.setCacheableCustom(thisObject, PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum | PropertyAttribute::DontDelete, argumentsGetter);
return true;
- }
- if (propertyName == vm.propertyNames->caller) {
+ } else if (propertyName == vm.propertyNames->caller) {
if (!thisObject->jsExecutable()->hasCallerAndArgumentsProperties())
return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp (233425 => 233426)
--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp 2018-07-02 17:29:03 UTC (rev 233425)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp 2018-07-02 17:51:21 UTC (rev 233426)
@@ -416,9 +416,16 @@
ExecState::initGlobalExec(JSGlobalObject::globalExec(), globalCallee);
ExecState* exec = JSGlobalObject::globalExec();
- 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_hostFunctionStructure.set(vm, this, JSFunction::createStructure(vm, this, m_functionPrototype.get()));
+
+ auto initFunctionStructures = [&] (FunctionStructures& structures) {
+ structures.strictFunctionStructure.set(vm, this, JSFunction::createStructure(vm, this, m_functionPrototype.get()));
+ structures.sloppyFunctionStructure.set(vm, this, JSFunction::createStructure(vm, this, m_functionPrototype.get()));
+ structures.arrowFunctionStructure.set(vm, this, JSFunction::createStructure(vm, this, m_functionPrototype.get()));
+ };
+ initFunctionStructures(m_builtinFunctions);
+ initFunctionStructures(m_ordinaryFunctions);
+
m_customGetterSetterFunctionStructure.initLater(
[] (const Initializer<Structure>& init) {
init.set(JSCustomGetterSetterFunction::createStructure(init.vm, init.owner, init.owner->m_functionPrototype.get()));
@@ -1394,9 +1401,16 @@
visitor.append(thisObject->m_nullPrototypeObjectStructure);
visitor.append(thisObject->m_errorStructure);
visitor.append(thisObject->m_calleeStructure);
- visitor.append(thisObject->m_strictFunctionStructure);
- visitor.append(thisObject->m_sloppyFunctionStructure);
- visitor.append(thisObject->m_arrowFunctionStructure);
+
+ visitor.append(thisObject->m_hostFunctionStructure);
+ auto visitFunctionStructures = [&] (FunctionStructures& structures) {
+ visitor.append(structures.arrowFunctionStructure);
+ visitor.append(structures.sloppyFunctionStructure);
+ visitor.append(structures.strictFunctionStructure);
+ };
+ visitFunctionStructures(thisObject->m_builtinFunctions);
+ visitFunctionStructures(thisObject->m_ordinaryFunctions);
+
thisObject->m_customGetterSetterFunctionStructure.visit(visitor);
thisObject->m_boundFunctionStructure.visit(visitor);
visitor.append(thisObject->m_getterSetterStructure);
Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.h (233425 => 233426)
--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.h 2018-07-02 17:29:03 UTC (rev 233425)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.h 2018-07-02 17:51:21 UTC (rev 233426)
@@ -341,9 +341,17 @@
#endif
WriteBarrier<Structure> m_nullPrototypeObjectStructure;
WriteBarrier<Structure> m_calleeStructure;
- WriteBarrier<Structure> m_strictFunctionStructure;
- WriteBarrier<Structure> m_arrowFunctionStructure;
- WriteBarrier<Structure> m_sloppyFunctionStructure;
+
+ WriteBarrier<Structure> m_hostFunctionStructure;
+
+ struct FunctionStructures {
+ WriteBarrier<Structure> arrowFunctionStructure;
+ WriteBarrier<Structure> sloppyFunctionStructure;
+ WriteBarrier<Structure> strictFunctionStructure;
+ };
+ FunctionStructures m_builtinFunctions;
+ FunctionStructures m_ordinaryFunctions;
+
LazyProperty<JSGlobalObject, Structure> m_boundFunctionStructure;
LazyProperty<JSGlobalObject, Structure> m_customGetterSetterFunctionStructure;
WriteBarrier<Structure> m_getterSetterStructure;
@@ -657,9 +665,27 @@
Structure* nullPrototypeObjectStructure() const { return m_nullPrototypeObjectStructure.get(); }
Structure* errorStructure() const { return m_errorStructure.get(); }
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* hostFunctionStructure() const { return m_hostFunctionStructure.get(); }
+
+ Structure* arrowFunctionStructure(bool isBuiltin) const
+ {
+ if (isBuiltin)
+ return m_builtinFunctions.arrowFunctionStructure.get();
+ return m_ordinaryFunctions.arrowFunctionStructure.get();
+ }
+ Structure* sloppyFunctionStructure(bool isBuiltin) const
+ {
+ if (isBuiltin)
+ return m_builtinFunctions.sloppyFunctionStructure.get();
+ return m_ordinaryFunctions.sloppyFunctionStructure.get();
+ }
+ Structure* strictFunctionStructure(bool isBuiltin) const
+ {
+ if (isBuiltin)
+ return m_builtinFunctions.strictFunctionStructure.get();
+ return m_ordinaryFunctions.strictFunctionStructure.get();
+ }
+
Structure* boundFunctionStructure() const { return m_boundFunctionStructure.get(this); }
Structure* customGetterSetterFunctionStructure() const { return m_customGetterSetterFunctionStructure.get(this); }
Structure* getterSetterStructure() const { return m_getterSetterStructure.get(); }