diff options
Diffstat (limited to 'deps/v8/src/builtins/builtins-generator-gen.cc')
-rw-r--r-- | deps/v8/src/builtins/builtins-generator-gen.cc | 115 |
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"); } |