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