[wasm] Refactor indirect function calls
This is the combined second and third step of refactoring indirect function calls through tables with index > 0 to work without runtime calls. The first CL introduces the WasmIndirectFunctionTable heap object. For a table of type anyfunc within a WebAssembly instance, WasmIndirectFunctionTable stores the size, the signature id's, the call targets, and the reference parameters for that table. I used the names that are already used for the matching fields of the WasmInstanceObject. The second CL expands the IndirectFunctionTableEntry to work also on WasmIndirectFunctionTable objects. All changes to a function table go through this class. The third CL introduces uses of the WasmIndirectFunctionTable. In this CL I change the code generation in TurboFan to replace runime calls with direct accesses to the new WasmIndirectFunctionTable. Additionally I extended the initialization of WasmIndirectFunctionTable, and also implement Table.grow. R=mstarzinger@chromium.org Bug: v8:7581 Change-Id: Ic7615c0138562d27897683358ddc0943add1acfe Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1684186 Commit-Queue: Andreas Haas <ahaas@chromium.org> Reviewed-by: Michael Starzinger <mstarzinger@chromium.org> Cr-Commit-Position: refs/heads/master@{#62515}
This commit is contained in:
parent
d3472765d8
commit
02f18b2df1
@ -2854,25 +2854,69 @@ Node* WasmGraphBuilder::CallDirect(uint32_t index, Node** args, Node*** rets,
|
||||
Node* WasmGraphBuilder::CallIndirect(uint32_t table_index, uint32_t sig_index,
|
||||
Node** args, Node*** rets,
|
||||
wasm::WasmCodePosition position) {
|
||||
if (table_index == 0) {
|
||||
return BuildIndirectCall(sig_index, args, rets, position, kCallContinues);
|
||||
}
|
||||
return BuildIndirectCall(table_index, sig_index, args, rets, position,
|
||||
kCallContinues);
|
||||
}
|
||||
|
||||
Node* WasmGraphBuilder::BuildIndirectCall(uint32_t sig_index, Node** args,
|
||||
void WasmGraphBuilder::LoadIndirectFunctionTable(uint32_t table_index,
|
||||
Node** ift_size,
|
||||
Node** ift_sig_ids,
|
||||
Node** ift_targets,
|
||||
Node** ift_instances) {
|
||||
if (table_index == 0) {
|
||||
*ift_size =
|
||||
LOAD_INSTANCE_FIELD(IndirectFunctionTableSize, MachineType::Uint32());
|
||||
*ift_sig_ids = LOAD_INSTANCE_FIELD(IndirectFunctionTableSigIds,
|
||||
MachineType::Pointer());
|
||||
*ift_targets = LOAD_INSTANCE_FIELD(IndirectFunctionTableTargets,
|
||||
MachineType::Pointer());
|
||||
*ift_instances = LOAD_INSTANCE_FIELD(
|
||||
IndirectFunctionTableRefs, MachineType::TypeCompressedTaggedPointer());
|
||||
return;
|
||||
}
|
||||
|
||||
Node* ift_tables = LOAD_INSTANCE_FIELD(
|
||||
IndirectFunctionTables, MachineType::TypeCompressedTaggedPointer());
|
||||
Node* ift_table = LOAD_FIXED_ARRAY_SLOT_ANY(ift_tables, table_index);
|
||||
|
||||
*ift_size = LOAD_RAW(
|
||||
ift_table,
|
||||
wasm::ObjectAccess::ToTagged(WasmIndirectFunctionTable::kSizeOffset),
|
||||
MachineType::Int32());
|
||||
|
||||
*ift_sig_ids = LOAD_RAW(
|
||||
ift_table,
|
||||
wasm::ObjectAccess::ToTagged(WasmIndirectFunctionTable::kSigIdsOffset),
|
||||
MachineType::Pointer());
|
||||
|
||||
*ift_targets = LOAD_RAW(
|
||||
ift_table,
|
||||
wasm::ObjectAccess::ToTagged(WasmIndirectFunctionTable::kTargetsOffset),
|
||||
MachineType::Pointer());
|
||||
|
||||
*ift_instances = LOAD_RAW(
|
||||
ift_table,
|
||||
wasm::ObjectAccess::ToTagged(WasmIndirectFunctionTable::kRefsOffset),
|
||||
MachineType::TypeCompressedTaggedPointer());
|
||||
}
|
||||
|
||||
Node* WasmGraphBuilder::BuildIndirectCall(uint32_t table_index,
|
||||
uint32_t sig_index, Node** args,
|
||||
Node*** rets,
|
||||
wasm::WasmCodePosition position,
|
||||
IsReturnCall continuation) {
|
||||
DCHECK_NOT_NULL(args[0]);
|
||||
DCHECK_NOT_NULL(env_);
|
||||
|
||||
// Assume only one table for now.
|
||||
wasm::FunctionSig* sig = env_->module->signatures[sig_index];
|
||||
// First we have to load the table.
|
||||
Node* ift_size;
|
||||
Node* ift_sig_ids;
|
||||
Node* ift_targets;
|
||||
Node* ift_instances;
|
||||
LoadIndirectFunctionTable(table_index, &ift_size, &ift_sig_ids, &ift_targets,
|
||||
&ift_instances);
|
||||
|
||||
Node* ift_size =
|
||||
LOAD_INSTANCE_FIELD(IndirectFunctionTableSize, MachineType::Uint32());
|
||||
wasm::FunctionSig* sig = env_->module->signatures[sig_index];
|
||||
|
||||
MachineOperatorBuilder* machine = mcgraph()->machine();
|
||||
Node* key = args[0];
|
||||
@ -2895,9 +2939,6 @@ Node* WasmGraphBuilder::BuildIndirectCall(uint32_t sig_index, Node** args,
|
||||
}
|
||||
|
||||
// Load signature from the table and check.
|
||||
Node* ift_sig_ids =
|
||||
LOAD_INSTANCE_FIELD(IndirectFunctionTableSigIds, MachineType::Pointer());
|
||||
|
||||
int32_t expected_sig_id = env_->module->signature_ids[sig_index];
|
||||
Node* int32_scaled_key = Uint32ToUintptr(
|
||||
graph()->NewNode(machine->Word32Shl(), key, Int32Constant(2)));
|
||||
@ -2910,11 +2951,6 @@ Node* WasmGraphBuilder::BuildIndirectCall(uint32_t sig_index, Node** args,
|
||||
|
||||
TrapIfFalse(wasm::kTrapFuncSigMismatch, sig_match, position);
|
||||
|
||||
Node* ift_targets =
|
||||
LOAD_INSTANCE_FIELD(IndirectFunctionTableTargets, MachineType::Pointer());
|
||||
Node* ift_instances = LOAD_INSTANCE_FIELD(
|
||||
IndirectFunctionTableRefs, MachineType::TypeCompressedTaggedPointer());
|
||||
|
||||
Node* tagged_scaled_key;
|
||||
if (kTaggedSize == kInt32Size) {
|
||||
tagged_scaled_key = int32_scaled_key;
|
||||
@ -2956,48 +2992,6 @@ Node* WasmGraphBuilder::BuildIndirectCall(uint32_t sig_index, Node** args,
|
||||
}
|
||||
}
|
||||
|
||||
Node* WasmGraphBuilder::BuildIndirectCall(uint32_t table_index,
|
||||
uint32_t sig_index, Node** args,
|
||||
Node*** rets,
|
||||
wasm::WasmCodePosition position,
|
||||
IsReturnCall continuation) {
|
||||
DCHECK_NOT_NULL(args[0]);
|
||||
Node* entry_index = args[0];
|
||||
DCHECK_NOT_NULL(env_);
|
||||
BoundsCheckTable(table_index, entry_index, position, wasm::kTrapFuncInvalid,
|
||||
nullptr);
|
||||
|
||||
DCHECK(Smi::IsValid(table_index));
|
||||
DCHECK(Smi::IsValid(sig_index));
|
||||
Node* runtime_args[]{
|
||||
graph()->NewNode(mcgraph()->common()->NumberConstant(table_index)),
|
||||
BuildChangeUint31ToSmi(entry_index),
|
||||
graph()->NewNode(mcgraph()->common()->NumberConstant(sig_index))};
|
||||
|
||||
Node* target_instance = BuildCallToRuntime(
|
||||
Runtime::kWasmIndirectCallCheckSignatureAndGetTargetInstance,
|
||||
runtime_args, arraysize(runtime_args));
|
||||
|
||||
// We reuse the runtime_args array here, even though we only need the first
|
||||
// two arguments.
|
||||
Node* call_target = BuildCallToRuntime(
|
||||
Runtime::kWasmIndirectCallGetTargetAddress, runtime_args, 2);
|
||||
|
||||
wasm::FunctionSig* sig = env_->module->signatures[sig_index];
|
||||
args[0] = call_target;
|
||||
const UseRetpoline use_retpoline =
|
||||
untrusted_code_mitigations_ ? kRetpoline : kNoRetpoline;
|
||||
|
||||
switch (continuation) {
|
||||
case kCallContinues:
|
||||
return BuildWasmCall(sig, args, rets, position, target_instance,
|
||||
use_retpoline);
|
||||
case kReturnCall:
|
||||
return BuildWasmReturnCall(sig, args, position, target_instance,
|
||||
use_retpoline);
|
||||
}
|
||||
}
|
||||
|
||||
Node* WasmGraphBuilder::ReturnCall(uint32_t index, Node** args,
|
||||
wasm::WasmCodePosition position) {
|
||||
DCHECK_NULL(args[0]);
|
||||
@ -3020,9 +3014,6 @@ Node* WasmGraphBuilder::ReturnCall(uint32_t index, Node** args,
|
||||
Node* WasmGraphBuilder::ReturnCallIndirect(uint32_t table_index,
|
||||
uint32_t sig_index, Node** args,
|
||||
wasm::WasmCodePosition position) {
|
||||
if (table_index == 0) {
|
||||
return BuildIndirectCall(sig_index, args, nullptr, position, kReturnCall);
|
||||
}
|
||||
return BuildIndirectCall(table_index, sig_index, args, nullptr, position,
|
||||
kReturnCall);
|
||||
}
|
||||
|
@ -490,10 +490,10 @@ class WasmGraphBuilder {
|
||||
Node* BuildCallNode(wasm::FunctionSig* sig, Node** args,
|
||||
wasm::WasmCodePosition position, Node* instance_node,
|
||||
const Operator* op);
|
||||
// Special implementation for CallIndirect for table 0.
|
||||
Node* BuildIndirectCall(uint32_t sig_index, Node** args, Node*** rets,
|
||||
wasm::WasmCodePosition position,
|
||||
IsReturnCall continuation);
|
||||
// Helper function for {BuildIndirectCall}.
|
||||
void LoadIndirectFunctionTable(uint32_t table_index, Node** ift_size,
|
||||
Node** ift_sig_ids, Node** ift_targets,
|
||||
Node** ift_instances);
|
||||
Node* BuildIndirectCall(uint32_t table_index, uint32_t sig_index, Node** args,
|
||||
Node*** rets, wasm::WasmCodePosition position,
|
||||
IsReturnCall continuation);
|
||||
|
@ -479,122 +479,6 @@ RUNTIME_FUNCTION(Runtime_WasmFunctionTableSet) {
|
||||
return ReadOnlyRoots(isolate).undefined_value();
|
||||
}
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_WasmIndirectCallCheckSignatureAndGetTargetInstance) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(3, args.length());
|
||||
auto instance =
|
||||
Handle<WasmInstanceObject>(GetWasmInstanceOnStackTop(isolate), isolate);
|
||||
CONVERT_UINT32_ARG_CHECKED(table_index, 0);
|
||||
CONVERT_UINT32_ARG_CHECKED(entry_index, 1);
|
||||
CONVERT_UINT32_ARG_CHECKED(sig_index, 2);
|
||||
DCHECK(isolate->context().is_null());
|
||||
isolate->set_context(instance->native_context());
|
||||
|
||||
DCHECK_LT(table_index, instance->tables().length());
|
||||
auto table_obj = handle(
|
||||
WasmTableObject::cast(instance->tables().get(table_index)), isolate);
|
||||
|
||||
// This check is already done in generated code.
|
||||
DCHECK(WasmTableObject::IsInBounds(isolate, table_obj, entry_index));
|
||||
|
||||
bool is_valid;
|
||||
bool is_null;
|
||||
MaybeHandle<WasmInstanceObject> maybe_target_instance;
|
||||
int function_index;
|
||||
MaybeHandle<WasmJSFunction> maybe_js_function;
|
||||
WasmTableObject::GetFunctionTableEntry(
|
||||
isolate, table_obj, entry_index, &is_valid, &is_null,
|
||||
&maybe_target_instance, &function_index, &maybe_js_function);
|
||||
|
||||
CHECK(is_valid);
|
||||
if (is_null) {
|
||||
// We throw a signature mismatch trap to be in sync with the generated
|
||||
// code. There we do a signature check instead of a null-check. Trap
|
||||
// reasons are not defined in the spec. Otherwise, a null-check is
|
||||
// performed before a signature, according to the spec.
|
||||
return ThrowWasmError(isolate, MessageTemplate::kWasmTrapFuncSigMismatch);
|
||||
}
|
||||
// TODO(7742): Test and implement indirect calls for non-zero tables.
|
||||
CHECK(maybe_js_function.is_null());
|
||||
|
||||
// Now we do the signature check.
|
||||
Handle<WasmInstanceObject> target_instance =
|
||||
maybe_target_instance.ToHandleChecked();
|
||||
|
||||
const wasm::WasmModule* target_module =
|
||||
target_instance->module_object().native_module()->module();
|
||||
|
||||
wasm::FunctionSig* target_sig = target_module->functions[function_index].sig;
|
||||
|
||||
auto target_sig_id = instance->module()->signature_map.Find(*target_sig);
|
||||
uint32_t expected_sig_id = instance->module()->signature_ids[sig_index];
|
||||
|
||||
if (expected_sig_id != static_cast<uint32_t>(target_sig_id)) {
|
||||
return ThrowWasmError(isolate, MessageTemplate::kWasmTrapFuncSigMismatch);
|
||||
}
|
||||
|
||||
if (function_index <
|
||||
static_cast<int>(target_instance->module()->num_imported_functions)) {
|
||||
// The function in the target instance was imported. Use its imports table,
|
||||
// which contains a tuple needed by the import wrapper.
|
||||
ImportedFunctionEntry entry(target_instance, function_index);
|
||||
return entry.object_ref();
|
||||
}
|
||||
return *target_instance;
|
||||
}
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_WasmIndirectCallGetTargetAddress) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(2, args.length());
|
||||
auto instance =
|
||||
Handle<WasmInstanceObject>(GetWasmInstanceOnStackTop(isolate), isolate);
|
||||
CONVERT_UINT32_ARG_CHECKED(table_index, 0);
|
||||
CONVERT_UINT32_ARG_CHECKED(entry_index, 1);
|
||||
|
||||
DCHECK_LT(table_index, instance->tables().length());
|
||||
auto table_obj = handle(
|
||||
WasmTableObject::cast(instance->tables().get(table_index)), isolate);
|
||||
|
||||
DCHECK(WasmTableObject::IsInBounds(isolate, table_obj, entry_index));
|
||||
|
||||
bool is_valid;
|
||||
bool is_null;
|
||||
MaybeHandle<WasmInstanceObject> maybe_target_instance;
|
||||
int function_index;
|
||||
MaybeHandle<WasmJSFunction> maybe_js_function;
|
||||
WasmTableObject::GetFunctionTableEntry(
|
||||
isolate, table_obj, entry_index, &is_valid, &is_null,
|
||||
&maybe_target_instance, &function_index, &maybe_js_function);
|
||||
|
||||
CHECK(is_valid);
|
||||
// The null-check should already have been done in
|
||||
// Runtime_WasmIndirectCallCheckSignatureAndGetTargetInstance. That runtime
|
||||
// function should always be called first.
|
||||
CHECK(!is_null);
|
||||
// TODO(7742): Test and implement indirect calls for non-zero tables.
|
||||
CHECK(maybe_js_function.is_null());
|
||||
|
||||
Handle<WasmInstanceObject> target_instance =
|
||||
maybe_target_instance.ToHandleChecked();
|
||||
|
||||
Address call_target = 0;
|
||||
if (function_index <
|
||||
static_cast<int>(target_instance->module()->num_imported_functions)) {
|
||||
// The function in the target instance was imported. Use its imports table,
|
||||
// which contains a tuple needed by the import wrapper.
|
||||
ImportedFunctionEntry entry(target_instance, function_index);
|
||||
call_target = entry.target();
|
||||
} else {
|
||||
// The function in the target instance was not imported.
|
||||
call_target = target_instance->GetCallTarget(function_index);
|
||||
}
|
||||
|
||||
// The return value is an address and not a SMI. However, the address is
|
||||
// always aligned, and a SMI uses the same space as {Address}.
|
||||
CHECK(HAS_SMI_TAG(call_target));
|
||||
return Smi(call_target);
|
||||
}
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_WasmTableInit) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(5, args.length());
|
||||
|
@ -528,29 +528,27 @@ namespace internal {
|
||||
F(TypedArraySet, 2, 1) \
|
||||
F(TypedArraySortFast, 1, 1)
|
||||
|
||||
#define FOR_EACH_INTRINSIC_WASM(F, I) \
|
||||
F(ThrowWasmError, 1, 1) \
|
||||
F(ThrowWasmStackOverflow, 0, 1) \
|
||||
F(WasmI32AtomicWait, 4, 1) \
|
||||
F(WasmI64AtomicWait, 5, 1) \
|
||||
F(WasmAtomicNotify, 3, 1) \
|
||||
F(WasmExceptionGetValues, 1, 1) \
|
||||
F(WasmExceptionGetTag, 1, 1) \
|
||||
F(WasmMemoryGrow, 2, 1) \
|
||||
F(WasmRunInterpreter, 2, 1) \
|
||||
F(WasmStackGuard, 0, 1) \
|
||||
F(WasmThrowCreate, 2, 1) \
|
||||
F(WasmThrowTypeError, 0, 1) \
|
||||
F(WasmRefFunc, 1, 1) \
|
||||
F(WasmFunctionTableGet, 3, 1) \
|
||||
F(WasmFunctionTableSet, 4, 1) \
|
||||
F(WasmTableInit, 5, 1) \
|
||||
F(WasmTableCopy, 5, 1) \
|
||||
F(WasmTableGrow, 3, 1) \
|
||||
F(WasmTableFill, 4, 1) \
|
||||
F(WasmIndirectCallCheckSignatureAndGetTargetInstance, 3, 1) \
|
||||
F(WasmIndirectCallGetTargetAddress, 2, 1) \
|
||||
F(WasmIsValidAnyFuncValue, 1, 1) \
|
||||
#define FOR_EACH_INTRINSIC_WASM(F, I) \
|
||||
F(ThrowWasmError, 1, 1) \
|
||||
F(ThrowWasmStackOverflow, 0, 1) \
|
||||
F(WasmI32AtomicWait, 4, 1) \
|
||||
F(WasmI64AtomicWait, 5, 1) \
|
||||
F(WasmAtomicNotify, 3, 1) \
|
||||
F(WasmExceptionGetValues, 1, 1) \
|
||||
F(WasmExceptionGetTag, 1, 1) \
|
||||
F(WasmMemoryGrow, 2, 1) \
|
||||
F(WasmRunInterpreter, 2, 1) \
|
||||
F(WasmStackGuard, 0, 1) \
|
||||
F(WasmThrowCreate, 2, 1) \
|
||||
F(WasmThrowTypeError, 0, 1) \
|
||||
F(WasmRefFunc, 1, 1) \
|
||||
F(WasmFunctionTableGet, 3, 1) \
|
||||
F(WasmFunctionTableSet, 4, 1) \
|
||||
F(WasmTableInit, 5, 1) \
|
||||
F(WasmTableCopy, 5, 1) \
|
||||
F(WasmTableGrow, 3, 1) \
|
||||
F(WasmTableFill, 4, 1) \
|
||||
F(WasmIsValidAnyFuncValue, 1, 1) \
|
||||
F(WasmCompileLazy, 2, 1)
|
||||
|
||||
#define FOR_EACH_INTRINSIC_RETURN_PAIR_IMPL(F, I) \
|
||||
|
@ -178,7 +178,7 @@ class InstanceBuilder {
|
||||
|
||||
// Initialize imported tables of type anyfunc.
|
||||
bool InitializeImportedIndirectFunctionTable(
|
||||
Handle<WasmInstanceObject> instance, int import_index,
|
||||
Handle<WasmInstanceObject> instance, int table_index, int import_index,
|
||||
Handle<WasmTableObject> table_object);
|
||||
|
||||
// Process a single imported table.
|
||||
@ -231,7 +231,7 @@ class InstanceBuilder {
|
||||
// and globals.
|
||||
void ProcessExports(Handle<WasmInstanceObject> instance);
|
||||
|
||||
void InitializeIndirectFunctionTable(Handle<WasmInstanceObject> instance);
|
||||
void InitializeIndirectFunctionTables(Handle<WasmInstanceObject> instance);
|
||||
|
||||
void LoadTableSegments(Handle<WasmInstanceObject> instance);
|
||||
|
||||
@ -437,7 +437,7 @@ MaybeHandle<WasmInstanceObject> InstanceBuilder::Build() {
|
||||
// Initialize the indirect tables.
|
||||
//--------------------------------------------------------------------------
|
||||
if (table_count > 0) {
|
||||
InitializeIndirectFunctionTable(instance);
|
||||
InitializeIndirectFunctionTables(instance);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
@ -895,14 +895,12 @@ bool InstanceBuilder::ProcessImportedFunction(
|
||||
}
|
||||
|
||||
bool InstanceBuilder::InitializeImportedIndirectFunctionTable(
|
||||
Handle<WasmInstanceObject> instance, int import_index,
|
||||
Handle<WasmInstanceObject> instance, int table_index, int import_index,
|
||||
Handle<WasmTableObject> table_object) {
|
||||
int imported_table_size = table_object->entries().length();
|
||||
// Allocate a new dispatch table.
|
||||
if (!instance->has_indirect_function_table()) {
|
||||
WasmInstanceObject::EnsureIndirectFunctionTableWithMinimumSize(
|
||||
instance, imported_table_size);
|
||||
}
|
||||
WasmInstanceObject::EnsureIndirectFunctionTableWithMinimumSize(
|
||||
instance, table_index, imported_table_size);
|
||||
// Initialize the dispatch table with the (foreign) JS functions
|
||||
// that are already in the table.
|
||||
for (int i = 0; i < imported_table_size; ++i) {
|
||||
@ -922,8 +920,8 @@ bool InstanceBuilder::InitializeImportedIndirectFunctionTable(
|
||||
if (is_null) continue;
|
||||
Handle<WasmJSFunction> js_function;
|
||||
if (maybe_js_function.ToHandle(&js_function)) {
|
||||
WasmInstanceObject::ImportWasmJSFunctionIntoTable(isolate_, instance, i,
|
||||
js_function);
|
||||
WasmInstanceObject::ImportWasmJSFunctionIntoTable(
|
||||
isolate_, instance, table_index, i, js_function);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -937,7 +935,7 @@ bool InstanceBuilder::InitializeImportedIndirectFunctionTable(
|
||||
// Look up the signature's canonical id. If there is no canonical
|
||||
// id, then the signature does not appear at all in this module,
|
||||
// so putting {-1} in the table will cause checks to always fail.
|
||||
IndirectFunctionTableEntry(instance, i)
|
||||
IndirectFunctionTableEntry(instance, table_index, i)
|
||||
.Set(module_->signature_map.Find(*sig), target_instance,
|
||||
function_index);
|
||||
}
|
||||
@ -992,10 +990,9 @@ bool InstanceBuilder::ProcessImportedTable(Handle<WasmInstanceObject> instance,
|
||||
return false;
|
||||
}
|
||||
|
||||
// The indirect function table only exists for table 0.
|
||||
if (table.type == kWasmAnyFunc && table_index == 0 &&
|
||||
!InitializeImportedIndirectFunctionTable(instance, import_index,
|
||||
table_object)) {
|
||||
if (table.type == kWasmAnyFunc &&
|
||||
!InitializeImportedIndirectFunctionTable(instance, table_index,
|
||||
import_index, table_object)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1609,15 +1606,15 @@ void InstanceBuilder::ProcessExports(Handle<WasmInstanceObject> instance) {
|
||||
}
|
||||
}
|
||||
|
||||
void InstanceBuilder::InitializeIndirectFunctionTable(
|
||||
void InstanceBuilder::InitializeIndirectFunctionTables(
|
||||
Handle<WasmInstanceObject> instance) {
|
||||
DCHECK_GT(module_->tables.size(), 0);
|
||||
for (int i = 0; i < static_cast<int>(module_->tables.size()); ++i) {
|
||||
const WasmTable& table = module_->tables[i];
|
||||
|
||||
const WasmTable& table = module_->tables[0];
|
||||
|
||||
if (!instance->has_indirect_function_table() && table.type == kWasmAnyFunc) {
|
||||
WasmInstanceObject::EnsureIndirectFunctionTableWithMinimumSize(
|
||||
instance, table.initial_size);
|
||||
if (table.type == kWasmAnyFunc) {
|
||||
WasmInstanceObject::EnsureIndirectFunctionTableWithMinimumSize(
|
||||
instance, i, table.initial_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1640,7 +1637,9 @@ bool LoadElemSegmentImpl(Isolate* isolate, Handle<WasmInstanceObject> instance,
|
||||
|
||||
if (func_index == WasmElemSegment::kNullIndex) {
|
||||
if (table_object->type() == kWasmAnyFunc) {
|
||||
IndirectFunctionTableEntry(instance, entry_index).clear();
|
||||
IndirectFunctionTableEntry(instance, elem_segment.table_index,
|
||||
entry_index)
|
||||
.clear();
|
||||
}
|
||||
WasmTableObject::Set(isolate, table_object, entry_index,
|
||||
isolate->factory()->null_value());
|
||||
@ -1649,13 +1648,11 @@ bool LoadElemSegmentImpl(Isolate* isolate, Handle<WasmInstanceObject> instance,
|
||||
|
||||
const WasmFunction* function = &module->functions[func_index];
|
||||
|
||||
// Update the local dispatch table first if necessary. We only have to
|
||||
// update the dispatch table if the first table of the instance is changed.
|
||||
// For all other tables, function calls do not use a dispatch table at
|
||||
// the moment.
|
||||
if (elem_segment.table_index == 0 && table_object->type() == kWasmAnyFunc) {
|
||||
// Update the local dispatch table first if necessary.
|
||||
if (table_object->type() == kWasmAnyFunc) {
|
||||
uint32_t sig_id = module->signature_ids[function->sig_index];
|
||||
IndirectFunctionTableEntry(instance, entry_index)
|
||||
IndirectFunctionTableEntry(instance, elem_segment.table_index,
|
||||
entry_index)
|
||||
.Set(sig_id, instance, func_index);
|
||||
}
|
||||
|
||||
|
@ -3687,7 +3687,7 @@ class ThreadImpl {
|
||||
return {ExternalCallResult::INVALID_FUNC};
|
||||
}
|
||||
|
||||
IndirectFunctionTableEntry entry(instance_object_, entry_index);
|
||||
IndirectFunctionTableEntry entry(instance_object_, 0, entry_index);
|
||||
// Signature check.
|
||||
if (entry.sig_id() != static_cast<int32_t>(expected_sig_id)) {
|
||||
return {ExternalCallResult::SIGNATURE_MISMATCH};
|
||||
|
@ -267,10 +267,6 @@ ACCESSORS(WasmInstanceObject, centry_stub, Code, kCEntryStubOffset)
|
||||
OPTIONAL_ACCESSORS(WasmInstanceObject, wasm_exported_functions, FixedArray,
|
||||
kWasmExportedFunctionsOffset)
|
||||
|
||||
inline bool WasmInstanceObject::has_indirect_function_table() {
|
||||
return indirect_function_table_sig_ids() != nullptr;
|
||||
}
|
||||
|
||||
void WasmInstanceObject::clear_padding() {
|
||||
if (FIELD_SIZE(kOptionalPaddingOffset) != 0) {
|
||||
DCHECK_EQ(4, FIELD_SIZE(kOptionalPaddingOffset));
|
||||
@ -280,10 +276,29 @@ void WasmInstanceObject::clear_padding() {
|
||||
}
|
||||
|
||||
IndirectFunctionTableEntry::IndirectFunctionTableEntry(
|
||||
Handle<WasmInstanceObject> instance, int index)
|
||||
: instance_(instance), index_(index) {
|
||||
DCHECK_GE(index, 0);
|
||||
DCHECK_LT(index, instance->indirect_function_table_size());
|
||||
Handle<WasmInstanceObject> instance, int table_index, int entry_index)
|
||||
: instance_(table_index == 0 ? instance
|
||||
: Handle<WasmInstanceObject>::null()),
|
||||
table_(table_index != 0
|
||||
? handle(WasmIndirectFunctionTable::cast(
|
||||
instance->indirect_function_tables().get(
|
||||
table_index)),
|
||||
instance->GetIsolate())
|
||||
: Handle<WasmIndirectFunctionTable>::null()),
|
||||
index_(entry_index) {
|
||||
DCHECK_GE(entry_index, 0);
|
||||
DCHECK_LT(entry_index, table_index == 0
|
||||
? instance->indirect_function_table_size()
|
||||
: table_->size());
|
||||
}
|
||||
|
||||
IndirectFunctionTableEntry::IndirectFunctionTableEntry(
|
||||
Handle<WasmIndirectFunctionTable> table, int entry_index)
|
||||
: instance_(Handle<WasmInstanceObject>::null()),
|
||||
table_(table),
|
||||
index_(entry_index) {
|
||||
DCHECK_GE(entry_index, 0);
|
||||
DCHECK_LT(entry_index, table_->size());
|
||||
}
|
||||
|
||||
ImportedFunctionEntry::ImportedFunctionEntry(
|
||||
|
@ -139,7 +139,9 @@ class WasmInstanceNativeAllocations {
|
||||
|
||||
instance->set_indirect_function_table_refs(*new_refs);
|
||||
for (uint32_t j = old_size; j < new_size; j++) {
|
||||
IndirectFunctionTableEntry(instance, static_cast<int>(j)).clear();
|
||||
// {WasmInstanceNativeAllocations} only manages the memory of table 0.
|
||||
// Therefore we pass the {table_index} as a constant here.
|
||||
IndirectFunctionTableEntry(instance, 0, static_cast<int>(j)).clear();
|
||||
}
|
||||
}
|
||||
uint32_t* indirect_function_table_sig_ids_ = nullptr;
|
||||
@ -867,15 +869,14 @@ int WasmTableObject::Grow(Isolate* isolate, Handle<WasmTableObject> table,
|
||||
i += kDispatchTableNumElements) {
|
||||
int table_index =
|
||||
Smi::cast(dispatch_tables->get(i + kDispatchTableIndexOffset)).value();
|
||||
if (table_index > 0) {
|
||||
continue;
|
||||
}
|
||||
// For Table 0 we have to update the indirect function table.
|
||||
|
||||
Handle<WasmInstanceObject> instance(
|
||||
WasmInstanceObject::cast(dispatch_tables->get(i)), isolate);
|
||||
DCHECK_EQ(old_size, instance->indirect_function_table_size());
|
||||
WasmInstanceObject::EnsureIndirectFunctionTableWithMinimumSize(instance,
|
||||
new_size);
|
||||
|
||||
DCHECK_EQ(old_size, WasmInstanceObject::IndirectFunctionTableSize(
|
||||
isolate, instance, table_index));
|
||||
WasmInstanceObject::EnsureIndirectFunctionTableWithMinimumSize(
|
||||
instance, table_index, new_size);
|
||||
}
|
||||
|
||||
for (uint32_t entry = old_size; entry < new_size; ++entry) {
|
||||
@ -1011,11 +1012,6 @@ void WasmTableObject::UpdateDispatchTables(
|
||||
i += kDispatchTableNumElements) {
|
||||
int table_index =
|
||||
Smi::cast(dispatch_tables->get(i + kDispatchTableIndexOffset)).value();
|
||||
if (table_index > 0) {
|
||||
// Only table 0 has a dispatch table in the instance at the moment.
|
||||
// TODO(ahaas): Introduce dispatch tables for the other tables as well.
|
||||
continue;
|
||||
}
|
||||
Handle<WasmInstanceObject> instance(
|
||||
WasmInstanceObject::cast(
|
||||
dispatch_tables->get(i + kDispatchTableInstanceOffset)),
|
||||
@ -1023,7 +1019,7 @@ void WasmTableObject::UpdateDispatchTables(
|
||||
// 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, entry_index)
|
||||
IndirectFunctionTableEntry(instance, table_index, entry_index)
|
||||
.Set(sig_id, target_instance, target_func_index);
|
||||
}
|
||||
}
|
||||
@ -1041,17 +1037,12 @@ void WasmTableObject::UpdateDispatchTables(Isolate* isolate,
|
||||
i += kDispatchTableNumElements) {
|
||||
int table_index =
|
||||
Smi::cast(dispatch_tables->get(i + kDispatchTableIndexOffset)).value();
|
||||
if (table_index > 0) {
|
||||
// Only table 0 has a dispatch table in the instance at the moment.
|
||||
// TODO(ahaas): Introduce dispatch tables for the other tables as well.
|
||||
continue;
|
||||
}
|
||||
Handle<WasmInstanceObject> instance(
|
||||
WasmInstanceObject::cast(
|
||||
dispatch_tables->get(i + kDispatchTableInstanceOffset)),
|
||||
isolate);
|
||||
WasmInstanceObject::ImportWasmJSFunctionIntoTable(isolate, instance,
|
||||
entry_index, function);
|
||||
WasmInstanceObject::ImportWasmJSFunctionIntoTable(
|
||||
isolate, instance, table_index, entry_index, function);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1085,11 +1076,6 @@ void WasmTableObject::UpdateDispatchTables(
|
||||
i += kDispatchTableNumElements) {
|
||||
int table_index =
|
||||
Smi::cast(dispatch_tables->get(i + kDispatchTableIndexOffset)).value();
|
||||
if (table_index > 0) {
|
||||
// Only table 0 has a dispatch table in the instance at the moment.
|
||||
// TODO(ahaas): Introduce dispatch tables for the other tables as well.
|
||||
continue;
|
||||
}
|
||||
Handle<WasmInstanceObject> instance(
|
||||
WasmInstanceObject::cast(
|
||||
dispatch_tables->get(i + kDispatchTableInstanceOffset)),
|
||||
@ -1110,7 +1096,7 @@ void WasmTableObject::UpdateDispatchTables(
|
||||
// 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, entry_index)
|
||||
IndirectFunctionTableEntry(instance, table_index, entry_index)
|
||||
.Set(sig_id, wasm_code->instruction_start(), *tuple);
|
||||
}
|
||||
}
|
||||
@ -1124,16 +1110,13 @@ void WasmTableObject::ClearDispatchTables(Isolate* isolate,
|
||||
i += kDispatchTableNumElements) {
|
||||
int table_index =
|
||||
Smi::cast(dispatch_tables->get(i + kDispatchTableIndexOffset)).value();
|
||||
if (table_index > 0) {
|
||||
// Only table 0 has a dispatch table in the instance at the moment.
|
||||
continue;
|
||||
}
|
||||
Handle<WasmInstanceObject> target_instance(
|
||||
WasmInstanceObject::cast(
|
||||
dispatch_tables->get(i + kDispatchTableInstanceOffset)),
|
||||
isolate);
|
||||
DCHECK_LT(index, target_instance->indirect_function_table_size());
|
||||
IndirectFunctionTableEntry(target_instance, index).clear();
|
||||
DCHECK_LT(index, WasmInstanceObject::IndirectFunctionTableSize(
|
||||
isolate, target_instance, table_index));
|
||||
IndirectFunctionTableEntry(target_instance, table_index, index).clear();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1196,6 +1179,17 @@ class IftNativeAllocations {
|
||||
return size * (sizeof(Address) + sizeof(uint32_t));
|
||||
}
|
||||
|
||||
void resize(Handle<WasmIndirectFunctionTable> table, uint32_t new_size) {
|
||||
DCHECK_GE(new_size, sig_ids_.size());
|
||||
DCHECK_EQ(this, Managed<IftNativeAllocations>::cast(
|
||||
table->managed_native_allocations())
|
||||
.raw());
|
||||
sig_ids_.resize(new_size);
|
||||
targets_.resize(new_size);
|
||||
table->set_sig_ids(sig_ids_.data());
|
||||
table->set_targets(targets_.data());
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<uint32_t> sig_ids_;
|
||||
std::vector<Address> targets_;
|
||||
@ -1212,9 +1206,32 @@ Handle<WasmIndirectFunctionTable> WasmIndirectFunctionTable::New(
|
||||
auto native_allocations = Managed<IftNativeAllocations>::Allocate(
|
||||
isolate, IftNativeAllocations::SizeInMemory(size), table, size);
|
||||
table->set_managed_native_allocations(*native_allocations);
|
||||
for (uint32_t i = 0; i < size; ++i) {
|
||||
IndirectFunctionTableEntry(table, static_cast<int>(i)).clear();
|
||||
}
|
||||
return table;
|
||||
}
|
||||
|
||||
void WasmIndirectFunctionTable::Resize(Isolate* isolate,
|
||||
Handle<WasmIndirectFunctionTable> table,
|
||||
uint32_t new_size) {
|
||||
uint32_t old_size = table->size();
|
||||
if (old_size >= new_size) return; // Nothing to do.
|
||||
|
||||
Managed<IftNativeAllocations>::cast(table->managed_native_allocations())
|
||||
.raw()
|
||||
->resize(table, new_size);
|
||||
|
||||
Handle<FixedArray> old_refs(table->refs(), isolate);
|
||||
Handle<FixedArray> new_refs = isolate->factory()->CopyFixedArrayAndGrow(
|
||||
old_refs, static_cast<int>(new_size - old_size));
|
||||
table->set_refs(*new_refs);
|
||||
table->set_size(new_size);
|
||||
for (uint32_t i = old_size; i < new_size; ++i) {
|
||||
IndirectFunctionTableEntry(table, static_cast<int>(i)).clear();
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
bool AdjustBufferPermissions(Isolate* isolate, Handle<JSArrayBuffer> old_buffer,
|
||||
size_t new_size) {
|
||||
@ -1499,10 +1516,19 @@ MaybeHandle<WasmGlobalObject> WasmGlobalObject::New(
|
||||
}
|
||||
|
||||
void IndirectFunctionTableEntry::clear() {
|
||||
instance_->indirect_function_table_sig_ids()[index_] = -1;
|
||||
instance_->indirect_function_table_targets()[index_] = 0;
|
||||
instance_->indirect_function_table_refs().set(
|
||||
index_, ReadOnlyRoots(instance_->GetIsolate()).undefined_value());
|
||||
if (!instance_.is_null()) {
|
||||
instance_->indirect_function_table_sig_ids()[index_] = -1;
|
||||
instance_->indirect_function_table_targets()[index_] = 0;
|
||||
instance_->indirect_function_table_refs().set(
|
||||
index_, ReadOnlyRoots(instance_->GetIsolate()).undefined_value());
|
||||
} else {
|
||||
DCHECK(!table_.is_null());
|
||||
table_->sig_ids()[index_] = -1;
|
||||
table_->targets()[index_] = 0;
|
||||
table_->refs().set(
|
||||
index_,
|
||||
ReadOnlyRoots(GetIsolateFromWritableObject(*table_)).undefined_value());
|
||||
}
|
||||
}
|
||||
|
||||
void IndirectFunctionTableEntry::Set(int sig_id,
|
||||
@ -1533,21 +1559,34 @@ void IndirectFunctionTableEntry::Set(int sig_id,
|
||||
|
||||
void IndirectFunctionTableEntry::Set(int sig_id, Address call_target,
|
||||
Object ref) {
|
||||
instance_->indirect_function_table_sig_ids()[index_] = sig_id;
|
||||
instance_->indirect_function_table_targets()[index_] = call_target;
|
||||
instance_->indirect_function_table_refs().set(index_, ref);
|
||||
if (!instance_.is_null()) {
|
||||
instance_->indirect_function_table_sig_ids()[index_] = sig_id;
|
||||
instance_->indirect_function_table_targets()[index_] = call_target;
|
||||
instance_->indirect_function_table_refs().set(index_, ref);
|
||||
} else {
|
||||
DCHECK(!table_.is_null());
|
||||
table_->sig_ids()[index_] = sig_id;
|
||||
table_->targets()[index_] = call_target;
|
||||
table_->refs().set(index_, ref);
|
||||
}
|
||||
}
|
||||
|
||||
Object IndirectFunctionTableEntry::object_ref() const {
|
||||
return instance_->indirect_function_table_refs().get(index_);
|
||||
return !instance_.is_null()
|
||||
? instance_->indirect_function_table_refs().get(index_)
|
||||
: table_->refs().get(index_);
|
||||
}
|
||||
|
||||
int IndirectFunctionTableEntry::sig_id() const {
|
||||
return instance_->indirect_function_table_sig_ids()[index_];
|
||||
return !instance_.is_null()
|
||||
? instance_->indirect_function_table_sig_ids()[index_]
|
||||
: table_->sig_ids()[index_];
|
||||
}
|
||||
|
||||
Address IndirectFunctionTableEntry::target() const {
|
||||
return instance_->indirect_function_table_targets()[index_];
|
||||
return !instance_.is_null()
|
||||
? instance_->indirect_function_table_targets()[index_]
|
||||
: table_->targets()[index_];
|
||||
}
|
||||
|
||||
void IndirectFunctionTableEntry::CopyFrom(
|
||||
@ -1608,11 +1647,21 @@ constexpr uint16_t WasmInstanceObject::kTaggedFieldOffsets[];
|
||||
|
||||
// static
|
||||
bool WasmInstanceObject::EnsureIndirectFunctionTableWithMinimumSize(
|
||||
Handle<WasmInstanceObject> instance, uint32_t minimum_size) {
|
||||
Handle<WasmInstanceObject> instance, int table_index,
|
||||
uint32_t minimum_size) {
|
||||
Isolate* isolate = instance->GetIsolate();
|
||||
if (table_index > 0) {
|
||||
DCHECK_LT(table_index, instance->indirect_function_tables().length());
|
||||
auto table =
|
||||
handle(WasmIndirectFunctionTable::cast(
|
||||
instance->indirect_function_tables().get(table_index)),
|
||||
isolate);
|
||||
WasmIndirectFunctionTable::Resize(isolate, table, minimum_size);
|
||||
return true;
|
||||
}
|
||||
uint32_t old_size = instance->indirect_function_table_size();
|
||||
if (old_size >= minimum_size) return false; // Nothing to do.
|
||||
|
||||
Isolate* isolate = instance->GetIsolate();
|
||||
HandleScope scope(isolate);
|
||||
auto native_allocations = GetNativeAllocations(*instance);
|
||||
native_allocations->resize_indirect_function_table(isolate, instance,
|
||||
@ -1768,20 +1817,37 @@ Address WasmInstanceObject::GetCallTarget(uint32_t func_index) {
|
||||
return native_module->GetCallTargetForFunction(func_index);
|
||||
}
|
||||
|
||||
int WasmInstanceObject::IndirectFunctionTableSize(
|
||||
Isolate* isolate, Handle<WasmInstanceObject> instance,
|
||||
uint32_t table_index) {
|
||||
if (table_index == 0) {
|
||||
return instance->indirect_function_table_size();
|
||||
}
|
||||
auto table =
|
||||
handle(WasmIndirectFunctionTable::cast(
|
||||
instance->indirect_function_tables().get(table_index)),
|
||||
isolate);
|
||||
return table->size();
|
||||
}
|
||||
|
||||
namespace {
|
||||
void CopyTableEntriesImpl(Handle<WasmInstanceObject> instance, uint32_t dst,
|
||||
uint32_t src, uint32_t count, bool copy_backward) {
|
||||
DCHECK(IsInBounds(dst, count, instance->indirect_function_table_size()));
|
||||
if (copy_backward) {
|
||||
for (uint32_t i = count; i > 0; i--) {
|
||||
auto to_entry = IndirectFunctionTableEntry(instance, dst + i - 1);
|
||||
auto from_entry = IndirectFunctionTableEntry(instance, src + i - 1);
|
||||
// TODO(ahaas): Use a table index here once table.copy supports multiple
|
||||
// tables.
|
||||
auto to_entry = IndirectFunctionTableEntry(instance, 0, dst + i - 1);
|
||||
auto from_entry = IndirectFunctionTableEntry(instance, 0, src + i - 1);
|
||||
to_entry.CopyFrom(from_entry);
|
||||
}
|
||||
} else {
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
auto to_entry = IndirectFunctionTableEntry(instance, dst + i);
|
||||
auto from_entry = IndirectFunctionTableEntry(instance, src + i);
|
||||
// TODO(ahaas): Use a table index here once table.copy supports multiple
|
||||
// tables.
|
||||
auto to_entry = IndirectFunctionTableEntry(instance, 0, dst + i);
|
||||
auto from_entry = IndirectFunctionTableEntry(instance, 0, src + i);
|
||||
to_entry.CopyFrom(from_entry);
|
||||
}
|
||||
}
|
||||
@ -1934,7 +2000,7 @@ void WasmInstanceObject::SetWasmExportedFunction(
|
||||
// static
|
||||
void WasmInstanceObject::ImportWasmJSFunctionIntoTable(
|
||||
Isolate* isolate, Handle<WasmInstanceObject> instance, int table_index,
|
||||
Handle<WasmJSFunction> js_function) {
|
||||
int entry_index, Handle<WasmJSFunction> js_function) {
|
||||
// Deserialize the signature encapsulated with the {WasmJSFunction}.
|
||||
// Note that {SignatureMap::Find} may return {-1} if the signature is
|
||||
// not found; it will simply never match any check.
|
||||
@ -1974,7 +2040,7 @@ void WasmInstanceObject::ImportWasmJSFunctionIntoTable(
|
||||
// Update the dispatch table.
|
||||
Handle<Tuple2> tuple =
|
||||
isolate->factory()->NewTuple2(instance, callable, AllocationType::kOld);
|
||||
IndirectFunctionTableEntry(instance, table_index)
|
||||
IndirectFunctionTableEntry(instance, table_index, entry_index)
|
||||
.Set(sig_id, call_target, *tuple);
|
||||
}
|
||||
|
||||
|
@ -44,6 +44,7 @@ class WasmExportedFunction;
|
||||
class WasmInstanceObject;
|
||||
class WasmJSFunction;
|
||||
class WasmModuleObject;
|
||||
class WasmIndirectFunctionTable;
|
||||
|
||||
template <class CppType>
|
||||
class Managed;
|
||||
@ -61,7 +62,11 @@ class Managed;
|
||||
// - target = entrypoint to Wasm code or import wrapper code
|
||||
class IndirectFunctionTableEntry {
|
||||
public:
|
||||
inline IndirectFunctionTableEntry(Handle<WasmInstanceObject>, int index);
|
||||
inline IndirectFunctionTableEntry(Handle<WasmInstanceObject>, int table_index,
|
||||
int entry_index);
|
||||
|
||||
inline IndirectFunctionTableEntry(Handle<WasmIndirectFunctionTable> table,
|
||||
int entry_index);
|
||||
|
||||
void clear();
|
||||
V8_EXPORT_PRIVATE void Set(int sig_id,
|
||||
@ -77,6 +82,7 @@ class IndirectFunctionTableEntry {
|
||||
|
||||
private:
|
||||
Handle<WasmInstanceObject> const instance_;
|
||||
Handle<WasmIndirectFunctionTable> const table_;
|
||||
int const index_;
|
||||
};
|
||||
|
||||
@ -552,9 +558,8 @@ class WasmInstanceObject : public JSObject {
|
||||
V8_EXPORT_PRIVATE const wasm::WasmModule* module();
|
||||
|
||||
V8_EXPORT_PRIVATE static bool EnsureIndirectFunctionTableWithMinimumSize(
|
||||
Handle<WasmInstanceObject> instance, uint32_t minimum_size);
|
||||
|
||||
bool has_indirect_function_table();
|
||||
Handle<WasmInstanceObject> instance, int table_index,
|
||||
uint32_t minimum_size);
|
||||
|
||||
V8_EXPORT_PRIVATE void SetRawMemory(byte* mem_start, size_t mem_size);
|
||||
|
||||
@ -568,6 +573,10 @@ class WasmInstanceObject : public JSObject {
|
||||
|
||||
Address GetCallTarget(uint32_t func_index);
|
||||
|
||||
static int IndirectFunctionTableSize(Isolate* isolate,
|
||||
Handle<WasmInstanceObject> instance,
|
||||
uint32_t table_index);
|
||||
|
||||
// Copies table entries. Returns {false} if the ranges are out-of-bounds.
|
||||
static bool CopyTableEntries(Isolate* isolate,
|
||||
Handle<WasmInstanceObject> instance,
|
||||
@ -609,7 +618,7 @@ class WasmInstanceObject : public JSObject {
|
||||
// {WasmJSFunction} is instance-independent and just wraps a JS callable.
|
||||
static void ImportWasmJSFunctionIntoTable(Isolate* isolate,
|
||||
Handle<WasmInstanceObject> instance,
|
||||
int table_index,
|
||||
int table_index, int entry_index,
|
||||
Handle<WasmJSFunction> js_function);
|
||||
|
||||
OBJECT_CONSTRUCTORS(WasmInstanceObject, JSObject);
|
||||
@ -734,6 +743,8 @@ class WasmIndirectFunctionTable : public Struct {
|
||||
DECL_ACCESSORS(refs, FixedArray)
|
||||
|
||||
static Handle<WasmIndirectFunctionTable> New(Isolate* isolate, uint32_t size);
|
||||
static void Resize(Isolate* isolate, Handle<WasmIndirectFunctionTable> table,
|
||||
uint32_t new_size);
|
||||
|
||||
DECL_CAST(WasmIndirectFunctionTable)
|
||||
|
||||
|
@ -172,7 +172,7 @@ void TestingModuleBuilder::AddIndirectFunctionTable(
|
||||
table.has_maximum_size = true;
|
||||
table.type = kWasmAnyFunc;
|
||||
WasmInstanceObject::EnsureIndirectFunctionTableWithMinimumSize(
|
||||
instance_object(), table_size);
|
||||
instance_object(), 0, table_size);
|
||||
Handle<WasmTableObject> table_obj =
|
||||
WasmTableObject::New(isolate_, table.type, table.initial_size,
|
||||
table.has_maximum_size, table.maximum_size, nullptr);
|
||||
@ -184,7 +184,7 @@ void TestingModuleBuilder::AddIndirectFunctionTable(
|
||||
for (uint32_t i = 0; i < table_size; ++i) {
|
||||
WasmFunction& function = test_module_->functions[function_indexes[i]];
|
||||
int sig_id = test_module_->signature_map.Find(*function.sig);
|
||||
IndirectFunctionTableEntry(instance, i)
|
||||
IndirectFunctionTableEntry(instance, 0, i)
|
||||
.Set(sig_id, instance, function.func_index);
|
||||
WasmTableObject::SetFunctionTablePlaceholder(
|
||||
isolate_, table_obj, i, instance_object_, function_indexes[i]);
|
||||
|
Loading…
Reference in New Issue
Block a user