[wasm] Simplify 'ref' field for API-defined functions
Design doc: https://bit.ly/3jEVgzz Summary: We change the context for WasmJSFunction and WasmCapiFunction from a tuple containing the instance to a triple WasmAPIFunctionRef = {isolate root, context, callable}. This way we do not have to maintain the correct instance at runtime. Also, a few places in the code get simplified. Changes: - In WasmGraphBuilder, support having a WasmAPIFunctionRef at parameter 0. - Remove unpacking of (instance, callable) tuple from code generators. - Remove the part in WasmGraphBuilder and LiftoffCompiler that used to set the instance field of the function reference. - Modify code that handles the 'ref' field in wasm-objects.*, factory.* and c-api.cc. - Fix the recorded safepoint address for arm when calling a C function from wasm. - (Drive-by) Remove WasmAllocatePair. Bug: v8:11510 Change-Id: I2a4ef3abaf9da36c4a2d85b434965a40a289b9ec Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3236719 Commit-Queue: Manos Koukoutos <manoskouk@chromium.org> Reviewed-by: Jakob Kummerow <jkummerow@chromium.org> Reviewed-by: Michael Lippautz <mlippautz@chromium.org> Reviewed-by: Maya Lekova <mslekova@chromium.org> Cr-Commit-Position: refs/heads/main@{#77639}
This commit is contained in:
parent
a3cbf9af1e
commit
48b2b89176
@ -254,6 +254,14 @@ builtin WasmRethrow(exception: Object): JSAny {
|
||||
tail runtime::WasmReThrow(LoadContextFromFrame(), exception);
|
||||
}
|
||||
|
||||
// We need this for frames that do not have the instance in the parameters.
|
||||
// Currently, this is CapiCallWrapper frames.
|
||||
builtin WasmRethrowExplicitContext(
|
||||
exception: Object, explicitContext: Context): JSAny {
|
||||
if (exception == Null) tail ThrowWasmTrapRethrowNull();
|
||||
tail runtime::WasmReThrow(explicitContext, exception);
|
||||
}
|
||||
|
||||
builtin WasmTriggerTierUp(): JSAny {
|
||||
const instance: WasmInstanceObject = LoadInstanceFromFrame();
|
||||
tail runtime::WasmTriggerTierUp(LoadContextFromFrame(), instance);
|
||||
@ -284,11 +292,6 @@ builtin WasmAllocateJSArray(implicit context: Context)(size: Smi): JSArray {
|
||||
return AllocateJSArray(ElementsKind::PACKED_ELEMENTS, map, size, size);
|
||||
}
|
||||
|
||||
builtin WasmAllocatePair(first: Object, second: Object): Tuple2 {
|
||||
const tuple2Map: Map = %GetClassMapConstant<Tuple2>();
|
||||
return new Tuple2{map: tuple2Map, value1: first, value2: second};
|
||||
}
|
||||
|
||||
builtin WasmAllocateRtt(typeIndex: intptr, parent: Map): Map {
|
||||
tail runtime::WasmAllocateRtt(
|
||||
LoadContextFromFrame(), SmiTag(typeIndex), parent,
|
||||
@ -469,7 +472,7 @@ extern macro GetCodeEntry(CodeDataContainer): RawPtr;
|
||||
|
||||
struct TargetAndInstance {
|
||||
target: RawPtr;
|
||||
instance: HeapObject; // WasmInstanceObject or Tuple2
|
||||
instance: HeapObject; // WasmInstanceObject or WasmApiFunctionRef
|
||||
}
|
||||
|
||||
macro GetTargetAndInstance(funcref: JSFunction): TargetAndInstance {
|
||||
@ -477,10 +480,6 @@ macro GetTargetAndInstance(funcref: JSFunction): TargetAndInstance {
|
||||
dcheck(Is<WasmFunctionData>(sfi.function_data));
|
||||
const funcData = UnsafeCast<WasmFunctionData>(sfi.function_data);
|
||||
const ref = funcData.ref;
|
||||
if (Is<Tuple2>(ref)) {
|
||||
const instance: WasmInstanceObject = LoadInstanceFromFrame();
|
||||
UnsafeCast<Tuple2>(ref).value1 = instance;
|
||||
}
|
||||
let target = funcData.foreign_address_ptr;
|
||||
if (Signed(target) == IntPtrConstant(0)) {
|
||||
const wrapper =
|
||||
|
@ -808,8 +808,16 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
int const num_parameters = MiscField::decode(instr->opcode());
|
||||
#if V8_ENABLE_WEBASSEMBLY
|
||||
if (linkage()->GetIncomingDescriptor()->IsWasmCapiFunction()) {
|
||||
// Put the return address in a stack slot.
|
||||
// Put the current address in a stack slot, and record a safepoint on
|
||||
// the same address. In most architectures, we record the address after
|
||||
// the function call, but this works too as long as the address in the
|
||||
// frame and safepoint table match.
|
||||
__ str(pc, MemOperand(fp, WasmExitFrameConstants::kCallingPCOffset));
|
||||
// In Arm, the pc points two instructions after the currently executing
|
||||
// instruction: see https://bit.ly/3CD80OA. To line up the safepoint
|
||||
// address with the stored pc, we add a nop here.
|
||||
__ nop();
|
||||
RecordSafepoint(instr->reference_map());
|
||||
}
|
||||
#endif // V8_ENABLE_WEBASSEMBLY
|
||||
if (instr->InputAt(0)->IsImmediate()) {
|
||||
@ -819,11 +827,6 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
Register func = i.InputRegister(0);
|
||||
__ CallCFunction(func, num_parameters);
|
||||
}
|
||||
#if V8_ENABLE_WEBASSEMBLY
|
||||
if (linkage()->GetIncomingDescriptor()->IsWasmCapiFunction()) {
|
||||
RecordSafepoint(instr->reference_map());
|
||||
}
|
||||
#endif // V8_ENABLE_WEBASSEMBLY
|
||||
frame_access_state()->SetFrameAccessToDefault();
|
||||
// Ideally, we should decrement SP delta to match the change of stack
|
||||
// pointer in CallCFunction. However, for certain architectures (e.g.
|
||||
@ -3696,23 +3699,14 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
} else {
|
||||
__ StubPrologue(info()->GetOutputStackFrameType());
|
||||
#if V8_ENABLE_WEBASSEMBLY
|
||||
if (call_descriptor->IsWasmFunctionCall()) {
|
||||
if (call_descriptor->IsWasmFunctionCall() ||
|
||||
call_descriptor->IsWasmImportWrapper() ||
|
||||
call_descriptor->IsWasmCapiFunction()) {
|
||||
__ Push(kWasmInstanceRegister);
|
||||
} else if (call_descriptor->IsWasmImportWrapper() ||
|
||||
call_descriptor->IsWasmCapiFunction()) {
|
||||
// Wasm import wrappers are passed a tuple in the place of the instance.
|
||||
// Unpack the tuple into the instance and the target callable.
|
||||
// This must be done here in the codegen because it cannot be expressed
|
||||
// properly in the graph.
|
||||
__ ldr(kJSFunctionRegister,
|
||||
FieldMemOperand(kWasmInstanceRegister, Tuple2::kValue2Offset));
|
||||
__ ldr(kWasmInstanceRegister,
|
||||
FieldMemOperand(kWasmInstanceRegister, Tuple2::kValue1Offset));
|
||||
__ Push(kWasmInstanceRegister);
|
||||
if (call_descriptor->IsWasmCapiFunction()) {
|
||||
// Reserve space for saving the PC later.
|
||||
__ AllocateStackSpace(kSystemPointerSize);
|
||||
}
|
||||
}
|
||||
if (call_descriptor->IsWasmCapiFunction()) {
|
||||
// Reserve space for saving the PC later.
|
||||
__ AllocateStackSpace(kSystemPointerSize);
|
||||
}
|
||||
#endif // V8_ENABLE_WEBASSEMBLY
|
||||
}
|
||||
|
@ -3138,7 +3138,8 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
// {required_slots} to be odd.
|
||||
DCHECK_GE(required_slots, 1);
|
||||
__ Claim(required_slots - 1);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
#if V8_ENABLE_WEBASSEMBLY
|
||||
case CallDescriptor::kCallWasmFunction: {
|
||||
UseScratchRegisterScope temps(tasm());
|
||||
@ -3147,16 +3148,11 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
StackFrame::TypeToMarker(info()->GetOutputStackFrameType()));
|
||||
__ Push(scratch, kWasmInstanceRegister);
|
||||
__ Claim(required_slots);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
case CallDescriptor::kCallWasmImportWrapper:
|
||||
case CallDescriptor::kCallWasmCapiFunction: {
|
||||
UseScratchRegisterScope temps(tasm());
|
||||
__ LoadTaggedPointerField(
|
||||
kJSFunctionRegister,
|
||||
FieldMemOperand(kWasmInstanceRegister, Tuple2::kValue2Offset));
|
||||
__ LoadTaggedPointerField(
|
||||
kWasmInstanceRegister,
|
||||
FieldMemOperand(kWasmInstanceRegister, Tuple2::kValue1Offset));
|
||||
Register scratch = temps.AcquireX();
|
||||
__ Mov(scratch,
|
||||
StackFrame::TypeToMarker(info()->GetOutputStackFrameType()));
|
||||
@ -3166,7 +3162,8 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
? 0 // Import wrapper: none.
|
||||
: 1; // C-API function: PC.
|
||||
__ Claim(required_slots + extra_slots);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
#endif // V8_ENABLE_WEBASSEMBLY
|
||||
case CallDescriptor::kCallAddress:
|
||||
#if V8_ENABLE_WEBASSEMBLY
|
||||
|
@ -3977,25 +3977,14 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
} else {
|
||||
__ StubPrologue(info()->GetOutputStackFrameType());
|
||||
#if V8_ENABLE_WEBASSEMBLY
|
||||
if (call_descriptor->IsWasmFunctionCall()) {
|
||||
if (call_descriptor->IsWasmFunctionCall() ||
|
||||
call_descriptor->IsWasmImportWrapper() ||
|
||||
call_descriptor->IsWasmCapiFunction()) {
|
||||
__ push(kWasmInstanceRegister);
|
||||
} else if (call_descriptor->IsWasmImportWrapper() ||
|
||||
call_descriptor->IsWasmCapiFunction()) {
|
||||
// Wasm import wrappers are passed a tuple in the place of the instance.
|
||||
// Unpack the tuple into the instance and the target callable.
|
||||
// This must be done here in the codegen because it cannot be expressed
|
||||
// properly in the graph.
|
||||
__ mov(kJSFunctionRegister,
|
||||
Operand(kWasmInstanceRegister,
|
||||
Tuple2::kValue2Offset - kHeapObjectTag));
|
||||
__ mov(kWasmInstanceRegister,
|
||||
Operand(kWasmInstanceRegister,
|
||||
Tuple2::kValue1Offset - kHeapObjectTag));
|
||||
__ push(kWasmInstanceRegister);
|
||||
if (call_descriptor->IsWasmCapiFunction()) {
|
||||
// Reserve space for saving the PC later.
|
||||
__ AllocateStackSpace(kSystemPointerSize);
|
||||
}
|
||||
}
|
||||
if (call_descriptor->IsWasmCapiFunction()) {
|
||||
// Reserve space for saving the PC later.
|
||||
__ AllocateStackSpace(kSystemPointerSize);
|
||||
}
|
||||
#endif // V8_ENABLE_WEBASSEMBLY
|
||||
}
|
||||
|
@ -2216,23 +2216,14 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
} else {
|
||||
__ StubPrologue(info()->GetOutputStackFrameType());
|
||||
#if V8_ENABLE_WEBASSEMBLY
|
||||
if (call_descriptor->IsWasmFunctionCall()) {
|
||||
if (call_descriptor->IsWasmImportWrapper() ||
|
||||
call_descriptor->IsWasmImportWrapper() ||
|
||||
call_descriptor->IsWasmCapiFunction()) {
|
||||
__ Push(kWasmInstanceRegister);
|
||||
} else if (call_descriptor->IsWasmImportWrapper() ||
|
||||
call_descriptor->IsWasmCapiFunction()) {
|
||||
// Wasm import wrappers are passed a tuple in the place of the instance.
|
||||
// Unpack the tuple into the instance and the target callable.
|
||||
// This must be done here in the codegen because it cannot be expressed
|
||||
// properly in the graph.
|
||||
__ Ld_d(kJSFunctionRegister,
|
||||
FieldMemOperand(kWasmInstanceRegister, Tuple2::kValue2Offset));
|
||||
__ Ld_d(kWasmInstanceRegister,
|
||||
FieldMemOperand(kWasmInstanceRegister, Tuple2::kValue1Offset));
|
||||
__ Push(kWasmInstanceRegister);
|
||||
if (call_descriptor->IsWasmCapiFunction()) {
|
||||
// Reserve space for saving the PC later.
|
||||
__ Sub_d(sp, sp, Operand(kSystemPointerSize));
|
||||
}
|
||||
}
|
||||
if (call_descriptor->IsWasmCapiFunction()) {
|
||||
// Reserve space for saving the PC later.
|
||||
__ Sub_d(sp, sp, Operand(kSystemPointerSize));
|
||||
}
|
||||
#endif // V8_ENABLE_WEBASSEMBLY
|
||||
}
|
||||
|
@ -3972,23 +3972,14 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
} else {
|
||||
__ StubPrologue(info()->GetOutputStackFrameType());
|
||||
#if V8_ENABLE_WEBASSEMBLY
|
||||
if (call_descriptor->IsWasmFunctionCall()) {
|
||||
if (call_descriptor->IsWasmFunctionCall() ||
|
||||
call_descriptor->IsWasmImportWrapper() ||
|
||||
call_descriptor->IsWasmCapiFunction()) {
|
||||
__ Push(kWasmInstanceRegister);
|
||||
} else if (call_descriptor->IsWasmImportWrapper() ||
|
||||
call_descriptor->IsWasmCapiFunction()) {
|
||||
// Wasm import wrappers are passed a tuple in the place of the instance.
|
||||
// Unpack the tuple into the instance and the target callable.
|
||||
// This must be done here in the codegen because it cannot be expressed
|
||||
// properly in the graph.
|
||||
__ lw(kJSFunctionRegister,
|
||||
FieldMemOperand(kWasmInstanceRegister, Tuple2::kValue2Offset));
|
||||
__ lw(kWasmInstanceRegister,
|
||||
FieldMemOperand(kWasmInstanceRegister, Tuple2::kValue1Offset));
|
||||
__ Push(kWasmInstanceRegister);
|
||||
if (call_descriptor->IsWasmCapiFunction()) {
|
||||
// Reserve space for saving the PC later.
|
||||
__ Subu(sp, sp, Operand(kSystemPointerSize));
|
||||
}
|
||||
}
|
||||
if (call_descriptor->IsWasmCapiFunction()) {
|
||||
// Reserve space for saving the PC later.
|
||||
__ Subu(sp, sp, Operand(kSystemPointerSize));
|
||||
}
|
||||
#endif // V8_ENABLE_WEBASSEMBLY
|
||||
}
|
||||
|
@ -4174,23 +4174,14 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
} else {
|
||||
__ StubPrologue(info()->GetOutputStackFrameType());
|
||||
#if V8_ENABLE_WEBASSEMBLY
|
||||
if (call_descriptor->IsWasmFunctionCall()) {
|
||||
if (call_descriptor->IsWasmFunctionCall() ||
|
||||
call_descriptor->IsWasmImportWrapper() ||
|
||||
call_descriptor->IsWasmCapiFunction()) {
|
||||
__ Push(kWasmInstanceRegister);
|
||||
} else if (call_descriptor->IsWasmImportWrapper() ||
|
||||
call_descriptor->IsWasmCapiFunction()) {
|
||||
// Wasm import wrappers are passed a tuple in the place of the instance.
|
||||
// Unpack the tuple into the instance and the target callable.
|
||||
// This must be done here in the codegen because it cannot be expressed
|
||||
// properly in the graph.
|
||||
__ ld(kJSFunctionRegister,
|
||||
FieldMemOperand(kWasmInstanceRegister, Tuple2::kValue2Offset));
|
||||
__ ld(kWasmInstanceRegister,
|
||||
FieldMemOperand(kWasmInstanceRegister, Tuple2::kValue1Offset));
|
||||
__ Push(kWasmInstanceRegister);
|
||||
if (call_descriptor->IsWasmCapiFunction()) {
|
||||
// Reserve space for saving the PC later.
|
||||
__ Dsubu(sp, sp, Operand(kSystemPointerSize));
|
||||
}
|
||||
}
|
||||
if (call_descriptor->IsWasmCapiFunction()) {
|
||||
// Reserve space for saving the PC later.
|
||||
__ Dsubu(sp, sp, Operand(kSystemPointerSize));
|
||||
}
|
||||
#endif // V8_ENABLE_WEBASSEMBLY
|
||||
}
|
||||
|
@ -3983,25 +3983,14 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
// efficient intialization of the constant pool pointer register).
|
||||
__ StubPrologue(type);
|
||||
#if V8_ENABLE_WEBASSEMBLY
|
||||
if (call_descriptor->IsWasmFunctionCall()) {
|
||||
if (call_descriptor->IsWasmFunctionCall() ||
|
||||
call_descriptor->IsWasmImportWrapper() ||
|
||||
call_descriptor->IsWasmCapiFunction()) {
|
||||
__ Push(kWasmInstanceRegister);
|
||||
} else if (call_descriptor->IsWasmImportWrapper() ||
|
||||
call_descriptor->IsWasmCapiFunction()) {
|
||||
// Wasm import wrappers are passed a tuple in the place of the instance.
|
||||
// Unpack the tuple into the instance and the target callable.
|
||||
// This must be done here in the codegen because it cannot be expressed
|
||||
// properly in the graph.
|
||||
__ LoadTaggedPointerField(
|
||||
kJSFunctionRegister,
|
||||
FieldMemOperand(kWasmInstanceRegister, Tuple2::kValue2Offset), r0);
|
||||
__ LoadTaggedPointerField(
|
||||
kWasmInstanceRegister,
|
||||
FieldMemOperand(kWasmInstanceRegister, Tuple2::kValue1Offset), r0);
|
||||
__ Push(kWasmInstanceRegister);
|
||||
if (call_descriptor->IsWasmCapiFunction()) {
|
||||
// Reserve space for saving the PC later.
|
||||
__ addi(sp, sp, Operand(-kSystemPointerSize));
|
||||
}
|
||||
}
|
||||
if (call_descriptor->IsWasmCapiFunction()) {
|
||||
// Reserve space for saving the PC later.
|
||||
__ addi(sp, sp, Operand(-kSystemPointerSize));
|
||||
}
|
||||
#endif // V8_ENABLE_WEBASSEMBLY
|
||||
}
|
||||
|
@ -3040,25 +3040,14 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
__ Prologue();
|
||||
} else {
|
||||
__ StubPrologue(info()->GetOutputStackFrameType());
|
||||
if (call_descriptor->IsWasmFunctionCall()) {
|
||||
if (call_descriptor->IsWasmFunctionCall() ||
|
||||
call_descriptor->IsWasmImportWrapper() ||
|
||||
call_descriptor->IsWasmCapiFunction()) {
|
||||
__ Push(kWasmInstanceRegister);
|
||||
} else if (call_descriptor->IsWasmImportWrapper() ||
|
||||
call_descriptor->IsWasmCapiFunction()) {
|
||||
// Wasm import wrappers are passed a tuple in the place of the instance.
|
||||
// Unpack the tuple into the instance and the target callable.
|
||||
// This must be done here in the codegen because it cannot be expressed
|
||||
// properly in the graph.
|
||||
__ LoadTaggedPointerField(
|
||||
kJSFunctionRegister,
|
||||
FieldMemOperand(kWasmInstanceRegister, Tuple2::kValue2Offset));
|
||||
__ LoadTaggedPointerField(
|
||||
kWasmInstanceRegister,
|
||||
FieldMemOperand(kWasmInstanceRegister, Tuple2::kValue1Offset));
|
||||
__ Push(kWasmInstanceRegister);
|
||||
if (call_descriptor->IsWasmCapiFunction()) {
|
||||
// Reserve space for saving the PC later.
|
||||
__ Sub64(sp, sp, Operand(kSystemPointerSize));
|
||||
}
|
||||
}
|
||||
if (call_descriptor->IsWasmCapiFunction()) {
|
||||
// Reserve space for saving the PC later.
|
||||
__ Sub64(sp, sp, Operand(kSystemPointerSize));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3744,25 +3744,14 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
// efficient intialization of the constant pool pointer register).
|
||||
__ StubPrologue(type);
|
||||
#if V8_ENABLE_WEBASSEMBLY
|
||||
if (call_descriptor->IsWasmFunctionCall()) {
|
||||
if (call_descriptor->IsWasmFunctionCall() ||
|
||||
call_descriptor->IsWasmImportWrapper() ||
|
||||
call_descriptor->IsWasmCapiFunction()) {
|
||||
__ Push(kWasmInstanceRegister);
|
||||
} else if (call_descriptor->IsWasmImportWrapper() ||
|
||||
call_descriptor->IsWasmCapiFunction()) {
|
||||
// Wasm import wrappers are passed a tuple in the place of the instance.
|
||||
// Unpack the tuple into the instance and the target callable.
|
||||
// This must be done here in the codegen because it cannot be expressed
|
||||
// properly in the graph.
|
||||
__ LoadTaggedPointerField(
|
||||
kJSFunctionRegister,
|
||||
FieldMemOperand(kWasmInstanceRegister, Tuple2::kValue2Offset), r0);
|
||||
__ LoadTaggedPointerField(
|
||||
kWasmInstanceRegister,
|
||||
FieldMemOperand(kWasmInstanceRegister, Tuple2::kValue1Offset), r0);
|
||||
__ Push(kWasmInstanceRegister);
|
||||
if (call_descriptor->IsWasmCapiFunction()) {
|
||||
// Reserve space for saving the PC later.
|
||||
__ lay(sp, MemOperand(sp, -kSystemPointerSize));
|
||||
}
|
||||
}
|
||||
if (call_descriptor->IsWasmCapiFunction()) {
|
||||
// Reserve space for saving the PC later.
|
||||
__ lay(sp, MemOperand(sp, -kSystemPointerSize));
|
||||
}
|
||||
#endif // V8_ENABLE_WEBASSEMBLY
|
||||
}
|
||||
|
@ -4589,25 +4589,18 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
} else {
|
||||
__ StubPrologue(info()->GetOutputStackFrameType());
|
||||
#if V8_ENABLE_WEBASSEMBLY
|
||||
if (call_descriptor->IsWasmFunctionCall()) {
|
||||
if (call_descriptor->IsWasmFunctionCall() ||
|
||||
call_descriptor->IsWasmImportWrapper() ||
|
||||
call_descriptor->IsWasmCapiFunction()) {
|
||||
// We do not use this stack value in import wrappers and capi functions.
|
||||
// We push it anyway to satisfy legacy assumptions about these frames'
|
||||
// size and order.
|
||||
// TODO(manoskouk): Consider fixing this.
|
||||
__ pushq(kWasmInstanceRegister);
|
||||
} else if (call_descriptor->IsWasmImportWrapper() ||
|
||||
call_descriptor->IsWasmCapiFunction()) {
|
||||
// Wasm import wrappers are passed a tuple in the place of the instance.
|
||||
// Unpack the tuple into the instance and the target callable.
|
||||
// This must be done here in the codegen because it cannot be expressed
|
||||
// properly in the graph.
|
||||
__ LoadTaggedPointerField(
|
||||
kJSFunctionRegister,
|
||||
FieldOperand(kWasmInstanceRegister, Tuple2::kValue2Offset));
|
||||
__ LoadTaggedPointerField(
|
||||
kWasmInstanceRegister,
|
||||
FieldOperand(kWasmInstanceRegister, Tuple2::kValue1Offset));
|
||||
__ pushq(kWasmInstanceRegister);
|
||||
if (call_descriptor->IsWasmCapiFunction()) {
|
||||
// Reserve space for saving the PC later.
|
||||
__ AllocateStackSpace(kSystemPointerSize);
|
||||
}
|
||||
}
|
||||
if (call_descriptor->IsWasmCapiFunction()) {
|
||||
// Reserve space for saving the PC later.
|
||||
__ AllocateStackSpace(kSystemPointerSize);
|
||||
}
|
||||
#endif // V8_ENABLE_WEBASSEMBLY
|
||||
}
|
||||
|
@ -625,8 +625,7 @@ bool NodeProperties::IsFreshObject(Node* node) {
|
||||
callee == Builtin::kWasmAllocateArray_InitNull ||
|
||||
callee == Builtin::kWasmAllocateArray_InitZero ||
|
||||
callee == Builtin::kWasmAllocateStructWithRtt ||
|
||||
callee == Builtin::kWasmAllocateObjectWrapper ||
|
||||
callee == Builtin::kWasmAllocatePair;
|
||||
callee == Builtin::kWasmAllocateObjectWrapper;
|
||||
}
|
||||
}
|
||||
#endif // V8_ENABLE_WEBASSEMBLY
|
||||
|
@ -99,7 +99,7 @@ MachineType assert_size(int expected_size, MachineType type) {
|
||||
WasmInstanceObject::k##name##Offset)))
|
||||
|
||||
#define LOAD_ROOT(root_name, factory_name) \
|
||||
(use_js_isolate_and_params() \
|
||||
(parameter_mode_ == kNoSpecialParameterMode \
|
||||
? graph()->NewNode(mcgraph()->common()->HeapConstant( \
|
||||
isolate_->factory()->factory_name())) \
|
||||
: gasm_->LoadImmutable( \
|
||||
@ -477,7 +477,8 @@ class WasmGraphAssembler : public GraphAssembler {
|
||||
WasmGraphBuilder::WasmGraphBuilder(
|
||||
wasm::CompilationEnv* env, Zone* zone, MachineGraph* mcgraph,
|
||||
const wasm::FunctionSig* sig,
|
||||
compiler::SourcePositionTable* source_position_table, Isolate* isolate)
|
||||
compiler::SourcePositionTable* source_position_table,
|
||||
Parameter0Mode parameter_mode, Isolate* isolate)
|
||||
: gasm_(std::make_unique<WasmGraphAssembler>(mcgraph, zone)),
|
||||
zone_(zone),
|
||||
mcgraph_(mcgraph),
|
||||
@ -485,7 +486,9 @@ WasmGraphBuilder::WasmGraphBuilder(
|
||||
has_simd_(ContainsSimd(sig)),
|
||||
sig_(sig),
|
||||
source_position_table_(source_position_table),
|
||||
parameter_mode_(parameter_mode),
|
||||
isolate_(isolate) {
|
||||
DCHECK_EQ(isolate == nullptr, parameter_mode_ != kNoSpecialParameterMode);
|
||||
DCHECK_IMPLIES(env && env->bounds_checks == wasm::kTrapHandler,
|
||||
trap_handler::IsTrapHandlerEnabled());
|
||||
DCHECK_NOT_NULL(mcgraph_);
|
||||
@ -505,13 +508,18 @@ void WasmGraphBuilder::Start(unsigned params) {
|
||||
parameters_[i] = nullptr;
|
||||
}
|
||||
// Initialize instance node.
|
||||
instance_node_ =
|
||||
use_js_isolate_and_params()
|
||||
? gasm_->LoadExportedFunctionInstance(
|
||||
gasm_->LoadFunctionDataFromJSFunction(
|
||||
Param(Linkage::kJSCallClosureParamIndex, "%closure")))
|
||||
: Param(wasm::kWasmInstanceParameterIndex);
|
||||
|
||||
switch (parameter_mode_) {
|
||||
case kInstanceMode:
|
||||
instance_node_ = Param(wasm::kWasmInstanceParameterIndex);
|
||||
break;
|
||||
case kNoSpecialParameterMode:
|
||||
instance_node_ = gasm_->LoadExportedFunctionInstance(
|
||||
gasm_->LoadFunctionDataFromJSFunction(
|
||||
Param(Linkage::kJSCallClosureParamIndex, "%closure")));
|
||||
break;
|
||||
case kWasmApiFunctionRefMode:
|
||||
break;
|
||||
}
|
||||
graph()->SetEnd(graph()->NewNode(mcgraph()->common()->End(0)));
|
||||
}
|
||||
|
||||
@ -640,15 +648,23 @@ Node* WasmGraphBuilder::NoContextConstant() {
|
||||
return mcgraph()->IntPtrConstant(0);
|
||||
}
|
||||
|
||||
Node* WasmGraphBuilder::GetInstance() { return instance_node_.get(); }
|
||||
Node* WasmGraphBuilder::GetInstance() {
|
||||
DCHECK_NE(parameter_mode_, kWasmApiFunctionRefMode);
|
||||
return instance_node_.get();
|
||||
}
|
||||
|
||||
Node* WasmGraphBuilder::BuildLoadIsolateRoot() {
|
||||
if (use_js_isolate_and_params()) {
|
||||
return mcgraph()->IntPtrConstant(isolate_->isolate_root());
|
||||
} else {
|
||||
// For wasm functions, the IsolateRoot is loaded from the instance node so
|
||||
// that the generated code is Isolate independent.
|
||||
return LOAD_INSTANCE_FIELD(IsolateRoot, MachineType::Pointer());
|
||||
switch (parameter_mode_) {
|
||||
case kInstanceMode:
|
||||
// For wasm functions, the IsolateRoot is loaded from the instance node so
|
||||
// that the generated code is Isolate independent.
|
||||
return LOAD_INSTANCE_FIELD(IsolateRoot, MachineType::Pointer());
|
||||
case kWasmApiFunctionRefMode:
|
||||
return gasm_->Load(MachineType::Pointer(), Param(0),
|
||||
wasm::ObjectAccess::ToTagged(
|
||||
WasmApiFunctionRef::kForeignAddressOffset));
|
||||
case kNoSpecialParameterMode:
|
||||
return mcgraph()->IntPtrConstant(isolate_->isolate_root());
|
||||
}
|
||||
}
|
||||
|
||||
@ -3199,20 +3215,6 @@ Node* WasmGraphBuilder::BuildCallRef(const wasm::FunctionSig* sig,
|
||||
MachineType::TaggedPointer(), function_data,
|
||||
wasm::ObjectAccess::ToTagged(WasmFunctionData::kRefOffset));
|
||||
|
||||
Node* is_pair = gasm_->HasInstanceType(instance_node, TUPLE2_TYPE);
|
||||
gasm_->GotoIfNot(is_pair, &load_target);
|
||||
{
|
||||
// Overwrite the tuple's "instance" entry with the current instance.
|
||||
// TODO(jkummerow): Can we avoid this, by guaranteeing that it's always
|
||||
// pre-populated?
|
||||
gasm_->StoreToObject(
|
||||
ObjectAccess(MachineType::TaggedPointer(), kFullWriteBarrier),
|
||||
instance_node, wasm::ObjectAccess::ToTagged(Tuple2::kValue1Offset),
|
||||
GetInstance());
|
||||
gasm_->Goto(&load_target);
|
||||
}
|
||||
|
||||
gasm_->Bind(&load_target);
|
||||
Node* target = BuildLoadCallTargetFromExportedFunctionData(function_data);
|
||||
Node* is_null_target = gasm_->WordEqual(target, gasm_->IntPtrConstant(0));
|
||||
gasm_->GotoIfNot(is_null_target, &end_label, target);
|
||||
@ -6163,10 +6165,12 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
|
||||
public:
|
||||
WasmWrapperGraphBuilder(Zone* zone, MachineGraph* mcgraph,
|
||||
const wasm::FunctionSig* sig,
|
||||
const wasm::WasmModule* module, Isolate* isolate,
|
||||
const wasm::WasmModule* module,
|
||||
Parameter0Mode parameter_mode, Isolate* isolate,
|
||||
compiler::SourcePositionTable* spt,
|
||||
StubCallMode stub_mode, wasm::WasmFeatures features)
|
||||
: WasmGraphBuilder(nullptr, zone, mcgraph, sig, spt, isolate),
|
||||
: WasmGraphBuilder(nullptr, zone, mcgraph, sig, spt, parameter_mode,
|
||||
isolate),
|
||||
module_(module),
|
||||
stub_mode_(stub_mode),
|
||||
enabled_features_(features) {}
|
||||
@ -6942,14 +6946,16 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
|
||||
global_proxy);
|
||||
}
|
||||
|
||||
// For wasm-to-js wrappers, parameter 0 is a WasmApiFunctionRef.
|
||||
bool BuildWasmToJSWrapper(WasmImportCallKind kind, int expected_arity) {
|
||||
int wasm_count = static_cast<int>(sig_->parameter_count());
|
||||
|
||||
// Build the start and the parameter nodes.
|
||||
Start(wasm_count + 4);
|
||||
Start(wasm_count + 3);
|
||||
|
||||
Node* native_context =
|
||||
LOAD_INSTANCE_FIELD(NativeContext, MachineType::TaggedPointer());
|
||||
Node* native_context = gasm_->Load(
|
||||
MachineType::TaggedPointer(), Param(0),
|
||||
wasm::ObjectAccess::ToTagged(WasmApiFunctionRef::kNativeContextOffset));
|
||||
|
||||
if (kind == WasmImportCallKind::kRuntimeTypeError) {
|
||||
// =======================================================================
|
||||
@ -6961,13 +6967,9 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
|
||||
return false;
|
||||
}
|
||||
|
||||
// The Wasm-to-JS wrapper gets passed a pair of (instance, JS callable) in
|
||||
// parameter kWasmInstanceParameterIndex, instead of just the instance, like
|
||||
// most wasm functions. In {CodeGenerator::AssembleConstructFrame}, the pair
|
||||
// expanded into kWasmInstanceRegister and kJSFunctionRegister. The TF call
|
||||
// descriptor for import wrappers is then adapted to contain an additional
|
||||
// parameter mapped to kJSFunctionRegister (in {GetWasmCallDescriptor}).
|
||||
Node* callable_node = Param(wasm_count + 1);
|
||||
Node* callable_node = gasm_->Load(
|
||||
MachineType::TaggedPointer(), Param(0),
|
||||
wasm::ObjectAccess::ToTagged(WasmApiFunctionRef::kCallableOffset));
|
||||
|
||||
Node* undefined_node = UndefinedValue();
|
||||
|
||||
@ -7107,6 +7109,10 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
|
||||
}
|
||||
|
||||
void BuildCapiCallWrapper() {
|
||||
// Set up the graph start.
|
||||
Start(static_cast<int>(sig_->parameter_count()) +
|
||||
1 /* offset for first parameter index being -1 */ +
|
||||
1 /* WasmApiFunctionRef */);
|
||||
// Store arguments on our stack, then align the stack for calling to C.
|
||||
int param_bytes = 0;
|
||||
for (wasm::ValueType type : sig_->parameters()) {
|
||||
@ -7135,8 +7141,10 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
|
||||
control()));
|
||||
offset += type.element_size_bytes();
|
||||
}
|
||||
// The function is passed as the last parameter, after Wasm arguments.
|
||||
Node* function_node = Param(param_count + 1);
|
||||
|
||||
Node* function_node = gasm_->Load(
|
||||
MachineType::TaggedPointer(), Param(0),
|
||||
wasm::ObjectAccess::ToTagged(WasmApiFunctionRef::kCallableOffset));
|
||||
Node* sfi_data = gasm_->LoadFunctionDataFromJSFunction(function_node);
|
||||
Node* host_data_foreign =
|
||||
gasm_->Load(MachineType::AnyTagged(), sfi_data,
|
||||
@ -7168,14 +7176,17 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
|
||||
control());
|
||||
SetControl(
|
||||
graph()->NewNode(mcgraph()->common()->IfFalse(), exception_branch));
|
||||
WasmRethrowDescriptor interface_descriptor;
|
||||
WasmRethrowExplicitContextDescriptor interface_descriptor;
|
||||
auto call_descriptor = Linkage::GetStubCallDescriptor(
|
||||
mcgraph()->zone(), interface_descriptor,
|
||||
interface_descriptor.GetStackParameterCount(), CallDescriptor::kNoFlags,
|
||||
Operator::kNoProperties, StubCallMode::kCallWasmRuntimeStub);
|
||||
Node* call_target = mcgraph()->RelocatableIntPtrConstant(
|
||||
wasm::WasmCode::kWasmRethrow, RelocInfo::WASM_STUB_CALL);
|
||||
gasm_->Call(call_descriptor, call_target, return_value);
|
||||
wasm::WasmCode::kWasmRethrowExplicitContext, RelocInfo::WASM_STUB_CALL);
|
||||
Node* context = gasm_->Load(
|
||||
MachineType::TaggedPointer(), Param(0),
|
||||
wasm::ObjectAccess::ToTagged(WasmApiFunctionRef::kNativeContextOffset));
|
||||
gasm_->Call(call_descriptor, call_target, return_value, context);
|
||||
TerminateThrow(effect(), control());
|
||||
|
||||
SetEffectControl(old_effect, graph()->NewNode(mcgraph()->common()->IfTrue(),
|
||||
@ -7221,12 +7232,12 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
|
||||
|
||||
// Load the original callable from the closure.
|
||||
Node* func_data = gasm_->LoadFunctionDataFromJSFunction(closure);
|
||||
Node* pair = gasm_->LoadFromObject(
|
||||
Node* ref = gasm_->LoadFromObject(
|
||||
MachineType::AnyTagged(), func_data,
|
||||
wasm::ObjectAccess::ToTagged(WasmJSFunctionData::kRefOffset));
|
||||
Node* callable = gasm_->LoadFromObject(
|
||||
MachineType::AnyTagged(), pair,
|
||||
wasm::ObjectAccess::ToTagged(Tuple2::kValue2Offset));
|
||||
MachineType::AnyTagged(), ref,
|
||||
wasm::ObjectAccess::ToTagged(WasmApiFunctionRef::kCallableOffset));
|
||||
|
||||
// Call the underlying closure.
|
||||
base::SmallVector<Node*, 16> args(wasm_count + 7);
|
||||
@ -7385,8 +7396,9 @@ void BuildInlinedJSToWasmWrapper(
|
||||
compiler::SourcePositionTable* spt, StubCallMode stub_mode,
|
||||
wasm::WasmFeatures features, const JSWasmCallData* js_wasm_call_data,
|
||||
Node* frame_state) {
|
||||
WasmWrapperGraphBuilder builder(zone, mcgraph, signature, module, isolate,
|
||||
spt, stub_mode, features);
|
||||
WasmWrapperGraphBuilder builder(zone, mcgraph, signature, module,
|
||||
WasmGraphBuilder::kNoSpecialParameterMode,
|
||||
isolate, spt, stub_mode, features);
|
||||
builder.BuildJSToWasmWrapper(false, js_wasm_call_data, frame_state);
|
||||
}
|
||||
|
||||
@ -7407,9 +7419,10 @@ std::unique_ptr<OptimizedCompilationJob> NewJSToWasmCompilationJob(
|
||||
InstructionSelector::AlignmentRequirements());
|
||||
MachineGraph* mcgraph = zone->New<MachineGraph>(graph, common, machine);
|
||||
|
||||
WasmWrapperGraphBuilder builder(zone.get(), mcgraph, sig, module, isolate,
|
||||
nullptr, StubCallMode::kCallBuiltinPointer,
|
||||
enabled_features);
|
||||
WasmWrapperGraphBuilder builder(
|
||||
zone.get(), mcgraph, sig, module,
|
||||
WasmGraphBuilder::kNoSpecialParameterMode, isolate, nullptr,
|
||||
StubCallMode::kCallBuiltinPointer, enabled_features);
|
||||
builder.BuildJSToWasmWrapper(is_import);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@ -7682,7 +7695,8 @@ wasm::WasmCompilationResult CompileWasmImportCallWrapper(
|
||||
source_positions ? zone.New<SourcePositionTable>(graph) : nullptr;
|
||||
|
||||
WasmWrapperGraphBuilder builder(
|
||||
&zone, mcgraph, sig, env->module, nullptr, source_position_table,
|
||||
&zone, mcgraph, sig, env->module,
|
||||
WasmGraphBuilder::kWasmApiFunctionRefMode, nullptr, source_position_table,
|
||||
StubCallMode::kCallWasmRuntimeStub, env->enabled_features);
|
||||
builder.BuildWasmToJSWrapper(kind, expected_arity);
|
||||
|
||||
@ -7722,14 +7736,10 @@ wasm::WasmCode* CompileWasmCapiCallWrapper(wasm::NativeModule* native_module,
|
||||
InstructionSelector::AlignmentRequirements()));
|
||||
|
||||
WasmWrapperGraphBuilder builder(
|
||||
&zone, mcgraph, sig, native_module->module(), nullptr, source_positions,
|
||||
&zone, mcgraph, sig, native_module->module(),
|
||||
WasmGraphBuilder::kWasmApiFunctionRefMode, nullptr, source_positions,
|
||||
StubCallMode::kCallWasmRuntimeStub, native_module->enabled_features());
|
||||
|
||||
// Set up the graph start.
|
||||
int param_count = static_cast<int>(sig->parameter_count()) +
|
||||
1 /* offset for first parameter index being -1 */ +
|
||||
1 /* Wasm instance */ + 1 /* kExtraCallableParam */;
|
||||
builder.Start(param_count);
|
||||
builder.BuildCapiCallWrapper();
|
||||
|
||||
// Run the compiler pipeline to generate machine code.
|
||||
@ -7773,8 +7783,10 @@ MaybeHandle<Code> CompileWasmToJSWrapper(Isolate* isolate,
|
||||
InstructionSelector::AlignmentRequirements());
|
||||
MachineGraph* mcgraph = zone->New<MachineGraph>(graph, common, machine);
|
||||
|
||||
WasmWrapperGraphBuilder builder(zone.get(), mcgraph, sig, nullptr, nullptr,
|
||||
nullptr, StubCallMode::kCallBuiltinPointer,
|
||||
WasmWrapperGraphBuilder builder(zone.get(), mcgraph, sig, nullptr,
|
||||
WasmGraphBuilder::kWasmApiFunctionRefMode,
|
||||
nullptr, nullptr,
|
||||
StubCallMode::kCallBuiltinPointer,
|
||||
wasm::WasmFeatures::FromIsolate(isolate));
|
||||
builder.BuildWasmToJSWrapper(kind, expected_arity);
|
||||
|
||||
@ -7820,8 +7832,10 @@ MaybeHandle<Code> CompileJSToJSWrapper(Isolate* isolate,
|
||||
InstructionSelector::AlignmentRequirements());
|
||||
MachineGraph* mcgraph = zone->New<MachineGraph>(graph, common, machine);
|
||||
|
||||
WasmWrapperGraphBuilder builder(zone.get(), mcgraph, sig, module, isolate,
|
||||
nullptr, StubCallMode::kCallBuiltinPointer,
|
||||
WasmWrapperGraphBuilder builder(zone.get(), mcgraph, sig, module,
|
||||
WasmGraphBuilder::kNoSpecialParameterMode,
|
||||
isolate, nullptr,
|
||||
StubCallMode::kCallBuiltinPointer,
|
||||
wasm::WasmFeatures::FromIsolate(isolate));
|
||||
builder.BuildJSToJSWrapper();
|
||||
|
||||
@ -7866,8 +7880,10 @@ Handle<CodeT> CompileCWasmEntry(Isolate* isolate, const wasm::FunctionSig* sig,
|
||||
InstructionSelector::AlignmentRequirements());
|
||||
MachineGraph* mcgraph = zone->New<MachineGraph>(graph, common, machine);
|
||||
|
||||
WasmWrapperGraphBuilder builder(zone.get(), mcgraph, sig, module, nullptr,
|
||||
nullptr, StubCallMode::kCallBuiltinPointer,
|
||||
WasmWrapperGraphBuilder builder(zone.get(), mcgraph, sig, module,
|
||||
WasmGraphBuilder::kWasmApiFunctionRefMode,
|
||||
nullptr, nullptr,
|
||||
StubCallMode::kCallBuiltinPointer,
|
||||
wasm::WasmFeatures::FromIsolate(isolate));
|
||||
builder.BuildCWasmEntry();
|
||||
|
||||
|
@ -195,6 +195,18 @@ struct WasmLoopInfo {
|
||||
// the wasm decoder from the internal details of TurboFan.
|
||||
class WasmGraphBuilder {
|
||||
public:
|
||||
// The parameter at index 0 in a wasm function has special meaning:
|
||||
// - For normal wasm functions, it points to the function's instance.
|
||||
// - For Wasm-to-JS and C-API wrappers, it points to a {WasmApiFunctionRef}
|
||||
// object which represents the function's context.
|
||||
// - For JS-to-Wasm and JS-to-JS wrappers (which are JS functions), it does
|
||||
// not have a special meaning. In these cases, we need access to an isolate
|
||||
// at compile time, i.e., {isolate_} needs to be non-null.
|
||||
enum Parameter0Mode {
|
||||
kInstanceMode,
|
||||
kWasmApiFunctionRefMode,
|
||||
kNoSpecialParameterMode
|
||||
};
|
||||
enum ReferenceKind : bool { // --
|
||||
kArrayOrStruct = true,
|
||||
kFunction = false
|
||||
@ -227,7 +239,8 @@ class WasmGraphBuilder {
|
||||
wasm::CompilationEnv* env, Zone* zone, MachineGraph* mcgraph,
|
||||
const wasm::FunctionSig* sig,
|
||||
compiler::SourcePositionTable* spt = nullptr)
|
||||
: WasmGraphBuilder(env, zone, mcgraph, sig, spt, nullptr) {}
|
||||
: WasmGraphBuilder(env, zone, mcgraph, sig, spt, kInstanceMode, nullptr) {
|
||||
}
|
||||
|
||||
V8_EXPORT_PRIVATE ~WasmGraphBuilder();
|
||||
|
||||
@ -528,6 +541,7 @@ class WasmGraphBuilder {
|
||||
MachineGraph* mcgraph,
|
||||
const wasm::FunctionSig* sig,
|
||||
compiler::SourcePositionTable* spt,
|
||||
Parameter0Mode parameter_mode,
|
||||
Isolate* isolate);
|
||||
|
||||
Node* NoContextConstant();
|
||||
@ -763,7 +777,6 @@ class WasmGraphBuilder {
|
||||
SetOncePointer<Node> stack_check_code_node_;
|
||||
SetOncePointer<const Operator> stack_check_call_operator_;
|
||||
|
||||
bool use_js_isolate_and_params() const { return isolate_ != nullptr; }
|
||||
bool has_simd_ = false;
|
||||
bool needs_stack_check_ = false;
|
||||
|
||||
@ -772,6 +785,7 @@ class WasmGraphBuilder {
|
||||
compiler::WasmDecorator* decorator_ = nullptr;
|
||||
|
||||
compiler::SourcePositionTable* const source_position_table_ = nullptr;
|
||||
Parameter0Mode parameter_mode_;
|
||||
Isolate* const isolate_;
|
||||
SetOncePointer<Node> instance_node_;
|
||||
|
||||
|
@ -1493,7 +1493,7 @@ Handle<WasmJSFunctionData> Factory::NewWasmJSFunctionData(
|
||||
Address opt_call_target, Handle<JSReceiver> callable, int return_count,
|
||||
int parameter_count, Handle<PodArray<wasm::ValueType>> serialized_sig,
|
||||
Handle<Code> wrapper_code) {
|
||||
Handle<Tuple2> pair = NewTuple2(null_value(), callable, AllocationType::kOld);
|
||||
Handle<WasmApiFunctionRef> ref = NewWasmApiFunctionRef(callable);
|
||||
Map map = *wasm_js_function_data_map();
|
||||
WasmJSFunctionData result =
|
||||
WasmJSFunctionData::cast(AllocateRawWithImmortalMap(
|
||||
@ -1501,7 +1501,7 @@ Handle<WasmJSFunctionData> Factory::NewWasmJSFunctionData(
|
||||
DisallowGarbageCollection no_gc;
|
||||
result.AllocateExternalPointerEntries(isolate());
|
||||
result.set_foreign_address(isolate(), opt_call_target);
|
||||
result.set_ref(*pair);
|
||||
result.set_ref(*ref);
|
||||
result.set_wrapper_code(*wrapper_code);
|
||||
result.set_serialized_return_count(return_count);
|
||||
result.set_serialized_parameter_count(parameter_count);
|
||||
@ -1524,6 +1524,7 @@ Handle<WasmExportedFunctionData> Factory::NewWasmExportedFunctionData(
|
||||
DisallowGarbageCollection no_gc;
|
||||
result.AllocateExternalPointerEntries(isolate());
|
||||
result.set_foreign_address(isolate(), call_target);
|
||||
DCHECK(ref->IsWasmInstanceObject() || ref->IsWasmApiFunctionRef());
|
||||
result.set_ref(*ref);
|
||||
result.set_wrapper_code(*export_wrapper);
|
||||
result.set_instance(*instance);
|
||||
@ -1540,8 +1541,7 @@ Handle<WasmCapiFunctionData> Factory::NewWasmCapiFunctionData(
|
||||
Address call_target, Handle<Foreign> embedder_data,
|
||||
Handle<Code> wrapper_code,
|
||||
Handle<PodArray<wasm::ValueType>> serialized_sig) {
|
||||
Handle<Tuple2> pair =
|
||||
NewTuple2(null_value(), null_value(), AllocationType::kOld);
|
||||
Handle<WasmApiFunctionRef> ref = NewWasmApiFunctionRef(Handle<JSReceiver>());
|
||||
Map map = *wasm_capi_function_data_map();
|
||||
WasmCapiFunctionData result =
|
||||
WasmCapiFunctionData::cast(AllocateRawWithImmortalMap(
|
||||
@ -1549,7 +1549,7 @@ Handle<WasmCapiFunctionData> Factory::NewWasmCapiFunctionData(
|
||||
DisallowGarbageCollection no_gc;
|
||||
result.AllocateExternalPointerEntries(isolate());
|
||||
result.set_foreign_address(isolate(), call_target);
|
||||
result.set_ref(*pair);
|
||||
result.set_ref(*ref);
|
||||
result.set_wrapper_code(*wrapper_code);
|
||||
result.set_embedder_data(*embedder_data);
|
||||
result.set_serialized_signature(*serialized_sig);
|
||||
|
@ -653,8 +653,8 @@ class WasmApiFunctionRef::BodyDescriptor final : public BodyDescriptorBase {
|
||||
ObjectVisitor* v) {
|
||||
Foreign::BodyDescriptor::IterateBody<ObjectVisitor>(map, obj, object_size,
|
||||
v);
|
||||
IteratePointers(obj, WasmFunctionData::kStartOfStrongFieldsOffset,
|
||||
kEndOfStrongFieldsOffset, v);
|
||||
IteratePointers(obj, kStartOfStrongFieldsOffset, kEndOfStrongFieldsOffset,
|
||||
v);
|
||||
}
|
||||
|
||||
static inline int SizeOf(Map map, HeapObject object) { return kSize; }
|
||||
|
@ -6120,40 +6120,11 @@ class LiftoffCompiler {
|
||||
wasm::ObjectAccess::ToTagged(SharedFunctionInfo::kFunctionDataOffset),
|
||||
pinned);
|
||||
|
||||
// Load "ref" (instance or <instance, callable> pair) and target.
|
||||
// Load "ref" (instance or WasmApiFunctionRef) and target.
|
||||
__ LoadTaggedPointer(
|
||||
instance.gp(), func_data.gp(), no_reg,
|
||||
wasm::ObjectAccess::ToTagged(WasmFunctionData::kRefOffset), pinned);
|
||||
|
||||
Label load_target, perform_call;
|
||||
|
||||
// Check if "ref" is a Tuple2.
|
||||
{
|
||||
LiftoffRegister pair_map = temp;
|
||||
LiftoffRegister ref_map = target;
|
||||
__ LoadMap(ref_map.gp(), instance.gp());
|
||||
LOAD_INSTANCE_FIELD(pair_map.gp(), IsolateRoot, kSystemPointerSize,
|
||||
pinned);
|
||||
__ LoadTaggedPointer(
|
||||
pair_map.gp(), pair_map.gp(), no_reg,
|
||||
IsolateData::root_slot_offset(RootIndex::kTuple2Map), pinned);
|
||||
__ emit_cond_jump(kUnequal, &load_target, kRef, ref_map.gp(),
|
||||
pair_map.gp());
|
||||
|
||||
// Overwrite the tuple's "instance" entry with the current instance.
|
||||
// TODO(jkummerow): Can we figure out a way to guarantee that the
|
||||
// instance field is always precomputed?
|
||||
LiftoffRegister current_instance = temp;
|
||||
__ FillInstanceInto(current_instance.gp());
|
||||
__ StoreTaggedPointer(
|
||||
instance.gp(), no_reg,
|
||||
wasm::ObjectAccess::ToTagged(Tuple2::kValue1Offset),
|
||||
current_instance, pinned);
|
||||
// Fall through to {load_target}.
|
||||
}
|
||||
// Load the call target.
|
||||
__ bind(&load_target);
|
||||
|
||||
#ifdef V8_HEAP_SANDBOX
|
||||
LOAD_INSTANCE_FIELD(temp.gp(), IsolateRoot, kSystemPointerSize, pinned);
|
||||
__ LoadExternalPointer(target.gp(), func_data.gp(),
|
||||
@ -6166,6 +6137,8 @@ class LiftoffCompiler {
|
||||
kPointerLoadType, pinned);
|
||||
#endif
|
||||
|
||||
Label perform_call;
|
||||
|
||||
LiftoffRegister null_address = temp;
|
||||
__ LoadConstant(null_address, WasmValue::ForUintPtr(0));
|
||||
__ emit_cond_jump(kUnequal, &perform_call, kRef, target.gp(),
|
||||
|
@ -1442,8 +1442,9 @@ auto make_func(Store* store_abs, FuncData* data) -> own<Func> {
|
||||
i::Handle<i::WasmCapiFunction> function = i::WasmCapiFunction::New(
|
||||
isolate, reinterpret_cast<i::Address>(&FuncData::v8_callback),
|
||||
embedder_data, SignatureHelper::Serialize(isolate, data->type.get()));
|
||||
i::Tuple2::cast(function->shared().wasm_capi_function_data().ref())
|
||||
.set_value2(*function);
|
||||
i::WasmApiFunctionRef::cast(
|
||||
function->shared().wasm_capi_function_data().ref())
|
||||
.set_callable(*function);
|
||||
auto func = implement<Func>::type::make(store, function);
|
||||
return func;
|
||||
}
|
||||
@ -1679,9 +1680,9 @@ auto Func::call(const Val args[], Val results[]) const -> own<Trap> {
|
||||
static_cast<int>(instance->module()->num_imported_functions)) {
|
||||
object_ref = i::handle(
|
||||
instance->imported_function_refs().get(function_index), isolate);
|
||||
if (object_ref->IsTuple2()) {
|
||||
i::JSFunction jsfunc =
|
||||
i::JSFunction::cast(i::Tuple2::cast(*object_ref).value2());
|
||||
if (object_ref->IsWasmApiFunctionRef()) {
|
||||
i::JSFunction jsfunc = i::JSFunction::cast(
|
||||
i::WasmApiFunctionRef::cast(*object_ref).callable());
|
||||
i::Object data = jsfunc.shared().function_data(v8::kAcquireLoad);
|
||||
if (data.IsWasmCapiFunctionData()) {
|
||||
return CallWasmCapiFunction(i::WasmCapiFunctionData::cast(data), args,
|
||||
|
@ -61,7 +61,6 @@ struct WasmModule;
|
||||
V(WasmFloat64ToNumber) \
|
||||
V(WasmTaggedToFloat64) \
|
||||
V(WasmAllocateJSArray) \
|
||||
V(WasmAllocatePair) \
|
||||
V(WasmAtomicNotify) \
|
||||
V(WasmI32AtomicWait32) \
|
||||
V(WasmI32AtomicWait64) \
|
||||
@ -81,6 +80,7 @@ struct WasmModule;
|
||||
V(WasmAllocateFixedArray) \
|
||||
V(WasmThrow) \
|
||||
V(WasmRethrow) \
|
||||
V(WasmRethrowExplicitContext) \
|
||||
V(WasmTraceEnter) \
|
||||
V(WasmTraceExit) \
|
||||
V(WasmTraceMemory) \
|
||||
|
@ -634,15 +634,14 @@ void WasmTableObject::UpdateDispatchTables(
|
||||
isolate->counters()->wasm_reloc_size()->Increment(
|
||||
wasm_code->reloc_info().length());
|
||||
}
|
||||
// There is a cached tuple on the {capi_function}, but it is instance-
|
||||
// independent, so we prefer to allocate a fresh tuple here.
|
||||
Handle<Tuple2> tuple = isolate->factory()->NewTuple2(
|
||||
instance, capi_function, AllocationType::kOld);
|
||||
// Note that {SignatureMap::Find} may return {-1} if the signature is
|
||||
// not found; it will simply never match any check.
|
||||
auto sig_id = instance->module()->signature_map.Find(sig);
|
||||
IndirectFunctionTableEntry(instance, table_index, entry_index)
|
||||
.Set(sig_id, wasm_code->instruction_start(), *tuple);
|
||||
.Set(sig_id, wasm_code->instruction_start(),
|
||||
WasmCapiFunctionData::cast(
|
||||
capi_function->shared().function_data(kAcquireLoad))
|
||||
.ref());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1153,9 +1152,9 @@ void ImportedFunctionEntry::SetWasmToJs(
|
||||
wasm_to_js_wrapper->instructions().begin());
|
||||
DCHECK(wasm_to_js_wrapper->kind() == wasm::WasmCode::kWasmToJsWrapper ||
|
||||
wasm_to_js_wrapper->kind() == wasm::WasmCode::kWasmToCapiWrapper);
|
||||
Handle<Tuple2> tuple =
|
||||
isolate->factory()->NewTuple2(instance_, callable, AllocationType::kOld);
|
||||
instance_->imported_function_refs().set(index_, *tuple);
|
||||
Handle<WasmApiFunctionRef> ref =
|
||||
isolate->factory()->NewWasmApiFunctionRef(callable);
|
||||
instance_->imported_function_refs().set(index_, *ref);
|
||||
instance_->imported_function_targets()[index_] =
|
||||
wasm_to_js_wrapper->instruction_start();
|
||||
}
|
||||
@ -1169,28 +1168,16 @@ void ImportedFunctionEntry::SetWasmToWasm(WasmInstanceObject instance,
|
||||
instance_->imported_function_targets()[index_] = call_target;
|
||||
}
|
||||
|
||||
WasmInstanceObject ImportedFunctionEntry::instance() {
|
||||
// The imported reference entry is either a target instance or a tuple
|
||||
// of this instance and the target callable.
|
||||
Object value = object_ref();
|
||||
if (value.IsWasmInstanceObject()) {
|
||||
return WasmInstanceObject::cast(value);
|
||||
}
|
||||
Tuple2 tuple = Tuple2::cast(value);
|
||||
return WasmInstanceObject::cast(tuple.value1());
|
||||
}
|
||||
|
||||
// Returns an empty Object() if no callable is available, a JSReceiver
|
||||
// otherwise.
|
||||
Object ImportedFunctionEntry::maybe_callable() {
|
||||
Object value = object_ref();
|
||||
if (!value.IsTuple2()) return Object();
|
||||
Tuple2 tuple = Tuple2::cast(value);
|
||||
return JSReceiver::cast(tuple.value2());
|
||||
if (!value.IsWasmApiFunctionRef()) return Object();
|
||||
return JSReceiver::cast(WasmApiFunctionRef::cast(value).callable());
|
||||
}
|
||||
|
||||
JSReceiver ImportedFunctionEntry::callable() {
|
||||
return JSReceiver::cast(Tuple2::cast(object_ref()).value2());
|
||||
return JSReceiver::cast(WasmApiFunctionRef::cast(object_ref()).callable());
|
||||
}
|
||||
|
||||
Object ImportedFunctionEntry::object_ref() {
|
||||
@ -1578,10 +1565,10 @@ void WasmInstanceObject::ImportWasmJSFunctionIntoTable(
|
||||
}
|
||||
|
||||
// Update the dispatch table.
|
||||
Handle<Tuple2> tuple =
|
||||
isolate->factory()->NewTuple2(instance, callable, AllocationType::kOld);
|
||||
Handle<WasmApiFunctionRef> ref =
|
||||
isolate->factory()->NewWasmApiFunctionRef(callable);
|
||||
IndirectFunctionTableEntry(instance, table_index, entry_index)
|
||||
.Set(sig_id, call_target, *tuple);
|
||||
.Set(sig_id, call_target, *ref);
|
||||
}
|
||||
|
||||
// static
|
||||
@ -2183,7 +2170,8 @@ Handle<WasmJSFunction> WasmJSFunction::New(Isolate* isolate,
|
||||
|
||||
JSReceiver WasmJSFunction::GetCallable() const {
|
||||
return JSReceiver::cast(
|
||||
Tuple2::cast(shared().wasm_js_function_data().ref()).value2());
|
||||
WasmApiFunctionRef::cast(shared().wasm_js_function_data().ref())
|
||||
.callable());
|
||||
}
|
||||
|
||||
const wasm::FunctionSig* WasmJSFunction::GetSignature(Zone* zone) {
|
||||
|
@ -96,7 +96,7 @@ class V8_EXPORT_PRIVATE IndirectFunctionTableEntry {
|
||||
// call imported functions at runtime.
|
||||
// Each entry is either:
|
||||
// - Wasm to JS, which has fields
|
||||
// - object = a Tuple2 of the importing instance and the callable
|
||||
// - object = a WasmApiFunctionRef
|
||||
// - target = entrypoint to import wrapper code
|
||||
// - Wasm to Wasm, which has fields
|
||||
// - object = target instance
|
||||
@ -112,7 +112,6 @@ class ImportedFunctionEntry {
|
||||
// Initialize this entry as a Wasm to Wasm call.
|
||||
void SetWasmToWasm(WasmInstanceObject target_instance, Address call_target);
|
||||
|
||||
WasmInstanceObject instance();
|
||||
JSReceiver callable();
|
||||
Object maybe_callable();
|
||||
Object object_ref();
|
||||
|
@ -23,13 +23,12 @@ extern class WasmApiFunctionRef extends Foreign {
|
||||
|
||||
extern class WasmFunctionData extends Foreign {
|
||||
// This is the "reference" value that must be passed along in the "instance"
|
||||
// register when calling the given function. It is either the target instance,
|
||||
// or a pair holding the target instance and the callable; currently the
|
||||
// latter is the case when the function being called is defined in JavaScript
|
||||
// or via the C-API.
|
||||
// register when calling the given function. It is either the target instance
|
||||
// (for wasm functions), or a WasmApiFunctionRef object (for functions defined
|
||||
// through the JS or C APIs).
|
||||
// For imported functions, this value equals the respective entry in
|
||||
// the module's imported_function_refs array.
|
||||
ref: WasmInstanceObject|Tuple2;
|
||||
ref: WasmInstanceObject|WasmApiFunctionRef;
|
||||
// Used for calling this function from JavaScript.
|
||||
@if(V8_EXTERNAL_CODE_SPACE) wrapper_code: CodeDataContainer;
|
||||
@ifnot(V8_EXTERNAL_CODE_SPACE) wrapper_code: Code;
|
||||
|
Loading…
Reference in New Issue
Block a user