Commit 553e70b9 authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

[wasm] Merge function table and signature table

Both tables are always updated together and are always accessed
together. Thus merge them, reducing code complexity, but also code
space and overhead for accessing them during runtime. Instead of two
weak global handles, we only need one, which also means one less load
for each indirect call.
Merging them also improves cache locality, since signature and code
address are not stored next to each other in memory, so they will very
likely end up in the same cache line.

R=titzer@chromium.org

Change-Id: I862df7de93a98aa602a3895796610c2c520d6f21
Reviewed-on: https://chromium-review.googlesource.com/866868
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Reviewed-by: 's avatarBen Titzer <titzer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50623}
parent 0dddc6fd
...@@ -88,9 +88,7 @@ WasmGraphBuilder::WasmGraphBuilder( ...@@ -88,9 +88,7 @@ WasmGraphBuilder::WasmGraphBuilder(
jsgraph_(jsgraph), jsgraph_(jsgraph),
centry_stub_node_(jsgraph_->HeapConstant(centry_stub)), centry_stub_node_(jsgraph_->HeapConstant(centry_stub)),
env_(env), env_(env),
signature_tables_(zone),
function_tables_(zone), function_tables_(zone),
function_table_sizes_(zone),
cur_buffer_(def_buffer_), cur_buffer_(def_buffer_),
cur_bufsize_(kDefaultBufferSize), cur_bufsize_(kDefaultBufferSize),
has_simd_(ContainsSimd(sig)), has_simd_(ContainsSimd(sig)),
...@@ -2425,45 +2423,39 @@ Node* WasmGraphBuilder::CallIndirect(uint32_t sig_index, Node** args, ...@@ -2425,45 +2423,39 @@ Node* WasmGraphBuilder::CallIndirect(uint32_t sig_index, Node** args,
Node* key = args[0]; Node* key = args[0];
// Bounds check against the table size. // Bounds check against the table size.
Node* size = function_table_sizes_[table_index]; Node* size = function_tables_[table_index].size;
Node* in_bounds = graph()->NewNode(machine->Uint32LessThan(), key, size); Node* in_bounds = graph()->NewNode(machine->Uint32LessThan(), key, size);
TrapIfFalse(wasm::kTrapFuncInvalid, in_bounds, position); TrapIfFalse(wasm::kTrapFuncInvalid, in_bounds, position);
Node* table_address = function_tables_[table_index]; Node* table_address = function_tables_[table_index].table_addr;
Node* table = graph()->NewNode( Node* table = graph()->NewNode(
jsgraph()->machine()->Load(MachineType::AnyTagged()), table_address, jsgraph()->machine()->Load(MachineType::AnyTagged()), table_address,
jsgraph()->IntPtrConstant(0), *effect_, *control_); jsgraph()->IntPtrConstant(0), *effect_, *control_);
Node* signatures_address = signature_tables_[table_index];
Node* signatures = graph()->NewNode(
jsgraph()->machine()->Load(MachineType::AnyTagged()), signatures_address,
jsgraph()->IntPtrConstant(0), *effect_, *control_);
// Load signature from the table and check. // Load signature from the table and check.
// The table is a FixedArray; signatures are encoded as SMIs. // The table is a FixedArray; signatures are encoded as SMIs.
// [sig1, sig2, sig3, ...., code1, code2, code3 ...] // [sig1, code1, sig2, code2, sig3, code3, ...]
static_assert(compiler::kFunctionTableEntrySize == 2, "consistency");
static_assert(compiler::kFunctionTableSignatureOffset == 0, "consistency");
static_assert(compiler::kFunctionTableCodeOffset == 1, "consistency");
ElementAccess access = AccessBuilder::ForFixedArrayElement(); ElementAccess access = AccessBuilder::ForFixedArrayElement();
const int fixed_offset = access.header_size - access.tag(); const int fixed_offset = access.header_size - access.tag();
{ Node* key_offset = graph()->NewNode(machine->Word32Shl(), key,
Node* load_sig = graph()->NewNode( Int32Constant(kPointerSizeLog2 + 1));
machine->Load(MachineType::AnyTagged()), signatures, Node* load_sig =
graph()->NewNode(machine->Int32Add(), graph()->NewNode(machine->Load(MachineType::AnyTagged()), table,
graph()->NewNode(machine->Word32Shl(), key, graph()->NewNode(machine->Int32Add(), key_offset,
Int32Constant(kPointerSizeLog2)),
Int32Constant(fixed_offset)), Int32Constant(fixed_offset)),
*effect_, *control_); *effect_, *control_);
int32_t canonical_sig_num = env_->module->signature_ids[sig_index]; int32_t canonical_sig_num = env_->module->signature_ids[sig_index];
CHECK_GE(sig_index, 0); CHECK_GE(sig_index, 0);
Node* sig_match = Node* sig_match = graph()->NewNode(machine->WordEqual(), load_sig,
graph()->NewNode(machine->WordEqual(), load_sig,
jsgraph()->SmiConstant(canonical_sig_num)); jsgraph()->SmiConstant(canonical_sig_num));
TrapIfFalse(wasm::kTrapFuncSigMismatch, sig_match, position); TrapIfFalse(wasm::kTrapFuncSigMismatch, sig_match, position);
}
// Load code object from the table. It is held by a Foreign. // Load code object from the table. It is held by a Foreign.
Node* entry = graph()->NewNode( Node* entry = graph()->NewNode(
machine->Load(MachineType::AnyTagged()), table, machine->Load(MachineType::AnyTagged()), table,
graph()->NewNode(machine->Int32Add(), graph()->NewNode(machine->Int32Add(), key_offset,
graph()->NewNode(machine->Word32Shl(), key, Uint32Constant(fixed_offset + kPointerSize)),
Int32Constant(kPointerSizeLog2)),
Uint32Constant(fixed_offset)),
*effect_, *control_); *effect_, *control_);
if (FLAG_wasm_jit_to_native) { if (FLAG_wasm_jit_to_native) {
Node* address = graph()->NewNode( Node* address = graph()->NewNode(
...@@ -3426,18 +3418,14 @@ void WasmGraphBuilder::EnsureFunctionTableNodes() { ...@@ -3426,18 +3418,14 @@ void WasmGraphBuilder::EnsureFunctionTableNodes() {
for (size_t i = 0; i < tables_size; ++i) { for (size_t i = 0; i < tables_size; ++i) {
wasm::GlobalHandleAddress function_handle_address = wasm::GlobalHandleAddress function_handle_address =
env_->function_tables[i]; env_->function_tables[i];
wasm::GlobalHandleAddress signature_handle_address = Node* table_addr = jsgraph()->RelocatableIntPtrConstant(
env_->signature_tables[i];
function_tables_.push_back(jsgraph()->RelocatableIntPtrConstant(
reinterpret_cast<intptr_t>(function_handle_address), reinterpret_cast<intptr_t>(function_handle_address),
RelocInfo::WASM_GLOBAL_HANDLE)); RelocInfo::WASM_GLOBAL_HANDLE);
signature_tables_.push_back(jsgraph()->RelocatableIntPtrConstant(
reinterpret_cast<intptr_t>(signature_handle_address),
RelocInfo::WASM_GLOBAL_HANDLE));
uint32_t table_size = env_->module->function_tables[i].initial_size; uint32_t table_size = env_->module->function_tables[i].initial_size;
function_table_sizes_.push_back(jsgraph()->RelocatableInt32Constant( Node* size = jsgraph()->RelocatableInt32Constant(
static_cast<uint32_t>(table_size), static_cast<uint32_t>(table_size),
RelocInfo::WASM_FUNCTION_TABLE_SIZE_REFERENCE)); RelocInfo::WASM_FUNCTION_TABLE_SIZE_REFERENCE);
function_tables_.push_back({table_addr, size});
} }
} }
...@@ -4451,14 +4439,11 @@ Handle<Code> CompileJSToWasmWrapper(Isolate* isolate, wasm::WasmModule* module, ...@@ -4451,14 +4439,11 @@ Handle<Code> CompileJSToWasmWrapper(Isolate* isolate, wasm::WasmModule* module,
Node* effect = nullptr; Node* effect = nullptr;
// TODO(titzer): compile JS to WASM wrappers without a {ModuleEnv}. // TODO(titzer): compile JS to WASM wrappers without a {ModuleEnv}.
ModuleEnv env = {module, ModuleEnv env(module,
std::vector<Address>(), // function_tables // TODO(mtrofin): remove the Illegal builtin when we don't need
std::vector<Address>(), // signature_tables
// TODO(mtrofin): remove these 2 lines when we don't need
// FLAG_wasm_jit_to_native // FLAG_wasm_jit_to_native
std::vector<Handle<Code>>(), // function_code
BUILTIN_CODE(isolate, Illegal), // default_function_code BUILTIN_CODE(isolate, Illegal), // default_function_code
use_trap_handler}; use_trap_handler);
WasmGraphBuilder builder(&env, &zone, &jsgraph, WasmGraphBuilder builder(&env, &zone, &jsgraph,
CEntryStub(isolate, 1).GetCode(), func->sig); CEntryStub(isolate, 1).GetCode(), func->sig);
...@@ -4571,12 +4556,7 @@ Handle<Code> CompileWasmToJSWrapper( ...@@ -4571,12 +4556,7 @@ Handle<Code> CompileWasmToJSWrapper(
origin == wasm::kAsmJsOrigin ? new (&zone) SourcePositionTable(&graph) origin == wasm::kAsmJsOrigin ? new (&zone) SourcePositionTable(&graph)
: nullptr; : nullptr;
ModuleEnv env = {nullptr, ModuleEnv env(nullptr, Handle<Code>::null(), use_trap_handler);
std::vector<Address>(),
std::vector<Address>(),
std::vector<Handle<Code>>(),
Handle<Code>(),
use_trap_handler};
WasmGraphBuilder builder(&env, &zone, &jsgraph, WasmGraphBuilder builder(&env, &zone, &jsgraph,
CEntryStub(isolate, 1).GetCode(), sig, CEntryStub(isolate, 1).GetCode(), sig,
source_position_table); source_position_table);
...@@ -4663,13 +4643,9 @@ Handle<Code> CompileWasmToWasmWrapper(Isolate* isolate, WasmCodeWrapper target, ...@@ -4663,13 +4643,9 @@ Handle<Code> CompileWasmToWasmWrapper(Isolate* isolate, WasmCodeWrapper target,
Node* control = nullptr; Node* control = nullptr;
Node* effect = nullptr; Node* effect = nullptr;
ModuleEnv env = { ModuleEnv env(
nullptr, nullptr, Handle<Code>::null(),
std::vector<Address>(), !target.IsCodeObject() && target.GetWasmCode()->HasTrapHandlerIndex());
std::vector<Address>(),
std::vector<Handle<Code>>(),
Handle<Code>(),
!target.IsCodeObject() && target.GetWasmCode()->HasTrapHandlerIndex()};
WasmGraphBuilder builder(&env, &zone, &jsgraph, Handle<Code>(), sig); WasmGraphBuilder builder(&env, &zone, &jsgraph, Handle<Code>(), sig);
builder.set_control_ptr(&control); builder.set_control_ptr(&control);
builder.set_effect_ptr(&effect); builder.set_effect_ptr(&effect);
...@@ -4856,13 +4832,6 @@ Handle<Code> CompileCWasmEntry(Isolate* isolate, wasm::FunctionSig* sig, ...@@ -4856,13 +4832,6 @@ Handle<Code> CompileCWasmEntry(Isolate* isolate, wasm::FunctionSig* sig,
SourcePositionTable* WasmCompilationUnit::BuildGraphForWasmFunction( SourcePositionTable* WasmCompilationUnit::BuildGraphForWasmFunction(
double* decode_ms) { double* decode_ms) {
#if DEBUG
if (env_) {
size_t tables_size = env_->module->function_tables.size();
DCHECK_EQ(tables_size, env_->function_tables.size());
DCHECK_EQ(tables_size, env_->signature_tables.size());
}
#endif
base::ElapsedTimer decode_timer; base::ElapsedTimer decode_timer;
if (FLAG_trace_wasm_decode_time) { if (FLAG_trace_wasm_decode_time) {
......
...@@ -43,25 +43,34 @@ class WasmCode; ...@@ -43,25 +43,34 @@ class WasmCode;
namespace compiler { namespace compiler {
// Indirect function tables contain a <smi(sig), code> pair for each entry.
enum FunctionTableEntries : int {
kFunctionTableSignatureOffset = 0,
kFunctionTableCodeOffset = 1,
kFunctionTableEntrySize = 2
};
constexpr inline int FunctionTableSigOffset(int i) {
return kFunctionTableEntrySize * i + kFunctionTableSignatureOffset;
}
constexpr inline int FunctionTableCodeOffset(int i) {
return kFunctionTableEntrySize * i + kFunctionTableCodeOffset;
}
// The {ModuleEnv} encapsulates the module data that is used by the // The {ModuleEnv} encapsulates the module data that is used by the
// {WasmGraphBuilder} during graph building. It represents the parameters to // {WasmGraphBuilder} during graph building. It represents the parameters to
// which the compiled code should be specialized, including which code to call // which the compiled code should be specialized, including which code to call
// for direct calls {function_code}, which tables to use for indirect calls // for direct calls {function_code}, which tables to use for indirect calls
// {function_tables}, memory start address and size {mem_start, mem_size}, // {function_tables}, memory start address and size {mem_start, mem_size},
// as well as signature maps {signature_maps} and the module itself {module}. // as well as the module itself {module}.
// ModuleEnvs are shareable across multiple compilations. // ModuleEnvs are shareable across multiple compilations.
struct ModuleEnv { struct ModuleEnv {
// A pointer to the decoded module's static representation. // A pointer to the decoded module's static representation.
const wasm::WasmModule* module; const wasm::WasmModule* module;
// The function tables are FixedArrays of code used to dispatch indirect // The function tables are FixedArrays of <smi, code> pairs used to signature
// calls. (the same length as module.function_tables). We use the address // check and dispatch indirect calls. It has the same length as
// to a global handle to the FixedArray. // module.function_tables. We use the address to a global handle to the
// FixedArray.
const std::vector<Address> function_tables; const std::vector<Address> function_tables;
// The signatures tables are FixedArrays of SMIs used to check signatures
// match at runtime.
// (the same length as module.function_tables)
// We use the address to a global handle to the FixedArray.
const std::vector<Address> signature_tables;
// TODO(mtrofin): remove these 2 once we don't need FLAG_wasm_jit_to_native // TODO(mtrofin): remove these 2 once we don't need FLAG_wasm_jit_to_native
// Contains the code objects to call for each direct call. // Contains the code objects to call for each direct call.
...@@ -72,6 +81,22 @@ struct ModuleEnv { ...@@ -72,6 +81,22 @@ struct ModuleEnv {
// True if trap handling should be used in compiled code, rather than // True if trap handling should be used in compiled code, rather than
// compiling in bounds checks for each memory access. // compiling in bounds checks for each memory access.
const bool use_trap_handler; const bool use_trap_handler;
ModuleEnv(const wasm::WasmModule* module, Handle<Code> default_function_code,
bool use_trap_handler)
: module(module),
default_function_code(default_function_code),
use_trap_handler(use_trap_handler) {}
ModuleEnv(const wasm::WasmModule* module,
std::vector<Address> function_tables,
std::vector<Handle<Code>> function_code,
Handle<Code> default_function_code, bool use_trap_handler)
: module(module),
function_tables(std::move(function_tables)),
function_code(std::move(function_code)),
default_function_code(default_function_code),
use_trap_handler(use_trap_handler) {}
}; };
enum RuntimeExceptionSupport : bool { enum RuntimeExceptionSupport : bool {
...@@ -432,9 +457,11 @@ class WasmGraphBuilder { ...@@ -432,9 +457,11 @@ class WasmGraphBuilder {
// wrappers or interpreter stubs. // wrappers or interpreter stubs.
ModuleEnv* const env_ = nullptr; ModuleEnv* const env_ = nullptr;
SetOncePointer<Node> wasm_context_; SetOncePointer<Node> wasm_context_;
NodeVector signature_tables_; struct FunctionTableNodes {
NodeVector function_tables_; Node* table_addr;
NodeVector function_table_sizes_; Node* size;
};
ZoneVector<FunctionTableNodes> function_tables_;
Node** control_ = nullptr; Node** control_ = nullptr;
Node** effect_ = nullptr; Node** effect_ = nullptr;
WasmContextCacheNodes* context_cache_ = nullptr; WasmContextCacheNodes* context_cache_ = nullptr;
......
...@@ -52,12 +52,12 @@ ...@@ -52,12 +52,12 @@
if (FLAG_trace_wasm_lazy_compilation) PrintF(__VA_ARGS__); \ if (FLAG_trace_wasm_lazy_compilation) PrintF(__VA_ARGS__); \
} while (false) } while (false)
static const int kInvalidSigIndex = -1;
namespace v8 { namespace v8 {
namespace internal { namespace internal {
namespace wasm { namespace wasm {
static constexpr int kInvalidSigIndex = -1;
// A class compiling an entire module. // A class compiling an entire module.
class ModuleCompiler { class ModuleCompiler {
public: public:
...@@ -319,8 +319,7 @@ class InstanceBuilder { ...@@ -319,8 +319,7 @@ class InstanceBuilder {
struct TableInstance { struct TableInstance {
Handle<WasmTableObject> table_object; // WebAssembly.Table instance Handle<WasmTableObject> table_object; // WebAssembly.Table instance
Handle<FixedArray> js_wrappers; // JSFunctions exported Handle<FixedArray> js_wrappers; // JSFunctions exported
Handle<FixedArray> function_table; // internal code array Handle<FixedArray> function_table; // internal array of <sig,code> pairs
Handle<FixedArray> signature_table; // internal sig array
}; };
// A pre-evaluated value to use in import binding. // A pre-evaluated value to use in import binding.
...@@ -746,8 +745,9 @@ Handle<Code> CompileLazyOnGCHeap(Isolate* isolate) { ...@@ -746,8 +745,9 @@ Handle<Code> CompileLazyOnGCHeap(Isolate* isolate) {
if (exp_deopt_data->get(idx)->IsUndefined(isolate)) break; if (exp_deopt_data->get(idx)->IsUndefined(isolate)) break;
FixedArray* exp_table = FixedArray::cast(exp_deopt_data->get(idx)); FixedArray* exp_table = FixedArray::cast(exp_deopt_data->get(idx));
int exp_index = Smi::ToInt(exp_deopt_data->get(idx + 1)); int exp_index = Smi::ToInt(exp_deopt_data->get(idx + 1));
DCHECK(exp_table->get(exp_index) == *lazy_compile_code); int table_index = compiler::FunctionTableCodeOffset(exp_index);
exp_table->set(exp_index, *compiled_code); DCHECK(exp_table->get(table_index) == *lazy_compile_code);
exp_table->set(table_index, *compiled_code);
} }
// TODO(6792): No longer needed once WebAssembly code is off heap. // TODO(6792): No longer needed once WebAssembly code is off heap.
CodeSpaceMemoryModificationScope modification_scope(isolate->heap()); CodeSpaceMemoryModificationScope modification_scope(isolate->heap());
...@@ -868,7 +868,8 @@ Address CompileLazy(Isolate* isolate) { ...@@ -868,7 +868,8 @@ Address CompileLazy(Isolate* isolate) {
DisallowHeapAllocation no_gc; DisallowHeapAllocation no_gc;
int exp_index = Smi::ToInt(exp_deopt_data->get(idx + 1)); int exp_index = Smi::ToInt(exp_deopt_data->get(idx + 1));
FixedArray* exp_table = FixedArray::cast(exp_deopt_data->get(idx)); FixedArray* exp_table = FixedArray::cast(exp_deopt_data->get(idx));
exp_table->set(exp_index, *foreign_holder); exp_table->set(compiler::FunctionTableCodeOffset(exp_index),
*foreign_holder);
} }
// TODO(6792): No longer needed once WebAssembly code is off heap. // TODO(6792): No longer needed once WebAssembly code is off heap.
CodeSpaceMemoryModificationScope modification_scope(isolate->heap()); CodeSpaceMemoryModificationScope modification_scope(isolate->heap());
...@@ -885,43 +886,29 @@ compiler::ModuleEnv CreateModuleEnvFromCompiledModule( ...@@ -885,43 +886,29 @@ compiler::ModuleEnv CreateModuleEnvFromCompiledModule(
Isolate* isolate, Handle<WasmCompiledModule> compiled_module) { Isolate* isolate, Handle<WasmCompiledModule> compiled_module) {
DisallowHeapAllocation no_gc; DisallowHeapAllocation no_gc;
WasmModule* module = compiled_module->shared()->module(); WasmModule* module = compiled_module->shared()->module();
std::vector<Handle<Code>> empty_code;
if (FLAG_wasm_jit_to_native) { if (FLAG_wasm_jit_to_native) {
NativeModule* native_module = compiled_module->GetNativeModule(); NativeModule* native_module = compiled_module->GetNativeModule();
std::vector<GlobalHandleAddress> function_tables = compiler::ModuleEnv result(module, native_module->function_tables(),
native_module->function_tables(); std::vector<Handle<Code>>{},
std::vector<GlobalHandleAddress> signature_tables =
native_module->signature_tables();
compiler::ModuleEnv result = {module, // --
function_tables, // --
signature_tables, // --
empty_code,
BUILTIN_CODE(isolate, WasmCompileLazy), BUILTIN_CODE(isolate, WasmCompileLazy),
compiled_module->use_trap_handler()}; compiled_module->use_trap_handler());
return result; return result;
} else { }
std::vector<GlobalHandleAddress> function_tables; std::vector<GlobalHandleAddress> function_tables;
std::vector<GlobalHandleAddress> signature_tables;
int num_function_tables = static_cast<int>(module->function_tables.size()); int num_function_tables = static_cast<int>(module->function_tables.size());
for (int i = 0; i < num_function_tables; ++i) {
FixedArray* ft = compiled_module->function_tables(); FixedArray* ft = compiled_module->function_tables();
FixedArray* st = compiled_module->signature_tables(); for (int i = 0; i < num_function_tables; ++i) {
// TODO(clemensh): defer these handles for concurrent compilation. // TODO(clemensh): defer these handles for concurrent compilation.
function_tables.push_back(WasmCompiledModule::GetTableValue(ft, i)); function_tables.push_back(WasmCompiledModule::GetTableValue(ft, i));
signature_tables.push_back(WasmCompiledModule::GetTableValue(st, i));
} }
compiler::ModuleEnv result = {module, // -- compiler::ModuleEnv result(module, std::move(function_tables),
function_tables, // -- std::vector<Handle<Code>>{},
signature_tables, // --
empty_code, // --
BUILTIN_CODE(isolate, WasmCompileLazy), BUILTIN_CODE(isolate, WasmCompileLazy),
compiled_module->use_trap_handler()}; compiled_module->use_trap_handler());
return result; return result;
}
} }
const wasm::WasmCode* LazyCompilationOrchestrator::CompileFunction( const wasm::WasmCode* LazyCompilationOrchestrator::CompileFunction(
...@@ -2014,34 +2001,21 @@ void FunctionTableFinalizer(const v8::WeakCallbackInfo<void>& data) { ...@@ -2014,34 +2001,21 @@ void FunctionTableFinalizer(const v8::WeakCallbackInfo<void>& data) {
std::unique_ptr<compiler::ModuleEnv> CreateDefaultModuleEnv( std::unique_ptr<compiler::ModuleEnv> CreateDefaultModuleEnv(
Isolate* isolate, WasmModule* module, Handle<Code> illegal_builtin) { Isolate* isolate, WasmModule* module, Handle<Code> illegal_builtin) {
std::vector<GlobalHandleAddress> function_tables; std::vector<GlobalHandleAddress> function_tables;
std::vector<GlobalHandleAddress> signature_tables;
for (size_t i = 0; i < module->function_tables.size(); i++) { for (size_t i = module->function_tables.size(); i > 0; --i) {
Handle<Object> func_table = Handle<Object> func_table =
isolate->global_handles()->Create(isolate->heap()->undefined_value()); isolate->global_handles()->Create(isolate->heap()->undefined_value());
Handle<Object> sig_table =
isolate->global_handles()->Create(isolate->heap()->undefined_value());
GlobalHandles::MakeWeak(func_table.location(), func_table.location(), GlobalHandles::MakeWeak(func_table.location(), func_table.location(),
&FunctionTableFinalizer, &FunctionTableFinalizer,
v8::WeakCallbackType::kFinalizer); v8::WeakCallbackType::kFinalizer);
GlobalHandles::MakeWeak(sig_table.location(), sig_table.location(),
&FunctionTableFinalizer,
v8::WeakCallbackType::kFinalizer);
function_tables.push_back(func_table.address()); function_tables.push_back(func_table.address());
signature_tables.push_back(sig_table.address());
} }
std::vector<Handle<Code>> empty_code;
// TODO(kschimpf): Add module-specific policy handling here (see v8:7143)? // TODO(kschimpf): Add module-specific policy handling here (see v8:7143)?
bool use_trap_handler = trap_handler::IsTrapHandlerEnabled(); bool use_trap_handler = trap_handler::IsTrapHandlerEnabled();
compiler::ModuleEnv result = {module, // -- return base::make_unique<compiler::ModuleEnv>(
function_tables, // -- module, function_tables, std::vector<Handle<Code>>{}, illegal_builtin,
signature_tables, // -- use_trap_handler);
empty_code, // --
illegal_builtin, // --
use_trap_handler};
return std::unique_ptr<compiler::ModuleEnv>(new compiler::ModuleEnv(result));
} }
// TODO(mtrofin): remove code_table when we don't need FLAG_wasm_jit_to_native // TODO(mtrofin): remove code_table when we don't need FLAG_wasm_jit_to_native
...@@ -2050,9 +2024,9 @@ Handle<WasmCompiledModule> NewCompiledModule(Isolate* isolate, ...@@ -2050,9 +2024,9 @@ Handle<WasmCompiledModule> NewCompiledModule(Isolate* isolate,
Handle<FixedArray> code_table, Handle<FixedArray> code_table,
Handle<FixedArray> export_wrappers, Handle<FixedArray> export_wrappers,
compiler::ModuleEnv* env) { compiler::ModuleEnv* env) {
Handle<WasmCompiledModule> compiled_module = WasmCompiledModule::New( Handle<WasmCompiledModule> compiled_module =
isolate, module, code_table, export_wrappers, env->function_tables, WasmCompiledModule::New(isolate, module, code_table, export_wrappers,
env->signature_tables, env->use_trap_handler); env->function_tables, env->use_trap_handler);
return compiled_module; return compiled_module;
} }
...@@ -2426,9 +2400,7 @@ MaybeHandle<WasmInstanceObject> InstanceBuilder::Build() { ...@@ -2426,9 +2400,7 @@ MaybeHandle<WasmInstanceObject> InstanceBuilder::Build() {
int function_table_count = static_cast<int>(module_->function_tables.size()); int function_table_count = static_cast<int>(module_->function_tables.size());
table_instances_.reserve(module_->function_tables.size()); table_instances_.reserve(module_->function_tables.size());
for (int index = 0; index < function_table_count; ++index) { for (int index = 0; index < function_table_count; ++index) {
table_instances_.push_back( table_instances_.emplace_back();
{Handle<WasmTableObject>::null(), Handle<FixedArray>::null(),
Handle<FixedArray>::null(), Handle<FixedArray>::null()});
} }
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
...@@ -2503,7 +2475,8 @@ MaybeHandle<WasmInstanceObject> InstanceBuilder::Build() { ...@@ -2503,7 +2475,8 @@ MaybeHandle<WasmInstanceObject> InstanceBuilder::Build() {
DCHECK(table_init.table_index < table_instances_.size()); DCHECK(table_init.table_index < table_instances_.size());
uint32_t base = EvalUint32InitExpr(table_init.offset); uint32_t base = EvalUint32InitExpr(table_init.offset);
uint32_t table_size = uint32_t table_size =
table_instances_[table_init.table_index].function_table->length(); table_instances_[table_init.table_index].function_table->length() /
compiler::kFunctionTableEntrySize;
if (!in_bounds(base, static_cast<uint32_t>(table_init.entries.size()), if (!in_bounds(base, static_cast<uint32_t>(table_init.entries.size()),
table_size)) { table_size)) {
thrower_->LinkError("table initializer is out of bounds"); thrower_->LinkError("table initializer is out of bounds");
...@@ -2880,6 +2853,9 @@ Handle<FixedArray> InstanceBuilder::SetupWasmToJSImportsTable( ...@@ -2880,6 +2853,9 @@ Handle<FixedArray> InstanceBuilder::SetupWasmToJSImportsTable(
// functions. // functions.
int InstanceBuilder::ProcessImports(Handle<FixedArray> code_table, int InstanceBuilder::ProcessImports(Handle<FixedArray> code_table,
Handle<WasmInstanceObject> instance) { Handle<WasmInstanceObject> instance) {
using compiler::kFunctionTableSignatureOffset;
using compiler::kFunctionTableCodeOffset;
using compiler::kFunctionTableEntrySize;
int num_imported_functions = 0; int num_imported_functions = 0;
int num_imported_tables = 0; int num_imported_tables = 0;
Handle<FixedArray> js_imports_table = SetupWasmToJSImportsTable(instance); Handle<FixedArray> js_imports_table = SetupWasmToJSImportsTable(instance);
...@@ -2960,19 +2936,18 @@ int InstanceBuilder::ProcessImports(Handle<FixedArray> code_table, ...@@ -2960,19 +2936,18 @@ int InstanceBuilder::ProcessImports(Handle<FixedArray> code_table,
} }
} }
// Allocate a new dispatch table and signature table. // Allocate a new dispatch table, containing <smi(sig), code> pairs.
int table_size = imported_cur_size; CHECK_GE(kMaxInt / kFunctionTableEntrySize, imported_cur_size);
int table_size = kFunctionTableEntrySize * imported_cur_size;
table_instance.function_table = table_instance.function_table =
isolate_->factory()->NewFixedArray(table_size); isolate_->factory()->NewFixedArray(table_size);
table_instance.signature_table = for (int i = kFunctionTableSignatureOffset; i < table_size;
isolate_->factory()->NewFixedArray(table_size); i += kFunctionTableEntrySize) {
for (int i = 0; i < table_size; ++i) { table_instance.function_table->set(i, Smi::FromInt(kInvalidSigIndex));
table_instance.signature_table->set(i,
Smi::FromInt(kInvalidSigIndex));
} }
// Initialize the dispatch table with the (foreign) JS functions // Initialize the dispatch table with the (foreign) JS functions
// that are already in the table. // that are already in the table.
for (int i = 0; i < table_size; ++i) { for (int i = 0; i < imported_cur_size; ++i) {
Handle<Object> val(table_instance.js_wrappers->get(i), isolate_); Handle<Object> val(table_instance.js_wrappers->get(i), isolate_);
// TODO(mtrofin): this is the same logic as WasmTableObject::Set: // TODO(mtrofin): this is the same logic as WasmTableObject::Set:
// insert in the local table a wrapper from the other module, and add // insert in the local table a wrapper from the other module, and add
...@@ -2994,8 +2969,10 @@ int InstanceBuilder::ProcessImports(Handle<FixedArray> code_table, ...@@ -2994,8 +2969,10 @@ int InstanceBuilder::ProcessImports(Handle<FixedArray> code_table,
&imported_wasm_instances, instance, 0) &imported_wasm_instances, instance, 0)
.GetCode(); .GetCode();
int sig_index = module_->signature_map.Find(sig); int sig_index = module_->signature_map.Find(sig);
table_instance.signature_table->set(i, Smi::FromInt(sig_index)); table_instance.function_table->set(
table_instance.function_table->set(i, *code); compiler::FunctionTableSigOffset(i), Smi::FromInt(sig_index));
table_instance.function_table->set(
compiler::FunctionTableCodeOffset(i), *code);
} else { } else {
const wasm::WasmCode* exported_code = const wasm::WasmCode* exported_code =
target->GetWasmCode().GetWasmCode(); target->GetWasmCode().GetWasmCode();
...@@ -3019,10 +2996,12 @@ int InstanceBuilder::ProcessImports(Handle<FixedArray> code_table, ...@@ -3019,10 +2996,12 @@ int InstanceBuilder::ProcessImports(Handle<FixedArray> code_table,
wrapper, exported_code->index()); wrapper, exported_code->index());
} }
int sig_index = module_->signature_map.Find(sig); int sig_index = module_->signature_map.Find(sig);
table_instance.signature_table->set(i, Smi::FromInt(sig_index));
Handle<Foreign> foreign_holder = isolate_->factory()->NewForeign( Handle<Foreign> foreign_holder = isolate_->factory()->NewForeign(
wrapper_code->instructions().start(), TENURED); wrapper_code->instructions().start(), TENURED);
table_instance.function_table->set(i, *foreign_holder); table_instance.function_table->set(
compiler::FunctionTableSigOffset(i), Smi::FromInt(sig_index));
table_instance.function_table->set(
compiler::FunctionTableCodeOffset(i), *foreign_holder);
} }
} }
...@@ -3373,23 +3352,16 @@ void InstanceBuilder::InitializeTables( ...@@ -3373,23 +3352,16 @@ void InstanceBuilder::InitializeTables(
CodeSpecialization* code_specialization) { CodeSpecialization* code_specialization) {
size_t function_table_count = module_->function_tables.size(); size_t function_table_count = module_->function_tables.size();
std::vector<GlobalHandleAddress> new_function_tables(function_table_count); std::vector<GlobalHandleAddress> new_function_tables(function_table_count);
std::vector<GlobalHandleAddress> new_signature_tables(function_table_count);
wasm::NativeModule* native_module = compiled_module_->GetNativeModule(); wasm::NativeModule* native_module = compiled_module_->GetNativeModule();
std::vector<GlobalHandleAddress> empty; std::vector<GlobalHandleAddress> empty;
std::vector<GlobalHandleAddress>& old_function_tables = std::vector<GlobalHandleAddress>& old_function_tables =
FLAG_wasm_jit_to_native ? native_module->function_tables() : empty; FLAG_wasm_jit_to_native ? native_module->function_tables() : empty;
std::vector<GlobalHandleAddress>& old_signature_tables =
FLAG_wasm_jit_to_native ? native_module->signature_tables() : empty;
Handle<FixedArray> old_function_tables_gc = Handle<FixedArray> old_function_tables_gc =
FLAG_wasm_jit_to_native FLAG_wasm_jit_to_native
? Handle<FixedArray>::null() ? Handle<FixedArray>::null()
: handle(compiled_module_->function_tables(), isolate_); : handle(compiled_module_->function_tables(), isolate_);
Handle<FixedArray> old_signature_tables_gc =
FLAG_wasm_jit_to_native
? Handle<FixedArray>::null()
: handle(compiled_module_->signature_tables(), isolate_);
// function_table_count is 0 or 1, so we just create these objects even if not // function_table_count is 0 or 1, so we just create these objects even if not
// needed for native wasm. // needed for native wasm.
...@@ -3398,58 +3370,52 @@ void InstanceBuilder::InitializeTables( ...@@ -3398,58 +3370,52 @@ void InstanceBuilder::InitializeTables(
Handle<FixedArray> new_function_tables_gc = Handle<FixedArray> new_function_tables_gc =
isolate_->factory()->NewFixedArray(static_cast<int>(function_table_count), isolate_->factory()->NewFixedArray(static_cast<int>(function_table_count),
TENURED); TENURED);
Handle<FixedArray> new_signature_tables_gc =
isolate_->factory()->NewFixedArray(static_cast<int>(function_table_count),
TENURED);
// These go on the instance. // These go on the instance.
Handle<FixedArray> rooted_function_tables = Handle<FixedArray> rooted_function_tables =
isolate_->factory()->NewFixedArray(static_cast<int>(function_table_count), isolate_->factory()->NewFixedArray(static_cast<int>(function_table_count),
TENURED); TENURED);
Handle<FixedArray> rooted_signature_tables =
isolate_->factory()->NewFixedArray(static_cast<int>(function_table_count),
TENURED);
instance->set_function_tables(*rooted_function_tables); instance->set_function_tables(*rooted_function_tables);
instance->set_signature_tables(*rooted_signature_tables);
if (FLAG_wasm_jit_to_native) { if (FLAG_wasm_jit_to_native) {
DCHECK_EQ(old_function_tables.size(), new_function_tables.size()); DCHECK_EQ(old_function_tables.size(), new_function_tables.size());
DCHECK_EQ(old_signature_tables.size(), new_signature_tables.size());
} else { } else {
DCHECK_EQ(old_function_tables_gc->length(), DCHECK_EQ(old_function_tables_gc->length(),
new_function_tables_gc->length()); new_function_tables_gc->length());
DCHECK_EQ(old_signature_tables_gc->length(),
new_signature_tables_gc->length());
} }
for (size_t index = 0; index < function_table_count; ++index) { for (size_t index = 0; index < function_table_count; ++index) {
WasmIndirectFunctionTable& table = module_->function_tables[index]; WasmIndirectFunctionTable& table = module_->function_tables[index];
TableInstance& table_instance = table_instances_[index]; TableInstance& table_instance = table_instances_[index];
int table_size = static_cast<int>(table.initial_size); // The table holds <smi(sig), code> pairs.
CHECK_GE(kMaxInt / compiler::kFunctionTableEntrySize, table.initial_size);
int num_table_entries = static_cast<int>(table.initial_size);
int table_size = compiler::kFunctionTableEntrySize * num_table_entries;
if (table_instance.function_table.is_null()) { if (table_instance.function_table.is_null()) {
// Create a new dispatch table if necessary. // Create a new dispatch table if necessary.
table_instance.function_table = table_instance.function_table =
isolate_->factory()->NewFixedArray(table_size); isolate_->factory()->NewFixedArray(table_size);
table_instance.signature_table = for (int i = compiler::kFunctionTableSignatureOffset; i < table_size;
isolate_->factory()->NewFixedArray(table_size); i += compiler::kFunctionTableEntrySize) {
for (int i = 0; i < table_size; ++i) {
// Fill the table with invalid signature indexes so that // Fill the table with invalid signature indexes so that
// uninitialized entries will always fail the signature check. // uninitialized entries will always fail the signature check.
table_instance.signature_table->set(i, Smi::FromInt(kInvalidSigIndex)); table_instance.function_table->set(i, Smi::FromInt(kInvalidSigIndex));
} }
} else { } else {
// Table is imported, patch table bounds check // Table is imported, patch table bounds check
DCHECK_LE(table_size, table_instance.function_table->length()); int existing_table_size = table_instance.function_table->length();
code_specialization->PatchTableSize( DCHECK_EQ(0, existing_table_size % compiler::kFunctionTableEntrySize);
table_size, table_instance.function_table->length()); int existing_num_table_entries =
existing_table_size / compiler::kFunctionTableEntrySize;
DCHECK_LE(num_table_entries, existing_num_table_entries);
code_specialization->PatchTableSize(num_table_entries,
existing_num_table_entries);
} }
int int_index = static_cast<int>(index); int int_index = static_cast<int>(index);
Handle<FixedArray> global_func_table = Handle<FixedArray> global_func_table =
isolate_->global_handles()->Create(*table_instance.function_table); isolate_->global_handles()->Create(*table_instance.function_table);
Handle<FixedArray> global_sig_table =
isolate_->global_handles()->Create(*table_instance.signature_table);
// Make the handles weak. The table objects are rooted on the instance, as // Make the handles weak. The table objects are rooted on the instance, as
// they belong to it. We need the global handles in order to have stable // they belong to it. We need the global handles in order to have stable
// pointers to embed in the instance's specialization (wasm compiled code). // pointers to embed in the instance's specialization (wasm compiled code).
...@@ -3462,47 +3428,30 @@ void InstanceBuilder::InitializeTables( ...@@ -3462,47 +3428,30 @@ void InstanceBuilder::InitializeTables(
reinterpret_cast<Object**>(global_func_table.location()), reinterpret_cast<Object**>(global_func_table.location()),
global_func_table.location(), &FunctionTableFinalizer, global_func_table.location(), &FunctionTableFinalizer,
v8::WeakCallbackType::kFinalizer); v8::WeakCallbackType::kFinalizer);
GlobalHandles::MakeWeak(
reinterpret_cast<Object**>(global_sig_table.location()),
global_sig_table.location(), &FunctionTableFinalizer,
v8::WeakCallbackType::kFinalizer);
rooted_function_tables->set(int_index, *global_func_table); rooted_function_tables->set(int_index, *global_func_table);
rooted_signature_tables->set(int_index, *global_sig_table);
GlobalHandleAddress new_func_table_addr = global_func_table.address(); GlobalHandleAddress new_func_table_addr = global_func_table.address();
GlobalHandleAddress new_sig_table_addr = global_sig_table.address();
GlobalHandleAddress old_func_table_addr; GlobalHandleAddress old_func_table_addr;
GlobalHandleAddress old_sig_table_addr;
if (!FLAG_wasm_jit_to_native) { if (!FLAG_wasm_jit_to_native) {
WasmCompiledModule::SetTableValue(isolate_, new_function_tables_gc, WasmCompiledModule::SetTableValue(isolate_, new_function_tables_gc,
int_index, new_func_table_addr); int_index, new_func_table_addr);
WasmCompiledModule::SetTableValue(isolate_, new_signature_tables_gc,
int_index, new_sig_table_addr);
old_func_table_addr = old_func_table_addr =
WasmCompiledModule::GetTableValue(*old_function_tables_gc, int_index); WasmCompiledModule::GetTableValue(*old_function_tables_gc, int_index);
old_sig_table_addr = WasmCompiledModule::GetTableValue(
*old_signature_tables_gc, int_index);
} else { } else {
new_function_tables[int_index] = new_func_table_addr; new_function_tables[int_index] = new_func_table_addr;
new_signature_tables[int_index] = new_sig_table_addr;
old_func_table_addr = old_function_tables[int_index]; old_func_table_addr = old_function_tables[int_index];
old_sig_table_addr = old_signature_tables[int_index];
} }
code_specialization->RelocatePointer(old_func_table_addr, code_specialization->RelocatePointer(old_func_table_addr,
new_func_table_addr); new_func_table_addr);
code_specialization->RelocatePointer(old_sig_table_addr,
new_sig_table_addr);
} }
if (FLAG_wasm_jit_to_native) { if (FLAG_wasm_jit_to_native) {
native_module->function_tables() = new_function_tables; native_module->function_tables() = new_function_tables;
native_module->signature_tables() = new_signature_tables;
} else { } else {
compiled_module_->set_function_tables(*new_function_tables_gc); compiled_module_->set_function_tables(*new_function_tables_gc);
compiled_module_->set_signature_tables(*new_signature_tables_gc);
} }
} }
...@@ -3544,13 +3493,15 @@ void InstanceBuilder::LoadTableSegments(Handle<FixedArray> code_table, ...@@ -3544,13 +3493,15 @@ void InstanceBuilder::LoadTableSegments(Handle<FixedArray> code_table,
uint32_t base = EvalUint32InitExpr(table_init.offset); uint32_t base = EvalUint32InitExpr(table_init.offset);
uint32_t num_entries = static_cast<uint32_t>(table_init.entries.size()); uint32_t num_entries = static_cast<uint32_t>(table_init.entries.size());
DCHECK(in_bounds(base, num_entries, DCHECK(in_bounds(base, num_entries,
table_instance.function_table->length())); table_instance.function_table->length() /
compiler::kFunctionTableEntrySize));
for (uint32_t i = 0; i < num_entries; ++i) { for (uint32_t i = 0; i < num_entries; ++i) {
uint32_t func_index = table_init.entries[i]; uint32_t func_index = table_init.entries[i];
WasmFunction* function = &module_->functions[func_index]; WasmFunction* function = &module_->functions[func_index];
int table_index = static_cast<int>(i + base); int table_index = static_cast<int>(i + base);
uint32_t sig_index = module_->signature_ids[function->sig_index]; uint32_t sig_index = module_->signature_ids[function->sig_index];
table_instance.signature_table->set(table_index, table_instance.function_table->set(
compiler::FunctionTableSigOffset(table_index),
Smi::FromInt(sig_index)); Smi::FromInt(sig_index));
WasmCodeWrapper wasm_code = EnsureTableExportLazyDeoptData( WasmCodeWrapper wasm_code = EnsureTableExportLazyDeoptData(
isolate_, instance, code_table, native_module, func_index, isolate_, instance, code_table, native_module, func_index,
...@@ -3559,12 +3510,13 @@ void InstanceBuilder::LoadTableSegments(Handle<FixedArray> code_table, ...@@ -3559,12 +3510,13 @@ void InstanceBuilder::LoadTableSegments(Handle<FixedArray> code_table,
if (!wasm_code.IsCodeObject()) { if (!wasm_code.IsCodeObject()) {
Handle<Foreign> as_foreign = isolate_->factory()->NewForeign( Handle<Foreign> as_foreign = isolate_->factory()->NewForeign(
wasm_code.GetWasmCode()->instructions().start(), TENURED); wasm_code.GetWasmCode()->instructions().start(), TENURED);
table_instance.function_table->set(table_index, *as_foreign);
value_to_update_with = as_foreign; value_to_update_with = as_foreign;
} else { } else {
table_instance.function_table->set(table_index, *wasm_code.GetCode());
value_to_update_with = wasm_code.GetCode(); value_to_update_with = wasm_code.GetCode();
} }
table_instance.function_table->set(
compiler::FunctionTableCodeOffset(table_index),
*value_to_update_with);
if (!table_instance.table_object.is_null()) { if (!table_instance.table_object.is_null()) {
if (js_wrappers_[func_index].is_null()) { if (js_wrappers_[func_index].is_null()) {
// No JSFunction entry yet exists for this function. Create one. // No JSFunction entry yet exists for this function. Create one.
...@@ -3616,8 +3568,8 @@ void InstanceBuilder::LoadTableSegments(Handle<FixedArray> code_table, ...@@ -3616,8 +3568,8 @@ void InstanceBuilder::LoadTableSegments(Handle<FixedArray> code_table,
WasmCode::kWasmToWasmWrapper); WasmCode::kWasmToWasmWrapper);
} }
} }
WasmTableObject::UpdateDispatchTables( WasmTableObject::UpdateDispatchTables(table_instance.table_object,
isolate_, table_instance.table_object, table_index, function->sig, table_index, function->sig,
value_to_update_with); value_to_update_with);
} }
} }
...@@ -3636,9 +3588,9 @@ void InstanceBuilder::LoadTableSegments(Handle<FixedArray> code_table, ...@@ -3636,9 +3588,9 @@ void InstanceBuilder::LoadTableSegments(Handle<FixedArray> code_table,
// initialized. // initialized.
if (!table_instance.table_object.is_null()) { if (!table_instance.table_object.is_null()) {
// Add the new dispatch table to the WebAssembly.Table object. // Add the new dispatch table to the WebAssembly.Table object.
WasmTableObject::AddDispatchTable( WasmTableObject::AddDispatchTable(isolate_, table_instance.table_object,
isolate_, table_instance.table_object, instance, index, instance, index,
table_instance.function_table, table_instance.signature_table); table_instance.function_table);
} }
} }
} }
......
...@@ -248,16 +248,10 @@ class V8_EXPORT_PRIVATE NativeModule final { ...@@ -248,16 +248,10 @@ class V8_EXPORT_PRIVATE NativeModule final {
std::vector<wasm::GlobalHandleAddress>& function_tables() { std::vector<wasm::GlobalHandleAddress>& function_tables() {
return specialization_data_.function_tables; return specialization_data_.function_tables;
} }
std::vector<wasm::GlobalHandleAddress>& signature_tables() {
return specialization_data_.signature_tables;
}
std::vector<wasm::GlobalHandleAddress>& empty_function_tables() { std::vector<wasm::GlobalHandleAddress>& empty_function_tables() {
return specialization_data_.empty_function_tables; return specialization_data_.empty_function_tables;
} }
std::vector<wasm::GlobalHandleAddress>& empty_signature_tables() {
return specialization_data_.empty_signature_tables;
}
uint32_t num_imported_functions() const { return num_imported_functions_; } uint32_t num_imported_functions() const { return num_imported_functions_; }
size_t num_function_tables() const { size_t num_function_tables() const {
...@@ -337,9 +331,7 @@ class V8_EXPORT_PRIVATE NativeModule final { ...@@ -337,9 +331,7 @@ class V8_EXPORT_PRIVATE NativeModule final {
// elements a 1 line copy. // elements a 1 line copy.
struct { struct {
std::vector<wasm::GlobalHandleAddress> function_tables; std::vector<wasm::GlobalHandleAddress> function_tables;
std::vector<wasm::GlobalHandleAddress> signature_tables;
std::vector<wasm::GlobalHandleAddress> empty_function_tables; std::vector<wasm::GlobalHandleAddress> empty_function_tables;
std::vector<wasm::GlobalHandleAddress> empty_signature_tables;
} specialization_data_; } specialization_data_;
}; };
......
...@@ -2558,63 +2558,57 @@ class ThreadImpl { ...@@ -2558,63 +2558,57 @@ class ThreadImpl {
if (!FLAG_wasm_jit_to_native) { if (!FLAG_wasm_jit_to_native) {
// Check signature. // Check signature.
FixedArray* sig_tables = compiled_module->signature_tables(); FixedArray* fun_tables = compiled_module->function_tables();
if (table_index >= static_cast<uint32_t>(sig_tables->length())) { if (table_index >= static_cast<uint32_t>(fun_tables->length())) {
return {ExternalCallResult::INVALID_FUNC}; return {ExternalCallResult::INVALID_FUNC};
} }
// Reconstitute the global handle to sig_table, and, further below, // Reconstitute the global handle to the function table, from the
// to the function table, from the address stored in the // address stored in the respective table of tables.
// respective table of tables.
int table_index_as_int = static_cast<int>(table_index); int table_index_as_int = static_cast<int>(table_index);
Handle<FixedArray> sig_table(reinterpret_cast<FixedArray**>( FixedArray* fun_table = *reinterpret_cast<FixedArray**>(
WasmCompiledModule::GetTableValue(sig_tables, table_index_as_int))); WasmCompiledModule::GetTableValue(fun_tables, table_index_as_int));
if (entry_index >= static_cast<uint32_t>(sig_table->length())) { // Function tables store <smi, code> pairs.
int num_funcs_in_table =
fun_table->length() / compiler::kFunctionTableEntrySize;
if (entry_index >= static_cast<uint32_t>(num_funcs_in_table)) {
return {ExternalCallResult::INVALID_FUNC}; return {ExternalCallResult::INVALID_FUNC};
} }
int found_sig = int found_sig = Smi::ToInt(fun_table->get(
Smi::ToInt(sig_table->get(static_cast<int>(entry_index))); compiler::FunctionTableSigOffset(static_cast<int>(entry_index))));
if (static_cast<uint32_t>(found_sig) != canonical_sig_index) { if (static_cast<uint32_t>(found_sig) != canonical_sig_index) {
return {ExternalCallResult::SIGNATURE_MISMATCH}; return {ExternalCallResult::SIGNATURE_MISMATCH};
} }
// Get code object. // Get code object.
FixedArray* fun_tables = compiled_module->function_tables(); target_gc = Code::cast(fun_table->get(
DCHECK_EQ(sig_tables->length(), fun_tables->length()); compiler::FunctionTableCodeOffset(static_cast<int>(entry_index))));
Handle<FixedArray> fun_table(reinterpret_cast<FixedArray**>(
WasmCompiledModule::GetTableValue(fun_tables, table_index_as_int)));
DCHECK_EQ(sig_table->length(), fun_table->length());
target_gc = Code::cast(fun_table->get(static_cast<int>(entry_index)));
} else { } else {
// Check signature. // Check signature.
std::vector<GlobalHandleAddress>& sig_tables = std::vector<GlobalHandleAddress>& fun_tables =
compiled_module->GetNativeModule()->signature_tables(); compiled_module->GetNativeModule()->function_tables();
if (table_index >= sig_tables.size()) { if (table_index >= fun_tables.size()) {
return {ExternalCallResult::INVALID_FUNC}; return {ExternalCallResult::INVALID_FUNC};
} }
// Reconstitute the global handle to sig_table, and, further below, // Reconstitute the global handle to the function table, from the
// to the function table, from the address stored in the // address stored in the respective table of tables.
// respective table of tables. FixedArray* fun_table =
int table_index_as_int = static_cast<int>(table_index); *reinterpret_cast<FixedArray**>(fun_tables[table_index]);
Handle<FixedArray> sig_table( // Function tables store <smi, code> pairs.
reinterpret_cast<FixedArray**>(sig_tables[table_index_as_int])); int num_funcs_in_table =
if (entry_index >= static_cast<uint32_t>(sig_table->length())) { fun_table->length() / compiler::kFunctionTableEntrySize;
if (entry_index >= static_cast<uint32_t>(num_funcs_in_table)) {
return {ExternalCallResult::INVALID_FUNC}; return {ExternalCallResult::INVALID_FUNC};
} }
int found_sig = int found_sig = Smi::ToInt(fun_table->get(
Smi::ToInt(sig_table->get(static_cast<int>(entry_index))); compiler::FunctionTableSigOffset(static_cast<int>(entry_index))));
if (static_cast<uint32_t>(found_sig) != canonical_sig_index) { if (static_cast<uint32_t>(found_sig) != canonical_sig_index) {
return {ExternalCallResult::SIGNATURE_MISMATCH}; return {ExternalCallResult::SIGNATURE_MISMATCH};
} }
// Get code object. // Get code object.
std::vector<GlobalHandleAddress>& fun_tables =
compiled_module->GetNativeModule()->function_tables();
DCHECK_EQ(sig_tables.size(), fun_tables.size());
Handle<FixedArray> fun_table(
reinterpret_cast<FixedArray**>(fun_tables[table_index_as_int]));
DCHECK_EQ(sig_table->length(), fun_table->length());
Address first_instr = Address first_instr =
Foreign::cast(fun_table->get(static_cast<int>(entry_index))) Foreign::cast(fun_table->get(compiler::FunctionTableCodeOffset(
static_cast<int>(entry_index))))
->foreign_address(); ->foreign_address();
target = target =
isolate->wasm_engine()->code_manager()->GetCodeFromStartAddress( isolate->wasm_engine()->code_manager()->GetCodeFromStartAddress(
......
...@@ -56,8 +56,6 @@ OPTIONAL_ACCESSORS(WasmInstanceObject, table_object, WasmTableObject, ...@@ -56,8 +56,6 @@ OPTIONAL_ACCESSORS(WasmInstanceObject, table_object, WasmTableObject,
kTableObjectOffset) kTableObjectOffset)
OPTIONAL_ACCESSORS(WasmInstanceObject, function_tables, FixedArray, OPTIONAL_ACCESSORS(WasmInstanceObject, function_tables, FixedArray,
kFunctionTablesOffset) kFunctionTablesOffset)
OPTIONAL_ACCESSORS(WasmInstanceObject, signature_tables, FixedArray,
kSignatureTablesOffset)
ACCESSORS(WasmInstanceObject, directly_called_instances, FixedArray, ACCESSORS(WasmInstanceObject, directly_called_instances, FixedArray,
kDirectlyCalledInstancesOffset) kDirectlyCalledInstancesOffset)
ACCESSORS(WasmInstanceObject, js_imports_table, FixedArray, ACCESSORS(WasmInstanceObject, js_imports_table, FixedArray,
......
...@@ -167,7 +167,6 @@ enum DispatchTableElements : int { ...@@ -167,7 +167,6 @@ enum DispatchTableElements : int {
kDispatchTableInstanceOffset, kDispatchTableInstanceOffset,
kDispatchTableIndexOffset, kDispatchTableIndexOffset,
kDispatchTableFunctionTableOffset, kDispatchTableFunctionTableOffset,
kDispatchTableSignatureTableOffset,
// Marker: // Marker:
kDispatchTableNumElements kDispatchTableNumElements
}; };
...@@ -216,8 +215,7 @@ Handle<WasmTableObject> WasmTableObject::New(Isolate* isolate, uint32_t initial, ...@@ -216,8 +215,7 @@ Handle<WasmTableObject> WasmTableObject::New(Isolate* isolate, uint32_t initial,
Handle<Object> max = isolate->factory()->NewNumber(maximum); Handle<Object> max = isolate->factory()->NewNumber(maximum);
table_obj->set_maximum_length(*max); table_obj->set_maximum_length(*max);
Handle<FixedArray> dispatch_tables = isolate->factory()->empty_fixed_array(); table_obj->set_dispatch_tables(isolate->heap()->empty_fixed_array());
table_obj->set_dispatch_tables(*dispatch_tables);
return Handle<WasmTableObject>::cast(table_obj); return Handle<WasmTableObject>::cast(table_obj);
} }
...@@ -225,8 +223,8 @@ void WasmTableObject::AddDispatchTable(Isolate* isolate, ...@@ -225,8 +223,8 @@ void WasmTableObject::AddDispatchTable(Isolate* isolate,
Handle<WasmTableObject> table_obj, Handle<WasmTableObject> table_obj,
Handle<WasmInstanceObject> instance, Handle<WasmInstanceObject> instance,
int table_index, int table_index,
Handle<FixedArray> function_table, Handle<FixedArray> function_table) {
Handle<FixedArray> signature_table) { DCHECK_EQ(0, function_table->length() % compiler::kFunctionTableEntrySize);
Handle<FixedArray> dispatch_tables(table_obj->dispatch_tables()); Handle<FixedArray> dispatch_tables(table_obj->dispatch_tables());
int old_length = dispatch_tables->length(); int old_length = dispatch_tables->length();
DCHECK_EQ(0, old_length % kDispatchTableNumElements); DCHECK_EQ(0, old_length % kDispatchTableNumElements);
...@@ -245,8 +243,6 @@ void WasmTableObject::AddDispatchTable(Isolate* isolate, ...@@ -245,8 +243,6 @@ void WasmTableObject::AddDispatchTable(Isolate* isolate,
Smi::FromInt(table_index)); Smi::FromInt(table_index));
new_dispatch_tables->set(old_length + kDispatchTableFunctionTableOffset, new_dispatch_tables->set(old_length + kDispatchTableFunctionTableOffset,
*function_table); *function_table);
new_dispatch_tables->set(old_length + kDispatchTableSignatureTableOffset,
*signature_table);
table_obj->set_dispatch_tables(*new_dispatch_tables); table_obj->set_dispatch_tables(*new_dispatch_tables);
} }
...@@ -263,24 +259,17 @@ void WasmTableObject::Grow(Isolate* isolate, uint32_t count) { ...@@ -263,24 +259,17 @@ void WasmTableObject::Grow(Isolate* isolate, uint32_t count) {
i += kDispatchTableNumElements) { i += kDispatchTableNumElements) {
Handle<FixedArray> old_function_table(FixedArray::cast( Handle<FixedArray> old_function_table(FixedArray::cast(
dispatch_tables->get(i + kDispatchTableFunctionTableOffset))); dispatch_tables->get(i + kDispatchTableFunctionTableOffset)));
Handle<FixedArray> old_signature_table(FixedArray::cast(
dispatch_tables->get(i + kDispatchTableSignatureTableOffset)));
Handle<FixedArray> new_function_table = isolate->global_handles()->Create( Handle<FixedArray> new_function_table = isolate->global_handles()->Create(
*isolate->factory()->CopyFixedArrayAndGrow(old_function_table, count)); *isolate->factory()->CopyFixedArrayAndGrow(
Handle<FixedArray> new_signature_table = isolate->global_handles()->Create( old_function_table, count * compiler::kFunctionTableEntrySize));
*isolate->factory()->CopyFixedArrayAndGrow(old_signature_table, count));
GlobalHandleAddress new_function_table_addr = new_function_table.address(); GlobalHandleAddress new_function_table_addr = new_function_table.address();
GlobalHandleAddress new_signature_table_addr =
new_signature_table.address();
int table_index = int table_index =
Smi::cast(dispatch_tables->get(i + kDispatchTableIndexOffset))->value(); Smi::cast(dispatch_tables->get(i + kDispatchTableIndexOffset))->value();
// Update dispatch tables with new function tables. // Update dispatch tables with new function tables.
dispatch_tables->set(i + kDispatchTableFunctionTableOffset, dispatch_tables->set(i + kDispatchTableFunctionTableOffset,
*new_function_table); *new_function_table);
dispatch_tables->set(i + kDispatchTableSignatureTableOffset,
*new_signature_table);
// Patch the code of the respective instance. // Patch the code of the respective instance.
if (FLAG_wasm_jit_to_native) { if (FLAG_wasm_jit_to_native) {
...@@ -295,16 +284,11 @@ void WasmTableObject::Grow(Isolate* isolate, uint32_t count) { ...@@ -295,16 +284,11 @@ void WasmTableObject::Grow(Isolate* isolate, uint32_t count) {
native_module); native_module);
GlobalHandleAddress old_function_table_addr = GlobalHandleAddress old_function_table_addr =
native_module->function_tables()[table_index]; native_module->function_tables()[table_index];
GlobalHandleAddress old_signature_table_addr =
native_module->signature_tables()[table_index];
code_specialization.PatchTableSize(old_size, old_size + count); code_specialization.PatchTableSize(old_size, old_size + count);
code_specialization.RelocatePointer(old_function_table_addr, code_specialization.RelocatePointer(old_function_table_addr,
new_function_table_addr); new_function_table_addr);
code_specialization.RelocatePointer(old_signature_table_addr,
new_signature_table_addr);
code_specialization.ApplyToWholeInstance(instance); code_specialization.ApplyToWholeInstance(instance);
native_module->function_tables()[table_index] = new_function_table_addr; native_module->function_tables()[table_index] = new_function_table_addr;
native_module->signature_tables()[table_index] = new_signature_table_addr;
} else { } else {
DisallowHeapAllocation no_gc; DisallowHeapAllocation no_gc;
wasm::CodeSpecialization code_specialization(isolate, wasm::CodeSpecialization code_specialization(isolate,
...@@ -315,21 +299,13 @@ void WasmTableObject::Grow(Isolate* isolate, uint32_t count) { ...@@ -315,21 +299,13 @@ void WasmTableObject::Grow(Isolate* isolate, uint32_t count) {
GlobalHandleAddress old_function_table_addr = GlobalHandleAddress old_function_table_addr =
WasmCompiledModule::GetTableValue(compiled_module->function_tables(), WasmCompiledModule::GetTableValue(compiled_module->function_tables(),
table_index); table_index);
GlobalHandleAddress old_signature_table_addr =
WasmCompiledModule::GetTableValue(compiled_module->signature_tables(),
table_index);
code_specialization.PatchTableSize(old_size, old_size + count); code_specialization.PatchTableSize(old_size, old_size + count);
code_specialization.RelocatePointer(old_function_table_addr, code_specialization.RelocatePointer(old_function_table_addr,
new_function_table_addr); new_function_table_addr);
code_specialization.RelocatePointer(old_signature_table_addr,
new_signature_table_addr);
code_specialization.ApplyToWholeInstance(instance); code_specialization.ApplyToWholeInstance(instance);
WasmCompiledModule::UpdateTableValue(compiled_module->function_tables(), WasmCompiledModule::UpdateTableValue(compiled_module->function_tables(),
table_index, table_index,
new_function_table_addr); new_function_table_addr);
WasmCompiledModule::UpdateTableValue(compiled_module->signature_tables(),
table_index,
new_signature_table_addr);
} }
} }
} }
...@@ -364,42 +340,36 @@ void WasmTableObject::Set(Isolate* isolate, Handle<WasmTableObject> table, ...@@ -364,42 +340,36 @@ void WasmTableObject::Set(Isolate* isolate, Handle<WasmTableObject> table,
isolate, handle(exported_function->instance()), wasm_code, isolate, handle(exported_function->instance()), wasm_code,
exported_function->function_index(), sig); exported_function->function_index(), sig);
} }
UpdateDispatchTables(isolate, table, index, sig, code); UpdateDispatchTables(table, index, sig, code);
array->set(index, *value); array->set(index, *value);
} }
void WasmTableObject::UpdateDispatchTables(Isolate* isolate, void WasmTableObject::UpdateDispatchTables(Handle<WasmTableObject> table,
Handle<WasmTableObject> table,
int index, wasm::FunctionSig* sig, int index, wasm::FunctionSig* sig,
Handle<Object> code_or_foreign) { Handle<Object> code_or_foreign) {
Handle<FixedArray> dispatch_tables(table->dispatch_tables(), isolate); DisallowHeapAllocation no_gc;
FixedArray* dispatch_tables = table->dispatch_tables();
DCHECK_EQ(0, dispatch_tables->length() % kDispatchTableNumElements); DCHECK_EQ(0, dispatch_tables->length() % kDispatchTableNumElements);
for (int i = 0; i < dispatch_tables->length(); for (int i = 0; i < dispatch_tables->length();
i += kDispatchTableNumElements) { i += kDispatchTableNumElements) {
Handle<FixedArray> function_table( FixedArray* function_table = FixedArray::cast(
FixedArray::cast( dispatch_tables->get(i + kDispatchTableFunctionTableOffset));
dispatch_tables->get(i + kDispatchTableFunctionTableOffset)), Smi* sig_smi = Smi::FromInt(-1);
isolate); Object* code = Smi::kZero;
Handle<FixedArray> signature_table(
FixedArray::cast(
dispatch_tables->get(i + kDispatchTableSignatureTableOffset)),
isolate);
if (sig) { if (sig) {
DCHECK(code_or_foreign->IsCode() || code_or_foreign->IsForeign()); DCHECK(code_or_foreign->IsCode() || code_or_foreign->IsForeign());
Handle<WasmInstanceObject> instance( WasmInstanceObject* instance = WasmInstanceObject::cast(
WasmInstanceObject::cast( dispatch_tables->get(i + kDispatchTableInstanceOffset));
dispatch_tables->get(i + kDispatchTableInstanceOffset)),
isolate);
// Note that {SignatureMap::Find} may return {-1} if the signature is // Note that {SignatureMap::Find} may return {-1} if the signature is
// not found; it will simply never match any check. // not found; it will simply never match any check.
auto sig_index = instance->module()->signature_map.Find(sig); auto sig_index = instance->module()->signature_map.Find(sig);
signature_table->set(index, Smi::FromInt(sig_index)); sig_smi = Smi::FromInt(sig_index);
function_table->set(index, *code_or_foreign); code = *code_or_foreign;
} else { } else {
DCHECK(code_or_foreign.is_null()); DCHECK(code_or_foreign.is_null());
signature_table->set(index, Smi::FromInt(-1));
function_table->set(index, Smi::kZero);
} }
function_table->set(compiler::FunctionTableSigOffset(index), sig_smi);
function_table->set(compiler::FunctionTableCodeOffset(index), code);
} }
} }
...@@ -1289,9 +1259,7 @@ Handle<WasmCompiledModule> WasmCompiledModule::New( ...@@ -1289,9 +1259,7 @@ Handle<WasmCompiledModule> WasmCompiledModule::New(
Isolate* isolate, WasmModule* module, Handle<FixedArray> code_table, Isolate* isolate, WasmModule* module, Handle<FixedArray> code_table,
Handle<FixedArray> export_wrappers, Handle<FixedArray> export_wrappers,
const std::vector<GlobalHandleAddress>& function_tables, const std::vector<GlobalHandleAddress>& function_tables,
const std::vector<GlobalHandleAddress>& signature_tables,
bool use_trap_handler) { bool use_trap_handler) {
DCHECK_EQ(function_tables.size(), signature_tables.size());
Handle<FixedArray> ret = Handle<FixedArray> ret =
isolate->factory()->NewFixedArray(PropertyIndices::Count, TENURED); isolate->factory()->NewFixedArray(PropertyIndices::Count, TENURED);
// WasmCompiledModule::cast would fail since fields are not set yet. // WasmCompiledModule::cast would fail since fields are not set yet.
...@@ -1313,21 +1281,15 @@ Handle<WasmCompiledModule> WasmCompiledModule::New( ...@@ -1313,21 +1281,15 @@ Handle<WasmCompiledModule> WasmCompiledModule::New(
int num_function_tables = static_cast<int>(function_tables.size()); int num_function_tables = static_cast<int>(function_tables.size());
if (num_function_tables > 0) { if (num_function_tables > 0) {
Handle<FixedArray> st =
isolate->factory()->NewFixedArray(num_function_tables, TENURED);
Handle<FixedArray> ft = Handle<FixedArray> ft =
isolate->factory()->NewFixedArray(num_function_tables, TENURED); isolate->factory()->NewFixedArray(num_function_tables, TENURED);
for (int i = 0; i < num_function_tables; ++i) { for (int i = 0; i < num_function_tables; ++i) {
size_t index = static_cast<size_t>(i); SetTableValue(isolate, ft, i, function_tables[i]);
SetTableValue(isolate, ft, i, function_tables[index]);
SetTableValue(isolate, st, i, signature_tables[index]);
} }
// TODO(wasm): setting the empty tables here this way is OK under the // TODO(wasm): setting the empty tables here this way is OK under the
// assumption that we compile and then instantiate. It needs rework if we // assumption that we compile and then instantiate. It needs rework if we
// do direct instantiation. The empty tables are used as a default when // do direct instantiation. The empty tables are used as a default when
// resetting the compiled module. // resetting the compiled module.
compiled_module->set_signature_tables(*st);
compiled_module->set_empty_signature_tables(*st);
compiled_module->set_function_tables(*ft); compiled_module->set_function_tables(*ft);
compiled_module->set_empty_function_tables(*ft); compiled_module->set_empty_function_tables(*ft);
} }
...@@ -1357,9 +1319,7 @@ Handle<WasmCompiledModule> WasmCompiledModule::New( ...@@ -1357,9 +1319,7 @@ Handle<WasmCompiledModule> WasmCompiledModule::New(
compiled_module->set_code_table(*code_table); compiled_module->set_code_table(*code_table);
native_module->function_tables() = function_tables; native_module->function_tables() = function_tables;
native_module->signature_tables() = signature_tables;
native_module->empty_function_tables() = function_tables; native_module->empty_function_tables() = function_tables;
native_module->empty_signature_tables() = signature_tables;
int function_count = static_cast<int>(module->functions.size()); int function_count = static_cast<int>(module->functions.size());
Handle<FixedArray> handler_table = Handle<FixedArray> handler_table =
...@@ -1457,27 +1417,18 @@ void WasmCompiledModule::ResetGCModel(Isolate* isolate, ...@@ -1457,27 +1417,18 @@ void WasmCompiledModule::ResetGCModel(Isolate* isolate,
// Reset function tables. // Reset function tables.
if (compiled_module->has_function_tables()) { if (compiled_module->has_function_tables()) {
FixedArray* function_tables = compiled_module->function_tables(); FixedArray* function_tables = compiled_module->function_tables();
FixedArray* signature_tables = compiled_module->signature_tables();
FixedArray* empty_function_tables = FixedArray* empty_function_tables =
compiled_module->empty_function_tables(); compiled_module->empty_function_tables();
FixedArray* empty_signature_tables =
compiled_module->empty_signature_tables();
if (function_tables != empty_function_tables) { if (function_tables != empty_function_tables) {
DCHECK_EQ(function_tables->length(), empty_function_tables->length()); DCHECK_EQ(function_tables->length(), empty_function_tables->length());
for (int i = 0, e = function_tables->length(); i < e; ++i) { for (int i = 0, e = function_tables->length(); i < e; ++i) {
GlobalHandleAddress func_addr = GlobalHandleAddress func_addr =
WasmCompiledModule::GetTableValue(function_tables, i); WasmCompiledModule::GetTableValue(function_tables, i);
GlobalHandleAddress sig_addr =
WasmCompiledModule::GetTableValue(signature_tables, i);
code_specialization.RelocatePointer( code_specialization.RelocatePointer(
func_addr, func_addr,
WasmCompiledModule::GetTableValue(empty_function_tables, i)); WasmCompiledModule::GetTableValue(empty_function_tables, i));
code_specialization.RelocatePointer(
sig_addr,
WasmCompiledModule::GetTableValue(empty_signature_tables, i));
} }
compiled_module->set_function_tables(empty_function_tables); compiled_module->set_function_tables(empty_function_tables);
compiled_module->set_signature_tables(empty_signature_tables);
} }
} }
...@@ -1559,23 +1510,16 @@ void WasmCompiledModule::Reset(Isolate* isolate, ...@@ -1559,23 +1510,16 @@ void WasmCompiledModule::Reset(Isolate* isolate,
if (native_module->function_tables().size() > 0) { if (native_module->function_tables().size() > 0) {
std::vector<GlobalHandleAddress>& function_tables = std::vector<GlobalHandleAddress>& function_tables =
native_module->function_tables(); native_module->function_tables();
std::vector<GlobalHandleAddress>& signature_tables =
native_module->signature_tables();
std::vector<GlobalHandleAddress>& empty_function_tables = std::vector<GlobalHandleAddress>& empty_function_tables =
native_module->empty_function_tables(); native_module->empty_function_tables();
std::vector<GlobalHandleAddress>& empty_signature_tables =
native_module->empty_signature_tables();
if (function_tables != empty_function_tables) { if (function_tables != empty_function_tables) {
DCHECK_EQ(function_tables.size(), empty_function_tables.size()); DCHECK_EQ(function_tables.size(), empty_function_tables.size());
for (size_t i = 0, e = function_tables.size(); i < e; ++i) { for (size_t i = 0, e = function_tables.size(); i < e; ++i) {
code_specialization.RelocatePointer(function_tables[i], code_specialization.RelocatePointer(function_tables[i],
empty_function_tables[i]); empty_function_tables[i]);
code_specialization.RelocatePointer(signature_tables[i],
empty_signature_tables[i]);
} }
native_module->function_tables() = empty_function_tables; native_module->function_tables() = empty_function_tables;
native_module->signature_tables() = empty_signature_tables;
} }
} }
...@@ -1725,39 +1669,22 @@ void WasmCompiledModule::ReinitializeAfterDeserialization( ...@@ -1725,39 +1669,22 @@ void WasmCompiledModule::ReinitializeAfterDeserialization(
// which will relocate the code. We end up with a WasmCompiledModule as-if // which will relocate the code. We end up with a WasmCompiledModule as-if
// it were just compiled. // it were just compiled.
Handle<FixedArray> function_tables; Handle<FixedArray> function_tables;
Handle<FixedArray> signature_tables;
if (!FLAG_wasm_jit_to_native) { if (!FLAG_wasm_jit_to_native) {
DCHECK(compiled_module->has_function_tables()); DCHECK(compiled_module->has_function_tables());
DCHECK(compiled_module->has_signature_tables());
DCHECK(compiled_module->has_empty_signature_tables());
DCHECK(compiled_module->has_empty_function_tables());
function_tables = function_tables =
handle(compiled_module->empty_function_tables(), isolate); handle(compiled_module->empty_function_tables(), isolate);
signature_tables =
handle(compiled_module->empty_signature_tables(), isolate);
} else { } else {
DCHECK_GT(native_module->function_tables().size(), 0); DCHECK_GT(native_module->function_tables().size(), 0);
DCHECK_GT(native_module->signature_tables().size(), 0);
DCHECK_EQ(native_module->empty_signature_tables().size(),
native_module->function_tables().size());
DCHECK_EQ(native_module->empty_function_tables().size(),
native_module->function_tables().size());
} }
for (size_t i = 0; i < function_table_count; ++i) { for (size_t i = 0; i < function_table_count; ++i) {
Handle<Object> global_func_table_handle = Handle<Object> global_func_table_handle =
isolate->global_handles()->Create(isolate->heap()->undefined_value()); isolate->global_handles()->Create(isolate->heap()->undefined_value());
Handle<Object> global_sig_table_handle =
isolate->global_handles()->Create(isolate->heap()->undefined_value());
GlobalHandleAddress new_func_table = global_func_table_handle.address(); GlobalHandleAddress new_func_table = global_func_table_handle.address();
GlobalHandleAddress new_sig_table = global_sig_table_handle.address();
if (!FLAG_wasm_jit_to_native) { if (!FLAG_wasm_jit_to_native) {
SetTableValue(isolate, function_tables, static_cast<int>(i), SetTableValue(isolate, function_tables, static_cast<int>(i),
new_func_table); new_func_table);
SetTableValue(isolate, signature_tables, static_cast<int>(i),
new_sig_table);
} else { } else {
native_module->empty_function_tables()[i] = new_func_table; native_module->empty_function_tables()[i] = new_func_table;
native_module->empty_signature_tables()[i] = new_sig_table;
} }
} }
} }
......
...@@ -132,14 +132,12 @@ class WasmTableObject : public JSObject { ...@@ -132,14 +132,12 @@ class WasmTableObject : public JSObject {
static void AddDispatchTable(Isolate* isolate, Handle<WasmTableObject> table, static void AddDispatchTable(Isolate* isolate, Handle<WasmTableObject> table,
Handle<WasmInstanceObject> instance, Handle<WasmInstanceObject> instance,
int table_index, int table_index,
Handle<FixedArray> function_table, Handle<FixedArray> function_table);
Handle<FixedArray> signature_table);
static void Set(Isolate* isolate, Handle<WasmTableObject> table, static void Set(Isolate* isolate, Handle<WasmTableObject> table,
int32_t index, Handle<JSFunction> function); int32_t index, Handle<JSFunction> function);
static void UpdateDispatchTables(Isolate* isolate, static void UpdateDispatchTables(Handle<WasmTableObject> table, int index,
Handle<WasmTableObject> table, int index,
wasm::FunctionSig* sig, wasm::FunctionSig* sig,
Handle<Object> code_or_foreign); Handle<Object> code_or_foreign);
}; };
...@@ -196,7 +194,6 @@ class WasmInstanceObject : public JSObject { ...@@ -196,7 +194,6 @@ class WasmInstanceObject : public JSObject {
DECL_OPTIONAL_ACCESSORS(debug_info, WasmDebugInfo) DECL_OPTIONAL_ACCESSORS(debug_info, WasmDebugInfo)
DECL_OPTIONAL_ACCESSORS(table_object, WasmTableObject) DECL_OPTIONAL_ACCESSORS(table_object, WasmTableObject)
DECL_OPTIONAL_ACCESSORS(function_tables, FixedArray) DECL_OPTIONAL_ACCESSORS(function_tables, FixedArray)
DECL_OPTIONAL_ACCESSORS(signature_tables, FixedArray)
// FixedArray of all instances whose code was imported // FixedArray of all instances whose code was imported
DECL_OPTIONAL_ACCESSORS(directly_called_instances, FixedArray) DECL_OPTIONAL_ACCESSORS(directly_called_instances, FixedArray)
...@@ -211,7 +208,6 @@ class WasmInstanceObject : public JSObject { ...@@ -211,7 +208,6 @@ class WasmInstanceObject : public JSObject {
kDebugInfoIndex, kDebugInfoIndex,
kTableObjectIndex, kTableObjectIndex,
kFunctionTablesIndex, kFunctionTablesIndex,
kSignatureTablesIndex,
kDirectlyCalledInstancesIndex, kDirectlyCalledInstancesIndex,
kJsImportsTableIndex, kJsImportsTableIndex,
kFieldCount kFieldCount
...@@ -226,7 +222,6 @@ class WasmInstanceObject : public JSObject { ...@@ -226,7 +222,6 @@ class WasmInstanceObject : public JSObject {
DEF_OFFSET(DebugInfo) DEF_OFFSET(DebugInfo)
DEF_OFFSET(TableObject) DEF_OFFSET(TableObject)
DEF_OFFSET(FunctionTables) DEF_OFFSET(FunctionTables)
DEF_OFFSET(SignatureTables)
DEF_OFFSET(DirectlyCalledInstances) DEF_OFFSET(DirectlyCalledInstances)
DEF_OFFSET(JsImportsTable) DEF_OFFSET(JsImportsTable)
...@@ -519,7 +514,6 @@ class WasmCompiledModule : public FixedArray { ...@@ -519,7 +514,6 @@ class WasmCompiledModule : public FixedArray {
Isolate* isolate, wasm::WasmModule* module, Handle<FixedArray> code_table, Isolate* isolate, wasm::WasmModule* module, Handle<FixedArray> code_table,
Handle<FixedArray> export_wrappers, Handle<FixedArray> export_wrappers,
const std::vector<wasm::GlobalHandleAddress>& function_tables, const std::vector<wasm::GlobalHandleAddress>& function_tables,
const std::vector<wasm::GlobalHandleAddress>& signature_tables,
bool use_trap_hander); bool use_trap_hander);
static Handle<WasmCompiledModule> Clone(Isolate* isolate, static Handle<WasmCompiledModule> Clone(Isolate* isolate,
......
...@@ -213,8 +213,8 @@ size_t NativeModuleSerializer::MeasureHeader() const { ...@@ -213,8 +213,8 @@ size_t NativeModuleSerializer::MeasureHeader() const {
sizeof( sizeof(
uint32_t) + // imported fcts - i.e. index of first wasm function uint32_t) + // imported fcts - i.e. index of first wasm function
sizeof(uint32_t) + // table count sizeof(uint32_t) + // table count
native_module_->specialization_data_.function_tables.size() * native_module_->specialization_data_.function_tables.size()
2 // 2 same-sized tables, containing pointers // function table, containing pointers
* sizeof(GlobalHandleAddress); * sizeof(GlobalHandleAddress);
} }
...@@ -231,7 +231,6 @@ void NativeModuleSerializer::BufferHeader() { ...@@ -231,7 +231,6 @@ void NativeModuleSerializer::BufferHeader() {
e = native_module_->specialization_data_.function_tables.size(); e = native_module_->specialization_data_.function_tables.size();
i < e; ++i) { i < e; ++i) {
writer.Write(native_module_->specialization_data_.function_tables[i]); writer.Write(native_module_->specialization_data_.function_tables[i]);
writer.Write(native_module_->specialization_data_.signature_tables[i]);
} }
} }
...@@ -558,18 +557,14 @@ bool NativeModuleDeserializer::ReadHeader() { ...@@ -558,18 +557,14 @@ bool NativeModuleDeserializer::ReadHeader() {
if (!ok) return false; if (!ok) return false;
size_t table_count = reader.Read<uint32_t>(); size_t table_count = reader.Read<uint32_t>();
std::vector<GlobalHandleAddress> sigs(table_count);
std::vector<GlobalHandleAddress> funcs(table_count); std::vector<GlobalHandleAddress> funcs(table_count);
for (size_t i = 0; i < table_count; ++i) { for (size_t i = 0; i < table_count; ++i) {
funcs[i] = reader.Read<GlobalHandleAddress>(); funcs[i] = reader.Read<GlobalHandleAddress>();
sigs[i] = reader.Read<GlobalHandleAddress>();
} }
native_module_->signature_tables() = sigs;
native_module_->function_tables() = funcs; native_module_->function_tables() = funcs;
// resize, so that from here on the native module can be // resize, so that from here on the native module can be
// asked about num_function_tables(). // asked about num_function_tables().
native_module_->empty_function_tables().resize(table_count); native_module_->empty_function_tables().resize(table_count);
native_module_->empty_signature_tables().resize(table_count);
unread_ = unread_ + (start_size - reader.current_buffer().size()); unread_ = unread_ + (start_size - reader.current_buffer().size());
return true; return true;
...@@ -739,9 +734,8 @@ MaybeHandle<WasmCompiledModule> DeserializeNativeModule( ...@@ -739,9 +734,8 @@ MaybeHandle<WasmCompiledModule> DeserializeNativeModule(
static_cast<int>(export_wrappers_size), TENURED); static_cast<int>(export_wrappers_size), TENURED);
Handle<WasmCompiledModule> compiled_module = WasmCompiledModule::New( Handle<WasmCompiledModule> compiled_module = WasmCompiledModule::New(
isolate, shared->module(), isolate->factory()->NewFixedArray(0, TENURED), isolate, shared->module(), isolate->factory()->empty_fixed_array(),
export_wrappers, std::vector<wasm::GlobalHandleAddress>(), export_wrappers, std::vector<wasm::GlobalHandleAddress>(),
std::vector<wasm::GlobalHandleAddress>(),
trap_handler::IsTrapHandlerEnabled()); trap_handler::IsTrapHandlerEnabled());
compiled_module->OnWasmModuleDecodingComplete(shared); compiled_module->OnWasmModuleDecodingComplete(shared);
NativeModuleDeserializer deserializer(isolate, NativeModuleDeserializer deserializer(isolate,
......
...@@ -144,8 +144,8 @@ Handle<JSFunction> TestingModuleBuilder::WrapCode(uint32_t index) { ...@@ -144,8 +144,8 @@ Handle<JSFunction> TestingModuleBuilder::WrapCode(uint32_t index) {
return ret; return ret;
} }
void TestingModuleBuilder::AddIndirectFunctionTable(uint16_t* function_indexes, void TestingModuleBuilder::AddIndirectFunctionTable(
uint32_t table_size) { const uint16_t* function_indexes, uint32_t table_size) {
test_module_.function_tables.emplace_back(); test_module_.function_tables.emplace_back();
WasmIndirectFunctionTable& table = test_module_.function_tables.back(); WasmIndirectFunctionTable& table = test_module_.function_tables.back();
table.initial_size = table_size; table.initial_size = table_size;
...@@ -155,14 +155,10 @@ void TestingModuleBuilder::AddIndirectFunctionTable(uint16_t* function_indexes, ...@@ -155,14 +155,10 @@ void TestingModuleBuilder::AddIndirectFunctionTable(uint16_t* function_indexes,
table.values.push_back(function_indexes[i]); table.values.push_back(function_indexes[i]);
} }
FixedArray* func_table = *isolate_->factory()->NewFixedArray(
table_size * compiler::kFunctionTableEntrySize);
function_tables_.push_back( function_tables_.push_back(
isolate_->global_handles() isolate_->global_handles()->Create(func_table).address());
->Create(*isolate_->factory()->NewFixedArray(table_size))
.address());
signature_tables_.push_back(
isolate_->global_handles()
->Create(*isolate_->factory()->NewFixedArray(table_size))
.address());
} }
void TestingModuleBuilder::PopulateIndirectFunctionTable() { void TestingModuleBuilder::PopulateIndirectFunctionTable() {
...@@ -172,22 +168,23 @@ void TestingModuleBuilder::PopulateIndirectFunctionTable() { ...@@ -172,22 +168,23 @@ void TestingModuleBuilder::PopulateIndirectFunctionTable() {
WasmIndirectFunctionTable& table = test_module_.function_tables[i]; WasmIndirectFunctionTable& table = test_module_.function_tables[i];
Handle<FixedArray> function_table( Handle<FixedArray> function_table(
reinterpret_cast<FixedArray**>(function_tables_[i])); reinterpret_cast<FixedArray**>(function_tables_[i]));
Handle<FixedArray> signature_table(
reinterpret_cast<FixedArray**>(signature_tables_[i]));
int table_size = static_cast<int>(table.values.size()); int table_size = static_cast<int>(table.values.size());
for (int j = 0; j < table_size; j++) { for (int j = 0; j < table_size; j++) {
WasmFunction& function = test_module_.functions[table.values[j]]; WasmFunction& function = test_module_.functions[table.values[j]];
signature_table->set( function_table->set(
j, Smi::FromInt(test_module_.signature_map.Find(function.sig))); compiler::FunctionTableSigOffset(j),
Smi::FromInt(test_module_.signature_map.Find(function.sig)));
if (FLAG_wasm_jit_to_native) { if (FLAG_wasm_jit_to_native) {
Handle<Foreign> foreign_holder = isolate_->factory()->NewForeign( Handle<Foreign> foreign_holder = isolate_->factory()->NewForeign(
native_module_->GetCode(function.func_index) native_module_->GetCode(function.func_index)
->instructions() ->instructions()
.start(), .start(),
TENURED); TENURED);
function_table->set(j, *foreign_holder); function_table->set(compiler::FunctionTableCodeOffset(j),
*foreign_holder);
} else { } else {
function_table->set(j, *function_code_[function.func_index]); function_table->set(compiler::FunctionTableCodeOffset(j),
*function_code_[function.func_index]);
} }
} }
} }
...@@ -211,9 +208,8 @@ uint32_t TestingModuleBuilder::AddBytes(Vector<const byte> bytes) { ...@@ -211,9 +208,8 @@ uint32_t TestingModuleBuilder::AddBytes(Vector<const byte> bytes) {
} }
compiler::ModuleEnv TestingModuleBuilder::CreateModuleEnv() { compiler::ModuleEnv TestingModuleBuilder::CreateModuleEnv() {
return {&test_module_, function_tables_, return {&test_module_, function_tables_, function_code_, Handle<Code>::null(),
signature_tables_, function_code_, trap_handler::IsTrapHandlerEnabled()};
Handle<Code>::null(), trap_handler::IsTrapHandlerEnabled()};
} }
const WasmGlobal* TestingModuleBuilder::AddGlobal(ValueType type) { const WasmGlobal* TestingModuleBuilder::AddGlobal(ValueType type) {
...@@ -244,7 +240,7 @@ Handle<WasmInstanceObject> TestingModuleBuilder::InitInstanceObject() { ...@@ -244,7 +240,7 @@ Handle<WasmInstanceObject> TestingModuleBuilder::InitInstanceObject() {
Handle<FixedArray> export_wrappers = isolate_->factory()->NewFixedArray(0); Handle<FixedArray> export_wrappers = isolate_->factory()->NewFixedArray(0);
Handle<WasmCompiledModule> compiled_module = WasmCompiledModule::New( Handle<WasmCompiledModule> compiled_module = WasmCompiledModule::New(
isolate_, test_module_ptr_, code_table, export_wrappers, function_tables_, isolate_, test_module_ptr_, code_table, export_wrappers, function_tables_,
signature_tables_, trap_handler::IsTrapHandlerEnabled()); trap_handler::IsTrapHandlerEnabled());
compiled_module->OnWasmModuleDecodingComplete(shared_module_data); compiled_module->OnWasmModuleDecodingComplete(shared_module_data);
// This method is called when we initialize TestEnvironment. We don't // This method is called when we initialize TestEnvironment. We don't
// have a memory yet, so we won't create it here. We'll update the // have a memory yet, so we won't create it here. We'll update the
......
...@@ -191,7 +191,7 @@ class TestingModuleBuilder { ...@@ -191,7 +191,7 @@ class TestingModuleBuilder {
function_code_[index] = code; function_code_[index] = code;
} }
void AddIndirectFunctionTable(uint16_t* function_indexes, void AddIndirectFunctionTable(const uint16_t* function_indexes,
uint32_t table_size); uint32_t table_size);
void PopulateIndirectFunctionTable(); void PopulateIndirectFunctionTable();
...@@ -244,7 +244,6 @@ class TestingModuleBuilder { ...@@ -244,7 +244,6 @@ class TestingModuleBuilder {
uint32_t mem_size_; uint32_t mem_size_;
std::vector<Handle<Code>> function_code_; std::vector<Handle<Code>> function_code_;
std::vector<GlobalHandleAddress> function_tables_; std::vector<GlobalHandleAddress> function_tables_;
std::vector<GlobalHandleAddress> signature_tables_;
V8_ALIGNED(16) byte globals_data_[kMaxGlobalsSize]; V8_ALIGNED(16) byte globals_data_[kMaxGlobalsSize];
WasmInterpreter* interpreter_; WasmInterpreter* interpreter_;
WasmExecutionMode execution_mode_; WasmExecutionMode execution_mode_;
......
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