Commit 04233410 authored by caitp's avatar caitp Committed by Commit bot

[async-iteration] implement Async-from-Sync Iterator

Introduce a new Object to allow GetIterator("async") to function when the
iterable does not have a Symbol.asyncIterator method.

This patch has been split out from https://codereview.chromium.org/2622833002/
and incorporates test cases.

BUG=v8:5855, v8:4483
R=jgruber@chromium.org, rmcilroy@chromium.org, neis@chromium.org
TBR=hpayer@chromium.org, bmeurer@chromium.org

Review-Url: https://codereview.chromium.org/2645313003
Cr-Commit-Position: refs/heads/master@{#43419}
parent 8cfe45b6
...@@ -930,6 +930,7 @@ v8_source_set("v8_base") { ...@@ -930,6 +930,7 @@ v8_source_set("v8_base") {
"src/builtins/builtins-array.cc", "src/builtins/builtins-array.cc",
"src/builtins/builtins-arraybuffer.cc", "src/builtins/builtins-arraybuffer.cc",
"src/builtins/builtins-async-function.cc", "src/builtins/builtins-async-function.cc",
"src/builtins/builtins-async-iterator.cc",
"src/builtins/builtins-async.cc", "src/builtins/builtins-async.cc",
"src/builtins/builtins-async.h", "src/builtins/builtins-async.h",
"src/builtins/builtins-boolean.cc", "src/builtins/builtins-boolean.cc",
......
...@@ -220,6 +220,7 @@ AstType::bitset AstBitsetType::Lub(i::Map* map) { ...@@ -220,6 +220,7 @@ AstType::bitset AstBitsetType::Lub(i::Map* map) {
case JS_SET_ITERATOR_TYPE: case JS_SET_ITERATOR_TYPE:
case JS_MAP_ITERATOR_TYPE: case JS_MAP_ITERATOR_TYPE:
case JS_STRING_ITERATOR_TYPE: case JS_STRING_ITERATOR_TYPE:
case JS_ASYNC_FROM_SYNC_ITERATOR_TYPE:
case JS_TYPED_ARRAY_KEY_ITERATOR_TYPE: case JS_TYPED_ARRAY_KEY_ITERATOR_TYPE:
case JS_FAST_ARRAY_KEY_ITERATOR_TYPE: case JS_FAST_ARRAY_KEY_ITERATOR_TYPE:
......
...@@ -172,6 +172,7 @@ class Genesis BASE_EMBEDDED { ...@@ -172,6 +172,7 @@ class Genesis BASE_EMBEDDED {
void CreateStrictModeFunctionMaps(Handle<JSFunction> empty); void CreateStrictModeFunctionMaps(Handle<JSFunction> empty);
void CreateIteratorMaps(Handle<JSFunction> empty); void CreateIteratorMaps(Handle<JSFunction> empty);
void CreateAsyncIteratorMaps();
void CreateAsyncFunctionMaps(Handle<JSFunction> empty); void CreateAsyncFunctionMaps(Handle<JSFunction> empty);
void CreateJSProxyMaps(); void CreateJSProxyMaps();
...@@ -785,6 +786,50 @@ void Genesis::CreateIteratorMaps(Handle<JSFunction> empty) { ...@@ -785,6 +786,50 @@ void Genesis::CreateIteratorMaps(Handle<JSFunction> empty) {
*generator_object_prototype_map); *generator_object_prototype_map);
} }
void Genesis::CreateAsyncIteratorMaps() {
// %AsyncIteratorPrototype%
// proposal-async-iteration/#sec-asynciteratorprototype
Handle<JSObject> async_iterator_prototype =
factory()->NewJSObject(isolate()->object_function(), TENURED);
Handle<JSFunction> async_iterator_prototype_iterator = SimpleCreateFunction(
isolate(), factory()->NewStringFromAsciiChecked("[Symbol.asyncIterator]"),
Builtins::kReturnReceiver, 0, true);
JSObject::AddProperty(async_iterator_prototype,
factory()->async_iterator_symbol(),
async_iterator_prototype_iterator, DONT_ENUM);
// %AsyncFromSyncIteratorPrototype%
// proposal-async-iteration/#sec-%asyncfromsynciteratorprototype%-object
Handle<JSObject> async_from_sync_iterator_prototype =
factory()->NewJSObject(isolate()->object_function(), TENURED);
SimpleInstallFunction(async_from_sync_iterator_prototype,
factory()->next_string(),
Builtins::kAsyncFromSyncIteratorPrototypeNext, 1, true);
SimpleInstallFunction(
async_from_sync_iterator_prototype, factory()->return_string(),
Builtins::kAsyncFromSyncIteratorPrototypeReturn, 1, true);
SimpleInstallFunction(
async_from_sync_iterator_prototype, factory()->throw_string(),
Builtins::kAsyncFromSyncIteratorPrototypeThrow, 1, true);
JSObject::AddProperty(
async_from_sync_iterator_prototype, factory()->to_string_tag_symbol(),
factory()->NewStringFromAsciiChecked("Async-from-Sync Iterator"),
static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY));
JSObject::ForceSetPrototype(async_from_sync_iterator_prototype,
async_iterator_prototype);
Handle<Map> async_from_sync_iterator_map = factory()->NewMap(
JS_ASYNC_FROM_SYNC_ITERATOR_TYPE, JSAsyncFromSyncIterator::kSize);
Map::SetPrototype(async_from_sync_iterator_map,
async_from_sync_iterator_prototype);
native_context()->set_async_from_sync_iterator_map(
*async_from_sync_iterator_map);
}
void Genesis::CreateAsyncFunctionMaps(Handle<JSFunction> empty) { void Genesis::CreateAsyncFunctionMaps(Handle<JSFunction> empty) {
// %AsyncFunctionPrototype% intrinsic // %AsyncFunctionPrototype% intrinsic
Handle<JSObject> async_function_prototype = Handle<JSObject> async_function_prototype =
...@@ -1295,6 +1340,16 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object, ...@@ -1295,6 +1340,16 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
class_function_map_->SetConstructor(*function_fun); class_function_map_->SetConstructor(*function_fun);
} }
{
// --- A s y n c F r o m S y n c I t e r a t o r
Handle<Code> code = isolate->builtins()->AsyncIteratorValueUnwrap();
Handle<SharedFunctionInfo> info =
factory->NewSharedFunctionInfo(factory->empty_string(), code, false);
info->set_internal_formal_parameter_count(1);
info->set_length(1);
native_context()->set_async_iterator_value_unwrap_shared_fun(*info);
}
{ // --- A r r a y --- { // --- A r r a y ---
Handle<JSFunction> array_function = Handle<JSFunction> array_function =
InstallFunction(global, "Array", JS_ARRAY_TYPE, JSArray::kSize, InstallFunction(global, "Array", JS_ARRAY_TYPE, JSArray::kSize,
...@@ -4761,6 +4816,7 @@ Genesis::Genesis( ...@@ -4761,6 +4816,7 @@ Genesis::Genesis(
Handle<JSFunction> empty_function = CreateEmptyFunction(isolate); Handle<JSFunction> empty_function = CreateEmptyFunction(isolate);
CreateStrictModeFunctionMaps(empty_function); CreateStrictModeFunctionMaps(empty_function);
CreateIteratorMaps(empty_function); CreateIteratorMaps(empty_function);
CreateAsyncIteratorMaps();
CreateAsyncFunctionMaps(empty_function); CreateAsyncFunctionMaps(empty_function);
Handle<JSGlobalObject> global_object = Handle<JSGlobalObject> global_object =
CreateNewGlobals(global_proxy_template, global_proxy); CreateNewGlobals(global_proxy_template, global_proxy);
......
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/builtins/builtins-async.h"
#include "src/builtins/builtins-utils.h"
#include "src/builtins/builtins.h"
#include "src/code-factory.h"
#include "src/code-stub-assembler.h"
#include "src/frames-inl.h"
namespace v8 {
namespace internal {
namespace {
// Describe fields of Context associated with the AsyncIterator unwrap closure.
class ValueUnwrapContext {
public:
enum Fields { kDoneSlot = Context::MIN_CONTEXT_SLOTS, kLength };
};
class AsyncFromSyncBuiltinsAssembler : public AsyncBuiltinsAssembler {
public:
explicit AsyncFromSyncBuiltinsAssembler(CodeAssemblerState* state)
: AsyncBuiltinsAssembler(state) {}
void ThrowIfNotAsyncFromSyncIterator(Node* const context, Node* const object,
Label* if_exception,
Variable* var_exception,
const char* method_name);
typedef std::function<void(Node* const context, Node* const promise,
Label* if_exception)>
UndefinedMethodHandler;
void Generate_AsyncFromSyncIteratorMethod(
Node* const context, Node* const iterator, Node* const sent_value,
Handle<Name> method_name, UndefinedMethodHandler&& if_method_undefined,
const char* operation_name,
Label::Type reject_label_type = Label::kDeferred,
Node* const initial_exception_value = nullptr);
Node* AllocateAsyncIteratorValueUnwrapContext(Node* native_context,
Node* done);
// Load "value" and "done" from an iterator result object. If an exception
// is thrown at any point, jumps to te `if_exception` label with exception
// stored in `var_exception`.
//
// Returns a Pair of Nodes, whose first element is the value of the "value"
// property, and whose second element is the value of the "done" property,
// converted to a Boolean if needed.
std::pair<Node*, Node*> LoadIteratorResult(Node* const context,
Node* const native_context,
Node* const iter_result,
Label* if_exception,
Variable* var_exception);
Node* CreateUnwrapClosure(Node* const native_context, Node* const done);
};
void AsyncFromSyncBuiltinsAssembler::ThrowIfNotAsyncFromSyncIterator(
Node* const context, Node* const object, Label* if_exception,
Variable* var_exception, const char* method_name) {
Label if_receiverisincompatible(this, Label::kDeferred), done(this);
GotoIf(TaggedIsSmi(object), &if_receiverisincompatible);
Branch(HasInstanceType(object, JS_ASYNC_FROM_SYNC_ITERATOR_TYPE), &done,
&if_receiverisincompatible);
Bind(&if_receiverisincompatible);
{
// If Type(O) is not Object, or if O does not have a [[SyncIterator]]
// internal slot, then
// Let badIteratorError be a new TypeError exception.
Node* const error =
MakeTypeError(MessageTemplate::kIncompatibleMethodReceiver, context,
CStringConstant(method_name), object);
// Perform ! Call(promiseCapability.[[Reject]], undefined,
// « badIteratorError »).
var_exception->Bind(error);
Goto(if_exception);
}
Bind(&done);
}
void AsyncFromSyncBuiltinsAssembler::Generate_AsyncFromSyncIteratorMethod(
Node* const context, Node* const iterator, Node* const sent_value,
Handle<Name> method_name, UndefinedMethodHandler&& if_method_undefined,
const char* operation_name, Label::Type reject_label_type,
Node* const initial_exception_value) {
Node* const native_context = LoadNativeContext(context);
Node* const promise = AllocateAndInitJSPromise(context);
Variable var_exception(this, MachineRepresentation::kTagged,
initial_exception_value == nullptr
? UndefinedConstant()
: initial_exception_value);
Label reject_promise(this, reject_label_type);
ThrowIfNotAsyncFromSyncIterator(context, iterator, &reject_promise,
&var_exception, operation_name);
Node* const sync_iterator =
LoadObjectField(iterator, JSAsyncFromSyncIterator::kSyncIteratorOffset);
Node* const method = GetProperty(context, sync_iterator, method_name);
if (if_method_undefined) {
Label if_isnotundefined(this);
GotoIfNot(IsUndefined(method), &if_isnotundefined);
if_method_undefined(native_context, promise, &reject_promise);
Bind(&if_isnotundefined);
}
Node* const iter_result = CallJS(CodeFactory::Call(isolate()), context,
method, sync_iterator, sent_value);
GotoIfException(iter_result, &reject_promise, &var_exception);
Node* value;
Node* done;
std::tie(value, done) = LoadIteratorResult(
context, native_context, iter_result, &reject_promise, &var_exception);
Node* const wrapper = AllocateAndInitJSPromise(context);
// Perform ! Call(valueWrapperCapability.[[Resolve]], undefined, «
// throwValue »).
InternalResolvePromise(context, wrapper, value);
// Let onFulfilled be a new built-in function object as defined in
// Async Iterator Value Unwrap Functions.
// Set onFulfilled.[[Done]] to throwDone.
Node* const on_fulfilled = CreateUnwrapClosure(native_context, done);
// Perform ! PerformPromiseThen(valueWrapperCapability.[[Promise]],
// onFulfilled, undefined, promiseCapability).
Node* const undefined = UndefinedConstant();
InternalPerformPromiseThen(context, wrapper, on_fulfilled, undefined, promise,
undefined, undefined);
Return(promise);
Bind(&reject_promise);
{
Node* const exception = var_exception.value();
InternalPromiseReject(context, promise, exception, TrueConstant());
Return(promise);
}
}
std::pair<Node*, Node*> AsyncFromSyncBuiltinsAssembler::LoadIteratorResult(
Node* const context, Node* const native_context, Node* const iter_result,
Label* if_exception, Variable* var_exception) {
Label if_fastpath(this), if_slowpath(this), merge(this), to_boolean(this),
done(this), if_notanobject(this, Label::kDeferred);
GotoIf(TaggedIsSmi(iter_result), &if_notanobject);
Node* const iter_result_map = LoadMap(iter_result);
GotoIfNot(IsJSReceiverMap(iter_result_map), &if_notanobject);
Node* const fast_iter_result_map =
LoadContextElement(native_context, Context::ITERATOR_RESULT_MAP_INDEX);
Variable var_value(this, MachineRepresentation::kTagged);
Variable var_done(this, MachineRepresentation::kTagged);
Branch(WordEqual(iter_result_map, fast_iter_result_map), &if_fastpath,
&if_slowpath);
Bind(&if_fastpath);
{
var_value.Bind(
LoadObjectField(iter_result, JSIteratorResult::kValueOffset));
var_done.Bind(LoadObjectField(iter_result, JSIteratorResult::kDoneOffset));
Goto(&merge);
}
Bind(&if_slowpath);
{
// Let nextValue be IteratorValue(nextResult).
// IfAbruptRejectPromise(nextValue, promiseCapability).
Node* const value =
GetProperty(context, iter_result, factory()->value_string());
GotoIfException(value, if_exception, var_exception);
// Let nextDone be IteratorComplete(nextResult).
// IfAbruptRejectPromise(nextDone, promiseCapability).
Node* const done =
GetProperty(context, iter_result, factory()->done_string());
GotoIfException(done, if_exception, var_exception);
var_value.Bind(value);
var_done.Bind(done);
Goto(&merge);
}
Bind(&if_notanobject);
{
// Sync iterator result is not an object --- Produce a TypeError and jump
// to the `if_exception` path.
Node* const error = MakeTypeError(
MessageTemplate::kIteratorResultNotAnObject, context, iter_result);
var_exception->Bind(error);
Goto(if_exception);
}
Bind(&merge);
// Ensure `iterResult.done` is a Boolean.
GotoIf(TaggedIsSmi(var_done.value()), &to_boolean);
Branch(IsBoolean(var_done.value()), &done, &to_boolean);
Bind(&to_boolean);
{
Node* const result =
CallStub(CodeFactory::ToBoolean(isolate()), context, var_done.value());
var_done.Bind(result);
Goto(&done);
}
Bind(&done);
return std::make_pair(var_value.value(), var_done.value());
}
Node* AsyncFromSyncBuiltinsAssembler::CreateUnwrapClosure(Node* native_context,
Node* done) {
Node* const map = LoadContextElement(
native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
Node* const on_fulfilled_shared = LoadContextElement(
native_context, Context::ASYNC_ITERATOR_VALUE_UNWRAP_SHARED_FUN);
CSA_ASSERT(this,
HasInstanceType(on_fulfilled_shared, SHARED_FUNCTION_INFO_TYPE));
Node* const closure_context =
AllocateAsyncIteratorValueUnwrapContext(native_context, done);
return AllocateFunctionWithMapAndContext(map, on_fulfilled_shared,
closure_context);
}
Node* AsyncFromSyncBuiltinsAssembler::AllocateAsyncIteratorValueUnwrapContext(
Node* native_context, Node* done) {
CSA_ASSERT(this, IsNativeContext(native_context));
CSA_ASSERT(this, IsBoolean(done));
Node* const context =
CreatePromiseContext(native_context, ValueUnwrapContext::kLength);
StoreContextElementNoWriteBarrier(context, ValueUnwrapContext::kDoneSlot,
done);
return context;
}
} // namespace
// https://tc39.github.io/proposal-async-iteration/
// Section #sec-%asyncfromsynciteratorprototype%.next
TF_BUILTIN(AsyncFromSyncIteratorPrototypeNext, AsyncFromSyncBuiltinsAssembler) {
Node* const iterator = Parameter(0);
Node* const value = Parameter(1);
Node* const context = Parameter(4);
Generate_AsyncFromSyncIteratorMethod(
context, iterator, value, factory()->next_string(),
UndefinedMethodHandler(), "[Async-from-Sync Iterator].prototype.next");
}
// https://tc39.github.io/proposal-async-iteration/
// Section #sec-%asyncfromsynciteratorprototype%.return
TF_BUILTIN(AsyncFromSyncIteratorPrototypeReturn,
AsyncFromSyncBuiltinsAssembler) {
Node* const iterator = Parameter(0);
Node* const value = Parameter(1);
Node* const context = Parameter(4);
auto if_return_undefined = [=](Node* const native_context,
Node* const promise, Label* if_exception) {
// If return is undefined, then
// Let iterResult be ! CreateIterResultObject(value, true)
Node* const iter_result =
CallStub(CodeFactory::CreateIterResultObject(isolate()), context, value,
TrueConstant());
// Perform ! Call(promiseCapability.[[Resolve]], undefined, « iterResult »).
// IfAbruptRejectPromise(nextDone, promiseCapability).
// Return promiseCapability.[[Promise]].
PromiseFulfill(context, promise, iter_result, v8::Promise::kFulfilled);
Return(promise);
};
Generate_AsyncFromSyncIteratorMethod(
context, iterator, value, factory()->return_string(), if_return_undefined,
"[Async-from-Sync Iterator].prototype.return");
}
// https://tc39.github.io/proposal-async-iteration/
// Section #sec-%asyncfromsynciteratorprototype%.throw
TF_BUILTIN(AsyncFromSyncIteratorPrototypeThrow,
AsyncFromSyncBuiltinsAssembler) {
Node* const iterator = Parameter(0);
Node* const reason = Parameter(1);
Node* const context = Parameter(4);
auto if_throw_undefined = [=](Node* const native_context, Node* const promise,
Label* if_exception) { Goto(if_exception); };
Generate_AsyncFromSyncIteratorMethod(
context, iterator, reason, factory()->throw_string(), if_throw_undefined,
"[Async-from-Sync Iterator].prototype.throw", Label::kNonDeferred,
reason);
}
TF_BUILTIN(AsyncIteratorValueUnwrap, AsyncFromSyncBuiltinsAssembler) {
Node* const value = Parameter(1);
Node* const context = Parameter(4);
Node* const done = LoadContextElement(context, ValueUnwrapContext::kDoneSlot);
CSA_ASSERT(this, IsBoolean(done));
Node* const unwrapped_value = CallStub(
CodeFactory::CreateIterResultObject(isolate()), context, value, done);
Return(unwrapped_value);
}
} // namespace internal
} // namespace v8
...@@ -846,7 +846,18 @@ class Isolate; ...@@ -846,7 +846,18 @@ class Isolate;
WasmRuntimeCall, 1) \ WasmRuntimeCall, 1) \
TFS(ThrowWasmTrapFuncInvalid, BUILTIN, kNoExtraICState, WasmRuntimeCall, 1) \ TFS(ThrowWasmTrapFuncInvalid, BUILTIN, kNoExtraICState, WasmRuntimeCall, 1) \
TFS(ThrowWasmTrapFuncSigMismatch, BUILTIN, kNoExtraICState, WasmRuntimeCall, \ TFS(ThrowWasmTrapFuncSigMismatch, BUILTIN, kNoExtraICState, WasmRuntimeCall, \
1) 1) \
\
/* Async-from-Sync Iterator */ \
\
/* %AsyncFromSyncIteratorPrototype% */ \
/* (proposal-async-iteration/#sec-%asyncfromsynciteratorprototype%-object)*/ \
TFJ(AsyncFromSyncIteratorPrototypeNext, 1) \
TFJ(AsyncFromSyncIteratorPrototypeThrow, 1) \
TFJ(AsyncFromSyncIteratorPrototypeReturn, 1) \
\
/* proposal-async-iteration/#sec-async-iterator-value-unwrap-functions */ \
TFJ(AsyncIteratorValueUnwrap, 1)
#define IGNORE_BUILTIN(...) #define IGNORE_BUILTIN(...)
......
...@@ -2890,6 +2890,11 @@ Node* CodeStubAssembler::IsJSReceiver(Node* object) { ...@@ -2890,6 +2890,11 @@ Node* CodeStubAssembler::IsJSReceiver(Node* object) {
return IsJSReceiverInstanceType(LoadInstanceType(object)); return IsJSReceiverInstanceType(LoadInstanceType(object));
} }
Node* CodeStubAssembler::IsJSReceiverMap(Node* map) {
STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE);
return IsJSReceiverInstanceType(LoadMapInstanceType(map));
}
Node* CodeStubAssembler::IsJSObject(Node* object) { Node* CodeStubAssembler::IsJSObject(Node* object) {
STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE); STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE);
return Int32GreaterThanOrEqual(LoadInstanceType(object), return Int32GreaterThanOrEqual(LoadInstanceType(object),
......
...@@ -692,6 +692,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler { ...@@ -692,6 +692,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
Node* IsJSGlobalProxy(Node* object); Node* IsJSGlobalProxy(Node* object);
Node* IsJSReceiverInstanceType(Node* instance_type); Node* IsJSReceiverInstanceType(Node* instance_type);
Node* IsJSReceiver(Node* object); Node* IsJSReceiver(Node* object);
Node* IsJSReceiverMap(Node* map);
Node* IsMap(Node* object); Node* IsMap(Node* object);
Node* IsCallableMap(Node* map); Node* IsCallableMap(Node* map);
Node* IsCallable(Node* object); Node* IsCallable(Node* object);
...@@ -1003,6 +1004,11 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler { ...@@ -1003,6 +1004,11 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
Label* if_found, Variable* var_value, Label* if_found, Variable* var_value,
Label* if_not_found, Label* if_bailout); Label* if_not_found, Label* if_bailout);
Node* GetProperty(Node* context, Node* receiver, Handle<Name> name) {
return CallStub(CodeFactory::GetProperty(isolate()), context, receiver,
HeapConstant(name));
}
void LoadPropertyFromFastObject(Node* object, Node* map, Node* descriptors, void LoadPropertyFromFastObject(Node* object, Node* map, Node* descriptors,
Node* name_index, Variable* var_details, Node* name_index, Variable* var_details,
Variable* var_value); Variable* var_value);
...@@ -1258,6 +1264,16 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler { ...@@ -1258,6 +1264,16 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
void Print(const char* prefix, Node* tagged_value); void Print(const char* prefix, Node* tagged_value);
inline void Print(Node* tagged_value) { return Print(nullptr, tagged_value); } inline void Print(Node* tagged_value) { return Print(nullptr, tagged_value); }
template <class... TArgs>
Node* MakeTypeError(MessageTemplate::Template message, Node* context,
TArgs... args) {
STATIC_ASSERT(sizeof...(TArgs) <= 3);
Node* const make_type_error = LoadContextElement(
LoadNativeContext(context), Context::MAKE_TYPE_ERROR_INDEX);
return CallJS(CodeFactory::Call(isolate()), context, make_type_error,
UndefinedConstant(), SmiConstant(message), args...);
}
protected: protected:
void DescriptorLookup(Node* unique_name, Node* descriptors, Node* bitfield3, void DescriptorLookup(Node* unique_name, Node* descriptors, Node* bitfield3,
Label* if_found, Variable* var_name_index, Label* if_found, Variable* var_name_index,
......
...@@ -188,6 +188,10 @@ Node* CodeAssembler::HeapConstant(Handle<HeapObject> object) { ...@@ -188,6 +188,10 @@ Node* CodeAssembler::HeapConstant(Handle<HeapObject> object) {
return raw_assembler()->HeapConstant(object); return raw_assembler()->HeapConstant(object);
} }
Node* CodeAssembler::CStringConstant(const char* str) {
return HeapConstant(factory()->NewStringFromAsciiChecked(str, TENURED));
}
Node* CodeAssembler::BooleanConstant(bool value) { Node* CodeAssembler::BooleanConstant(bool value) {
return raw_assembler()->BooleanConstant(value); return raw_assembler()->BooleanConstant(value);
} }
......
...@@ -216,6 +216,7 @@ class V8_EXPORT_PRIVATE CodeAssembler { ...@@ -216,6 +216,7 @@ class V8_EXPORT_PRIVATE CodeAssembler {
Node* SmiConstant(Smi* value); Node* SmiConstant(Smi* value);
Node* SmiConstant(int value); Node* SmiConstant(int value);
Node* HeapConstant(Handle<HeapObject> object); Node* HeapConstant(Handle<HeapObject> object);
Node* CStringConstant(const char* str);
Node* BooleanConstant(bool value); Node* BooleanConstant(bool value);
Node* ExternalConstant(ExternalReference address); Node* ExternalConstant(ExternalReference address);
Node* Float64Constant(double value); Node* Float64Constant(double value);
......
...@@ -225,6 +225,7 @@ Type::bitset BitsetType::Lub(i::Map* map) { ...@@ -225,6 +225,7 @@ Type::bitset BitsetType::Lub(i::Map* map) {
case JS_SET_ITERATOR_TYPE: case JS_SET_ITERATOR_TYPE:
case JS_MAP_ITERATOR_TYPE: case JS_MAP_ITERATOR_TYPE:
case JS_STRING_ITERATOR_TYPE: case JS_STRING_ITERATOR_TYPE:
case JS_ASYNC_FROM_SYNC_ITERATOR_TYPE:
case JS_TYPED_ARRAY_KEY_ITERATOR_TYPE: case JS_TYPED_ARRAY_KEY_ITERATOR_TYPE:
case JS_FAST_ARRAY_KEY_ITERATOR_TYPE: case JS_FAST_ARRAY_KEY_ITERATOR_TYPE:
......
...@@ -197,11 +197,14 @@ enum ContextLookupFlags { ...@@ -197,11 +197,14 @@ enum ContextLookupFlags {
V(ARRAY_BUFFER_FUN_INDEX, JSFunction, array_buffer_fun) \ V(ARRAY_BUFFER_FUN_INDEX, JSFunction, array_buffer_fun) \
V(ARRAY_BUFFER_MAP_INDEX, Map, array_buffer_map) \ V(ARRAY_BUFFER_MAP_INDEX, Map, array_buffer_map) \
V(ARRAY_FUNCTION_INDEX, JSFunction, array_function) \ V(ARRAY_FUNCTION_INDEX, JSFunction, array_function) \
V(ASYNC_FROM_SYNC_ITERATOR_MAP_INDEX, Map, async_from_sync_iterator_map) \
V(ASYNC_FUNCTION_AWAIT_REJECT_SHARED_FUN, SharedFunctionInfo, \ V(ASYNC_FUNCTION_AWAIT_REJECT_SHARED_FUN, SharedFunctionInfo, \
async_function_await_reject_shared_fun) \ async_function_await_reject_shared_fun) \
V(ASYNC_FUNCTION_AWAIT_RESOLVE_SHARED_FUN, SharedFunctionInfo, \ V(ASYNC_FUNCTION_AWAIT_RESOLVE_SHARED_FUN, SharedFunctionInfo, \
async_function_await_resolve_shared_fun) \ async_function_await_resolve_shared_fun) \
V(ASYNC_FUNCTION_FUNCTION_INDEX, JSFunction, async_function_constructor) \ V(ASYNC_FUNCTION_FUNCTION_INDEX, JSFunction, async_function_constructor) \
V(ASYNC_ITERATOR_VALUE_UNWRAP_SHARED_FUN, SharedFunctionInfo, \
async_iterator_value_unwrap_shared_fun) \
V(BOOLEAN_FUNCTION_INDEX, JSFunction, boolean_function) \ V(BOOLEAN_FUNCTION_INDEX, JSFunction, boolean_function) \
V(BOUND_FUNCTION_WITH_CONSTRUCTOR_MAP_INDEX, Map, \ V(BOUND_FUNCTION_WITH_CONSTRUCTOR_MAP_INDEX, Map, \
bound_function_with_constructor_map) \ bound_function_with_constructor_map) \
......
...@@ -3794,6 +3794,19 @@ Handle<Object> TranslatedState::MaterializeCapturedObjectAt( ...@@ -3794,6 +3794,19 @@ Handle<Object> TranslatedState::MaterializeCapturedObjectAt(
object->set_index(Smi::cast(*next_index)->value()); object->set_index(Smi::cast(*next_index)->value());
return object; return object;
} }
case JS_ASYNC_FROM_SYNC_ITERATOR_TYPE: {
Handle<JSAsyncFromSyncIterator> object =
Handle<JSAsyncFromSyncIterator>::cast(
isolate_->factory()->NewJSObjectFromMap(map, NOT_TENURED));
slot->value_ = object;
Handle<Object> properties = materializer.FieldAt(value_index);
Handle<Object> elements = materializer.FieldAt(value_index);
Handle<Object> sync_iterator = materializer.FieldAt(value_index);
object->set_properties(FixedArray::cast(*properties));
object->set_elements(FixedArrayBase::cast(*elements));
object->set_sync_iterator(JSReceiver::cast(*sync_iterator));
return object;
}
case JS_ARRAY_TYPE: { case JS_ARRAY_TYPE: {
Handle<JSArray> object = Handle<JSArray>::cast( Handle<JSArray> object = Handle<JSArray>::cast(
isolate_->factory()->NewJSObjectFromMap(map, NOT_TENURED)); isolate_->factory()->NewJSObjectFromMap(map, NOT_TENURED));
......
...@@ -1975,6 +1975,16 @@ Handle<JSIteratorResult> Factory::NewJSIteratorResult(Handle<Object> value, ...@@ -1975,6 +1975,16 @@ Handle<JSIteratorResult> Factory::NewJSIteratorResult(Handle<Object> value,
return js_iter_result; return js_iter_result;
} }
Handle<JSAsyncFromSyncIterator> Factory::NewJSAsyncFromSyncIterator(
Handle<JSReceiver> sync_iterator) {
Handle<Map> map(isolate()->native_context()->async_from_sync_iterator_map());
Handle<JSAsyncFromSyncIterator> iterator =
Handle<JSAsyncFromSyncIterator>::cast(NewJSObjectFromMap(map));
iterator->set_sync_iterator(*sync_iterator);
return iterator;
}
Handle<JSMap> Factory::NewJSMap() { Handle<JSMap> Factory::NewJSMap() {
Handle<Map> map(isolate()->native_context()->js_map_map()); Handle<Map> map(isolate()->native_context()->js_map_map());
Handle<JSMap> js_map = Handle<JSMap>::cast(NewJSObjectFromMap(map)); Handle<JSMap> js_map = Handle<JSMap>::cast(NewJSObjectFromMap(map));
......
...@@ -558,6 +558,8 @@ class V8_EXPORT_PRIVATE Factory final { ...@@ -558,6 +558,8 @@ class V8_EXPORT_PRIVATE Factory final {
size_t byte_offset, size_t byte_length); size_t byte_offset, size_t byte_length);
Handle<JSIteratorResult> NewJSIteratorResult(Handle<Object> value, bool done); Handle<JSIteratorResult> NewJSIteratorResult(Handle<Object> value, bool done);
Handle<JSAsyncFromSyncIterator> NewJSAsyncFromSyncIterator(
Handle<JSReceiver> sync_iterator);
Handle<JSMap> NewJSMap(); Handle<JSMap> NewJSMap();
Handle<JSSet> NewJSSet(); Handle<JSSet> NewJSSet();
......
...@@ -109,6 +109,7 @@ StaticVisitorBase::VisitorId StaticVisitorBase::GetVisitorId( ...@@ -109,6 +109,7 @@ StaticVisitorBase::VisitorId StaticVisitorBase::GetVisitorId(
case JS_OBJECT_TYPE: case JS_OBJECT_TYPE:
case JS_ERROR_TYPE: case JS_ERROR_TYPE:
case JS_ARGUMENTS_TYPE: case JS_ARGUMENTS_TYPE:
case JS_ASYNC_FROM_SYNC_ITERATOR_TYPE:
case JS_CONTEXT_EXTENSION_OBJECT_TYPE: case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
case JS_GENERATOR_OBJECT_TYPE: case JS_GENERATOR_OBJECT_TYPE:
case JS_MODULE_NAMESPACE_TYPE: case JS_MODULE_NAMESPACE_TYPE:
......
...@@ -299,6 +299,44 @@ Node* IntrinsicsHelper::ClassOf(Node* args_reg, Node* arg_count, ...@@ -299,6 +299,44 @@ Node* IntrinsicsHelper::ClassOf(Node* args_reg, Node* arg_count,
return __ ClassOf(value); return __ ClassOf(value);
} }
Node* IntrinsicsHelper::CreateAsyncFromSyncIterator(Node* args_reg,
Node* arg_count,
Node* context) {
InterpreterAssembler::Label not_receiver(
assembler_, InterpreterAssembler::Label::kDeferred);
InterpreterAssembler::Label done(assembler_);
InterpreterAssembler::Variable return_value(assembler_,
MachineRepresentation::kTagged);
Node* sync_iterator = __ LoadRegister(args_reg);
__ GotoIf(__ TaggedIsSmi(sync_iterator), &not_receiver);
__ GotoIfNot(__ IsJSReceiver(sync_iterator), &not_receiver);
Node* const native_context = __ LoadNativeContext(context);
Node* const map = __ LoadContextElement(
native_context, Context::ASYNC_FROM_SYNC_ITERATOR_MAP_INDEX);
Node* const iterator = __ AllocateJSObjectFromMap(map);
__ StoreObjectFieldNoWriteBarrier(
iterator, JSAsyncFromSyncIterator::kSyncIteratorOffset, sync_iterator);
return_value.Bind(iterator);
__ Goto(&done);
__ Bind(&not_receiver);
{
return_value.Bind(
__ CallRuntime(Runtime::kThrowSymbolIteratorInvalid, context));
// Unreachable due to the Throw in runtime call.
__ Goto(&done);
}
__ Bind(&done);
return return_value.value();
}
void IntrinsicsHelper::AbortIfArgCountMismatch(int expected, Node* actual) { void IntrinsicsHelper::AbortIfArgCountMismatch(int expected, Node* actual) {
InterpreterAssembler::Label match(assembler_); InterpreterAssembler::Label match(assembler_);
Node* comparison = __ Word32Equal(actual, __ Int32Constant(expected)); Node* comparison = __ Word32Equal(actual, __ Int32Constant(expected));
......
...@@ -27,6 +27,7 @@ namespace interpreter { ...@@ -27,6 +27,7 @@ namespace interpreter {
V(Call, call, -1) \ V(Call, call, -1) \
V(ClassOf, class_of, 1) \ V(ClassOf, class_of, 1) \
V(CreateIterResultObject, create_iter_result_object, 2) \ V(CreateIterResultObject, create_iter_result_object, 2) \
V(CreateAsyncFromSyncIterator, create_async_from_sync_iterator, 1) \
V(HasProperty, has_property, 2) \ V(HasProperty, has_property, 2) \
V(IsArray, is_array, 1) \ V(IsArray, is_array, 1) \
V(IsJSProxy, is_js_proxy, 1) \ V(IsJSProxy, is_js_proxy, 1) \
......
...@@ -467,6 +467,7 @@ ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3) { ...@@ -467,6 +467,7 @@ ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3) {
case JS_OBJECT_TYPE: case JS_OBJECT_TYPE:
case JS_ERROR_TYPE: case JS_ERROR_TYPE:
case JS_ARGUMENTS_TYPE: case JS_ARGUMENTS_TYPE:
case JS_ASYNC_FROM_SYNC_ITERATOR_TYPE:
case JS_PROMISE_CAPABILITY_TYPE: case JS_PROMISE_CAPABILITY_TYPE:
case JS_PROMISE_TYPE: case JS_PROMISE_TYPE:
case JS_CONTEXT_EXTENSION_OBJECT_TYPE: case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
......
...@@ -200,6 +200,9 @@ void HeapObject::HeapObjectVerify() { ...@@ -200,6 +200,9 @@ void HeapObject::HeapObjectVerify() {
case JS_STRING_ITERATOR_TYPE: case JS_STRING_ITERATOR_TYPE:
JSStringIterator::cast(this)->JSStringIteratorVerify(); JSStringIterator::cast(this)->JSStringIteratorVerify();
break; break;
case JS_ASYNC_FROM_SYNC_ITERATOR_TYPE:
JSAsyncFromSyncIterator::cast(this)->JSAsyncFromSyncIteratorVerify();
break;
case JS_WEAK_MAP_TYPE: case JS_WEAK_MAP_TYPE:
JSWeakMap::cast(this)->JSWeakMapVerify(); JSWeakMap::cast(this)->JSWeakMapVerify();
break; break;
...@@ -890,6 +893,12 @@ void JSStringIterator::JSStringIteratorVerify() { ...@@ -890,6 +893,12 @@ void JSStringIterator::JSStringIteratorVerify() {
CHECK_LE(index(), String::kMaxLength); CHECK_LE(index(), String::kMaxLength);
} }
void JSAsyncFromSyncIterator::JSAsyncFromSyncIteratorVerify() {
CHECK(IsJSAsyncFromSyncIterator());
JSObjectVerify();
VerifyHeapPointer(sync_iterator());
}
void JSWeakSet::JSWeakSetVerify() { void JSWeakSet::JSWeakSetVerify() {
CHECK(IsJSWeakSet()); CHECK(IsJSWeakSet());
JSObjectVerify(); JSObjectVerify();
......
...@@ -164,6 +164,7 @@ TYPE_CHECKER(JSPromise, JS_PROMISE_TYPE) ...@@ -164,6 +164,7 @@ TYPE_CHECKER(JSPromise, JS_PROMISE_TYPE)
TYPE_CHECKER(JSRegExp, JS_REGEXP_TYPE) TYPE_CHECKER(JSRegExp, JS_REGEXP_TYPE)
TYPE_CHECKER(JSSet, JS_SET_TYPE) TYPE_CHECKER(JSSet, JS_SET_TYPE)
TYPE_CHECKER(JSSetIterator, JS_SET_ITERATOR_TYPE) TYPE_CHECKER(JSSetIterator, JS_SET_ITERATOR_TYPE)
TYPE_CHECKER(JSAsyncFromSyncIterator, JS_ASYNC_FROM_SYNC_ITERATOR_TYPE)
TYPE_CHECKER(JSStringIterator, JS_STRING_ITERATOR_TYPE) TYPE_CHECKER(JSStringIterator, JS_STRING_ITERATOR_TYPE)
TYPE_CHECKER(JSTypedArray, JS_TYPED_ARRAY_TYPE) TYPE_CHECKER(JSTypedArray, JS_TYPED_ARRAY_TYPE)
TYPE_CHECKER(JSValue, JS_VALUE_TYPE) TYPE_CHECKER(JSValue, JS_VALUE_TYPE)
...@@ -656,6 +657,7 @@ CAST_ACCESSOR(JSPromiseCapability) ...@@ -656,6 +657,7 @@ CAST_ACCESSOR(JSPromiseCapability)
CAST_ACCESSOR(JSPromise) CAST_ACCESSOR(JSPromise)
CAST_ACCESSOR(JSSet) CAST_ACCESSOR(JSSet)
CAST_ACCESSOR(JSSetIterator) CAST_ACCESSOR(JSSetIterator)
CAST_ACCESSOR(JSAsyncFromSyncIterator)
CAST_ACCESSOR(JSStringIterator) CAST_ACCESSOR(JSStringIterator)
CAST_ACCESSOR(JSArrayIterator) CAST_ACCESSOR(JSArrayIterator)
CAST_ACCESSOR(JSTypedArray) CAST_ACCESSOR(JSTypedArray)
...@@ -8214,6 +8216,9 @@ ACCESSORS(JSArrayIterator, object, Object, kIteratedObjectOffset) ...@@ -8214,6 +8216,9 @@ ACCESSORS(JSArrayIterator, object, Object, kIteratedObjectOffset)
ACCESSORS(JSArrayIterator, index, Object, kNextIndexOffset) ACCESSORS(JSArrayIterator, index, Object, kNextIndexOffset)
ACCESSORS(JSArrayIterator, object_map, Object, kIteratedObjectMapOffset) ACCESSORS(JSArrayIterator, object_map, Object, kIteratedObjectMapOffset)
ACCESSORS(JSAsyncFromSyncIterator, sync_iterator, JSReceiver,
kSyncIteratorOffset)
ACCESSORS(JSStringIterator, string, String, kStringOffset) ACCESSORS(JSStringIterator, string, String, kStringOffset)
SMI_ACCESSORS(JSStringIterator, index, kNextIndexOffset) SMI_ACCESSORS(JSStringIterator, index, kNextIndexOffset)
......
...@@ -12555,6 +12555,7 @@ bool CanSubclassHaveInobjectProperties(InstanceType instance_type) { ...@@ -12555,6 +12555,7 @@ bool CanSubclassHaveInobjectProperties(InstanceType instance_type) {
case JS_API_OBJECT_TYPE: case JS_API_OBJECT_TYPE:
case JS_ARRAY_BUFFER_TYPE: case JS_ARRAY_BUFFER_TYPE:
case JS_ARRAY_TYPE: case JS_ARRAY_TYPE:
case JS_ASYNC_FROM_SYNC_ITERATOR_TYPE:
case JS_CONTEXT_EXTENSION_OBJECT_TYPE: case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
case JS_DATA_VIEW_TYPE: case JS_DATA_VIEW_TYPE:
case JS_DATE_TYPE: case JS_DATE_TYPE:
......
...@@ -398,6 +398,7 @@ const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1; ...@@ -398,6 +398,7 @@ const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1;
V(JS_PROMISE_TYPE) \ V(JS_PROMISE_TYPE) \
V(JS_REGEXP_TYPE) \ V(JS_REGEXP_TYPE) \
V(JS_ERROR_TYPE) \ V(JS_ERROR_TYPE) \
V(JS_ASYNC_FROM_SYNC_ITERATOR_TYPE) \
V(JS_STRING_ITERATOR_TYPE) \ V(JS_STRING_ITERATOR_TYPE) \
\ \
V(JS_TYPED_ARRAY_KEY_ITERATOR_TYPE) \ V(JS_TYPED_ARRAY_KEY_ITERATOR_TYPE) \
...@@ -743,6 +744,7 @@ enum InstanceType { ...@@ -743,6 +744,7 @@ enum InstanceType {
JS_PROMISE_TYPE, JS_PROMISE_TYPE,
JS_REGEXP_TYPE, JS_REGEXP_TYPE,
JS_ERROR_TYPE, JS_ERROR_TYPE,
JS_ASYNC_FROM_SYNC_ITERATOR_TYPE,
JS_STRING_ITERATOR_TYPE, JS_STRING_ITERATOR_TYPE,
JS_TYPED_ARRAY_KEY_ITERATOR_TYPE, JS_TYPED_ARRAY_KEY_ITERATOR_TYPE,
...@@ -1039,6 +1041,7 @@ template <class C> inline bool Is(Object* obj); ...@@ -1039,6 +1041,7 @@ template <class C> inline bool Is(Object* obj);
V(JSArray) \ V(JSArray) \
V(JSArrayBuffer) \ V(JSArrayBuffer) \
V(JSArrayBufferView) \ V(JSArrayBufferView) \
V(JSAsyncFromSyncIterator) \
V(JSCollection) \ V(JSCollection) \
V(JSTypedArray) \ V(JSTypedArray) \
V(JSArrayIterator) \ V(JSArrayIterator) \
...@@ -10437,6 +10440,32 @@ class JSArrayIterator : public JSObject { ...@@ -10437,6 +10440,32 @@ class JSArrayIterator : public JSObject {
DISALLOW_IMPLICIT_CONSTRUCTORS(JSArrayIterator); DISALLOW_IMPLICIT_CONSTRUCTORS(JSArrayIterator);
}; };
// The [Async-from-Sync Iterator] object
// (proposal-async-iteration/#sec-async-from-sync-iterator-objects)
// An object which wraps an ordinary Iterator and converts it to behave
// according to the Async Iterator protocol.
// (See https://tc39.github.io/proposal-async-iteration/#sec-iteration)
class JSAsyncFromSyncIterator : public JSObject {
public:
DECLARE_CAST(JSAsyncFromSyncIterator)
DECLARE_PRINTER(JSAsyncFromSyncIterator)
DECLARE_VERIFIER(JSAsyncFromSyncIterator)
// Async-from-Sync Iterator instances are ordinary objects that inherit
// properties from the %AsyncFromSyncIteratorPrototype% intrinsic object.
// Async-from-Sync Iterator instances are initially created with the internal
// slots listed in Table 4.
// (proposal-async-iteration/#table-async-from-sync-iterator-internal-slots)
DECL_ACCESSORS(sync_iterator, JSReceiver)
// Offsets of object fields.
static const int kSyncIteratorOffset = JSObject::kHeaderSize;
static const int kSize = kSyncIteratorOffset + kPointerSize;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(JSAsyncFromSyncIterator);
};
class JSStringIterator : public JSObject { class JSStringIterator : public JSObject {
public: public:
// Dispatched behavior. // Dispatched behavior.
......
...@@ -511,10 +511,18 @@ RUNTIME_FUNCTION(Runtime_AllowDynamicFunction) { ...@@ -511,10 +511,18 @@ RUNTIME_FUNCTION(Runtime_AllowDynamicFunction) {
} }
RUNTIME_FUNCTION(Runtime_CreateAsyncFromSyncIterator) { RUNTIME_FUNCTION(Runtime_CreateAsyncFromSyncIterator) {
// TODO(caitp): split AsyncFromSyncIterator functionality out of HandleScope scope(isolate);
// https://codereview.chromium.org/2622833002 DCHECK_EQ(1, args.length());
UNREACHABLE();
return isolate->heap()->undefined_value(); CONVERT_ARG_HANDLE_CHECKED(Object, sync_iterator, 0);
if (!sync_iterator->IsJSReceiver()) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewTypeError(MessageTemplate::kSymbolIteratorInvalid));
}
return *isolate->factory()->NewJSAsyncFromSyncIterator(
Handle<JSReceiver>::cast(sync_iterator));
} }
} // namespace internal } // namespace internal
......
...@@ -477,6 +477,7 @@ ...@@ -477,6 +477,7 @@
'builtins/builtins-arguments.h', 'builtins/builtins-arguments.h',
'builtins/builtins-arraybuffer.cc', 'builtins/builtins-arraybuffer.cc',
'builtins/builtins-array.cc', 'builtins/builtins-array.cc',
'builtins/builtins-async-iterator.cc',
'builtins/builtins-async-function.cc', 'builtins/builtins-async-function.cc',
'builtins/builtins-async.cc', 'builtins/builtins-async.cc',
'builtins/builtins-async.h', 'builtins/builtins-async.h',
......
#
# Autogenerated by generate-bytecode-expectations.
#
---
wrap: no
test function name: f
async iteration: yes
---
snippet: "
async function f() {
for await (let x of [1, 2, 3]) {}
}
f();
"
frame size: 19
parameter count: 1
bytecode array length: 1055
bytecodes: [
B(Ldar), R(new_target),
B(JumpIfUndefined), U8(42),
B(CallRuntime), U16(Runtime::k_GeneratorGetContext), R(new_target), U8(1),
B(PushContext), R(4),
B(ResumeGenerator), R(new_target),
B(Star), R(3),
B(LdaZero),
B(TestEqualStrict), R(3), U8(0),
B(JumpIfTrue), U8(136),
B(LdaSmi), I8(1),
B(TestEqualStrict), R(3), U8(0),
B(JumpIfTrueConstant), U8(13),
B(LdaSmi), I8(2),
B(TestEqualStrict), R(3), U8(0),
B(JumpIfTrueConstant), U8(15),
B(LdaSmi), I8(78),
B(Star), R(5),
B(CallRuntime), U16(Runtime::kAbort), R(5), U8(1),
B(LdaSmi), I8(-2),
B(Star), R(3),
B(CreateFunctionContext), U8(13),
B(PushContext), R(0),
B(Ldar), R(this),
B(StaCurrentContextSlot), U8(4),
/* 16 E> */ B(StackCheck),
B(LdaImmutableCurrentContextSlot), U8(4),
B(Star), R(6),
B(Mov), R(closure), R(5),
B(CallRuntime), U16(Runtime::kCreateJSGeneratorObject), R(5), U8(2),
B(StaCurrentContextSlot), U8(5),
B(LdaUndefined),
B(Star), R(5),
B(CallJSRuntime), U8(%async_function_promise_create), R(5), U8(1),
B(StaCurrentContextSlot), U8(10),
B(Mov), R(context), R(7),
B(Mov), R(context), R(8),
B(Ldar), R(closure),
B(CreateBlockContext), U8(0),
B(PushContext), R(1),
B(LdaTheHole),
B(StaCurrentContextSlot), U8(4),
B(LdaZero),
B(StaContextSlot), R(1), U8(9), U8(0),
B(Mov), R(context), R(11),
B(Mov), R(context), R(12),
/* 43 S> */ B(CreateArrayLiteral), U8(1), U8(2), U8(9),
B(Star), R(13),
B(LdaNamedProperty), R(13), U8(2), U8(7),
B(JumpIfUndefined), U8(18),
B(JumpIfNull), U8(16),
B(Star), R(14),
B(CallProperty), R(14), R(13), U8(1), U8(9),
B(JumpIfJSReceiver), U8(24),
B(CallRuntime), U16(Runtime::kThrowSymbolAsyncIteratorInvalid), R(0), U8(0),
B(LdaNamedProperty), R(13), U8(3), U8(3),
B(Star), R(14),
B(CallProperty), R(14), R(13), U8(1), U8(5),
B(Star), R(14),
B(InvokeIntrinsic), U8(Runtime::k_CreateAsyncFromSyncIterator), R(14), U8(1),
/* 43 E> */ B(StaContextSlot), R(1), U8(7), U8(0),
B(LdaSmi), I8(-2),
B(TestEqual), R(3), U8(0),
B(JumpIfTrue), U8(17),
B(LdaZero),
B(TestEqualStrict), R(3), U8(0),
B(JumpIfTrue), U8(75),
B(LdaSmi), I8(78),
B(Star), R(13),
B(CallRuntime), U16(Runtime::kAbort), R(13), U8(1),
/* 40 S> */ B(LdaContextSlot), R(1), U8(7), U8(0),
B(Star), R(14),
B(LdaNamedProperty), R(14), U8(4), U8(13),
B(Star), R(13),
/* 40 E> */ B(CallProperty), R(13), R(14), U8(1), U8(11),
B(StaContextSlot), R(1), U8(11), U8(0),
/* 40 S> */ B(LdaUndefined),
B(Star), R(13),
B(LdaImmutableContextSlot), R(1), U8(5), U8(0),
B(Star), R(14),
B(LdaContextSlot), R(1), U8(11), U8(0),
B(Star), R(15),
B(LdaContextSlot), R(1), U8(10), U8(0),
B(Star), R(16),
B(CallJSRuntime), U8(%async_function_await_uncaught), R(13), U8(4),
B(LdaContextSlot), R(1), U8(10), U8(0),
B(Star), R(13),
B(LdaImmutableContextSlot), R(1), U8(5), U8(0),
B(Star), R(14),
B(LdaZero),
B(SuspendGenerator), R(14),
B(Ldar), R(13),
/* 57 S> */ B(Return),
B(LdaSmi), I8(-2),
B(Star), R(3),
B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(14), U8(1),
B(Star), R(15),
B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(14), U8(1),
B(Star), R(16),
B(LdaZero),
B(TestEqualStrict), R(16), U8(0),
B(JumpIfTrue), U8(31),
B(LdaSmi), I8(2),
B(TestEqualStrict), R(16), U8(0),
B(JumpIfTrue), U8(21),
B(Jump), U8(2),
B(LdaTrue),
B(Star), R(18),
B(Mov), R(15), R(17),
B(InvokeIntrinsic), U8(Runtime::k_CreateIterResultObject), R(17), U8(2),
B(Star), R(10),
B(LdaZero),
B(Star), R(9),
B(Jump), U8(155),
B(Ldar), R(15),
B(ReThrow),
B(Ldar), R(15),
/* 40 E> */ B(StaContextSlot), R(1), U8(8), U8(0),
B(InvokeIntrinsic), U8(Runtime::k_IsJSReceiver), R(15), U8(1),
B(ToBooleanLogicalNot),
B(JumpIfFalse), U8(13),
B(LdaContextSlot), R(1), U8(8), U8(0),
B(Star), R(13),
B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(13), U8(1),
B(LdaContextSlot), R(1), U8(8), U8(0),
B(Star), R(13),
B(LdaNamedProperty), R(13), U8(5), U8(15),
B(JumpIfToBooleanTrue), U8(56),
B(LdaContextSlot), R(1), U8(8), U8(0),
B(Star), R(13),
B(LdaNamedProperty), R(13), U8(6), U8(17),
B(StaContextSlot), R(1), U8(12), U8(0),
B(LdaSmi), I8(2),
B(StaContextSlot), R(1), U8(9), U8(0),
B(LdaContextSlot), R(1), U8(12), U8(0),
B(StaContextSlot), R(1), U8(6), U8(0),
/* 23 E> */ B(StackCheck),
B(Ldar), R(closure),
B(CreateBlockContext), U8(7),
B(PushContext), R(2),
B(LdaTheHole),
B(StaCurrentContextSlot), U8(4),
B(LdaContextSlot), R(1), U8(6), U8(0),
B(StaCurrentContextSlot), U8(4),
B(PopContext), R(2),
B(LdaZero),
B(StaContextSlot), R(1), U8(9), U8(0),
B(JumpLoop), U8(226), I8(0),
B(Jump), U8(48),
B(Star), R(13),
B(Ldar), R(closure),
B(CreateCatchContext), R(13), U8(8), U8(9),
B(Star), R(12),
B(LdaTheHole),
B(SetPendingMessage),
B(Ldar), R(12),
B(PushContext), R(2),
B(LdaContextSlot), R(1), U8(9), U8(0),
B(Star), R(13),
B(LdaSmi), I8(2),
B(TestEqualStrict), R(13), U8(19),
B(JumpIfFalse), U8(8),
B(LdaSmi), I8(1),
B(StaContextSlot), R(1), U8(9), U8(0),
B(LdaImmutableCurrentContextSlot), U8(4),
B(Star), R(13),
B(CallRuntime), U16(Runtime::kReThrow), R(13), U8(1),
B(PopContext), R(2),
B(LdaSmi), I8(-1),
B(Star), R(9),
B(Jump), U8(8),
B(Star), R(10),
B(LdaSmi), I8(1),
B(Star), R(9),
B(LdaTheHole),
B(SetPendingMessage),
B(Star), R(11),
B(LdaContextSlot), R(1), U8(9), U8(0),
B(Star), R(12),
B(LdaZero),
B(TestEqualStrict), R(12), U8(20),
B(JumpIfTrueConstant), U8(17),
B(LdaContextSlot), R(1), U8(7), U8(0),
B(Star), R(12),
B(LdaNamedProperty), R(12), U8(10), U8(21),
B(StaContextSlot), R(1), U8(13), U8(0),
B(LdaContextSlot), R(1), U8(13), U8(0),
B(Star), R(12),
B(TestUndetectable), R(12),
B(JumpIfFalse), U8(4),
B(JumpConstant), U8(16),
B(LdaContextSlot), R(1), U8(9), U8(0),
B(Star), R(12),
B(LdaSmi), I8(1),
B(TestEqualStrict), R(12), U8(24),
B(JumpIfFalse), U8(186),
B(LdaContextSlot), R(1), U8(13), U8(0),
B(TypeOf),
B(Star), R(12),
B(LdaConstant), U8(11),
B(TestEqualStrict), R(12), U8(25),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(130),
B(Star), R(12),
B(LdaConstant), U8(12),
B(Star), R(13),
B(CallRuntime), U16(Runtime::kNewTypeError), R(12), U8(2),
B(Throw),
B(Mov), R(context), R(12),
B(LdaContextSlot), R(1), U8(13), U8(0),
B(Star), R(13),
B(LdaContextSlot), R(1), U8(7), U8(0),
B(Star), R(14),
B(InvokeIntrinsic), U8(Runtime::k_Call), R(13), U8(2),
B(StaContextSlot), R(1), U8(14), U8(0),
B(LdaUndefined),
B(Star), R(13),
B(LdaImmutableContextSlot), R(1), U8(5), U8(0),
B(Star), R(14),
B(LdaContextSlot), R(1), U8(14), U8(0),
B(Star), R(15),
B(LdaContextSlot), R(1), U8(10), U8(0),
B(Star), R(16),
B(CallJSRuntime), U8(%async_function_await_caught), R(13), U8(4),
B(LdaContextSlot), R(1), U8(10), U8(0),
B(Star), R(13),
B(LdaImmutableContextSlot), R(1), U8(5), U8(0),
B(Star), R(14),
B(LdaSmi), I8(1),
B(SuspendGenerator), R(14),
B(Ldar), R(13),
/* 57 S> */ B(Return),
B(LdaSmi), I8(-2),
B(Star), R(3),
B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(14), U8(1),
B(Star), R(15),
B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(14), U8(1),
B(Star), R(16),
B(LdaZero),
B(TestEqualStrict), R(16), U8(0),
B(JumpIfTrue), U8(39),
B(LdaSmi), I8(2),
B(TestEqualStrict), R(16), U8(0),
B(JumpIfTrue), U8(29),
B(Jump), U8(2),
B(LdaTrue),
B(Star), R(18),
B(Mov), R(15), R(17),
B(InvokeIntrinsic), U8(Runtime::k_CreateIterResultObject), R(17), U8(2),
B(PopContext), R(1),
B(PopContext), R(1),
B(PopContext), R(1),
B(PopContext), R(1),
B(Star), R(6),
B(LdaZero),
B(Star), R(5),
B(JumpConstant), U8(19),
B(Ldar), R(15),
B(ReThrow),
B(Ldar), R(15),
B(Jump), U8(20),
B(Star), R(13),
B(Ldar), R(closure),
B(CreateCatchContext), R(13), U8(8), U8(14),
B(Star), R(12),
B(LdaTheHole),
B(SetPendingMessage),
B(Ldar), R(12),
B(PushContext), R(2),
B(PopContext), R(2),
B(Jump), U8(159),
B(LdaContextSlot), R(1), U8(13), U8(0),
B(Star), R(12),
B(LdaContextSlot), R(1), U8(7), U8(0),
B(Star), R(13),
B(InvokeIntrinsic), U8(Runtime::k_Call), R(12), U8(2),
B(StaContextSlot), R(1), U8(16), U8(0),
B(LdaUndefined),
B(Star), R(12),
B(LdaImmutableContextSlot), R(1), U8(5), U8(0),
B(Star), R(13),
B(LdaContextSlot), R(1), U8(16), U8(0),
B(Star), R(14),
B(LdaContextSlot), R(1), U8(10), U8(0),
B(Star), R(15),
B(CallJSRuntime), U8(%async_function_await_uncaught), R(12), U8(4),
B(LdaContextSlot), R(1), U8(10), U8(0),
B(Star), R(12),
B(LdaImmutableContextSlot), R(1), U8(5), U8(0),
B(Star), R(13),
B(LdaSmi), I8(2),
B(SuspendGenerator), R(13),
B(Ldar), R(12),
/* 57 S> */ B(Return),
B(LdaSmi), I8(-2),
B(Star), R(3),
B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(13), U8(1),
B(Star), R(14),
B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(13), U8(1),
B(Star), R(15),
B(LdaZero),
B(TestEqualStrict), R(15), U8(0),
B(JumpIfTrue), U8(40),
B(LdaSmi), I8(2),
B(TestEqualStrict), R(15), U8(0),
B(JumpIfTrue), U8(30),
B(Jump), U8(2),
B(LdaTrue),
B(Star), R(17),
B(Mov), R(14), R(16),
B(InvokeIntrinsic), U8(Runtime::k_CreateIterResultObject), R(16), U8(2),
B(PopContext), R(1),
B(PopContext), R(1),
B(PopContext), R(1),
B(PopContext), R(1),
B(Star), R(6),
B(LdaSmi), I8(1),
B(Star), R(5),
B(Jump), U8(170),
B(Ldar), R(14),
B(ReThrow),
B(Ldar), R(14),
B(StaContextSlot), R(1), U8(15), U8(0),
B(LdaContextSlot), R(1), U8(15), U8(0),
B(Star), R(12),
B(InvokeIntrinsic), U8(Runtime::k_IsJSReceiver), R(12), U8(1),
B(JumpIfToBooleanFalse), U8(4),
B(Jump), U8(13),
B(LdaContextSlot), R(1), U8(15), U8(0),
B(Star), R(12),
B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(12), U8(1),
B(Ldar), R(11),
B(SetPendingMessage),
B(LdaZero),
B(TestEqualStrict), R(9), U8(0),
B(JumpIfTrue), U8(11),
B(LdaSmi), I8(1),
B(TestEqualStrict), R(9), U8(0),
B(JumpIfTrue), U8(21),
B(Jump), U8(26),
B(PopContext), R(1),
B(PopContext), R(1),
B(PopContext), R(1),
B(PopContext), R(1),
B(LdaSmi), I8(2),
B(Star), R(5),
B(Mov), R(10), R(6),
B(Jump), U8(101),
B(PopContext), R(1),
B(PopContext), R(1),
B(Ldar), R(10),
B(ReThrow),
B(PopContext), R(1),
B(LdaUndefined),
B(Star), R(9),
B(LdaCurrentContextSlot), U8(10),
B(Star), R(10),
B(LdaUndefined),
B(Star), R(11),
B(CallJSRuntime), U8(%promise_resolve), R(9), U8(3),
B(LdaCurrentContextSlot), U8(10),
B(Star), R(6),
B(LdaSmi), I8(3),
B(Star), R(5),
B(Jump), U8(68),
B(Jump), U8(54),
B(Star), R(9),
B(Ldar), R(closure),
B(CreateCatchContext), R(9), U8(8), U8(18),
B(Star), R(8),
B(LdaTheHole),
B(SetPendingMessage),
B(Ldar), R(8),
B(PushContext), R(1),
B(LdaUndefined),
B(Star), R(9),
B(LdaContextSlot), R(1), U8(10), U8(0),
B(Star), R(10),
B(LdaImmutableCurrentContextSlot), U8(4),
B(Star), R(11),
B(LdaFalse),
B(Star), R(12),
B(CallJSRuntime), U8(%promise_internal_reject), R(9), U8(4),
B(LdaContextSlot), R(1), U8(10), U8(0),
B(PopContext), R(1),
B(PopContext), R(1),
B(Star), R(6),
B(LdaSmi), I8(4),
B(Star), R(5),
B(Jump), U8(14),
B(LdaSmi), I8(-1),
B(Star), R(5),
B(Jump), U8(8),
B(Star), R(6),
B(LdaSmi), I8(5),
B(Star), R(5),
B(LdaTheHole),
B(SetPendingMessage),
B(Star), R(7),
B(LdaUndefined),
B(Star), R(8),
B(LdaCurrentContextSlot), U8(10),
B(Star), R(9),
B(CallJSRuntime), U8(%async_function_promise_release), R(8), U8(2),
B(Ldar), R(7),
B(SetPendingMessage),
B(LdaZero),
B(TestEqualStrict), R(5), U8(0),
B(JumpIfTrue), U8(39),
B(LdaSmi), I8(1),
B(TestEqualStrict), R(5), U8(0),
B(JumpIfTrue), U8(35),
B(LdaSmi), I8(2),
B(TestEqualStrict), R(5), U8(0),
B(JumpIfTrue), U8(31),
B(LdaSmi), I8(3),
B(TestEqualStrict), R(5), U8(0),
B(JumpIfTrue), U8(27),
B(LdaSmi), I8(4),
B(TestEqualStrict), R(5), U8(0),
B(JumpIfTrue), U8(23),
B(LdaSmi), I8(5),
B(TestEqualStrict), R(5), U8(0),
B(JumpIfTrue), U8(19),
B(Jump), U8(20),
B(Ldar), R(6),
/* 57 S> */ B(Return),
B(Ldar), R(6),
/* 57 S> */ B(Return),
B(Ldar), R(6),
/* 57 S> */ B(Return),
B(Ldar), R(6),
/* 57 S> */ B(Return),
B(Ldar), R(6),
/* 57 S> */ B(Return),
B(Ldar), R(6),
B(ReThrow),
B(LdaUndefined),
/* 57 S> */ B(Return),
]
constant pool: [
FIXED_ARRAY_TYPE,
CONSTANT_ELEMENTS_PAIR_TYPE,
SYMBOL_TYPE,
SYMBOL_TYPE,
ONE_BYTE_INTERNALIZED_STRING_TYPE ["next"],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["done"],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["value"],
FIXED_ARRAY_TYPE,
ONE_BYTE_INTERNALIZED_STRING_TYPE [".catch"],
FIXED_ARRAY_TYPE,
ONE_BYTE_INTERNALIZED_STRING_TYPE ["return"],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["function"],
ONE_BYTE_INTERNALIZED_STRING_TYPE [""],
Smi [572],
FIXED_ARRAY_TYPE,
Smi [714],
Smi [356],
Smi [382],
FIXED_ARRAY_TYPE,
Smi [320],
]
handlers: [
[83, 962, 968],
[86, 908, 910],
[103, 432, 438],
[106, 384, 386],
[534, 661, 663],
]
---
snippet: "
async function f() {
for await (let x of [1, 2, 3]) { return x; }
}
f();
"
frame size: 19
parameter count: 1
bytecode array length: 1115
bytecodes: [
B(Ldar), R(new_target),
B(JumpIfUndefined), U8(42),
B(CallRuntime), U16(Runtime::k_GeneratorGetContext), R(new_target), U8(1),
B(PushContext), R(4),
B(ResumeGenerator), R(new_target),
B(Star), R(3),
B(LdaZero),
B(TestEqualStrict), R(3), U8(0),
B(JumpIfTrue), U8(136),
B(LdaSmi), I8(1),
B(TestEqualStrict), R(3), U8(0),
B(JumpIfTrueConstant), U8(13),
B(LdaSmi), I8(2),
B(TestEqualStrict), R(3), U8(0),
B(JumpIfTrueConstant), U8(15),
B(LdaSmi), I8(78),
B(Star), R(5),
B(CallRuntime), U16(Runtime::kAbort), R(5), U8(1),
B(LdaSmi), I8(-2),
B(Star), R(3),
B(CreateFunctionContext), U8(13),
B(PushContext), R(0),
B(Ldar), R(this),
B(StaCurrentContextSlot), U8(4),
/* 16 E> */ B(StackCheck),
B(LdaImmutableCurrentContextSlot), U8(4),
B(Star), R(6),
B(Mov), R(closure), R(5),
B(CallRuntime), U16(Runtime::kCreateJSGeneratorObject), R(5), U8(2),
B(StaCurrentContextSlot), U8(5),
B(LdaUndefined),
B(Star), R(5),
B(CallJSRuntime), U8(%async_function_promise_create), R(5), U8(1),
B(StaCurrentContextSlot), U8(10),
B(Mov), R(context), R(7),
B(Mov), R(context), R(8),
B(Ldar), R(closure),
B(CreateBlockContext), U8(0),
B(PushContext), R(1),
B(LdaTheHole),
B(StaCurrentContextSlot), U8(4),
B(LdaZero),
B(StaContextSlot), R(1), U8(9), U8(0),
B(Mov), R(context), R(11),
B(Mov), R(context), R(12),
/* 43 S> */ B(CreateArrayLiteral), U8(1), U8(2), U8(9),
B(Star), R(13),
B(LdaNamedProperty), R(13), U8(2), U8(7),
B(JumpIfUndefined), U8(18),
B(JumpIfNull), U8(16),
B(Star), R(14),
B(CallProperty), R(14), R(13), U8(1), U8(9),
B(JumpIfJSReceiver), U8(24),
B(CallRuntime), U16(Runtime::kThrowSymbolAsyncIteratorInvalid), R(0), U8(0),
B(LdaNamedProperty), R(13), U8(3), U8(3),
B(Star), R(14),
B(CallProperty), R(14), R(13), U8(1), U8(5),
B(Star), R(14),
B(InvokeIntrinsic), U8(Runtime::k_CreateAsyncFromSyncIterator), R(14), U8(1),
/* 43 E> */ B(StaContextSlot), R(1), U8(7), U8(0),
B(LdaSmi), I8(-2),
B(TestEqual), R(3), U8(0),
B(JumpIfTrue), U8(17),
B(LdaZero),
B(TestEqualStrict), R(3), U8(0),
B(JumpIfTrue), U8(75),
B(LdaSmi), I8(78),
B(Star), R(13),
B(CallRuntime), U16(Runtime::kAbort), R(13), U8(1),
/* 40 S> */ B(LdaContextSlot), R(1), U8(7), U8(0),
B(Star), R(14),
B(LdaNamedProperty), R(14), U8(4), U8(13),
B(Star), R(13),
/* 40 E> */ B(CallProperty), R(13), R(14), U8(1), U8(11),
B(StaContextSlot), R(1), U8(11), U8(0),
/* 40 S> */ B(LdaUndefined),
B(Star), R(13),
B(LdaImmutableContextSlot), R(1), U8(5), U8(0),
B(Star), R(14),
B(LdaContextSlot), R(1), U8(11), U8(0),
B(Star), R(15),
B(LdaContextSlot), R(1), U8(10), U8(0),
B(Star), R(16),
B(CallJSRuntime), U8(%async_function_await_uncaught), R(13), U8(4),
B(LdaContextSlot), R(1), U8(10), U8(0),
B(Star), R(13),
B(LdaImmutableContextSlot), R(1), U8(5), U8(0),
B(Star), R(14),
B(LdaZero),
B(SuspendGenerator), R(14),
B(Ldar), R(13),
/* 68 S> */ B(Return),
B(LdaSmi), I8(-2),
B(Star), R(3),
B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(14), U8(1),
B(Star), R(15),
B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(14), U8(1),
B(Star), R(16),
B(LdaZero),
B(TestEqualStrict), R(16), U8(0),
B(JumpIfTrue), U8(31),
B(LdaSmi), I8(2),
B(TestEqualStrict), R(16), U8(0),
B(JumpIfTrue), U8(21),
B(Jump), U8(2),
B(LdaTrue),
B(Star), R(18),
B(Mov), R(15), R(17),
B(InvokeIntrinsic), U8(Runtime::k_CreateIterResultObject), R(17), U8(2),
B(Star), R(10),
B(LdaZero),
B(Star), R(9),
B(Jump), U8(167),
B(Ldar), R(15),
B(ReThrow),
B(Ldar), R(15),
/* 40 E> */ B(StaContextSlot), R(1), U8(8), U8(0),
B(InvokeIntrinsic), U8(Runtime::k_IsJSReceiver), R(15), U8(1),
B(ToBooleanLogicalNot),
B(JumpIfFalse), U8(13),
B(LdaContextSlot), R(1), U8(8), U8(0),
B(Star), R(13),
B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(13), U8(1),
B(LdaContextSlot), R(1), U8(8), U8(0),
B(Star), R(13),
B(LdaNamedProperty), R(13), U8(5), U8(15),
B(JumpIfToBooleanTrue), U8(68),
B(LdaContextSlot), R(1), U8(8), U8(0),
B(Star), R(13),
B(LdaNamedProperty), R(13), U8(6), U8(17),
B(StaContextSlot), R(1), U8(12), U8(0),
B(LdaSmi), I8(2),
B(StaContextSlot), R(1), U8(9), U8(0),
B(LdaContextSlot), R(1), U8(12), U8(0),
B(StaContextSlot), R(1), U8(6), U8(0),
/* 23 E> */ B(StackCheck),
B(Ldar), R(closure),
B(CreateBlockContext), U8(7),
B(PushContext), R(2),
B(LdaTheHole),
B(StaCurrentContextSlot), U8(4),
B(LdaContextSlot), R(1), U8(6), U8(0),
B(StaCurrentContextSlot), U8(4),
/* 56 S> */ B(LdaImmutableCurrentContextSlot), U8(4),
B(PopContext), R(2),
B(PopContext), R(2),
B(PopContext), R(2),
B(PopContext), R(2),
B(PopContext), R(2),
B(PopContext), R(2),
B(Star), R(10),
B(LdaSmi), I8(1),
B(Star), R(9),
B(Jump), U8(62),
B(Jump), U8(48),
B(Star), R(13),
B(Ldar), R(closure),
B(CreateCatchContext), R(13), U8(8), U8(9),
B(Star), R(12),
B(LdaTheHole),
B(SetPendingMessage),
B(Ldar), R(12),
B(PushContext), R(2),
B(LdaContextSlot), R(1), U8(9), U8(0),
B(Star), R(13),
B(LdaSmi), I8(2),
B(TestEqualStrict), R(13), U8(19),
B(JumpIfFalse), U8(8),
B(LdaSmi), I8(1),
B(StaContextSlot), R(1), U8(9), U8(0),
B(LdaImmutableCurrentContextSlot), U8(4),
B(Star), R(13),
B(CallRuntime), U16(Runtime::kReThrow), R(13), U8(1),
B(PopContext), R(2),
B(LdaSmi), I8(-1),
B(Star), R(9),
B(Jump), U8(8),
B(Star), R(10),
B(LdaSmi), I8(2),
B(Star), R(9),
B(LdaTheHole),
B(SetPendingMessage),
B(Star), R(11),
B(LdaContextSlot), R(1), U8(9), U8(0),
B(Star), R(12),
B(LdaZero),
B(TestEqualStrict), R(12), U8(20),
B(JumpIfTrueConstant), U8(17),
B(LdaContextSlot), R(1), U8(7), U8(0),
B(Star), R(12),
B(LdaNamedProperty), R(12), U8(10), U8(21),
B(StaContextSlot), R(1), U8(13), U8(0),
B(LdaContextSlot), R(1), U8(13), U8(0),
B(Star), R(12),
B(TestUndetectable), R(12),
B(JumpIfFalse), U8(4),
B(JumpConstant), U8(16),
B(LdaContextSlot), R(1), U8(9), U8(0),
B(Star), R(12),
B(LdaSmi), I8(1),
B(TestEqualStrict), R(12), U8(24),
B(JumpIfFalse), U8(186),
B(LdaContextSlot), R(1), U8(13), U8(0),
B(TypeOf),
B(Star), R(12),
B(LdaConstant), U8(11),
B(TestEqualStrict), R(12), U8(25),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(130),
B(Star), R(12),
B(LdaConstant), U8(12),
B(Star), R(13),
B(CallRuntime), U16(Runtime::kNewTypeError), R(12), U8(2),
B(Throw),
B(Mov), R(context), R(12),
B(LdaContextSlot), R(1), U8(13), U8(0),
B(Star), R(13),
B(LdaContextSlot), R(1), U8(7), U8(0),
B(Star), R(14),
B(InvokeIntrinsic), U8(Runtime::k_Call), R(13), U8(2),
B(StaContextSlot), R(1), U8(14), U8(0),
B(LdaUndefined),
B(Star), R(13),
B(LdaImmutableContextSlot), R(1), U8(5), U8(0),
B(Star), R(14),
B(LdaContextSlot), R(1), U8(14), U8(0),
B(Star), R(15),
B(LdaContextSlot), R(1), U8(10), U8(0),
B(Star), R(16),
B(CallJSRuntime), U8(%async_function_await_caught), R(13), U8(4),
B(LdaContextSlot), R(1), U8(10), U8(0),
B(Star), R(13),
B(LdaImmutableContextSlot), R(1), U8(5), U8(0),
B(Star), R(14),
B(LdaSmi), I8(1),
B(SuspendGenerator), R(14),
B(Ldar), R(13),
/* 68 S> */ B(Return),
B(LdaSmi), I8(-2),
B(Star), R(3),
B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(14), U8(1),
B(Star), R(15),
B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(14), U8(1),
B(Star), R(16),
B(LdaZero),
B(TestEqualStrict), R(16), U8(0),
B(JumpIfTrue), U8(39),
B(LdaSmi), I8(2),
B(TestEqualStrict), R(16), U8(0),
B(JumpIfTrue), U8(29),
B(Jump), U8(2),
B(LdaTrue),
B(Star), R(18),
B(Mov), R(15), R(17),
B(InvokeIntrinsic), U8(Runtime::k_CreateIterResultObject), R(17), U8(2),
B(PopContext), R(1),
B(PopContext), R(1),
B(PopContext), R(1),
B(PopContext), R(1),
B(Star), R(6),
B(LdaZero),
B(Star), R(5),
B(JumpConstant), U8(19),
B(Ldar), R(15),
B(ReThrow),
B(Ldar), R(15),
B(Jump), U8(20),
B(Star), R(13),
B(Ldar), R(closure),
B(CreateCatchContext), R(13), U8(8), U8(14),
B(Star), R(12),
B(LdaTheHole),
B(SetPendingMessage),
B(Ldar), R(12),
B(PushContext), R(2),
B(PopContext), R(2),
B(Jump), U8(159),
B(LdaContextSlot), R(1), U8(13), U8(0),
B(Star), R(12),
B(LdaContextSlot), R(1), U8(7), U8(0),
B(Star), R(13),
B(InvokeIntrinsic), U8(Runtime::k_Call), R(12), U8(2),
B(StaContextSlot), R(1), U8(16), U8(0),
B(LdaUndefined),
B(Star), R(12),
B(LdaImmutableContextSlot), R(1), U8(5), U8(0),
B(Star), R(13),
B(LdaContextSlot), R(1), U8(16), U8(0),
B(Star), R(14),
B(LdaContextSlot), R(1), U8(10), U8(0),
B(Star), R(15),
B(CallJSRuntime), U8(%async_function_await_uncaught), R(12), U8(4),
B(LdaContextSlot), R(1), U8(10), U8(0),
B(Star), R(12),
B(LdaImmutableContextSlot), R(1), U8(5), U8(0),
B(Star), R(13),
B(LdaSmi), I8(2),
B(SuspendGenerator), R(13),
B(Ldar), R(12),
/* 68 S> */ B(Return),
B(LdaSmi), I8(-2),
B(Star), R(3),
B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(13), U8(1),
B(Star), R(14),
B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(13), U8(1),
B(Star), R(15),
B(LdaZero),
B(TestEqualStrict), R(15), U8(0),
B(JumpIfTrue), U8(40),
B(LdaSmi), I8(2),
B(TestEqualStrict), R(15), U8(0),
B(JumpIfTrue), U8(30),
B(Jump), U8(2),
B(LdaTrue),
B(Star), R(17),
B(Mov), R(14), R(16),
B(InvokeIntrinsic), U8(Runtime::k_CreateIterResultObject), R(16), U8(2),
B(PopContext), R(1),
B(PopContext), R(1),
B(PopContext), R(1),
B(PopContext), R(1),
B(Star), R(6),
B(LdaSmi), I8(1),
B(Star), R(5),
B(Jump), U8(194),
B(Ldar), R(14),
B(ReThrow),
B(Ldar), R(14),
B(StaContextSlot), R(1), U8(15), U8(0),
B(LdaContextSlot), R(1), U8(15), U8(0),
B(Star), R(12),
B(InvokeIntrinsic), U8(Runtime::k_IsJSReceiver), R(12), U8(1),
B(JumpIfToBooleanFalse), U8(4),
B(Jump), U8(13),
B(LdaContextSlot), R(1), U8(15), U8(0),
B(Star), R(12),
B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(12), U8(1),
B(Ldar), R(11),
B(SetPendingMessage),
B(LdaZero),
B(TestEqualStrict), R(9), U8(0),
B(JumpIfTrue), U8(18),
B(LdaSmi), I8(1),
B(TestEqualStrict), R(9), U8(0),
B(JumpIfTrue), U8(28),
B(LdaSmi), I8(2),
B(TestEqualStrict), R(9), U8(0),
B(JumpIfTrue), U8(38),
B(Jump), U8(43),
B(PopContext), R(1),
B(PopContext), R(1),
B(PopContext), R(1),
B(PopContext), R(1),
B(LdaSmi), I8(2),
B(Star), R(5),
B(Mov), R(10), R(6),
B(Jump), U8(118),
B(PopContext), R(1),
B(PopContext), R(1),
B(PopContext), R(1),
B(PopContext), R(1),
B(LdaSmi), I8(3),
B(Star), R(5),
B(Mov), R(10), R(6),
B(Jump), U8(101),
B(PopContext), R(1),
B(PopContext), R(1),
B(Ldar), R(10),
B(ReThrow),
B(PopContext), R(1),
B(LdaUndefined),
B(Star), R(9),
B(LdaCurrentContextSlot), U8(10),
B(Star), R(10),
B(LdaUndefined),
B(Star), R(11),
B(CallJSRuntime), U8(%promise_resolve), R(9), U8(3),
B(LdaCurrentContextSlot), U8(10),
B(Star), R(6),
B(LdaSmi), I8(4),
B(Star), R(5),
B(Jump), U8(68),
B(Jump), U8(54),
B(Star), R(9),
B(Ldar), R(closure),
B(CreateCatchContext), R(9), U8(8), U8(18),
B(Star), R(8),
B(LdaTheHole),
B(SetPendingMessage),
B(Ldar), R(8),
B(PushContext), R(1),
B(LdaUndefined),
B(Star), R(9),
B(LdaContextSlot), R(1), U8(10), U8(0),
B(Star), R(10),
B(LdaImmutableCurrentContextSlot), U8(4),
B(Star), R(11),
B(LdaFalse),
B(Star), R(12),
B(CallJSRuntime), U8(%promise_internal_reject), R(9), U8(4),
B(LdaContextSlot), R(1), U8(10), U8(0),
B(PopContext), R(1),
B(PopContext), R(1),
B(Star), R(6),
B(LdaSmi), I8(5),
B(Star), R(5),
B(Jump), U8(14),
B(LdaSmi), I8(-1),
B(Star), R(5),
B(Jump), U8(8),
B(Star), R(6),
B(LdaSmi), I8(6),
B(Star), R(5),
B(LdaTheHole),
B(SetPendingMessage),
B(Star), R(7),
B(LdaUndefined),
B(Star), R(8),
B(LdaCurrentContextSlot), U8(10),
B(Star), R(9),
B(CallJSRuntime), U8(%async_function_promise_release), R(8), U8(2),
B(Ldar), R(7),
B(SetPendingMessage),
B(LdaZero),
B(TestEqualStrict), R(5), U8(0),
B(JumpIfTrue), U8(46),
B(LdaSmi), I8(1),
B(TestEqualStrict), R(5), U8(0),
B(JumpIfTrue), U8(42),
B(LdaSmi), I8(2),
B(TestEqualStrict), R(5), U8(0),
B(JumpIfTrue), U8(38),
B(LdaSmi), I8(3),
B(TestEqualStrict), R(5), U8(0),
B(JumpIfTrue), U8(34),
B(LdaSmi), I8(4),
B(TestEqualStrict), R(5), U8(0),
B(JumpIfTrue), U8(44),
B(LdaSmi), I8(5),
B(TestEqualStrict), R(5), U8(0),
B(JumpIfTrue), U8(40),
B(LdaSmi), I8(6),
B(TestEqualStrict), R(5), U8(0),
B(JumpIfTrue), U8(36),
B(Jump), U8(37),
B(Ldar), R(6),
/* 68 S> */ B(Return),
B(Ldar), R(6),
/* 68 S> */ B(Return),
B(Ldar), R(6),
/* 68 S> */ B(Return),
B(LdaCurrentContextSlot), U8(10),
B(Star), R(9),
B(LdaUndefined),
B(Star), R(8),
B(Mov), R(6), R(10),
B(CallJSRuntime), U8(%promise_resolve), R(8), U8(3),
B(Ldar), R(9),
/* 68 S> */ B(Return),
B(Ldar), R(6),
/* 68 S> */ B(Return),
B(Ldar), R(6),
/* 68 S> */ B(Return),
B(Ldar), R(6),
B(ReThrow),
B(LdaUndefined),
/* 68 S> */ B(Return),
]
constant pool: [
FIXED_ARRAY_TYPE,
CONSTANT_ELEMENTS_PAIR_TYPE,
SYMBOL_TYPE,
SYMBOL_TYPE,
ONE_BYTE_INTERNALIZED_STRING_TYPE ["next"],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["done"],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["value"],
FIXED_ARRAY_TYPE,
ONE_BYTE_INTERNALIZED_STRING_TYPE [".catch"],
FIXED_ARRAY_TYPE,
ONE_BYTE_INTERNALIZED_STRING_TYPE ["return"],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["function"],
ONE_BYTE_INTERNALIZED_STRING_TYPE [""],
Smi [584],
FIXED_ARRAY_TYPE,
Smi [726],
Smi [356],
Smi [382],
FIXED_ARRAY_TYPE,
Smi [344],
]
handlers: [
[83, 998, 1004],
[86, 944, 946],
[103, 444, 450],
[106, 396, 398],
[546, 673, 675],
]
---
snippet: "
async function f() {
for await (let x of [10, 20, 30]) {
if (x == 10) continue;
if (x == 20) break;
}
}
f();
"
frame size: 19
parameter count: 1
bytecode array length: 1092
bytecodes: [
B(Ldar), R(new_target),
B(JumpIfUndefined), U8(42),
B(CallRuntime), U16(Runtime::k_GeneratorGetContext), R(new_target), U8(1),
B(PushContext), R(4),
B(ResumeGenerator), R(new_target),
B(Star), R(3),
B(LdaZero),
B(TestEqualStrict), R(3), U8(0),
B(JumpIfTrue), U8(136),
B(LdaSmi), I8(1),
B(TestEqualStrict), R(3), U8(0),
B(JumpIfTrueConstant), U8(13),
B(LdaSmi), I8(2),
B(TestEqualStrict), R(3), U8(0),
B(JumpIfTrueConstant), U8(15),
B(LdaSmi), I8(78),
B(Star), R(5),
B(CallRuntime), U16(Runtime::kAbort), R(5), U8(1),
B(LdaSmi), I8(-2),
B(Star), R(3),
B(CreateFunctionContext), U8(13),
B(PushContext), R(0),
B(Ldar), R(this),
B(StaCurrentContextSlot), U8(4),
/* 16 E> */ B(StackCheck),
B(LdaImmutableCurrentContextSlot), U8(4),
B(Star), R(6),
B(Mov), R(closure), R(5),
B(CallRuntime), U16(Runtime::kCreateJSGeneratorObject), R(5), U8(2),
B(StaCurrentContextSlot), U8(5),
B(LdaUndefined),
B(Star), R(5),
B(CallJSRuntime), U8(%async_function_promise_create), R(5), U8(1),
B(StaCurrentContextSlot), U8(10),
B(Mov), R(context), R(7),
B(Mov), R(context), R(8),
B(Ldar), R(closure),
B(CreateBlockContext), U8(0),
B(PushContext), R(1),
B(LdaTheHole),
B(StaCurrentContextSlot), U8(4),
B(LdaZero),
B(StaContextSlot), R(1), U8(9), U8(0),
B(Mov), R(context), R(11),
B(Mov), R(context), R(12),
/* 43 S> */ B(CreateArrayLiteral), U8(1), U8(2), U8(9),
B(Star), R(13),
B(LdaNamedProperty), R(13), U8(2), U8(7),
B(JumpIfUndefined), U8(18),
B(JumpIfNull), U8(16),
B(Star), R(14),
B(CallProperty), R(14), R(13), U8(1), U8(9),
B(JumpIfJSReceiver), U8(24),
B(CallRuntime), U16(Runtime::kThrowSymbolAsyncIteratorInvalid), R(0), U8(0),
B(LdaNamedProperty), R(13), U8(3), U8(3),
B(Star), R(14),
B(CallProperty), R(14), R(13), U8(1), U8(5),
B(Star), R(14),
B(InvokeIntrinsic), U8(Runtime::k_CreateAsyncFromSyncIterator), R(14), U8(1),
/* 43 E> */ B(StaContextSlot), R(1), U8(7), U8(0),
B(LdaSmi), I8(-2),
B(TestEqual), R(3), U8(0),
B(JumpIfTrue), U8(17),
B(LdaZero),
B(TestEqualStrict), R(3), U8(0),
B(JumpIfTrue), U8(75),
B(LdaSmi), I8(78),
B(Star), R(13),
B(CallRuntime), U16(Runtime::kAbort), R(13), U8(1),
/* 40 S> */ B(LdaContextSlot), R(1), U8(7), U8(0),
B(Star), R(14),
B(LdaNamedProperty), R(14), U8(4), U8(13),
B(Star), R(13),
/* 40 E> */ B(CallProperty), R(13), R(14), U8(1), U8(11),
B(StaContextSlot), R(1), U8(11), U8(0),
/* 40 S> */ B(LdaUndefined),
B(Star), R(13),
B(LdaImmutableContextSlot), R(1), U8(5), U8(0),
B(Star), R(14),
B(LdaContextSlot), R(1), U8(11), U8(0),
B(Star), R(15),
B(LdaContextSlot), R(1), U8(10), U8(0),
B(Star), R(16),
B(CallJSRuntime), U8(%async_function_await_uncaught), R(13), U8(4),
B(LdaContextSlot), R(1), U8(10), U8(0),
B(Star), R(13),
B(LdaImmutableContextSlot), R(1), U8(5), U8(0),
B(Star), R(14),
B(LdaZero),
B(SuspendGenerator), R(14),
B(Ldar), R(13),
/* 114 S> */ B(Return),
B(LdaSmi), I8(-2),
B(Star), R(3),
B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(14), U8(1),
B(Star), R(15),
B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(14), U8(1),
B(Star), R(16),
B(LdaZero),
B(TestEqualStrict), R(16), U8(0),
B(JumpIfTrue), U8(31),
B(LdaSmi), I8(2),
B(TestEqualStrict), R(16), U8(0),
B(JumpIfTrue), U8(21),
B(Jump), U8(2),
B(LdaTrue),
B(Star), R(18),
B(Mov), R(15), R(17),
B(InvokeIntrinsic), U8(Runtime::k_CreateIterResultObject), R(17), U8(2),
B(Star), R(10),
B(LdaZero),
B(Star), R(9),
B(Jump), U8(192),
B(Ldar), R(15),
B(ReThrow),
B(Ldar), R(15),
/* 40 E> */ B(StaContextSlot), R(1), U8(8), U8(0),
B(InvokeIntrinsic), U8(Runtime::k_IsJSReceiver), R(15), U8(1),
B(ToBooleanLogicalNot),
B(JumpIfFalse), U8(13),
B(LdaContextSlot), R(1), U8(8), U8(0),
B(Star), R(13),
B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(13), U8(1),
B(LdaContextSlot), R(1), U8(8), U8(0),
B(Star), R(13),
B(LdaNamedProperty), R(13), U8(5), U8(15),
B(JumpIfToBooleanTrue), U8(93),
B(LdaContextSlot), R(1), U8(8), U8(0),
B(Star), R(13),
B(LdaNamedProperty), R(13), U8(6), U8(17),
B(StaContextSlot), R(1), U8(12), U8(0),
B(LdaSmi), I8(2),
B(StaContextSlot), R(1), U8(9), U8(0),
B(LdaContextSlot), R(1), U8(12), U8(0),
B(StaContextSlot), R(1), U8(6), U8(0),
/* 23 E> */ B(StackCheck),
B(Ldar), R(closure),
B(CreateBlockContext), U8(7),
B(PushContext), R(2),
B(LdaTheHole),
B(StaCurrentContextSlot), U8(4),
B(LdaContextSlot), R(1), U8(6), U8(0),
B(StaCurrentContextSlot), U8(4),
/* 63 S> */ B(LdaImmutableCurrentContextSlot), U8(4),
B(Star), R(13),
B(LdaSmi), I8(10),
/* 69 E> */ B(TestEqual), R(13), U8(19),
B(JumpIfFalse), U8(8),
/* 76 S> */ B(PopContext), R(2),
B(PopContext), R(2),
B(Jump), U8(26),
/* 90 S> */ B(LdaImmutableCurrentContextSlot), U8(4),
B(Star), R(13),
B(LdaSmi), I8(20),
/* 96 E> */ B(TestEqual), R(13), U8(20),
B(JumpIfFalse), U8(8),
/* 103 S> */ B(PopContext), R(2),
B(PopContext), R(2),
B(Jump), U8(15),
B(PopContext), R(2),
B(LdaZero),
B(StaContextSlot), R(1), U8(9), U8(0),
B(Wide), B(JumpLoop), U16(261), I16(0),
B(Jump), U8(48),
B(Star), R(13),
B(Ldar), R(closure),
B(CreateCatchContext), R(13), U8(8), U8(9),
B(Star), R(12),
B(LdaTheHole),
B(SetPendingMessage),
B(Ldar), R(12),
B(PushContext), R(2),
B(LdaContextSlot), R(1), U8(9), U8(0),
B(Star), R(13),
B(LdaSmi), I8(2),
B(TestEqualStrict), R(13), U8(21),
B(JumpIfFalse), U8(8),
B(LdaSmi), I8(1),
B(StaContextSlot), R(1), U8(9), U8(0),
B(LdaImmutableCurrentContextSlot), U8(4),
B(Star), R(13),
B(CallRuntime), U16(Runtime::kReThrow), R(13), U8(1),
B(PopContext), R(2),
B(LdaSmi), I8(-1),
B(Star), R(9),
B(Jump), U8(8),
B(Star), R(10),
B(LdaSmi), I8(1),
B(Star), R(9),
B(LdaTheHole),
B(SetPendingMessage),
B(Star), R(11),
B(LdaContextSlot), R(1), U8(9), U8(0),
B(Star), R(12),
B(LdaZero),
B(TestEqualStrict), R(12), U8(22),
B(JumpIfTrueConstant), U8(17),
B(LdaContextSlot), R(1), U8(7), U8(0),
B(Star), R(12),
B(LdaNamedProperty), R(12), U8(10), U8(23),
B(StaContextSlot), R(1), U8(13), U8(0),
B(LdaContextSlot), R(1), U8(13), U8(0),
B(Star), R(12),
B(TestUndetectable), R(12),
B(JumpIfFalse), U8(4),
B(JumpConstant), U8(16),
B(LdaContextSlot), R(1), U8(9), U8(0),
B(Star), R(12),
B(LdaSmi), I8(1),
B(TestEqualStrict), R(12), U8(26),
B(JumpIfFalse), U8(186),
B(LdaContextSlot), R(1), U8(13), U8(0),
B(TypeOf),
B(Star), R(12),
B(LdaConstant), U8(11),
B(TestEqualStrict), R(12), U8(27),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(130),
B(Star), R(12),
B(LdaConstant), U8(12),
B(Star), R(13),
B(CallRuntime), U16(Runtime::kNewTypeError), R(12), U8(2),
B(Throw),
B(Mov), R(context), R(12),
B(LdaContextSlot), R(1), U8(13), U8(0),
B(Star), R(13),
B(LdaContextSlot), R(1), U8(7), U8(0),
B(Star), R(14),
B(InvokeIntrinsic), U8(Runtime::k_Call), R(13), U8(2),
B(StaContextSlot), R(1), U8(14), U8(0),
B(LdaUndefined),
B(Star), R(13),
B(LdaImmutableContextSlot), R(1), U8(5), U8(0),
B(Star), R(14),
B(LdaContextSlot), R(1), U8(14), U8(0),
B(Star), R(15),
B(LdaContextSlot), R(1), U8(10), U8(0),
B(Star), R(16),
B(CallJSRuntime), U8(%async_function_await_caught), R(13), U8(4),
B(LdaContextSlot), R(1), U8(10), U8(0),
B(Star), R(13),
B(LdaImmutableContextSlot), R(1), U8(5), U8(0),
B(Star), R(14),
B(LdaSmi), I8(1),
B(SuspendGenerator), R(14),
B(Ldar), R(13),
/* 114 S> */ B(Return),
B(LdaSmi), I8(-2),
B(Star), R(3),
B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(14), U8(1),
B(Star), R(15),
B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(14), U8(1),
B(Star), R(16),
B(LdaZero),
B(TestEqualStrict), R(16), U8(0),
B(JumpIfTrue), U8(39),
B(LdaSmi), I8(2),
B(TestEqualStrict), R(16), U8(0),
B(JumpIfTrue), U8(29),
B(Jump), U8(2),
B(LdaTrue),
B(Star), R(18),
B(Mov), R(15), R(17),
B(InvokeIntrinsic), U8(Runtime::k_CreateIterResultObject), R(17), U8(2),
B(PopContext), R(1),
B(PopContext), R(1),
B(PopContext), R(1),
B(PopContext), R(1),
B(Star), R(6),
B(LdaZero),
B(Star), R(5),
B(JumpConstant), U8(19),
B(Ldar), R(15),
B(ReThrow),
B(Ldar), R(15),
B(Jump), U8(20),
B(Star), R(13),
B(Ldar), R(closure),
B(CreateCatchContext), R(13), U8(8), U8(14),
B(Star), R(12),
B(LdaTheHole),
B(SetPendingMessage),
B(Ldar), R(12),
B(PushContext), R(2),
B(PopContext), R(2),
B(Jump), U8(159),
B(LdaContextSlot), R(1), U8(13), U8(0),
B(Star), R(12),
B(LdaContextSlot), R(1), U8(7), U8(0),
B(Star), R(13),
B(InvokeIntrinsic), U8(Runtime::k_Call), R(12), U8(2),
B(StaContextSlot), R(1), U8(16), U8(0),
B(LdaUndefined),
B(Star), R(12),
B(LdaImmutableContextSlot), R(1), U8(5), U8(0),
B(Star), R(13),
B(LdaContextSlot), R(1), U8(16), U8(0),
B(Star), R(14),
B(LdaContextSlot), R(1), U8(10), U8(0),
B(Star), R(15),
B(CallJSRuntime), U8(%async_function_await_uncaught), R(12), U8(4),
B(LdaContextSlot), R(1), U8(10), U8(0),
B(Star), R(12),
B(LdaImmutableContextSlot), R(1), U8(5), U8(0),
B(Star), R(13),
B(LdaSmi), I8(2),
B(SuspendGenerator), R(13),
B(Ldar), R(12),
/* 114 S> */ B(Return),
B(LdaSmi), I8(-2),
B(Star), R(3),
B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(13), U8(1),
B(Star), R(14),
B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(13), U8(1),
B(Star), R(15),
B(LdaZero),
B(TestEqualStrict), R(15), U8(0),
B(JumpIfTrue), U8(40),
B(LdaSmi), I8(2),
B(TestEqualStrict), R(15), U8(0),
B(JumpIfTrue), U8(30),
B(Jump), U8(2),
B(LdaTrue),
B(Star), R(17),
B(Mov), R(14), R(16),
B(InvokeIntrinsic), U8(Runtime::k_CreateIterResultObject), R(16), U8(2),
B(PopContext), R(1),
B(PopContext), R(1),
B(PopContext), R(1),
B(PopContext), R(1),
B(Star), R(6),
B(LdaSmi), I8(1),
B(Star), R(5),
B(Jump), U8(170),
B(Ldar), R(14),
B(ReThrow),
B(Ldar), R(14),
B(StaContextSlot), R(1), U8(15), U8(0),
B(LdaContextSlot), R(1), U8(15), U8(0),
B(Star), R(12),
B(InvokeIntrinsic), U8(Runtime::k_IsJSReceiver), R(12), U8(1),
B(JumpIfToBooleanFalse), U8(4),
B(Jump), U8(13),
B(LdaContextSlot), R(1), U8(15), U8(0),
B(Star), R(12),
B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(12), U8(1),
B(Ldar), R(11),
B(SetPendingMessage),
B(LdaZero),
B(TestEqualStrict), R(9), U8(0),
B(JumpIfTrue), U8(11),
B(LdaSmi), I8(1),
B(TestEqualStrict), R(9), U8(0),
B(JumpIfTrue), U8(21),
B(Jump), U8(26),
B(PopContext), R(1),
B(PopContext), R(1),
B(PopContext), R(1),
B(PopContext), R(1),
B(LdaSmi), I8(2),
B(Star), R(5),
B(Mov), R(10), R(6),
B(Jump), U8(101),
B(PopContext), R(1),
B(PopContext), R(1),
B(Ldar), R(10),
B(ReThrow),
B(PopContext), R(1),
B(LdaUndefined),
B(Star), R(9),
B(LdaCurrentContextSlot), U8(10),
B(Star), R(10),
B(LdaUndefined),
B(Star), R(11),
B(CallJSRuntime), U8(%promise_resolve), R(9), U8(3),
B(LdaCurrentContextSlot), U8(10),
B(Star), R(6),
B(LdaSmi), I8(3),
B(Star), R(5),
B(Jump), U8(68),
B(Jump), U8(54),
B(Star), R(9),
B(Ldar), R(closure),
B(CreateCatchContext), R(9), U8(8), U8(18),
B(Star), R(8),
B(LdaTheHole),
B(SetPendingMessage),
B(Ldar), R(8),
B(PushContext), R(1),
B(LdaUndefined),
B(Star), R(9),
B(LdaContextSlot), R(1), U8(10), U8(0),
B(Star), R(10),
B(LdaImmutableCurrentContextSlot), U8(4),
B(Star), R(11),
B(LdaFalse),
B(Star), R(12),
B(CallJSRuntime), U8(%promise_internal_reject), R(9), U8(4),
B(LdaContextSlot), R(1), U8(10), U8(0),
B(PopContext), R(1),
B(PopContext), R(1),
B(Star), R(6),
B(LdaSmi), I8(4),
B(Star), R(5),
B(Jump), U8(14),
B(LdaSmi), I8(-1),
B(Star), R(5),
B(Jump), U8(8),
B(Star), R(6),
B(LdaSmi), I8(5),
B(Star), R(5),
B(LdaTheHole),
B(SetPendingMessage),
B(Star), R(7),
B(LdaUndefined),
B(Star), R(8),
B(LdaCurrentContextSlot), U8(10),
B(Star), R(9),
B(CallJSRuntime), U8(%async_function_promise_release), R(8), U8(2),
B(Ldar), R(7),
B(SetPendingMessage),
B(LdaZero),
B(TestEqualStrict), R(5), U8(0),
B(JumpIfTrue), U8(39),
B(LdaSmi), I8(1),
B(TestEqualStrict), R(5), U8(0),
B(JumpIfTrue), U8(35),
B(LdaSmi), I8(2),
B(TestEqualStrict), R(5), U8(0),
B(JumpIfTrue), U8(31),
B(LdaSmi), I8(3),
B(TestEqualStrict), R(5), U8(0),
B(JumpIfTrue), U8(27),
B(LdaSmi), I8(4),
B(TestEqualStrict), R(5), U8(0),
B(JumpIfTrue), U8(23),
B(LdaSmi), I8(5),
B(TestEqualStrict), R(5), U8(0),
B(JumpIfTrue), U8(19),
B(Jump), U8(20),
B(Ldar), R(6),
/* 114 S> */ B(Return),
B(Ldar), R(6),
/* 114 S> */ B(Return),
B(Ldar), R(6),
/* 114 S> */ B(Return),
B(Ldar), R(6),
/* 114 S> */ B(Return),
B(Ldar), R(6),
/* 114 S> */ B(Return),
B(Ldar), R(6),
B(ReThrow),
B(LdaUndefined),
/* 114 S> */ B(Return),
]
constant pool: [
FIXED_ARRAY_TYPE,
CONSTANT_ELEMENTS_PAIR_TYPE,
SYMBOL_TYPE,
SYMBOL_TYPE,
ONE_BYTE_INTERNALIZED_STRING_TYPE ["next"],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["done"],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["value"],
FIXED_ARRAY_TYPE,
ONE_BYTE_INTERNALIZED_STRING_TYPE [".catch"],
FIXED_ARRAY_TYPE,
ONE_BYTE_INTERNALIZED_STRING_TYPE ["return"],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["function"],
ONE_BYTE_INTERNALIZED_STRING_TYPE [""],
Smi [609],
FIXED_ARRAY_TYPE,
Smi [751],
Smi [356],
Smi [382],
FIXED_ARRAY_TYPE,
Smi [320],
]
handlers: [
[83, 999, 1005],
[86, 945, 947],
[103, 469, 475],
[106, 421, 423],
[571, 698, 700],
]
---
snippet: "
async function f() {
var x = { 'a': 1, 'b': 2 };
for (x['a'] of [1,2,3]) { return x['a']; }
}
f();
"
frame size: 14
parameter count: 1
bytecode array length: 596
bytecodes: [
B(Ldar), R(new_target),
B(JumpIfUndefined), U8(22),
B(CallRuntime), U16(Runtime::k_GeneratorGetContext), R(new_target), U8(1),
B(PushContext), R(3),
B(ResumeGenerator), R(new_target),
B(Star), R(2),
B(LdaSmi), I8(78),
B(Star), R(4),
B(CallRuntime), U16(Runtime::kAbort), R(4), U8(1),
B(LdaSmi), I8(-2),
B(Star), R(2),
B(CreateFunctionContext), U8(10),
B(PushContext), R(0),
B(Ldar), R(this),
B(StaCurrentContextSlot), U8(4),
/* 16 E> */ B(StackCheck),
B(LdaImmutableCurrentContextSlot), U8(4),
B(Star), R(5),
B(Mov), R(closure), R(4),
B(CallRuntime), U16(Runtime::kCreateJSGeneratorObject), R(4), U8(2),
B(StaCurrentContextSlot), U8(5),
B(LdaUndefined),
B(Star), R(4),
B(CallJSRuntime), U8(%async_function_promise_create), R(4), U8(1),
B(StaCurrentContextSlot), U8(13),
B(Mov), R(context), R(6),
B(Mov), R(context), R(7),
/* 31 S> */ B(CreateObjectLiteral), U8(0), U8(2), U8(1), R(8),
B(Ldar), R(8),
/* 31 E> */ B(StaCurrentContextSlot), U8(6),
B(LdaZero),
B(StaCurrentContextSlot), U8(9),
B(Mov), R(context), R(10),
B(Mov), R(context), R(11),
/* 68 S> */ B(CreateArrayLiteral), U8(1), U8(3), U8(9),
B(Star), R(12),
B(LdaNamedProperty), R(12), U8(2), U8(4),
B(Star), R(13),
B(CallProperty), R(13), R(12), U8(1), U8(6),
B(JumpIfJSReceiver), U8(7),
B(CallRuntime), U16(Runtime::kThrowSymbolIteratorInvalid), R(0), U8(0),
/* 68 E> */ B(StaCurrentContextSlot), U8(7),
/* 65 S> */ B(LdaCurrentContextSlot), U8(7),
B(Star), R(13),
B(LdaNamedProperty), R(13), U8(3), U8(10),
B(Star), R(12),
/* 65 E> */ B(CallProperty), R(12), R(13), U8(1), U8(8),
/* 65 E> */ B(StaCurrentContextSlot), U8(8),
B(Star), R(12),
B(InvokeIntrinsic), U8(Runtime::k_IsJSReceiver), R(12), U8(1),
B(ToBooleanLogicalNot),
B(JumpIfFalse), U8(11),
B(LdaCurrentContextSlot), U8(8),
B(Star), R(12),
B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(12), U8(1),
B(LdaCurrentContextSlot), U8(8),
B(Star), R(12),
B(LdaNamedProperty), R(12), U8(4), U8(12),
B(JumpIfToBooleanTrue), U8(42),
B(LdaImmutableCurrentContextSlot), U8(6),
B(Star), R(12),
B(LdaCurrentContextSlot), U8(8),
B(Star), R(13),
/* 58 E> */ B(LdaNamedProperty), R(13), U8(5), U8(14),
B(StaCurrentContextSlot), U8(10),
B(LdaSmi), I8(2),
B(StaCurrentContextSlot), U8(9),
B(LdaCurrentContextSlot), U8(10),
B(StaNamedPropertySloppy), R(12), U8(6), U8(16),
/* 53 E> */ B(StackCheck),
/* 79 S> */ B(LdaImmutableCurrentContextSlot), U8(6),
B(Star), R(12),
/* 87 E> */ B(LdaNamedProperty), R(12), U8(6), U8(18),
B(Star), R(9),
B(LdaZero),
B(Star), R(8),
B(Jump), U8(62),
B(Jump), U8(48),
B(Star), R(12),
B(Ldar), R(closure),
B(CreateCatchContext), R(12), U8(7), U8(8),
B(Star), R(11),
B(LdaTheHole),
B(SetPendingMessage),
B(Ldar), R(11),
B(PushContext), R(1),
B(LdaContextSlot), R(1), U8(9), U8(0),
B(Star), R(12),
B(LdaSmi), I8(2),
B(TestEqualStrict), R(12), U8(20),
B(JumpIfFalse), U8(8),
B(LdaSmi), I8(1),
B(StaContextSlot), R(1), U8(9), U8(0),
B(LdaImmutableCurrentContextSlot), U8(4),
B(Star), R(12),
B(CallRuntime), U16(Runtime::kReThrow), R(12), U8(1),
B(PopContext), R(1),
B(LdaSmi), I8(-1),
B(Star), R(8),
B(Jump), U8(8),
B(Star), R(9),
B(LdaSmi), I8(1),
B(Star), R(8),
B(LdaTheHole),
B(SetPendingMessage),
B(Star), R(10),
B(LdaCurrentContextSlot), U8(9),
B(Star), R(11),
B(LdaZero),
B(TestEqualStrict), R(11), U8(21),
B(JumpIfTrue), U8(135),
B(LdaCurrentContextSlot), U8(7),
B(Star), R(11),
B(LdaNamedProperty), R(11), U8(9), U8(22),
B(StaCurrentContextSlot), U8(11),
B(LdaCurrentContextSlot), U8(11),
B(Star), R(11),
B(TestUndetectable), R(11),
B(JumpIfFalse), U8(4),
B(Jump), U8(115),
B(LdaCurrentContextSlot), U8(9),
B(Star), R(11),
B(LdaSmi), I8(1),
B(TestEqualStrict), R(11), U8(25),
B(JumpIfFalse), U8(69),
B(LdaCurrentContextSlot), U8(11),
B(TypeOf),
B(Star), R(11),
B(LdaConstant), U8(10),
B(TestEqualStrict), R(11), U8(26),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(130),
B(Star), R(11),
B(LdaConstant), U8(11),
B(Star), R(12),
B(CallRuntime), U16(Runtime::kNewTypeError), R(11), U8(2),
B(Throw),
B(Mov), R(context), R(11),
B(LdaCurrentContextSlot), U8(11),
B(Star), R(12),
B(LdaCurrentContextSlot), U8(7),
B(Star), R(13),
B(InvokeIntrinsic), U8(Runtime::k_Call), R(12), U8(2),
B(Jump), U8(20),
B(Star), R(12),
B(Ldar), R(closure),
B(CreateCatchContext), R(12), U8(7), U8(12),
B(Star), R(11),
B(LdaTheHole),
B(SetPendingMessage),
B(Ldar), R(11),
B(PushContext), R(1),
B(PopContext), R(1),
B(Jump), U8(37),
B(LdaCurrentContextSlot), U8(11),
B(Star), R(11),
B(LdaCurrentContextSlot), U8(7),
B(Star), R(12),
B(InvokeIntrinsic), U8(Runtime::k_Call), R(11), U8(2),
B(StaCurrentContextSlot), U8(12),
B(LdaCurrentContextSlot), U8(12),
B(Star), R(11),
B(InvokeIntrinsic), U8(Runtime::k_IsJSReceiver), R(11), U8(1),
B(JumpIfToBooleanFalse), U8(4),
B(Jump), U8(11),
B(LdaCurrentContextSlot), U8(12),
B(Star), R(11),
B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(11), U8(1),
B(Ldar), R(10),
B(SetPendingMessage),
B(LdaZero),
B(TestEqualStrict), R(8), U8(0),
B(JumpIfTrue), U8(11),
B(LdaSmi), I8(1),
B(TestEqualStrict), R(8), U8(0),
B(JumpIfTrue), U8(12),
B(Jump), U8(13),
B(LdaZero),
B(Star), R(4),
B(Mov), R(9), R(5),
B(Jump), U8(95),
B(Ldar), R(9),
B(ReThrow),
B(LdaUndefined),
B(Star), R(8),
B(LdaCurrentContextSlot), U8(13),
B(Star), R(9),
B(LdaUndefined),
B(Star), R(10),
B(CallJSRuntime), U8(%promise_resolve), R(8), U8(3),
B(LdaCurrentContextSlot), U8(13),
B(Star), R(5),
B(LdaSmi), I8(1),
B(Star), R(4),
B(Jump), U8(68),
B(Jump), U8(54),
B(Star), R(8),
B(Ldar), R(closure),
B(CreateCatchContext), R(8), U8(7), U8(13),
B(Star), R(7),
B(LdaTheHole),
B(SetPendingMessage),
B(Ldar), R(7),
B(PushContext), R(1),
B(LdaUndefined),
B(Star), R(8),
B(LdaContextSlot), R(1), U8(13), U8(0),
B(Star), R(9),
B(LdaImmutableCurrentContextSlot), U8(4),
B(Star), R(10),
B(LdaFalse),
B(Star), R(11),
B(CallJSRuntime), U8(%promise_internal_reject), R(8), U8(4),
B(LdaContextSlot), R(1), U8(13), U8(0),
B(PopContext), R(1),
B(PopContext), R(1),
B(Star), R(5),
B(LdaSmi), I8(2),
B(Star), R(4),
B(Jump), U8(14),
B(LdaSmi), I8(-1),
B(Star), R(4),
B(Jump), U8(8),
B(Star), R(5),
B(LdaSmi), I8(3),
B(Star), R(4),
B(LdaTheHole),
B(SetPendingMessage),
B(Star), R(6),
B(LdaUndefined),
B(Star), R(7),
B(LdaCurrentContextSlot), U8(13),
B(Star), R(8),
B(CallJSRuntime), U8(%async_function_promise_release), R(7), U8(2),
B(Ldar), R(6),
B(SetPendingMessage),
B(LdaZero),
B(TestEqualStrict), R(4), U8(0),
B(JumpIfTrue), U8(25),
B(LdaSmi), I8(1),
B(TestEqualStrict), R(4), U8(0),
B(JumpIfTrue), U8(35),
B(LdaSmi), I8(2),
B(TestEqualStrict), R(4), U8(0),
B(JumpIfTrue), U8(31),
B(LdaSmi), I8(3),
B(TestEqualStrict), R(4), U8(0),
B(JumpIfTrue), U8(27),
B(Jump), U8(28),
B(LdaCurrentContextSlot), U8(13),
B(Star), R(8),
B(LdaUndefined),
B(Star), R(7),
B(Mov), R(5), R(9),
B(CallJSRuntime), U8(%promise_resolve), R(7), U8(3),
B(Ldar), R(8),
/* 96 S> */ B(Return),
B(Ldar), R(5),
/* 96 S> */ B(Return),
B(Ldar), R(5),
/* 96 S> */ B(Return),
B(Ldar), R(5),
B(ReThrow),
B(LdaUndefined),
/* 96 S> */ B(Return),
]
constant pool: [
FIXED_ARRAY_TYPE,
CONSTANT_ELEMENTS_PAIR_TYPE,
SYMBOL_TYPE,
ONE_BYTE_INTERNALIZED_STRING_TYPE ["next"],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["done"],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["value"],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["a"],
ONE_BYTE_INTERNALIZED_STRING_TYPE [".catch"],
FIXED_ARRAY_TYPE,
ONE_BYTE_INTERNALIZED_STRING_TYPE ["return"],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["function"],
ONE_BYTE_INTERNALIZED_STRING_TYPE [""],
FIXED_ARRAY_TYPE,
FIXED_ARRAY_TYPE,
]
handlers: [
[63, 509, 515],
[66, 455, 457],
[81, 243, 249],
[84, 195, 197],
[333, 345, 347],
]
...@@ -43,6 +43,7 @@ class ProgramOptions final { ...@@ -43,6 +43,7 @@ class ProgramOptions final {
module_(false), module_(false),
top_level_(false), top_level_(false),
do_expressions_(false), do_expressions_(false),
async_iteration_(false),
verbose_(false) {} verbose_(false) {}
bool Validate() const; bool Validate() const;
...@@ -61,6 +62,7 @@ class ProgramOptions final { ...@@ -61,6 +62,7 @@ class ProgramOptions final {
bool module() const { return module_; } bool module() const { return module_; }
bool top_level() const { return top_level_; } bool top_level() const { return top_level_; }
bool do_expressions() const { return do_expressions_; } bool do_expressions() const { return do_expressions_; }
bool async_iteration() const { return async_iteration_; }
bool verbose() const { return verbose_; } bool verbose() const { return verbose_; }
bool suppress_runtime_errors() const { return rebaseline_ && !verbose_; } bool suppress_runtime_errors() const { return rebaseline_ && !verbose_; }
std::vector<std::string> input_filenames() const { return input_filenames_; } std::vector<std::string> input_filenames() const { return input_filenames_; }
...@@ -77,6 +79,7 @@ class ProgramOptions final { ...@@ -77,6 +79,7 @@ class ProgramOptions final {
bool module_; bool module_;
bool top_level_; bool top_level_;
bool do_expressions_; bool do_expressions_;
bool async_iteration_;
bool verbose_; bool verbose_;
std::vector<std::string> input_filenames_; std::vector<std::string> input_filenames_;
std::string output_filename_; std::string output_filename_;
...@@ -165,6 +168,8 @@ ProgramOptions ProgramOptions::FromCommandLine(int argc, char** argv) { ...@@ -165,6 +168,8 @@ ProgramOptions ProgramOptions::FromCommandLine(int argc, char** argv) {
options.top_level_ = true; options.top_level_ = true;
} else if (strcmp(argv[i], "--do-expressions") == 0) { } else if (strcmp(argv[i], "--do-expressions") == 0) {
options.do_expressions_ = true; options.do_expressions_ = true;
} else if (strcmp(argv[i], "--async-iteration") == 0) {
options.async_iteration_ = true;
} else if (strcmp(argv[i], "--verbose") == 0) { } else if (strcmp(argv[i], "--verbose") == 0) {
options.verbose_ = true; options.verbose_ = true;
} else if (strncmp(argv[i], "--output=", 9) == 0) { } else if (strncmp(argv[i], "--output=", 9) == 0) {
...@@ -267,6 +272,8 @@ void ProgramOptions::UpdateFromHeader(std::istream& stream) { ...@@ -267,6 +272,8 @@ void ProgramOptions::UpdateFromHeader(std::istream& stream) {
top_level_ = ParseBoolean(line.c_str() + 11); top_level_ = ParseBoolean(line.c_str() + 11);
} else if (line.compare(0, 16, "do expressions: ") == 0) { } else if (line.compare(0, 16, "do expressions: ") == 0) {
do_expressions_ = ParseBoolean(line.c_str() + 16); do_expressions_ = ParseBoolean(line.c_str() + 16);
} else if (line.compare(0, 17, "async iteration: ") == 0) {
async_iteration_ = ParseBoolean(line.c_str() + 17);
} else if (line == "---") { } else if (line == "---") {
break; break;
} else if (line.empty()) { } else if (line.empty()) {
...@@ -289,6 +296,7 @@ void ProgramOptions::PrintHeader(std::ostream& stream) const { // NOLINT ...@@ -289,6 +296,7 @@ void ProgramOptions::PrintHeader(std::ostream& stream) const { // NOLINT
if (module_) stream << "\nmodule: yes"; if (module_) stream << "\nmodule: yes";
if (top_level_) stream << "\ntop level: yes"; if (top_level_) stream << "\ntop level: yes";
if (do_expressions_) stream << "\ndo expressions: yes"; if (do_expressions_) stream << "\ndo expressions: yes";
if (async_iteration_) stream << "\nasync iteration: yes";
stream << "\n\n"; stream << "\n\n";
} }
...@@ -393,6 +401,7 @@ void GenerateExpectationsFile(std::ostream& stream, // NOLINT ...@@ -393,6 +401,7 @@ void GenerateExpectationsFile(std::ostream& stream, // NOLINT
} }
if (options.do_expressions()) i::FLAG_harmony_do_expressions = true; if (options.do_expressions()) i::FLAG_harmony_do_expressions = true;
if (options.async_iteration()) i::FLAG_harmony_async_iteration = true;
stream << "#\n# Autogenerated by generate-bytecode-expectations.\n#\n\n"; stream << "#\n# Autogenerated by generate-bytecode-expectations.\n#\n\n";
options.PrintHeader(stream); options.PrintHeader(stream);
...@@ -401,6 +410,7 @@ void GenerateExpectationsFile(std::ostream& stream, // NOLINT ...@@ -401,6 +410,7 @@ void GenerateExpectationsFile(std::ostream& stream, // NOLINT
} }
i::FLAG_harmony_do_expressions = false; i::FLAG_harmony_do_expressions = false;
i::FLAG_harmony_async_iteration = false;
} }
bool WriteExpectationsFile(const std::vector<std::string>& snippet_list, bool WriteExpectationsFile(const std::vector<std::string>& snippet_list,
...@@ -445,6 +455,7 @@ void PrintUsage(const char* exec_path) { ...@@ -445,6 +455,7 @@ void PrintUsage(const char* exec_path) {
"Specify the name of the test function.\n" "Specify the name of the test function.\n"
" --top-level Process top level code, not the top-level function.\n" " --top-level Process top level code, not the top-level function.\n"
" --do-expressions Enable harmony_do_expressions flag.\n" " --do-expressions Enable harmony_do_expressions flag.\n"
" --async-iteration Enable harmony_async_iteration flag.\n"
" --output=file.name\n" " --output=file.name\n"
" Specify the output file. If not specified, output goes to " " Specify the output file. If not specified, output goes to "
"stdout.\n" "stdout.\n"
......
...@@ -2371,6 +2371,45 @@ TEST(NewAndSpread) { ...@@ -2371,6 +2371,45 @@ TEST(NewAndSpread) {
LoadGolden("NewAndSpread.golden"))); LoadGolden("NewAndSpread.golden")));
} }
TEST(ForAwaitOf) {
bool old_flag = i::FLAG_harmony_async_iteration;
i::FLAG_harmony_async_iteration = true;
InitializedIgnitionHandleScope scope;
BytecodeExpectationsPrinter printer(CcTest::isolate());
printer.set_wrap(false);
printer.set_test_function_name("f");
const char* snippets[] = {
"async function f() {\n"
" for await (let x of [1, 2, 3]) {}\n"
"}\n"
"f();\n",
"async function f() {\n"
" for await (let x of [1, 2, 3]) { return x; }\n"
"}\n"
"f();\n",
"async function f() {\n"
" for await (let x of [10, 20, 30]) {\n"
" if (x == 10) continue;\n"
" if (x == 20) break;\n"
" }\n"
"}\n"
"f();\n",
"async function f() {\n"
" var x = { 'a': 1, 'b': 2 };\n"
" for (x['a'] of [1,2,3]) { return x['a']; }\n"
"}\n"
"f();\n"};
CHECK(CompareTexts(BuildActual(printer, snippets),
LoadGolden("ForAwaitOf.golden")));
i::FLAG_harmony_async_iteration = old_flag;
}
} // namespace interpreter } // namespace interpreter
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony-async-iteration --allow-natives-syntax
let testFailed = false;
let testFailure;
function assertThrowsAsync(run, errorType, message) {
var actual;
var hadValue = false;
var hadError = false;
var promise = run();
if (typeof promise !== "object" || typeof promise.then !== "function") {
throw new MjsUnitAssertionError(
"Expected " + run.toString() +
" to return a Promise, but it returned " + PrettyPrint(promise));
}
promise.then(function(value) { hadValue = true; actual = value; },
function(error) { hadError = true; actual = error; });
assertFalse(hadValue || hadError);
%RunMicrotasks();
if (!hadError) {
throw new MjsUnitAssertionError(
"Expected " + run + "() to throw " + errorType.name +
", but did not throw.");
}
if (!(actual instanceof errorType))
throw new MjsUnitAssertionError(
"Expected " + run + "() to throw " + errorType.name +
", but threw '" + actual + "'");
if (message !== void 0 && actual.message !== message)
throw new MjsUnitAssertionError(
"Expected " + run + "() to throw '" + message + "', but threw '" +
actual.message + "'");
};
function resolveLater(value) {
return new Promise(function(resolve) {
Promise.resolve().then(function() {
resolve(value);
});
});
}
function rejectLater(value) {
return new Promise(function(resolve, reject) {
Promise.resolve().then(function() {
reject(value);
});
});
}
const kNext = 1;
const kThrow = 2;
const kReturn = 4;
const kNextThrows = kNext | 8;
const kReturnThrows = kReturn | 16;
const kThrowNormal = kThrow | 32;
const kNextUnchanged = kNext | 64;
const kReturnUnchanged = kReturn | 128;
const kThrowUnchanged = kThrow | 256;
function sync(array, features, log) {
// `log` is a required parameter
if (log === void 0) %AbortJS("`log` is undefined");
let i = 0;
let methods = {
next(sent) {
let done = i >= array.length;
let value = array[i];
log.push({ method: "next", sent, value, done });
if ((features & kNextThrows) === kNextThrows) throw sent;
if ((features & kNextUnchanged) === kNextUnchanged) return sent;
i++;
return { value, done };
},
throw(sent) {
let done = i >= array.length;
log.push({ method: "throw", sent, done });
if ((features & kThrowNormal) === kThrowNormal)
return { value: sent, done };
if ((features & kThrowUnchanged) === kThrowUnchanged) return sent;
throw sent;
},
return(sent) {
let done = true;
log.push({ method: "return", sent, done });
if ((features & kReturnThrows) === kReturnThrows) throw sent;
if ((features & kReturnUnchanged) === kReturnUnchanged) return sent;
return { value: sent, done };
}
};
return {
[Symbol.iterator]() { return this; },
next: (features & kNext) ? methods.next : undefined,
throw: (features & kThrow) ? methods.throw : undefined,
return: (features & kReturn) ? methods.return : undefined
};
}
class MyError extends Error {};
(async function AsyncFromSyncWithGenerator() {
function* gen() {
yield "sync value";
try {
yield new Promise(function(resolve) {
resolve("async value");
});
} catch (error) {
throw error;
}
assertUnreachable("generator is closed");
}
let iter = %CreateAsyncFromSyncIterator(gen());
// [Async-from-Sync Iterator] wraps sync iterator values in a Promise
let promise = iter.next();
assertInstanceof(promise, Promise);
let iter_result = await promise;
assertEquals({ value: "sync value", done: false }, iter_result);
// [Async-from-Sync Iterator] will wait for resolution of Promise values
promise = iter.next();
assertInstanceof(promise, Promise);
iter_result = await promise;
assertEquals({ value: "async value", done: false }, iter_result);
// [Async-from-Sync Iterator].throw delegates to .throw() method of sync
// iterator.
promise = iter.throw(new MyError("Error#1"));
assertInstanceof(promise, Promise);
try {
await promise;
assertUnreachable("promise should be rejected");
} catch (e) {
// If assertUnreachable failed, rethrow
if (e instanceof MjsUnitAssertionError) throw e;
assertInstanceof(e, MyError);
assertEquals("Error#1", e.message);
}
// Generator is closed, subsequent calls to .next() will not resume.
promise = iter.next("floof");
iter_result = await promise;
assertEquals({ value: undefined, done: true }, iter_result);
promise = iter.return("generator closed");
assertInstanceof(promise, Promise);
iter_result = await promise;
assertEquals({ value: "generator closed", done: true }, iter_result);
// .next(), .return() and .throw() delegate to sync iterator methods, without
// keeping track of the state of the generator.
promise = iter.next("unused");
assertInstanceof(promise, Promise);
iter_result = await promise;
assertEquals({ value: undefined, done: true }, iter_result);
promise = iter.throw(new MyError("Error#2"));
assertInstanceof(promise, Promise);
try {
await promise;
assertUnreachable("promise should be rejected");
} catch (e) {
// If assertUnreachable failed, rethrow
if (e instanceof MjsUnitAssertionError) throw e;
assertInstanceof(e, MyError);
assertEquals("Error#2", e.message);
}
promise = iter.return("return-after-completed");
assertInstanceof(promise, Promise);
iter_result = await promise;
assertEquals({ value: "return-after-completed", done: true }, iter_result);
})().catch(function(error) {
testFailed = true;
testFailure = error;
});
%RunMicrotasks();
if (testFailed) {
throw testFailure;
}
(async function AsyncFromSyncOrderOfOperations() {
let log = [];
iter = %CreateAsyncFromSyncIterator(sync(["sync-value"], 0, log));
try {
await iter.next();
assertUnreachable("Iterator.next() method is not optional");
} catch (e) {
assertInstanceof(e, TypeError);
assertEquals([], log);
}
log = [];
iter = %CreateAsyncFromSyncIterator(sync(["sync-value"], kNext, log));
assertEquals({ value: "sync-value", done: false }, await iter.next("a"));
assertEquals([
{
method: "next",
sent: "a",
value: "sync-value",
done: false
}
], log);
log = [];
let asyncValue = resolveLater("async-value");
iter = %CreateAsyncFromSyncIterator(sync([asyncValue], kNext, log));
assertEquals({ value: "async-value", done: false }, await iter.next("b"));
assertEquals([
{
method: "next",
sent: "b",
value: asyncValue,
done: false
}
], log);
// If [sync_iterator].next() produces a rejected Promise or an exception is
// thrown, Promise is rejected with thrown/rejected value.
log = [];
asyncValue = rejectLater("Boo!");
iter = %CreateAsyncFromSyncIterator(sync([asyncValue], kNext, log));
try {
await iter.next('c');
assertUnreachable('Expected `iter.next(\'c\') to throw, but did not throw');
} catch (e) {
assertEquals("Boo!", e);
assertEquals([
{
method: 'next',
sent: 'c',
value: asyncValue,
done: false
}
], log);
}
log = [];
iter = %CreateAsyncFromSyncIterator(sync(['sync-value'], kNextThrows, log));
try {
await iter.next('Boo!');
assertUnreachable('Expected `iter.next(\'c\') to throw, but did not throw');
} catch (e) {
assertEquals("Boo!", e);
assertEquals([
{
method: 'next',
sent: 'Boo!',
value: 'sync-value',
done: false
}
], log);
}
// [Async-from-Sync Iterator].next() will be rejected with a TypeError if
// Type([sync_iterator].next()) is not Object.
log = [];
iter = %CreateAsyncFromSyncIterator(sync(['sync-value'], kNextUnchanged,
log));
try {
await iter.next('not-a-JSReceiver');
assertUnreachable('Expected `iter.next(\'not-a-JSReceiver\')` to ' +
'throw, but did not throw')
} catch (e) {
assertEquals(e.constructor, TypeError);
}
assertEquals([
{
method: 'next',
sent: 'not-a-JSReceiver',
value: 'sync-value',
done: false
}
], log);
// If [sync_iterator] does not have a .return() method, return a Promise
// resolved with the value `{ value: <<sent value>>, done: true }`.
log = [];
iter = %CreateAsyncFromSyncIterator(sync(['sync-return'], kNext, log));
assertEquals({
value: 'd',
done: true
}, await iter.return('d'));
// [Async-from-Sync Iterator] merely delegates, and does not keep track of
// whether [sync_iterator] is completed or not.
assertEquals({
value: 'sync-return',
done: false
}, await iter.next('e'));
assertEquals([
{
method: 'next',
sent: 'e',
value: 'sync-return',
done: false
}
], log);
// If [sync_iterator] does have a .return() method, return a Promise
// fulfilled with the iterator result of [sync_iterator].return().
log = [];
iter = %CreateAsyncFromSyncIterator(sync(['sync-return'],
kNext|kReturn, log));
assertEquals({
value: 'f',
done: true
}, await iter.return('f'));
// [Async-from-Sync Iterator] merely delegates, and does not keep track of
// whether [sync_iterator] is completed or not.
assertEquals({
value: 'sync-return',
done: false
}, await iter.next('g'));
assertEquals([
{
method: 'return',
sent: 'f',
done: true
},
{
method: 'next',
sent: 'g',
value: 'sync-return',
done: false
}
], log);
// If [sync_iterator].return() produces a rejected Promise or an exception is
// thrown, Promise is rejected with thrown/rejected value.
log = [];
iter = %CreateAsyncFromSyncIterator(sync(['sync-value'], kNext|kReturnThrows,
log));
try {
await iter.return('Boo!!');
assertUnreachable('Expected `iter.return(\'Boo!!\')` to throw, but did ' +
'not throw');
} catch (e) {
assertEquals("Boo!!", e);
}
// [Async-from-Sync Iterator] merely delegates, and does not keep track of
// whether [sync_iterator] is completed or not.
assertEquals({ value: 'sync-value', done: false }, await iter.next('h'));
assertEquals([
{
method: 'return',
sent: 'Boo!!',
done: true
},
{
method: 'next',
sent: 'h',
value: 'sync-value',
done: false
}
], log);
log = [];
iter = %CreateAsyncFromSyncIterator(sync(['sync-value'], kNext|kReturn, log));
let rejection = Promise.reject('Boo!!');
try {
await iter.return(rejection);
assertUnreachable('Expected `iter.return(Promise.reject(\'Boo!!\'))` to ' +
'throw, but did not throw');
} catch (e) {
assertEquals('Boo!!', e);
}
// [Async-from-Sync Iterator] merely delegates, and does not keep track of
// whether [sync_iterator] is completed or not.
assertEquals({ value: 'sync-value', done: false }, await iter.next('i'));
assertEquals([
{
method: 'return',
sent: rejection,
done: true
},
{
method: 'next',
sent: 'i',
value: 'sync-value',
done: false
}
], log);
// [Async-from-Sync Iterator].return() will be rejected with a TypeError if
// Type([sync_iterator].return()) is not Object.
log = [];
iter = %CreateAsyncFromSyncIterator(sync(['sync-value'],
kNext|kReturnUnchanged, log));
try {
await iter.return('not-a-JSReceiver');
assertUnreachable('Expected `iter.return(\'not-a-JSReceiver\')` to ' +
'throw, but did not throw')
} catch (e) {
assertEquals(e.constructor, TypeError);
}
// [Async-from-Sync Iterator] merely delegates, and does not keep track of
// whether [sync_iterator] is completed or not.
assertEquals({ value: 'sync-value', done: false }, await iter.next('j'));
assertEquals([
{
method: 'return',
sent: 'not-a-JSReceiver',
done: true
},
{
method: 'next',
sent: 'j',
value: 'sync-value',
done: false
}
], log);
// If [sync_iterator] does not have a .throw method, return a Promise rejected
// with the sent value.
log = [];
iter = %CreateAsyncFromSyncIterator(sync(['sync-value'], kNext, log));
try {
await iter.throw('Boo!!');
assertUnreachable('Expected iter.throw(\'Boo!!\') to throw, but did not ' +
'throw');
} catch (e) {
assertEquals('Boo!!', e);
}
// [Async-from-Sync Iterator] merely delegates, and does not keep track of
// whether [sync_iterator] is completed or not.
assertEquals({ value: 'sync-value', done: false }, await iter.next('k'));
assertEquals([
{
method: 'next',
sent: 'k',
value: 'sync-value',
done: false
}
], log);
log = [];
iter = %CreateAsyncFromSyncIterator(sync(['sync-value'], kNext|kThrow, log));
try {
await iter.throw('Boo!!');
assertUnreachable('Expected iter.throw(\'Boo!!\') to throw, but did not ' +
'throw');
} catch (e) {
assertEquals('Boo!!', e);
}
// [Async-from-Sync Iterator] merely delegates, and does not keep track of
// whether [sync_iterator] is completed or not.
assertEquals({ value: 'sync-value', done: false }, await iter.next('l'));
assertEquals([
{
method: 'throw',
sent: 'Boo!!',
done: false
},
{
method: 'next',
sent: 'l',
value: 'sync-value',
done: false
}
], log);
// If [sync_iterator].throw() returns a resolved Promise or a Completion
// with [[Type]] "normal" or "return", return a resolved Promise
log = [];
iter = %CreateAsyncFromSyncIterator(sync(['sync-value'], kNext|kThrowNormal,
log));
assertEquals({
value: 'Boo!!',
done: false
}, await iter.throw('Boo!!'));
// [Async-from-Sync Iterator] merely delegates, and does not keep track of
// whether [sync_iterator] is completed or not.
assertEquals({ value: 'sync-value', done: false }, await iter.next('m'));
assertEquals([
{
method: 'throw',
sent: 'Boo!!',
done: false
},
{
method: 'next',
sent: 'm',
value: 'sync-value',
done: false
}
], log);
// [Async-from-Sync Iterator].throw() will be rejected with a TypeError if
// Type([sync_iterator].throw()) is not Object.
log = [];
iter = %CreateAsyncFromSyncIterator(sync(['sync-value'],
kNext|kThrowUnchanged, log));
try {
await iter.throw('not-a-JSReceiver');
assertUnreachable('Expected `iter.throw(\'not-a-JSReceiver\')` to ' +
'throw, but did not throw')
} catch (e) {
assertEquals(e.constructor, TypeError);
}
// [Async-from-Sync Iterator] merely delegates, and does not keep track of
// whether [sync_iterator] is completed or not.
assertEquals({ value: 'sync-value', done: false }, await iter.next('n'));
assertEquals([
{
method: 'throw',
sent: 'not-a-JSReceiver',
done: false
},
{
method: 'next',
sent: 'n',
value: 'sync-value',
done: false
}
], log);
// Let nextValue be IteratorValue(nextResult).
// IfAbruptRejectPromise(nextValue, promiseCapability).)
iter = %CreateAsyncFromSyncIterator({
next() { return { get value() { throw "BadValue!" }, done: false }; }
});
try {
await iter.next();
assertUnreachable('Expected `iter.next()` to throw, but did not throw');
} catch (e) {
assertEquals('BadValue!', e);
}
// Let nextDone be IteratorComplete(nextResult).
// IfAbruptRejectPromise(nextDone, promiseCapability).
iter = %CreateAsyncFromSyncIterator({
next() { return { value: undefined, get done() { throw "BadValue!" } }; }
});
try {
await iter.next();
assertUnreachable('Expected `iter.next()` to throw, but did not throw');
} catch (e) {
assertEquals('BadValue!', e);
}
// IfAbruptRejectPromise(returnResult, promiseCapability).
// Let returnValue be IteratorValue(returnResult).
iter = %CreateAsyncFromSyncIterator({
return() { return { get value() { throw "BadValue!" }, done: false }; }
});
try {
await iter.return();
assertUnreachable('Expected `iter.return()` to throw, but did not throw');
} catch (e) {
assertEquals('BadValue!', e);
}
// IfAbruptRejectPromise(returnValue, promiseCapability).
// Let returnDone be IteratorComplete(returnResult).
iter = %CreateAsyncFromSyncIterator({
return() { return { value: undefined, get done() { throw "BadValue!" } }; }
});
try {
await iter.return();
assertUnreachable('Expected `iter.return()` to throw, but did not throw');
} catch (e) {
assertEquals('BadValue!', e);
}
// IfAbruptRejectPromise(throwResult, promiseCapability).
// Let throwValue be IteratorValue(throwResult).
iter = %CreateAsyncFromSyncIterator({
throw() { return { get value() { throw "BadValue!" }, done: false }; }
});
try {
await iter.throw();
assertUnreachable('Expected `iter.throw()` to throw, but did not throw');
} catch (e) {
assertEquals('BadValue!', e);
}
// IfAbruptRejectPromise(throwValue, promiseCapability).
// Let throwDone be IteratorComplete(throwResult).
iter = %CreateAsyncFromSyncIterator({
throw() { return { value: undefined, get done() { throw "BadValue!" } }; }
});
try {
await iter.throw();
assertUnreachable('Expected `iter.throw()` to throw, but did not throw');
} catch (e) {
assertEquals('BadValue!', e);
}
})().catch(function(error) {
testFailed = true;
testFailure = error;
});
%RunMicrotasks();
if (testFailed) {
throw testFailure;
}
(function ExtractedAsyncFromSyncIteratorMethods() {
// Async-from-Sync iterator methods can be extracted via function.caller.
// TODO(caitp): test extracted `throw` method using yield* in async generator.
let extractor = [0, 1, 2, 3, 4,5,6,7,8,9];
let extractedNext;
let extractedReturn;
extractor[Symbol.iterator] = function() {
let it = [][Symbol.iterator].call(extractor);
let origNext = it.next, origThrow = it.throw, origReturn = it.return;
function extractNext() {
extractedNext = extractNext.caller;
return origNext;
}
function extractReturn() {
extractedReturn = extractReturn.caller;
return origReturn;
}
Object.defineProperties(it, {
"next": { get: extractNext, configurable: true },
"return": { get: extractReturn, configurable: true }
});
return it;
};
async function f() {
let i;
let it = extractor[Symbol.iterator]();
for await (let x of it) break;
for await (let x of it) return "x";
}
// Cycle through `f` to extract iterator methods
f().catch(function() { %AbortJS("No error should have occurred"); });
%RunMicrotasks();
assertEquals(typeof extractedNext, "function");
assertThrowsAsync(() => extractedNext.call(undefined), TypeError);
assertThrowsAsync(() => extractedNext.call(1), TypeError);
assertEquals(typeof extractedReturn, "function");
assertThrowsAsync(() => extractedReturn.call(undefined), TypeError);
assertThrowsAsync(() => extractedReturn.call(1), TypeError);
})();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment