[wasm][stack-switching] Support rejected promises

If the returned promise rejects, we switch to the suspender's stack and
throw the value.
Re-purpose the WasmOnFulfilled data to also represent the rejecting
case and rename it to WasmResumeData.

R=ahaas@chromium.org
CC=fgm@chromium.org

Bug: v8:12191
Change-Id: I91a301c3c6d9d243efbfabe7263555e11f0d9277
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3706606
Reviewed-by: Omer Katz <omerkatz@chromium.org>
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Reviewed-by: Andreas Haas <ahaas@chromium.org>
Commit-Queue: Thibaud Michaud <thibaudm@chromium.org>
Cr-Commit-Position: refs/heads/main@{#81325}
This commit is contained in:
Thibaud Michaud 2022-06-21 16:52:09 +02:00 committed by V8 LUCI CQ
parent 6b4850484f
commit e35039e773
27 changed files with 150 additions and 59 deletions

View File

@ -2784,6 +2784,11 @@ void Builtins::Generate_WasmResume(MacroAssembler* masm) {
__ Trap();
}
void Builtins::Generate_WasmReject(MacroAssembler* masm) {
// TODO(v8:12191): Implement for this platform.
__ Trap();
}
void Builtins::Generate_WasmOnStackReplace(MacroAssembler* masm) {
// Only needed on x64.
__ Trap();

View File

@ -3175,6 +3175,11 @@ void Builtins::Generate_WasmResume(MacroAssembler* masm) {
__ Trap();
}
void Builtins::Generate_WasmReject(MacroAssembler* masm) {
// TODO(v8:12191): Implement for this platform.
__ Trap();
}
void Builtins::Generate_WasmOnStackReplace(MacroAssembler* masm) {
// Only needed on x64.
__ Trap();

View File

@ -966,6 +966,7 @@ namespace internal {
IF_WASM(ASM, WasmReturnPromiseOnSuspend, WasmDummy) \
IF_WASM(ASM, WasmSuspend, WasmSuspend) \
IF_WASM(ASM, WasmResume, WasmDummy) \
IF_WASM(ASM, WasmReject, WasmDummy) \
IF_WASM(ASM, WasmCompileLazy, WasmDummy) \
IF_WASM(ASM, WasmDebugBreak, WasmDummy) \
IF_WASM(ASM, WasmOnStackReplace, WasmDummy) \

View File

@ -3032,6 +3032,11 @@ void Builtins::Generate_WasmResume(MacroAssembler* masm) {
__ Trap();
}
void Builtins::Generate_WasmReject(MacroAssembler* masm) {
// TODO(v8:12191): Implement for this platform.
__ Trap();
}
void Builtins::Generate_WasmOnStackReplace(MacroAssembler* masm) {
// Only needed on x64.
__ Trap();

View File

@ -4116,8 +4116,12 @@ void Builtins::Generate_WasmSuspend(MacroAssembler* masm) {
__ ret(0);
}
// Resume the suspender stored in the closure.
void Builtins::Generate_WasmResume(MacroAssembler* masm) {
namespace {
// Resume the suspender stored in the closure. We generate two variants of this
// builtin: the onFulfilled variant resumes execution at the saved PC and
// forwards the value, the onRejected variant throws the value.
void Generate_WasmResumeHelper(MacroAssembler* masm, wasm::OnResume on_resume) {
__ EnterFrame(StackFrame::STACK_SWITCH);
Register param_count = rax;
@ -4152,8 +4156,7 @@ void Builtins::Generate_WasmResume(MacroAssembler* masm) {
FieldOperand(sfi, SharedFunctionInfo::kFunctionDataOffset));
Register suspender = rax;
__ LoadAnyTaggedField(
suspender,
FieldOperand(function_data, WasmOnFulfilledData::kSuspenderOffset));
suspender, FieldOperand(function_data, WasmResumeData::kSuspenderOffset));
// Check the suspender state.
Label suspender_is_suspended;
Register state = rdx;
@ -4232,12 +4235,30 @@ void Builtins::Generate_WasmResume(MacroAssembler* masm) {
// Move resolved value to return register.
__ movq(kReturnRegister0, Operand(rbp, 3 * kSystemPointerSize));
__ Move(GCScanSlotPlace, 0);
LoadJumpBuffer(masm, target_jmpbuf, true);
if (on_resume == wasm::OnResume::kThrow) {
// Switch to the continuation's stack without restoring the PC.
LoadJumpBuffer(masm, target_jmpbuf, false);
// Forward the onRejected value to kThrow.
__ pushq(kReturnRegister0);
__ CallRuntime(Runtime::kThrow);
} else {
// Resume the continuation normally.
LoadJumpBuffer(masm, target_jmpbuf, true);
}
__ Trap();
__ bind(&suspend);
__ LeaveFrame(StackFrame::STACK_SWITCH);
__ ret(3);
}
} // namespace
void Builtins::Generate_WasmResume(MacroAssembler* masm) {
Generate_WasmResumeHelper(masm, wasm::OnResume::kContinue);
}
void Builtins::Generate_WasmReject(MacroAssembler* masm) {
Generate_WasmResumeHelper(masm, wasm::OnResume::kThrow);
}
void Builtins::Generate_WasmOnStackReplace(MacroAssembler* masm) {
MemOperand OSRTargetSlot(rbp, -wasm::kOSRTargetOffset);

View File

@ -14740,7 +14740,7 @@ TNode<CodeT> CodeStubAssembler::GetSharedFunctionInfoCode(
WASM_EXPORTED_FUNCTION_DATA_TYPE,
WASM_JS_FUNCTION_DATA_TYPE,
ASM_WASM_DATA_TYPE,
WASM_ON_FULFILLED_DATA_TYPE,
WASM_RESUME_DATA_TYPE,
#endif // V8_ENABLE_WEBASSEMBLY
};
Label check_is_bytecode_array(this);
@ -14750,7 +14750,7 @@ TNode<CodeT> CodeStubAssembler::GetSharedFunctionInfoCode(
Label check_is_function_template_info(this);
Label check_is_interpreter_data(this);
Label check_is_wasm_function_data(this);
Label check_is_wasm_on_fulfilled(this);
Label check_is_wasm_resume(this);
Label* case_labels[] = {
&check_is_bytecode_array,
&check_is_baseline_data,
@ -14764,7 +14764,7 @@ TNode<CodeT> CodeStubAssembler::GetSharedFunctionInfoCode(
&check_is_wasm_function_data,
&check_is_wasm_function_data,
&check_is_asm_wasm_data,
&check_is_wasm_on_fulfilled,
&check_is_wasm_resume,
#endif // V8_ENABLE_WEBASSEMBLY
};
static_assert(arraysize(case_values) == arraysize(case_labels));
@ -14819,8 +14819,8 @@ TNode<CodeT> CodeStubAssembler::GetSharedFunctionInfoCode(
sfi_code = HeapConstant(BUILTIN_CODE(isolate(), InstantiateAsmJs));
Goto(&done);
// IsWasmOnFulfilledData: Resume the suspended wasm continuation.
BIND(&check_is_wasm_on_fulfilled);
// IsWasmResumeData: Resume the suspended wasm continuation.
BIND(&check_is_wasm_resume);
sfi_code = HeapConstant(BUILTIN_CODE(isolate(), WasmResume));
Goto(&done);
#endif // V8_ENABLE_WEBASSEMBLY

View File

@ -950,7 +950,7 @@ void SharedFunctionInfo::SharedFunctionInfoVerify(ReadOnlyRoots roots) {
#if V8_ENABLE_WEBASSEMBLY
bool is_wasm = HasWasmExportedFunctionData() || HasAsmWasmData() ||
HasWasmJSFunctionData() || HasWasmCapiFunctionData() ||
HasWasmOnFulfilledData();
HasWasmResumeData();
#else
bool is_wasm = false;
#endif // V8_ENABLE_WEBASSEMBLY

View File

@ -2053,8 +2053,8 @@ void WasmJSFunctionData::WasmJSFunctionDataPrint(std::ostream& os) {
os << "\n";
}
void WasmOnFulfilledData::WasmOnFulfilledDataPrint(std::ostream& os) {
PrintHeader(os, "WasmOnFulfilledData");
void WasmResumeData::WasmResumeDataPrint(std::ostream& os) {
PrintHeader(os, "WasmResumeData");
os << "\n - suspender: " << Brief(suspender());
os << '\n';
}

View File

@ -1600,14 +1600,14 @@ Handle<WasmJSFunctionData> Factory::NewWasmJSFunctionData(
return handle(result, isolate());
}
Handle<WasmOnFulfilledData> Factory::NewWasmOnFulfilledData(
Handle<WasmSuspenderObject> suspender) {
Map map = *wasm_onfulfilled_data_map();
WasmOnFulfilledData result =
WasmOnFulfilledData::cast(AllocateRawWithImmortalMap(
map.instance_size(), AllocationType::kOld, map));
Handle<WasmResumeData> Factory::NewWasmResumeData(
Handle<WasmSuspenderObject> suspender, wasm::OnResume on_resume) {
Map map = *wasm_resume_data_map();
WasmResumeData result = WasmResumeData::cast(AllocateRawWithImmortalMap(
map.instance_size(), AllocationType::kOld, map));
DisallowGarbageCollection no_gc;
result.set_suspender(*suspender);
result.set_on_resume(static_cast<int>(on_resume));
return handle(result, isolate());
}
@ -1776,8 +1776,8 @@ Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfoForWasmJSFunction(
return NewSharedFunctionInfo(name, data, Builtin::kNoBuiltinId);
}
Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfoForWasmOnFulfilled(
Handle<WasmOnFulfilledData> data) {
Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfoForWasmResume(
Handle<WasmResumeData> data) {
return NewSharedFunctionInfo({}, data, Builtin::kNoBuiltinId);
}

View File

@ -78,6 +78,7 @@ class ArrayType;
class StructType;
struct WasmElemSegment;
class WasmValue;
enum class OnResume : int;
} // namespace wasm
#endif
@ -638,8 +639,8 @@ class V8_EXPORT_PRIVATE Factory : public FactoryBase<Factory> {
int parameter_count, Handle<PodArray<wasm::ValueType>> serialized_sig,
Handle<CodeT> wrapper_code, Handle<Map> rtt,
Handle<HeapObject> suspender);
Handle<WasmOnFulfilledData> NewWasmOnFulfilledData(
Handle<WasmSuspenderObject> suspender);
Handle<WasmResumeData> NewWasmResumeData(
Handle<WasmSuspenderObject> suspender, wasm::OnResume on_resume);
Handle<WasmStruct> NewWasmStruct(const wasm::StructType* type,
wasm::WasmValue* args, Handle<Map> map);
Handle<WasmArray> NewWasmArrayFromElements(
@ -657,8 +658,8 @@ class V8_EXPORT_PRIVATE Factory : public FactoryBase<Factory> {
Handle<String> name, Handle<WasmExportedFunctionData> data);
Handle<SharedFunctionInfo> NewSharedFunctionInfoForWasmJSFunction(
Handle<String> name, Handle<WasmJSFunctionData> data);
Handle<SharedFunctionInfo> NewSharedFunctionInfoForWasmOnFulfilled(
Handle<WasmOnFulfilledData> data);
Handle<SharedFunctionInfo> NewSharedFunctionInfoForWasmResume(
Handle<WasmResumeData> data);
Handle<SharedFunctionInfo> NewSharedFunctionInfoForWasmCapiFunction(
Handle<WasmCapiFunctionData> data);
#endif // V8_ENABLE_WEBASSEMBLY

View File

@ -67,7 +67,7 @@ namespace internal {
IF_WASM(V, WasmJSFunctionData) \
IF_WASM(V, WasmStruct) \
IF_WASM(V, WasmSuspenderObject) \
IF_WASM(V, WasmOnFulfilledData) \
IF_WASM(V, WasmResumeData) \
IF_WASM(V, WasmTypeInfo)
#define FORWARD_DECLARE(TypeName) class TypeName;

View File

@ -517,8 +517,8 @@ bool Heap::CreateInitialMaps() {
WasmInternalFunction::kSize, wasm_internal_function)
IF_WASM(ALLOCATE_MAP, WASM_JS_FUNCTION_DATA_TYPE, WasmJSFunctionData::kSize,
wasm_js_function_data)
IF_WASM(ALLOCATE_MAP, WASM_ON_FULFILLED_DATA_TYPE,
WasmOnFulfilledData::kSize, wasm_onfulfilled_data)
IF_WASM(ALLOCATE_MAP, WASM_RESUME_DATA_TYPE, WasmResumeData::kSize,
wasm_resume_data)
IF_WASM(ALLOCATE_MAP, WASM_TYPE_INFO_TYPE, kVariableSizeSentinel,
wasm_type_info)

View File

@ -393,8 +393,8 @@ VisitorId Map::GetVisitorId(Map map) {
return kVisitWasmInternalFunction;
case WASM_JS_FUNCTION_DATA_TYPE:
return kVisitWasmJSFunctionData;
case WASM_ON_FULFILLED_DATA_TYPE:
return kVisitWasmOnFulfilledData;
case WASM_RESUME_DATA_TYPE:
return kVisitWasmResumeData;
case WASM_API_FUNCTION_REF_TYPE:
return kVisitWasmApiFunctionRef;
case WASM_EXPORTED_FUNCTION_DATA_TYPE:

View File

@ -83,7 +83,7 @@ enum InstanceType : uint16_t;
IF_WASM(V, WasmInstanceObject) \
IF_WASM(V, WasmInternalFunction) \
IF_WASM(V, WasmJSFunctionData) \
IF_WASM(V, WasmOnFulfilledData) \
IF_WASM(V, WasmResumeData) \
IF_WASM(V, WasmStruct) \
IF_WASM(V, WasmSuspenderObject) \
IF_WASM(V, WasmTypeInfo) \

View File

@ -258,7 +258,7 @@ class ZoneForwardList;
IF_WASM(V, WasmMemoryObject) \
IF_WASM(V, WasmModuleObject) \
IF_WASM(V, WasmObject) \
IF_WASM(V, WasmOnFulfilledData) \
IF_WASM(V, WasmResumeData) \
IF_WASM(V, WasmStruct) \
IF_WASM(V, WasmTypeInfo) \
IF_WASM(V, WasmTableObject) \

View File

@ -1172,8 +1172,8 @@ auto BodyDescriptorApply(InstanceType type, Args&&... args) {
return CALL_APPLY(WasmInternalFunction);
case WASM_JS_FUNCTION_DATA_TYPE:
return CALL_APPLY(WasmJSFunctionData);
case WASM_ON_FULFILLED_DATA_TYPE:
return CALL_APPLY(WasmOnFulfilledData);
case WASM_RESUME_DATA_TYPE:
return CALL_APPLY(WasmResumeData);
case WASM_STRUCT_TYPE:
return CALL_APPLY(WasmStruct);
case WASM_TYPE_INFO_TYPE:

View File

@ -711,8 +711,8 @@ bool SharedFunctionInfo::HasWasmCapiFunctionData() const {
return function_data(kAcquireLoad).IsWasmCapiFunctionData();
}
bool SharedFunctionInfo::HasWasmOnFulfilledData() const {
return function_data(kAcquireLoad).IsWasmOnFulfilledData();
bool SharedFunctionInfo::HasWasmResumeData() const {
return function_data(kAcquireLoad).IsWasmResumeData();
}
AsmWasmData SharedFunctionInfo::asm_wasm_data() const {

View File

@ -108,8 +108,13 @@ CodeT SharedFunctionInfo::GetCode() const {
if (data.IsWasmCapiFunctionData()) {
return wasm_capi_function_data().wrapper_code();
}
if (data.IsWasmOnFulfilledData()) {
return isolate->builtins()->code(Builtin::kWasmResume);
if (data.IsWasmResumeData()) {
if (static_cast<wasm::OnResume>(wasm_resume_data().on_resume()) ==
wasm::OnResume::kContinue) {
return isolate->builtins()->code(Builtin::kWasmResume);
} else {
return isolate->builtins()->code(Builtin::kWasmReject);
}
}
#endif // V8_ENABLE_WEBASSEMBLY
if (data.IsUncompiledData()) {
@ -147,6 +152,11 @@ WasmCapiFunctionData SharedFunctionInfo::wasm_capi_function_data() const {
DCHECK(HasWasmCapiFunctionData());
return WasmCapiFunctionData::cast(function_data(kAcquireLoad));
}
WasmResumeData SharedFunctionInfo::wasm_resume_data() const {
DCHECK(HasWasmResumeData());
return WasmResumeData::cast(function_data(kAcquireLoad));
}
#endif // V8_ENABLE_WEBASSEMBLY
SharedFunctionInfo::ScriptIterator::ScriptIterator(Isolate* isolate,

View File

@ -40,6 +40,7 @@ class Signature;
class WasmCapiFunctionData;
class WasmExportedFunctionData;
class WasmJSFunctionData;
class WasmResumeData;
namespace wasm {
struct WasmModule;
@ -347,7 +348,7 @@ class SharedFunctionInfo
inline bool HasWasmExportedFunctionData() const;
inline bool HasWasmJSFunctionData() const;
inline bool HasWasmCapiFunctionData() const;
inline bool HasWasmOnFulfilledData() const;
inline bool HasWasmResumeData() const;
inline AsmWasmData asm_wasm_data() const;
inline void set_asm_wasm_data(AsmWasmData data);
@ -355,6 +356,7 @@ class SharedFunctionInfo
wasm_exported_function_data() const;
WasmJSFunctionData wasm_js_function_data() const;
WasmCapiFunctionData wasm_capi_function_data() const;
WasmResumeData wasm_resume_data() const;
inline const wasm::WasmModule* wasm_module() const;
inline const wasm::FunctionSig* wasm_function_signature() const;

View File

@ -120,7 +120,7 @@ class Symbol;
WasmExportedFunctionDataMap) \
IF_WASM(V, Map, wasm_internal_function_map, WasmInternalFunctionMap) \
IF_WASM(V, Map, wasm_js_function_data_map, WasmJSFunctionDataMap) \
IF_WASM(V, Map, wasm_onfulfilled_data_map, WasmOnFulfilledDataMap) \
IF_WASM(V, Map, wasm_resume_data_map, WasmResumeDataMap) \
IF_WASM(V, Map, wasm_type_info_map, WasmTypeInfoMap) \
V(Map, weak_fixed_array_map, WeakFixedArrayMap) \
V(Map, weak_array_list_map, WeakArrayListMap) \

View File

@ -832,15 +832,16 @@ RUNTIME_FUNCTION(Runtime_WasmSyncStackLimit) {
return ReadOnlyRoots(isolate).undefined_value();
}
// Takes a promise and a suspender, and returns promise.then(onFulfilled), where
// onFulfilled resumes the suspender.
// Takes a promise and a suspender, and returns
// promise.then(suspender.resume(), suspender.reject());
RUNTIME_FUNCTION(Runtime_WasmCreateResumePromise) {
CHECK(FLAG_experimental_wasm_stack_switching);
HandleScope scope(isolate);
Handle<Object> promise = args.at(0);
Handle<WasmSuspenderObject> suspender = args.at<WasmSuspenderObject>(1);
i::Handle<i::Object> argv[] = {handle(suspender->resume(), isolate)};
i::Handle<i::Object> argv[] = {handle(suspender->resume(), isolate),
handle(suspender->reject(), isolate)};
i::Handle<i::Object> result;
bool has_pending_exception =
!i::Execution::CallBuiltin(isolate, isolate->promise_then(), promise,

View File

@ -55,7 +55,7 @@ TQ_OBJECT_CONSTRUCTORS_IMPL(WasmStruct)
TQ_OBJECT_CONSTRUCTORS_IMPL(WasmArray)
TQ_OBJECT_CONSTRUCTORS_IMPL(WasmContinuationObject)
TQ_OBJECT_CONSTRUCTORS_IMPL(WasmSuspenderObject)
TQ_OBJECT_CONSTRUCTORS_IMPL(WasmOnFulfilledData)
TQ_OBJECT_CONSTRUCTORS_IMPL(WasmResumeData)
CAST_ACCESSOR(WasmInstanceObject)

View File

@ -1807,15 +1807,22 @@ Handle<WasmSuspenderObject> WasmSuspenderObject::New(Isolate* isolate) {
suspender->set_state(kInactive);
// Instantiate the callable object which resumes this Suspender. This will be
// used implicitly as the onFulfilled callback of the returned JS promise.
Handle<WasmOnFulfilledData> function_data =
isolate->factory()->NewWasmOnFulfilledData(suspender);
Handle<SharedFunctionInfo> shared =
isolate->factory()->NewSharedFunctionInfoForWasmOnFulfilled(
function_data);
Handle<WasmResumeData> resume_data = isolate->factory()->NewWasmResumeData(
suspender, wasm::OnResume::kContinue);
Handle<SharedFunctionInfo> resume_sfi =
isolate->factory()->NewSharedFunctionInfoForWasmResume(resume_data);
Handle<Context> context(isolate->native_context());
Handle<JSObject> resume =
Factory::JSFunctionBuilder{isolate, shared, context}.Build();
Factory::JSFunctionBuilder{isolate, resume_sfi, context}.Build();
Handle<WasmResumeData> reject_data =
isolate->factory()->NewWasmResumeData(suspender, wasm::OnResume::kThrow);
Handle<SharedFunctionInfo> reject_sfi =
isolate->factory()->NewSharedFunctionInfoForWasmResume(reject_data);
Handle<JSObject> reject =
Factory::JSFunctionBuilder{isolate, reject_sfi, context}.Build();
suspender->set_resume(*resume);
suspender->set_reject(*reject);
return suspender;
}

View File

@ -787,14 +787,17 @@ class WasmCapiFunctionData
TQ_OBJECT_CONSTRUCTORS(WasmCapiFunctionData)
};
class WasmOnFulfilledData
: public TorqueGeneratedWasmOnFulfilledData<WasmOnFulfilledData,
HeapObject> {
namespace wasm {
enum class OnResume : int { kContinue, kThrow };
}
class WasmResumeData
: public TorqueGeneratedWasmResumeData<WasmResumeData, HeapObject> {
public:
using BodyDescriptor =
FlexibleBodyDescriptor<WasmOnFulfilledData::kStartOfStrongFieldsOffset>;
DECL_PRINTER(WasmOnFulfilledData)
TQ_OBJECT_CONSTRUCTORS(WasmOnFulfilledData)
FlexibleBodyDescriptor<WasmResumeData::kStartOfStrongFieldsOffset>;
DECL_PRINTER(WasmResumeData)
TQ_OBJECT_CONSTRUCTORS(WasmResumeData)
};
class WasmScript : public AllStatic {

View File

@ -80,8 +80,9 @@ extern class WasmCapiFunctionData extends WasmFunctionData {
serialized_signature: PodArrayOfWasmValueType;
}
extern class WasmOnFulfilledData extends HeapObject {
extern class WasmResumeData extends HeapObject {
suspender: WasmSuspenderObject;
on_resume: Smi; // See wasm::OnResume enum.
}
extern class WasmIndirectFunctionTable extends Struct {
@ -104,6 +105,7 @@ extern class WasmSuspenderObject extends JSObject {
continuation: WasmContinuationObject|Undefined;
parent: WasmSuspenderObject|Undefined;
resume: JSObject|Undefined;
reject: JSObject|Undefined;
state: Smi; // 0: Inactive, 1: Active, 2: Suspended.
}

View File

@ -295,3 +295,31 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
let combined_promise = wrapped_export();
assertThrowsAsync(combined_promise, WebAssembly.Exception);
})();
(function TestStackSwitchPromiseReject() {
print(arguments.callee.name);
let tag = new WebAssembly.Tag({parameters: ['i32']});
let builder = new WasmModuleBuilder();
import_index = builder.addImport('m', 'import', kSig_i_v);
tag_index = builder.addImportedTag('m', 'tag', kSig_v_i);
builder.addFunction("test", kSig_i_v)
.addBody([
kExprTry, kWasmI32,
kExprCallFunction, import_index,
kExprCatch, tag_index,
kExprEnd,
]).exportFunc();
let suspender = new WebAssembly.Suspender();
function js_import() {
return Promise.reject(new WebAssembly.Exception(tag, [42]));
};
let wasm_js_import = new WebAssembly.Function(
{parameters: [], results: ['externref']}, js_import);
let suspending_wasm_js_import =
suspender.suspendOnReturnedPromise(wasm_js_import);
let instance = builder.instantiate({m: {import: suspending_wasm_js_import, tag: tag}});
let wrapped_export = suspender.returnPromiseOnSuspend(instance.exports.test);
let combined_promise = wrapped_export();
assertPromiseResult(combined_promise, v => assertEquals(v, 42));
})();

View File

@ -167,7 +167,7 @@ INSTANCE_TYPES = {
260: "SORT_STATE_TYPE",
261: "SWISS_NAME_DICTIONARY_TYPE",
262: "WASM_API_FUNCTION_REF_TYPE",
263: "WASM_ON_FULFILLED_DATA_TYPE",
263: "WASM_RESUME_DATA_TYPE",
264: "WEAK_ARRAY_LIST_TYPE",
265: "WEAK_CELL_TYPE",
266: "WASM_ARRAY_TYPE",
@ -353,7 +353,7 @@ KNOWN_MAPS = {
("read_only_space", 0x02f51): (223, "WasmExportedFunctionDataMap"),
("read_only_space", 0x02f79): (205, "WasmInternalFunctionMap"),
("read_only_space", 0x02fa1): (224, "WasmJSFunctionDataMap"),
("read_only_space", 0x02fc9): (263, "WasmOnFulfilledDataMap"),
("read_only_space", 0x02fc9): (263, "WasmResumeDataMap"),
("read_only_space", 0x02ff1): (206, "WasmTypeInfoMap"),
("read_only_space", 0x03019): (235, "WeakFixedArrayMap"),
("read_only_space", 0x03041): (179, "EphemeronHashTableMap"),