Title: [232442] trunk
Revision
232442
Author
[email protected]
Date
2018-06-02 14:08:10 -0700 (Sat, 02 Jun 2018)

Log Message

[JSC] Object.create should have intrinsic
https://bugs.webkit.org/show_bug.cgi?id=186200

Reviewed by Filip Pizlo.

JSTests:

* microbenchmarks/object-create-null.js: Added.
(test):
* microbenchmarks/object-create-unknown-object-prototype.js: Added.
(test):
* microbenchmarks/object-create-untyped-prototype.js: Added.
(test):
* stress/get-by-pname-only-prototype-properties.js: Added.
(foo):
* stress/object-create-define.js: Added.
(shouldBe):
(test):
* stress/object-create-null-external.js: Added.
(shouldBe):
(test):
* stress/object-create-null.js: Added.
(shouldBe):
(test):
* stress/object-create-prototype.js: Added.
(shouldBe):
(test):
* stress/object-create-undefined.js: Added.
(shouldThrow):
(i.shouldThrow):

Source/_javascript_Core:

Object.create is used in various JS code. `Object.create(null)` is particularly used
to create empty plain object with null [[Prototype]]. We can find `Object.create(null)`
call in ARES-6/Babylon code.

This patch adds ObjectCreateIntrinsic to JSC. DFG recognizes it and produces ObjectCreate
DFG node. DFG AI and constant folding attempt to convert it to NewObject when prototype
object is null. It offers significant performance boost for `Object.create(null)`.

                                                 baseline                  patched

object-create-null                           53.7940+-1.5297     ^     19.8846+-0.6584        ^ definitely 2.7053x faster
object-create-unknown-object-prototype       38.9977+-1.1364     ^     37.2207+-0.6143        ^ definitely 1.0477x faster
object-create-untyped-prototype              22.5632+-0.6917           22.2539+-0.6876          might be 1.0139x faster

* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::handleIntrinsicCall):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGConstantFoldingPhase.cpp:
(JSC::DFG::ConstantFoldingPhase::foldConstants):
* dfg/DFGDoesGC.cpp:
(JSC::DFG::doesGC):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGNode.h:
(JSC::DFG::Node::convertToNewObject):
* dfg/DFGNodeType.h:
* dfg/DFGOperations.cpp:
* dfg/DFGOperations.h:
* dfg/DFGPredictionPropagationPhase.cpp:
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileObjectCreate):
* dfg/DFGSpeculativeJIT.h:
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileObjectCreate):
* runtime/Intrinsic.cpp:
(JSC::intrinsicName):
* runtime/Intrinsic.h:
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::init):
(JSC::JSGlobalObject::visitChildren):
* runtime/JSGlobalObject.h:
(JSC::JSGlobalObject::nullPrototypeObjectStructure const):
* runtime/ObjectConstructor.cpp:

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (232441 => 232442)


--- trunk/JSTests/ChangeLog	2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/JSTests/ChangeLog	2018-06-02 21:08:10 UTC (rev 232442)
@@ -1,3 +1,34 @@
+2018-06-02  Yusuke Suzuki  <[email protected]>
+
+        [JSC] Object.create should have intrinsic
+        https://bugs.webkit.org/show_bug.cgi?id=186200
+
+        Reviewed by Filip Pizlo.
+
+        * microbenchmarks/object-create-null.js: Added.
+        (test):
+        * microbenchmarks/object-create-unknown-object-prototype.js: Added.
+        (test):
+        * microbenchmarks/object-create-untyped-prototype.js: Added.
+        (test):
+        * stress/get-by-pname-only-prototype-properties.js: Added.
+        (foo):
+        * stress/object-create-define.js: Added.
+        (shouldBe):
+        (test):
+        * stress/object-create-null-external.js: Added.
+        (shouldBe):
+        (test):
+        * stress/object-create-null.js: Added.
+        (shouldBe):
+        (test):
+        * stress/object-create-prototype.js: Added.
+        (shouldBe):
+        (test):
+        * stress/object-create-undefined.js: Added.
+        (shouldThrow):
+        (i.shouldThrow):
+
 2018-06-02  Caio Lima  <[email protected]>
 
         [ESNext][BigInt] Implement support for addition operations

Added: trunk/JSTests/microbenchmarks/object-create-null.js (0 => 232442)


--- trunk/JSTests/microbenchmarks/object-create-null.js	                        (rev 0)
+++ trunk/JSTests/microbenchmarks/object-create-null.js	2018-06-02 21:08:10 UTC (rev 232442)
@@ -0,0 +1,8 @@
+function test()
+{
+    return Object.create(null);
+}
+noInline(test);
+
+for (var i = 0; i < 1e6; ++i)
+    test();

Added: trunk/JSTests/microbenchmarks/object-create-unknown-object-prototype.js (0 => 232442)


--- trunk/JSTests/microbenchmarks/object-create-unknown-object-prototype.js	                        (rev 0)
+++ trunk/JSTests/microbenchmarks/object-create-unknown-object-prototype.js	2018-06-02 21:08:10 UTC (rev 232442)
@@ -0,0 +1,18 @@
+function test(prototype)
+{
+    return Object.create(prototype);
+}
+noInline(test);
+
+var prototype1 = {};
+var prototype2 = [];
+var prototype3 = new Date();
+var prototype4 = { hello: 42 };
+var prototype5 = new Map();
+for (var i = 0; i < 1e5; ++i) {
+    test(prototype1);
+    test(prototype2);
+    test(prototype3);
+    test(prototype4);
+    test(prototype5);
+}

Added: trunk/JSTests/microbenchmarks/object-create-untyped-prototype.js (0 => 232442)


--- trunk/JSTests/microbenchmarks/object-create-untyped-prototype.js	                        (rev 0)
+++ trunk/JSTests/microbenchmarks/object-create-untyped-prototype.js	2018-06-02 21:08:10 UTC (rev 232442)
@@ -0,0 +1,13 @@
+function test(prototype)
+{
+    return Object.create(prototype);
+}
+noInline(test);
+
+var prototype1 = {};
+var prototype2 = [];
+for (var i = 0; i < 1e5; ++i) {
+    test(prototype1);
+    test(prototype2);
+    test(null);
+}

Added: trunk/JSTests/stress/get-by-pname-only-prototype-properties.js (0 => 232442)


--- trunk/JSTests/stress/get-by-pname-only-prototype-properties.js	                        (rev 0)
+++ trunk/JSTests/stress/get-by-pname-only-prototype-properties.js	2018-06-02 21:08:10 UTC (rev 232442)
@@ -0,0 +1,50 @@
+var foo = function (C, A) {
+    for(var B in (A||{})) {
+        C[B]=A[B];
+    }
+    return C;
+}
+
+var protos = [];
+for (var i = 0; i < 256; i++) {
+    var proto = Object.create(null);
+    protos.push(proto);
+    proto.aa = 1;
+    proto.ab = 1;
+    proto.ac = 1;
+    proto.ad = 1;
+    proto.ae = 1;
+    proto.af = 1;
+    proto.ag = 1;
+    proto.ah = 1;
+    proto.ai = 1;
+    proto.aj = 1;
+    proto.ak = 1;
+    proto.al = 1;
+    proto.am = 1;
+    proto.an = 1;
+    proto.ao = 1;
+    proto.ap = 1;
+    proto.aq = 1;
+    proto.ar = 1;
+    proto.as = 1;
+    proto.at = 1;
+    proto.au = 1;
+    proto.av = 1;
+    proto.aw = 1;
+    proto.ax = 1;
+    proto.ay = 1;
+    proto.az = 1;
+    proto.ba = 1;
+    proto.bb = 1;
+    proto.bc = 1;
+    proto.bd = 1;
+    proto.be = 1;
+    proto.bf = 1;
+    var weirdObject = Object.create(proto);
+    var result = foo({}, weirdObject);
+    for (var p in result) {
+        if (result[p] !== result["" + p])
+            throw new Error("OUT");
+    }
+}

Added: trunk/JSTests/stress/object-create-define.js (0 => 232442)


--- trunk/JSTests/stress/object-create-define.js	                        (rev 0)
+++ trunk/JSTests/stress/object-create-define.js	2018-06-02 21:08:10 UTC (rev 232442)
@@ -0,0 +1,31 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function test(prototype, data)
+{
+    return Object.create(prototype, data);
+}
+noInline(test);
+
+for (var i = 0; i < 1e4; ++i) {
+    var prototype = { Cocoa: false };
+    var object = test(prototype, {
+        Cappuccino: {
+            value: 42,
+            enumerable: true,
+            configurable: true,
+            writable: true
+        },
+        Matcha: {
+            value: 40,
+            enumerable: false,
+            configurable: true,
+            writable: true
+        }
+    });
+    shouldBe(Object.getPrototypeOf(object), prototype);
+    shouldBe(JSON.stringify(Object.getOwnPropertyNames(object).sort()), `["Cappuccino","Matcha"]`);
+    shouldBe(JSON.stringify(Object.keys(object).sort()), `["Cappuccino"]`);
+}

Added: trunk/JSTests/stress/object-create-null-external.js (0 => 232442)


--- trunk/JSTests/stress/object-create-null-external.js	                        (rev 0)
+++ trunk/JSTests/stress/object-create-null-external.js	2018-06-02 21:08:10 UTC (rev 232442)
@@ -0,0 +1,16 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function test(prototype)
+{
+    return Object.create(prototype);
+}
+noInline(test);
+
+for (var i = 0; i < 1e4; ++i) {
+    var object = test(null);
+    shouldBe(Object.getPrototypeOf(object), null);
+    shouldBe(JSON.stringify(Object.getOwnPropertyNames(object)), `[]`);
+}

Added: trunk/JSTests/stress/object-create-null.js (0 => 232442)


--- trunk/JSTests/stress/object-create-null.js	                        (rev 0)
+++ trunk/JSTests/stress/object-create-null.js	2018-06-02 21:08:10 UTC (rev 232442)
@@ -0,0 +1,16 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function test()
+{
+    return Object.create(null);
+}
+noInline(test);
+
+for (var i = 0; i < 1e4; ++i) {
+    var object = test();
+    shouldBe(Object.getPrototypeOf(object), null);
+    shouldBe(JSON.stringify(Object.getOwnPropertyNames(object)), `[]`);
+}

Added: trunk/JSTests/stress/object-create-prototype.js (0 => 232442)


--- trunk/JSTests/stress/object-create-prototype.js	                        (rev 0)
+++ trunk/JSTests/stress/object-create-prototype.js	2018-06-02 21:08:10 UTC (rev 232442)
@@ -0,0 +1,17 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function test(prototype)
+{
+    return Object.create(prototype);
+}
+noInline(test);
+
+for (var i = 0; i < 1e4; ++i) {
+    var prototype = { Cocoa: false };
+    var object = test(prototype);
+    shouldBe(Object.getPrototypeOf(object), prototype);
+    shouldBe(JSON.stringify(Object.getOwnPropertyNames(object)), `[]`);
+}

Added: trunk/JSTests/stress/object-create-undefined.js (0 => 232442)


--- trunk/JSTests/stress/object-create-undefined.js	                        (rev 0)
+++ trunk/JSTests/stress/object-create-undefined.js	2018-06-02 21:08:10 UTC (rev 232442)
@@ -0,0 +1,26 @@
+function shouldThrow(func, errorMessage) {
+    var errorThrown = false;
+    var error = null;
+    try {
+        func();
+    } catch (e) {
+        errorThrown = true;
+        error = e;
+    }
+    if (!errorThrown)
+        throw new Error('not thrown');
+    if (String(error) !== errorMessage)
+        throw new Error(`bad error: ${String(error)}`);
+}
+
+function test(value)
+{
+    return Object.create(value);
+}
+noInline(test);
+
+for (var i = 0; i < 1e4; ++i) {
+    shouldThrow(() => {
+        test(undefined);
+    }, `TypeError: Object prototype may only be an Object or null.`);
+}

Modified: trunk/Source/_javascript_Core/ChangeLog (232441 => 232442)


--- trunk/Source/_javascript_Core/ChangeLog	2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/ChangeLog	2018-06-02 21:08:10 UTC (rev 232442)
@@ -1,3 +1,66 @@
+2018-06-02  Yusuke Suzuki  <[email protected]>
+
+        [JSC] Object.create should have intrinsic
+        https://bugs.webkit.org/show_bug.cgi?id=186200
+
+        Reviewed by Filip Pizlo.
+
+        Object.create is used in various JS code. `Object.create(null)` is particularly used
+        to create empty plain object with null [[Prototype]]. We can find `Object.create(null)`
+        call in ARES-6/Babylon code.
+
+        This patch adds ObjectCreateIntrinsic to JSC. DFG recognizes it and produces ObjectCreate
+        DFG node. DFG AI and constant folding attempt to convert it to NewObject when prototype
+        object is null. It offers significant performance boost for `Object.create(null)`.
+
+                                                         baseline                  patched
+
+        object-create-null                           53.7940+-1.5297     ^     19.8846+-0.6584        ^ definitely 2.7053x faster
+        object-create-unknown-object-prototype       38.9977+-1.1364     ^     37.2207+-0.6143        ^ definitely 1.0477x faster
+        object-create-untyped-prototype              22.5632+-0.6917           22.2539+-0.6876          might be 1.0139x faster
+
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::handleIntrinsicCall):
+        * dfg/DFGClobberize.h:
+        (JSC::DFG::clobberize):
+        * dfg/DFGConstantFoldingPhase.cpp:
+        (JSC::DFG::ConstantFoldingPhase::foldConstants):
+        * dfg/DFGDoesGC.cpp:
+        (JSC::DFG::doesGC):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        * dfg/DFGNode.h:
+        (JSC::DFG::Node::convertToNewObject):
+        * dfg/DFGNodeType.h:
+        * dfg/DFGOperations.cpp:
+        * dfg/DFGOperations.h:
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        * dfg/DFGSafeToExecute.h:
+        (JSC::DFG::safeToExecute):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileObjectCreate):
+        * dfg/DFGSpeculativeJIT.h:
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * ftl/FTLCapabilities.cpp:
+        (JSC::FTL::canCompile):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileNode):
+        (JSC::FTL::DFG::LowerDFGToB3::compileObjectCreate):
+        * runtime/Intrinsic.cpp:
+        (JSC::intrinsicName):
+        * runtime/Intrinsic.h:
+        * runtime/JSGlobalObject.cpp:
+        (JSC::JSGlobalObject::init):
+        (JSC::JSGlobalObject::visitChildren):
+        * runtime/JSGlobalObject.h:
+        (JSC::JSGlobalObject::nullPrototypeObjectStructure const):
+        * runtime/ObjectConstructor.cpp:
+
 2018-06-02  Caio Lima  <[email protected]>
 
         [ESNext][BigInt] Implement support for addition operations

Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (232441 => 232442)


--- trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2018-06-02 21:08:10 UTC (rev 232442)
@@ -2368,6 +2368,26 @@
         setForNode(node, node->structure());
         break;
 
+    case ObjectCreate: {
+        if (JSValue base = forNode(node->child1()).m_value) {
+            if (base.isNull()) {
+                JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
+                m_state.setFoundConstants(true);
+                if (node->child1().useKind() == UntypedUse)
+                    didFoldClobberWorld();
+                setForNode(node, globalObject->nullPrototypeObjectStructure());
+                break;
+            }
+            // FIXME: We should get a structure for a constant prototype. We need to allow concurrent
+            // access to StructureCache from compiler threads.
+            // https://bugs.webkit.org/show_bug.cgi?id=186199
+        }
+        if (node->child1().useKind() == UntypedUse)
+            clobberWorld();
+        setTypeForNode(node, SpecFinalObject);
+        break;
+    }
+
     case ToObject:
     case CallObjectConstructor: {
         AbstractValue& source = forNode(node->child1());

Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (232441 => 232442)


--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2018-06-02 21:08:10 UTC (rev 232442)
@@ -2642,6 +2642,15 @@
         return true;
     }
 
+    case ObjectCreateIntrinsic: {
+        if (argumentCountIncludingThis != 2)
+            return false;
+
+        insertChecks();
+        set(VirtualRegister(resultOperand), addToGraph(ObjectCreate, get(virtualRegisterForArgument(1, registerOffset))));
+        return true;
+    }
+
     case ObjectGetPrototypeOfIntrinsic: {
         if (argumentCountIncludingThis != 2)
             return false;

Modified: trunk/Source/_javascript_Core/dfg/DFGClobberize.h (232441 => 232442)


--- trunk/Source/_javascript_Core/dfg/DFGClobberize.h	2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/dfg/DFGClobberize.h	2018-06-02 21:08:10 UTC (rev 232442)
@@ -1489,6 +1489,23 @@
         return;
     }
 
+    case ObjectCreate: {
+        switch (node->child1().useKind()) {
+        case ObjectUse:
+            read(HeapObjectCount);
+            write(HeapObjectCount);
+            return;
+        case UntypedUse:
+            read(World);
+            write(Heap);
+            return;
+        default:
+            RELEASE_ASSERT_NOT_REACHED();
+            return;
+        }
+    }
+
+
     case NewObject:
     case NewRegexp:
     case NewStringObject:

Modified: trunk/Source/_javascript_Core/dfg/DFGConstantFoldingPhase.cpp (232441 => 232442)


--- trunk/Source/_javascript_Core/dfg/DFGConstantFoldingPhase.cpp	2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/dfg/DFGConstantFoldingPhase.cpp	2018-06-02 21:08:10 UTC (rev 232442)
@@ -737,6 +737,21 @@
                 break;
             }
 
+            case ObjectCreate: {
+                if (JSValue base = m_state.forNode(node->child1()).m_value) {
+                    if (base.isNull()) {
+                        JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
+                        node->convertToNewObject(m_graph.registerStructure(globalObject->nullPrototypeObjectStructure()));
+                        changed = true;
+                        break;
+                    }
+                    // FIXME: We should get a structure for a constant prototype. We need to allow concurrent
+                    // access to StructureCache from compiler threads.
+                    // https://bugs.webkit.org/show_bug.cgi?id=186199
+                }
+                break;
+            }
+
             case ToNumber: {
                 if (m_state.forNode(node->child1()).m_type & ~SpecBytecodeNumber)
                     break;

Modified: trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp (232441 => 232442)


--- trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp	2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp	2018-06-02 21:08:10 UTC (rev 232442)
@@ -324,6 +324,7 @@
     case ToObject:
     case ToThis:
     case CreateThis:
+    case ObjectCreate:
     case AllocatePropertyStorage:
     case ReallocatePropertyStorage:
     case Arrayify:

Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (232441 => 232442)


--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2018-06-02 21:08:10 UTC (rev 232442)
@@ -1446,6 +1446,15 @@
             break;
         }
 
+        case ObjectCreate: {
+            if (node->child1()->shouldSpeculateObject()) {
+                fixEdge<ObjectUse>(node->child1());
+                node->clearFlags(NodeMustGenerate);
+                break;
+            }
+            break;
+        }
+
         case CheckStringIdent: {
             fixEdge<StringIdentUse>(node->child1());
             break;

Modified: trunk/Source/_javascript_Core/dfg/DFGNode.h (232441 => 232442)


--- trunk/Source/_javascript_Core/dfg/DFGNode.h	2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/dfg/DFGNode.h	2018-06-02 21:08:10 UTC (rev 232442)
@@ -733,7 +733,7 @@
 
     void convertToNewObject(RegisteredStructure structure)
     {
-        ASSERT(m_op == CallObjectConstructor || m_op == CreateThis);
+        ASSERT(m_op == CallObjectConstructor || m_op == CreateThis || m_op == ObjectCreate);
         setOpAndDefaultFlags(NewObject);
         children.reset();
         m_opInfo = structure;

Modified: trunk/Source/_javascript_Core/dfg/DFGNodeType.h (232441 => 232442)


--- trunk/Source/_javascript_Core/dfg/DFGNodeType.h	2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/dfg/DFGNodeType.h	2018-06-02 21:08:10 UTC (rev 232442)
@@ -255,6 +255,7 @@
     macro(CheckSubClass, NodeMustGenerate) \
     macro(ParseInt, NodeMustGenerate | NodeResultJS) \
     macro(GetPrototypeOf, NodeMustGenerate | NodeResultJS) \
+    macro(ObjectCreate, NodeMustGenerate | NodeResultJS) \
     \
     /* Atomics object functions. */\
     macro(AtomicsAdd, NodeResultJS | NodeMustGenerate | NodeHasVarArgs) \

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (232441 => 232442)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2018-06-02 21:08:10 UTC (rev 232442)
@@ -248,6 +248,34 @@
     return JSValue::encode(JSValue::decode(encodedOp).toThis(exec, StrictMode));
 }
 
+JSCell* JIT_OPERATION operationObjectCreate(ExecState* exec, EncodedJSValue encodedPrototype)
+{
+    VM& vm = exec->vm();
+    NativeCallFrameTracer tracer(&vm, exec);
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    JSValue prototype = JSValue::decode(encodedPrototype);
+
+    if (!prototype.isObject() && !prototype.isNull()) {
+        throwVMTypeError(exec, scope, ASCIILiteral("Object prototype may only be an Object or null."));
+        return nullptr;
+    }
+
+    if (prototype.isObject()) {
+        scope.release();
+        return constructEmptyObject(exec, asObject(prototype));
+    }
+    scope.release();
+    return constructEmptyObject(exec, exec->lexicalGlobalObject()->nullPrototypeObjectStructure());
+}
+
+JSCell* JIT_OPERATION operationObjectCreateObject(ExecState* exec, JSObject* prototype)
+{
+    VM& vm = exec->vm();
+    NativeCallFrameTracer tracer(&vm, exec);
+    return constructEmptyObject(exec, prototype);
+}
+
 JSCell* JIT_OPERATION operationCreateThis(ExecState* exec, JSObject* constructor, uint32_t inlineCapacity)
 {
     VM& vm = exec->vm();

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.h (232441 => 232442)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.h	2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.h	2018-06-02 21:08:10 UTC (rev 232442)
@@ -43,6 +43,8 @@
 // These routines provide callbacks out to C++ implementations of operations too complex to JIT.
 JSCell* JIT_OPERATION operationCallObjectConstructor(ExecState*, JSGlobalObject*, EncodedJSValue encodedTarget) WTF_INTERNAL;
 JSCell* JIT_OPERATION operationToObject(ExecState*, JSGlobalObject*, EncodedJSValue encodedTarget, UniquedStringImpl*) WTF_INTERNAL;
+JSCell* JIT_OPERATION operationObjectCreate(ExecState*, EncodedJSValue) WTF_INTERNAL;
+JSCell* JIT_OPERATION operationObjectCreateObject(ExecState*, JSObject*) WTF_INTERNAL;
 JSCell* JIT_OPERATION operationCreateThis(ExecState*, JSObject* constructor, uint32_t inlineCapacity) WTF_INTERNAL;
 EncodedJSValue JIT_OPERATION operationToThis(ExecState*, EncodedJSValue encodedOp1) WTF_INTERNAL;
 EncodedJSValue JIT_OPERATION operationToThisStrict(ExecState*, EncodedJSValue encodedOp1) WTF_INTERNAL;

Modified: trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp (232441 => 232442)


--- trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2018-06-02 21:08:10 UTC (rev 232442)
@@ -906,6 +906,7 @@
             break;
         }
             
+        case ObjectCreate:
         case CreateThis:
         case NewObject: {
             setPrediction(SpecFinalObject);

Modified: trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h (232441 => 232442)


--- trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h	2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h	2018-06-02 21:08:10 UTC (rev 232442)
@@ -171,6 +171,7 @@
     case IdentityWithProfile:
     case ToThis:
     case CreateThis:
+    case ObjectCreate:
     case GetCallee:
     case SetCallee:
     case GetArgumentCountIncludingThis:

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (232441 => 232442)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2018-06-02 21:08:10 UTC (rev 232442)
@@ -12172,6 +12172,47 @@
     jsValueResult(tempRegs, node);
 }
 
+void SpeculativeJIT::compileObjectCreate(Node* node)
+{
+    switch (node->child1().useKind()) {
+    case ObjectUse: {
+        SpeculateCellOperand prototype(this, node->child1());
+
+        GPRReg prototypeGPR = prototype.gpr();
+
+        speculateObject(node->child1(), prototypeGPR);
+
+        flushRegisters();
+        GPRFlushedCallResult result(this);
+        GPRReg resultGPR = result.gpr();
+        callOperation(operationObjectCreateObject, resultGPR, prototypeGPR);
+        m_jit.exceptionCheck();
+
+        cellResult(resultGPR, node);
+        break;
+    }
+
+    case UntypedUse: {
+        JSValueOperand prototype(this, node->child1());
+
+        JSValueRegs prototypeRegs = prototype.jsValueRegs();
+
+        flushRegisters();
+        GPRFlushedCallResult result(this);
+        GPRReg resultGPR = result.gpr();
+        callOperation(operationObjectCreate, resultGPR, prototypeRegs);
+        m_jit.exceptionCheck();
+
+        cellResult(resultGPR, node);
+        break;
+    }
+
+    default:
+        RELEASE_ASSERT_NOT_REACHED();
+        break;
+    }
+}
+
 void SpeculativeJIT::compileCreateThis(Node* node)
 {
     // Note that there is not so much profit to speculate here. The only things we

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (232441 => 232442)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h	2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h	2018-06-02 21:08:10 UTC (rev 232442)
@@ -1472,6 +1472,7 @@
     void compileNewArrayWithSize(Node*);
     void compileNewTypedArray(Node*);
     void compileToThis(Node*);
+    void compileObjectCreate(Node*);
     void compileCreateThis(Node*);
     void compileNewObject(Node*);
     void compileToPrimitive(Node*);

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (232441 => 232442)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2018-06-02 21:08:10 UTC (rev 232442)
@@ -3132,6 +3132,11 @@
         break;
     }
 
+    case ObjectCreate: {
+        compileObjectCreate(node);
+        break;
+    }
+
     case CreateThis: {
         compileCreateThis(node);
         break;

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (232441 => 232442)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2018-06-02 21:08:10 UTC (rev 232442)
@@ -3382,6 +3382,11 @@
         break;
     }
 
+    case ObjectCreate: {
+        compileObjectCreate(node);
+        break;
+    }
+
     case CreateThis: {
         compileCreateThis(node);
         break;

Modified: trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp (232441 => 232442)


--- trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp	2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp	2018-06-02 21:08:10 UTC (rev 232442)
@@ -191,6 +191,7 @@
     case ToObject:
     case CallObjectConstructor:
     case CallStringConstructor:
+    case ObjectCreate:
     case MakeRope:
     case NewArrayWithSize:
     case TryGetById:

Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (232441 => 232442)


--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2018-06-02 21:08:10 UTC (rev 232442)
@@ -838,6 +838,9 @@
         case CreateClonedArguments:
             compileCreateClonedArguments();
             break;
+        case ObjectCreate:
+            compileObjectCreate();
+            break;
         case NewObject:
             compileNewObject();
             break;
@@ -5353,6 +5356,21 @@
         m_out.appendTo(continuation, lastNext);
         setInt32(m_out.phi(Int32, zeroLengthResult, nonZeroLengthResult));
     }
+
+    void compileObjectCreate()
+    {
+        switch (m_node->child1().useKind()) {
+        case ObjectUse:
+            setJSValue(vmCall(Int64, m_out.operation(operationObjectCreateObject), m_callFrame, lowObject(m_node->child1())));
+            break;
+        case UntypedUse:
+            setJSValue(vmCall(Int64, m_out.operation(operationObjectCreate), m_callFrame, lowJSValue(m_node->child1())));
+            break;
+        default:
+            RELEASE_ASSERT_NOT_REACHED();
+            break;
+        }
+    }
     
     void compileNewObject()
     {

Modified: trunk/Source/_javascript_Core/runtime/Intrinsic.cpp (232441 => 232442)


--- trunk/Source/_javascript_Core/runtime/Intrinsic.cpp	2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/runtime/Intrinsic.cpp	2018-06-02 21:08:10 UTC (rev 232442)
@@ -113,6 +113,8 @@
         return "RegExpTestFastIntrinsic";
     case RegExpMatchFastIntrinsic:
         return "RegExpMatchFastIntrinsic";
+    case ObjectCreateIntrinsic:
+        return "ObjectCreateIntrinsic";
     case ObjectGetPrototypeOfIntrinsic:
         return "ObjectGetPrototypeOfIntrinsic";
     case ObjectIsIntrinsic:

Modified: trunk/Source/_javascript_Core/runtime/Intrinsic.h (232441 => 232442)


--- trunk/Source/_javascript_Core/runtime/Intrinsic.h	2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/runtime/Intrinsic.h	2018-06-02 21:08:10 UTC (rev 232442)
@@ -69,6 +69,7 @@
     RegExpTestIntrinsic,
     RegExpTestFastIntrinsic,
     RegExpMatchFastIntrinsic,
+    ObjectCreateIntrinsic,
     ObjectGetPrototypeOfIntrinsic,
     ObjectIsIntrinsic,
     ReflectGetPrototypeOfIntrinsic,

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp (232441 => 232442)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2018-06-02 21:08:10 UTC (rev 232442)
@@ -537,10 +537,7 @@
             init.set(JSWithScope::createStructure(init.vm, init.owner, jsNull()));
         });
     
-    m_nullPrototypeObjectStructure.initLater(
-        [] (const Initializer<Structure>& init) {
-            init.set(JSFinalObject::createStructure(init.vm, init.owner, jsNull(), JSFinalObject::defaultInlineCapacity()));
-        });
+    m_nullPrototypeObjectStructure.set(vm, this, JSFinalObject::createStructure(vm, this, jsNull(), JSFinalObject::defaultInlineCapacity()));
     
     m_callbackFunctionStructure.initLater(
         [] (const Initializer<Structure>& init) {
@@ -1394,7 +1391,7 @@
     thisObject->m_glibCallbackFunctionStructure.visit(visitor);
     thisObject->m_glibWrapperObjectStructure.visit(visitor);
 #endif
-    thisObject->m_nullPrototypeObjectStructure.visit(visitor);
+    visitor.append(thisObject->m_nullPrototypeObjectStructure);
     visitor.append(thisObject->m_errorStructure);
     visitor.append(thisObject->m_calleeStructure);
     visitor.append(thisObject->m_strictFunctionStructure);

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.h (232441 => 232442)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.h	2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.h	2018-06-02 21:08:10 UTC (rev 232442)
@@ -339,7 +339,7 @@
     LazyProperty<JSGlobalObject, Structure> m_glibCallbackFunctionStructure;
     LazyProperty<JSGlobalObject, Structure> m_glibWrapperObjectStructure;
 #endif
-    LazyProperty<JSGlobalObject, Structure> m_nullPrototypeObjectStructure;
+    WriteBarrier<Structure> m_nullPrototypeObjectStructure;
     WriteBarrier<Structure> m_calleeStructure;
     WriteBarrier<Structure> m_strictFunctionStructure;
     WriteBarrier<Structure> m_arrowFunctionStructure;
@@ -654,7 +654,7 @@
     Structure* glibWrapperObjectStructure() const { return m_glibWrapperObjectStructure.get(this); }
 #endif
     Structure* dateStructure() const { return m_dateStructure.get(this); }
-    Structure* nullPrototypeObjectStructure() const { return m_nullPrototypeObjectStructure.get(this); }
+    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(); }

Modified: trunk/Source/_javascript_Core/runtime/ObjectConstructor.cpp (232441 => 232442)


--- trunk/Source/_javascript_Core/runtime/ObjectConstructor.cpp	2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/runtime/ObjectConstructor.cpp	2018-06-02 21:08:10 UTC (rev 232442)
@@ -76,7 +76,7 @@
   keys                      objectConstructorKeys                       DontEnum|Function 1
   defineProperty            objectConstructorDefineProperty             DontEnum|Function 3
   defineProperties          objectConstructorDefineProperties           DontEnum|Function 2
-  create                    objectConstructorCreate                     DontEnum|Function 2
+  create                    objectConstructorCreate                     DontEnum|Function 2 ObjectCreateIntrinsic
   seal                      objectConstructorSeal                       DontEnum|Function 1
   freeze                    objectConstructorFreeze                     DontEnum|Function 1
   preventExtensions         objectConstructorPreventExtensions          DontEnum|Function 1
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to