LCOV - code coverage report
Current view: top level - src/builtins - builtins-generator-gen.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 67 67 100.0 %
Date: 2019-04-19 Functions: 8 8 100.0 %

          Line data    Source code
       1             : // Copyright 2016 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/builtins/builtins-utils-gen.h"
       6             : #include "src/builtins/builtins.h"
       7             : #include "src/code-factory.h"
       8             : #include "src/code-stub-assembler.h"
       9             : #include "src/isolate.h"
      10             : #include "src/objects-inl.h"
      11             : #include "src/objects/js-generator.h"
      12             : 
      13             : namespace v8 {
      14             : namespace internal {
      15             : 
      16         168 : class GeneratorBuiltinsAssembler : public CodeStubAssembler {
      17             :  public:
      18             :   explicit GeneratorBuiltinsAssembler(compiler::CodeAssemblerState* state)
      19         168 :       : CodeStubAssembler(state) {}
      20             : 
      21             :  protected:
      22             :   void GeneratorPrototypeResume(CodeStubArguments* args, Node* receiver,
      23             :                                 Node* value, Node* context,
      24             :                                 JSGeneratorObject::ResumeMode resume_mode,
      25             :                                 char const* const method_name);
      26             : };
      27             : 
      28         168 : void GeneratorBuiltinsAssembler::GeneratorPrototypeResume(
      29             :     CodeStubArguments* args, Node* receiver, Node* value, Node* context,
      30             :     JSGeneratorObject::ResumeMode resume_mode, char const* const method_name) {
      31             :   // Check if the {receiver} is actually a JSGeneratorObject.
      32         168 :   ThrowIfNotInstanceType(context, receiver, JS_GENERATOR_OBJECT_TYPE,
      33         168 :                          method_name);
      34             : 
      35             :   // Check if the {receiver} is running or already closed.
      36             :   TNode<Smi> receiver_continuation =
      37         168 :       CAST(LoadObjectField(receiver, JSGeneratorObject::kContinuationOffset));
      38         336 :   Label if_receiverisclosed(this, Label::kDeferred),
      39         168 :       if_receiverisrunning(this, Label::kDeferred);
      40         168 :   TNode<Smi> closed = SmiConstant(JSGeneratorObject::kGeneratorClosed);
      41         336 :   GotoIf(SmiEqual(receiver_continuation, closed), &if_receiverisclosed);
      42             :   DCHECK_LT(JSGeneratorObject::kGeneratorExecuting,
      43             :             JSGeneratorObject::kGeneratorClosed);
      44         336 :   GotoIf(SmiLessThan(receiver_continuation, closed), &if_receiverisrunning);
      45             : 
      46             :   // Remember the {resume_mode} for the {receiver}.
      47             :   StoreObjectFieldNoWriteBarrier(receiver, JSGeneratorObject::kResumeModeOffset,
      48         168 :                                  SmiConstant(resume_mode));
      49             : 
      50             :   // Resume the {receiver} using our trampoline.
      51         504 :   VARIABLE(var_exception, MachineRepresentation::kTagged, UndefinedConstant());
      52         168 :   Label if_exception(this, Label::kDeferred), if_final_return(this);
      53         504 :   Node* result = CallStub(CodeFactory::ResumeGenerator(isolate()), context,
      54         168 :                           value, receiver);
      55             :   // Make sure we close the generator if there was an exception.
      56         168 :   GotoIfException(result, &if_exception, &var_exception);
      57             : 
      58             :   // If the generator is not suspended (i.e., its state is 'executing'),
      59             :   // close it and wrap the return value in IteratorResult.
      60             :   TNode<Smi> result_continuation =
      61         168 :       CAST(LoadObjectField(receiver, JSGeneratorObject::kContinuationOffset));
      62             : 
      63             :   // The generator function should not close the generator by itself, let's
      64             :   // check it is indeed not closed yet.
      65             :   CSA_ASSERT(this, SmiNotEqual(result_continuation, closed));
      66             : 
      67         168 :   TNode<Smi> executing = SmiConstant(JSGeneratorObject::kGeneratorExecuting);
      68         336 :   GotoIf(SmiEqual(result_continuation, executing), &if_final_return);
      69             : 
      70         168 :   args->PopAndReturn(result);
      71             : 
      72         168 :   BIND(&if_final_return);
      73             :   {
      74             :     // Close the generator.
      75             :     StoreObjectFieldNoWriteBarrier(
      76         168 :         receiver, JSGeneratorObject::kContinuationOffset, closed);
      77             :     // Return the wrapped result.
      78         336 :     args->PopAndReturn(CallBuiltin(Builtins::kCreateIterResultObject, context,
      79         504 :                                    result, TrueConstant()));
      80             :   }
      81             : 
      82         168 :   BIND(&if_receiverisclosed);
      83             :   {
      84             :     // The {receiver} is closed already.
      85             :     Node* result = nullptr;
      86         168 :     switch (resume_mode) {
      87             :       case JSGeneratorObject::kNext:
      88         112 :         result = CallBuiltin(Builtins::kCreateIterResultObject, context,
      89         112 :                              UndefinedConstant(), TrueConstant());
      90          56 :         break;
      91             :       case JSGeneratorObject::kReturn:
      92         112 :         result = CallBuiltin(Builtins::kCreateIterResultObject, context, value,
      93         112 :                              TrueConstant());
      94          56 :         break;
      95             :       case JSGeneratorObject::kThrow:
      96             :         result = CallRuntime(Runtime::kThrow, context, value);
      97          56 :         break;
      98             :     }
      99         168 :     args->PopAndReturn(result);
     100             :   }
     101             : 
     102         168 :   BIND(&if_receiverisrunning);
     103         168 :   { ThrowTypeError(context, MessageTemplate::kGeneratorRunning); }
     104             : 
     105         168 :   BIND(&if_exception);
     106             :   {
     107             :     StoreObjectFieldNoWriteBarrier(
     108         168 :         receiver, JSGeneratorObject::kContinuationOffset, closed);
     109         168 :     CallRuntime(Runtime::kReThrow, context, var_exception.value());
     110         168 :     Unreachable();
     111             :   }
     112         168 : }
     113             : 
     114             : // ES6 #sec-generator.prototype.next
     115         280 : TF_BUILTIN(GeneratorPrototypeNext, GeneratorBuiltinsAssembler) {
     116             :   const int kValueArg = 0;
     117             : 
     118             :   Node* argc =
     119         112 :       ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
     120          56 :   CodeStubArguments args(this, argc);
     121             : 
     122         112 :   Node* receiver = args.GetReceiver();
     123         112 :   Node* value = args.GetOptionalArgumentValue(kValueArg);
     124             :   Node* context = Parameter(Descriptor::kContext);
     125             : 
     126          56 :   GeneratorPrototypeResume(&args, receiver, value, context,
     127             :                            JSGeneratorObject::kNext,
     128          56 :                            "[Generator].prototype.next");
     129          56 : }
     130             : 
     131             : // ES6 #sec-generator.prototype.return
     132         280 : TF_BUILTIN(GeneratorPrototypeReturn, GeneratorBuiltinsAssembler) {
     133             :   const int kValueArg = 0;
     134             : 
     135             :   Node* argc =
     136         112 :       ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
     137          56 :   CodeStubArguments args(this, argc);
     138             : 
     139         112 :   Node* receiver = args.GetReceiver();
     140         112 :   Node* value = args.GetOptionalArgumentValue(kValueArg);
     141             :   Node* context = Parameter(Descriptor::kContext);
     142             : 
     143          56 :   GeneratorPrototypeResume(&args, receiver, value, context,
     144             :                            JSGeneratorObject::kReturn,
     145          56 :                            "[Generator].prototype.return");
     146          56 : }
     147             : 
     148             : // ES6 #sec-generator.prototype.throw
     149         280 : TF_BUILTIN(GeneratorPrototypeThrow, GeneratorBuiltinsAssembler) {
     150             :   const int kExceptionArg = 0;
     151             : 
     152             :   Node* argc =
     153         112 :       ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
     154          56 :   CodeStubArguments args(this, argc);
     155             : 
     156         112 :   Node* receiver = args.GetReceiver();
     157         112 :   Node* exception = args.GetOptionalArgumentValue(kExceptionArg);
     158             :   Node* context = Parameter(Descriptor::kContext);
     159             : 
     160          56 :   GeneratorPrototypeResume(&args, receiver, exception, context,
     161             :                            JSGeneratorObject::kThrow,
     162          56 :                            "[Generator].prototype.throw");
     163          56 : }
     164             : 
     165             : }  // namespace internal
     166       59480 : }  // namespace v8

Generated by: LCOV version 1.10