Commit 6b8d17e3 authored by mtrofin's avatar mtrofin Committed by Commit bot

[wasm] globals size is not a per-instance property.

Moved globals offsets calculation to the wasm module decoder, since
this is a property of the module, not of each instance.

Qualified as "const" references to WasmModule outside of the decoder
and some test situations.

BUG=

Review-Url: https://codereview.chromium.org/2005933003
Cr-Commit-Position: refs/heads/master@{#36484}
parent 9be961f5
......@@ -2965,7 +2965,7 @@ static void RecordFunctionCompilation(Logger::LogEventsAndTags tag,
Handle<JSFunction> CompileJSToWasmWrapper(
Isolate* isolate, wasm::ModuleEnv* module, Handle<String> name,
Handle<Code> wasm_code, Handle<JSObject> module_object, uint32_t index) {
wasm::WasmFunction* func = &module->module->functions[index];
const wasm::WasmFunction* func = &module->module->functions[index];
//----------------------------------------------------------------------------
// Create the JSFunction object.
......
......@@ -419,7 +419,9 @@ class ModuleDecoder : public Decoder {
}
done:
ModuleResult result = toResult(module);
CalculateGlobalsOffsets(module);
const WasmModule* finished_module = module;
ModuleResult result = toResult(finished_module);
if (FLAG_dump_wasm_module) {
DumpModule(module, result);
}
......@@ -570,6 +572,22 @@ class ModuleDecoder : public Decoder {
consume_bytes(segment->source_size);
}
// Calculate individual global offsets and total size of globals table.
void CalculateGlobalsOffsets(WasmModule* module) {
uint32_t offset = 0;
if (module->globals.size() == 0) {
module->globals_size = 0;
return;
}
for (WasmGlobal& global : module->globals) {
byte size = WasmOpcodes::MemSize(global.type);
offset = (offset + size - 1) & ~(size - 1); // align
global.offset = offset;
offset += size;
}
module->globals_size = offset;
}
// Verifies the body (code) of a given function.
void VerifyFunctionBody(uint32_t func_num, ModuleEnv* menv,
WasmFunction* function) {
......
......@@ -20,7 +20,8 @@ namespace wasm {
// concatenation of all function names.
//
// Returns undefined if the array length would not fit in an integer value.
Handle<Object> BuildFunctionNamesTable(Isolate* isolate, WasmModule* module) {
Handle<Object> BuildFunctionNamesTable(Isolate* isolate,
const WasmModule* module) {
uint64_t func_names_length = 0;
for (auto& func : module->functions) func_names_length += func.name_length;
int num_funcs_int = static_cast<int>(module->functions.size());
......@@ -36,7 +37,7 @@ Handle<Object> BuildFunctionNamesTable(Isolate* isolate, WasmModule* module) {
if (func_names_array.is_null()) return isolate->factory()->undefined_value();
func_names_array->set_int(0, num_funcs_int);
int func_index = 0;
for (WasmFunction& fun : module->functions) {
for (const WasmFunction& fun : module->functions) {
WasmName name = module->GetNameOrNull(&fun);
if (name.start() == nullptr) {
func_names_array->set_int(func_index + 1, -current_offset);
......
......@@ -17,7 +17,8 @@ struct WasmModule;
// Encode all function names of the WasmModule into one ByteArray.
// Returns undefined if the array length would not fit in an integer value.
Handle<Object> BuildFunctionNamesTable(Isolate* isolate, WasmModule* module);
Handle<Object> BuildFunctionNamesTable(Isolate* isolate,
const WasmModule* module);
// Extract the function name for the given func_index from the function name
// table.
......
......@@ -142,7 +142,7 @@ class WasmLinker {
}
void Link(Handle<FixedArray> function_table,
std::vector<uint16_t>& functions) {
const std::vector<uint16_t>& functions) {
for (size_t i = 0; i < function_code_.size(); i++) {
LinkFunction(function_code_[i]);
}
......@@ -203,19 +203,8 @@ const int kWasmMemArrayBuffer = 2;
const int kWasmGlobalsArrayBuffer = 3;
const int kWasmFunctionNamesArray = 4;
size_t AllocateGlobalsOffsets(std::vector<WasmGlobal>& globals) {
uint32_t offset = 0;
if (globals.size() == 0) return 0;
for (WasmGlobal& global : globals) {
byte size = WasmOpcodes::MemSize(global.type);
offset = (offset + size - 1) & ~(size - 1); // align
global.offset = offset;
offset += size;
}
return offset;
}
void LoadDataSegments(WasmModule* module, byte* mem_addr, size_t mem_size) {
void LoadDataSegments(const WasmModule* module, byte* mem_addr,
size_t mem_size) {
for (const WasmDataSegment& segment : module->data_segments) {
if (!segment.init) continue;
if (!segment.source_size) continue;
......@@ -228,14 +217,16 @@ void LoadDataSegments(WasmModule* module, byte* mem_addr, size_t mem_size) {
}
}
Handle<FixedArray> BuildFunctionTable(Isolate* isolate, WasmModule* module) {
Handle<FixedArray> BuildFunctionTable(Isolate* isolate,
const WasmModule* module) {
if (module->function_table.size() == 0) {
return Handle<FixedArray>::null();
}
int table_size = static_cast<int>(module->function_table.size());
Handle<FixedArray> fixed = isolate->factory()->NewFixedArray(2 * table_size);
for (int i = 0; i < table_size; i++) {
WasmFunction* function = &module->functions[module->function_table[i]];
const WasmFunction* function =
&module->functions[module->function_table[i]];
fixed->set(i, Smi::FromInt(function->sig_index));
}
return fixed;
......@@ -302,11 +293,10 @@ bool AllocateMemory(ErrorThrower* thrower, Isolate* isolate,
bool AllocateGlobals(ErrorThrower* thrower, Isolate* isolate,
WasmModuleInstance* instance) {
instance->globals_size = AllocateGlobalsOffsets(instance->module->globals);
if (instance->globals_size > 0) {
instance->globals_buffer = NewArrayBuffer(isolate, instance->globals_size,
&instance->globals_start);
uint32_t globals_size = instance->module->globals_size;
if (globals_size > 0) {
instance->globals_buffer =
NewArrayBuffer(isolate, globals_size, &instance->globals_start);
if (!instance->globals_start) {
// Not enough space for backing store of globals.
thrower->Error("Out of memory: wasm globals");
......@@ -473,12 +463,10 @@ struct CodeStats {
}
};
bool CompileWrappersToImportedFunctions(Isolate* isolate, WasmModule* module,
const Handle<JSReceiver> ffi,
WasmModuleInstance* instance,
ErrorThrower* thrower, Factory* factory,
ModuleEnv* module_env,
CodeStats& code_stats) {
bool CompileWrappersToImportedFunctions(
Isolate* isolate, const WasmModule* module, const Handle<JSReceiver> ffi,
WasmModuleInstance* instance, ErrorThrower* thrower, Factory* factory,
ModuleEnv* module_env, CodeStats& code_stats) {
uint32_t index = 0;
if (module->import_table.size() > 0) {
instance->import_code.reserve(module->import_table.size());
......@@ -503,7 +491,7 @@ bool CompileWrappersToImportedFunctions(Isolate* isolate, WasmModule* module,
}
void InitializeParallelCompilation(
Isolate* isolate, std::vector<WasmFunction>& functions,
Isolate* isolate, const std::vector<WasmFunction>& functions,
std::vector<compiler::WasmCompilationUnit*>& compilation_units,
ModuleEnv& module_env, ErrorThrower& thrower) {
// Create a placeholder code object for all functions.
......@@ -555,7 +543,6 @@ void WaitForCompilationTasks(
}
void FinishCompilationUnits(
WasmModule* module,
std::queue<compiler::WasmCompilationUnit*>& executed_units,
std::vector<Handle<Code>>& results, base::Mutex& result_mutex) {
while (true) {
......@@ -574,7 +561,7 @@ void FinishCompilationUnits(
}
}
bool FinishCompilation(Isolate* isolate, WasmModule* module,
bool FinishCompilation(Isolate* isolate, const WasmModule* module,
const Handle<JSReceiver> ffi,
const std::vector<Handle<Code>>& results,
const WasmModuleInstance& instance,
......@@ -636,9 +623,9 @@ bool FinishCompilation(Isolate* isolate, WasmModule* module,
// * installs a named property "memory" for that buffer if exported
// * installs named properties on the object for exported functions
// * compiles wasm code to machine code
MaybeHandle<JSObject> WasmModule::Instantiate(Isolate* isolate,
Handle<JSReceiver> ffi,
Handle<JSArrayBuffer> memory) {
MaybeHandle<JSObject> WasmModule::Instantiate(
Isolate* isolate, Handle<JSReceiver> ffi,
Handle<JSArrayBuffer> memory) const {
HistogramTimerScope wasm_instantiate_module_time_scope(
isolate->counters()->wasm_instantiate_module_time());
ErrorThrower thrower(isolate, "WasmModule::Instantiate()");
......@@ -775,13 +762,13 @@ MaybeHandle<JSObject> WasmModule::Instantiate(Isolate* isolate,
// dequeues it and finishes the compilation unit. Compilation units
// are finished concurrently to the background threads to save
// memory.
FinishCompilationUnits(this, executed_units, results, result_mutex);
FinishCompilationUnits(executed_units, results, result_mutex);
}
// 4) After the parallel phase of all compilation units has started, the
// main thread waits for all {WasmCompilationTask} instances to finish.
WaitForCompilationTasks(isolate, task_ids.get(), pending_tasks);
// Finish the compilation of the remaining compilation units.
FinishCompilationUnits(this, executed_units, results, result_mutex);
FinishCompilationUnits(executed_units, results, result_mutex);
}
// 5) The main thread finishes the compilation.
if (!FinishCompilation(isolate, this, ffi, results, instance, code_table,
......@@ -881,7 +868,7 @@ compiler::CallDescriptor* ModuleEnv::GetCallDescriptor(Zone* zone,
DCHECK(IsValidFunction(index));
// Always make a direct call to whatever is in the table at that location.
// A wrapper will be generated for FFI calls.
WasmFunction* function = &module->functions[index];
const WasmFunction* function = &module->functions[index];
return GetWasmCallDescriptor(zone, function->sig);
}
......@@ -910,7 +897,7 @@ int32_t CompileAndRunWasmModule(Isolate* isolate, const byte* module_start,
return retval;
}
int32_t CompileAndRunWasmModule(Isolate* isolate, WasmModule* module) {
int32_t CompileAndRunWasmModule(Isolate* isolate, const WasmModule* module) {
ErrorThrower thrower(isolate, "CompileAndRunWasmModule");
WasmModuleInstance instance(module);
......
......@@ -169,6 +169,7 @@ struct WasmModule {
ModuleOrigin origin; // origin of the module
std::vector<WasmGlobal> globals; // globals in this module.
uint32_t globals_size; // size of globals table.
std::vector<FunctionSig*> signatures; // signatures in this module.
std::vector<WasmFunction> functions; // functions in this module.
std::vector<WasmDataSegment> data_segments; // data segments in this module.
......@@ -202,7 +203,7 @@ struct WasmModule {
}
// Get a string stored in the module bytes representing a function name.
WasmName GetNameOrNull(WasmFunction* function) const {
WasmName GetNameOrNull(const WasmFunction* function) const {
return GetNameOrNull(function->name_offset, function->name_length);
}
......@@ -214,12 +215,12 @@ struct WasmModule {
// Creates a new instantiation of the module in the given isolate.
MaybeHandle<JSObject> Instantiate(Isolate* isolate, Handle<JSReceiver> ffi,
Handle<JSArrayBuffer> memory);
Handle<JSArrayBuffer> memory) const;
};
// An instantiated WASM module, including memory, function table, etc.
struct WasmModuleInstance {
WasmModule* module; // static representation of the module.
const WasmModule* module; // static representation of the module.
// -- Heap allocated --------------------------------------------------------
Handle<JSObject> js_object; // JavaScript module object.
Handle<Context> context; // JavaScript native context.
......@@ -233,14 +234,9 @@ struct WasmModuleInstance {
size_t mem_size; // size of the linear memory.
// -- raw globals -----------------------------------------------------------
byte* globals_start; // start of the globals area.
size_t globals_size; // size of the globals area.
explicit WasmModuleInstance(WasmModule* m)
: module(m),
mem_start(nullptr),
mem_size(0),
globals_start(nullptr),
globals_size(0) {}
explicit WasmModuleInstance(const WasmModule* m)
: module(m), mem_start(nullptr), mem_size(0), globals_start(nullptr) {}
};
// forward declaration.
......@@ -249,7 +245,7 @@ class WasmLinker;
// Interface provided to the decoder/graph builder which contains only
// minimal information about the globals, functions, and function tables.
struct ModuleEnv {
WasmModule* module;
const WasmModule* module;
WasmModuleInstance* instance;
WasmLinker* linker;
ModuleOrigin origin;
......@@ -311,7 +307,7 @@ std::ostream& operator<<(std::ostream& os, const WasmModule& module);
std::ostream& operator<<(std::ostream& os, const WasmFunction& function);
std::ostream& operator<<(std::ostream& os, const WasmFunctionName& name);
typedef Result<WasmModule*> ModuleResult;
typedef Result<const WasmModule*> ModuleResult;
typedef Result<WasmFunction*> FunctionResult;
// For testing. Decode, verify, and run the last exported function in the
......@@ -321,7 +317,7 @@ int32_t CompileAndRunWasmModule(Isolate* isolate, const byte* module_start,
// For testing. Decode, verify, and run the last exported function in the
// given decoded module.
int32_t CompileAndRunWasmModule(Isolate* isolate, WasmModule* module);
int32_t CompileAndRunWasmModule(Isolate* isolate, const WasmModule* module);
// Extract a function name from the given wasm object.
// Returns a null handle if the function is unnamed or the name is not a valid
......
......@@ -80,7 +80,7 @@ class TestingModule : public ModuleEnv {
instance = &instance_;
instance->module = &module_;
instance->globals_start = global_data;
instance->globals_size = kMaxGlobalsSize;
module_.globals_size = kMaxGlobalsSize;
instance->mem_start = nullptr;
instance->mem_size = 0;
linker = nullptr;
......@@ -112,12 +112,12 @@ class TestingModule : public ModuleEnv {
template <typename T>
T* AddGlobal(MachineType mem_type) {
WasmGlobal* global = AddGlobal(mem_type);
const WasmGlobal* global = AddGlobal(mem_type);
return reinterpret_cast<T*>(instance->globals_start + global->offset);
}
byte AddSignature(FunctionSig* sig) {
module->signatures.push_back(sig);
module_.signatures.push_back(sig);
size_t size = module->signatures.size();
CHECK(size < 127);
return static_cast<byte>(size - 1);
......@@ -167,10 +167,10 @@ class TestingModule : public ModuleEnv {
if (module->functions.size() == 0) {
// TODO(titzer): Reserving space here to avoid the underlying WasmFunction
// structs from moving.
module->functions.reserve(kMaxFunctions);
module_.functions.reserve(kMaxFunctions);
}
uint32_t index = static_cast<uint32_t>(module->functions.size());
module->functions.push_back({sig, index, 0, 0, 0, 0, 0, false});
module_.functions.push_back({sig, index, 0, 0, 0, 0, 0, false});
instance->function_code.push_back(code);
DCHECK_LT(index, kMaxFunctions); // limited for testing.
return index;
......@@ -208,7 +208,7 @@ class TestingModule : public ModuleEnv {
instance->function_table = fixed;
DCHECK_EQ(0u, module->function_table.size());
for (int i = 0; i < table_size; i++) {
module->function_table.push_back(functions[i]);
module_.function_table.push_back(functions[i]);
}
}
......@@ -217,12 +217,13 @@ class TestingModule : public ModuleEnv {
int table_size = static_cast<int>(module->function_table.size());
for (int i = 0; i < table_size; i++) {
int function_index = module->function_table[i];
WasmFunction* function = &module->functions[function_index];
const WasmFunction* function = &module->functions[function_index];
instance->function_table->set(i, Smi::FromInt(function->sig_index));
instance->function_table->set(i + table_size,
*instance->function_code[function_index]);
}
}
WasmFunction* GetFunctionAt(int index) { return &module_.functions[index]; }
private:
WasmModule module_;
......@@ -231,10 +232,10 @@ class TestingModule : public ModuleEnv {
uint32_t global_offset;
V8_ALIGNED(8) byte global_data[kMaxGlobalsSize]; // preallocated global data.
WasmGlobal* AddGlobal(MachineType mem_type) {
const WasmGlobal* AddGlobal(MachineType mem_type) {
byte size = WasmOpcodes::MemSize(mem_type);
global_offset = (global_offset + size - 1) & ~(size - 1); // align
module->globals.push_back({0, 0, mem_type, global_offset, false});
module_.globals.push_back({0, 0, mem_type, global_offset, false});
global_offset += size;
// limit number of globals.
CHECK_LT(global_offset, kMaxGlobalsSize);
......@@ -524,7 +525,7 @@ class WasmFunctionCompiler : public HandleAndZoneScope,
WasmFunction* function() {
if (function_) return function_;
return &testing_module_->module->functions[function_index_];
return testing_module_->GetFunctionAt(function_index_);
}
// Set the context, such that e.g. runtime functions can be called.
......
......@@ -156,7 +156,7 @@ TEST_F(WasmModuleVerifyTest, OneGlobal) {
EXPECT_EQ(0, result.val->functions.size());
EXPECT_EQ(0, result.val->data_segments.size());
WasmGlobal* global = &result.val->globals.back();
const WasmGlobal* global = &result.val->globals.back();
EXPECT_EQ(1, global->name_length);
EXPECT_EQ(MachineType::Int32(), global->type);
......@@ -262,8 +262,8 @@ TEST_F(WasmModuleVerifyTest, TwoGlobals) {
EXPECT_EQ(0, result.val->functions.size());
EXPECT_EQ(0, result.val->data_segments.size());
WasmGlobal* g0 = &result.val->globals[0];
WasmGlobal* g1 = &result.val->globals[1];
const WasmGlobal* g0 = &result.val->globals[0];
const WasmGlobal* g1 = &result.val->globals[1];
EXPECT_EQ(0, g0->name_length);
EXPECT_EQ(MachineType::Float32(), g0->type);
......@@ -272,7 +272,7 @@ TEST_F(WasmModuleVerifyTest, TwoGlobals) {
EXPECT_EQ(0, g1->name_length);
EXPECT_EQ(MachineType::Float64(), g1->type);
EXPECT_EQ(0, g1->offset);
EXPECT_EQ(8, g1->offset);
EXPECT_TRUE(g1->exported);
if (result.val) delete result.val;
......@@ -367,7 +367,7 @@ TEST_F(WasmModuleVerifyTest, OneEmptyVoidVoidFunction) {
EXPECT_EQ(0, result.val->data_segments.size());
EXPECT_EQ(0, result.val->function_table.size());
WasmFunction* function = &result.val->functions.back();
const WasmFunction* function = &result.val->functions.back();
EXPECT_EQ(37, function->name_offset);
EXPECT_EQ(2, function->name_length);
......@@ -399,7 +399,7 @@ TEST_F(WasmModuleVerifyTest, OneFunctionWithNopBody) {
ModuleResult result = DecodeModule(data, data + arraysize(data));
EXPECT_OK(result);
EXPECT_EQ(1, result.val->functions.size());
WasmFunction* function = &result.val->functions.back();
const WasmFunction* function = &result.val->functions.back();
EXPECT_EQ(0, function->name_length);
EXPECT_EQ(kCodeStartOffset, function->code_start_offset);
......@@ -451,14 +451,14 @@ TEST_F(WasmModuleVerifyTest, OneGlobalOneFunctionWithNopBodyOneDataSegment) {
EXPECT_EQ(1, result.val->functions.size());
EXPECT_EQ(1, result.val->data_segments.size());
WasmGlobal* global = &result.val->globals.back();
const WasmGlobal* global = &result.val->globals.back();
EXPECT_EQ(0, global->name_length);
EXPECT_EQ(MachineType::Uint8(), global->type);
EXPECT_EQ(0, global->offset);
EXPECT_FALSE(global->exported);
WasmFunction* function = &result.val->functions.back();
const WasmFunction* function = &result.val->functions.back();
EXPECT_EQ(kNameOffset, function->name_offset);
EXPECT_EQ(2, function->name_length);
......@@ -467,7 +467,7 @@ TEST_F(WasmModuleVerifyTest, OneGlobalOneFunctionWithNopBodyOneDataSegment) {
EXPECT_FALSE(function->exported);
WasmDataSegment* segment = &result.val->data_segments.back();
const WasmDataSegment* segment = &result.val->data_segments.back();
EXPECT_EQ(0x8b3ae, segment->dest_addr);
EXPECT_EQ(kDataSegmentSourceOffset, segment->source_offset);
......@@ -502,7 +502,7 @@ TEST_F(WasmModuleVerifyTest, OneDataSegment) {
EXPECT_EQ(0, result.val->functions.size());
EXPECT_EQ(1, result.val->data_segments.size());
WasmDataSegment* segment = &result.val->data_segments.back();
const WasmDataSegment* segment = &result.val->data_segments.back();
EXPECT_EQ(0x9bbaa, segment->dest_addr);
EXPECT_EQ(kDataSegmentSourceOffset, segment->source_offset);
......@@ -553,8 +553,8 @@ TEST_F(WasmModuleVerifyTest, TwoDataSegments) {
EXPECT_EQ(0, result.val->functions.size());
EXPECT_EQ(2, result.val->data_segments.size());
WasmDataSegment* s0 = &result.val->data_segments[0];
WasmDataSegment* s1 = &result.val->data_segments[1];
const WasmDataSegment* s0 = &result.val->data_segments[0];
const WasmDataSegment* s1 = &result.val->data_segments[1];
EXPECT_EQ(0x7ffee, s0->dest_addr);
EXPECT_EQ(kDataSegment0SourceOffset, s0->source_offset);
......@@ -983,7 +983,7 @@ TEST_F(WasmModuleVerifyTest, UnknownSectionSkipped) {
EXPECT_EQ(0, result.val->functions.size());
EXPECT_EQ(0, result.val->data_segments.size());
WasmGlobal* global = &result.val->globals.back();
const WasmGlobal* global = &result.val->globals.back();
EXPECT_EQ(0, global->name_length);
EXPECT_EQ(MachineType::Int32(), global->type);
......
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