[JSC] Handle new_async_func / new_async_func_exp in DFG / FTL
https://bugs.webkit.org/show_bug.cgi?id=164037
Reviewed by Yusuke Suzuki.
JSTests:
Add tests based on tests from https://trac.webkit.org/changeset/194216.
* asyncFunctionTests.yaml:
* stress/async-function-create-nobaseline.js: Added.
* stress/async-function-create-optimized.js: Added.
* stress/async-function-declaration-sinking-no-double-allocate.js: Added.
* stress/async-function-declaration-sinking-osrexit.js: Added.
* stress/async-function-declaration-sinking-put.js: Added.
* stress/async-function-expression-sinking-no-double-allocate.js: Added.
* stress/async-function-expression-sinking-osrexit.js: Added.
* stress/async-function-expression-sinking-put.js: Added.
Source/JavaScriptCore:
This patch introduces new_async_func / new_async_func_exp into DFG and FTL,
in much the same capacity that https://trac.webkit.org/changeset/194216 added
DFG / FTL support for generators: by adding new DFG nodes (NewAsyncFunction and
PhantomNewAsyncFunction), rather than extending the existing NewFunction node type.
Like NewFunction and PhantomNewFunction, and the Generator variants, allocation of
async wrapper functions may be deferred or eliminated during the allocation sinking
phase.
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGCapabilities.cpp:
(JSC::DFG::capabilityLevel):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGClobbersExitState.cpp:
(JSC::DFG::clobbersExitState):
* dfg/DFGDoesGC.cpp:
(JSC::DFG::doesGC):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGMayExit.cpp:
* dfg/DFGNode.h:
(JSC::DFG::Node::convertToPhantomNewFunction):
(JSC::DFG::Node::convertToPhantomNewAsyncFunction):
(JSC::DFG::Node::hasCellOperand):
(JSC::DFG::Node::isFunctionAllocation):
(JSC::DFG::Node::isPhantomFunctionAllocation):
(JSC::DFG::Node::isPhantomAllocation):
* dfg/DFGNodeType.h:
* dfg/DFGObjectAllocationSinkingPhase.cpp:
* dfg/DFGPredictionPropagationPhase.cpp:
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileNewFunction):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGStoreBarrierInsertionPhase.cpp:
* dfg/DFGStructureRegistrationPhase.cpp:
(JSC::DFG::StructureRegistrationPhase::run):
* dfg/DFGValidate.cpp:
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileNewFunction):
* ftl/FTLOperations.cpp:
(JSC::FTL::operationPopulateObjectInOSR):
(JSC::FTL::operationMaterializeObjectInOSR):
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::init):
(JSC::JSGlobalObject::visitChildren):
* runtime/JSGlobalObject.h:
(JSC::JSGlobalObject::asyncFunctionPrototype):
(JSC::JSGlobalObject::asyncFunctionStructure):
(JSC::JSGlobalObject::lazyAsyncFunctionStructure): Deleted.
(JSC::JSGlobalObject::asyncFunctionPrototypeConcurrently): Deleted.
(JSC::JSGlobalObject::asyncFunctionStructureConcurrently): Deleted.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@208704 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog
index 54ce0cc..b64a9fe 100644
--- a/Source/JavaScriptCore/ChangeLog
+++ b/Source/JavaScriptCore/ChangeLog
@@ -1,3 +1,74 @@
+2016-11-14 Caitlin Potter <caitp@igalia.com>
+
+ [JSC] Handle new_async_func / new_async_func_exp in DFG / FTL
+ https://bugs.webkit.org/show_bug.cgi?id=164037
+
+ Reviewed by Yusuke Suzuki.
+
+ This patch introduces new_async_func / new_async_func_exp into DFG and FTL,
+ in much the same capacity that https://trac.webkit.org/changeset/194216 added
+ DFG / FTL support for generators: by adding new DFG nodes (NewAsyncFunction and
+ PhantomNewAsyncFunction), rather than extending the existing NewFunction node type.
+
+ Like NewFunction and PhantomNewFunction, and the Generator variants, allocation of
+ async wrapper functions may be deferred or eliminated during the allocation sinking
+ phase.
+
+ * dfg/DFGAbstractInterpreterInlines.h:
+ (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::parseBlock):
+ * dfg/DFGCapabilities.cpp:
+ (JSC::DFG::capabilityLevel):
+ * dfg/DFGClobberize.h:
+ (JSC::DFG::clobberize):
+ * dfg/DFGClobbersExitState.cpp:
+ (JSC::DFG::clobbersExitState):
+ * dfg/DFGDoesGC.cpp:
+ (JSC::DFG::doesGC):
+ * dfg/DFGFixupPhase.cpp:
+ (JSC::DFG::FixupPhase::fixupNode):
+ * dfg/DFGMayExit.cpp:
+ * dfg/DFGNode.h:
+ (JSC::DFG::Node::convertToPhantomNewFunction):
+ (JSC::DFG::Node::convertToPhantomNewAsyncFunction):
+ (JSC::DFG::Node::hasCellOperand):
+ (JSC::DFG::Node::isFunctionAllocation):
+ (JSC::DFG::Node::isPhantomFunctionAllocation):
+ (JSC::DFG::Node::isPhantomAllocation):
+ * dfg/DFGNodeType.h:
+ * dfg/DFGObjectAllocationSinkingPhase.cpp:
+ * dfg/DFGPredictionPropagationPhase.cpp:
+ * dfg/DFGSafeToExecute.h:
+ (JSC::DFG::safeToExecute):
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::compileNewFunction):
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGStoreBarrierInsertionPhase.cpp:
+ * dfg/DFGStructureRegistrationPhase.cpp:
+ (JSC::DFG::StructureRegistrationPhase::run):
+ * dfg/DFGValidate.cpp:
+ * ftl/FTLCapabilities.cpp:
+ (JSC::FTL::canCompile):
+ * ftl/FTLLowerDFGToB3.cpp:
+ (JSC::FTL::DFG::LowerDFGToB3::compileNode):
+ (JSC::FTL::DFG::LowerDFGToB3::compileNewFunction):
+ * ftl/FTLOperations.cpp:
+ (JSC::FTL::operationPopulateObjectInOSR):
+ (JSC::FTL::operationMaterializeObjectInOSR):
+ * runtime/JSGlobalObject.cpp:
+ (JSC::JSGlobalObject::init):
+ (JSC::JSGlobalObject::visitChildren):
+ * runtime/JSGlobalObject.h:
+ (JSC::JSGlobalObject::asyncFunctionPrototype):
+ (JSC::JSGlobalObject::asyncFunctionStructure):
+ (JSC::JSGlobalObject::lazyAsyncFunctionStructure): Deleted.
+ (JSC::JSGlobalObject::asyncFunctionPrototypeConcurrently): Deleted.
+ (JSC::JSGlobalObject::asyncFunctionStructureConcurrently): Deleted.
+
2016-11-14 Mark Lam <mark.lam@apple.com>
Some of JSStringView::SafeView methods are not idiomatically safe for JSString to StringView conversions.
diff --git a/Source/JavaScriptCore/builtins/AsyncFunctionPrototype.js b/Source/JavaScriptCore/builtins/AsyncFunctionPrototype.js
index 2247882..ea90ef4 100644
--- a/Source/JavaScriptCore/builtins/AsyncFunctionPrototype.js
+++ b/Source/JavaScriptCore/builtins/AsyncFunctionPrototype.js
@@ -23,6 +23,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+@globalPrivate
function asyncFunctionResume(generator, sentValue, resumeMode)
{
"use strict";
diff --git a/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h b/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
index 8c7e631..5df4da3 100644
--- a/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
+++ b/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
@@ -1970,6 +1970,7 @@
case PhantomNewObject:
case PhantomNewFunction:
case PhantomNewGeneratorFunction:
+ case PhantomNewAsyncFunction:
case PhantomCreateActivation:
case PhantomDirectArguments:
case PhantomClonedArguments:
@@ -2014,6 +2015,11 @@
m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->generatorFunctionStructure());
break;
+ case NewAsyncFunction:
+ forNode(node).set(
+ m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->asyncFunctionStructure());
+ break;
+
case NewFunction:
forNode(node).set(
m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->functionStructure());
diff --git a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
index 1a941d1..e7a8314 100644
--- a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
+++ b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
@@ -5325,23 +5325,29 @@
}
case op_new_func:
- case op_new_generator_func: {
+ case op_new_generator_func:
+ case op_new_async_func: {
FunctionExecutable* decl = m_inlineStackTop->m_profiledBlock->functionDecl(currentInstruction[3].u.operand);
FrozenValue* frozen = m_graph.freezeStrong(decl);
- NodeType op = (opcodeID == op_new_generator_func) ? NewGeneratorFunction : NewFunction;
+ NodeType op = (opcodeID == op_new_generator_func) ? NewGeneratorFunction :
+ (opcodeID == op_new_async_func) ? NewAsyncFunction : NewFunction;
set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(op, OpInfo(frozen), get(VirtualRegister(currentInstruction[2].u.operand))));
static_assert(OPCODE_LENGTH(op_new_func) == OPCODE_LENGTH(op_new_generator_func), "The length of op_new_func should eqaual to one of op_new_generator_func");
+ static_assert(OPCODE_LENGTH(op_new_func) == OPCODE_LENGTH(op_new_async_func), "The length of op_new_func should eqaual to one of op_new_async_func");
NEXT_OPCODE(op_new_func);
}
case op_new_func_exp:
- case op_new_generator_func_exp: {
+ case op_new_generator_func_exp:
+ case op_new_async_func_exp: {
FunctionExecutable* expr = m_inlineStackTop->m_profiledBlock->functionExpr(currentInstruction[3].u.operand);
FrozenValue* frozen = m_graph.freezeStrong(expr);
- NodeType op = (opcodeID == op_new_generator_func_exp) ? NewGeneratorFunction : NewFunction;
+ NodeType op = (opcodeID == op_new_generator_func_exp) ? NewGeneratorFunction :
+ (opcodeID == op_new_async_func_exp) ? NewAsyncFunction : NewFunction;
set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(op, OpInfo(frozen), get(VirtualRegister(currentInstruction[2].u.operand))));
-
+
static_assert(OPCODE_LENGTH(op_new_func_exp) == OPCODE_LENGTH(op_new_generator_func_exp), "The length of op_new_func_exp should eqaual to one of op_new_generator_func_exp");
+ static_assert(OPCODE_LENGTH(op_new_func_exp) == OPCODE_LENGTH(op_new_async_func_exp), "The length of op_new_func_exp should eqaual to one of op_new_async_func_exp");
NEXT_OPCODE(op_new_func_exp);
}
diff --git a/Source/JavaScriptCore/dfg/DFGCapabilities.cpp b/Source/JavaScriptCore/dfg/DFGCapabilities.cpp
index bfb7019..a8789c7 100644
--- a/Source/JavaScriptCore/dfg/DFGCapabilities.cpp
+++ b/Source/JavaScriptCore/dfg/DFGCapabilities.cpp
@@ -239,6 +239,8 @@
case op_new_func_exp:
case op_new_generator_func:
case op_new_generator_func_exp:
+ case op_new_async_func:
+ case op_new_async_func_exp:
case op_set_function_name:
case op_create_lexical_environment:
case op_get_parent_scope:
diff --git a/Source/JavaScriptCore/dfg/DFGClobberize.h b/Source/JavaScriptCore/dfg/DFGClobberize.h
index e12dfa8..456cf8c 100644
--- a/Source/JavaScriptCore/dfg/DFGClobberize.h
+++ b/Source/JavaScriptCore/dfg/DFGClobberize.h
@@ -1273,6 +1273,7 @@
case MaterializeNewObject:
case PhantomNewFunction:
case PhantomNewGeneratorFunction:
+ case PhantomNewAsyncFunction:
case PhantomCreateActivation:
case MaterializeCreateActivation:
read(HeapObjectCount);
@@ -1281,6 +1282,7 @@
case NewFunction:
case NewGeneratorFunction:
+ case NewAsyncFunction:
if (node->castOperand<FunctionExecutable*>()->singletonFunction()->isStillValid())
write(Watchpoint_fire);
read(HeapObjectCount);
diff --git a/Source/JavaScriptCore/dfg/DFGClobbersExitState.cpp b/Source/JavaScriptCore/dfg/DFGClobbersExitState.cpp
index bd339b8..91fb271 100644
--- a/Source/JavaScriptCore/dfg/DFGClobbersExitState.cpp
+++ b/Source/JavaScriptCore/dfg/DFGClobbersExitState.cpp
@@ -62,6 +62,7 @@
case MaterializeNewObject:
case PhantomNewFunction:
case PhantomNewGeneratorFunction:
+ case PhantomNewAsyncFunction:
case PhantomCreateActivation:
case MaterializeCreateActivation:
case CountExecution:
@@ -80,6 +81,7 @@
case NewFunction:
case NewGeneratorFunction:
+ case NewAsyncFunction:
// Like above, but with the JSFunction allocation caveat.
return node->castOperand<FunctionExecutable*>()->singletonFunction()->isStillValid();
diff --git a/Source/JavaScriptCore/dfg/DFGDoesGC.cpp b/Source/JavaScriptCore/dfg/DFGDoesGC.cpp
index 9e853e3..411881c 100644
--- a/Source/JavaScriptCore/dfg/DFGDoesGC.cpp
+++ b/Source/JavaScriptCore/dfg/DFGDoesGC.cpp
@@ -244,6 +244,7 @@
case PhantomNewObject:
case PhantomNewFunction:
case PhantomNewGeneratorFunction:
+ case PhantomNewAsyncFunction:
case PhantomCreateActivation:
case PhantomDirectArguments:
case PhantomCreateRest:
@@ -288,6 +289,7 @@
case MakeRope:
case NewFunction:
case NewGeneratorFunction:
+ case NewAsyncFunction:
case NewTypedArray:
case ThrowStaticError:
case GetPropertyEnumerator:
diff --git a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
index cbf7b0e..b15f00f 100644
--- a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
@@ -1435,6 +1435,7 @@
case PhantomNewObject:
case PhantomNewFunction:
case PhantomNewGeneratorFunction:
+ case PhantomNewAsyncFunction:
case PhantomCreateActivation:
case PhantomDirectArguments:
case PhantomCreateRest:
@@ -1596,7 +1597,8 @@
case CreateScopedArguments:
case CreateActivation:
case NewFunction:
- case NewGeneratorFunction: {
+ case NewGeneratorFunction:
+ case NewAsyncFunction: {
fixEdge<CellUse>(node->child1());
break;
}
diff --git a/Source/JavaScriptCore/dfg/DFGMayExit.cpp b/Source/JavaScriptCore/dfg/DFGMayExit.cpp
index 80b3374..fbbb1b9 100644
--- a/Source/JavaScriptCore/dfg/DFGMayExit.cpp
+++ b/Source/JavaScriptCore/dfg/DFGMayExit.cpp
@@ -106,6 +106,7 @@
case MaterializeNewObject:
case NewFunction:
case NewGeneratorFunction:
+ case NewAsyncFunction:
case NewStringObject:
case ToNumber:
result = ExitsForExceptions;
diff --git a/Source/JavaScriptCore/dfg/DFGNode.h b/Source/JavaScriptCore/dfg/DFGNode.h
index 1b21de9..36115de 100644
--- a/Source/JavaScriptCore/dfg/DFGNode.h
+++ b/Source/JavaScriptCore/dfg/DFGNode.h
@@ -587,7 +587,7 @@
void convertToPhantomNewFunction()
{
- ASSERT(m_op == NewFunction || m_op == NewGeneratorFunction);
+ ASSERT(m_op == NewFunction || m_op == NewGeneratorFunction || m_op == NewAsyncFunction);
m_op = PhantomNewFunction;
m_flags |= NodeMustGenerate;
m_opInfo = OpInfoWrapper();
@@ -605,6 +605,16 @@
children = AdjacencyList();
}
+ void convertToPhantomNewAsyncFunction()
+ {
+ ASSERT(m_op == NewAsyncFunction);
+ m_op = PhantomNewAsyncFunction;
+ m_flags |= NodeMustGenerate;
+ m_opInfo = OpInfoWrapper();
+ m_opInfo2 = OpInfoWrapper();
+ children = AdjacencyList();
+ }
+
void convertToPhantomCreateActivation()
{
ASSERT(m_op == CreateActivation || m_op == MaterializeCreateActivation);
@@ -1498,6 +1508,7 @@
case OverridesHasInstance:
case NewFunction:
case NewGeneratorFunction:
+ case NewAsyncFunction:
case CreateActivation:
case MaterializeCreateActivation:
case NewRegexp:
@@ -1733,6 +1744,7 @@
switch (op()) {
case NewFunction:
case NewGeneratorFunction:
+ case NewAsyncFunction:
return true;
default:
return false;
@@ -1744,6 +1756,7 @@
switch (op()) {
case PhantomNewFunction:
case PhantomNewGeneratorFunction:
+ case PhantomNewAsyncFunction:
return true;
default:
return false;
@@ -1759,6 +1772,7 @@
case PhantomClonedArguments:
case PhantomNewFunction:
case PhantomNewGeneratorFunction:
+ case PhantomNewAsyncFunction:
case PhantomCreateActivation:
return true;
default:
diff --git a/Source/JavaScriptCore/dfg/DFGNodeType.h b/Source/JavaScriptCore/dfg/DFGNodeType.h
index 005af66..bff7fe3 100644
--- a/Source/JavaScriptCore/dfg/DFGNodeType.h
+++ b/Source/JavaScriptCore/dfg/DFGNodeType.h
@@ -307,6 +307,7 @@
macro(MaterializeNewObject, NodeResultJS | NodeHasVarArgs) \
macro(PhantomNewFunction, NodeResultJS | NodeMustGenerate) \
macro(PhantomNewGeneratorFunction, NodeResultJS | NodeMustGenerate) \
+ macro(PhantomNewAsyncFunction, NodeResultJS | NodeMustGenerate) \
macro(PhantomCreateActivation, NodeResultJS | NodeMustGenerate) \
macro(MaterializeCreateActivation, NodeResultJS | NodeHasVarArgs) \
\
@@ -355,6 +356,8 @@
\
macro(NewGeneratorFunction, NodeResultJS) \
\
+ macro(NewAsyncFunction, NodeResultJS) \
+ \
/* These aren't terminals but always exit */ \
macro(Throw, NodeMustGenerate) \
macro(ThrowStaticError, NodeMustGenerate) \
diff --git a/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp b/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp
index 81c3061..a1b8393 100644
--- a/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp
@@ -139,7 +139,7 @@
// once it is escaped if it still has pointers to it in order to
// replace any use of those pointers by the corresponding
// materialization
- enum class Kind { Escaped, Object, Activation, Function, GeneratorFunction };
+ enum class Kind { Escaped, Object, Activation, Function, GeneratorFunction, AsyncFunction };
explicit Allocation(Node* identifier = nullptr, Kind kind = Kind::Escaped)
: m_identifier(identifier)
@@ -233,7 +233,7 @@
bool isFunctionAllocation() const
{
- return m_kind == Kind::Function || m_kind == Kind::GeneratorFunction;
+ return m_kind == Kind::Function || m_kind == Kind::GeneratorFunction || m_kind == Kind::AsyncFunction;
}
bool operator==(const Allocation& other) const
@@ -273,6 +273,10 @@
out.print("GeneratorFunction");
break;
+ case Kind::AsyncFunction:
+ out.print("AsyncFunction");
+ break;
+
case Kind::Activation:
out.print("Activation");
break;
@@ -832,16 +836,20 @@
break;
case NewFunction:
- case NewGeneratorFunction: {
+ case NewGeneratorFunction:
+ case NewAsyncFunction: {
if (isStillValid(node->castOperand<FunctionExecutable*>()->singletonFunction())) {
m_heap.escape(node->child1().node());
break;
}
-
+
if (node->op() == NewGeneratorFunction)
target = &m_heap.newAllocation(node, Allocation::Kind::GeneratorFunction);
+ else if (node->op() == NewAsyncFunction)
+ target = &m_heap.newAllocation(node, Allocation::Kind::AsyncFunction);
else
target = &m_heap.newAllocation(node, Allocation::Kind::Function);
+
writes.add(FunctionExecutablePLoc, LazyNode(node->cellOperand()));
writes.add(FunctionActivationPLoc, LazyNode(node->child1().node()));
break;
@@ -1444,12 +1452,14 @@
OpInfo(set), OpInfo(data), 0, 0);
}
+ case Allocation::Kind::AsyncFunction:
case Allocation::Kind::GeneratorFunction:
case Allocation::Kind::Function: {
FrozenValue* executable = allocation.identifier()->cellOperand();
NodeType nodeType =
- allocation.kind() == Allocation::Kind::GeneratorFunction ? NewGeneratorFunction : NewFunction;
+ allocation.kind() == Allocation::Kind::GeneratorFunction ? NewGeneratorFunction :
+ allocation.kind() == Allocation::Kind::AsyncFunction ? NewAsyncFunction : NewFunction;
return m_graph.addNode(
allocation.identifier()->prediction(), nodeType,
@@ -1791,6 +1801,10 @@
node->convertToPhantomNewGeneratorFunction();
break;
+ case NewAsyncFunction:
+ node->convertToPhantomNewAsyncFunction();
+ break;
+
case CreateActivation:
node->convertToPhantomCreateActivation();
break;
@@ -2047,7 +2061,8 @@
}
case NewFunction:
- case NewGeneratorFunction: {
+ case NewGeneratorFunction:
+ case NewAsyncFunction: {
Vector<PromotedHeapLocation> locations = m_locationsForAllocation.get(escapee);
ASSERT(locations.size() == 2);
diff --git a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
index 0907b9f..db9f31d 100644
--- a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
@@ -730,7 +730,8 @@
case GetSetter:
case GetCallee:
case NewFunction:
- case NewGeneratorFunction: {
+ case NewGeneratorFunction:
+ case NewAsyncFunction: {
setPrediction(SpecFunction);
break;
}
@@ -1007,6 +1008,7 @@
case PhantomNewObject:
case PhantomNewFunction:
case PhantomNewGeneratorFunction:
+ case PhantomNewAsyncFunction:
case PhantomCreateActivation:
case PhantomDirectArguments:
case PhantomCreateRest:
diff --git a/Source/JavaScriptCore/dfg/DFGSafeToExecute.h b/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
index 065e665..ae632d3 100644
--- a/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
+++ b/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
@@ -303,6 +303,7 @@
case PutToArguments:
case NewFunction:
case NewGeneratorFunction:
+ case NewAsyncFunction:
case Jump:
case Branch:
case Switch:
@@ -351,6 +352,7 @@
case PhantomNewObject:
case PhantomNewFunction:
case PhantomNewGeneratorFunction:
+ case PhantomNewAsyncFunction:
case PhantomCreateActivation:
case PutHint:
case CheckStructureImmediate:
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
index d308b98..3a1d0ff 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
@@ -50,6 +50,7 @@
#include "JITMulGenerator.h"
#include "JITRightShiftGenerator.h"
#include "JITSubGenerator.h"
+#include "JSAsyncFunction.h"
#include "JSCInlines.h"
#include "JSEnvironmentRecord.h"
#include "JSFixedArray.h"
@@ -6360,7 +6361,7 @@
void SpeculativeJIT::compileNewFunction(Node* node)
{
NodeType nodeType = node->op();
- ASSERT(nodeType == NewFunction || nodeType == NewGeneratorFunction);
+ ASSERT(nodeType == NewFunction || nodeType == NewGeneratorFunction || nodeType == NewAsyncFunction);
SpeculateCellOperand scope(this, node->child1());
GPRReg scopeGPR = scope.gpr();
@@ -6375,6 +6376,8 @@
if (nodeType == NewGeneratorFunction)
callOperation(operationNewGeneratorFunction, resultGPR, scopeGPR, executable);
+ else if (nodeType == NewAsyncFunction)
+ callOperation(operationNewAsyncFunction, resultGPR, scopeGPR, executable);
else
callOperation(operationNewFunction, resultGPR, scopeGPR, executable);
m_jit.exceptionCheck();
@@ -6384,6 +6387,7 @@
Structure* structure =
nodeType == NewGeneratorFunction ? m_jit.graph().globalObjectFor(node->origin.semantic)->generatorFunctionStructure() :
+ nodeType == NewAsyncFunction ? m_jit.graph().globalObjectFor(node->origin.semantic)->asyncFunctionStructure() :
m_jit.graph().globalObjectFor(node->origin.semantic)->functionStructure();
GPRTemporary result(this);
@@ -6408,6 +6412,12 @@
addSlowPathGenerator(slowPathCall(slowPath, this, operationNewGeneratorFunctionWithInvalidatedReallocationWatchpoint, resultGPR, scopeGPR, executable));
}
+ if (nodeType == NewAsyncFunction) {
+ compileNewFunctionCommon<JSAsyncFunction>(resultGPR, structure, scratch1GPR, scratch2GPR, scopeGPR, slowPath, JSAsyncFunction::allocationSize(0), executable, JSAsyncFunction::offsetOfScopeChain(), JSAsyncFunction::offsetOfExecutable(), JSAsyncFunction::offsetOfRareData());
+
+ addSlowPathGenerator(slowPathCall(slowPath, this, operationNewAsyncFunctionWithInvalidatedReallocationWatchpoint, resultGPR, scopeGPR, executable));
+ }
+
cellResult(resultGPR, node);
}
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
index a4e7c10..657442f 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
@@ -5014,6 +5014,7 @@
case NewFunction:
case NewGeneratorFunction:
+ case NewAsyncFunction:
compileNewFunction(node);
break;
@@ -5604,6 +5605,7 @@
case PhantomNewObject:
case PhantomNewFunction:
case PhantomNewGeneratorFunction:
+ case PhantomNewAsyncFunction:
case PhantomCreateActivation:
case PutHint:
case CheckStructureImmediate:
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
index c12143a..22aad77 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
@@ -5179,6 +5179,7 @@
case NewFunction:
case NewGeneratorFunction:
+ case NewAsyncFunction:
compileNewFunction(node);
break;
@@ -5820,6 +5821,7 @@
case PhantomNewObject:
case PhantomNewFunction:
case PhantomNewGeneratorFunction:
+ case PhantomNewAsyncFunction:
case PhantomCreateActivation:
case GetMyArgumentByVal:
case GetMyArgumentByValOutOfBounds:
diff --git a/Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.cpp b/Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.cpp
index 5f32b4d6..60b8f4a 100644
--- a/Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.cpp
@@ -317,6 +317,7 @@
case CreateClonedArguments:
case NewFunction:
case NewGeneratorFunction:
+ case NewAsyncFunction:
// Nodes that allocate get to set their epoch because for those nodes we know
// that they will be the newest object in the heap.
m_node->setEpoch(m_currentEpoch);
diff --git a/Source/JavaScriptCore/dfg/DFGStructureRegistrationPhase.cpp b/Source/JavaScriptCore/dfg/DFGStructureRegistrationPhase.cpp
index bed19f5..0b0be44 100644
--- a/Source/JavaScriptCore/dfg/DFGStructureRegistrationPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGStructureRegistrationPhase.cpp
@@ -177,6 +177,9 @@
case NewGeneratorFunction:
registerStructure(m_graph.globalObjectFor(node->origin.semantic)->generatorFunctionStructure());
break;
+ case NewAsyncFunction:
+ registerStructure(m_graph.globalObjectFor(node->origin.semantic)->asyncFunctionStructure());
+ break;
default:
break;
diff --git a/Source/JavaScriptCore/dfg/DFGValidate.cpp b/Source/JavaScriptCore/dfg/DFGValidate.cpp
index 423301c..733932f 100644
--- a/Source/JavaScriptCore/dfg/DFGValidate.cpp
+++ b/Source/JavaScriptCore/dfg/DFGValidate.cpp
@@ -529,6 +529,7 @@
case PhantomNewObject:
case PhantomNewFunction:
case PhantomNewGeneratorFunction:
+ case PhantomNewAsyncFunction:
case PhantomCreateActivation:
case GetMyArgumentByVal:
case GetMyArgumentByValOutOfBounds:
@@ -668,6 +669,7 @@
case PhantomNewObject:
case PhantomNewFunction:
case PhantomNewGeneratorFunction:
+ case PhantomNewAsyncFunction:
case PhantomCreateActivation:
case PhantomDirectArguments:
case PhantomCreateRest:
diff --git a/Source/JavaScriptCore/ftl/FTLCapabilities.cpp b/Source/JavaScriptCore/ftl/FTLCapabilities.cpp
index bce38a6..f99179f 100644
--- a/Source/JavaScriptCore/ftl/FTLCapabilities.cpp
+++ b/Source/JavaScriptCore/ftl/FTLCapabilities.cpp
@@ -119,6 +119,7 @@
case CreateActivation:
case NewFunction:
case NewGeneratorFunction:
+ case NewAsyncFunction:
case GetClosureVar:
case PutClosureVar:
case CreateDirectArguments:
@@ -226,6 +227,7 @@
case PhantomNewObject:
case PhantomNewFunction:
case PhantomNewGeneratorFunction:
+ case PhantomNewAsyncFunction:
case PhantomCreateActivation:
case PutHint:
case CheckStructureImmediate:
diff --git a/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp b/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
index fd8a90b..9fcfd65 100644
--- a/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
+++ b/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
@@ -710,6 +710,7 @@
break;
case NewFunction:
case NewGeneratorFunction:
+ case NewAsyncFunction:
compileNewFunction();
break;
case CreateDirectArguments:
@@ -1081,6 +1082,7 @@
case PhantomNewObject:
case PhantomNewFunction:
case PhantomNewGeneratorFunction:
+ case PhantomNewAsyncFunction:
case PhantomCreateActivation:
case PhantomDirectArguments:
case PhantomCreateRest:
@@ -3967,8 +3969,9 @@
void compileNewFunction()
{
- ASSERT(m_node->op() == NewFunction || m_node->op() == NewGeneratorFunction);
+ ASSERT(m_node->op() == NewFunction || m_node->op() == NewGeneratorFunction || m_node->op() == NewAsyncFunction);
bool isGeneratorFunction = m_node->op() == NewGeneratorFunction;
+ bool isAsyncFunction = m_node->op() == NewAsyncFunction;
LValue scope = lowCell(m_node->child1());
@@ -3976,6 +3979,7 @@
if (executable->singletonFunction()->isStillValid()) {
LValue callResult =
isGeneratorFunction ? vmCall(Int64, m_out.operation(operationNewGeneratorFunction), m_callFrame, scope, weakPointer(executable)) :
+ isAsyncFunction ? vmCall(Int64, m_out.operation(operationNewAsyncFunction), m_callFrame, scope, weakPointer(executable)) :
vmCall(Int64, m_out.operation(operationNewFunction), m_callFrame, scope, weakPointer(executable));
setJSValue(callResult);
return;
@@ -3983,6 +3987,7 @@
Structure* structure =
isGeneratorFunction ? m_graph.globalObjectFor(m_node->origin.semantic)->generatorFunctionStructure() :
+ isAsyncFunction ? m_graph.globalObjectFor(m_node->origin.semantic)->asyncFunctionStructure() :
m_graph.globalObjectFor(m_node->origin.semantic)->functionStructure();
LBasicBlock slowPath = m_out.newBlock();
@@ -4016,6 +4021,12 @@
locations[0].directGPR(), locations[1].directGPR(),
CCallHelpers::TrustedImmPtr(executable));
}
+ if (isAsyncFunction) {
+ return createLazyCallGenerator(
+ operationNewAsyncFunctionWithInvalidatedReallocationWatchpoint,
+ locations[0].directGPR(), locations[1].directGPR(),
+ CCallHelpers::TrustedImmPtr(executable));
+ }
return createLazyCallGenerator(
operationNewFunctionWithInvalidatedReallocationWatchpoint,
locations[0].directGPR(), locations[1].directGPR(),
diff --git a/Source/JavaScriptCore/ftl/FTLOperations.cpp b/Source/JavaScriptCore/ftl/FTLOperations.cpp
index 592b3ca..d747524 100644
--- a/Source/JavaScriptCore/ftl/FTLOperations.cpp
+++ b/Source/JavaScriptCore/ftl/FTLOperations.cpp
@@ -33,6 +33,7 @@
#include "FTLJITCode.h"
#include "FTLLazySlowPath.h"
#include "InlineCallFrame.h"
+#include "JSAsyncFunction.h"
#include "JSCInlines.h"
#include "JSGeneratorFunction.h"
#include "JSLexicalEnvironment.h"
@@ -81,6 +82,7 @@
case PhantomNewFunction:
case PhantomNewGeneratorFunction:
+ case PhantomNewAsyncFunction:
case PhantomDirectArguments:
case PhantomClonedArguments:
case PhantomCreateRest:
@@ -151,7 +153,8 @@
}
case PhantomNewFunction:
- case PhantomNewGeneratorFunction: {
+ case PhantomNewGeneratorFunction:
+ case PhantomNewAsyncFunction: {
// Figure out what the executable and activation are
FunctionExecutable* executable = nullptr;
JSScope* activation = nullptr;
@@ -166,8 +169,10 @@
if (materialization->type() == PhantomNewFunction)
return JSFunction::createWithInvalidatedReallocationWatchpoint(vm, executable, activation);
- ASSERT(materialization->type() == PhantomNewGeneratorFunction);
- return JSGeneratorFunction::createWithInvalidatedReallocationWatchpoint(vm, executable, activation);
+ else if (materialization->type() == PhantomNewGeneratorFunction)
+ return JSGeneratorFunction::createWithInvalidatedReallocationWatchpoint(vm, executable, activation);
+ ASSERT(materialization->type() == PhantomNewAsyncFunction);
+ return JSAsyncFunction::createWithInvalidatedReallocationWatchpoint(vm, executable, activation);
}
case PhantomCreateActivation: {
diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
index 8aa6c11..1675f82 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
@@ -612,7 +612,6 @@
m_throwTypeErrorFunction.set(vm, this, throwTypeErrorFunction);
JSCell* functionConstructor = FunctionConstructor::create(vm, FunctionConstructor::createStructure(vm, this, m_functionPrototype.get()), m_functionPrototype.get());
- m_functionConstructor.set(vm, this, (FunctionConstructor*)functionConstructor);
ArrayConstructor* arrayConstructor = ArrayConstructor::create(vm, this, ArrayConstructor::createStructure(vm, this, m_functionPrototype.get()), m_arrayPrototype.get(), m_speciesGetterSetter.get());
m_arrayConstructor.set(vm, this, arrayConstructor);
@@ -668,15 +667,10 @@
m_generatorPrototype->putDirectWithoutTransition(vm, vm.propertyNames->constructor, m_generatorFunctionPrototype.get(), DontEnum | ReadOnly);
m_generatorFunctionPrototype->putDirectWithoutTransition(vm, vm.propertyNames->prototype, m_generatorPrototype.get(), DontEnum | ReadOnly);
- m_asyncFunctionStructure.initLater(
- [](LazyClassStructure::Initializer& init) {
- AsyncFunctionPrototype* asyncFunctionPrototype = AsyncFunctionPrototype::create(init.vm, AsyncFunctionPrototype::createStructure(init.vm, init.global, init.global->m_functionPrototype.get()));
- init.setPrototype(asyncFunctionPrototype);
- init.setStructure(JSAsyncFunction::createStructure(init.vm, init.global, init.prototype));
- init.setConstructor(PropertyName(nullptr), AsyncFunctionConstructor::create(init.vm, AsyncFunctionConstructor::createStructure(init.vm, init.global, init.global->m_functionConstructor.get()), asyncFunctionPrototype));
-
- init.global->putDirectWithoutTransition(init.vm, init.vm.propertyNames->builtinNames().asyncFunctionResumePrivateName(), JSFunction::createBuiltinFunction(init.vm, asyncFunctionPrototypeAsyncFunctionResumeCodeGenerator(init.vm), init.global), DontEnum | DontDelete | ReadOnly);
- });
+ m_asyncFunctionPrototype.set(vm, this, AsyncFunctionPrototype::create(vm, AsyncFunctionPrototype::createStructure(vm, this, m_functionPrototype.get())));
+ AsyncFunctionConstructor* asyncFunctionConstructor = AsyncFunctionConstructor::create(vm, AsyncFunctionConstructor::createStructure(vm, this, functionConstructor), m_asyncFunctionPrototype.get());
+ m_asyncFunctionPrototype->putDirectWithoutTransition(vm, vm.propertyNames->constructor, asyncFunctionConstructor, DontEnum | ReadOnly);
+ m_asyncFunctionStructure.set(vm, this, JSAsyncFunction::createStructure(vm, this, m_asyncFunctionPrototype.get()));
m_objectPrototype->putDirectWithoutTransition(vm, vm.propertyNames->constructor, objectConstructor, DontEnum);
m_functionPrototype->putDirectWithoutTransition(vm, vm.propertyNames->constructor, functionConstructor, DontEnum);
@@ -1175,7 +1169,6 @@
thisObject->m_throwTypeErrorGetterSetter.visit(visitor);
visitor.append(&thisObject->m_throwTypeErrorArgumentsCalleeAndCallerGetterSetter);
visitor.append(&thisObject->m_moduleLoader);
- visitor.append(&thisObject->m_functionConstructor);
visitor.append(&thisObject->m_objectPrototype);
visitor.append(&thisObject->m_functionPrototype);
@@ -1184,7 +1177,7 @@
visitor.append(&thisObject->m_iteratorPrototype);
visitor.append(&thisObject->m_generatorFunctionPrototype);
visitor.append(&thisObject->m_generatorPrototype);
- thisObject->m_asyncFunctionStructure.visit(visitor);
+ visitor.append(&thisObject->m_asyncFunctionPrototype);
visitor.append(&thisObject->m_moduleLoaderPrototype);
thisObject->m_debuggerScopeStructure.visit(visitor);
@@ -1220,6 +1213,7 @@
visitor.append(&thisObject->m_symbolObjectStructure);
visitor.append(&thisObject->m_regExpStructure);
visitor.append(&thisObject->m_generatorFunctionStructure);
+ visitor.append(&thisObject->m_asyncFunctionStructure);
visitor.append(&thisObject->m_iteratorResultObjectStructure);
visitor.append(&thisObject->m_regExpMatchesArrayStructure);
visitor.append(&thisObject->m_moduleRecordStructure);
diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.h b/Source/JavaScriptCore/runtime/JSGlobalObject.h
index 6b1bff8..30918cd 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalObject.h
+++ b/Source/JavaScriptCore/runtime/JSGlobalObject.h
@@ -241,7 +241,6 @@
LazyProperty<JSGlobalObject, NativeErrorConstructor> m_syntaxErrorConstructor;
WriteBarrier<NativeErrorConstructor> m_typeErrorConstructor;
LazyProperty<JSGlobalObject, NativeErrorConstructor> m_URIErrorConstructor;
- WriteBarrier<FunctionConstructor> m_functionConstructor;
WriteBarrier<ObjectConstructor> m_objectConstructor;
WriteBarrier<ArrayConstructor> m_arrayConstructor;
WriteBarrier<JSPromiseConstructor> m_promiseConstructor;
@@ -316,7 +315,8 @@
PropertyOffset m_functionNameOffset;
WriteBarrier<Structure> m_privateNameStructure;
WriteBarrier<Structure> m_regExpStructure;
- LazyClassStructure m_asyncFunctionStructure;
+ WriteBarrier<AsyncFunctionPrototype> m_asyncFunctionPrototype;
+ WriteBarrier<Structure> m_asyncFunctionStructure;
WriteBarrier<Structure> m_generatorFunctionStructure;
WriteBarrier<Structure> m_dollarVMStructure;
WriteBarrier<Structure> m_iteratorResultObjectStructure;
@@ -550,19 +550,7 @@
IteratorPrototype* iteratorPrototype() const { return m_iteratorPrototype.get(); }
GeneratorFunctionPrototype* generatorFunctionPrototype() const { return m_generatorFunctionPrototype.get(); }
GeneratorPrototype* generatorPrototype() const { return m_generatorPrototype.get(); }
-
- LazyClassStructure& lazyAsyncFunctionStructure()
- {
- return m_asyncFunctionStructure;
- }
- const LazyClassStructure& lazyAsyncFunctionStructure() const
- {
- return m_asyncFunctionStructure;
- }
- AsyncFunctionPrototype* asyncFunctionPrototype() const { return reinterpret_cast<AsyncFunctionPrototype*>(lazyAsyncFunctionStructure().prototype(this)); }
- AsyncFunctionPrototype* asyncFunctionPrototypeConcurrently() const { return reinterpret_cast<AsyncFunctionPrototype*>(lazyAsyncFunctionStructure().prototypeConcurrently()); }
- Structure* asyncFunctionStructure() const { return lazyAsyncFunctionStructure().get(this); }
- Structure* asyncFunctionStructureConcurrently() const { return lazyAsyncFunctionStructure().getConcurrently(); }
+ AsyncFunctionPrototype* asyncFunctionPrototype() const { return m_asyncFunctionPrototype.get(); }
Structure* debuggerScopeStructure() const { return m_debuggerScopeStructure.get(this); }
Structure* withScopeStructure() const { return m_withScopeStructure.get(this); }
@@ -622,6 +610,7 @@
Structure* mapStructure() const { return m_mapStructure.get(); }
Structure* regExpStructure() const { return m_regExpStructure.get(); }
Structure* generatorFunctionStructure() const { return m_generatorFunctionStructure.get(); }
+ Structure* asyncFunctionStructure() const { return m_asyncFunctionStructure.get(); }
Structure* setStructure() const { return m_setStructure.get(this); }
Structure* stringObjectStructure() const { return m_stringObjectStructure.get(); }
Structure* symbolObjectStructure() const { return m_symbolObjectStructure.get(); }