[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();
|
__ Trap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Builtins::Generate_WasmReject(MacroAssembler* masm) {
|
||||||
|
// TODO(v8:12191): Implement for this platform.
|
||||||
|
__ Trap();
|
||||||
|
}
|
||||||
|
|
||||||
void Builtins::Generate_WasmOnStackReplace(MacroAssembler* masm) {
|
void Builtins::Generate_WasmOnStackReplace(MacroAssembler* masm) {
|
||||||
// Only needed on x64.
|
// Only needed on x64.
|
||||||
__ Trap();
|
__ Trap();
|
||||||
|
@ -3175,6 +3175,11 @@ void Builtins::Generate_WasmResume(MacroAssembler* masm) {
|
|||||||
__ Trap();
|
__ Trap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Builtins::Generate_WasmReject(MacroAssembler* masm) {
|
||||||
|
// TODO(v8:12191): Implement for this platform.
|
||||||
|
__ Trap();
|
||||||
|
}
|
||||||
|
|
||||||
void Builtins::Generate_WasmOnStackReplace(MacroAssembler* masm) {
|
void Builtins::Generate_WasmOnStackReplace(MacroAssembler* masm) {
|
||||||
// Only needed on x64.
|
// Only needed on x64.
|
||||||
__ Trap();
|
__ Trap();
|
||||||
|
@ -966,6 +966,7 @@ namespace internal {
|
|||||||
IF_WASM(ASM, WasmReturnPromiseOnSuspend, WasmDummy) \
|
IF_WASM(ASM, WasmReturnPromiseOnSuspend, WasmDummy) \
|
||||||
IF_WASM(ASM, WasmSuspend, WasmSuspend) \
|
IF_WASM(ASM, WasmSuspend, WasmSuspend) \
|
||||||
IF_WASM(ASM, WasmResume, WasmDummy) \
|
IF_WASM(ASM, WasmResume, WasmDummy) \
|
||||||
|
IF_WASM(ASM, WasmReject, WasmDummy) \
|
||||||
IF_WASM(ASM, WasmCompileLazy, WasmDummy) \
|
IF_WASM(ASM, WasmCompileLazy, WasmDummy) \
|
||||||
IF_WASM(ASM, WasmDebugBreak, WasmDummy) \
|
IF_WASM(ASM, WasmDebugBreak, WasmDummy) \
|
||||||
IF_WASM(ASM, WasmOnStackReplace, WasmDummy) \
|
IF_WASM(ASM, WasmOnStackReplace, WasmDummy) \
|
||||||
|
@ -3032,6 +3032,11 @@ void Builtins::Generate_WasmResume(MacroAssembler* masm) {
|
|||||||
__ Trap();
|
__ Trap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Builtins::Generate_WasmReject(MacroAssembler* masm) {
|
||||||
|
// TODO(v8:12191): Implement for this platform.
|
||||||
|
__ Trap();
|
||||||
|
}
|
||||||
|
|
||||||
void Builtins::Generate_WasmOnStackReplace(MacroAssembler* masm) {
|
void Builtins::Generate_WasmOnStackReplace(MacroAssembler* masm) {
|
||||||
// Only needed on x64.
|
// Only needed on x64.
|
||||||
__ Trap();
|
__ Trap();
|
||||||
|
@ -4116,8 +4116,12 @@ void Builtins::Generate_WasmSuspend(MacroAssembler* masm) {
|
|||||||
__ ret(0);
|
__ ret(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resume the suspender stored in the closure.
|
namespace {
|
||||||
void Builtins::Generate_WasmResume(MacroAssembler* masm) {
|
// 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);
|
__ EnterFrame(StackFrame::STACK_SWITCH);
|
||||||
|
|
||||||
Register param_count = rax;
|
Register param_count = rax;
|
||||||
@ -4152,8 +4156,7 @@ void Builtins::Generate_WasmResume(MacroAssembler* masm) {
|
|||||||
FieldOperand(sfi, SharedFunctionInfo::kFunctionDataOffset));
|
FieldOperand(sfi, SharedFunctionInfo::kFunctionDataOffset));
|
||||||
Register suspender = rax;
|
Register suspender = rax;
|
||||||
__ LoadAnyTaggedField(
|
__ LoadAnyTaggedField(
|
||||||
suspender,
|
suspender, FieldOperand(function_data, WasmResumeData::kSuspenderOffset));
|
||||||
FieldOperand(function_data, WasmOnFulfilledData::kSuspenderOffset));
|
|
||||||
// Check the suspender state.
|
// Check the suspender state.
|
||||||
Label suspender_is_suspended;
|
Label suspender_is_suspended;
|
||||||
Register state = rdx;
|
Register state = rdx;
|
||||||
@ -4232,12 +4235,30 @@ void Builtins::Generate_WasmResume(MacroAssembler* masm) {
|
|||||||
// Move resolved value to return register.
|
// Move resolved value to return register.
|
||||||
__ movq(kReturnRegister0, Operand(rbp, 3 * kSystemPointerSize));
|
__ movq(kReturnRegister0, Operand(rbp, 3 * kSystemPointerSize));
|
||||||
__ Move(GCScanSlotPlace, 0);
|
__ 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();
|
__ Trap();
|
||||||
__ bind(&suspend);
|
__ bind(&suspend);
|
||||||
__ LeaveFrame(StackFrame::STACK_SWITCH);
|
__ LeaveFrame(StackFrame::STACK_SWITCH);
|
||||||
__ ret(3);
|
__ 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) {
|
void Builtins::Generate_WasmOnStackReplace(MacroAssembler* masm) {
|
||||||
MemOperand OSRTargetSlot(rbp, -wasm::kOSRTargetOffset);
|
MemOperand OSRTargetSlot(rbp, -wasm::kOSRTargetOffset);
|
||||||
|
@ -14740,7 +14740,7 @@ TNode<CodeT> CodeStubAssembler::GetSharedFunctionInfoCode(
|
|||||||
WASM_EXPORTED_FUNCTION_DATA_TYPE,
|
WASM_EXPORTED_FUNCTION_DATA_TYPE,
|
||||||
WASM_JS_FUNCTION_DATA_TYPE,
|
WASM_JS_FUNCTION_DATA_TYPE,
|
||||||
ASM_WASM_DATA_TYPE,
|
ASM_WASM_DATA_TYPE,
|
||||||
WASM_ON_FULFILLED_DATA_TYPE,
|
WASM_RESUME_DATA_TYPE,
|
||||||
#endif // V8_ENABLE_WEBASSEMBLY
|
#endif // V8_ENABLE_WEBASSEMBLY
|
||||||
};
|
};
|
||||||
Label check_is_bytecode_array(this);
|
Label check_is_bytecode_array(this);
|
||||||
@ -14750,7 +14750,7 @@ TNode<CodeT> CodeStubAssembler::GetSharedFunctionInfoCode(
|
|||||||
Label check_is_function_template_info(this);
|
Label check_is_function_template_info(this);
|
||||||
Label check_is_interpreter_data(this);
|
Label check_is_interpreter_data(this);
|
||||||
Label check_is_wasm_function_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[] = {
|
Label* case_labels[] = {
|
||||||
&check_is_bytecode_array,
|
&check_is_bytecode_array,
|
||||||
&check_is_baseline_data,
|
&check_is_baseline_data,
|
||||||
@ -14764,7 +14764,7 @@ TNode<CodeT> CodeStubAssembler::GetSharedFunctionInfoCode(
|
|||||||
&check_is_wasm_function_data,
|
&check_is_wasm_function_data,
|
||||||
&check_is_wasm_function_data,
|
&check_is_wasm_function_data,
|
||||||
&check_is_asm_wasm_data,
|
&check_is_asm_wasm_data,
|
||||||
&check_is_wasm_on_fulfilled,
|
&check_is_wasm_resume,
|
||||||
#endif // V8_ENABLE_WEBASSEMBLY
|
#endif // V8_ENABLE_WEBASSEMBLY
|
||||||
};
|
};
|
||||||
static_assert(arraysize(case_values) == arraysize(case_labels));
|
static_assert(arraysize(case_values) == arraysize(case_labels));
|
||||||
@ -14819,8 +14819,8 @@ TNode<CodeT> CodeStubAssembler::GetSharedFunctionInfoCode(
|
|||||||
sfi_code = HeapConstant(BUILTIN_CODE(isolate(), InstantiateAsmJs));
|
sfi_code = HeapConstant(BUILTIN_CODE(isolate(), InstantiateAsmJs));
|
||||||
Goto(&done);
|
Goto(&done);
|
||||||
|
|
||||||
// IsWasmOnFulfilledData: Resume the suspended wasm continuation.
|
// IsWasmResumeData: Resume the suspended wasm continuation.
|
||||||
BIND(&check_is_wasm_on_fulfilled);
|
BIND(&check_is_wasm_resume);
|
||||||
sfi_code = HeapConstant(BUILTIN_CODE(isolate(), WasmResume));
|
sfi_code = HeapConstant(BUILTIN_CODE(isolate(), WasmResume));
|
||||||
Goto(&done);
|
Goto(&done);
|
||||||
#endif // V8_ENABLE_WEBASSEMBLY
|
#endif // V8_ENABLE_WEBASSEMBLY
|
||||||
|
@ -950,7 +950,7 @@ void SharedFunctionInfo::SharedFunctionInfoVerify(ReadOnlyRoots roots) {
|
|||||||
#if V8_ENABLE_WEBASSEMBLY
|
#if V8_ENABLE_WEBASSEMBLY
|
||||||
bool is_wasm = HasWasmExportedFunctionData() || HasAsmWasmData() ||
|
bool is_wasm = HasWasmExportedFunctionData() || HasAsmWasmData() ||
|
||||||
HasWasmJSFunctionData() || HasWasmCapiFunctionData() ||
|
HasWasmJSFunctionData() || HasWasmCapiFunctionData() ||
|
||||||
HasWasmOnFulfilledData();
|
HasWasmResumeData();
|
||||||
#else
|
#else
|
||||||
bool is_wasm = false;
|
bool is_wasm = false;
|
||||||
#endif // V8_ENABLE_WEBASSEMBLY
|
#endif // V8_ENABLE_WEBASSEMBLY
|
||||||
|
@ -2053,8 +2053,8 @@ void WasmJSFunctionData::WasmJSFunctionDataPrint(std::ostream& os) {
|
|||||||
os << "\n";
|
os << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void WasmOnFulfilledData::WasmOnFulfilledDataPrint(std::ostream& os) {
|
void WasmResumeData::WasmResumeDataPrint(std::ostream& os) {
|
||||||
PrintHeader(os, "WasmOnFulfilledData");
|
PrintHeader(os, "WasmResumeData");
|
||||||
os << "\n - suspender: " << Brief(suspender());
|
os << "\n - suspender: " << Brief(suspender());
|
||||||
os << '\n';
|
os << '\n';
|
||||||
}
|
}
|
||||||
|
@ -1600,14 +1600,14 @@ Handle<WasmJSFunctionData> Factory::NewWasmJSFunctionData(
|
|||||||
return handle(result, isolate());
|
return handle(result, isolate());
|
||||||
}
|
}
|
||||||
|
|
||||||
Handle<WasmOnFulfilledData> Factory::NewWasmOnFulfilledData(
|
Handle<WasmResumeData> Factory::NewWasmResumeData(
|
||||||
Handle<WasmSuspenderObject> suspender) {
|
Handle<WasmSuspenderObject> suspender, wasm::OnResume on_resume) {
|
||||||
Map map = *wasm_onfulfilled_data_map();
|
Map map = *wasm_resume_data_map();
|
||||||
WasmOnFulfilledData result =
|
WasmResumeData result = WasmResumeData::cast(AllocateRawWithImmortalMap(
|
||||||
WasmOnFulfilledData::cast(AllocateRawWithImmortalMap(
|
map.instance_size(), AllocationType::kOld, map));
|
||||||
map.instance_size(), AllocationType::kOld, map));
|
|
||||||
DisallowGarbageCollection no_gc;
|
DisallowGarbageCollection no_gc;
|
||||||
result.set_suspender(*suspender);
|
result.set_suspender(*suspender);
|
||||||
|
result.set_on_resume(static_cast<int>(on_resume));
|
||||||
return handle(result, isolate());
|
return handle(result, isolate());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1776,8 +1776,8 @@ Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfoForWasmJSFunction(
|
|||||||
return NewSharedFunctionInfo(name, data, Builtin::kNoBuiltinId);
|
return NewSharedFunctionInfo(name, data, Builtin::kNoBuiltinId);
|
||||||
}
|
}
|
||||||
|
|
||||||
Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfoForWasmOnFulfilled(
|
Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfoForWasmResume(
|
||||||
Handle<WasmOnFulfilledData> data) {
|
Handle<WasmResumeData> data) {
|
||||||
return NewSharedFunctionInfo({}, data, Builtin::kNoBuiltinId);
|
return NewSharedFunctionInfo({}, data, Builtin::kNoBuiltinId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,6 +78,7 @@ class ArrayType;
|
|||||||
class StructType;
|
class StructType;
|
||||||
struct WasmElemSegment;
|
struct WasmElemSegment;
|
||||||
class WasmValue;
|
class WasmValue;
|
||||||
|
enum class OnResume : int;
|
||||||
} // namespace wasm
|
} // namespace wasm
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -638,8 +639,8 @@ class V8_EXPORT_PRIVATE Factory : public FactoryBase<Factory> {
|
|||||||
int parameter_count, Handle<PodArray<wasm::ValueType>> serialized_sig,
|
int parameter_count, Handle<PodArray<wasm::ValueType>> serialized_sig,
|
||||||
Handle<CodeT> wrapper_code, Handle<Map> rtt,
|
Handle<CodeT> wrapper_code, Handle<Map> rtt,
|
||||||
Handle<HeapObject> suspender);
|
Handle<HeapObject> suspender);
|
||||||
Handle<WasmOnFulfilledData> NewWasmOnFulfilledData(
|
Handle<WasmResumeData> NewWasmResumeData(
|
||||||
Handle<WasmSuspenderObject> suspender);
|
Handle<WasmSuspenderObject> suspender, wasm::OnResume on_resume);
|
||||||
Handle<WasmStruct> NewWasmStruct(const wasm::StructType* type,
|
Handle<WasmStruct> NewWasmStruct(const wasm::StructType* type,
|
||||||
wasm::WasmValue* args, Handle<Map> map);
|
wasm::WasmValue* args, Handle<Map> map);
|
||||||
Handle<WasmArray> NewWasmArrayFromElements(
|
Handle<WasmArray> NewWasmArrayFromElements(
|
||||||
@ -657,8 +658,8 @@ class V8_EXPORT_PRIVATE Factory : public FactoryBase<Factory> {
|
|||||||
Handle<String> name, Handle<WasmExportedFunctionData> data);
|
Handle<String> name, Handle<WasmExportedFunctionData> data);
|
||||||
Handle<SharedFunctionInfo> NewSharedFunctionInfoForWasmJSFunction(
|
Handle<SharedFunctionInfo> NewSharedFunctionInfoForWasmJSFunction(
|
||||||
Handle<String> name, Handle<WasmJSFunctionData> data);
|
Handle<String> name, Handle<WasmJSFunctionData> data);
|
||||||
Handle<SharedFunctionInfo> NewSharedFunctionInfoForWasmOnFulfilled(
|
Handle<SharedFunctionInfo> NewSharedFunctionInfoForWasmResume(
|
||||||
Handle<WasmOnFulfilledData> data);
|
Handle<WasmResumeData> data);
|
||||||
Handle<SharedFunctionInfo> NewSharedFunctionInfoForWasmCapiFunction(
|
Handle<SharedFunctionInfo> NewSharedFunctionInfoForWasmCapiFunction(
|
||||||
Handle<WasmCapiFunctionData> data);
|
Handle<WasmCapiFunctionData> data);
|
||||||
#endif // V8_ENABLE_WEBASSEMBLY
|
#endif // V8_ENABLE_WEBASSEMBLY
|
||||||
|
@ -67,7 +67,7 @@ namespace internal {
|
|||||||
IF_WASM(V, WasmJSFunctionData) \
|
IF_WASM(V, WasmJSFunctionData) \
|
||||||
IF_WASM(V, WasmStruct) \
|
IF_WASM(V, WasmStruct) \
|
||||||
IF_WASM(V, WasmSuspenderObject) \
|
IF_WASM(V, WasmSuspenderObject) \
|
||||||
IF_WASM(V, WasmOnFulfilledData) \
|
IF_WASM(V, WasmResumeData) \
|
||||||
IF_WASM(V, WasmTypeInfo)
|
IF_WASM(V, WasmTypeInfo)
|
||||||
|
|
||||||
#define FORWARD_DECLARE(TypeName) class TypeName;
|
#define FORWARD_DECLARE(TypeName) class TypeName;
|
||||||
|
@ -517,8 +517,8 @@ bool Heap::CreateInitialMaps() {
|
|||||||
WasmInternalFunction::kSize, wasm_internal_function)
|
WasmInternalFunction::kSize, wasm_internal_function)
|
||||||
IF_WASM(ALLOCATE_MAP, WASM_JS_FUNCTION_DATA_TYPE, WasmJSFunctionData::kSize,
|
IF_WASM(ALLOCATE_MAP, WASM_JS_FUNCTION_DATA_TYPE, WasmJSFunctionData::kSize,
|
||||||
wasm_js_function_data)
|
wasm_js_function_data)
|
||||||
IF_WASM(ALLOCATE_MAP, WASM_ON_FULFILLED_DATA_TYPE,
|
IF_WASM(ALLOCATE_MAP, WASM_RESUME_DATA_TYPE, WasmResumeData::kSize,
|
||||||
WasmOnFulfilledData::kSize, wasm_onfulfilled_data)
|
wasm_resume_data)
|
||||||
IF_WASM(ALLOCATE_MAP, WASM_TYPE_INFO_TYPE, kVariableSizeSentinel,
|
IF_WASM(ALLOCATE_MAP, WASM_TYPE_INFO_TYPE, kVariableSizeSentinel,
|
||||||
wasm_type_info)
|
wasm_type_info)
|
||||||
|
|
||||||
|
@ -393,8 +393,8 @@ VisitorId Map::GetVisitorId(Map map) {
|
|||||||
return kVisitWasmInternalFunction;
|
return kVisitWasmInternalFunction;
|
||||||
case WASM_JS_FUNCTION_DATA_TYPE:
|
case WASM_JS_FUNCTION_DATA_TYPE:
|
||||||
return kVisitWasmJSFunctionData;
|
return kVisitWasmJSFunctionData;
|
||||||
case WASM_ON_FULFILLED_DATA_TYPE:
|
case WASM_RESUME_DATA_TYPE:
|
||||||
return kVisitWasmOnFulfilledData;
|
return kVisitWasmResumeData;
|
||||||
case WASM_API_FUNCTION_REF_TYPE:
|
case WASM_API_FUNCTION_REF_TYPE:
|
||||||
return kVisitWasmApiFunctionRef;
|
return kVisitWasmApiFunctionRef;
|
||||||
case WASM_EXPORTED_FUNCTION_DATA_TYPE:
|
case WASM_EXPORTED_FUNCTION_DATA_TYPE:
|
||||||
|
@ -83,7 +83,7 @@ enum InstanceType : uint16_t;
|
|||||||
IF_WASM(V, WasmInstanceObject) \
|
IF_WASM(V, WasmInstanceObject) \
|
||||||
IF_WASM(V, WasmInternalFunction) \
|
IF_WASM(V, WasmInternalFunction) \
|
||||||
IF_WASM(V, WasmJSFunctionData) \
|
IF_WASM(V, WasmJSFunctionData) \
|
||||||
IF_WASM(V, WasmOnFulfilledData) \
|
IF_WASM(V, WasmResumeData) \
|
||||||
IF_WASM(V, WasmStruct) \
|
IF_WASM(V, WasmStruct) \
|
||||||
IF_WASM(V, WasmSuspenderObject) \
|
IF_WASM(V, WasmSuspenderObject) \
|
||||||
IF_WASM(V, WasmTypeInfo) \
|
IF_WASM(V, WasmTypeInfo) \
|
||||||
|
@ -258,7 +258,7 @@ class ZoneForwardList;
|
|||||||
IF_WASM(V, WasmMemoryObject) \
|
IF_WASM(V, WasmMemoryObject) \
|
||||||
IF_WASM(V, WasmModuleObject) \
|
IF_WASM(V, WasmModuleObject) \
|
||||||
IF_WASM(V, WasmObject) \
|
IF_WASM(V, WasmObject) \
|
||||||
IF_WASM(V, WasmOnFulfilledData) \
|
IF_WASM(V, WasmResumeData) \
|
||||||
IF_WASM(V, WasmStruct) \
|
IF_WASM(V, WasmStruct) \
|
||||||
IF_WASM(V, WasmTypeInfo) \
|
IF_WASM(V, WasmTypeInfo) \
|
||||||
IF_WASM(V, WasmTableObject) \
|
IF_WASM(V, WasmTableObject) \
|
||||||
|
@ -1172,8 +1172,8 @@ auto BodyDescriptorApply(InstanceType type, Args&&... args) {
|
|||||||
return CALL_APPLY(WasmInternalFunction);
|
return CALL_APPLY(WasmInternalFunction);
|
||||||
case WASM_JS_FUNCTION_DATA_TYPE:
|
case WASM_JS_FUNCTION_DATA_TYPE:
|
||||||
return CALL_APPLY(WasmJSFunctionData);
|
return CALL_APPLY(WasmJSFunctionData);
|
||||||
case WASM_ON_FULFILLED_DATA_TYPE:
|
case WASM_RESUME_DATA_TYPE:
|
||||||
return CALL_APPLY(WasmOnFulfilledData);
|
return CALL_APPLY(WasmResumeData);
|
||||||
case WASM_STRUCT_TYPE:
|
case WASM_STRUCT_TYPE:
|
||||||
return CALL_APPLY(WasmStruct);
|
return CALL_APPLY(WasmStruct);
|
||||||
case WASM_TYPE_INFO_TYPE:
|
case WASM_TYPE_INFO_TYPE:
|
||||||
|
@ -711,8 +711,8 @@ bool SharedFunctionInfo::HasWasmCapiFunctionData() const {
|
|||||||
return function_data(kAcquireLoad).IsWasmCapiFunctionData();
|
return function_data(kAcquireLoad).IsWasmCapiFunctionData();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SharedFunctionInfo::HasWasmOnFulfilledData() const {
|
bool SharedFunctionInfo::HasWasmResumeData() const {
|
||||||
return function_data(kAcquireLoad).IsWasmOnFulfilledData();
|
return function_data(kAcquireLoad).IsWasmResumeData();
|
||||||
}
|
}
|
||||||
|
|
||||||
AsmWasmData SharedFunctionInfo::asm_wasm_data() const {
|
AsmWasmData SharedFunctionInfo::asm_wasm_data() const {
|
||||||
|
@ -108,8 +108,13 @@ CodeT SharedFunctionInfo::GetCode() const {
|
|||||||
if (data.IsWasmCapiFunctionData()) {
|
if (data.IsWasmCapiFunctionData()) {
|
||||||
return wasm_capi_function_data().wrapper_code();
|
return wasm_capi_function_data().wrapper_code();
|
||||||
}
|
}
|
||||||
if (data.IsWasmOnFulfilledData()) {
|
if (data.IsWasmResumeData()) {
|
||||||
return isolate->builtins()->code(Builtin::kWasmResume);
|
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
|
#endif // V8_ENABLE_WEBASSEMBLY
|
||||||
if (data.IsUncompiledData()) {
|
if (data.IsUncompiledData()) {
|
||||||
@ -147,6 +152,11 @@ WasmCapiFunctionData SharedFunctionInfo::wasm_capi_function_data() const {
|
|||||||
DCHECK(HasWasmCapiFunctionData());
|
DCHECK(HasWasmCapiFunctionData());
|
||||||
return WasmCapiFunctionData::cast(function_data(kAcquireLoad));
|
return WasmCapiFunctionData::cast(function_data(kAcquireLoad));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WasmResumeData SharedFunctionInfo::wasm_resume_data() const {
|
||||||
|
DCHECK(HasWasmResumeData());
|
||||||
|
return WasmResumeData::cast(function_data(kAcquireLoad));
|
||||||
|
}
|
||||||
#endif // V8_ENABLE_WEBASSEMBLY
|
#endif // V8_ENABLE_WEBASSEMBLY
|
||||||
|
|
||||||
SharedFunctionInfo::ScriptIterator::ScriptIterator(Isolate* isolate,
|
SharedFunctionInfo::ScriptIterator::ScriptIterator(Isolate* isolate,
|
||||||
|
@ -40,6 +40,7 @@ class Signature;
|
|||||||
class WasmCapiFunctionData;
|
class WasmCapiFunctionData;
|
||||||
class WasmExportedFunctionData;
|
class WasmExportedFunctionData;
|
||||||
class WasmJSFunctionData;
|
class WasmJSFunctionData;
|
||||||
|
class WasmResumeData;
|
||||||
|
|
||||||
namespace wasm {
|
namespace wasm {
|
||||||
struct WasmModule;
|
struct WasmModule;
|
||||||
@ -347,7 +348,7 @@ class SharedFunctionInfo
|
|||||||
inline bool HasWasmExportedFunctionData() const;
|
inline bool HasWasmExportedFunctionData() const;
|
||||||
inline bool HasWasmJSFunctionData() const;
|
inline bool HasWasmJSFunctionData() const;
|
||||||
inline bool HasWasmCapiFunctionData() const;
|
inline bool HasWasmCapiFunctionData() const;
|
||||||
inline bool HasWasmOnFulfilledData() const;
|
inline bool HasWasmResumeData() const;
|
||||||
inline AsmWasmData asm_wasm_data() const;
|
inline AsmWasmData asm_wasm_data() const;
|
||||||
inline void set_asm_wasm_data(AsmWasmData data);
|
inline void set_asm_wasm_data(AsmWasmData data);
|
||||||
|
|
||||||
@ -355,6 +356,7 @@ class SharedFunctionInfo
|
|||||||
wasm_exported_function_data() const;
|
wasm_exported_function_data() const;
|
||||||
WasmJSFunctionData wasm_js_function_data() const;
|
WasmJSFunctionData wasm_js_function_data() const;
|
||||||
WasmCapiFunctionData wasm_capi_function_data() const;
|
WasmCapiFunctionData wasm_capi_function_data() const;
|
||||||
|
WasmResumeData wasm_resume_data() const;
|
||||||
|
|
||||||
inline const wasm::WasmModule* wasm_module() const;
|
inline const wasm::WasmModule* wasm_module() const;
|
||||||
inline const wasm::FunctionSig* wasm_function_signature() const;
|
inline const wasm::FunctionSig* wasm_function_signature() const;
|
||||||
|
@ -120,7 +120,7 @@ class Symbol;
|
|||||||
WasmExportedFunctionDataMap) \
|
WasmExportedFunctionDataMap) \
|
||||||
IF_WASM(V, Map, wasm_internal_function_map, WasmInternalFunctionMap) \
|
IF_WASM(V, Map, wasm_internal_function_map, WasmInternalFunctionMap) \
|
||||||
IF_WASM(V, Map, wasm_js_function_data_map, WasmJSFunctionDataMap) \
|
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) \
|
IF_WASM(V, Map, wasm_type_info_map, WasmTypeInfoMap) \
|
||||||
V(Map, weak_fixed_array_map, WeakFixedArrayMap) \
|
V(Map, weak_fixed_array_map, WeakFixedArrayMap) \
|
||||||
V(Map, weak_array_list_map, WeakArrayListMap) \
|
V(Map, weak_array_list_map, WeakArrayListMap) \
|
||||||
|
@ -832,15 +832,16 @@ RUNTIME_FUNCTION(Runtime_WasmSyncStackLimit) {
|
|||||||
return ReadOnlyRoots(isolate).undefined_value();
|
return ReadOnlyRoots(isolate).undefined_value();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Takes a promise and a suspender, and returns promise.then(onFulfilled), where
|
// Takes a promise and a suspender, and returns
|
||||||
// onFulfilled resumes the suspender.
|
// promise.then(suspender.resume(), suspender.reject());
|
||||||
RUNTIME_FUNCTION(Runtime_WasmCreateResumePromise) {
|
RUNTIME_FUNCTION(Runtime_WasmCreateResumePromise) {
|
||||||
CHECK(FLAG_experimental_wasm_stack_switching);
|
CHECK(FLAG_experimental_wasm_stack_switching);
|
||||||
HandleScope scope(isolate);
|
HandleScope scope(isolate);
|
||||||
Handle<Object> promise = args.at(0);
|
Handle<Object> promise = args.at(0);
|
||||||
Handle<WasmSuspenderObject> suspender = args.at<WasmSuspenderObject>(1);
|
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;
|
i::Handle<i::Object> result;
|
||||||
bool has_pending_exception =
|
bool has_pending_exception =
|
||||||
!i::Execution::CallBuiltin(isolate, isolate->promise_then(), promise,
|
!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(WasmArray)
|
||||||
TQ_OBJECT_CONSTRUCTORS_IMPL(WasmContinuationObject)
|
TQ_OBJECT_CONSTRUCTORS_IMPL(WasmContinuationObject)
|
||||||
TQ_OBJECT_CONSTRUCTORS_IMPL(WasmSuspenderObject)
|
TQ_OBJECT_CONSTRUCTORS_IMPL(WasmSuspenderObject)
|
||||||
TQ_OBJECT_CONSTRUCTORS_IMPL(WasmOnFulfilledData)
|
TQ_OBJECT_CONSTRUCTORS_IMPL(WasmResumeData)
|
||||||
|
|
||||||
CAST_ACCESSOR(WasmInstanceObject)
|
CAST_ACCESSOR(WasmInstanceObject)
|
||||||
|
|
||||||
|
@ -1807,15 +1807,22 @@ Handle<WasmSuspenderObject> WasmSuspenderObject::New(Isolate* isolate) {
|
|||||||
suspender->set_state(kInactive);
|
suspender->set_state(kInactive);
|
||||||
// Instantiate the callable object which resumes this Suspender. This will be
|
// Instantiate the callable object which resumes this Suspender. This will be
|
||||||
// used implicitly as the onFulfilled callback of the returned JS promise.
|
// used implicitly as the onFulfilled callback of the returned JS promise.
|
||||||
Handle<WasmOnFulfilledData> function_data =
|
Handle<WasmResumeData> resume_data = isolate->factory()->NewWasmResumeData(
|
||||||
isolate->factory()->NewWasmOnFulfilledData(suspender);
|
suspender, wasm::OnResume::kContinue);
|
||||||
Handle<SharedFunctionInfo> shared =
|
Handle<SharedFunctionInfo> resume_sfi =
|
||||||
isolate->factory()->NewSharedFunctionInfoForWasmOnFulfilled(
|
isolate->factory()->NewSharedFunctionInfoForWasmResume(resume_data);
|
||||||
function_data);
|
|
||||||
Handle<Context> context(isolate->native_context());
|
Handle<Context> context(isolate->native_context());
|
||||||
Handle<JSObject> resume =
|
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_resume(*resume);
|
||||||
|
suspender->set_reject(*reject);
|
||||||
return suspender;
|
return suspender;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -787,14 +787,17 @@ class WasmCapiFunctionData
|
|||||||
TQ_OBJECT_CONSTRUCTORS(WasmCapiFunctionData)
|
TQ_OBJECT_CONSTRUCTORS(WasmCapiFunctionData)
|
||||||
};
|
};
|
||||||
|
|
||||||
class WasmOnFulfilledData
|
namespace wasm {
|
||||||
: public TorqueGeneratedWasmOnFulfilledData<WasmOnFulfilledData,
|
enum class OnResume : int { kContinue, kThrow };
|
||||||
HeapObject> {
|
}
|
||||||
|
|
||||||
|
class WasmResumeData
|
||||||
|
: public TorqueGeneratedWasmResumeData<WasmResumeData, HeapObject> {
|
||||||
public:
|
public:
|
||||||
using BodyDescriptor =
|
using BodyDescriptor =
|
||||||
FlexibleBodyDescriptor<WasmOnFulfilledData::kStartOfStrongFieldsOffset>;
|
FlexibleBodyDescriptor<WasmResumeData::kStartOfStrongFieldsOffset>;
|
||||||
DECL_PRINTER(WasmOnFulfilledData)
|
DECL_PRINTER(WasmResumeData)
|
||||||
TQ_OBJECT_CONSTRUCTORS(WasmOnFulfilledData)
|
TQ_OBJECT_CONSTRUCTORS(WasmResumeData)
|
||||||
};
|
};
|
||||||
|
|
||||||
class WasmScript : public AllStatic {
|
class WasmScript : public AllStatic {
|
||||||
|
@ -80,8 +80,9 @@ extern class WasmCapiFunctionData extends WasmFunctionData {
|
|||||||
serialized_signature: PodArrayOfWasmValueType;
|
serialized_signature: PodArrayOfWasmValueType;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern class WasmOnFulfilledData extends HeapObject {
|
extern class WasmResumeData extends HeapObject {
|
||||||
suspender: WasmSuspenderObject;
|
suspender: WasmSuspenderObject;
|
||||||
|
on_resume: Smi; // See wasm::OnResume enum.
|
||||||
}
|
}
|
||||||
|
|
||||||
extern class WasmIndirectFunctionTable extends Struct {
|
extern class WasmIndirectFunctionTable extends Struct {
|
||||||
@ -104,6 +105,7 @@ extern class WasmSuspenderObject extends JSObject {
|
|||||||
continuation: WasmContinuationObject|Undefined;
|
continuation: WasmContinuationObject|Undefined;
|
||||||
parent: WasmSuspenderObject|Undefined;
|
parent: WasmSuspenderObject|Undefined;
|
||||||
resume: JSObject|Undefined;
|
resume: JSObject|Undefined;
|
||||||
|
reject: JSObject|Undefined;
|
||||||
state: Smi; // 0: Inactive, 1: Active, 2: Suspended.
|
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();
|
let combined_promise = wrapped_export();
|
||||||
assertThrowsAsync(combined_promise, WebAssembly.Exception);
|
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",
|
260: "SORT_STATE_TYPE",
|
||||||
261: "SWISS_NAME_DICTIONARY_TYPE",
|
261: "SWISS_NAME_DICTIONARY_TYPE",
|
||||||
262: "WASM_API_FUNCTION_REF_TYPE",
|
262: "WASM_API_FUNCTION_REF_TYPE",
|
||||||
263: "WASM_ON_FULFILLED_DATA_TYPE",
|
263: "WASM_RESUME_DATA_TYPE",
|
||||||
264: "WEAK_ARRAY_LIST_TYPE",
|
264: "WEAK_ARRAY_LIST_TYPE",
|
||||||
265: "WEAK_CELL_TYPE",
|
265: "WEAK_CELL_TYPE",
|
||||||
266: "WASM_ARRAY_TYPE",
|
266: "WASM_ARRAY_TYPE",
|
||||||
@ -353,7 +353,7 @@ KNOWN_MAPS = {
|
|||||||
("read_only_space", 0x02f51): (223, "WasmExportedFunctionDataMap"),
|
("read_only_space", 0x02f51): (223, "WasmExportedFunctionDataMap"),
|
||||||
("read_only_space", 0x02f79): (205, "WasmInternalFunctionMap"),
|
("read_only_space", 0x02f79): (205, "WasmInternalFunctionMap"),
|
||||||
("read_only_space", 0x02fa1): (224, "WasmJSFunctionDataMap"),
|
("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", 0x02ff1): (206, "WasmTypeInfoMap"),
|
||||||
("read_only_space", 0x03019): (235, "WeakFixedArrayMap"),
|
("read_only_space", 0x03019): (235, "WeakFixedArrayMap"),
|
||||||
("read_only_space", 0x03041): (179, "EphemeronHashTableMap"),
|
("read_only_space", 0x03041): (179, "EphemeronHashTableMap"),
|
||||||
|
Loading…
Reference in New Issue
Block a user