[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/JavaScriptCore:
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):
(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):
(JSC::DFG::capabilityLevel):
(JSC::DFG::clobberize):
(JSC::DFG::doesGC):
(JSC::DFG::FixupPhase::fixupNode):
(JSC::DFG::FixupPhase::fixupToObject):
(JSC::DFG::FixupPhase::fixupCallObjectConstructor):
(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.
(JSC::DFG::SpeculativeJIT::callOperation):
- dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
- dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
(JSC::FTL::canCompile):
(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileToObjectOrCallObjectConstructor):
(JSC::FTL::DFG::LowerDFGToB3::compileCallObjectConstructor): Deleted.
(JSC::JIT::privateCompileMainPass):
(JSC::JIT::privateCompileSlowCases):
- jit/JIT.h:
- jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_to_object):
(JSC::JIT::emitSlow_op_to_object):
(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):