summaryrefslogtreecommitdiff
path: root/deps/v8/src/builtins/builtins-generator-gen.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/builtins/builtins-generator-gen.cc')
-rw-r--r--deps/v8/src/builtins/builtins-generator-gen.cc115
1 files changed, 83 insertions, 32 deletions
diff --git a/deps/v8/src/builtins/builtins-generator-gen.cc b/deps/v8/src/builtins/builtins-generator-gen.cc
index b011f1e5cd..2dbf34fcff 100644
--- a/deps/v8/src/builtins/builtins-generator-gen.cc
+++ b/deps/v8/src/builtins/builtins-generator-gen.cc
@@ -18,16 +18,15 @@ class GeneratorBuiltinsAssembler : public CodeStubAssembler {
: CodeStubAssembler(state) {}
protected:
- void GeneratorPrototypeResume(Node* receiver, Node* value, Node* context,
+ void GeneratorPrototypeResume(CodeStubArguments* args, Node* receiver,
+ Node* value, Node* context,
JSGeneratorObject::ResumeMode resume_mode,
char const* const method_name);
};
void GeneratorBuiltinsAssembler::GeneratorPrototypeResume(
- Node* receiver, Node* value, Node* context,
+ CodeStubArguments* args, Node* receiver, Node* value, Node* context,
JSGeneratorObject::ResumeMode resume_mode, char const* const method_name) {
- Node* closed = SmiConstant(JSGeneratorObject::kGeneratorClosed);
-
// Check if the {receiver} is actually a JSGeneratorObject.
Label if_receiverisincompatible(this, Label::kDeferred);
GotoIf(TaggedIsSmi(receiver), &if_receiverisincompatible);
@@ -41,49 +40,70 @@ void GeneratorBuiltinsAssembler::GeneratorPrototypeResume(
LoadObjectField(receiver, JSGeneratorObject::kContinuationOffset);
Label if_receiverisclosed(this, Label::kDeferred),
if_receiverisrunning(this, Label::kDeferred);
+ Node* closed = SmiConstant(JSGeneratorObject::kGeneratorClosed);
GotoIf(SmiEqual(receiver_continuation, closed), &if_receiverisclosed);
DCHECK_LT(JSGeneratorObject::kGeneratorExecuting,
JSGeneratorObject::kGeneratorClosed);
GotoIf(SmiLessThan(receiver_continuation, closed), &if_receiverisrunning);
// Resume the {receiver} using our trampoline.
- Node* result =
- CallStub(CodeFactory::ResumeGenerator(isolate()), context, value,
- receiver, SmiConstant(resume_mode),
- SmiConstant(static_cast<int>(SuspendFlags::kGeneratorYield)));
- Return(result);
+ VARIABLE(var_exception, MachineRepresentation::kTagged, UndefinedConstant());
+ Label if_exception(this, Label::kDeferred), if_final_return(this);
+ Node* result = CallStub(CodeFactory::ResumeGenerator(isolate()), context,
+ value, receiver, SmiConstant(resume_mode));
+ // Make sure we close the generator if there was an exception.
+ GotoIfException(result, &if_exception, &var_exception);
+
+ // If the generator is not suspended (i.e., its state is 'executing'),
+ // close it and wrap the return value in IteratorResult.
+ Node* result_continuation =
+ LoadObjectField(receiver, JSGeneratorObject::kContinuationOffset);
+
+ // The generator function should not close the generator by itself, let's
+ // check it is indeed not closed yet.
+ CSA_ASSERT(this, SmiNotEqual(result_continuation, closed));
+
+ Node* executing = SmiConstant(JSGeneratorObject::kGeneratorExecuting);
+ GotoIf(SmiEqual(result_continuation, executing), &if_final_return);
+
+ args->PopAndReturn(result);
+
+ BIND(&if_final_return);
+ {
+ // Close the generator.
+ StoreObjectFieldNoWriteBarrier(
+ receiver, JSGeneratorObject::kContinuationOffset, closed);
+ // Return the wrapped result.
+ args->PopAndReturn(CallBuiltin(Builtins::kCreateIterResultObject, context,
+ result, TrueConstant()));
+ }
BIND(&if_receiverisincompatible);
{
// The {receiver} is not a valid JSGeneratorObject.
CallRuntime(Runtime::kThrowIncompatibleMethodReceiver, context,
- HeapConstant(
- factory()->NewStringFromAsciiChecked(method_name, TENURED)),
- receiver);
+ StringConstant(method_name), receiver);
Unreachable();
}
BIND(&if_receiverisclosed);
{
- Callable create_iter_result_object =
- CodeFactory::CreateIterResultObject(isolate());
-
// The {receiver} is closed already.
Node* result = nullptr;
switch (resume_mode) {
case JSGeneratorObject::kNext:
- result = CallStub(create_iter_result_object, context,
- UndefinedConstant(), TrueConstant());
+ result = CallBuiltin(Builtins::kCreateIterResultObject, context,
+ UndefinedConstant(), TrueConstant());
break;
case JSGeneratorObject::kReturn:
- result =
- CallStub(create_iter_result_object, context, value, TrueConstant());
+ result = CallBuiltin(Builtins::kCreateIterResultObject, context, value,
+ TrueConstant());
break;
case JSGeneratorObject::kThrow:
result = CallRuntime(Runtime::kThrow, context, value);
break;
}
- Return(result);
+ args->PopAndReturn(result);
}
BIND(&if_receiverisrunning);
@@ -91,32 +111,63 @@ void GeneratorBuiltinsAssembler::GeneratorPrototypeResume(
CallRuntime(Runtime::kThrowGeneratorRunning, context);
Unreachable();
}
+
+ BIND(&if_exception);
+ {
+ StoreObjectFieldNoWriteBarrier(
+ receiver, JSGeneratorObject::kContinuationOffset, closed);
+ CallRuntime(Runtime::kReThrow, context, var_exception.value());
+ Unreachable();
+ }
}
// ES6 #sec-generator.prototype.next
TF_BUILTIN(GeneratorPrototypeNext, GeneratorBuiltinsAssembler) {
- Node* receiver = Parameter(Descriptor::kReceiver);
- Node* value = Parameter(Descriptor::kValue);
- Node* context = Parameter(Descriptor::kContext);
- GeneratorPrototypeResume(receiver, value, context, JSGeneratorObject::kNext,
+ const int kValueArg = 0;
+
+ Node* argc =
+ ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
+ CodeStubArguments args(this, argc);
+
+ Node* receiver = args.GetReceiver();
+ Node* value = args.GetOptionalArgumentValue(kValueArg);
+ Node* context = Parameter(BuiltinDescriptor::kContext);
+
+ GeneratorPrototypeResume(&args, receiver, value, context,
+ JSGeneratorObject::kNext,
"[Generator].prototype.next");
}
// ES6 #sec-generator.prototype.return
TF_BUILTIN(GeneratorPrototypeReturn, GeneratorBuiltinsAssembler) {
- Node* receiver = Parameter(Descriptor::kReceiver);
- Node* value = Parameter(Descriptor::kValue);
- Node* context = Parameter(Descriptor::kContext);
- GeneratorPrototypeResume(receiver, value, context, JSGeneratorObject::kReturn,
+ const int kValueArg = 0;
+
+ Node* argc =
+ ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
+ CodeStubArguments args(this, argc);
+
+ Node* receiver = args.GetReceiver();
+ Node* value = args.GetOptionalArgumentValue(kValueArg);
+ Node* context = Parameter(BuiltinDescriptor::kContext);
+
+ GeneratorPrototypeResume(&args, receiver, value, context,
+ JSGeneratorObject::kReturn,
"[Generator].prototype.return");
}
// ES6 #sec-generator.prototype.throw
TF_BUILTIN(GeneratorPrototypeThrow, GeneratorBuiltinsAssembler) {
- Node* receiver = Parameter(Descriptor::kReceiver);
- Node* exception = Parameter(Descriptor::kException);
- Node* context = Parameter(Descriptor::kContext);
- GeneratorPrototypeResume(receiver, exception, context,
+ const int kExceptionArg = 0;
+
+ Node* argc =
+ ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
+ CodeStubArguments args(this, argc);
+
+ Node* receiver = args.GetReceiver();
+ Node* exception = args.GetOptionalArgumentValue(kExceptionArg);
+ Node* context = Parameter(BuiltinDescriptor::kContext);
+
+ GeneratorPrototypeResume(&args, receiver, exception, context,
JSGeneratorObject::kThrow,
"[Generator].prototype.throw");
}