[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:
parent
6b4850484f
commit
e35039e773
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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) \
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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';
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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) \
|
||||
|
@ -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) \
|
||||
|
@ -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:
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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) \
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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.
|
||||
}
|
||||
|
||||
|
@ -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));
|
||||
})();
|
||||
|
@ -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"),
|
||||
|
Loading…
Reference in New Issue
Block a user