[ES6] Handle new_generator_func / new_generator_func_exp in DFG / FTL
https://bugs.webkit.org/show_bug.cgi?id=152227

Reviewed by Saam Barati.

Source/JavaScriptCore:

This patch introduces new_generator_func / new_generator_func_exp into DFG and FTL.
We add a new DFG Node, NewGeneratorFunction. It will construct a function with GeneratorFunction's structure.
The structure of GeneratorFunction is different from one of Function because GeneratorFunction has the different __proto__.

Instead of extending NewFunction / PhantomNewFunction, we just added new DFG nodes, NewGeneratorFunction and PhantomNewGeneratorFunction.
This is because NewGeneratorFunction will generate an object that has different class info from JSFunction (And if JSGeneratorFunction is extended, its size will become different from JSFunction).
So, rather than extending NewFunction with generator flag, just adding new DFG nodes seems cleaner.

Object allocation sinking phase will change NewGeneratorFunction to PhantomNewGeneratorFunction and defer or eliminate its actual materialization.
It is completely the same to NewFunction and PhantomNewFunction.
And when OSR exit occurs, we need to execute deferred NewGeneratorFunction since Baseline JIT does not consider it.
So in FTL operation, we should create JSGeneratorFunction if we see PhantomNewGeneratorFunction materialization.

* 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:
(JSC::DFG::mayExit):
* dfg/DFGNode.h:
(JSC::DFG::Node::convertToPhantomNewFunction):
(JSC::DFG::Node::convertToPhantomNewGeneratorFunction):
(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:
(JSC::DFG::PredictionPropagationPhase::propagate):
* 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:
(JSC::DFG::Validate::validateCPS):
(JSC::DFG::Validate::validateSSA):
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::DFG::LowerDFGToLLVM::compileNode):
(JSC::FTL::DFG::LowerDFGToLLVM::compileNewFunction):
* ftl/FTLOperations.cpp:
(JSC::FTL::operationPopulateObjectInOSR):
(JSC::FTL::operationMaterializeObjectInOSR):
* tests/stress/generator-function-create-optimized.js: Added.
(shouldBe):
(g):
(test.return.gen):
(test):
(test2.gen):
(test2):
* tests/stress/generator-function-declaration-sinking-no-double-allocate.js: Added.
(shouldBe):
(GeneratorFunctionPrototype):
(call):
(f):
(sink):
* tests/stress/generator-function-declaration-sinking-osrexit.js: Added.
(shouldBe):
(GeneratorFunctionPrototype):
(g):
(f):
(sink):
* tests/stress/generator-function-declaration-sinking-put.js: Added.
(shouldBe):
(GeneratorFunctionPrototype):
(g):
(f):
(sink):
* tests/stress/generator-function-expression-sinking-no-double-allocate.js: Added.
(shouldBe):
(GeneratorFunctionPrototype):
(call):
(f):
(sink):
* tests/stress/generator-function-expression-sinking-osrexit.js: Added.
(shouldBe):
(GeneratorFunctionPrototype):
(g):
(sink):
* tests/stress/generator-function-expression-sinking-put.js: Added.
(shouldBe):
(GeneratorFunctionPrototype):
(g):
(sink):

LayoutTests:

Make the test taking longer time.

* js/regress/script-tests/generator-function-create.js:
(test):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@194216 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp b/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp
index 12ab163..f6719f5 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, NewArrowFunction };
+    enum class Kind { Escaped, Object, Activation, Function, ArrowFunction, GeneratorFunction };
 
     explicit Allocation(Node* identifier = nullptr, Kind kind = Kind::Escaped)
         : m_identifier(identifier)
@@ -233,12 +233,7 @@
 
     bool isFunctionAllocation() const
     {
-        return m_kind == Kind::Function || m_kind == Kind::NewArrowFunction;
-    }
-    
-    bool isArrowFunctionAllocation() const
-    {
-        return m_kind == Kind::NewArrowFunction;
+        return m_kind == Kind::Function || m_kind == Kind::ArrowFunction || m_kind == Kind::GeneratorFunction;
     }
 
     bool operator==(const Allocation& other) const
@@ -274,8 +269,12 @@
             out.print("Function");
             break;
                 
-        case Kind::NewArrowFunction:
-            out.print("NewArrowFunction");
+        case Kind::ArrowFunction:
+            out.print("ArrowFunction");
+            break;
+
+        case Kind::GeneratorFunction:
+            out.print("GeneratorFunction");
             break;
 
         case Kind::Activation:
@@ -837,13 +836,19 @@
             break;
 
         case NewFunction:
-        case NewArrowFunction: {
+        case NewArrowFunction:
+        case NewGeneratorFunction: {
             if (node->castOperand<FunctionExecutable*>()->singletonFunction()->isStillValid()) {
                 m_heap.escape(node->child1().node());
                 break;
             }
             
-            target = &m_heap.newAllocation(node, Allocation::Kind::Function);
+            if (node->op() == NewGeneratorFunction)
+                target = &m_heap.newAllocation(node, Allocation::Kind::GeneratorFunction);
+            else if (node->op() == NewArrowFunction)
+                target = &m_heap.newAllocation(node, Allocation::Kind::ArrowFunction);
+            else
+                target = &m_heap.newAllocation(node, Allocation::Kind::Function);
             writes.add(FunctionExecutablePLoc, LazyNode(node->cellOperand()));
             writes.add(FunctionActivationPLoc, LazyNode(node->child1().node()));
             break;
@@ -1446,11 +1451,14 @@
                 OpInfo(set), OpInfo(data), 0, 0);
         }
 
-        case Allocation::Kind::NewArrowFunction:
+        case Allocation::Kind::ArrowFunction:
+        case Allocation::Kind::GeneratorFunction:
         case Allocation::Kind::Function: {
             FrozenValue* executable = allocation.identifier()->cellOperand();
             
-            NodeType nodeType = allocation.kind() == Allocation::Kind::NewArrowFunction ? NewArrowFunction : NewFunction;
+            NodeType nodeType =
+                allocation.kind() == Allocation::Kind::ArrowFunction ? NewArrowFunction :
+                allocation.kind() == Allocation::Kind::GeneratorFunction ? NewGeneratorFunction : NewFunction;
             
             return m_graph.addNode(
                 allocation.identifier()->prediction(), nodeType,
@@ -1785,6 +1793,10 @@
                         node->convertToPhantomNewFunction();
                         break;
 
+                    case NewGeneratorFunction:
+                        node->convertToPhantomNewGeneratorFunction();
+                        break;
+
                     case CreateActivation:
                         node->convertToPhantomCreateActivation();
                         break;
@@ -2033,7 +2045,8 @@
         }
         
         case NewFunction:
-        case NewArrowFunction: {
+        case NewArrowFunction:
+        case NewGeneratorFunction: {
             Vector<PromotedHeapLocation> locations = m_locationsForAllocation.get(escapee);
             ASSERT(locations.size() == 2);