Commit 2fe2a08b authored by Andreas Haas's avatar Andreas Haas Committed by Commit Bot

[wasm] Introduce WasmIndirectFunctionTable

This is the first of three CLs which refactors 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=jkummerow@chromium.org

Bug: v8:7581
Change-Id: I0ecfcb9565e992ddba087d46c1f0e952abfa5822
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1681134Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Commit-Queue: Andreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#62492}
parent 8d797820
......@@ -928,6 +928,16 @@ extern class WasmCapiFunctionData extends Struct {
serialized_signature: ByteArray; // PodArray<wasm::ValueType>
}
extern class WasmIndirectFunctionTable extends Struct {
size: uint32;
@if(TAGGED_SIZE_8_BYTES) optional_padding: uint32;
@ifnot(TAGGED_SIZE_8_BYTES) optional_padding: void;
sig_ids: RawPtr;
targets: RawPtr;
managed_native_allocations: Foreign | Undefined;
refs: FixedArray;
}
extern class WasmDebugInfo extends Struct {
instance: WasmInstanceObject;
interpreter_handle: Foreign | Undefined;
......
......@@ -338,6 +338,7 @@ class WasmExceptionObject;
class WasmExceptionTag;
class WasmExportedFunctionData;
class WasmGlobalObject;
class WasmIndirectFunctionTable;
class WasmJSFunctionData;
class WasmMemoryObject;
class WasmModuleObject;
......
......@@ -6,9 +6,10 @@
#include "src/compiler/types.h"
#include "src/utils/ostreams.h"
#include "src/handles/handles-inl.h"
#include "src/objects/instance-type.h"
#include "src/objects/objects-inl.h"
#include "src/utils/ostreams.h"
namespace v8 {
namespace internal {
......@@ -350,6 +351,7 @@ Type::bitset BitsetType::Lub(const MapRefLike& map) {
case ENUM_CACHE_TYPE:
case SOURCE_POSITION_TABLE_WITH_FRAME_CACHE_TYPE:
case WASM_CAPI_FUNCTION_DATA_TYPE:
case WASM_INDIRECT_FUNCTION_TABLE_TYPE:
case WASM_DEBUG_INFO_TYPE:
case WASM_EXCEPTION_TAG_TYPE:
case WASM_EXPORTED_FUNCTION_DATA_TYPE:
......
......@@ -1748,6 +1748,8 @@ USE_TORQUE_VERIFIER(WasmCapiFunctionData)
USE_TORQUE_VERIFIER(WasmJSFunctionData)
USE_TORQUE_VERIFIER(WasmIndirectFunctionTable)
USE_TORQUE_VERIFIER(ObjectTemplateInfo)
void AllocationSite::AllocationSiteVerify(Isolate* isolate) {
......
......@@ -2071,6 +2071,20 @@ void WasmCapiFunctionData::WasmCapiFunctionDataPrint(
os << "\n";
}
void WasmIndirectFunctionTable::WasmIndirectFunctionTablePrint(
std::ostream& os) {
PrintHeader(os, "WasmIndirectFunctionTable");
os << "\n - size: " << size();
os << "\n - sig_ids: " << static_cast<void*>(sig_ids());
os << "\n - targets: " << static_cast<void*>(targets());
if (has_managed_native_allocations()) {
os << "\n - managed_native_allocations: "
<< Brief(managed_native_allocations());
}
os << "\n - refs: " << Brief(refs());
os << "\n";
}
void ObjectTemplateInfo::ObjectTemplateInfoPrint(std::ostream& os) { // NOLINT
PrintHeader(os, "ObjectTemplateInfo");
os << "\n - tag: " << Brief(tag());
......
......@@ -62,6 +62,7 @@ namespace internal {
V(UncompiledDataWithoutPreparseData, UncompiledDataWithoutPreparseData) \
V(UncompiledDataWithPreparseData, UncompiledDataWithPreparseData) \
V(WasmCapiFunctionData, WasmCapiFunctionData) \
V(WasmIndirectFunctionTable, WasmIndirectFunctionTable) \
V(WasmInstanceObject, WasmInstanceObject)
#define FORWARD_DECLARE(TypeName, Type) class Type;
......
......@@ -143,6 +143,7 @@ enum InstanceType : uint16_t {
ACCESSOR_PAIR_TYPE,
ALIASED_ARGUMENTS_ENTRY_TYPE,
ALLOCATION_MEMENTO_TYPE,
ARRAY_BOILERPLATE_DESCRIPTION_TYPE,
ASM_WASM_DATA_TYPE,
ASYNC_GENERATOR_REQUEST_TYPE,
CLASS_POSITIONS_TYPE,
......@@ -164,11 +165,11 @@ enum InstanceType : uint16_t {
TEMPLATE_OBJECT_DESCRIPTION_TYPE,
TUPLE2_TYPE,
TUPLE3_TYPE,
ARRAY_BOILERPLATE_DESCRIPTION_TYPE,
WASM_CAPI_FUNCTION_DATA_TYPE,
WASM_DEBUG_INFO_TYPE,
WASM_EXCEPTION_TAG_TYPE,
WASM_EXPORTED_FUNCTION_DATA_TYPE,
WASM_INDIRECT_FUNCTION_TABLE_TYPE,
WASM_JS_FUNCTION_DATA_TYPE,
CALLABLE_TASK_TYPE, // FIRST_MICROTASK_TYPE
......
......@@ -352,6 +352,9 @@ VisitorId Map::GetVisitorId(Map map) {
if (instance_type == WASM_CAPI_FUNCTION_DATA_TYPE) {
return kVisitWasmCapiFunctionData;
}
if (instance_type == WASM_INDIRECT_FUNCTION_TABLE_TYPE) {
return kVisitWasmIndirectFunctionTable;
}
return kVisitStruct;
case LOAD_HANDLER_TYPE:
......
......@@ -74,6 +74,7 @@ enum InstanceType : uint16_t;
V(UncompiledDataWithoutPreparseData) \
V(UncompiledDataWithPreparseData) \
V(WasmCapiFunctionData) \
V(WasmIndirectFunctionTable) \
V(WasmInstanceObject) \
V(WeakArray) \
V(WeakCell)
......
......@@ -1045,6 +1045,9 @@ ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3, T4 p4) {
} else if (type == WASM_CAPI_FUNCTION_DATA_TYPE) {
return Op::template apply<WasmCapiFunctionData::BodyDescriptor>(p1, p2,
p3, p4);
} else if (type == WASM_INDIRECT_FUNCTION_TABLE_TYPE) {
return Op::template apply<WasmIndirectFunctionTable::BodyDescriptor>(
p1, p2, p3, p4);
} else {
return Op::template apply<StructBodyDescriptor>(p1, p2, p3, p4);
}
......
......@@ -82,6 +82,7 @@ namespace internal {
V(ACCESSOR_PAIR_TYPE) \
V(ALIASED_ARGUMENTS_ENTRY_TYPE) \
V(ALLOCATION_MEMENTO_TYPE) \
V(ARRAY_BOILERPLATE_DESCRIPTION_TYPE) \
V(ASM_WASM_DATA_TYPE) \
V(ASYNC_GENERATOR_REQUEST_TYPE) \
V(CLASS_POSITIONS_TYPE) \
......@@ -103,11 +104,11 @@ namespace internal {
V(TEMPLATE_OBJECT_DESCRIPTION_TYPE) \
V(TUPLE2_TYPE) \
V(TUPLE3_TYPE) \
V(ARRAY_BOILERPLATE_DESCRIPTION_TYPE) \
V(WASM_CAPI_FUNCTION_DATA_TYPE) \
V(WASM_DEBUG_INFO_TYPE) \
V(WASM_EXCEPTION_TAG_TYPE) \
V(WASM_EXPORTED_FUNCTION_DATA_TYPE) \
V(WASM_INDIRECT_FUNCTION_TABLE_TYPE) \
V(WASM_JS_FUNCTION_DATA_TYPE) \
\
V(CALLABLE_TASK_TYPE) \
......@@ -302,6 +303,8 @@ namespace internal {
V(_, ALIASED_ARGUMENTS_ENTRY_TYPE, AliasedArgumentsEntry, \
aliased_arguments_entry) \
V(_, ALLOCATION_MEMENTO_TYPE, AllocationMemento, allocation_memento) \
V(_, ARRAY_BOILERPLATE_DESCRIPTION_TYPE, ArrayBoilerplateDescription, \
array_boilerplate_description) \
V(_, ASM_WASM_DATA_TYPE, AsmWasmData, asm_wasm_data) \
V(_, ASYNC_GENERATOR_REQUEST_TYPE, AsyncGeneratorRequest, \
async_generator_request) \
......@@ -329,14 +332,14 @@ namespace internal {
template_object_description) \
V(_, TUPLE2_TYPE, Tuple2, tuple2) \
V(_, TUPLE3_TYPE, Tuple3, tuple3) \
V(_, ARRAY_BOILERPLATE_DESCRIPTION_TYPE, ArrayBoilerplateDescription, \
array_boilerplate_description) \
V(_, WASM_CAPI_FUNCTION_DATA_TYPE, WasmCapiFunctionData, \
wasm_capi_function_data) \
V(_, WASM_DEBUG_INFO_TYPE, WasmDebugInfo, wasm_debug_info) \
V(_, WASM_EXCEPTION_TAG_TYPE, WasmExceptionTag, wasm_exception_tag) \
V(_, WASM_EXPORTED_FUNCTION_DATA_TYPE, WasmExportedFunctionData, \
wasm_exported_function_data) \
V(_, WASM_INDIRECT_FUNCTION_TABLE_TYPE, WasmIndirectFunctionTable, \
wasm_indirect_function_table) \
V(_, WASM_JS_FUNCTION_DATA_TYPE, WasmJSFunctionData, wasm_js_function_data) \
V(_, CALLABLE_TASK_TYPE, CallableTask, callable_task) \
V(_, CALLBACK_TASK_TYPE, CallbackTask, callback_task) \
......
......@@ -397,6 +397,7 @@ MaybeHandle<WasmInstanceObject> InstanceBuilder::Build() {
// Set up table storage space.
//--------------------------------------------------------------------------
int table_count = static_cast<int>(module_->tables.size());
{
Handle<FixedArray> tables = isolate_->factory()->NewFixedArray(table_count);
for (int i = module_->num_imported_tables; i < table_count; i++) {
const WasmTable& table = module_->tables[i];
......@@ -406,6 +407,20 @@ MaybeHandle<WasmInstanceObject> InstanceBuilder::Build() {
tables->set(i, *table_obj);
}
instance->set_tables(*tables);
}
{
Handle<FixedArray> tables = isolate_->factory()->NewFixedArray(table_count);
for (int i = 0; i < table_count; ++i) {
const WasmTable& table = module_->tables[i];
if (table.type == kWasmAnyFunc) {
Handle<WasmIndirectFunctionTable> table_obj =
WasmIndirectFunctionTable::New(isolate_, table.initial_size);
tables->set(i, *table_obj);
}
}
instance->set_indirect_function_tables(*tables);
}
//--------------------------------------------------------------------------
// Process the imports for the module.
......
......@@ -251,6 +251,8 @@ OPTIONAL_ACCESSORS(WasmInstanceObject, imported_mutable_globals_buffers,
OPTIONAL_ACCESSORS(WasmInstanceObject, debug_info, WasmDebugInfo,
kDebugInfoOffset)
OPTIONAL_ACCESSORS(WasmInstanceObject, tables, FixedArray, kTablesOffset)
OPTIONAL_ACCESSORS(WasmInstanceObject, indirect_function_tables, FixedArray,
kIndirectFunctionTablesOffset)
ACCESSORS(WasmInstanceObject, imported_function_refs, FixedArray,
kImportedFunctionRefsOffset)
OPTIONAL_ACCESSORS(WasmInstanceObject, indirect_function_table_refs, FixedArray,
......@@ -349,6 +351,18 @@ ACCESSORS(WasmCapiFunctionData, wrapper_code, Code, kWrapperCodeOffset)
ACCESSORS(WasmCapiFunctionData, serialized_signature, PodArray<wasm::ValueType>,
kSerializedSignatureOffset)
// WasmIndirectFunctionTable
OBJECT_CONSTRUCTORS_IMPL(WasmIndirectFunctionTable, Struct)
CAST_ACCESSOR(WasmIndirectFunctionTable)
PRIMITIVE_ACCESSORS(WasmIndirectFunctionTable, size, uint32_t, kSizeOffset)
PRIMITIVE_ACCESSORS(WasmIndirectFunctionTable, sig_ids, uint32_t*,
kSigIdsOffset)
PRIMITIVE_ACCESSORS(WasmIndirectFunctionTable, targets, Address*,
kTargetsOffset)
OPTIONAL_ACCESSORS(WasmIndirectFunctionTable, managed_native_allocations,
Foreign, kManagedNativeAllocationsOffset)
ACCESSORS(WasmIndirectFunctionTable, refs, FixedArray, kRefsOffset)
// WasmDebugInfo
ACCESSORS(WasmDebugInfo, wasm_instance, WasmInstanceObject, kInstanceOffset)
ACCESSORS(WasmDebugInfo, interpreter_handle, Object, kInterpreterHandleOffset)
......
......@@ -1183,6 +1183,38 @@ void WasmTableObject::GetFunctionTableEntry(
*is_valid = false;
}
namespace {
class IftNativeAllocations {
public:
IftNativeAllocations(Handle<WasmIndirectFunctionTable> table, uint32_t size)
: sig_ids_(size), targets_(size) {
table->set_sig_ids(sig_ids_.data());
table->set_targets(targets_.data());
}
static size_t SizeInMemory(uint32_t size) {
return size * (sizeof(Address) + sizeof(uint32_t));
}
private:
std::vector<uint32_t> sig_ids_;
std::vector<Address> targets_;
};
} // namespace
Handle<WasmIndirectFunctionTable> WasmIndirectFunctionTable::New(
Isolate* isolate, uint32_t size) {
auto refs = isolate->factory()->NewFixedArray(static_cast<int>(size));
auto table = Handle<WasmIndirectFunctionTable>::cast(
isolate->factory()->NewStruct(WASM_INDIRECT_FUNCTION_TABLE_TYPE));
table->set_size(size);
table->set_refs(*refs);
auto native_allocations = Managed<IftNativeAllocations>::Allocate(
isolate, IftNativeAllocations::SizeInMemory(size), table, size);
table->set_managed_native_allocations(*native_allocations);
return table;
}
namespace {
bool AdjustBufferPermissions(Isolate* isolate, Handle<JSArrayBuffer> old_buffer,
size_t new_size) {
......
......@@ -435,6 +435,7 @@ class WasmInstanceObject : public JSObject {
DECL_OPTIONAL_ACCESSORS(imported_mutable_globals_buffers, FixedArray)
DECL_OPTIONAL_ACCESSORS(debug_info, WasmDebugInfo)
DECL_OPTIONAL_ACCESSORS(tables, FixedArray)
DECL_OPTIONAL_ACCESSORS(indirect_function_tables, FixedArray)
DECL_ACCESSORS(imported_function_refs, FixedArray)
DECL_OPTIONAL_ACCESSORS(indirect_function_table_refs, FixedArray)
DECL_OPTIONAL_ACCESSORS(managed_native_allocations, Foreign)
......@@ -499,6 +500,7 @@ class WasmInstanceObject : public JSObject {
V(kImportedMutableGlobalsBuffersOffset, kTaggedSize) \
V(kDebugInfoOffset, kTaggedSize) \
V(kTablesOffset, kTaggedSize) \
V(kIndirectFunctionTablesOffset, kTaggedSize) \
V(kManagedNativeAllocationsOffset, kTaggedSize) \
V(kExceptionsTableOffset, kTaggedSize) \
V(kNullValueOffset, kTaggedSize) \
......@@ -540,6 +542,7 @@ class WasmInstanceObject : public JSObject {
kImportedMutableGlobalsBuffersOffset,
kDebugInfoOffset,
kTablesOffset,
kIndirectFunctionTablesOffset,
kManagedNativeAllocationsOffset,
kExceptionsTableOffset,
kNullValueOffset,
......@@ -721,6 +724,31 @@ class WasmCapiFunction : public JSFunction {
OBJECT_CONSTRUCTORS(WasmCapiFunction, JSFunction);
};
class WasmIndirectFunctionTable : public Struct {
public:
DECL_PRIMITIVE_ACCESSORS(size, uint32_t)
DECL_PRIMITIVE_ACCESSORS(sig_ids, uint32_t*)
DECL_PRIMITIVE_ACCESSORS(targets, Address*)
DECL_OPTIONAL_ACCESSORS(managed_native_allocations, Foreign)
DECL_ACCESSORS(refs, FixedArray)
static Handle<WasmIndirectFunctionTable> New(Isolate* isolate, uint32_t size);
DECL_CAST(WasmIndirectFunctionTable)
DECL_PRINTER(WasmIndirectFunctionTable)
DECL_VERIFIER(WasmIndirectFunctionTable)
DEFINE_FIELD_OFFSET_CONSTANTS(
HeapObject::kHeaderSize,
TORQUE_GENERATED_WASM_INDIRECT_FUNCTION_TABLE_FIELDS)
STATIC_ASSERT(kStartOfStrongFieldsOffset == kManagedNativeAllocationsOffset);
using BodyDescriptor = FlexibleBodyDescriptor<kStartOfStrongFieldsOffset>;
OBJECT_CONSTRUCTORS(WasmIndirectFunctionTable, Struct);
};
class WasmCapiFunctionData : public Struct {
public:
DECL_PRIMITIVE_ACCESSORS(call_target, Address)
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment