WebKit Bugzilla
Attachment 341769 Details for
Bug 186200
: [JSC] Object.create should have intrinsic
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-186200-20180602021820.patch (text/plain), 28.02 KB, created by
Yusuke Suzuki
on 2018-06-01 10:18:21 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Yusuke Suzuki
Created:
2018-06-01 10:18:21 PDT
Size:
28.02 KB
patch
obsolete
>Subversion Revision: 232398 >diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog >index 526c31e0643e24ea94ca005e3c77e9d62f17acef..11ca178af3c4498b841cb623dcb92a20f511e8d8 100644 >--- a/Source/JavaScriptCore/ChangeLog >+++ b/Source/JavaScriptCore/ChangeLog >@@ -1,3 +1,61 @@ >+2018-06-01 Yusuke Suzuki <utatane.tea@gmail.com> >+ >+ [JSC] Object.create should have intrinsic >+ https://bugs.webkit.org/show_bug.cgi?id=186200 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ 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/ObjectConstructor.cpp: >+ > 2018-05-31 Yusuke Suzuki <utatane.tea@gmail.com> > > [Baseline] Store constant directly in emit_op_mov >diff --git a/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h b/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h >index d490d421b0e8ed2ba6629a462660a251b10a6692..28af100372ae1f19f1f45c2b1c20025cde7649c6 100644 >--- a/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h >+++ b/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h >@@ -2368,6 +2368,24 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi > 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); >+ 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 >+ } >+ clobberWorld(); >+ setTypeForNode(node, SpecFinalObject); >+ break; >+ } >+ > case ToObject: > case CallObjectConstructor: { > AbstractValue& source = forNode(node->child1()); >diff --git a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp >index bbac6cc65420f31d1f2ec419d3e777f02394c5d8..70ab2bb4ffc3a5108f025632c4e1a01bf29f55e3 100644 >--- a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp >+++ b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp >@@ -2641,6 +2641,15 @@ bool ByteCodeParser::handleIntrinsicCall(Node* callee, int resultOperand, Intrin > 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; >diff --git a/Source/JavaScriptCore/dfg/DFGClobberize.h b/Source/JavaScriptCore/dfg/DFGClobberize.h >index f781b15987ba04278333f848811e1a6c5c788d20..0483cdcf66abf571d52cefd2161236adb2679f27 100644 >--- a/Source/JavaScriptCore/dfg/DFGClobberize.h >+++ b/Source/JavaScriptCore/dfg/DFGClobberize.h >@@ -1489,6 +1489,7 @@ void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu > return; > } > >+ case ObjectCreate: > case NewObject: > case NewRegexp: > case NewStringObject: >diff --git a/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp b/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp >index 99976e00254c7ba5f7900dcc59c4fce6358ca805..74cf85d2f9e630867117220f7680ab8012724e51 100644 >--- a/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp >+++ b/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp >@@ -737,6 +737,21 @@ class ConstantFoldingPhase : public Phase { > 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; >diff --git a/Source/JavaScriptCore/dfg/DFGDoesGC.cpp b/Source/JavaScriptCore/dfg/DFGDoesGC.cpp >index e08d21ae4e123be93399d693512e6c561f9985b6..20bffecc9bc239ae686af197daf7eb27016b5c84 100644 >--- a/Source/JavaScriptCore/dfg/DFGDoesGC.cpp >+++ b/Source/JavaScriptCore/dfg/DFGDoesGC.cpp >@@ -324,6 +324,7 @@ bool doesGC(Graph& graph, Node* node) > case ToObject: > case ToThis: > case CreateThis: >+ case ObjectCreate: > case AllocatePropertyStorage: > case ReallocatePropertyStorage: > case Arrayify: >diff --git a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp >index cd73ce298adcd726349a700c6cbbb59755ffe17e..babbccf4b98cbb6d939733162e4704b1b814f48c 100644 >--- a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp >+++ b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp >@@ -1446,6 +1446,14 @@ class FixupPhase : public Phase { > break; > } > >+ case ObjectCreate: { >+ if (node->child1()->shouldSpeculateObject()) { >+ fixEdge<ObjectUse>(node->child1()); >+ break; >+ } >+ break; >+ } >+ > case CheckStringIdent: { > fixEdge<StringIdentUse>(node->child1()); > break; >diff --git a/Source/JavaScriptCore/dfg/DFGNode.h b/Source/JavaScriptCore/dfg/DFGNode.h >index 10b51fef423e28ec69c81434d781df714a1b0344..eee5e773be4b2f6ccade245be9ec7f3453af969a 100644 >--- a/Source/JavaScriptCore/dfg/DFGNode.h >+++ b/Source/JavaScriptCore/dfg/DFGNode.h >@@ -733,7 +733,7 @@ struct Node { > > 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; >diff --git a/Source/JavaScriptCore/dfg/DFGNodeType.h b/Source/JavaScriptCore/dfg/DFGNodeType.h >index 52b7bb9f82896ea46ffb129f5b49293d64eff316..fc12306a0499b09ce609c13d0c4be769dbe9bff9 100644 >--- a/Source/JavaScriptCore/dfg/DFGNodeType.h >+++ b/Source/JavaScriptCore/dfg/DFGNodeType.h >@@ -255,6 +255,7 @@ namespace JSC { namespace DFG { > macro(CheckSubClass, NodeMustGenerate) \ > macro(ParseInt, NodeMustGenerate | NodeResultJS) \ > macro(GetPrototypeOf, NodeMustGenerate | NodeResultJS) \ >+ macro(ObjectCreate, NodeResultJS) \ > \ > /* Atomics object functions. */\ > macro(AtomicsAdd, NodeResultJS | NodeMustGenerate | NodeHasVarArgs) \ >diff --git a/Source/JavaScriptCore/dfg/DFGOperations.cpp b/Source/JavaScriptCore/dfg/DFGOperations.cpp >index 7777368d6babb7683fe2fef3d4d59527e2eaa074..26de11188561b5cd1bb900381a6f412c48a87fc6 100644 >--- a/Source/JavaScriptCore/dfg/DFGOperations.cpp >+++ b/Source/JavaScriptCore/dfg/DFGOperations.cpp >@@ -248,6 +248,34 @@ EncodedJSValue JIT_OPERATION operationToThisStrict(ExecState* exec, EncodedJSVal > 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(); >diff --git a/Source/JavaScriptCore/dfg/DFGOperations.h b/Source/JavaScriptCore/dfg/DFGOperations.h >index 6309ec38d8b5190a3afa6e26cae9c6775f0f455a..35bf6bceadb644d004c76c985f631d5233d007cd 100644 >--- a/Source/JavaScriptCore/dfg/DFGOperations.h >+++ b/Source/JavaScriptCore/dfg/DFGOperations.h >@@ -43,6 +43,8 @@ EncodedJSValue JIT_OPERATION operationStringFromCharCodeUntyped(ExecState*, Enco > // 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; >diff --git a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp >index 5a6addb3c5acdf0de88c1c8de4588ac5d007e175..0119a25c4257d1addef405cf2898277d2780cb33 100644 >--- a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp >+++ b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp >@@ -906,6 +906,7 @@ class PredictionPropagationPhase : public Phase { > break; > } > >+ case ObjectCreate: > case CreateThis: > case NewObject: { > setPrediction(SpecFinalObject); >diff --git a/Source/JavaScriptCore/dfg/DFGSafeToExecute.h b/Source/JavaScriptCore/dfg/DFGSafeToExecute.h >index b35078fd7033586b4e3cf719da83a6cff0e3caaf..93916d8fe21713f6e823532ddaed2e81b08a141c 100644 >--- a/Source/JavaScriptCore/dfg/DFGSafeToExecute.h >+++ b/Source/JavaScriptCore/dfg/DFGSafeToExecute.h >@@ -171,6 +171,7 @@ bool safeToExecute(AbstractStateType& state, Graph& graph, Node* node, bool igno > case IdentityWithProfile: > case ToThis: > case CreateThis: >+ case ObjectCreate: > case GetCallee: > case SetCallee: > case GetArgumentCountIncludingThis: >diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp >index 73cee6a32369fc825309bce03a91b836a38c0b3d..6996d42ec53e7f92dd5de1686bbbefd270a10b7a 100644 >--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp >+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp >@@ -12172,6 +12172,47 @@ void SpeculativeJIT::compileToThis(Node* node) > 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 >diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h >index 8b0419417ca7da205629949e861c59f45db4bfc5..848fd3bc144487fe8f33d9f5c70f0c9ccf387248 100644 >--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h >+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h >@@ -1472,6 +1472,7 @@ class SpeculativeJIT { > void compileNewArrayWithSize(Node*); > void compileNewTypedArray(Node*); > void compileToThis(Node*); >+ void compileObjectCreate(Node*); > void compileCreateThis(Node*); > void compileNewObject(Node*); > void compileToPrimitive(Node*); >diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp >index ac73b7bb45b6694554662cada849b0a1d87e44d9..a8967d2317ed801788a326fd038f799265c9a9a9 100644 >--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp >+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp >@@ -3132,6 +3132,11 @@ void SpeculativeJIT::compile(Node* node) > break; > } > >+ case ObjectCreate: { >+ compileObjectCreate(node); >+ break; >+ } >+ > case CreateThis: { > compileCreateThis(node); > break; >diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp >index db193475f5a4d98d68655989bf4e591888983697..b70c211011e908d80e3389a1e81fb85ee04fe762 100644 >--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp >+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp >@@ -3382,6 +3382,11 @@ void SpeculativeJIT::compile(Node* node) > break; > } > >+ case ObjectCreate: { >+ compileObjectCreate(node); >+ break; >+ } >+ > case CreateThis: { > compileCreateThis(node); > break; >diff --git a/Source/JavaScriptCore/ftl/FTLCapabilities.cpp b/Source/JavaScriptCore/ftl/FTLCapabilities.cpp >index 7b44b66eb621467acc348b422939b6b18ef516e0..dc6b68628db06b698337cc676bb7fdd32dcd3fe0 100644 >--- a/Source/JavaScriptCore/ftl/FTLCapabilities.cpp >+++ b/Source/JavaScriptCore/ftl/FTLCapabilities.cpp >@@ -191,6 +191,7 @@ inline CapabilityLevel canCompile(Node* node) > case ToObject: > case CallObjectConstructor: > case CallStringConstructor: >+ case ObjectCreate: > case MakeRope: > case NewArrayWithSize: > case TryGetById: >diff --git a/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp b/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp >index 71354b3ca822e91a0ebd4ea53f3c66a80d140390..56bfad5cf9f123446935d977ea96ce5cf9ec59db 100644 >--- a/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp >+++ b/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp >@@ -838,6 +838,9 @@ class LowerDFGToB3 { > case CreateClonedArguments: > compileCreateClonedArguments(); > break; >+ case ObjectCreate: >+ compileObjectCreate(); >+ break; > case NewObject: > compileNewObject(); > break; >@@ -5353,6 +5356,21 @@ class LowerDFGToB3 { > 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() > { >diff --git a/Source/JavaScriptCore/runtime/Intrinsic.cpp b/Source/JavaScriptCore/runtime/Intrinsic.cpp >index 6652de04467b4615cd80ff753bf2da5cb990d980..801ed5493853fcaf37bf164d57afbf2dcc4f9ae7 100644 >--- a/Source/JavaScriptCore/runtime/Intrinsic.cpp >+++ b/Source/JavaScriptCore/runtime/Intrinsic.cpp >@@ -113,6 +113,8 @@ const char* intrinsicName(Intrinsic intrinsic) > return "RegExpTestFastIntrinsic"; > case RegExpMatchFastIntrinsic: > return "RegExpMatchFastIntrinsic"; >+ case ObjectCreateIntrinsic: >+ return "ObjectCreateIntrinsic"; > case ObjectGetPrototypeOfIntrinsic: > return "ObjectGetPrototypeOfIntrinsic"; > case ObjectIsIntrinsic: >diff --git a/Source/JavaScriptCore/runtime/Intrinsic.h b/Source/JavaScriptCore/runtime/Intrinsic.h >index 61fe0bd7f2580f265652167ff82bceaabbe76a00..757df0547b13c36c74f926033616ac5ed329cfcf 100644 >--- a/Source/JavaScriptCore/runtime/Intrinsic.h >+++ b/Source/JavaScriptCore/runtime/Intrinsic.h >@@ -69,6 +69,7 @@ enum Intrinsic { > RegExpTestIntrinsic, > RegExpTestFastIntrinsic, > RegExpMatchFastIntrinsic, >+ ObjectCreateIntrinsic, > ObjectGetPrototypeOfIntrinsic, > ObjectIsIntrinsic, > ReflectGetPrototypeOfIntrinsic, >diff --git a/Source/JavaScriptCore/runtime/ObjectConstructor.cpp b/Source/JavaScriptCore/runtime/ObjectConstructor.cpp >index 8152be7b3aae63e54ad8ce1053931041ca3b5238..f55dc296e9acae5b8083f19eadaff636144153e4 100644 >--- a/Source/JavaScriptCore/runtime/ObjectConstructor.cpp >+++ b/Source/JavaScriptCore/runtime/ObjectConstructor.cpp >@@ -76,7 +76,7 @@ const ClassInfo ObjectConstructor::s_info = { "Function", &InternalFunction::s_i > 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 >diff --git a/JSTests/ChangeLog b/JSTests/ChangeLog >index c6f6f12687bb2ecdf6995f63fb48c8b7403540d1..00af33f4d0ead5f3b7d04c2bf2f25a84f07fc31a 100644 >--- a/JSTests/ChangeLog >+++ b/JSTests/ChangeLog >@@ -1,3 +1,32 @@ >+2018-06-01 Yusuke Suzuki <utatane.tea@gmail.com> >+ >+ [JSC] Object.create should have intrinsic >+ https://bugs.webkit.org/show_bug.cgi?id=186200 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * 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/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-05-31 Caio Lima <ticaiolima@gmail.com> > > [ESNext][BigInt] Implement support for "=<" and ">=" relational operation >diff --git a/JSTests/microbenchmarks/object-create-null.js b/JSTests/microbenchmarks/object-create-null.js >new file mode 100644 >index 0000000000000000000000000000000000000000..0517d24fe2f977855ad2902a4dc3e95213df6168 >--- /dev/null >+++ b/JSTests/microbenchmarks/object-create-null.js >@@ -0,0 +1,8 @@ >+function test() >+{ >+ return Object.create(null); >+} >+noInline(test); >+ >+for (var i = 0; i < 1e6; ++i) >+ test(); >diff --git a/JSTests/microbenchmarks/object-create-unknown-object-prototype.js b/JSTests/microbenchmarks/object-create-unknown-object-prototype.js >new file mode 100644 >index 0000000000000000000000000000000000000000..28c468e3a6c255540c0da3b54f256a1c1143a518 >--- /dev/null >+++ b/JSTests/microbenchmarks/object-create-unknown-object-prototype.js >@@ -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); >+} >diff --git a/JSTests/microbenchmarks/object-create-untyped-prototype.js b/JSTests/microbenchmarks/object-create-untyped-prototype.js >new file mode 100644 >index 0000000000000000000000000000000000000000..78ca4727f2e015ffbb0edfa71dfc1e4db7eeba11 >--- /dev/null >+++ b/JSTests/microbenchmarks/object-create-untyped-prototype.js >@@ -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); >+} >diff --git a/JSTests/stress/object-create-define.js b/JSTests/stress/object-create-define.js >new file mode 100644 >index 0000000000000000000000000000000000000000..a3ed990f7eb51ef61c89d2ecad179b0e1a1abba4 >--- /dev/null >+++ b/JSTests/stress/object-create-define.js >@@ -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"]`); >+} >diff --git a/JSTests/stress/object-create-null-external.js b/JSTests/stress/object-create-null-external.js >new file mode 100644 >index 0000000000000000000000000000000000000000..96fd04d77dce65f0f866f4090edd6d78b2776db8 >--- /dev/null >+++ b/JSTests/stress/object-create-null-external.js >@@ -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)), `[]`); >+} >diff --git a/JSTests/stress/object-create-null.js b/JSTests/stress/object-create-null.js >new file mode 100644 >index 0000000000000000000000000000000000000000..0bc968e771350fdb60e5eb7c482eac3e60b1e598 >--- /dev/null >+++ b/JSTests/stress/object-create-null.js >@@ -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)), `[]`); >+} >diff --git a/JSTests/stress/object-create-prototype.js b/JSTests/stress/object-create-prototype.js >new file mode 100644 >index 0000000000000000000000000000000000000000..0d33fb439e1efacb256a250050e5549aa3cf80ad >--- /dev/null >+++ b/JSTests/stress/object-create-prototype.js >@@ -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)), `[]`); >+} >diff --git a/JSTests/stress/object-create-undefined.js b/JSTests/stress/object-create-undefined.js >new file mode 100644 >index 0000000000000000000000000000000000000000..9aa3c21c8dfcc69e556cf57cc46edbaed1fd6efa >--- /dev/null >+++ b/JSTests/stress/object-create-undefined.js >@@ -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.`); >+}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 186200
:
341768
|
341769
|
341777
|
341805
|
341845