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