V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
builtins-generator-gen.cc
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 
17  public:
19  : 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 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  ThrowIfNotInstanceType(context, receiver, JS_GENERATOR_OBJECT_TYPE,
33  method_name);
34 
35  // Check if the {receiver} is running or already closed.
36  TNode<Smi> receiver_continuation =
37  CAST(LoadObjectField(receiver, JSGeneratorObject::kContinuationOffset));
38  Label if_receiverisclosed(this, Label::kDeferred),
39  if_receiverisrunning(this, Label::kDeferred);
40  TNode<Smi> closed = SmiConstant(JSGeneratorObject::kGeneratorClosed);
41  GotoIf(SmiEqual(receiver_continuation, closed), &if_receiverisclosed);
42  DCHECK_LT(JSGeneratorObject::kGeneratorExecuting,
43  JSGeneratorObject::kGeneratorClosed);
44  GotoIf(SmiLessThan(receiver_continuation, closed), &if_receiverisrunning);
45 
46  // Remember the {resume_mode} for the {receiver}.
47  StoreObjectFieldNoWriteBarrier(receiver, JSGeneratorObject::kResumeModeOffset,
48  SmiConstant(resume_mode));
49 
50  // Resume the {receiver} using our trampoline.
51  VARIABLE(var_exception, MachineRepresentation::kTagged, UndefinedConstant());
52  Label if_exception(this, Label::kDeferred), if_final_return(this);
53  Node* result = CallStub(CodeFactory::ResumeGenerator(isolate()), context,
54  value, receiver);
55  // Make sure we close the generator if there was an exception.
56  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  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  TNode<Smi> executing = SmiConstant(JSGeneratorObject::kGeneratorExecuting);
68  GotoIf(SmiEqual(result_continuation, executing), &if_final_return);
69 
70  args->PopAndReturn(result);
71 
72  BIND(&if_final_return);
73  {
74  // Close the generator.
75  StoreObjectFieldNoWriteBarrier(
76  receiver, JSGeneratorObject::kContinuationOffset, closed);
77  // Return the wrapped result.
78  args->PopAndReturn(CallBuiltin(Builtins::kCreateIterResultObject, context,
79  result, TrueConstant()));
80  }
81 
82  BIND(&if_receiverisclosed);
83  {
84  // The {receiver} is closed already.
85  Node* result = nullptr;
86  switch (resume_mode) {
87  case JSGeneratorObject::kNext:
88  result = CallBuiltin(Builtins::kCreateIterResultObject, context,
89  UndefinedConstant(), TrueConstant());
90  break;
91  case JSGeneratorObject::kReturn:
92  result = CallBuiltin(Builtins::kCreateIterResultObject, context, value,
93  TrueConstant());
94  break;
95  case JSGeneratorObject::kThrow:
96  result = CallRuntime(Runtime::kThrow, context, value);
97  break;
98  }
99  args->PopAndReturn(result);
100  }
101 
102  BIND(&if_receiverisrunning);
103  { ThrowTypeError(context, MessageTemplate::kGeneratorRunning); }
104 
105  BIND(&if_exception);
106  {
107  StoreObjectFieldNoWriteBarrier(
108  receiver, JSGeneratorObject::kContinuationOffset, closed);
109  CallRuntime(Runtime::kReThrow, context, var_exception.value());
110  Unreachable();
111  }
112 }
113 
114 // ES6 #sec-generator.prototype.next
115 TF_BUILTIN(GeneratorPrototypeNext, GeneratorBuiltinsAssembler) {
116  const int kValueArg = 0;
117 
118  Node* argc =
119  ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
120  CodeStubArguments args(this, argc);
121 
122  Node* receiver = args.GetReceiver();
123  Node* value = args.GetOptionalArgumentValue(kValueArg);
124  Node* context = Parameter(Descriptor::kContext);
125 
126  GeneratorPrototypeResume(&args, receiver, value, context,
127  JSGeneratorObject::kNext,
128  "[Generator].prototype.next");
129 }
130 
131 // ES6 #sec-generator.prototype.return
132 TF_BUILTIN(GeneratorPrototypeReturn, GeneratorBuiltinsAssembler) {
133  const int kValueArg = 0;
134 
135  Node* argc =
136  ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
137  CodeStubArguments args(this, argc);
138 
139  Node* receiver = args.GetReceiver();
140  Node* value = args.GetOptionalArgumentValue(kValueArg);
141  Node* context = Parameter(Descriptor::kContext);
142 
143  GeneratorPrototypeResume(&args, receiver, value, context,
144  JSGeneratorObject::kReturn,
145  "[Generator].prototype.return");
146 }
147 
148 // ES6 #sec-generator.prototype.throw
149 TF_BUILTIN(GeneratorPrototypeThrow, GeneratorBuiltinsAssembler) {
150  const int kExceptionArg = 0;
151 
152  Node* argc =
153  ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
154  CodeStubArguments args(this, argc);
155 
156  Node* receiver = args.GetReceiver();
157  Node* exception = args.GetOptionalArgumentValue(kExceptionArg);
158  Node* context = Parameter(Descriptor::kContext);
159 
160  GeneratorPrototypeResume(&args, receiver, exception, context,
161  JSGeneratorObject::kThrow,
162  "[Generator].prototype.throw");
163 }
164 
165 } // namespace internal
166 } // namespace v8
Definition: libplatform.h:13