Diff
Modified: trunk/JSTests/ChangeLog (232441 => 232442)
--- trunk/JSTests/ChangeLog 2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/JSTests/ChangeLog 2018-06-02 21:08:10 UTC (rev 232442)
@@ -1,3 +1,34 @@
+2018-06-02 Yusuke Suzuki <[email protected]>
+
+ [JSC] Object.create should have intrinsic
+ https://bugs.webkit.org/show_bug.cgi?id=186200
+
+ Reviewed by Filip Pizlo.
+
+ * microbenchmarks/object-create-null.js: Added.
+ (test):
+ * microbenchmarks/object-create-unknown-object-prototype.js: Added.
+ (test):
+ * microbenchmarks/object-create-untyped-prototype.js: Added.
+ (test):
+ * stress/get-by-pname-only-prototype-properties.js: Added.
+ (foo):
+ * stress/object-create-define.js: Added.
+ (shouldBe):
+ (test):
+ * stress/object-create-null-external.js: Added.
+ (shouldBe):
+ (test):
+ * stress/object-create-null.js: Added.
+ (shouldBe):
+ (test):
+ * stress/object-create-prototype.js: Added.
+ (shouldBe):
+ (test):
+ * stress/object-create-undefined.js: Added.
+ (shouldThrow):
+ (i.shouldThrow):
+
2018-06-02 Caio Lima <[email protected]>
[ESNext][BigInt] Implement support for addition operations
Added: trunk/JSTests/microbenchmarks/object-create-null.js (0 => 232442)
--- trunk/JSTests/microbenchmarks/object-create-null.js (rev 0)
+++ trunk/JSTests/microbenchmarks/object-create-null.js 2018-06-02 21:08:10 UTC (rev 232442)
@@ -0,0 +1,8 @@
+function test()
+{
+ return Object.create(null);
+}
+noInline(test);
+
+for (var i = 0; i < 1e6; ++i)
+ test();
Added: trunk/JSTests/microbenchmarks/object-create-unknown-object-prototype.js (0 => 232442)
--- trunk/JSTests/microbenchmarks/object-create-unknown-object-prototype.js (rev 0)
+++ trunk/JSTests/microbenchmarks/object-create-unknown-object-prototype.js 2018-06-02 21:08:10 UTC (rev 232442)
@@ -0,0 +1,18 @@
+function test(prototype)
+{
+ return Object.create(prototype);
+}
+noInline(test);
+
+var prototype1 = {};
+var prototype2 = [];
+var prototype3 = new Date();
+var prototype4 = { hello: 42 };
+var prototype5 = new Map();
+for (var i = 0; i < 1e5; ++i) {
+ test(prototype1);
+ test(prototype2);
+ test(prototype3);
+ test(prototype4);
+ test(prototype5);
+}
Added: trunk/JSTests/microbenchmarks/object-create-untyped-prototype.js (0 => 232442)
--- trunk/JSTests/microbenchmarks/object-create-untyped-prototype.js (rev 0)
+++ trunk/JSTests/microbenchmarks/object-create-untyped-prototype.js 2018-06-02 21:08:10 UTC (rev 232442)
@@ -0,0 +1,13 @@
+function test(prototype)
+{
+ return Object.create(prototype);
+}
+noInline(test);
+
+var prototype1 = {};
+var prototype2 = [];
+for (var i = 0; i < 1e5; ++i) {
+ test(prototype1);
+ test(prototype2);
+ test(null);
+}
Added: trunk/JSTests/stress/get-by-pname-only-prototype-properties.js (0 => 232442)
--- trunk/JSTests/stress/get-by-pname-only-prototype-properties.js (rev 0)
+++ trunk/JSTests/stress/get-by-pname-only-prototype-properties.js 2018-06-02 21:08:10 UTC (rev 232442)
@@ -0,0 +1,50 @@
+var foo = function (C, A) {
+ for(var B in (A||{})) {
+ C[B]=A[B];
+ }
+ return C;
+}
+
+var protos = [];
+for (var i = 0; i < 256; i++) {
+ var proto = Object.create(null);
+ protos.push(proto);
+ proto.aa = 1;
+ proto.ab = 1;
+ proto.ac = 1;
+ proto.ad = 1;
+ proto.ae = 1;
+ proto.af = 1;
+ proto.ag = 1;
+ proto.ah = 1;
+ proto.ai = 1;
+ proto.aj = 1;
+ proto.ak = 1;
+ proto.al = 1;
+ proto.am = 1;
+ proto.an = 1;
+ proto.ao = 1;
+ proto.ap = 1;
+ proto.aq = 1;
+ proto.ar = 1;
+ proto.as = 1;
+ proto.at = 1;
+ proto.au = 1;
+ proto.av = 1;
+ proto.aw = 1;
+ proto.ax = 1;
+ proto.ay = 1;
+ proto.az = 1;
+ proto.ba = 1;
+ proto.bb = 1;
+ proto.bc = 1;
+ proto.bd = 1;
+ proto.be = 1;
+ proto.bf = 1;
+ var weirdObject = Object.create(proto);
+ var result = foo({}, weirdObject);
+ for (var p in result) {
+ if (result[p] !== result["" + p])
+ throw new Error("OUT");
+ }
+}
Added: trunk/JSTests/stress/object-create-define.js (0 => 232442)
--- trunk/JSTests/stress/object-create-define.js (rev 0)
+++ trunk/JSTests/stress/object-create-define.js 2018-06-02 21:08:10 UTC (rev 232442)
@@ -0,0 +1,31 @@
+function shouldBe(actual, expected) {
+ if (actual !== expected)
+ throw new Error('bad value: ' + actual);
+}
+
+function test(prototype, data)
+{
+ return Object.create(prototype, data);
+}
+noInline(test);
+
+for (var i = 0; i < 1e4; ++i) {
+ var prototype = { Cocoa: false };
+ var object = test(prototype, {
+ Cappuccino: {
+ value: 42,
+ enumerable: true,
+ configurable: true,
+ writable: true
+ },
+ Matcha: {
+ value: 40,
+ enumerable: false,
+ configurable: true,
+ writable: true
+ }
+ });
+ shouldBe(Object.getPrototypeOf(object), prototype);
+ shouldBe(JSON.stringify(Object.getOwnPropertyNames(object).sort()), `["Cappuccino","Matcha"]`);
+ shouldBe(JSON.stringify(Object.keys(object).sort()), `["Cappuccino"]`);
+}
Added: trunk/JSTests/stress/object-create-null-external.js (0 => 232442)
--- trunk/JSTests/stress/object-create-null-external.js (rev 0)
+++ trunk/JSTests/stress/object-create-null-external.js 2018-06-02 21:08:10 UTC (rev 232442)
@@ -0,0 +1,16 @@
+function shouldBe(actual, expected) {
+ if (actual !== expected)
+ throw new Error('bad value: ' + actual);
+}
+
+function test(prototype)
+{
+ return Object.create(prototype);
+}
+noInline(test);
+
+for (var i = 0; i < 1e4; ++i) {
+ var object = test(null);
+ shouldBe(Object.getPrototypeOf(object), null);
+ shouldBe(JSON.stringify(Object.getOwnPropertyNames(object)), `[]`);
+}
Added: trunk/JSTests/stress/object-create-null.js (0 => 232442)
--- trunk/JSTests/stress/object-create-null.js (rev 0)
+++ trunk/JSTests/stress/object-create-null.js 2018-06-02 21:08:10 UTC (rev 232442)
@@ -0,0 +1,16 @@
+function shouldBe(actual, expected) {
+ if (actual !== expected)
+ throw new Error('bad value: ' + actual);
+}
+
+function test()
+{
+ return Object.create(null);
+}
+noInline(test);
+
+for (var i = 0; i < 1e4; ++i) {
+ var object = test();
+ shouldBe(Object.getPrototypeOf(object), null);
+ shouldBe(JSON.stringify(Object.getOwnPropertyNames(object)), `[]`);
+}
Added: trunk/JSTests/stress/object-create-prototype.js (0 => 232442)
--- trunk/JSTests/stress/object-create-prototype.js (rev 0)
+++ trunk/JSTests/stress/object-create-prototype.js 2018-06-02 21:08:10 UTC (rev 232442)
@@ -0,0 +1,17 @@
+function shouldBe(actual, expected) {
+ if (actual !== expected)
+ throw new Error('bad value: ' + actual);
+}
+
+function test(prototype)
+{
+ return Object.create(prototype);
+}
+noInline(test);
+
+for (var i = 0; i < 1e4; ++i) {
+ var prototype = { Cocoa: false };
+ var object = test(prototype);
+ shouldBe(Object.getPrototypeOf(object), prototype);
+ shouldBe(JSON.stringify(Object.getOwnPropertyNames(object)), `[]`);
+}
Added: trunk/JSTests/stress/object-create-undefined.js (0 => 232442)
--- trunk/JSTests/stress/object-create-undefined.js (rev 0)
+++ trunk/JSTests/stress/object-create-undefined.js 2018-06-02 21:08:10 UTC (rev 232442)
@@ -0,0 +1,26 @@
+function shouldThrow(func, errorMessage) {
+ var errorThrown = false;
+ var error = null;
+ try {
+ func();
+ } catch (e) {
+ errorThrown = true;
+ error = e;
+ }
+ if (!errorThrown)
+ throw new Error('not thrown');
+ if (String(error) !== errorMessage)
+ throw new Error(`bad error: ${String(error)}`);
+}
+
+function test(value)
+{
+ return Object.create(value);
+}
+noInline(test);
+
+for (var i = 0; i < 1e4; ++i) {
+ shouldThrow(() => {
+ test(undefined);
+ }, `TypeError: Object prototype may only be an Object or null.`);
+}
Modified: trunk/Source/_javascript_Core/ChangeLog (232441 => 232442)
--- trunk/Source/_javascript_Core/ChangeLog 2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/ChangeLog 2018-06-02 21:08:10 UTC (rev 232442)
@@ -1,3 +1,66 @@
+2018-06-02 Yusuke Suzuki <[email protected]>
+
+ [JSC] Object.create should have intrinsic
+ https://bugs.webkit.org/show_bug.cgi?id=186200
+
+ Reviewed by Filip Pizlo.
+
+ Object.create is used in various JS code. `Object.create(null)` is particularly used
+ to create empty plain object with null [[Prototype]]. We can find `Object.create(null)`
+ call in ARES-6/Babylon code.
+
+ This patch adds ObjectCreateIntrinsic to JSC. DFG recognizes it and produces ObjectCreate
+ DFG node. DFG AI and constant folding attempt to convert it to NewObject when prototype
+ object is null. It offers significant performance boost for `Object.create(null)`.
+
+ baseline patched
+
+ object-create-null 53.7940+-1.5297 ^ 19.8846+-0.6584 ^ definitely 2.7053x faster
+ object-create-unknown-object-prototype 38.9977+-1.1364 ^ 37.2207+-0.6143 ^ definitely 1.0477x faster
+ object-create-untyped-prototype 22.5632+-0.6917 22.2539+-0.6876 might be 1.0139x faster
+
+ * dfg/DFGAbstractInterpreterInlines.h:
+ (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::handleIntrinsicCall):
+ * dfg/DFGClobberize.h:
+ (JSC::DFG::clobberize):
+ * dfg/DFGConstantFoldingPhase.cpp:
+ (JSC::DFG::ConstantFoldingPhase::foldConstants):
+ * dfg/DFGDoesGC.cpp:
+ (JSC::DFG::doesGC):
+ * dfg/DFGFixupPhase.cpp:
+ (JSC::DFG::FixupPhase::fixupNode):
+ * dfg/DFGNode.h:
+ (JSC::DFG::Node::convertToNewObject):
+ * dfg/DFGNodeType.h:
+ * dfg/DFGOperations.cpp:
+ * dfg/DFGOperations.h:
+ * dfg/DFGPredictionPropagationPhase.cpp:
+ * dfg/DFGSafeToExecute.h:
+ (JSC::DFG::safeToExecute):
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::compileObjectCreate):
+ * dfg/DFGSpeculativeJIT.h:
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * ftl/FTLCapabilities.cpp:
+ (JSC::FTL::canCompile):
+ * ftl/FTLLowerDFGToB3.cpp:
+ (JSC::FTL::DFG::LowerDFGToB3::compileNode):
+ (JSC::FTL::DFG::LowerDFGToB3::compileObjectCreate):
+ * runtime/Intrinsic.cpp:
+ (JSC::intrinsicName):
+ * runtime/Intrinsic.h:
+ * runtime/JSGlobalObject.cpp:
+ (JSC::JSGlobalObject::init):
+ (JSC::JSGlobalObject::visitChildren):
+ * runtime/JSGlobalObject.h:
+ (JSC::JSGlobalObject::nullPrototypeObjectStructure const):
+ * runtime/ObjectConstructor.cpp:
+
2018-06-02 Caio Lima <[email protected]>
[ESNext][BigInt] Implement support for addition operations
Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (232441 => 232442)
--- trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2018-06-02 21:08:10 UTC (rev 232442)
@@ -2368,6 +2368,26 @@
setForNode(node, node->structure());
break;
+ case ObjectCreate: {
+ if (JSValue base = forNode(node->child1()).m_value) {
+ if (base.isNull()) {
+ JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
+ m_state.setFoundConstants(true);
+ if (node->child1().useKind() == UntypedUse)
+ didFoldClobberWorld();
+ setForNode(node, globalObject->nullPrototypeObjectStructure());
+ break;
+ }
+ // FIXME: We should get a structure for a constant prototype. We need to allow concurrent
+ // access to StructureCache from compiler threads.
+ // https://bugs.webkit.org/show_bug.cgi?id=186199
+ }
+ if (node->child1().useKind() == UntypedUse)
+ clobberWorld();
+ setTypeForNode(node, SpecFinalObject);
+ break;
+ }
+
case ToObject:
case CallObjectConstructor: {
AbstractValue& source = forNode(node->child1());
Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (232441 => 232442)
--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2018-06-02 21:08:10 UTC (rev 232442)
@@ -2642,6 +2642,15 @@
return true;
}
+ case ObjectCreateIntrinsic: {
+ if (argumentCountIncludingThis != 2)
+ return false;
+
+ insertChecks();
+ set(VirtualRegister(resultOperand), addToGraph(ObjectCreate, get(virtualRegisterForArgument(1, registerOffset))));
+ return true;
+ }
+
case ObjectGetPrototypeOfIntrinsic: {
if (argumentCountIncludingThis != 2)
return false;
Modified: trunk/Source/_javascript_Core/dfg/DFGClobberize.h (232441 => 232442)
--- trunk/Source/_javascript_Core/dfg/DFGClobberize.h 2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/dfg/DFGClobberize.h 2018-06-02 21:08:10 UTC (rev 232442)
@@ -1489,6 +1489,23 @@
return;
}
+ case ObjectCreate: {
+ switch (node->child1().useKind()) {
+ case ObjectUse:
+ read(HeapObjectCount);
+ write(HeapObjectCount);
+ return;
+ case UntypedUse:
+ read(World);
+ write(Heap);
+ return;
+ default:
+ RELEASE_ASSERT_NOT_REACHED();
+ return;
+ }
+ }
+
+
case NewObject:
case NewRegexp:
case NewStringObject:
Modified: trunk/Source/_javascript_Core/dfg/DFGConstantFoldingPhase.cpp (232441 => 232442)
--- trunk/Source/_javascript_Core/dfg/DFGConstantFoldingPhase.cpp 2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/dfg/DFGConstantFoldingPhase.cpp 2018-06-02 21:08:10 UTC (rev 232442)
@@ -737,6 +737,21 @@
break;
}
+ case ObjectCreate: {
+ if (JSValue base = m_state.forNode(node->child1()).m_value) {
+ if (base.isNull()) {
+ JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
+ node->convertToNewObject(m_graph.registerStructure(globalObject->nullPrototypeObjectStructure()));
+ changed = true;
+ break;
+ }
+ // FIXME: We should get a structure for a constant prototype. We need to allow concurrent
+ // access to StructureCache from compiler threads.
+ // https://bugs.webkit.org/show_bug.cgi?id=186199
+ }
+ break;
+ }
+
case ToNumber: {
if (m_state.forNode(node->child1()).m_type & ~SpecBytecodeNumber)
break;
Modified: trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp (232441 => 232442)
--- trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp 2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp 2018-06-02 21:08:10 UTC (rev 232442)
@@ -324,6 +324,7 @@
case ToObject:
case ToThis:
case CreateThis:
+ case ObjectCreate:
case AllocatePropertyStorage:
case ReallocatePropertyStorage:
case Arrayify:
Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (232441 => 232442)
--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2018-06-02 21:08:10 UTC (rev 232442)
@@ -1446,6 +1446,15 @@
break;
}
+ case ObjectCreate: {
+ if (node->child1()->shouldSpeculateObject()) {
+ fixEdge<ObjectUse>(node->child1());
+ node->clearFlags(NodeMustGenerate);
+ break;
+ }
+ break;
+ }
+
case CheckStringIdent: {
fixEdge<StringIdentUse>(node->child1());
break;
Modified: trunk/Source/_javascript_Core/dfg/DFGNode.h (232441 => 232442)
--- trunk/Source/_javascript_Core/dfg/DFGNode.h 2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/dfg/DFGNode.h 2018-06-02 21:08:10 UTC (rev 232442)
@@ -733,7 +733,7 @@
void convertToNewObject(RegisteredStructure structure)
{
- ASSERT(m_op == CallObjectConstructor || m_op == CreateThis);
+ ASSERT(m_op == CallObjectConstructor || m_op == CreateThis || m_op == ObjectCreate);
setOpAndDefaultFlags(NewObject);
children.reset();
m_opInfo = structure;
Modified: trunk/Source/_javascript_Core/dfg/DFGNodeType.h (232441 => 232442)
--- trunk/Source/_javascript_Core/dfg/DFGNodeType.h 2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/dfg/DFGNodeType.h 2018-06-02 21:08:10 UTC (rev 232442)
@@ -255,6 +255,7 @@
macro(CheckSubClass, NodeMustGenerate) \
macro(ParseInt, NodeMustGenerate | NodeResultJS) \
macro(GetPrototypeOf, NodeMustGenerate | NodeResultJS) \
+ macro(ObjectCreate, NodeMustGenerate | NodeResultJS) \
\
/* Atomics object functions. */\
macro(AtomicsAdd, NodeResultJS | NodeMustGenerate | NodeHasVarArgs) \
Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (232441 => 232442)
--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp 2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp 2018-06-02 21:08:10 UTC (rev 232442)
@@ -248,6 +248,34 @@
return JSValue::encode(JSValue::decode(encodedOp).toThis(exec, StrictMode));
}
+JSCell* JIT_OPERATION operationObjectCreate(ExecState* exec, EncodedJSValue encodedPrototype)
+{
+ VM& vm = exec->vm();
+ NativeCallFrameTracer tracer(&vm, exec);
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ JSValue prototype = JSValue::decode(encodedPrototype);
+
+ if (!prototype.isObject() && !prototype.isNull()) {
+ throwVMTypeError(exec, scope, ASCIILiteral("Object prototype may only be an Object or null."));
+ return nullptr;
+ }
+
+ if (prototype.isObject()) {
+ scope.release();
+ return constructEmptyObject(exec, asObject(prototype));
+ }
+ scope.release();
+ return constructEmptyObject(exec, exec->lexicalGlobalObject()->nullPrototypeObjectStructure());
+}
+
+JSCell* JIT_OPERATION operationObjectCreateObject(ExecState* exec, JSObject* prototype)
+{
+ VM& vm = exec->vm();
+ NativeCallFrameTracer tracer(&vm, exec);
+ return constructEmptyObject(exec, prototype);
+}
+
JSCell* JIT_OPERATION operationCreateThis(ExecState* exec, JSObject* constructor, uint32_t inlineCapacity)
{
VM& vm = exec->vm();
Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.h (232441 => 232442)
--- trunk/Source/_javascript_Core/dfg/DFGOperations.h 2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.h 2018-06-02 21:08:10 UTC (rev 232442)
@@ -43,6 +43,8 @@
// These routines provide callbacks out to C++ implementations of operations too complex to JIT.
JSCell* JIT_OPERATION operationCallObjectConstructor(ExecState*, JSGlobalObject*, EncodedJSValue encodedTarget) WTF_INTERNAL;
JSCell* JIT_OPERATION operationToObject(ExecState*, JSGlobalObject*, EncodedJSValue encodedTarget, UniquedStringImpl*) WTF_INTERNAL;
+JSCell* JIT_OPERATION operationObjectCreate(ExecState*, EncodedJSValue) WTF_INTERNAL;
+JSCell* JIT_OPERATION operationObjectCreateObject(ExecState*, JSObject*) WTF_INTERNAL;
JSCell* JIT_OPERATION operationCreateThis(ExecState*, JSObject* constructor, uint32_t inlineCapacity) WTF_INTERNAL;
EncodedJSValue JIT_OPERATION operationToThis(ExecState*, EncodedJSValue encodedOp1) WTF_INTERNAL;
EncodedJSValue JIT_OPERATION operationToThisStrict(ExecState*, EncodedJSValue encodedOp1) WTF_INTERNAL;
Modified: trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp (232441 => 232442)
--- trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp 2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp 2018-06-02 21:08:10 UTC (rev 232442)
@@ -906,6 +906,7 @@
break;
}
+ case ObjectCreate:
case CreateThis:
case NewObject: {
setPrediction(SpecFinalObject);
Modified: trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h (232441 => 232442)
--- trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h 2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h 2018-06-02 21:08:10 UTC (rev 232442)
@@ -171,6 +171,7 @@
case IdentityWithProfile:
case ToThis:
case CreateThis:
+ case ObjectCreate:
case GetCallee:
case SetCallee:
case GetArgumentCountIncludingThis:
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (232441 => 232442)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2018-06-02 21:08:10 UTC (rev 232442)
@@ -12172,6 +12172,47 @@
jsValueResult(tempRegs, node);
}
+void SpeculativeJIT::compileObjectCreate(Node* node)
+{
+ switch (node->child1().useKind()) {
+ case ObjectUse: {
+ SpeculateCellOperand prototype(this, node->child1());
+
+ GPRReg prototypeGPR = prototype.gpr();
+
+ speculateObject(node->child1(), prototypeGPR);
+
+ flushRegisters();
+ GPRFlushedCallResult result(this);
+ GPRReg resultGPR = result.gpr();
+ callOperation(operationObjectCreateObject, resultGPR, prototypeGPR);
+ m_jit.exceptionCheck();
+
+ cellResult(resultGPR, node);
+ break;
+ }
+
+ case UntypedUse: {
+ JSValueOperand prototype(this, node->child1());
+
+ JSValueRegs prototypeRegs = prototype.jsValueRegs();
+
+ flushRegisters();
+ GPRFlushedCallResult result(this);
+ GPRReg resultGPR = result.gpr();
+ callOperation(operationObjectCreate, resultGPR, prototypeRegs);
+ m_jit.exceptionCheck();
+
+ cellResult(resultGPR, node);
+ break;
+ }
+
+ default:
+ RELEASE_ASSERT_NOT_REACHED();
+ break;
+ }
+}
+
void SpeculativeJIT::compileCreateThis(Node* node)
{
// Note that there is not so much profit to speculate here. The only things we
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (232441 => 232442)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2018-06-02 21:08:10 UTC (rev 232442)
@@ -1472,6 +1472,7 @@
void compileNewArrayWithSize(Node*);
void compileNewTypedArray(Node*);
void compileToThis(Node*);
+ void compileObjectCreate(Node*);
void compileCreateThis(Node*);
void compileNewObject(Node*);
void compileToPrimitive(Node*);
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (232441 => 232442)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2018-06-02 21:08:10 UTC (rev 232442)
@@ -3132,6 +3132,11 @@
break;
}
+ case ObjectCreate: {
+ compileObjectCreate(node);
+ break;
+ }
+
case CreateThis: {
compileCreateThis(node);
break;
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (232441 => 232442)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2018-06-02 21:08:10 UTC (rev 232442)
@@ -3382,6 +3382,11 @@
break;
}
+ case ObjectCreate: {
+ compileObjectCreate(node);
+ break;
+ }
+
case CreateThis: {
compileCreateThis(node);
break;
Modified: trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp (232441 => 232442)
--- trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp 2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp 2018-06-02 21:08:10 UTC (rev 232442)
@@ -191,6 +191,7 @@
case ToObject:
case CallObjectConstructor:
case CallStringConstructor:
+ case ObjectCreate:
case MakeRope:
case NewArrayWithSize:
case TryGetById:
Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (232441 => 232442)
--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2018-06-02 21:08:10 UTC (rev 232442)
@@ -838,6 +838,9 @@
case CreateClonedArguments:
compileCreateClonedArguments();
break;
+ case ObjectCreate:
+ compileObjectCreate();
+ break;
case NewObject:
compileNewObject();
break;
@@ -5353,6 +5356,21 @@
m_out.appendTo(continuation, lastNext);
setInt32(m_out.phi(Int32, zeroLengthResult, nonZeroLengthResult));
}
+
+ void compileObjectCreate()
+ {
+ switch (m_node->child1().useKind()) {
+ case ObjectUse:
+ setJSValue(vmCall(Int64, m_out.operation(operationObjectCreateObject), m_callFrame, lowObject(m_node->child1())));
+ break;
+ case UntypedUse:
+ setJSValue(vmCall(Int64, m_out.operation(operationObjectCreate), m_callFrame, lowJSValue(m_node->child1())));
+ break;
+ default:
+ RELEASE_ASSERT_NOT_REACHED();
+ break;
+ }
+ }
void compileNewObject()
{
Modified: trunk/Source/_javascript_Core/runtime/Intrinsic.cpp (232441 => 232442)
--- trunk/Source/_javascript_Core/runtime/Intrinsic.cpp 2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/runtime/Intrinsic.cpp 2018-06-02 21:08:10 UTC (rev 232442)
@@ -113,6 +113,8 @@
return "RegExpTestFastIntrinsic";
case RegExpMatchFastIntrinsic:
return "RegExpMatchFastIntrinsic";
+ case ObjectCreateIntrinsic:
+ return "ObjectCreateIntrinsic";
case ObjectGetPrototypeOfIntrinsic:
return "ObjectGetPrototypeOfIntrinsic";
case ObjectIsIntrinsic:
Modified: trunk/Source/_javascript_Core/runtime/Intrinsic.h (232441 => 232442)
--- trunk/Source/_javascript_Core/runtime/Intrinsic.h 2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/runtime/Intrinsic.h 2018-06-02 21:08:10 UTC (rev 232442)
@@ -69,6 +69,7 @@
RegExpTestIntrinsic,
RegExpTestFastIntrinsic,
RegExpMatchFastIntrinsic,
+ ObjectCreateIntrinsic,
ObjectGetPrototypeOfIntrinsic,
ObjectIsIntrinsic,
ReflectGetPrototypeOfIntrinsic,
Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp (232441 => 232442)
--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp 2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp 2018-06-02 21:08:10 UTC (rev 232442)
@@ -537,10 +537,7 @@
init.set(JSWithScope::createStructure(init.vm, init.owner, jsNull()));
});
- m_nullPrototypeObjectStructure.initLater(
- [] (const Initializer<Structure>& init) {
- init.set(JSFinalObject::createStructure(init.vm, init.owner, jsNull(), JSFinalObject::defaultInlineCapacity()));
- });
+ m_nullPrototypeObjectStructure.set(vm, this, JSFinalObject::createStructure(vm, this, jsNull(), JSFinalObject::defaultInlineCapacity()));
m_callbackFunctionStructure.initLater(
[] (const Initializer<Structure>& init) {
@@ -1394,7 +1391,7 @@
thisObject->m_glibCallbackFunctionStructure.visit(visitor);
thisObject->m_glibWrapperObjectStructure.visit(visitor);
#endif
- thisObject->m_nullPrototypeObjectStructure.visit(visitor);
+ visitor.append(thisObject->m_nullPrototypeObjectStructure);
visitor.append(thisObject->m_errorStructure);
visitor.append(thisObject->m_calleeStructure);
visitor.append(thisObject->m_strictFunctionStructure);
Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.h (232441 => 232442)
--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.h 2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.h 2018-06-02 21:08:10 UTC (rev 232442)
@@ -339,7 +339,7 @@
LazyProperty<JSGlobalObject, Structure> m_glibCallbackFunctionStructure;
LazyProperty<JSGlobalObject, Structure> m_glibWrapperObjectStructure;
#endif
- LazyProperty<JSGlobalObject, Structure> m_nullPrototypeObjectStructure;
+ WriteBarrier<Structure> m_nullPrototypeObjectStructure;
WriteBarrier<Structure> m_calleeStructure;
WriteBarrier<Structure> m_strictFunctionStructure;
WriteBarrier<Structure> m_arrowFunctionStructure;
@@ -654,7 +654,7 @@
Structure* glibWrapperObjectStructure() const { return m_glibWrapperObjectStructure.get(this); }
#endif
Structure* dateStructure() const { return m_dateStructure.get(this); }
- Structure* nullPrototypeObjectStructure() const { return m_nullPrototypeObjectStructure.get(this); }
+ Structure* nullPrototypeObjectStructure() const { return m_nullPrototypeObjectStructure.get(); }
Structure* errorStructure() const { return m_errorStructure.get(); }
Structure* calleeStructure() const { return m_calleeStructure.get(); }
Structure* strictFunctionStructure() const { return m_strictFunctionStructure.get(); }
Modified: trunk/Source/_javascript_Core/runtime/ObjectConstructor.cpp (232441 => 232442)
--- trunk/Source/_javascript_Core/runtime/ObjectConstructor.cpp 2018-06-02 17:43:29 UTC (rev 232441)
+++ trunk/Source/_javascript_Core/runtime/ObjectConstructor.cpp 2018-06-02 21:08:10 UTC (rev 232442)
@@ -76,7 +76,7 @@
keys objectConstructorKeys DontEnum|Function 1
defineProperty objectConstructorDefineProperty DontEnum|Function 3
defineProperties objectConstructorDefineProperties DontEnum|Function 2
- create objectConstructorCreate DontEnum|Function 2
+ create objectConstructorCreate DontEnum|Function 2 ObjectCreateIntrinsic
seal objectConstructorSeal DontEnum|Function 1
freeze objectConstructorFreeze DontEnum|Function 1
preventExtensions objectConstructorPreventExtensions DontEnum|Function 1