Title: [224280] trunk
Revision
224280
Author
[email protected]
Date
2017-11-01 10:32:08 -0700 (Wed, 01 Nov 2017)

Log Message

[JSC] Introduce @toObject
https://bugs.webkit.org/show_bug.cgi?id=178726

Reviewed by Saam Barati.

JSTests:

* stress/array-copywithin.js:
(shouldThrow):
* stress/object-constructor-boolean-edge.js: Added.
(shouldBe):
(test):
* stress/object-constructor-global.js: Added.
(shouldBe):
* stress/object-constructor-null-edge.js: Added.
(shouldBe):
(test):
* stress/object-constructor-number-edge.js: Added.
(shouldBe):
(test):
* stress/object-constructor-object-edge.js: Added.
(shouldBe):
(test):
(i.arg):
* stress/object-constructor-string-edge.js: Added.
(shouldBe):
(test):
* stress/object-constructor-symbol-edge.js: Added.
(shouldBe):
(test):
* stress/object-constructor-undefined-edge.js: Added.
(shouldBe):
(test):
* stress/symbol-array-from.js: Added.
(shouldBe):
* stress/to-object-intrinsic-boolean-edge.js: Added.
(shouldBe):
(builtin.createBuiltin):
* stress/to-object-intrinsic-null-or-undefined-edge.js: Added.
(shouldThrow):
* stress/to-object-intrinsic-number-edge.js: Added.
(shouldBe):
(builtin.createBuiltin):
* stress/to-object-intrinsic-object-edge.js: Added.
(shouldBe):
(builtin.createBuiltin):
(i.arg):
* stress/to-object-intrinsic-string-edge.js: Added.
(shouldBe):
(builtin.createBuiltin):
* stress/to-object-intrinsic-symbol-edge.js: Added.
(shouldBe):
(builtin.createBuiltin):
* stress/to-object-intrinsic.js: Added.
(shouldBe):
(shouldThrow):
(builtin.createBuiltin):

Source/_javascript_Core:

This patch introduces @toObject intrinsic. And we introduce op_to_object bytecode and DFG ToObject node.
Previously we emulated @toObject behavior in builtin JS. But it consumes much bytecode size while @toObject
is frequently seen and defined clearly in the spec. Furthermore, the emulated @toObject always calls
ObjectConstructor in LLInt and Baseline.

We add a new intrinsic `@toObject(target, "error message")`. It takes an error message string constant to
offer understandable messages in builtin JS. We can change the frequently seen "emulated ToObject" operation

    if (this === @undefined || this === null)
        @throwTypeError("error message");
    var object = @Object(this);

with

    var object = @toObject(this, "error message");

And we handle op_to_object in DFG as ToObject node. While CallObjectConstructor does not throw an error for null/undefined,
ToObject needs to throw an error for null/undefined. So it is marked as MustGenerate and it clobbers the world.
In fixup phase, we attempt to convert ToObject to CallObjectConstructor with edge filters to relax its side effect.

It also fixes a bug that CallObjectConstructor DFG node uses Node's semantic GlobalObject instead of function's one.

* builtins/ArrayConstructor.js:
(from):
* builtins/ArrayPrototype.js:
(values):
(keys):
(entries):
(reduce):
(reduceRight):
(every):
(forEach):
(filter):
(map):
(some):
(fill):
(find):
(findIndex):
(includes):
(sort):
(globalPrivate.concatSlowPath):
(copyWithin):
* builtins/DatePrototype.js:
(toLocaleString.toDateTimeOptionsAnyAll):
(toLocaleString):
(toLocaleDateString.toDateTimeOptionsDateDate):
(toLocaleDateString):
(toLocaleTimeString.toDateTimeOptionsTimeTime):
(toLocaleTimeString):
* builtins/GlobalOperations.js:
(globalPrivate.copyDataProperties):
(globalPrivate.copyDataPropertiesNoExclusions):
* builtins/ObjectConstructor.js:
(entries):
* builtins/StringConstructor.js:
(raw):
* builtins/TypedArrayConstructor.js:
(from):
* builtins/TypedArrayPrototype.js:
(map):
(filter):
* bytecode/BytecodeDumper.cpp:
(JSC::BytecodeDumper<Block>::dumpBytecode):
* bytecode/BytecodeIntrinsicRegistry.h:
* bytecode/BytecodeList.json:
* bytecode/BytecodeUseDef.h:
(JSC::computeUsesForBytecodeOffset):
(JSC::computeDefsForBytecodeOffset):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::finishCreation):
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::emitToObject):
* bytecompiler/BytecodeGenerator.h:
* bytecompiler/NodesCodegen.cpp:
(JSC::BytecodeIntrinsicNode::emit_intrinsic_toObject):
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::handleConstantInternalFunction):
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGCapabilities.cpp:
(JSC::DFG::capabilityLevel):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGDoesGC.cpp:
(JSC::DFG::doesGC):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
(JSC::DFG::FixupPhase::fixupToObject):
(JSC::DFG::FixupPhase::fixupCallObjectConstructor):
* dfg/DFGNode.h:
(JSC::DFG::Node::convertToCallObjectConstructor):
(JSC::DFG::Node::convertToNewStringObject):
(JSC::DFG::Node::convertToNewObject):
(JSC::DFG::Node::hasIdentifier):
(JSC::DFG::Node::hasHeapPrediction):
(JSC::DFG::Node::hasCellOperand):
* dfg/DFGNodeType.h:
* dfg/DFGOperations.cpp:
* dfg/DFGOperations.h:
* dfg/DFGPredictionPropagationPhase.cpp:
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileToObjectOrCallObjectConstructor):
(JSC::DFG::SpeculativeJIT::compileCallObjectConstructor): Deleted.
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::callOperation):
* 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::compileToObjectOrCallObjectConstructor):
(JSC::FTL::DFG::LowerDFGToB3::compileCallObjectConstructor): Deleted.
* jit/JIT.cpp:
(JSC::JIT::privateCompileMainPass):
(JSC::JIT::privateCompileSlowCases):
* jit/JIT.h:
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_to_object):
(JSC::JIT::emitSlow_op_to_object):
* jit/JITOpcodes32_64.cpp:
(JSC::JIT::emit_op_to_object):
(JSC::JIT::emitSlow_op_to_object):
* jit/JITOperations.cpp:
* jit/JITOperations.h:
* llint/LowLevelInterpreter32_64.asm:
* llint/LowLevelInterpreter64.asm:
* runtime/CommonSlowPaths.cpp:
(JSC::SLOW_PATH_DECL):
* runtime/CommonSlowPaths.h:

Source/WebCore:

Use @isObject instead. It is more efficient.

* Modules/mediastream/NavigatorUserMedia.js:
(getUserMedia):

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (224279 => 224280)


--- trunk/JSTests/ChangeLog	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/JSTests/ChangeLog	2017-11-01 17:32:08 UTC (rev 224280)
@@ -1,3 +1,61 @@
+2017-11-01  Yusuke Suzuki  <[email protected]>
+
+        [JSC] Introduce @toObject
+        https://bugs.webkit.org/show_bug.cgi?id=178726
+
+        Reviewed by Saam Barati.
+
+        * stress/array-copywithin.js:
+        (shouldThrow):
+        * stress/object-constructor-boolean-edge.js: Added.
+        (shouldBe):
+        (test):
+        * stress/object-constructor-global.js: Added.
+        (shouldBe):
+        * stress/object-constructor-null-edge.js: Added.
+        (shouldBe):
+        (test):
+        * stress/object-constructor-number-edge.js: Added.
+        (shouldBe):
+        (test):
+        * stress/object-constructor-object-edge.js: Added.
+        (shouldBe):
+        (test):
+        (i.arg):
+        * stress/object-constructor-string-edge.js: Added.
+        (shouldBe):
+        (test):
+        * stress/object-constructor-symbol-edge.js: Added.
+        (shouldBe):
+        (test):
+        * stress/object-constructor-undefined-edge.js: Added.
+        (shouldBe):
+        (test):
+        * stress/symbol-array-from.js: Added.
+        (shouldBe):
+        * stress/to-object-intrinsic-boolean-edge.js: Added.
+        (shouldBe):
+        (builtin.createBuiltin):
+        * stress/to-object-intrinsic-null-or-undefined-edge.js: Added.
+        (shouldThrow):
+        * stress/to-object-intrinsic-number-edge.js: Added.
+        (shouldBe):
+        (builtin.createBuiltin):
+        * stress/to-object-intrinsic-object-edge.js: Added.
+        (shouldBe):
+        (builtin.createBuiltin):
+        (i.arg):
+        * stress/to-object-intrinsic-string-edge.js: Added.
+        (shouldBe):
+        (builtin.createBuiltin):
+        * stress/to-object-intrinsic-symbol-edge.js: Added.
+        (shouldBe):
+        (builtin.createBuiltin):
+        * stress/to-object-intrinsic.js: Added.
+        (shouldBe):
+        (shouldThrow):
+        (builtin.createBuiltin):
+
 2017-10-27  Yusuke Suzuki  <[email protected]>
 
         [DFG][FTL] Introduce StringSlice

Modified: trunk/JSTests/stress/array-copywithin.js (224279 => 224280)


--- trunk/JSTests/stress/array-copywithin.js	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/JSTests/stress/array-copywithin.js	2017-11-01 17:32:08 UTC (rev 224280)
@@ -238,11 +238,11 @@
 
 shouldThrow(function () {
     Array.prototype.copyWithin.call(undefined);
-}, 'TypeError: Array.copyWithin requires that |this| not be null or undefined');
+}, 'TypeError: Array.prototype.copyWithin requires that |this| not be null or undefined');
 
 shouldThrow(function () {
     Array.prototype.copyWithin.call(null);
-}, 'TypeError: Array.copyWithin requires that |this| not be null or undefined');
+}, 'TypeError: Array.prototype.copyWithin requires that |this| not be null or undefined');
 
 
 function valueOf(code) {

Added: trunk/JSTests/stress/object-constructor-boolean-edge.js (0 => 224280)


--- trunk/JSTests/stress/object-constructor-boolean-edge.js	                        (rev 0)
+++ trunk/JSTests/stress/object-constructor-boolean-edge.js	2017-11-01 17:32:08 UTC (rev 224280)
@@ -0,0 +1,18 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function test(target)
+{
+    return Object(target);
+}
+noInline(test);
+
+(function () {
+    for (var i = 0; i < 1e4; ++i) {
+        var object = test(true);
+        shouldBe(object instanceof Boolean, true);
+        shouldBe(object.valueOf(), true);
+    }
+}());

Added: trunk/JSTests/stress/object-constructor-global.js (0 => 224280)


--- trunk/JSTests/stress/object-constructor-global.js	                        (rev 0)
+++ trunk/JSTests/stress/object-constructor-global.js	2017-11-01 17:32:08 UTC (rev 224280)
@@ -0,0 +1,22 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+var globalObject = createGlobalObject();
+var constructor = globalObject.Object;
+var tests = [
+    [ null, globalObject.Object ],
+    [ undefined, globalObject.Object ],
+    [ "Hello", globalObject.String ],
+    [ 42, globalObject.Number ],
+    [ false, globalObject.Boolean ],
+    [ Symbol("Cocoa"), globalObject.Symbol ],
+];
+
+for (var i = 0; i < 1e4; ++i) {
+    for (var [target, cls] of tests) {
+        var result = constructor(target);
+        shouldBe(result instanceof cls, true);
+    }
+}

Added: trunk/JSTests/stress/object-constructor-null-edge.js (0 => 224280)


--- trunk/JSTests/stress/object-constructor-null-edge.js	                        (rev 0)
+++ trunk/JSTests/stress/object-constructor-null-edge.js	2017-11-01 17:32:08 UTC (rev 224280)
@@ -0,0 +1,17 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function test(target)
+{
+    return Object(target);
+}
+noInline(test);
+
+(function () {
+    for (var i = 0; i < 1e4; ++i) {
+        var object = test(null);
+        shouldBe(object.__proto__, Object.prototype);
+    }
+}());

Added: trunk/JSTests/stress/object-constructor-number-edge.js (0 => 224280)


--- trunk/JSTests/stress/object-constructor-number-edge.js	                        (rev 0)
+++ trunk/JSTests/stress/object-constructor-number-edge.js	2017-11-01 17:32:08 UTC (rev 224280)
@@ -0,0 +1,22 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function test(target)
+{
+    return Object(target);
+}
+noInline(test);
+
+(function () {
+    for (var i = 0; i < 1e4; ++i) {
+        var object = test(42);
+        shouldBe(object instanceof Number, true);
+        shouldBe(object.valueOf(), 42);
+
+        var object = test(42.195);
+        shouldBe(object instanceof Number, true);
+        shouldBe(object.valueOf(), 42.195);
+    }
+}());

Added: trunk/JSTests/stress/object-constructor-object-edge.js (0 => 224280)


--- trunk/JSTests/stress/object-constructor-object-edge.js	                        (rev 0)
+++ trunk/JSTests/stress/object-constructor-object-edge.js	2017-11-01 17:32:08 UTC (rev 224280)
@@ -0,0 +1,26 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function test(target)
+{
+    return Object(target);
+}
+noInline(test);
+
+(function () {
+    for (var i = 0; i < 1e4; ++i) {
+        var arg = {};
+        var object = test(arg);
+        shouldBe(object, arg);
+
+        var arg = [];
+        var object = test(arg);
+        shouldBe(object, arg);
+
+        var arg = function () { };
+        var object = test(arg);
+        shouldBe(object, arg);
+    }
+}());

Added: trunk/JSTests/stress/object-constructor-string-edge.js (0 => 224280)


--- trunk/JSTests/stress/object-constructor-string-edge.js	                        (rev 0)
+++ trunk/JSTests/stress/object-constructor-string-edge.js	2017-11-01 17:32:08 UTC (rev 224280)
@@ -0,0 +1,18 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function test(target)
+{
+    return Object(target);
+}
+noInline(test);
+
+(function () {
+    for (var i = 0; i < 1e4; ++i) {
+        var object = test("Cocoa");
+        shouldBe(object instanceof String, true);
+        shouldBe(object.valueOf(), "Cocoa");
+    }
+}());

Added: trunk/JSTests/stress/object-constructor-symbol-edge.js (0 => 224280)


--- trunk/JSTests/stress/object-constructor-symbol-edge.js	                        (rev 0)
+++ trunk/JSTests/stress/object-constructor-symbol-edge.js	2017-11-01 17:32:08 UTC (rev 224280)
@@ -0,0 +1,18 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function test(target)
+{
+    return Object(target);
+}
+noInline(test);
+
+(function () {
+    for (var i = 0; i < 1e4; ++i) {
+        var object = test(Symbol("Cocoa"));
+        shouldBe(object instanceof Symbol, true);
+        shouldBe(String(object.valueOf()), `Symbol(Cocoa)`);
+    }
+}());

Added: trunk/JSTests/stress/object-constructor-undefined-edge.js (0 => 224280)


--- trunk/JSTests/stress/object-constructor-undefined-edge.js	                        (rev 0)
+++ trunk/JSTests/stress/object-constructor-undefined-edge.js	2017-11-01 17:32:08 UTC (rev 224280)
@@ -0,0 +1,17 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function test(target)
+{
+    return Object(target);
+}
+noInline(test);
+
+(function () {
+    for (var i = 0; i < 1e4; ++i) {
+        var object = test(undefined);
+        shouldBe(object.__proto__, Object.prototype);
+    }
+}());

Added: trunk/JSTests/stress/symbol-array-from.js (0 => 224280)


--- trunk/JSTests/stress/symbol-array-from.js	                        (rev 0)
+++ trunk/JSTests/stress/symbol-array-from.js	2017-11-01 17:32:08 UTC (rev 224280)
@@ -0,0 +1,26 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+var called = false;
+Object.defineProperty(Symbol.prototype, Symbol.iterator, {
+    get() {
+        "use strict";
+        shouldBe(typeof this, "symbol");
+        called = true;
+        return null;
+    }
+});
+
+var symbol = Symbol("Cocoa");
+{
+    called =false;
+    Array.from(symbol);
+    shouldBe(called, true);
+}
+{
+    called =false;
+    Uint8Array.from(symbol);
+    shouldBe(called, true);
+}

Added: trunk/JSTests/stress/to-object-intrinsic-boolean-edge.js (0 => 224280)


--- trunk/JSTests/stress/to-object-intrinsic-boolean-edge.js	                        (rev 0)
+++ trunk/JSTests/stress/to-object-intrinsic-boolean-edge.js	2017-11-01 17:32:08 UTC (rev 224280)
@@ -0,0 +1,17 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+var builtin = createBuiltin(`(function (target) {
+    return @toObject(target, "");
+})`);
+noInline(builtin);
+
+(function () {
+    for (var i = 0; i < 1e4; ++i) {
+        var object = builtin(true);
+        shouldBe(object instanceof Boolean, true);
+        shouldBe(object.valueOf(), true);
+    }
+}());

Added: trunk/JSTests/stress/to-object-intrinsic-null-or-undefined-edge.js (0 => 224280)


--- trunk/JSTests/stress/to-object-intrinsic-null-or-undefined-edge.js	                        (rev 0)
+++ trunk/JSTests/stress/to-object-intrinsic-null-or-undefined-edge.js	2017-11-01 17:32:08 UTC (rev 224280)
@@ -0,0 +1,34 @@
+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 () {
+    var builtin = createBuiltin(`(function (target) {
+        return @toObject(target, "");
+    })`);
+    noInline(builtin);
+
+    for (var i = 0; i < 1e4; ++i)
+        shouldThrow(() => builtin(null), `TypeError: null is not an object`);
+}());
+
+(function () {
+    var builtin = createBuiltin(`(function (target) {
+        return @toObject(target, "");
+    })`);
+    noInline(builtin);
+
+    for (var i = 0; i < 1e4; ++i)
+        shouldThrow(() => builtin(undefined), `TypeError: undefined is not an object`);
+}());

Added: trunk/JSTests/stress/to-object-intrinsic-number-edge.js (0 => 224280)


--- trunk/JSTests/stress/to-object-intrinsic-number-edge.js	                        (rev 0)
+++ trunk/JSTests/stress/to-object-intrinsic-number-edge.js	2017-11-01 17:32:08 UTC (rev 224280)
@@ -0,0 +1,21 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+var builtin = createBuiltin(`(function (target) {
+    return @toObject(target, "");
+})`);
+noInline(builtin);
+
+(function () {
+    for (var i = 0; i < 1e4; ++i) {
+        var object = builtin(42);
+        shouldBe(object instanceof Number, true);
+        shouldBe(object.valueOf(), 42);
+
+        var object = builtin(42.195);
+        shouldBe(object instanceof Number, true);
+        shouldBe(object.valueOf(), 42.195);
+    }
+}());

Added: trunk/JSTests/stress/to-object-intrinsic-object-edge.js (0 => 224280)


--- trunk/JSTests/stress/to-object-intrinsic-object-edge.js	                        (rev 0)
+++ trunk/JSTests/stress/to-object-intrinsic-object-edge.js	2017-11-01 17:32:08 UTC (rev 224280)
@@ -0,0 +1,25 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+var builtin = createBuiltin(`(function (target) {
+    return @toObject(target, "");
+})`);
+noInline(builtin);
+
+(function () {
+    for (var i = 0; i < 1e4; ++i) {
+        var arg = {};
+        var object = builtin(arg);
+        shouldBe(object, arg);
+
+        var arg = [];
+        var object = builtin(arg);
+        shouldBe(object, arg);
+
+        var arg = function () { };
+        var object = builtin(arg);
+        shouldBe(object, arg);
+    }
+}());

Added: trunk/JSTests/stress/to-object-intrinsic-string-edge.js (0 => 224280)


--- trunk/JSTests/stress/to-object-intrinsic-string-edge.js	                        (rev 0)
+++ trunk/JSTests/stress/to-object-intrinsic-string-edge.js	2017-11-01 17:32:08 UTC (rev 224280)
@@ -0,0 +1,17 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+var builtin = createBuiltin(`(function (target) {
+    return @toObject(target, "");
+})`);
+noInline(builtin);
+
+(function () {
+    for (var i = 0; i < 1e4; ++i) {
+        var object = builtin("Cocoa");
+        shouldBe(object instanceof String, true);
+        shouldBe(object.valueOf(), "Cocoa");
+    }
+}());

Added: trunk/JSTests/stress/to-object-intrinsic-symbol-edge.js (0 => 224280)


--- trunk/JSTests/stress/to-object-intrinsic-symbol-edge.js	                        (rev 0)
+++ trunk/JSTests/stress/to-object-intrinsic-symbol-edge.js	2017-11-01 17:32:08 UTC (rev 224280)
@@ -0,0 +1,17 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+var builtin = createBuiltin(`(function (target) {
+    return @toObject(target, "");
+})`);
+noInline(builtin);
+
+(function () {
+    for (var i = 0; i < 1e4; ++i) {
+        var object = builtin(Symbol("Cocoa"));
+        shouldBe(object instanceof Symbol, true);
+        shouldBe(String(object.valueOf()), `Symbol(Cocoa)`);
+    }
+}());

Added: trunk/JSTests/stress/to-object-intrinsic.js (0 => 224280)


--- trunk/JSTests/stress/to-object-intrinsic.js	                        (rev 0)
+++ trunk/JSTests/stress/to-object-intrinsic.js	2017-11-01 17:32:08 UTC (rev 224280)
@@ -0,0 +1,51 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+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)}`);
+}
+
+var builtin = createBuiltin(`(function (target) {
+    return @toObject(target, "");
+})`);
+noInline(builtin);
+
+(function () {
+    for (var i = 0; i < 1e4; ++i) {
+        shouldThrow(() => builtin(null), `TypeError: null is not an object`);
+        shouldThrow(() => builtin(undefined), `TypeError: undefined is not an object`);
+        var object = builtin(42);
+        shouldBe(object instanceof Number, true);
+        shouldBe(object.valueOf(), 42);
+
+        var object = builtin("Cocoa");
+        shouldBe(object instanceof String, true);
+        shouldBe(object.valueOf(), "Cocoa");
+
+        var object = builtin(true);
+        shouldBe(object instanceof Boolean, true);
+        shouldBe(object.valueOf(), true);
+
+        var object = builtin(Symbol("Cocoa"));
+        shouldBe(object instanceof Symbol, true);
+        shouldBe(String(object.valueOf()), `Symbol(Cocoa)`);
+
+        var arg = {};
+        var object = builtin(arg);
+        shouldBe(object, arg);
+    }
+}());
+

Modified: trunk/Source/_javascript_Core/ChangeLog (224279 => 224280)


--- trunk/Source/_javascript_Core/ChangeLog	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/Source/_javascript_Core/ChangeLog	2017-11-01 17:32:08 UTC (rev 224280)
@@ -1,3 +1,146 @@
+2017-11-01  Yusuke Suzuki  <[email protected]>
+
+        [JSC] Introduce @toObject
+        https://bugs.webkit.org/show_bug.cgi?id=178726
+
+        Reviewed by Saam Barati.
+
+        This patch introduces @toObject intrinsic. And we introduce op_to_object bytecode and DFG ToObject node.
+        Previously we emulated @toObject behavior in builtin JS. But it consumes much bytecode size while @toObject
+        is frequently seen and defined clearly in the spec. Furthermore, the emulated @toObject always calls
+        ObjectConstructor in LLInt and Baseline.
+
+        We add a new intrinsic `@toObject(target, "error message")`. It takes an error message string constant to
+        offer understandable messages in builtin JS. We can change the frequently seen "emulated ToObject" operation
+
+            if (this === @undefined || this === null)
+                @throwTypeError("error message");
+            var object = @Object(this);
+
+        with
+
+            var object = @toObject(this, "error message");
+
+        And we handle op_to_object in DFG as ToObject node. While CallObjectConstructor does not throw an error for null/undefined,
+        ToObject needs to throw an error for null/undefined. So it is marked as MustGenerate and it clobbers the world.
+        In fixup phase, we attempt to convert ToObject to CallObjectConstructor with edge filters to relax its side effect.
+
+        It also fixes a bug that CallObjectConstructor DFG node uses Node's semantic GlobalObject instead of function's one.
+
+        * builtins/ArrayConstructor.js:
+        (from):
+        * builtins/ArrayPrototype.js:
+        (values):
+        (keys):
+        (entries):
+        (reduce):
+        (reduceRight):
+        (every):
+        (forEach):
+        (filter):
+        (map):
+        (some):
+        (fill):
+        (find):
+        (findIndex):
+        (includes):
+        (sort):
+        (globalPrivate.concatSlowPath):
+        (copyWithin):
+        * builtins/DatePrototype.js:
+        (toLocaleString.toDateTimeOptionsAnyAll):
+        (toLocaleString):
+        (toLocaleDateString.toDateTimeOptionsDateDate):
+        (toLocaleDateString):
+        (toLocaleTimeString.toDateTimeOptionsTimeTime):
+        (toLocaleTimeString):
+        * builtins/GlobalOperations.js:
+        (globalPrivate.copyDataProperties):
+        (globalPrivate.copyDataPropertiesNoExclusions):
+        * builtins/ObjectConstructor.js:
+        (entries):
+        * builtins/StringConstructor.js:
+        (raw):
+        * builtins/TypedArrayConstructor.js:
+        (from):
+        * builtins/TypedArrayPrototype.js:
+        (map):
+        (filter):
+        * bytecode/BytecodeDumper.cpp:
+        (JSC::BytecodeDumper<Block>::dumpBytecode):
+        * bytecode/BytecodeIntrinsicRegistry.h:
+        * bytecode/BytecodeList.json:
+        * bytecode/BytecodeUseDef.h:
+        (JSC::computeUsesForBytecodeOffset):
+        (JSC::computeDefsForBytecodeOffset):
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::finishCreation):
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::emitToObject):
+        * bytecompiler/BytecodeGenerator.h:
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::BytecodeIntrinsicNode::emit_intrinsic_toObject):
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::handleConstantInternalFunction):
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * dfg/DFGCapabilities.cpp:
+        (JSC::DFG::capabilityLevel):
+        * dfg/DFGClobberize.h:
+        (JSC::DFG::clobberize):
+        * dfg/DFGDoesGC.cpp:
+        (JSC::DFG::doesGC):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        (JSC::DFG::FixupPhase::fixupToObject):
+        (JSC::DFG::FixupPhase::fixupCallObjectConstructor):
+        * dfg/DFGNode.h:
+        (JSC::DFG::Node::convertToCallObjectConstructor):
+        (JSC::DFG::Node::convertToNewStringObject):
+        (JSC::DFG::Node::convertToNewObject):
+        (JSC::DFG::Node::hasIdentifier):
+        (JSC::DFG::Node::hasHeapPrediction):
+        (JSC::DFG::Node::hasCellOperand):
+        * dfg/DFGNodeType.h:
+        * dfg/DFGOperations.cpp:
+        * dfg/DFGOperations.h:
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        * dfg/DFGSafeToExecute.h:
+        (JSC::DFG::safeToExecute):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileToObjectOrCallObjectConstructor):
+        (JSC::DFG::SpeculativeJIT::compileCallObjectConstructor): Deleted.
+        * dfg/DFGSpeculativeJIT.h:
+        (JSC::DFG::SpeculativeJIT::callOperation):
+        * 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::compileToObjectOrCallObjectConstructor):
+        (JSC::FTL::DFG::LowerDFGToB3::compileCallObjectConstructor): Deleted.
+        * jit/JIT.cpp:
+        (JSC::JIT::privateCompileMainPass):
+        (JSC::JIT::privateCompileSlowCases):
+        * jit/JIT.h:
+        * jit/JITOpcodes.cpp:
+        (JSC::JIT::emit_op_to_object):
+        (JSC::JIT::emitSlow_op_to_object):
+        * jit/JITOpcodes32_64.cpp:
+        (JSC::JIT::emit_op_to_object):
+        (JSC::JIT::emitSlow_op_to_object):
+        * jit/JITOperations.cpp:
+        * jit/JITOperations.h:
+        * llint/LowLevelInterpreter32_64.asm:
+        * llint/LowLevelInterpreter64.asm:
+        * runtime/CommonSlowPaths.cpp:
+        (JSC::SLOW_PATH_DECL):
+        * runtime/CommonSlowPaths.h:
+
 2017-11-01  Fujii Hironori  <[email protected]>
 
         Use LazyNeverDestroyed instead of DEFINE_GLOBAL

Modified: trunk/Source/_javascript_Core/builtins/ArrayConstructor.js (224279 => 224280)


--- trunk/Source/_javascript_Core/builtins/ArrayConstructor.js	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/Source/_javascript_Core/builtins/ArrayConstructor.js	2017-11-01 17:32:08 UTC (rev 224280)
@@ -52,8 +52,7 @@
         thisArg = @argument(2);
     }
 
-    if (items == null)
-        @throwTypeError("Array.from requires an array-like object - not null or undefined");
+    var arrayLike = @toObject(items, "Array.from requires an array-like object - not null or undefined");
 
     var iteratorMethod = items.@iteratorSymbol;
     if (iteratorMethod != null) {
@@ -83,7 +82,6 @@
         return result;
     }
 
-    var arrayLike = @Object(items);
     var arrayLikeLength = @toLength(arrayLike.length);
 
     var result = @isConstructor(thisObj) ? new thisObj(arrayLikeLength) : @newArrayWithSize(arrayLikeLength);

Modified: trunk/Source/_javascript_Core/builtins/ArrayPrototype.js (224279 => 224280)


--- trunk/Source/_javascript_Core/builtins/ArrayPrototype.js	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/Source/_javascript_Core/builtins/ArrayPrototype.js	2017-11-01 17:32:08 UTC (rev 224280)
@@ -41,10 +41,7 @@
 {
     "use strict";
 
-    if (this === null || this === @undefined)
-        @throwTypeError("Array.prototype.values requires that |this| not be null or undefined");
-
-    return new @createArrayIterator(@Object(this), "value", @arrayIteratorValueNext);
+    return new @createArrayIterator(@toObject(this, "Array.prototype.values requires that |this| not be null or undefined"), "value", @arrayIteratorValueNext);
 }
 
 function keys()
@@ -51,10 +48,7 @@
 {
     "use strict";
 
-    if (this === null || this === @undefined)
-        @throwTypeError("Array.prototype.keys requires that |this| not be null or undefined");
-
-    return new @createArrayIterator(@Object(this), "key", @arrayIteratorKeyNext);
+    return new @createArrayIterator(@toObject(this, "Array.prototype.keys requires that |this| not be null or undefined"), "key", @arrayIteratorKeyNext);
 }
 
 function entries()
@@ -61,10 +55,7 @@
 {
     "use strict";
 
-    if (this === null || this === @undefined)
-        @throwTypeError("Array.prototype.entries requires that |this| not be null or undefined");
-
-    return new @createArrayIterator(@Object(this), "key+value", @arrayIteratorKeyValueNext);
+    return new @createArrayIterator(@toObject(this, "Array.prototype.entries requires that |this| not be null or undefined"), "key+value", @arrayIteratorKeyValueNext);
 }
 
 function reduce(callback /*, initialValue */)
@@ -71,10 +62,7 @@
 {
     "use strict";
 
-    if (this === null || this === @undefined)
-        @throwTypeError("Array.prototype.reduce requires that |this| not be null or undefined");
-
-    var array = @Object(this);
+    var array = @toObject(this, "Array.prototype.reduce requires that |this| not be null or undefined");
     var length = @toLength(array.length);
 
     if (typeof callback !== "function")
@@ -107,10 +95,7 @@
 {
     "use strict";
 
-    if (this === null || this === @undefined)
-        @throwTypeError("Array.prototype.reduceRight requires that |this| not be null or undefined");
-
-    var array = @Object(this);
+    var array = @toObject(this, "Array.prototype.reduceRight requires that |this| not be null or undefined");
     var length = @toLength(array.length);
 
     if (typeof callback !== "function")
@@ -143,10 +128,7 @@
 {
     "use strict";
 
-    if (this === null || this === @undefined)
-        @throwTypeError("Array.prototype.every requires that |this| not be null or undefined");
-    
-    var array = @Object(this);
+    var array = @toObject(this, "Array.prototype.every requires that |this| not be null or undefined");
     var length = @toLength(array.length);
 
     if (typeof callback !== "function")
@@ -168,10 +150,7 @@
 {
     "use strict";
 
-    if (this === null || this === @undefined)
-        @throwTypeError("Array.prototype.forEach requires that |this| not be null or undefined");
-    
-    var array = @Object(this);
+    var array = @toObject(this, "Array.prototype.forEach requires that |this| not be null or undefined");
     var length = @toLength(array.length);
 
     if (typeof callback !== "function")
@@ -189,10 +168,7 @@
 {
     "use strict";
 
-    if (this === null || this === @undefined)
-        @throwTypeError("Array.prototype.filter requires that |this| not be null or undefined");
-    
-    var array = @Object(this);
+    var array = @toObject(this, "Array.prototype.filter requires that |this| not be null or undefined");
     var length = @toLength(array.length);
 
     if (typeof callback !== "function")
@@ -238,10 +214,7 @@
 {
     "use strict";
 
-    if (this === null || this === @undefined)
-        @throwTypeError("Array.prototype.map requires that |this| not be null or undefined");
-    
-    var array = @Object(this);
+    var array = @toObject(this, "Array.prototype.map requires that |this| not be null or undefined");
     var length = @toLength(array.length);
 
     if (typeof callback !== "function")
@@ -283,10 +256,7 @@
 {
     "use strict";
 
-    if (this === null || this === @undefined)
-        @throwTypeError("Array.prototype.some requires that |this| not be null or undefined");
-    
-    var array = @Object(this);
+    var array = @toObject(this, "Array.prototype.some requires that |this| not be null or undefined");
     var length = @toLength(array.length);
 
     if (typeof callback !== "function")
@@ -306,10 +276,7 @@
 {
     "use strict";
 
-    if (this === null || this === @undefined)
-        @throwTypeError("Array.prototype.fill requires that |this| not be null or undefined");
-
-    var array = @Object(this);
+    var array = @toObject(this, "Array.prototype.fill requires that |this| not be null or undefined");
     var length = @toLength(array.length);
 
     var relativeStart = @toInteger(@argument(1));
@@ -346,10 +313,7 @@
 {
     "use strict";
 
-    if (this === null || this === @undefined)
-        @throwTypeError("Array.prototype.find requires that |this| not be null or undefined");
-    
-    var array = @Object(this);
+    var array = @toObject(this, "Array.prototype.find requires that |this| not be null or undefined");
     var length = @toLength(array.length);
 
     if (typeof callback !== "function")
@@ -368,10 +332,7 @@
 {
     "use strict";
 
-    if (this === null || this === @undefined)
-        @throwTypeError("Array.prototype.findIndex requires that |this| not be null or undefined");
-    
-    var array = @Object(this);
+    var array = @toObject(this, "Array.prototype.findIndex requires that |this| not be null or undefined");
     var length = @toLength(array.length);
 
     if (typeof callback !== "function")
@@ -389,10 +350,7 @@
 {
     "use strict";
 
-    if (this === null || this === @undefined)
-        @throwTypeError("Array.prototype.includes requires that |this| not be null or undefined");
-
-    var array = @Object(this);
+    var array = @toObject(this, "Array.prototype.includes requires that |this| not be null or undefined");
     var length = @toLength(array.length);
 
     if (length === 0)
@@ -633,11 +591,8 @@
         bucketSort(array, 0, strings, 0);
     }
 
-    if (this === null || this === @undefined)
-        @throwTypeError("Array.prototype.sort requires that |this| not be null or undefined");
+    var array = @toObject(this, "Array.prototype.sort requires that |this| not be null or undefined");
 
-    var array = @Object(this);
-
     var length = array.length >>> 0;
 
     // For compatibility with Firefox and Chrome, do nothing observable
@@ -660,11 +615,8 @@
 {
     "use strict";
 
-    if (this === null || this === @undefined)
-        @throwTypeError("Array.prototype.concat requires that |this| not be null or undefined");
+    var currentElement = @toObject(this, "Array.prototype.concat requires that |this| not be null or undefined");
 
-    var currentElement = @Object(this);
-
     var constructor;
     if (@isArray(currentElement)) {
         constructor = currentElement.constructor;
@@ -750,10 +702,7 @@
         return (maybeNegativeZero < positive) ? maybeNegativeZero : positive;
     }
 
-    if (this === null || this === @undefined)
-        @throwTypeError("Array.copyWithin requires that |this| not be null or undefined");
-
-    var array = @Object(this);
+    var array = @toObject(this, "Array.prototype.copyWithin requires that |this| not be null or undefined");
     var length = @toLength(array.length);
 
     var relativeTarget = @toInteger(target);

Modified: trunk/Source/_javascript_Core/builtins/DatePrototype.js (224279 => 224280)


--- trunk/Source/_javascript_Core/builtins/DatePrototype.js	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/Source/_javascript_Core/builtins/DatePrototype.js	2017-11-01 17:32:08 UTC (rev 224280)
@@ -40,7 +40,7 @@
         else if (opts === null)
             @throwTypeError("null is not an object");
         else
-            options = @Object(opts);
+            options = @toObject(opts);
 
         // Check original instead of descendant to reduce lookups up the prototype chain.
         var needsDefaults = !options || (
@@ -97,7 +97,7 @@
         else if (opts === null)
             @throwTypeError("null is not an object");
         else
-            options = @Object(opts);
+            options = @toObject(opts);
 
         // Check original instead of descendant to reduce lookups up the prototype chain.
         var needsDefaults = !options || (
@@ -147,7 +147,7 @@
         else if (opts === null)
             @throwTypeError("null is not an object");
         else
-            options = @Object(opts);
+            options = @toObject(opts);
 
         // Check original instead of descendant to reduce lookups up the prototype chain.
         var needsDefaults = !options || (

Modified: trunk/Source/_javascript_Core/builtins/GlobalOperations.js (224279 => 224280)


--- trunk/Source/_javascript_Core/builtins/GlobalOperations.js	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/Source/_javascript_Core/builtins/GlobalOperations.js	2017-11-01 17:32:08 UTC (rev 224280)
@@ -90,7 +90,7 @@
     if (source == null) 
         return target;
 
-    let from = @Object(source); 
+    let from = @toObject(source);
     let keys = @Reflect.@ownKeys(from); 
     let keysLength = keys.length;
     for (let i = 0; i < keysLength; i++) {
@@ -115,7 +115,7 @@
     if (source == null) 
         return target;
 
-    let from = @Object(source); 
+    let from = @toObject(source);
     let keys = @Reflect.@ownKeys(from); 
     let keysLength = keys.length;
     for (let i = 0; i < keysLength; i++) {

Modified: trunk/Source/_javascript_Core/builtins/ObjectConstructor.js (224279 => 224280)


--- trunk/Source/_javascript_Core/builtins/ObjectConstructor.js	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/Source/_javascript_Core/builtins/ObjectConstructor.js	2017-11-01 17:32:08 UTC (rev 224280)
@@ -28,10 +28,7 @@
 {
     "use strict";
 
-    if (object == null)
-        @throwTypeError("Object.entries requires that input parameter not be null or undefined");
-
-    var obj = @Object(object);
+    var obj = @toObject(object, "Object.entries requires that input parameter not be null or undefined");
     var names = @getOwnPropertyNames(obj);
     var properties = [];
     for (var i = 0, length = names.length; i < length; ++i) {

Modified: trunk/Source/_javascript_Core/builtins/StringConstructor.js (224279 => 224280)


--- trunk/Source/_javascript_Core/builtins/StringConstructor.js	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/Source/_javascript_Core/builtins/StringConstructor.js	2017-11-01 17:32:08 UTC (rev 224280)
@@ -27,14 +27,9 @@
 {
     "use strict";
 
-    if (template === null || template === @undefined)
-        @throwTypeError("String.raw requires template not be null or undefined");
-    var cookedSegments = @Object(template);
+    var cookedSegments = @toObject(template, "String.raw requires template not be null or undefined");
 
-    var rawValue = cookedSegments.raw;
-    if (rawValue === null || rawValue === @undefined)
-        @throwTypeError("String.raw requires template.raw not be null or undefined");
-    var rawSegments = @Object(rawValue);
+    var rawSegments = @toObject(cookedSegments.raw, "String.raw requires template.raw not be null or undefined");
 
     var numberOfSubstitutions = arguments.length - 1;
 

Modified: trunk/Source/_javascript_Core/builtins/TypedArrayConstructor.js (224279 => 224280)


--- trunk/Source/_javascript_Core/builtins/TypedArrayConstructor.js	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/Source/_javascript_Core/builtins/TypedArrayConstructor.js	2017-11-01 17:32:08 UTC (rev 224280)
@@ -59,8 +59,7 @@
         thisArg = @argument(2);
     }
 
-    if (items == null)
-        @throwTypeError("TypedArray.from requires an array-like object - not null or undefined");
+    let arrayLike = @toObject(items, "TypedArray.from requires an array-like object - not null or undefined");
 
     let iteratorMethod = items.@iteratorSymbol;
     if (iteratorMethod != null) {
@@ -99,7 +98,6 @@
         return result;
     }
 
-    let arrayLike = @Object(items);
     let arrayLikeLength = @toLength(arrayLike.length);
 
     let constructFunction = this.@allocateTypedArray;

Modified: trunk/Source/_javascript_Core/builtins/TypedArrayPrototype.js (224279 => 224280)


--- trunk/Source/_javascript_Core/builtins/TypedArrayPrototype.js	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/Source/_javascript_Core/builtins/TypedArrayPrototype.js	2017-11-01 17:32:08 UTC (rev 224280)
@@ -339,7 +339,7 @@
     if (constructor === @undefined)
         result = new (@typedArrayGetOriginalConstructor(this))(length);
     else {
-        var speciesConstructor = @Object(constructor).@speciesSymbol;
+        var speciesConstructor = constructor.@speciesSymbol;
         if (speciesConstructor === null || speciesConstructor === @undefined)
             result = new (@typedArrayGetOriginalConstructor(this))(length);
         else {
@@ -380,7 +380,7 @@
     if (constructor === @undefined)
         result = new (@typedArrayGetOriginalConstructor(this))(resultLength);
     else {
-        var speciesConstructor = @Object(constructor).@speciesSymbol;
+        var speciesConstructor = constructor.@speciesSymbol;
         if (speciesConstructor === null || speciesConstructor === @undefined)
             result = new (@typedArrayGetOriginalConstructor(this))(resultLength);
         else {

Modified: trunk/Source/_javascript_Core/bytecode/BytecodeDumper.cpp (224279 => 224280)


--- trunk/Source/_javascript_Core/bytecode/BytecodeDumper.cpp	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeDumper.cpp	2017-11-01 17:32:08 UTC (rev 224280)
@@ -871,6 +871,13 @@
         printUnaryOp(out, location, it, "to_string");
         break;
     }
+    case op_to_object: {
+        printUnaryOp(out, location, it, "to_object");
+        int id0 = (++it)->u.operand;
+        out.printf(" %s", idName(id0, identifier(id0)).data());
+        dumpValueProfiling(out, it, hasPrintedProfiling);
+        break;
+    }
     case op_negate: {
         printUnaryOp(out, location, it, "negate");
         ++it; // op_negate has an extra operand for the ArithProfile.

Modified: trunk/Source/_javascript_Core/bytecode/BytecodeIntrinsicRegistry.h (224279 => 224280)


--- trunk/Source/_javascript_Core/bytecode/BytecodeIntrinsicRegistry.h	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeIntrinsicRegistry.h	2017-11-01 17:32:08 UTC (rev 224280)
@@ -57,6 +57,7 @@
     macro(putByValDirect) \
     macro(toNumber) \
     macro(toString) \
+    macro(toObject) \
     macro(newArrayWithSize) \
     macro(defineEnumerableWritableConfigurableDataProperty) \
 

Modified: trunk/Source/_javascript_Core/bytecode/BytecodeList.json (224279 => 224280)


--- trunk/Source/_javascript_Core/bytecode/BytecodeList.json	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeList.json	2017-11-01 17:32:08 UTC (rev 224280)
@@ -42,6 +42,7 @@
             { "name" : "op_dec", "length" : 2 },
             { "name" : "op_to_number", "length" : 4 },
             { "name" : "op_to_string", "length" : 3 },
+            { "name" : "op_to_object", "length" : 5 },
             { "name" : "op_negate", "length" : 4 },
             { "name" : "op_add", "length" : 5 },
             { "name" : "op_mul", "length" : 5 },

Modified: trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.h (224279 => 224280)


--- trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.h	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.h	2017-11-01 17:32:08 UTC (rev 224280)
@@ -193,6 +193,7 @@
     case op_is_function:
     case op_to_number:
     case op_to_string:
+    case op_to_object:
     case op_negate:
     case op_neq_null:
     case op_eq_null:
@@ -446,6 +447,7 @@
     case op_in:
     case op_to_number:
     case op_to_string:
+    case op_to_object:
     case op_negate:
     case op_add:
     case op_mul:

Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp (224279 => 224280)


--- trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2017-11-01 17:32:08 UTC (rev 224280)
@@ -576,6 +576,7 @@
         case op_get_by_val_with_this:
         case op_get_from_arguments:
         case op_to_number:
+        case op_to_object:
         case op_get_argument: {
             linkValueProfile(i, opLength);
             break;

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (224279 => 224280)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2017-11-01 17:32:08 UTC (rev 224280)
@@ -1686,6 +1686,16 @@
     return dst;
 }
 
+RegisterID* BytecodeGenerator::emitToObject(RegisterID* dst, RegisterID* src, const Identifier& message)
+{
+    UnlinkedValueProfile profile = ""
+    instructions().append(dst->index());
+    instructions().append(src->index());
+    instructions().append(addConstant(message));
+    instructions().append(profile);
+    return dst;
+}
+
 RegisterID* BytecodeGenerator::emitInc(RegisterID* srcDst)
 {
     emitOpcode(op_inc);

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h (224279 => 224280)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2017-11-01 17:32:08 UTC (rev 224280)
@@ -664,6 +664,7 @@
 
         RegisterID* emitToNumber(RegisterID* dst, RegisterID* src) { return emitUnaryOpProfiled(op_to_number, dst, src); }
         RegisterID* emitToString(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_to_string, dst, src); }
+        RegisterID* emitToObject(RegisterID* dst, RegisterID* src, const Identifier& message);
         RegisterID* emitInc(RegisterID* srcDst);
         RegisterID* emitDec(RegisterID* srcDst);
 

Modified: trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp (224279 => 224280)


--- trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2017-11-01 17:32:08 UTC (rev 224280)
@@ -1031,6 +1031,22 @@
     return generator.moveToDestinationIfNeeded(dst, generator.emitToString(generator.tempDestination(dst), src.get()));
 }
 
+RegisterID* BytecodeIntrinsicNode::emit_intrinsic_toObject(BytecodeGenerator& generator, RegisterID* dst)
+{
+    ArgumentListNode* node = m_args->m_listNode;
+    RefPtr<RegisterID> src = ""
+    node = node->m_next;
+
+    RefPtr<RegisterID> temp = generator.tempDestination(dst);
+    if (node) {
+        ASSERT(node->m_expr->isString());
+        const Identifier& message = static_cast<StringNode*>(node->m_expr)->value();
+        ASSERT(!node->m_next);
+        return generator.moveToDestinationIfNeeded(dst, generator.emitToObject(temp.get(), src.get(), message));
+    }
+    return generator.moveToDestinationIfNeeded(dst, generator.emitToObject(temp.get(), src.get(), generator.vm()->propertyNames->emptyIdentifier));
+}
+
 RegisterID* BytecodeIntrinsicNode::emit_intrinsic_idWithProfile(BytecodeGenerator& generator, RegisterID* dst)
 {
     ArgumentListNode* node = m_args->m_listNode;

Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (224279 => 224280)


--- trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2017-11-01 17:32:08 UTC (rev 224280)
@@ -2187,6 +2187,7 @@
         forNode(node).set(m_graph, node->structure());
         break;
 
+    case ToObject:
     case CallObjectConstructor: {
         AbstractValue& source = forNode(node->child1());
         AbstractValue& destination = forNode(node);
@@ -2197,6 +2198,8 @@
             break;
         }
 
+        if (node->op() == ToObject)
+            clobberWorld(node->origin.semantic, clobberLimit);
         forNode(node).setType(m_graph, SpecObject);
         break;
     }

Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (224279 => 224280)


--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2017-11-01 17:32:08 UTC (rev 224280)
@@ -3299,7 +3299,7 @@
         if (argumentCountIncludingThis <= 1)
             result = addToGraph(NewObject, OpInfo(m_graph.registerStructure(function->globalObject()->objectStructureForObjectConstructor())));
         else
-            result = addToGraph(CallObjectConstructor, get(virtualRegisterForArgument(1, registerOffset)));
+            result = addToGraph(CallObjectConstructor, OpInfo(m_graph.freeze(function->globalObject())), OpInfo(prediction), get(virtualRegisterForArgument(1, registerOffset)));
         set(VirtualRegister(resultOperand), result);
         return true;
     }
@@ -6069,6 +6069,14 @@
             NEXT_OPCODE(op_to_string);
         }
 
+        case op_to_object: {
+            SpeculatedType prediction = getPrediction();
+            Node* value = get(VirtualRegister(currentInstruction[2].u.operand));
+            unsigned identifierNumber = m_inlineStackTop->m_identifierRemap[currentInstruction[3].u.operand];
+            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(ToObject, OpInfo(identifierNumber), OpInfo(prediction), value));
+            NEXT_OPCODE(op_to_object);
+        }
+
         case op_in: {
             ArrayMode arrayMode = getArrayMode(currentInstruction[OPCODE_LENGTH(op_in) - 1].u.arrayProfile);
             set(VirtualRegister(currentInstruction[1].u.operand),

Modified: trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp (224279 => 224280)


--- trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp	2017-11-01 17:32:08 UTC (rev 224280)
@@ -228,6 +228,7 @@
     case op_typeof:
     case op_to_number:
     case op_to_string:
+    case op_to_object:
     case op_switch_imm:
     case op_switch_char:
     case op_in:

Modified: trunk/Source/_javascript_Core/dfg/DFGClobberize.h (224279 => 224280)


--- trunk/Source/_javascript_Core/dfg/DFGClobberize.h	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/Source/_javascript_Core/dfg/DFGClobberize.h	2017-11-01 17:32:08 UTC (rev 224280)
@@ -522,7 +522,16 @@
         write(HeapObjectCount);
         return;
 
+    case ToObject:
+        read(World);
+        write(Heap);
+        return;
+
     case CallObjectConstructor:
+        read(HeapObjectCount);
+        write(HeapObjectCount);
+        return;
+
     case ToThis:
     case CreateThis:
         read(MiscFields);

Modified: trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp (224279 => 224280)


--- trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp	2017-11-01 17:32:08 UTC (rev 224280)
@@ -301,6 +301,7 @@
     case CreateScopedArguments:
     case CreateClonedArguments:
     case CallObjectConstructor:
+    case ToObject:
     case ToThis:
     case CreateThis:
     case AllocatePropertyStorage:

Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (224279 => 224280)


--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2017-11-01 17:32:08 UTC (rev 224280)
@@ -1293,14 +1293,13 @@
             break;
         }
 
+        case ToObject: {
+            fixupToObject(node);
+            break;
+        }
+
         case CallObjectConstructor: {
-            if (node->child1()->shouldSpeculateObject()) {
-                fixEdge<ObjectUse>(node->child1());
-                node->convertToIdentity();
-                break;
-            }
-
-            fixEdge<UntypedUse>(node->child1());
+            fixupCallObjectConstructor(node);
             break;
         }
 
@@ -2509,6 +2508,72 @@
         fixEdge<UntypedUse>(node->child1());
         node->setResult(NodeResultJS);
     }
+
+    void fixupToObject(Node* node)
+    {
+        if (node->child1()->shouldSpeculateObject()) {
+            fixEdge<ObjectUse>(node->child1());
+            node->convertToIdentity();
+            return;
+        }
+
+        // ToObject(Null/Undefined) can throw an error. We can emit filters to convert ToObject to CallObjectConstructor.
+
+        JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
+
+        if (node->child1()->shouldSpeculateString()) {
+            insertCheck<StringUse>(node->child1().node());
+            fixEdge<KnownStringUse>(node->child1());
+            node->convertToNewStringObject(m_graph.registerStructure(globalObject->stringObjectStructure()));
+            return;
+        }
+
+        if (node->child1()->shouldSpeculateSymbol()) {
+            insertCheck<SymbolUse>(node->child1().node());
+            node->convertToCallObjectConstructor(m_graph.freeze(globalObject));
+            return;
+        }
+
+        if (node->child1()->shouldSpeculateNumber()) {
+            insertCheck<NumberUse>(node->child1().node());
+            node->convertToCallObjectConstructor(m_graph.freeze(globalObject));
+            return;
+        }
+
+        if (node->child1()->shouldSpeculateBoolean()) {
+            insertCheck<BooleanUse>(node->child1().node());
+            node->convertToCallObjectConstructor(m_graph.freeze(globalObject));
+            return;
+        }
+
+        fixEdge<UntypedUse>(node->child1());
+    }
+
+    void fixupCallObjectConstructor(Node* node)
+    {
+        if (node->child1()->shouldSpeculateObject()) {
+            fixEdge<ObjectUse>(node->child1());
+            node->convertToIdentity();
+            return;
+        }
+
+        if (node->child1()->shouldSpeculateString()) {
+            auto* globalObject = jsCast<JSGlobalObject*>(node->cellOperand()->cell());
+            insertCheck<StringUse>(node->child1().node());
+            fixEdge<KnownStringUse>(node->child1());
+            node->convertToNewStringObject(m_graph.registerStructure(globalObject->stringObjectStructure()));
+            return;
+        }
+
+        // While ToObject(Null/Undefined) throws an error, CallObjectConstructor(Null/Undefined) generates a new empty object.
+        if (node->child1()->shouldSpeculateOther()) {
+            insertCheck<OtherUse>(node->child1().node());
+            node->convertToNewObject(m_graph.registerStructure(jsCast<JSGlobalObject*>(node->cellOperand()->cell())->objectStructureForObjectConstructor()));
+            return;
+        }
+
+        fixEdge<UntypedUse>(node->child1());
+    }
     
     void fixupToStringOrCallStringConstructor(Node* node)
     {

Modified: trunk/Source/_javascript_Core/dfg/DFGNode.h (224279 => 224280)


--- trunk/Source/_javascript_Core/dfg/DFGNode.h	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/Source/_javascript_Core/dfg/DFGNode.h	2017-11-01 17:32:08 UTC (rev 224280)
@@ -718,6 +718,30 @@
         setOpAndDefaultFlags(GetGlobalThis);
         children.setChild1(Edge());
     }
+
+    void convertToCallObjectConstructor(FrozenValue* globalObject)
+    {
+        ASSERT(m_op == ToObject);
+        setOpAndDefaultFlags(CallObjectConstructor);
+        m_opInfo = globalObject;
+    }
+
+    void convertToNewStringObject(RegisteredStructure structure)
+    {
+        ASSERT(m_op == CallObjectConstructor || m_op == ToObject);
+        setOpAndDefaultFlags(NewStringObject);
+        m_opInfo = structure;
+        m_opInfo2 = OpInfoWrapper();
+    }
+
+    void convertToNewObject(RegisteredStructure structure)
+    {
+        ASSERT(m_op == CallObjectConstructor);
+        setOpAndDefaultFlags(NewObject);
+        children.reset();
+        m_opInfo = structure;
+        m_opInfo2 = OpInfoWrapper();
+    }
     
     void convertToDirectCall(FrozenValue*);
 
@@ -1003,6 +1027,7 @@
         case PutDynamicVar:
         case ResolveScopeForHoistingFuncDeclInEval:
         case ResolveScope:
+        case ToObject:
             return true;
         default:
             return false;
@@ -1578,6 +1603,8 @@
         case StringReplace:
         case StringReplaceRegExp:
         case ToNumber:
+        case ToObject:
+        case CallObjectConstructor:
         case LoadKeyFromMapBucket:
         case LoadValueFromMapBucket:
         case CallDOMGetter:
@@ -1643,6 +1670,7 @@
         case MaterializeCreateActivation:
         case NewRegexp:
         case CompareEqPtr:
+        case CallObjectConstructor:
         case DirectCall:
         case DirectTailCall:
         case DirectConstruct:

Modified: trunk/Source/_javascript_Core/dfg/DFGNodeType.h (224279 => 224280)


--- trunk/Source/_javascript_Core/dfg/DFGNodeType.h	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/Source/_javascript_Core/dfg/DFGNodeType.h	2017-11-01 17:32:08 UTC (rev 224280)
@@ -356,6 +356,7 @@
     macro(ToPrimitive, NodeResultJS | NodeMustGenerate) \
     macro(ToString, NodeResultJS | NodeMustGenerate) \
     macro(ToNumber, NodeResultJS | NodeMustGenerate) \
+    macro(ToObject, NodeResultJS | NodeMustGenerate) \
     macro(CallObjectConstructor, NodeResultJS) \
     macro(CallStringConstructor, NodeResultJS | NodeMustGenerate) \
     macro(NumberToStringWithRadix, NodeResultJS | NodeMustGenerate) \

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (224279 => 224280)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2017-11-01 17:32:08 UTC (rev 224280)
@@ -263,7 +263,7 @@
     return constructEmptyObject(exec);
 }
 
-JSCell* JIT_OPERATION operationObjectConstructor(ExecState* exec, JSGlobalObject* globalObject, EncodedJSValue encodedTarget)
+JSCell* JIT_OPERATION operationCallObjectConstructor(ExecState* exec, JSGlobalObject* globalObject, EncodedJSValue encodedTarget)
 {
     VM* vm = &exec->vm();
     NativeCallFrameTracer tracer(vm, exec);
@@ -276,6 +276,25 @@
     return value.toObject(exec, globalObject);
 }
 
+JSCell* JIT_OPERATION operationToObject(ExecState* exec, JSGlobalObject* globalObject, EncodedJSValue encodedTarget, UniquedStringImpl* errorMessage)
+{
+    VM* vm = &exec->vm();
+    NativeCallFrameTracer tracer(vm, exec);
+    auto scope = DECLARE_THROW_SCOPE(*vm);
+
+    JSValue value = JSValue::decode(encodedTarget);
+    ASSERT(!value.isObject());
+
+    if (UNLIKELY(value.isUndefinedOrNull())) {
+        if (errorMessage->length()) {
+            throwVMTypeError(exec, scope, errorMessage);
+            return nullptr;
+        }
+    }
+
+    return value.toObject(exec, globalObject);
+}
+
 EncodedJSValue JIT_OPERATION operationValueBitAnd(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
 {
     VM* vm = &exec->vm();

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.h (224279 => 224280)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.h	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.h	2017-11-01 17:32:08 UTC (rev 224280)
@@ -41,7 +41,8 @@
 EncodedJSValue JIT_OPERATION operationStringFromCharCodeUntyped(ExecState*, EncodedJSValue)  WTF_INTERNAL;
 
 // These routines provide callbacks out to C++ implementations of operations too complex to JIT.
-JSCell* JIT_OPERATION operationObjectConstructor(ExecState*, JSGlobalObject*, EncodedJSValue encodedTarget) WTF_INTERNAL;
+JSCell* JIT_OPERATION operationCallObjectConstructor(ExecState*, JSGlobalObject*, EncodedJSValue encodedTarget) WTF_INTERNAL;
+JSCell* JIT_OPERATION operationToObject(ExecState*, JSGlobalObject*, EncodedJSValue encodedTarget, UniquedStringImpl*) WTF_INTERNAL;
 JSCell* JIT_OPERATION operationCreateThis(ExecState*, JSObject* constructor, int32_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 (224279 => 224280)


--- trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2017-11-01 17:32:08 UTC (rev 224280)
@@ -720,6 +720,8 @@
         case LoadKeyFromMapBucket:
         case LoadValueFromMapBucket:
         case ToNumber:
+        case ToObject:
+        case CallObjectConstructor:
         case GetArgument:
         case CallDOMGetter:
         case GetDynamicVar:
@@ -857,10 +859,6 @@
         case CheckSubClass:
             break;
 
-        case CallObjectConstructor: {
-            setPrediction(SpecObject);
-            break;
-        }
         case SkipScope:
         case GetGlobalObject: {
             setPrediction(SpecObjectOther);

Modified: trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h (224279 => 224280)


--- trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h	2017-11-01 17:32:08 UTC (rev 224280)
@@ -314,6 +314,7 @@
     case ToPrimitive:
     case ToString:
     case ToNumber:
+    case ToObject:
     case NumberToStringWithRadix:
     case NumberToStringWithValidRadixConstant:
     case SetFunctionName:

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (224279 => 224280)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2017-11-01 17:32:08 UTC (rev 224280)
@@ -4088,9 +4088,10 @@
     blessedBooleanResult(resultGPR, node);
 }
 
-void SpeculativeJIT::compileCallObjectConstructor(Node* node)
+void SpeculativeJIT::compileToObjectOrCallObjectConstructor(Node* node)
 {
     RELEASE_ASSERT(node->child1().useKind() == UntypedUse);
+
     JSValueOperand value(this, node->child1());
 #if USE(JSVALUE64)
     GPRTemporary result(this, Reuse, value);
@@ -4106,7 +4107,11 @@
     slowCases.append(m_jit.branchIfNotObject(valueRegs.payloadGPR()));
     m_jit.move(valueRegs.payloadGPR(), resultGPR);
 
-    addSlowPathGenerator(slowPathCall(slowCases, this, operationObjectConstructor, resultGPR, m_jit.globalObjectFor(node->origin.semantic), valueRegs));
+    if (node->op() == ToObject)
+        addSlowPathGenerator(slowPathCall(slowCases, this, operationToObject, resultGPR, m_jit.graph().globalObjectFor(node->origin.semantic), valueRegs, identifierUID(node->identifierNumber())));
+    else
+        addSlowPathGenerator(slowPathCall(slowCases, this, operationCallObjectConstructor, resultGPR, TrustedImmPtr(node->cellOperand()), valueRegs));
+
     cellResult(resultGPR, node);
 }
 

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (224279 => 224280)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h	2017-11-01 17:32:08 UTC (rev 224280)
@@ -1189,6 +1189,12 @@
         return appendCallSetResult(operation, result);
     }
 
+    JITCompiler::Call callOperation(C_JITOperation_EGC operation, GPRReg result, TrustedImmPtr globalObject, GPRReg arg2)
+    {
+        m_jit.setupArgumentsWithExecState(globalObject, arg2);
+        return appendCallSetResult(operation, result);
+    }
+
     JITCompiler::Call callOperation(C_JITOperation_EGC operation, GPRReg result, JSGlobalObject* globalObject, GPRReg arg2)
     {
         m_jit.setupArgumentsWithExecState(TrustedImmPtr::weakPointer(m_jit.graph(), globalObject), arg2);
@@ -1682,17 +1688,33 @@
         return appendCallSetResult(operation, result);
     }
 
-    JITCompiler::Call callOperation(C_JITOperation_EGJ operation, GPRReg result, JSGlobalObject* globalObject, GPRReg arg1)
+    JITCompiler::Call callOperation(C_JITOperation_EGJ operation, GPRReg result, TrustedImmPtr globalObject, GPRReg arg1)
     {
-        m_jit.setupArgumentsWithExecState(TrustedImmPtr::weakPointer(m_jit.graph(), globalObject), arg1);
+        m_jit.setupArgumentsWithExecState(globalObject, arg1);
         return appendCallSetResult(operation, result);
     }
 
+    JITCompiler::Call callOperation(C_JITOperation_EGJ operation, GPRReg result, TrustedImmPtr globalObject, JSValueRegs arg1)
+    {
+        return callOperation(operation, result, globalObject, arg1.gpr());
+    }
+
+    JITCompiler::Call callOperation(C_JITOperation_EGJ operation, GPRReg result, JSGlobalObject* globalObject, GPRReg arg1)
+    {
+        return callOperation(operation, result, TrustedImmPtr::weakPointer(m_jit.graph(), globalObject), arg1);
+    }
+
     JITCompiler::Call callOperation(C_JITOperation_EGJ operation, GPRReg result, JSGlobalObject* globalObject, JSValueRegs arg1)
     {
         return callOperation(operation, result, globalObject, arg1.gpr());
     }
 
+    JITCompiler::Call callOperation(C_JITOperation_EGJI operation, GPRReg result, JSGlobalObject* globalObject, JSValueRegs arg1, UniquedStringImpl* arg2)
+    {
+        m_jit.setupArgumentsWithExecState(TrustedImmPtr::weakPointer(m_jit.graph(), globalObject), arg1.gpr(), TrustedImmPtr(arg2));
+        return appendCallSetResult(operation, result);
+    }
+
     JITCompiler::Call callOperation(C_JITOperation_EJ operation, GPRReg result, GPRReg arg1)
     {
         m_jit.setupArgumentsWithExecState(arg1);
@@ -2338,6 +2360,12 @@
         return appendCallSetResult(operation, result);
     }
 
+    JITCompiler::Call callOperation(C_JITOperation_EGJ operation, GPRReg result, TrustedImmPtr globalObject, JSValueRegs arg1)
+    {
+        m_jit.setupArgumentsWithExecState(globalObject, arg1.payloadGPR(), arg1.tagGPR());
+        return appendCallSetResult(operation, result);
+    }
+
     JITCompiler::Call callOperation(C_JITOperation_EGJ operation, GPRReg result, JSGlobalObject* globalObject, JSValueRegs arg1)
     {
         m_jit.setupArgumentsWithExecState(TrustedImmPtr::weakPointer(m_jit.graph(), globalObject), arg1.payloadGPR(), arg1.tagGPR());
@@ -2344,6 +2372,12 @@
         return appendCallSetResult(operation, result);
     }
 
+    JITCompiler::Call callOperation(C_JITOperation_EGJI operation, GPRReg result, JSGlobalObject* globalObject, JSValueRegs arg1, UniquedStringImpl* arg2)
+    {
+        m_jit.setupArgumentsWithExecState(TrustedImmPtr::weakPointer(m_jit.graph(), globalObject), arg1.payloadGPR(), arg1.tagGPR(), TrustedImmPtr(arg2));
+        return appendCallSetResult(operation, result);
+    }
+
     JITCompiler::Call callOperation(C_JITOperation_EJ operation, GPRReg result, JSValueRegs arg1)
     {
         m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1.payloadGPR(), arg1.tagGPR());
@@ -2975,7 +3009,7 @@
     void compileLazyJSConstant(Node*);
     void compileMaterializeNewObject(Node*);
     void compileRecordRegExpCachedResult(Node*);
-    void compileCallObjectConstructor(Node*);
+    void compileToObjectOrCallObjectConstructor(Node*);
     void compileResolveScope(Node*);
     void compileResolveScopeForHoistingFuncDeclInEval(Node*);
     void compileGetDynamicVar(Node*);

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (224279 => 224280)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2017-11-01 17:32:08 UTC (rev 224280)
@@ -4028,8 +4028,9 @@
         break;
     }
 
+    case ToObject:
     case CallObjectConstructor: {
-        compileCallObjectConstructor(node);
+        compileToObjectOrCallObjectConstructor(node);
         break;
     }
         

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (224279 => 224280)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2017-11-01 17:32:08 UTC (rev 224280)
@@ -4237,8 +4237,9 @@
         break;
     }
 
+    case ToObject:
     case CallObjectConstructor: {
-        compileCallObjectConstructor(node);
+        compileToObjectOrCallObjectConstructor(node);
         break;
     }
 

Modified: trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp (224279 => 224280)


--- trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp	2017-11-01 17:32:08 UTC (rev 224280)
@@ -180,6 +180,7 @@
     case GetArgumentCountIncludingThis:
     case ToNumber:
     case ToString:
+    case ToObject:
     case CallObjectConstructor:
     case CallStringConstructor:
     case MakeRope:

Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (224279 => 224280)


--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2017-11-01 17:32:08 UTC (rev 224280)
@@ -555,8 +555,9 @@
         case DFG::Check:
             compileNoOp();
             break;
+        case ToObject:
         case CallObjectConstructor:
-            compileCallObjectConstructor();
+            compileToObjectOrCallObjectConstructor();
             break;
         case ToThis:
             compileToThis();
@@ -1661,9 +1662,8 @@
         DFG_NODE_DO_TO_CHILDREN(m_graph, m_node, speculate);
     }
 
-    void compileCallObjectConstructor()
+    void compileToObjectOrCallObjectConstructor()
     {
-        JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
         LValue value = lowJSValue(m_node->child1());
 
         LBasicBlock isCellCase = m_out.newBlock();
@@ -1677,7 +1677,13 @@
         m_out.branch(isObject(value), usually(continuation), rarely(slowCase));
 
         m_out.appendTo(slowCase, continuation);
-        ValueFromBlock slowResult = m_out.anchor(vmCall(Int64, m_out.operation(operationObjectConstructor), m_callFrame, weakPointer(globalObject), value));
+
+        ValueFromBlock slowResult;
+        if (m_node->op() == ToObject) {
+            auto* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
+            slowResult = m_out.anchor(vmCall(Int64, m_out.operation(operationToObject), m_callFrame, weakPointer(globalObject), value, m_out.constIntPtr(m_graph.identifiers()[m_node->identifierNumber()])));
+        } else
+            slowResult = m_out.anchor(vmCall(Int64, m_out.operation(operationCallObjectConstructor), m_callFrame, frozenPointer(m_node->cellOperand()), value));
         m_out.jump(continuation);
 
         m_out.appendTo(continuation, lastNext);

Modified: trunk/Source/_javascript_Core/jit/JIT.cpp (224279 => 224280)


--- trunk/Source/_javascript_Core/jit/JIT.cpp	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/Source/_javascript_Core/jit/JIT.cpp	2017-11-01 17:32:08 UTC (rev 224280)
@@ -397,6 +397,7 @@
         DEFINE_OP(op_throw)
         DEFINE_OP(op_to_number)
         DEFINE_OP(op_to_string)
+        DEFINE_OP(op_to_object)
         DEFINE_OP(op_to_primitive)
 
         DEFINE_OP(op_resolve_scope)
@@ -532,6 +533,7 @@
         DEFINE_SLOWCASE_OP(op_sub)
         DEFINE_SLOWCASE_OP(op_to_number)
         DEFINE_SLOWCASE_OP(op_to_string)
+        DEFINE_SLOWCASE_OP(op_to_object)
         DEFINE_SLOWCASE_OP(op_to_primitive)
         DEFINE_SLOWCASE_OP(op_has_indexed_property)
         DEFINE_SLOWCASE_OP(op_has_structure_property)

Modified: trunk/Source/_javascript_Core/jit/JIT.h (224279 => 224280)


--- trunk/Source/_javascript_Core/jit/JIT.h	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/Source/_javascript_Core/jit/JIT.h	2017-11-01 17:32:08 UTC (rev 224280)
@@ -575,6 +575,7 @@
         void emit_op_throw(Instruction*);
         void emit_op_to_number(Instruction*);
         void emit_op_to_string(Instruction*);
+        void emit_op_to_object(Instruction*);
         void emit_op_to_primitive(Instruction*);
         void emit_op_unexpected_load(Instruction*);
         void emit_op_unsigned(Instruction*);
@@ -641,6 +642,7 @@
         void emitSlow_op_sub(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_to_number(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_to_string(Instruction*, Vector<SlowCaseEntry>::iterator&);
+        void emitSlow_op_to_object(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_to_primitive(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_unsigned(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_urshift(Instruction*, Vector<SlowCaseEntry>::iterator&);

Modified: trunk/Source/_javascript_Core/jit/JITOpcodes.cpp (224279 => 224280)


--- trunk/Source/_javascript_Core/jit/JITOpcodes.cpp	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/Source/_javascript_Core/jit/JITOpcodes.cpp	2017-11-01 17:32:08 UTC (rev 224280)
@@ -519,6 +519,20 @@
     emitPutVirtualRegister(currentInstruction[1].u.operand);
 }
 
+void JIT::emit_op_to_object(Instruction* currentInstruction)
+{
+    int dstVReg = currentInstruction[1].u.operand;
+    int srcVReg = currentInstruction[2].u.operand;
+    emitGetVirtualRegister(srcVReg, regT0);
+
+    addSlowCase(emitJumpIfNotJSCell(regT0));
+    addSlowCase(branch8(Below, Address(regT0, JSCell::typeInfoTypeOffset()), TrustedImm32(ObjectType)));
+
+    emitValueProfilingSite();
+    if (srcVReg != dstVReg)
+        emitPutVirtualRegister(dstVReg);
+}
+
 void JIT::emit_op_catch(Instruction* currentInstruction)
 {
     restoreCalleeSavesFromEntryFrameCalleeSavesBuffer(vm()->topEntryFrame);
@@ -900,6 +914,14 @@
     slowPathCall.call();
 }
 
+void JIT::emitSlow_op_to_object(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    linkAllSlowCases(iter);
+
+    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_to_object);
+    slowPathCall.call();
+}
+
 #endif // USE(JSVALUE64)
 
 void JIT::emit_op_loop_hint(Instruction*)

Modified: trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp (224279 => 224280)


--- trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp	2017-11-01 17:32:08 UTC (rev 224280)
@@ -723,6 +723,29 @@
     slowPathCall.call();
 }
 
+void JIT::emit_op_to_object(Instruction* currentInstruction)
+{
+    int dst = currentInstruction[1].u.operand;
+    int src = ""
+
+    emitLoad(src, regT1, regT0);
+
+    addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)));
+    addSlowCase(branch8(Below, Address(regT0, JSCell::typeInfoTypeOffset()), TrustedImm32(ObjectType)));
+
+    emitValueProfilingSite();
+    if (src != dst)
+        emitStore(dst, regT1, regT0);
+}
+
+void JIT::emitSlow_op_to_object(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    linkAllSlowCases(iter);
+
+    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_to_object);
+    slowPathCall.call();
+}
+
 void JIT::emit_op_catch(Instruction* currentInstruction)
 {
     restoreCalleeSavesFromEntryFrameCalleeSavesBuffer(vm()->topEntryFrame);

Modified: trunk/Source/_javascript_Core/jit/JITOperations.cpp (224279 => 224280)


--- trunk/Source/_javascript_Core/jit/JITOperations.cpp	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/Source/_javascript_Core/jit/JITOperations.cpp	2017-11-01 17:32:08 UTC (rev 224280)
@@ -2135,16 +2135,6 @@
     return newCallFrame;
 }
 
-EncodedJSValue JIT_OPERATION operationToObject(ExecState* exec, EncodedJSValue value)
-{
-    VM& vm = exec->vm();
-    NativeCallFrameTracer tracer(&vm, exec);
-    JSObject* obj = JSValue::decode(value).toObject(exec);
-    if (!obj)
-        return JSValue::encode(JSValue());
-    return JSValue::encode(obj);
-}
-
 char* JIT_OPERATION operationSwitchCharWithUnknownKeyType(ExecState* exec, EncodedJSValue encodedKey, size_t tableIndex)
 {
     VM& vm = exec->vm();

Modified: trunk/Source/_javascript_Core/jit/JITOperations.h (224279 => 224280)


--- trunk/Source/_javascript_Core/jit/JITOperations.h	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/Source/_javascript_Core/jit/JITOperations.h	2017-11-01 17:32:08 UTC (rev 224280)
@@ -188,6 +188,7 @@
 typedef JSCell* (JIT_OPERATION *C_JITOperation_ECC)(ExecState*, JSCell*, JSCell*);
 typedef JSCell* (JIT_OPERATION *C_JITOperation_EGC)(ExecState*, JSGlobalObject*, JSCell*);
 typedef JSCell* (JIT_OPERATION *C_JITOperation_EGJ)(ExecState*, JSGlobalObject*, EncodedJSValue);
+typedef JSCell* (JIT_OPERATION *C_JITOperation_EGJI)(ExecState*, JSGlobalObject*, EncodedJSValue, UniquedStringImpl*);
 typedef JSCell* (JIT_OPERATION *C_JITOperation_EIcf)(ExecState*, InlineCallFrame*);
 typedef JSCell* (JIT_OPERATION *C_JITOperation_EJ)(ExecState*, EncodedJSValue);
 typedef JSCell* (JIT_OPERATION *C_JITOperation_EJsc)(ExecState*, JSScope*);
@@ -439,7 +440,6 @@
 int32_t JIT_OPERATION operationSizeFrameForVarargs(ExecState*, EncodedJSValue arguments, int32_t numUsedStackSlots, int32_t firstVarArgOffset) WTF_INTERNAL;
 CallFrame* JIT_OPERATION operationSetupForwardArgumentsFrame(ExecState*, CallFrame*, EncodedJSValue, int32_t, int32_t length) WTF_INTERNAL;
 CallFrame* JIT_OPERATION operationSetupVarargsFrame(ExecState*, CallFrame*, EncodedJSValue arguments, int32_t firstVarArgOffset, int32_t length) WTF_INTERNAL;
-EncodedJSValue JIT_OPERATION operationToObject(ExecState*, EncodedJSValue) WTF_INTERNAL;
 
 char* JIT_OPERATION operationSwitchCharWithUnknownKeyType(ExecState*, EncodedJSValue key, size_t tableIndex) WTF_INTERNAL;
 char* JIT_OPERATION operationSwitchImmWithUnknownKeyType(ExecState*, EncodedJSValue key, size_t tableIndex) WTF_INTERNAL;

Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm (224279 => 224280)


--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm	2017-11-01 17:32:08 UTC (rev 224280)
@@ -944,6 +944,23 @@
     dispatch(constexpr op_to_string_length)
 
 
+_llint_op_to_object:
+    traceExecution()
+    loadi 8[PC], t0
+    loadi 4[PC], t1
+    loadConstantOrVariable(t0, t2, t3)
+    bineq t2, CellTag, .opToObjectSlow
+    bbb JSCell::m_type[t3], ObjectType, .opToObjectSlow
+    storei t2, TagOffset[cfr, t1, 8]
+    storei t3, PayloadOffset[cfr, t1, 8]
+    valueProfile(t2, t3, 16, t1)
+    dispatch(constexpr op_to_object_length)
+
+.opToObjectSlow:
+    callOpcodeSlowPath(_slow_path_to_object)
+    dispatch(constexpr op_to_object_length)
+
+
 _llint_op_negate:
     traceExecution()
     loadi 8[PC], t0

Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm (224279 => 224280)


--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm	2017-11-01 17:32:08 UTC (rev 224280)
@@ -847,6 +847,22 @@
     dispatch(constexpr op_to_string_length)
 
 
+_llint_op_to_object:
+    traceExecution()
+    loadisFromInstruction(2, t0)
+    loadisFromInstruction(1, t1)
+    loadConstantOrVariable(t0, t2)
+    btqnz t2, tagMask, .opToObjectSlow
+    bbb JSCell::m_type[t2], ObjectType, .opToObjectSlow
+    storeq t2, [cfr, t1, 8]
+    valueProfile(t2, 4, t0)
+    dispatch(constexpr op_to_object_length)
+
+.opToObjectSlow:
+    callOpcodeSlowPath(_slow_path_to_object)
+    dispatch(constexpr op_to_object_length)
+
+
 _llint_op_negate:
     traceExecution()
     loadisFromInstruction(2, t0)

Modified: trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp (224279 => 224280)


--- trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp	2017-11-01 17:32:08 UTC (rev 224280)
@@ -435,6 +435,19 @@
     RETURN_PROFILED(op_to_number, result);
 }
 
+SLOW_PATH_DECL(slow_path_to_object)
+{
+    BEGIN();
+    JSValue argument = OP_C(2).jsValue();
+    if (UNLIKELY(argument.isUndefinedOrNull())) {
+        const Identifier& ident = exec->codeBlock()->identifier(pc[3].u.operand);
+        if (!ident.isEmpty())
+            THROW(createTypeError(exec, ident.impl()));
+    }
+    JSObject* result = argument.toObject(exec);
+    RETURN_PROFILED(op_to_object, result);
+}
+
 SLOW_PATH_DECL(slow_path_add)
 {
     BEGIN();

Modified: trunk/Source/_javascript_Core/runtime/CommonSlowPaths.h (224279 => 224280)


--- trunk/Source/_javascript_Core/runtime/CommonSlowPaths.h	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/Source/_javascript_Core/runtime/CommonSlowPaths.h	2017-11-01 17:32:08 UTC (rev 224280)
@@ -234,6 +234,7 @@
 SLOW_PATH_HIDDEN_DECL(slow_path_dec);
 SLOW_PATH_HIDDEN_DECL(slow_path_to_number);
 SLOW_PATH_HIDDEN_DECL(slow_path_to_string);
+SLOW_PATH_HIDDEN_DECL(slow_path_to_object);
 SLOW_PATH_HIDDEN_DECL(slow_path_negate);
 SLOW_PATH_HIDDEN_DECL(slow_path_add);
 SLOW_PATH_HIDDEN_DECL(slow_path_mul);

Modified: trunk/Source/WebCore/ChangeLog (224279 => 224280)


--- trunk/Source/WebCore/ChangeLog	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/Source/WebCore/ChangeLog	2017-11-01 17:32:08 UTC (rev 224280)
@@ -1,3 +1,15 @@
+2017-11-01  Yusuke Suzuki  <[email protected]>
+
+        [JSC] Introduce @toObject
+        https://bugs.webkit.org/show_bug.cgi?id=178726
+
+        Reviewed by Saam Barati.
+
+        Use @isObject instead. It is more efficient.
+
+        * Modules/mediastream/NavigatorUserMedia.js:
+        (getUserMedia):
+
 2017-11-01  Commit Queue  <[email protected]>
 
         Unreviewed, rolling out r224273 and r224278.

Modified: trunk/Source/WebCore/Modules/mediastream/NavigatorUserMedia.js (224279 => 224280)


--- trunk/Source/WebCore/Modules/mediastream/NavigatorUserMedia.js	2017-11-01 16:28:17 UTC (rev 224279)
+++ trunk/Source/WebCore/Modules/mediastream/NavigatorUserMedia.js	2017-11-01 17:32:08 UTC (rev 224280)
@@ -37,7 +37,7 @@
     if (arguments.length < 3)
         @throwTypeError("Not enough arguments");
 
-    if (options !== @Object(options))
+    if (!@isObject(options))
         @throwTypeError("Argument 1 (options) to Navigator.getUserMedia must be an object");
 
     if (typeof successCallback !== "function")
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to