Title: [233426] trunk
Revision
233426
Author
[email protected]
Date
2018-07-02 10:51:21 -0700 (Mon, 02 Jul 2018)

Log Message

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.

JSTests:

* stress/regress-187211.js: Added.

Source/_javascript_Core:

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):

Modified Paths

Added Paths

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(); }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to