[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:
Manos Koukoutos 2021-11-01 06:43:07 +00:00 committed by V8 LUCI CQ
parent a3cbf9af1e
commit 48b2b89176
22 changed files with 229 additions and 328 deletions

View File

@ -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 =

View File

@ -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
}

View File

@ -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

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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));
}
}
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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

View File

@ -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();

View File

@ -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_;

View File

@ -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);

View File

@ -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; }

View File

@ -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(),

View File

@ -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,

View File

@ -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) \

View File

@ -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) {

View File

@ -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();

View File

@ -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;