Index: src/wasm/wasm-module.cc |
diff --git a/src/wasm/wasm-module.cc b/src/wasm/wasm-module.cc |
index 8f99797fdec82807362ffd31b19e2e064e85529c..e725ec16773eb6be2b95a37148cf6204517fdb51 100644 |
--- a/src/wasm/wasm-module.cc |
+++ b/src/wasm/wasm-module.cc |
@@ -52,54 +52,12 @@ enum JSFunctionExportInternalField { |
enum WasmInstanceObjectFields { |
kWasmCompiledModule = 0, |
kWasmModuleFunctionTable, |
- kWasmModuleCodeTable, |
+ kWasmModuleCodeTable, // TODO(titzer): code_table is in compiled module |
kWasmMemObject, |
kWasmMemArrayBuffer, |
kWasmGlobalsArrayBuffer, |
kWasmDebugInfo, |
- kWasmModuleInternalFieldCount |
-}; |
- |
-enum WasmImportData { |
- kImportKind, // Smi. an ExternalKind |
- kImportGlobalType, // Smi. Type for globals. |
- kImportIndex, // Smi. index for the import. |
- kModuleName, // String |
- kFunctionName, // maybe String |
- kOutputCount, // Smi. an uint32_t |
- kSignature, // ByteArray. A copy of the data in FunctionSig |
- kWasmImportDataSize // Sentinel value. |
-}; |
- |
-enum WasmExportData { |
- kExportKind, // Smi. an ExternalKind |
- kExportGlobalType, // Smi. Type for globals. |
- kExportName, // String |
- kExportArity, // Smi, an int |
- kExportIndex, // Smi, an uint32_t |
- kExportedSignature, // ByteArray. A copy of the data in FunctionSig |
- kWasmExportDataSize // Sentinel value. |
-}; |
- |
-enum WasmGlobalInitData { |
- kGlobalInitKind, // 0 = constant, 1 = global index |
- kGlobalInitType, // Smi. Type for globals. |
- kGlobalInitIndex, // Smi, an uint32_t |
- kGlobalInitValue, // Number. |
- kWasmGlobalInitDataSize |
-}; |
- |
-enum WasmSegmentInfo { |
- kDestAddrKind, // 0 = constant, 1 = global index |
- kDestAddrValue, // Smi. an uint32_t |
- kSourceSize, // Smi. an uint32_t |
- kWasmSegmentInfoSize // Sentinel value. |
-}; |
- |
-enum WasmIndirectFunctionTableData { |
- kSize, // Smi. an uint32_t |
- kTable, // FixedArray of indirect function table |
- kWasmIndirectFunctionTableDataSize // Sentinel value. |
+ kWasmInstanceInternalFieldCount |
}; |
byte* raw_buffer_ptr(MaybeHandle<JSArrayBuffer> buffer, int offset) { |
@@ -110,53 +68,24 @@ uint32_t GetMinModuleMemSize(const WasmModule* module) { |
return WasmModule::kPageSize * module->min_mem_pages; |
} |
-void SaveDataSegmentInfo(Factory* factory, const WasmModule* module, |
- Handle<WasmCompiledModule> compiled_module) { |
- Handle<FixedArray> segments = factory->NewFixedArray( |
- static_cast<int>(module->data_segments.size()), TENURED); |
- uint32_t data_size = 0; |
- for (const WasmDataSegment& segment : module->data_segments) { |
- if (segment.source_size == 0) continue; |
- data_size += segment.source_size; |
- } |
- Handle<ByteArray> data = factory->NewByteArray(data_size, TENURED); |
- |
- uint32_t last_insertion_pos = 0; |
- for (uint32_t i = 0; i < module->data_segments.size(); ++i) { |
- const WasmDataSegment& segment = module->data_segments[i]; |
- if (segment.source_size == 0) continue; |
- Handle<ByteArray> js_segment = |
- factory->NewByteArray(kWasmSegmentInfoSize * sizeof(uint32_t), TENURED); |
- if (segment.dest_addr.kind == WasmInitExpr::kGlobalIndex) { |
- // The destination address is the value of a global variable. |
- js_segment->set_int(kDestAddrKind, 1); |
- uint32_t offset = |
- module->globals[segment.dest_addr.val.global_index].offset; |
- js_segment->set_int(kDestAddrValue, static_cast<int>(offset)); |
- } else { |
- // The destination address is a constant. |
- CHECK_EQ(WasmInitExpr::kI32Const, segment.dest_addr.kind); |
- js_segment->set_int(kDestAddrKind, 0); |
- js_segment->set_int(kDestAddrValue, segment.dest_addr.val.i32_const); |
- } |
- js_segment->set_int(kSourceSize, segment.source_size); |
- segments->set(i, *js_segment); |
- data->copy_in(last_insertion_pos, |
- module->module_start + segment.source_offset, |
- segment.source_size); |
- last_insertion_pos += segment.source_size; |
- } |
- compiled_module->set_data_segments_info(segments); |
- compiled_module->set_data_segments(data); |
+MaybeHandle<String> ExtractStringFromModuleBytes( |
+ Isolate* isolate, Handle<WasmCompiledModule> compiled_module, |
+ uint32_t offset, uint32_t size) { |
+ Handle<SeqOneByteString> module_bytes = compiled_module->module_bytes(); |
+ Address raw = module_bytes->GetCharsAddress() + offset; |
+ if (!unibrow::Utf8::Validate(reinterpret_cast<const byte*>(raw), size)) |
+ return {}; |
+ Vector<const char> vec(reinterpret_cast<const char*>(raw), size); |
+ // TODO(titzer): can't GC move the underlying storage during this call? |
+ return isolate->factory()->NewStringFromUtf8(vec); |
Mircea Trofin
2016/10/15 17:38:40
Shouldn't we worry about GC happening when: alloca
|
} |
-void PatchFunctionTable(Handle<Code> code, |
- Handle<FixedArray> old_indirect_table, |
- Handle<FixedArray> new_indirect_table) { |
+void ReplaceReferenceInCode(Handle<Code> code, Handle<Object> old_ref, |
+ Handle<Object> new_ref) { |
for (RelocIterator it(*code, 1 << RelocInfo::EMBEDDED_OBJECT); !it.done(); |
it.next()) { |
- if (it.rinfo()->target_object() == *old_indirect_table) { |
- it.rinfo()->set_target_object(*new_indirect_table); |
+ if (it.rinfo()->target_object() == *old_ref) { |
+ it.rinfo()->set_target_object(*new_ref); |
} |
} |
} |
@@ -185,33 +114,30 @@ Handle<JSArrayBuffer> NewArrayBuffer(Isolate* isolate, size_t size) { |
return buffer; |
} |
-void RelocateInstanceCode(Handle<JSObject> instance, Address old_start, |
+void RelocateInstanceCode(Handle<FixedArray> code_table, Address old_start, |
Address start, uint32_t prev_size, |
uint32_t new_size) { |
- Handle<FixedArray> functions = Handle<FixedArray>( |
- FixedArray::cast(instance->GetInternalField(kWasmModuleCodeTable))); |
- for (int i = 0; i < functions->length(); ++i) { |
- Handle<Code> function = Handle<Code>(Code::cast(functions->get(i))); |
+ for (int i = 0; i < code_table->length(); ++i) { |
+ DCHECK(code_table->get(i)->IsCode()); |
+ Handle<Code> code = Handle<Code>(Code::cast(code_table->get(i))); |
AllowDeferredHandleDereference embedding_raw_address; |
int mask = (1 << RelocInfo::WASM_MEMORY_REFERENCE) | |
(1 << RelocInfo::WASM_MEMORY_SIZE_REFERENCE); |
- for (RelocIterator it(*function, mask); !it.done(); it.next()) { |
+ for (RelocIterator it(*code, mask); !it.done(); it.next()) { |
it.rinfo()->update_wasm_memory_reference(old_start, start, prev_size, |
new_size); |
} |
} |
} |
-void RelocateGlobals(Handle<JSObject> instance, Address old_start, |
+void RelocateGlobals(Handle<FixedArray> code_table, Address old_start, |
Address globals_start) { |
- Handle<FixedArray> functions = Handle<FixedArray>( |
- FixedArray::cast(instance->GetInternalField(kWasmModuleCodeTable))); |
- uint32_t function_count = static_cast<uint32_t>(functions->length()); |
- for (uint32_t i = 0; i < function_count; ++i) { |
- Handle<Code> function = Handle<Code>(Code::cast(functions->get(i))); |
+ for (int i = 0; i < code_table->length(); ++i) { |
+ DCHECK(code_table->get(i)->IsCode()); |
+ Handle<Code> code = Handle<Code>(Code::cast(code_table->get(i))); |
AllowDeferredHandleDereference embedding_raw_address; |
int mask = 1 << RelocInfo::WASM_GLOBAL_REFERENCE; |
- for (RelocIterator it(*function, mask); !it.done(); it.next()) { |
+ for (RelocIterator it(*code, mask); !it.done(); it.next()) { |
it.rinfo()->update_wasm_global_reference(old_start, globals_start); |
} |
} |
@@ -265,9 +191,9 @@ bool LinkFunction(Handle<Code> unlinked, |
return modified; |
} |
-void FlushICache(Isolate* isolate, Handle<FixedArray> functions) { |
- for (int i = 0; i < functions->length(); ++i) { |
- Handle<Code> code = functions->GetValueChecked<Code>(isolate, i); |
+void FlushICache(Isolate* isolate, Handle<FixedArray> code_table) { |
+ for (int i = 0; i < code_table->length(); ++i) { |
+ Handle<Code> code = code_table->GetValueChecked<Code>(isolate, i); |
Assembler::FlushICache(isolate, code->instruction_start(), |
code->instruction_size()); |
} |
@@ -356,69 +282,6 @@ Address GetGlobalStartAddressFromCodeTemplate(Object* undefined, |
return old_address; |
} |
-Handle<FixedArray> EncodeImports(Factory* factory, const WasmModule* module) { |
- // TODO(wasm): Encode this in one big FixedArray. |
- Handle<FixedArray> ret = factory->NewFixedArray( |
- static_cast<int>(module->import_table.size()), TENURED); |
- |
- for (size_t i = 0; i < module->import_table.size(); ++i) { |
- const WasmImport& import = module->import_table[i]; |
- Handle<FixedArray> encoded_import = |
- factory->NewFixedArray(kWasmImportDataSize, TENURED); |
- encoded_import->set(kImportKind, Smi::FromInt(import.kind)); |
- encoded_import->set(kImportIndex, Smi::FromInt(import.index)); |
- |
- // Add the module and function name. |
- WasmName module_name = module->GetNameOrNull(import.module_name_offset, |
- import.module_name_length); |
- WasmName function_name = module->GetNameOrNull(import.field_name_offset, |
- import.field_name_length); |
- |
- Handle<String> module_name_string = |
- factory->InternalizeUtf8String(module_name); |
- encoded_import->set(kModuleName, *module_name_string); |
- if (!function_name.is_empty()) { |
- Handle<String> function_name_string = |
- factory->InternalizeUtf8String(function_name); |
- encoded_import->set(kFunctionName, *function_name_string); |
- } |
- |
- switch (import.kind) { |
- case kExternalFunction: { |
- // Encode the signature into the import. |
- FunctionSig* fsig = module->functions[import.index].sig; |
- Handle<ByteArray> sig = factory->NewByteArray( |
- static_cast<int>(fsig->parameter_count() + fsig->return_count()), |
- TENURED); |
- sig->copy_in(0, reinterpret_cast<const byte*>(fsig->raw_data()), |
- sig->length()); |
- encoded_import->set( |
- kOutputCount, Smi::FromInt(static_cast<int>(fsig->return_count()))); |
- encoded_import->set(kSignature, *sig); |
- break; |
- } |
- case kExternalTable: |
- // Nothing extra required for imported tables. |
- break; |
- case kExternalMemory: |
- // Nothing extra required for imported memories. |
- break; |
- case kExternalGlobal: { |
- // Encode the offset and the global type into the import. |
- const WasmGlobal& global = module->globals[import.index]; |
- TRACE("import[%zu].type = %s\n", i, WasmOpcodes::TypeName(global.type)); |
- encoded_import->set( |
- kImportGlobalType, |
- Smi::FromInt(WasmOpcodes::LocalTypeCodeFor(global.type))); |
- encoded_import->set(kImportIndex, Smi::FromInt(global.offset)); |
- break; |
- } |
- } |
- ret->set(static_cast<int>(i), *encoded_import); |
- } |
- return ret; |
-} |
- |
void InitializeParallelCompilation( |
Isolate* isolate, const std::vector<WasmFunction>& functions, |
std::vector<compiler::WasmCompilationUnit*>& compilation_units, |
@@ -610,15 +473,17 @@ static void ResetCompiledModule(Isolate* isolate, JSObject* owner, |
WasmCompiledModule* compiled_module) { |
TRACE("Resetting %d\n", compiled_module->instance_id()); |
Object* undefined = *isolate->factory()->undefined_value(); |
- uint32_t old_mem_size = compiled_module->has_heap() |
+ uint32_t old_mem_size = compiled_module->has_memory() |
? compiled_module->mem_size() |
: compiled_module->default_mem_size(); |
uint32_t default_mem_size = compiled_module->default_mem_size(); |
- Object* mem_start = compiled_module->ptr_to_heap(); |
+ Object* mem_start = compiled_module->ptr_to_memory(); |
Address old_mem_address = nullptr; |
Address globals_start = |
GetGlobalStartAddressFromCodeTemplate(undefined, owner); |
+ // TODO(titzer): reset the function tables as well. |
+ |
if (old_mem_size > 0) { |
CHECK_NE(mem_start, undefined); |
old_mem_address = |
@@ -654,7 +519,7 @@ static void ResetCompiledModule(Isolate* isolate, JSObject* owner, |
} |
} |
} |
- compiled_module->reset_heap(); |
+ compiled_module->reset_memory(); |
} |
static void InstanceFinalizer(const v8::WeakCallbackInfo<void>& data) { |
@@ -663,16 +528,16 @@ static void InstanceFinalizer(const v8::WeakCallbackInfo<void>& data) { |
WasmCompiledModule* compiled_module = GetCompiledModule(owner); |
TRACE("Finalizing %d {\n", compiled_module->instance_id()); |
Isolate* isolate = reinterpret_cast<Isolate*>(data.GetIsolate()); |
- DCHECK(compiled_module->has_weak_module_object()); |
- WeakCell* weak_module_obj = compiled_module->ptr_to_weak_module_object(); |
+ DCHECK(compiled_module->has_weak_wasm_module()); |
+ WeakCell* weak_wasm_module = compiled_module->ptr_to_weak_wasm_module(); |
- // weak_module_obj may have been cleared, meaning the module object |
+ // weak_wasm_module may have been cleared, meaning the module object |
// was GC-ed. In that case, there won't be any new instances created, |
// and we don't need to maintain the links between instances. |
- if (!weak_module_obj->cleared()) { |
- JSObject* module_obj = JSObject::cast(weak_module_obj->value()); |
+ if (!weak_wasm_module->cleared()) { |
+ JSObject* wasm_module = JSObject::cast(weak_wasm_module->value()); |
WasmCompiledModule* current_template = |
- WasmCompiledModule::cast(module_obj->GetInternalField(0)); |
+ WasmCompiledModule::cast(wasm_module->GetInternalField(0)); |
TRACE("chain before {\n"); |
TRACE_CHAIN(current_template); |
@@ -687,7 +552,7 @@ static void InstanceFinalizer(const v8::WeakCallbackInfo<void>& data) { |
ResetCompiledModule(isolate, owner, compiled_module); |
} else { |
DCHECK(next->value()->IsFixedArray()); |
- module_obj->SetInternalField(0, next->value()); |
+ wasm_module->SetInternalField(0, next->value()); |
DCHECK_NULL(prev); |
WasmCompiledModule::cast(next->value())->reset_weak_prev_instance(); |
} |
@@ -716,7 +581,7 @@ static void InstanceFinalizer(const v8::WeakCallbackInfo<void>& data) { |
} |
} |
TRACE("chain after {\n"); |
- TRACE_CHAIN(WasmCompiledModule::cast(module_obj->GetInternalField(0))); |
+ TRACE_CHAIN(WasmCompiledModule::cast(wasm_module->GetInternalField(0))); |
TRACE("}\n"); |
} |
compiled_module->reset_weak_owning_instance(); |
@@ -724,36 +589,6 @@ static void InstanceFinalizer(const v8::WeakCallbackInfo<void>& data) { |
TRACE("}\n"); |
} |
-Handle<FixedArray> SetupIndirectFunctionTable( |
- Isolate* isolate, Handle<FixedArray> wasm_functions, |
- Handle<FixedArray> indirect_table_template, |
- Handle<FixedArray> tables_to_replace) { |
- Factory* factory = isolate->factory(); |
- Handle<FixedArray> cloned_indirect_tables = |
- factory->CopyFixedArray(indirect_table_template); |
- for (int i = 0; i < cloned_indirect_tables->length(); ++i) { |
- Handle<FixedArray> orig_metadata = |
- cloned_indirect_tables->GetValueChecked<FixedArray>(isolate, i); |
- Handle<FixedArray> cloned_metadata = factory->CopyFixedArray(orig_metadata); |
- cloned_indirect_tables->set(i, *cloned_metadata); |
- |
- Handle<FixedArray> orig_table = |
- cloned_metadata->GetValueChecked<FixedArray>(isolate, kTable); |
- Handle<FixedArray> cloned_table = factory->CopyFixedArray(orig_table); |
- cloned_metadata->set(kTable, *cloned_table); |
- // Patch the cloned code to refer to the cloned kTable. |
- Handle<FixedArray> table_to_replace = |
- tables_to_replace->GetValueChecked<FixedArray>(isolate, i) |
- ->GetValueChecked<FixedArray>(isolate, kTable); |
- for (int fct_index = 0; fct_index < wasm_functions->length(); ++fct_index) { |
- Handle<Code> wasm_function = |
- wasm_functions->GetValueChecked<Code>(isolate, fct_index); |
- PatchFunctionTable(wasm_function, table_to_replace, cloned_table); |
- } |
- } |
- return cloned_indirect_tables; |
-} |
- |
} // namespace |
const char* wasm::SectionName(WasmSectionCode code) { |
@@ -824,24 +659,28 @@ std::ostream& wasm::operator<<(std::ostream& os, const WasmFunctionName& pair) { |
} |
Handle<JSFunction> wasm::WrapExportCodeAsJSFunction( |
- Isolate* isolate, Handle<Code> export_code, Handle<String> name, int arity, |
- MaybeHandle<ByteArray> maybe_signature, Handle<JSObject> module_instance) { |
+ Isolate* isolate, Handle<Code> export_code, Handle<String> name, |
+ FunctionSig* sig, Handle<JSObject> module_instance) { |
Handle<SharedFunctionInfo> shared = |
isolate->factory()->NewSharedFunctionInfo(name, export_code, false); |
+ int arity = static_cast<int>(sig->parameter_count()); |
shared->set_length(arity); |
shared->set_internal_formal_parameter_count(arity); |
Handle<JSFunction> function = isolate->factory()->NewFunction( |
isolate->wasm_function_map(), name, export_code); |
function->set_shared(*shared); |
+ // TODO(titzer): embed the function index and get the signature from |
+ // the underlying WasmModuleWrapper. |
function->SetInternalField(kInternalModuleInstance, *module_instance); |
// add another Internal Field as the function arity |
function->SetInternalField(kInternalArity, Smi::FromInt(arity)); |
// add another Internal Field as the signature of the foreign function |
- Handle<ByteArray> signature; |
- if (maybe_signature.ToHandle(&signature)) { |
- function->SetInternalField(kInternalSignature, *signature); |
- } |
+ int size = static_cast<int>(sig->return_count() + sig->parameter_count()); |
+ Handle<ByteArray> signature = isolate->factory()->NewByteArray(size); |
+ // TODO(titzer): don't use raw_data() from FunctionSig. |
+ signature->copy_in(0, reinterpret_cast<const byte*>(sig->raw_data()), size); |
+ function->SetInternalField(kInternalSignature, *signature); |
return function; |
} |
@@ -857,78 +696,25 @@ Object* wasm::GetOwningWasmInstance(Code* code) { |
return cell->value(); |
} |
-int wasm::GetNumImportedFunctions(Handle<JSObject> wasm_object) { |
- // TODO(wasm): Cache this number if it ever becomes a performance problem. |
- DCHECK(IsWasmObject(*wasm_object)); |
- WasmCompiledModule* compiled_module = GetCompiledModule(*wasm_object); |
- Handle<FixedArray> imports = |
- WasmCompiledModule::cast(compiled_module)->imports(); |
- int num_imports = imports->length(); |
- int num_imported_functions = 0; |
- for (int i = 0; i < num_imports; ++i) { |
- FixedArray* encoded_import = FixedArray::cast(imports->get(i)); |
- int kind = Smi::cast(encoded_import->get(kImportKind))->value(); |
- if (kind == kExternalFunction) ++num_imported_functions; |
- } |
- return num_imported_functions; |
+WasmModule* CppModule(Handle<JSObject> wasm_module) { |
Mircea Trofin
2016/10/15 17:38:40
GetCppModule? (as opposed to Create)
|
+ DCHECK(IsWasmModule(*wasm_module)); |
+ return reinterpret_cast<WasmModuleWrapper*>( |
+ *GetCompiledModule(*wasm_module)->module_wrapper()) |
+ ->get(); |
} |
-WasmModule::WasmModule(byte* module_start) |
- : module_start(module_start), |
- module_end(nullptr), |
- min_mem_pages(0), |
- max_mem_pages(0), |
- mem_export(false), |
- start_function_index(-1), |
- origin(kWasmOrigin), |
- globals_size(0), |
- num_imported_functions(0), |
- num_declared_functions(0), |
- num_exported_functions(0), |
- pending_tasks(new base::Semaphore(0)) {} |
- |
-namespace { |
- |
-void EncodeInit(const WasmModule* module, Factory* factory, |
- Handle<FixedArray> entry, int kind_index, int value_index, |
- const WasmInitExpr& expr) { |
- entry->set(kind_index, Smi::kZero); |
- |
- Handle<Object> value; |
- switch (expr.kind) { |
- case WasmInitExpr::kGlobalIndex: { |
- TRACE(" kind = 1, global index %u\n", expr.val.global_index); |
- entry->set(kind_index, Smi::FromInt(1)); |
- uint32_t offset = module->globals[expr.val.global_index].offset; |
- entry->set(value_index, Smi::FromInt(offset)); |
- return; |
- } |
- case WasmInitExpr::kI32Const: |
- TRACE(" kind = 0, i32 = %d\n", expr.val.i32_const); |
- value = factory->NewNumber(expr.val.i32_const); |
- break; |
- case WasmInitExpr::kI64Const: |
- // TODO(titzer): implement initializers for i64 globals. |
- UNREACHABLE(); |
- break; |
- case WasmInitExpr::kF32Const: |
- TRACE(" kind = 0, f32 = %f\n", expr.val.f32_const); |
- value = factory->NewNumber(expr.val.f32_const); |
- break; |
- case WasmInitExpr::kF64Const: |
- TRACE(" kind = 0, f64 = %lf\n", expr.val.f64_const); |
- value = factory->NewNumber(expr.val.f64_const); |
- break; |
- default: |
- UNREACHABLE(); |
- } |
- entry->set(value_index, *value); |
+int wasm::GetNumImportedFunctions(Handle<JSObject> wasm_module) { |
+ return static_cast<int>(CppModule(wasm_module)->num_imported_functions); |
} |
-} // namespace |
+WasmModule::WasmModule(Zone* owned, const byte* module_start) |
+ : owned_zone(owned), |
+ module_start(module_start), |
+ pending_tasks(new base::Semaphore(0)) {} |
MaybeHandle<WasmCompiledModule> WasmModule::CompileFunctions( |
- Isolate* isolate, ErrorThrower* thrower) const { |
+ Isolate* isolate, Handle<WasmModuleWrapper> module_wrapper, |
+ ErrorThrower* thrower) const { |
Factory* factory = isolate->factory(); |
MaybeHandle<WasmCompiledModule> nothing; |
@@ -939,20 +725,15 @@ MaybeHandle<WasmCompiledModule> WasmModule::CompileFunctions( |
temp_instance.mem_start = nullptr; |
temp_instance.globals_start = nullptr; |
- MaybeHandle<FixedArray> indirect_table = |
- function_tables.size() |
- ? factory->NewFixedArray(static_cast<int>(function_tables.size()), |
- TENURED) |
- : MaybeHandle<FixedArray>(); |
- for (uint32_t i = 0; i < function_tables.size(); ++i) { |
- Handle<FixedArray> values = wasm::BuildFunctionTable(isolate, i, this); |
- temp_instance.function_tables[i] = values; |
- |
- Handle<FixedArray> metadata = isolate->factory()->NewFixedArray( |
- kWasmIndirectFunctionTableDataSize, TENURED); |
- metadata->set(kSize, Smi::FromInt(function_tables[i].size)); |
- metadata->set(kTable, *values); |
- indirect_table.ToHandleChecked()->set(i, *metadata); |
+ // Initialize the indirect tables with placeholders. |
+ Handle<FixedArray> function_tables; |
Mircea Trofin
2016/10/15 17:38:40
I thought we're supposed to use MaybeHandle whenev
|
+ int function_table_count = static_cast<int>(this->function_tables.size()); |
+ if (function_table_count > 0) { |
+ function_tables = factory->NewFixedArray(function_table_count); |
+ for (int i = 0; i < function_table_count; ++i) { |
+ temp_instance.function_tables[i] = factory->NewFixedArray(0); |
+ function_tables->set(i, *temp_instance.function_tables[i]); |
+ } |
} |
HistogramTimerScope wasm_compile_module_time_scope( |
@@ -1023,117 +804,23 @@ MaybeHandle<WasmCompiledModule> WasmModule::CompileFunctions( |
// serializable. Instantiation may occur off a deserialized version of this |
// object. |
Handle<WasmCompiledModule> ret = |
- WasmCompiledModule::New(isolate, min_mem_pages, globals_size, origin); |
+ WasmCompiledModule::New(isolate, module_wrapper); |
ret->set_code_table(code_table); |
- if (!indirect_table.is_null()) { |
- ret->set_indirect_function_tables(indirect_table.ToHandleChecked()); |
- } |
- |
- // Create and set import data. |
- Handle<FixedArray> imports = EncodeImports(factory, this); |
- ret->set_imports(imports); |
- |
- // Create and set export data. |
- int export_size = static_cast<int>(export_table.size()); |
- if (export_size > 0) { |
- Handle<FixedArray> exports = factory->NewFixedArray(export_size, TENURED); |
- int index = 0; |
- int func_index = 0; |
- |
- for (const WasmExport& exp : export_table) { |
- if (thrower->error()) return nothing; |
- Handle<FixedArray> encoded_export = |
- factory->NewFixedArray(kWasmExportDataSize, TENURED); |
- WasmName str = GetName(exp.name_offset, exp.name_length); |
- Handle<String> name = factory->InternalizeUtf8String(str); |
- encoded_export->set(kExportKind, Smi::FromInt(exp.kind)); |
- encoded_export->set(kExportName, *name); |
- encoded_export->set(kExportIndex, |
- Smi::FromInt(static_cast<int>(exp.index))); |
- exports->set(index, *encoded_export); |
- |
- switch (exp.kind) { |
- case kExternalFunction: { |
- // Copy the signature and arity. |
- FunctionSig* funcSig = functions[exp.index].sig; |
- Handle<ByteArray> exportedSig = factory->NewByteArray( |
- static_cast<int>(funcSig->parameter_count() + |
- funcSig->return_count()), |
- TENURED); |
- exportedSig->copy_in( |
- 0, reinterpret_cast<const byte*>(funcSig->raw_data()), |
- exportedSig->length()); |
- encoded_export->set(kExportedSignature, *exportedSig); |
- encoded_export->set( |
- kExportArity, |
- Smi::FromInt(static_cast<int>(funcSig->parameter_count()))); |
- |
- // Compile a wrapper for an exported function. |
- Handle<Code> code = |
- code_table->GetValueChecked<Code>(isolate, exp.index); |
- Handle<Code> export_code = compiler::CompileJSToWasmWrapper( |
- isolate, &module_env, code, exp.index); |
- int code_table_index = |
- static_cast<int>(functions.size() + func_index); |
- code_table->set(code_table_index, *export_code); |
- encoded_export->set(kExportIndex, Smi::FromInt(code_table_index)); |
- ++func_index; |
- } |
- case kExternalTable: |
- // Nothing special about exported tables. |
- break; |
- case kExternalMemory: |
- // Nothing special about exported tables. |
- break; |
- case kExternalGlobal: { |
- // Encode the global type and the global offset. |
- const WasmGlobal& global = globals[exp.index]; |
- encoded_export->set( |
- kExportGlobalType, |
- Smi::FromInt(WasmOpcodes::LocalTypeCodeFor(global.type))); |
- encoded_export->set(kExportIndex, Smi::FromInt(global.offset)); |
- break; |
- } |
- } |
- ++index; |
- } |
- ret->set_exports(exports); |
- } |
- |
- // Create and set init data. |
- int init_size = static_cast<int>(globals.size()); |
- if (init_size > 0) { |
- Handle<FixedArray> inits = factory->NewFixedArray(init_size, TENURED); |
- int index = 0; |
- for (const WasmGlobal& global : globals) { |
- // Skip globals that have no initializer (e.g. imported ones). |
- if (global.init.kind == WasmInitExpr::kNone) continue; |
- |
- Handle<FixedArray> encoded_init = |
- factory->NewFixedArray(kWasmGlobalInitDataSize, TENURED); |
- inits->set(index, *encoded_init); |
- TRACE("init[%d].type = %s\n", index, WasmOpcodes::TypeName(global.type)); |
- |
- encoded_init->set( |
- kGlobalInitType, |
- Smi::FromInt(WasmOpcodes::LocalTypeCodeFor(global.type))); |
- encoded_init->set(kGlobalInitIndex, Smi::FromInt(global.offset)); |
- EncodeInit(this, factory, encoded_init, kGlobalInitKind, kGlobalInitValue, |
- global.init); |
- ++index; |
- } |
- inits->Shrink(index); |
- ret->set_inits(inits); |
+ if (function_table_count > 0) { |
+ ret->set_function_tables(function_tables); |
} |
- // Record data for startup function. |
- if (start_function_index >= 0) { |
- HandleScope scope(isolate); |
- Handle<FixedArray> startup_data = |
- factory->NewFixedArray(kWasmExportDataSize, TENURED); |
- startup_data->set(kExportArity, Smi::kZero); |
- startup_data->set(kExportIndex, Smi::FromInt(start_function_index)); |
- ret->set_startup_function(startup_data); |
+ // Compile JS->WASM wrappers for exported functions. |
+ int func_index = 0; |
+ for (auto exp : export_table) { |
Mircea Trofin
2016/10/15 17:38:40
I know auto is allowed for iterators, but since we
|
+ if (exp.kind != kExternalFunction) continue; |
+ Handle<Code> wasm_code = |
+ code_table->GetValueChecked<Code>(isolate, exp.index); |
+ Handle<Code> wrapper_code = compiler::CompileJSToWasmWrapper( |
+ isolate, &module_env, wasm_code, exp.index); |
+ int export_index = static_cast<int>(functions.size() + func_index); |
+ code_table->set(export_index, *wrapper_code); |
+ func_index++; |
Mircea Trofin
2016/10/15 17:38:40
++func_index;
|
} |
// TODO(wasm): saving the module bytes for debugging is wasteful. We should |
@@ -1150,10 +837,6 @@ MaybeHandle<WasmCompiledModule> WasmModule::CompileFunctions( |
ret->set_module_bytes(Handle<SeqOneByteString>::cast(module_bytes_string)); |
} |
- Handle<ByteArray> function_name_table = |
- BuildFunctionNamesTable(isolate, module_env.module); |
- ret->set_function_names(function_name_table); |
- if (data_segments.size() > 0) SaveDataSegmentInfo(factory, this, ret); |
DCHECK_EQ(ret->default_mem_size(), temp_instance.mem_size); |
return ret; |
} |
@@ -1164,11 +847,11 @@ MaybeHandle<WasmCompiledModule> WasmModule::CompileFunctions( |
class WasmInstanceBuilder { |
public: |
WasmInstanceBuilder(Isolate* isolate, ErrorThrower* thrower, |
- Handle<JSObject> module_object, Handle<JSReceiver> ffi, |
+ Handle<JSObject> wasm_module, Handle<JSReceiver> ffi, |
Handle<JSArrayBuffer> memory) |
: isolate_(isolate), |
thrower_(thrower), |
- module_object_(module_object), |
+ wasm_module_(wasm_module), |
ffi_(ffi), |
memory_(memory) {} |
@@ -1197,8 +880,8 @@ class WasmInstanceBuilder { |
Handle<WasmCompiledModule> original; |
{ |
DisallowHeapAllocation no_gc; |
- original = handle( |
- WasmCompiledModule::cast(module_object_->GetInternalField(0))); |
+ original = |
+ handle(WasmCompiledModule::cast(wasm_module_->GetInternalField(0))); |
if (original->has_weak_owning_instance()) { |
owner = |
handle(JSObject::cast(original->weak_owning_instance()->value())); |
@@ -1218,6 +901,8 @@ class WasmInstanceBuilder { |
DCHECK(!owner.is_null()); |
TRACE("Cloning from %d\n", original->instance_id()); |
compiled_module_ = WasmCompiledModule::Clone(isolate_, original); |
+ // Avoid creating too many handles in the outer scope. |
+ HandleScope scope(isolate_); |
// Clone the code for WASM functions and exports. |
for (int i = 0; i < code_table->length(); ++i) { |
@@ -1246,13 +931,16 @@ class WasmInstanceBuilder { |
} |
compiled_module_->set_code_table(code_table); |
} |
+ module_ = reinterpret_cast<WasmModuleWrapper*>( |
+ *compiled_module_->module_wrapper()) |
+ ->get(); |
//-------------------------------------------------------------------------- |
// Allocate the instance object. |
//-------------------------------------------------------------------------- |
Handle<Map> map = factory->NewMap( |
JS_OBJECT_TYPE, |
- JSObject::kHeaderSize + kWasmModuleInternalFieldCount * kPointerSize); |
+ JSObject::kHeaderSize + kWasmInstanceInternalFieldCount * kPointerSize); |
Handle<JSObject> instance = factory->NewJSObjectFromMap(map, TENURED); |
instance->SetInternalField(kWasmModuleCodeTable, *code_table); |
instance->SetInternalField(kWasmMemObject, *factory->undefined_value()); |
@@ -1262,7 +950,7 @@ class WasmInstanceBuilder { |
//-------------------------------------------------------------------------- |
MaybeHandle<JSArrayBuffer> old_globals; |
MaybeHandle<JSArrayBuffer> globals; |
- uint32_t globals_size = compiled_module_->globals_size(); |
+ uint32_t globals_size = module_->globals_size; |
if (globals_size > 0) { |
Handle<JSArrayBuffer> global_buffer = |
NewArrayBuffer(isolate_, globals_size); |
@@ -1276,7 +964,7 @@ class WasmInstanceBuilder { |
: GetGlobalStartAddressFromCodeTemplate( |
*factory->undefined_value(), |
JSObject::cast(*owner.ToHandleChecked())); |
- RelocateGlobals(instance, old_address, |
+ RelocateGlobals(code_table, old_address, |
static_cast<Address>(global_buffer->backing_store())); |
instance->SetInternalField(kWasmGlobalsArrayBuffer, *global_buffer); |
} |
@@ -1290,7 +978,7 @@ class WasmInstanceBuilder { |
//-------------------------------------------------------------------------- |
// Process the initialization for the module's globals. |
//-------------------------------------------------------------------------- |
- ProcessInits(globals); |
+ InitGlobals(globals); |
//-------------------------------------------------------------------------- |
// Set up the memory for the new instance. |
@@ -1298,7 +986,7 @@ class WasmInstanceBuilder { |
MaybeHandle<JSArrayBuffer> old_memory; |
// TODO(titzer): handle imported memory properly. |
- uint32_t min_mem_pages = compiled_module_->min_memory_pages(); |
+ uint32_t min_mem_pages = module_->min_mem_pages; |
isolate_->counters()->wasm_min_mem_pages_count()->AddSample(min_mem_pages); |
// TODO(wasm): re-enable counter for max_mem_pages when we use that field. |
@@ -1314,16 +1002,17 @@ class WasmInstanceBuilder { |
static_cast<uint32_t>(memory_->byte_length()->Number()); |
LoadDataSegments(globals, mem_start, mem_size); |
- uint32_t old_mem_size = compiled_module_->has_heap() |
+ uint32_t old_mem_size = compiled_module_->has_memory() |
? compiled_module_->mem_size() |
: compiled_module_->default_mem_size(); |
Address old_mem_start = |
- compiled_module_->has_heap() |
- ? static_cast<Address>(compiled_module_->heap()->backing_store()) |
+ compiled_module_->has_memory() |
+ ? static_cast<Address>( |
+ compiled_module_->memory()->backing_store()) |
: nullptr; |
- RelocateInstanceCode(instance, old_mem_start, mem_start, old_mem_size, |
+ RelocateInstanceCode(code_table, old_mem_start, mem_start, old_mem_size, |
mem_size); |
- compiled_module_->set_heap(memory_); |
+ compiled_module_->set_memory(memory_); |
} |
//-------------------------------------------------------------------------- |
@@ -1346,33 +1035,47 @@ class WasmInstanceBuilder { |
//-------------------------------------------------------------------------- |
// Set up the indirect function tables for the new instance. |
//-------------------------------------------------------------------------- |
- { |
- std::vector<Handle<Code>> functions( |
- static_cast<size_t>(code_table->length())); |
- for (int i = 0; i < code_table->length(); ++i) { |
- functions[i] = code_table->GetValueChecked<Code>(isolate_, i); |
+ int function_table_count = |
+ static_cast<int>(module_->function_tables.size()); |
+ if (function_table_count > 0) { |
+ Handle<FixedArray> old_function_tables = |
+ compiled_module_->function_tables(); |
+ Handle<FixedArray> new_function_tables = |
+ factory->NewFixedArray(function_table_count); |
+ for (int index = 0; index < function_table_count; index++) { |
+ WasmIndirectFunctionTable& table = module_->function_tables[index]; |
+ uint32_t size = table.max_size; |
+ Handle<FixedArray> new_table = factory->NewFixedArray(size * 2); |
+ for (int i = 0; i < new_table->length(); i++) { |
Mircea Trofin
2016/10/15 17:38:40
++i
|
+ static const int kInvalidSigIndex = -1; |
+ // Fill the table with invalid signature indexes so that uninitialized |
+ // entries will always fail the signature check. |
+ new_table->set(i, Smi::FromInt(kInvalidSigIndex)); |
+ } |
+ for (auto table_init : module_->table_inits) { |
Mircea Trofin
2016/10/15 17:38:40
same comment about auto as above.
|
+ // TODO(titzer): proper bounds check of the initialization. |
+ uint32_t base = EvalUint32InitExpr(globals, table_init.offset); |
+ for (size_t i = 0; i < table_init.entries.size(); i++) { |
Mircea Trofin
2016/10/15 17:38:40
++i
|
+ FunctionSig* sig = module_->functions[table_init.entries[i]].sig; |
+ int32_t sig_index = table.map.Find(sig); |
+ new_table->set(static_cast<int>(i + base), Smi::FromInt(sig_index)); |
+ new_table->set(static_cast<int>(i + base + size), |
+ code_table->get(table_init.entries[i])); |
+ } |
+ } |
+ new_function_tables->set(static_cast<int>(index), *new_table); |
} |
- |
- if (compiled_module_->has_indirect_function_tables()) { |
- Handle<FixedArray> indirect_tables_template = |
- compiled_module_->indirect_function_tables(); |
- Handle<FixedArray> to_replace = |
- owner.is_null() ? indirect_tables_template |
- : handle(FixedArray::cast( |
- owner.ToHandleChecked()->GetInternalField( |
- kWasmModuleFunctionTable))); |
- Handle<FixedArray> indirect_tables = SetupIndirectFunctionTable( |
- isolate_, code_table, indirect_tables_template, to_replace); |
- for (int i = 0; i < indirect_tables->length(); ++i) { |
- Handle<FixedArray> metadata = |
- indirect_tables->GetValueChecked<FixedArray>(isolate_, i); |
- uint32_t size = Smi::cast(metadata->get(kSize))->value(); |
- Handle<FixedArray> table = |
- metadata->GetValueChecked<FixedArray>(isolate_, kTable); |
- PopulateFunctionTable(table, size, &functions); |
+ // Patch all code that has references to the old indirect table. |
+ for (int i = 0; i < code_table->length(); i++) { |
Mircea Trofin
2016/10/15 17:38:40
++i
|
+ if (!code_table->get(i)->IsCode()) continue; |
+ Handle<Code> code(Code::cast(code_table->get(i)), isolate_); |
+ for (int j = 0; j < function_table_count; j++) { |
Mircea Trofin
2016/10/15 17:38:41
++j
|
+ ReplaceReferenceInCode( |
+ code, Handle<Object>(old_function_tables->get(j), isolate_), |
+ Handle<Object>(new_function_tables->get(j), isolate_)); |
} |
- instance->SetInternalField(kWasmModuleFunctionTable, *indirect_tables); |
} |
+ compiled_module_->set_function_tables(new_function_tables); |
} |
//-------------------------------------------------------------------------- |
@@ -1390,19 +1093,15 @@ class WasmInstanceBuilder { |
//-------------------------------------------------------------------------- |
// Run the start function if one was specified. |
//-------------------------------------------------------------------------- |
- if (compiled_module_->has_startup_function()) { |
- Handle<FixedArray> startup_data = compiled_module_->startup_function(); |
+ if (module_->start_function_index >= 0) { |
HandleScope scope(isolate_); |
- int32_t start_index = |
- startup_data->GetValueChecked<Smi>(isolate_, kExportIndex)->value(); |
+ int32_t start_index = module_->start_function_index; |
Handle<Code> startup_code = |
code_table->GetValueChecked<Code>(isolate_, start_index); |
- int arity = Smi::cast(startup_data->get(kExportArity))->value(); |
- MaybeHandle<ByteArray> startup_signature = |
- startup_data->GetValue<ByteArray>(isolate_, kExportedSignature); |
+ FunctionSig* sig = module_->functions[start_index].sig; |
Handle<JSFunction> startup_fct = WrapExportCodeAsJSFunction( |
- isolate_, startup_code, factory->InternalizeUtf8String("start"), |
- arity, startup_signature, instance); |
+ isolate_, startup_code, factory->InternalizeUtf8String("start"), sig, |
+ instance); |
RecordStats(isolate_, *startup_code); |
// Call the JS function. |
Handle<Object> undefined = factory->undefined_value(); |
@@ -1438,10 +1137,10 @@ class WasmInstanceBuilder { |
compiled_module_->set_weak_next_instance( |
link_to_original.ToHandleChecked()); |
original.ToHandleChecked()->set_weak_prev_instance(link_to_clone); |
- compiled_module_->set_weak_module_object( |
- original.ToHandleChecked()->weak_module_object()); |
+ compiled_module_->set_weak_wasm_module( |
+ original.ToHandleChecked()->weak_wasm_module()); |
} |
- module_object_->SetInternalField(0, *compiled_module_); |
+ wasm_module_->SetInternalField(0, *compiled_module_); |
instance->SetInternalField(kWasmCompiledModule, *compiled_module_); |
compiled_module_->set_weak_owning_instance(link_to_owning_instance); |
GlobalHandles::MakeWeak(global_handle.location(), |
@@ -1450,17 +1149,18 @@ class WasmInstanceBuilder { |
} |
} |
- DCHECK(wasm::IsWasmObject(*instance)); |
+ DCHECK(wasm::IsWasmModule(*instance)); |
TRACE("Finishing instance %d\n", compiled_module_->instance_id()); |
- TRACE_CHAIN(WasmCompiledModule::cast(module_object_->GetInternalField(0))); |
+ TRACE_CHAIN(WasmCompiledModule::cast(wasm_module_->GetInternalField(0))); |
return instance; |
} |
private: |
Isolate* isolate_; |
+ WasmModule* module_; |
Mircea Trofin
2016/10/15 17:38:40
elsewhere, there was a CppModule API. Could we cal
|
ErrorThrower* thrower_; |
- Handle<JSObject> module_object_; |
+ Handle<JSObject> wasm_module_; |
Handle<JSReceiver> ffi_; |
Handle<JSArrayBuffer> memory_; |
Handle<WasmCompiledModule> compiled_module_; |
@@ -1522,57 +1222,47 @@ class WasmInstanceBuilder { |
return result; |
} |
+ uint32_t EvalUint32InitExpr(MaybeHandle<JSArrayBuffer> globals, |
+ WasmInitExpr& expr) { |
+ switch (expr.kind) { |
+ case WasmInitExpr::kI32Const: |
+ return expr.val.i32_const; |
+ case WasmInitExpr::kGlobalIndex: { |
+ uint32_t offset = module_->globals[expr.val.global_index].offset; |
+ return *reinterpret_cast<uint32_t*>(raw_buffer_ptr(globals, offset)); |
+ } |
+ default: |
+ UNREACHABLE(); |
+ break; |
+ } |
+ } |
+ |
// Load data segments into the memory. |
void LoadDataSegments(MaybeHandle<JSArrayBuffer> globals, Address mem_addr, |
size_t mem_size) { |
- CHECK(compiled_module_->has_data_segments() == |
- compiled_module_->has_data_segments_info()); |
- |
- // If we have neither, we're done. |
- if (!compiled_module_->has_data_segments()) return; |
- |
- Handle<ByteArray> data = compiled_module_->data_segments(); |
- Handle<FixedArray> segments = compiled_module_->data_segments_info(); |
- |
- uint32_t last_extraction_pos = 0; |
- for (int i = 0; i < segments->length(); ++i) { |
- Handle<ByteArray> segment = |
- Handle<ByteArray>(ByteArray::cast(segments->get(i))); |
- uint32_t dest_addr = |
- static_cast<uint32_t>(segment->get_int(kDestAddrValue)); |
- if (segment->get_int(kDestAddrKind) == 1) { |
- // The destination address is the value of a global variable. |
- dest_addr = |
- *reinterpret_cast<uint32_t*>(raw_buffer_ptr(globals, dest_addr)); |
+ Handle<SeqOneByteString> module_bytes = compiled_module_->module_bytes(); |
+ for (auto segment : module_->data_segments) { |
+ uint32_t dest_offset = EvalUint32InitExpr(globals, segment.dest_addr); |
+ uint32_t source_size = segment.source_size; |
+ if (dest_offset >= mem_size || source_size >= mem_size || |
+ dest_offset >= (mem_size - source_size)) { |
+ thrower_->RangeError("data segment does not fit into memory"); |
} |
- |
- uint32_t source_size = |
- static_cast<uint32_t>(segment->get_int(kSourceSize)); |
- // TODO(titzer): These should be runtime errors and not CHECKs if |
- // dest_addr is global (and therefore initialized at linktime to an |
- // possibly-invalid value). |
- CHECK_LT(dest_addr, mem_size); |
- CHECK_LE(source_size, mem_size); |
- CHECK_LE(dest_addr, mem_size - source_size); |
- byte* addr = mem_addr + dest_addr; |
- data->copy_out(last_extraction_pos, addr, source_size); |
- last_extraction_pos += source_size; |
+ byte* dest = mem_addr + dest_offset; |
+ const byte* src = reinterpret_cast<const byte*>( |
+ module_bytes->GetCharsAddress() + segment.source_offset); |
+ memcpy(dest, src, source_size); |
} |
} |
- Handle<Code> CompileImportWrapper(int index, Handle<FixedArray> data, |
+ Handle<Code> CompileImportWrapper(int index, const WasmImport& import, |
Handle<JSReceiver> target, |
Handle<String> module_name, |
MaybeHandle<String> import_name) { |
// TODO(mtrofin): this is an uint32_t, actually. We should rationalize |
// it when we rationalize signed/unsigned stuff. |
- int ret_count = Smi::cast(data->get(kOutputCount))->value(); |
- CHECK_GE(ret_count, 0); |
- Handle<ByteArray> sig_data = |
- data->GetValueChecked<ByteArray>(isolate_, kSignature); |
- int sig_data_size = sig_data->length(); |
- int param_count = sig_data_size - ret_count; |
- CHECK(param_count >= 0); |
+ FunctionSig* sig = module_->functions[import.index].sig; |
+ int param_count = static_cast<int>(sig->parameter_count()); |
Handle<Code> code; |
bool isMatch = false; |
@@ -1586,15 +1276,18 @@ class WasmInstanceBuilder { |
Handle<ByteArray> exportedSig = Handle<ByteArray>( |
Mircea Trofin
2016/10/15 17:38:40
do we still need this, given we now have the nativ
|
ByteArray::cast(func->GetInternalField(kInternalSignature))); |
if (exported_param_count == param_count && |
- exportedSig->length() == sig_data->length() && |
- memcmp(exportedSig->GetDataStartAddress(), |
- sig_data->GetDataStartAddress(), |
+ exportedSig->length() == |
+ (sig->return_count() + sig->parameter_count()) && |
+ // TODO(titzer): do not use raw_data() of signature. |
+ memcmp(exportedSig->GetDataStartAddress(), sig->raw_data(), |
exportedSig->length()) == 0) { |
isMatch = true; |
} |
} |
} |
if (isMatch) { |
+ // Signature matched. Unwrap the JS->WASM wrapper and return the naked |
+ // WASM function code. |
int wasm_count = 0; |
int const mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET); |
for (RelocIterator it(*export_wrapper_code, mask); !it.done(); |
@@ -1610,22 +1303,14 @@ class WasmInstanceBuilder { |
DCHECK(wasm_count == 1); |
return code; |
} else { |
- // Copy the signature to avoid a raw pointer into a heap object when |
- // GC can happen. |
- Zone zone(isolate_->allocator()); |
- MachineRepresentation* reps = |
- zone.NewArray<MachineRepresentation>(sig_data_size); |
- memcpy(reps, sig_data->GetDataStartAddress(), |
- sizeof(MachineRepresentation) * sig_data_size); |
- FunctionSig sig(ret_count, param_count, reps); |
- |
- return compiler::CompileWasmToJSWrapper(isolate_, target, &sig, index, |
+ // Signature mismatch. Compile a new wrapper for the new signature. |
+ return compiler::CompileWasmToJSWrapper(isolate_, target, sig, index, |
module_name, import_name); |
} |
} |
- void WriteGlobalValue(MaybeHandle<JSArrayBuffer> globals, uint32_t offset, |
- Handle<Object> value, int type) { |
+ void WriteGlobalValue(WasmGlobal& global, MaybeHandle<JSArrayBuffer> globals, |
+ Handle<Object> value) { |
double num = 0; |
if (value->IsSmi()) { |
num = Smi::cast(*value)->value(); |
@@ -1634,21 +1319,21 @@ class WasmInstanceBuilder { |
} else { |
UNREACHABLE(); |
} |
- TRACE("init [globals+%u] = %lf, type = %d\n", offset, num, type); |
- byte* ptr = raw_buffer_ptr(globals, offset); |
- switch (type) { |
- case kLocalI32: |
- *reinterpret_cast<int32_t*>(ptr) = static_cast<int32_t>(num); |
+ TRACE("init [globals+%u] = %lf, type = %s\n", global.offset, num, |
+ WasmOpcodes::TypeName(global.type)); |
+ switch (global.type) { |
+ case kAstI32: |
+ *GetRawGlobalPtr<int32_t>(global, globals) = static_cast<int32_t>(num); |
Mircea Trofin
2016/10/15 17:38:40
Is this change here related, or could it be a diff
|
break; |
- case kLocalI64: |
+ case kAstI64: |
// TODO(titzer): initialization of imported i64 globals. |
UNREACHABLE(); |
break; |
- case kLocalF32: |
- *reinterpret_cast<float*>(ptr) = static_cast<float>(num); |
+ case kAstF32: |
+ *GetRawGlobalPtr<float>(global, globals) = static_cast<float>(num); |
break; |
- case kLocalF64: |
- *reinterpret_cast<double*>(ptr) = num; |
+ case kAstF64: |
+ *GetRawGlobalPtr<double>(global, globals) = static_cast<double>(num); |
break; |
default: |
UNREACHABLE(); |
@@ -1661,25 +1346,27 @@ class WasmInstanceBuilder { |
int ProcessImports(MaybeHandle<JSArrayBuffer> globals, |
Handle<FixedArray> code_table, Handle<JSObject> instance) { |
int num_imported_functions = 0; |
- if (!compiled_module_->has_imports()) return num_imported_functions; |
- |
- Handle<FixedArray> imports = compiled_module_->imports(); |
- for (int index = 0; index < imports->length(); ++index) { |
- Handle<FixedArray> data = |
- imports->GetValueChecked<FixedArray>(isolate_, index); |
- |
+ for (int index = 0; index < static_cast<int>(module_->import_table.size()); |
+ index++) { |
Mircea Trofin
2016/10/15 17:38:40
++index
|
+ WasmImport& import = module_->import_table[index]; |
Handle<String> module_name = |
- data->GetValueChecked<String>(isolate_, kModuleName); |
- MaybeHandle<String> function_name = |
- data->GetValue<String>(isolate_, kFunctionName); |
+ ExtractStringFromModuleBytes(isolate_, compiled_module_, |
Mircea Trofin
2016/10/15 17:38:40
ExtractString allocates each time we call it. Shou
|
+ import.module_name_offset, |
+ import.module_name_length) |
+ .ToHandleChecked(); |
+ Handle<String> function_name = Handle<String>::null(); |
+ if (import.field_name_length > 0) { |
+ function_name = ExtractStringFromModuleBytes(isolate_, compiled_module_, |
+ import.field_name_offset, |
+ import.field_name_length) |
+ .ToHandleChecked(); |
+ } |
MaybeHandle<Object> result = |
LookupImport(index, module_name, function_name); |
if (thrower_->error()) return -1; |
- WasmExternalKind kind = static_cast<WasmExternalKind>( |
- Smi::cast(data->get(kImportKind))->value()); |
- switch (kind) { |
+ switch (import.kind) { |
case kExternalFunction: { |
// Function imports must be callable. |
Handle<Object> function = result.ToHandleChecked(); |
@@ -1690,10 +1377,9 @@ class WasmInstanceBuilder { |
} |
Handle<Code> import_wrapper = CompileImportWrapper( |
- index, data, Handle<JSReceiver>::cast(function), module_name, |
+ index, import, Handle<JSReceiver>::cast(function), module_name, |
function_name); |
- int func_index = Smi::cast(data->get(kImportIndex))->value(); |
- code_table->set(func_index, *import_wrapper); |
+ code_table->set(num_imported_functions, *import_wrapper); |
RecordStats(isolate_, *import_wrapper); |
num_imported_functions++; |
break; |
@@ -1723,9 +1409,7 @@ class WasmInstanceBuilder { |
return -1; |
} |
Handle<Object> val = number.ToHandleChecked(); |
- int offset = Smi::cast(data->get(kImportIndex))->value(); |
- int type = Smi::cast(data->get(kImportGlobalType))->value(); |
- WriteGlobalValue(globals, offset, val, type); |
+ WriteGlobalValue(module_->globals[import.index], globals, val); |
break; |
} |
default: |
@@ -1736,29 +1420,49 @@ class WasmInstanceBuilder { |
return num_imported_functions; |
} |
+ template <typename T> |
+ T* GetRawGlobalPtr(WasmGlobal& global, MaybeHandle<JSArrayBuffer> globals) { |
+ return reinterpret_cast<T*>(raw_buffer_ptr(globals, global.offset)); |
+ } |
+ |
// Process initialization of globals. |
- void ProcessInits(MaybeHandle<JSArrayBuffer> globals) { |
- if (!compiled_module_->has_inits()) return; |
- |
- Handle<FixedArray> inits = compiled_module_->inits(); |
- for (int index = 0; index < inits->length(); ++index) { |
- Handle<FixedArray> data = |
- inits->GetValueChecked<FixedArray>(isolate_, index); |
- |
- int offset = Smi::cast(data->get(kGlobalInitIndex))->value(); |
- Handle<Object> val(data->get(kGlobalInitValue), isolate_); |
- int type = Smi::cast(data->get(kGlobalInitType))->value(); |
- if (Smi::cast(data->get(kGlobalInitKind))->value() == 0) { |
- // Initialize with a constant. |
- WriteGlobalValue(globals, offset, val, type); |
- } else { |
- // Initialize with another global. |
- int old_offset = Smi::cast(*val)->value(); |
- TRACE("init [globals+%u] = [globals+%d]\n", offset, old_offset); |
- int size = sizeof(int32_t); |
- if (type == kLocalI64 || type == kLocalF64) size = sizeof(double); |
- memcpy(raw_buffer_ptr(globals, offset), |
- raw_buffer_ptr(globals, old_offset), size); |
+ void InitGlobals(MaybeHandle<JSArrayBuffer> globals) { |
+ for (auto global : module_->globals) { |
+ switch (global.init.kind) { |
+ case WasmInitExpr::kI32Const: |
+ *GetRawGlobalPtr<int32_t>(global, globals) = |
+ global.init.val.i32_const; |
+ break; |
+ case WasmInitExpr::kI64Const: |
+ *GetRawGlobalPtr<int64_t>(global, globals) = |
+ global.init.val.i64_const; |
+ break; |
+ case WasmInitExpr::kF32Const: |
+ *GetRawGlobalPtr<float>(global, globals) = global.init.val.f32_const; |
+ break; |
+ case WasmInitExpr::kF64Const: |
+ *GetRawGlobalPtr<double>(global, globals) = global.init.val.f64_const; |
+ break; |
+ case WasmInitExpr::kGlobalIndex: { |
+ // Initialize with another global. |
+ uint32_t new_offset = global.offset; |
+ uint32_t old_offset = |
+ module_->globals[global.init.val.global_index].offset; |
+ TRACE("init [globals+%u] = [globals+%d]\n", global.offset, |
+ old_offset); |
+ size_t size = (global.type == kAstI64 || global.type == kAstF64) |
+ ? size = sizeof(double) |
+ : sizeof(int32_t); |
+ memcpy(raw_buffer_ptr(globals, new_offset), |
+ raw_buffer_ptr(globals, old_offset), size); |
+ break; |
+ } |
+ case WasmInitExpr::kNone: |
+ // Happens with imported globals. |
+ break; |
+ default: |
+ UNREACHABLE(); |
+ break; |
} |
} |
} |
@@ -1783,10 +1487,10 @@ class WasmInstanceBuilder { |
void ProcessExports(MaybeHandle<JSArrayBuffer> globals, |
Handle<FixedArray> code_table, |
Handle<JSObject> instance) { |
- if (!compiled_module_->has_exports()) return; |
+ if (module_->export_table.size() == 0) return; |
Handle<JSObject> exports_object = instance; |
- if (compiled_module_->origin() == kWasmOrigin) { |
+ if (module_->origin == kWasmOrigin) { |
// Create the "exports" object. |
Handle<JSFunction> object_function = Handle<JSFunction>( |
isolate_->native_context()->object_function(), isolate_); |
@@ -1800,27 +1504,23 @@ class WasmInstanceBuilder { |
PropertyDescriptor desc; |
desc.set_writable(false); |
- Handle<FixedArray> exports = compiled_module_->exports(); |
- |
- for (int i = 0; i < exports->length(); ++i) { |
- Handle<FixedArray> export_data = |
- exports->GetValueChecked<FixedArray>(isolate_, i); |
+ int func_index = 0; |
+ for (auto exp : module_->export_table) { |
Mircea Trofin
2016/10/15 17:38:40
same comment about auto as above.
|
Handle<String> name = |
- export_data->GetValueChecked<String>(isolate_, kExportName); |
- WasmExternalKind kind = static_cast<WasmExternalKind>( |
- Smi::cast(export_data->get(kExportKind))->value()); |
- switch (kind) { |
+ ExtractStringFromModuleBytes(isolate_, compiled_module_, |
Mircea Trofin
2016/10/15 17:38:40
same comment about string interning as above
|
+ exp.name_offset, exp.name_length) |
+ .ToHandleChecked(); |
+ switch (exp.kind) { |
case kExternalFunction: { |
// Wrap and export the code as a JSFunction. |
- int code_table_index = |
- Smi::cast(export_data->get(kExportIndex))->value(); |
+ WasmFunction& function = module_->functions[exp.index]; |
+ int export_index = |
+ static_cast<int>(module_->functions.size() + func_index); |
Handle<Code> export_code = |
- code_table->GetValueChecked<Code>(isolate_, code_table_index); |
- int arity = Smi::cast(export_data->get(kExportArity))->value(); |
- MaybeHandle<ByteArray> signature = |
- export_data->GetValue<ByteArray>(isolate_, kExportedSignature); |
- desc.set_value(WrapExportCodeAsJSFunction( |
- isolate_, export_code, name, arity, signature, instance)); |
+ code_table->GetValueChecked<Code>(isolate_, export_index); |
+ desc.set_value(WrapExportCodeAsJSFunction(isolate_, export_code, name, |
+ function.sig, instance)); |
+ func_index++; |
break; |
} |
case kExternalTable: |
@@ -1847,18 +1547,17 @@ class WasmInstanceBuilder { |
} |
case kExternalGlobal: { |
// Export the value of the global variable as a number. |
- int offset = Smi::cast(export_data->get(kExportIndex))->value(); |
- byte* ptr = raw_buffer_ptr(globals, offset); |
+ WasmGlobal& global = module_->globals[exp.index]; |
double num = 0; |
- switch (Smi::cast(export_data->get(kExportGlobalType))->value()) { |
- case kLocalI32: |
- num = *reinterpret_cast<int32_t*>(ptr); |
+ switch (global.type) { |
+ case kAstI32: |
+ num = *GetRawGlobalPtr<int32_t>(global, globals); |
break; |
- case kLocalF32: |
- num = *reinterpret_cast<float*>(ptr); |
+ case kAstF32: |
+ num = *GetRawGlobalPtr<float>(global, globals); |
break; |
- case kLocalF64: |
- num = *reinterpret_cast<double*>(ptr); |
+ case kAstF64: |
+ num = *GetRawGlobalPtr<double>(global, globals); |
break; |
default: |
UNREACHABLE(); |
@@ -1886,37 +1585,26 @@ class WasmInstanceBuilder { |
// WebAssembly.Module. |
MaybeHandle<JSObject> WasmModule::Instantiate(Isolate* isolate, |
ErrorThrower* thrower, |
- Handle<JSObject> module_object, |
+ Handle<JSObject> wasm_module, |
Handle<JSReceiver> ffi, |
Handle<JSArrayBuffer> memory) { |
- WasmInstanceBuilder builder(isolate, thrower, module_object, ffi, memory); |
+ WasmInstanceBuilder builder(isolate, thrower, wasm_module, ffi, memory); |
return builder.Build(); |
} |
-Handle<WasmCompiledModule> WasmCompiledModule::New(Isolate* isolate, |
- uint32_t min_memory_pages, |
- uint32_t globals_size, |
- ModuleOrigin origin) { |
+Handle<WasmCompiledModule> WasmCompiledModule::New( |
+ Isolate* isolate, Handle<WasmModuleWrapper> module_wrapper) { |
Handle<FixedArray> ret = |
isolate->factory()->NewFixedArray(PropertyIndices::Count, TENURED); |
- // Globals size is expected to fit into an int without overflow. This is not |
- // supported by the spec at the moment, however, we don't support array |
- // buffer sizes over 1g, so, for now, we avoid alocating a HeapNumber for |
- // the globals size. The CHECK guards this assumption. |
- CHECK_GE(static_cast<int>(globals_size), 0); |
- ret->set(kID_min_memory_pages, |
- Smi::FromInt(static_cast<int>(min_memory_pages))); |
- ret->set(kID_globals_size, Smi::FromInt(static_cast<int>(globals_size))); |
- ret->set(kID_origin, Smi::FromInt(static_cast<int>(origin))); |
- |
// WasmCompiledModule::cast would fail since module bytes are not set yet. |
- Handle<WasmCompiledModule> module(reinterpret_cast<WasmCompiledModule*>(*ret), |
- isolate); |
- module->Init(); |
- return module; |
+ Handle<WasmCompiledModule> compiled_module( |
+ reinterpret_cast<WasmCompiledModule*>(*ret), isolate); |
+ compiled_module->InitId(); |
+ compiled_module->set_module_wrapper(module_wrapper); |
+ return compiled_module; |
} |
-void WasmCompiledModule::Init() { |
+void WasmCompiledModule::InitId() { |
#if DEBUG |
static uint32_t instance_id_counter = 0; |
set(kID_instance_id, Smi::FromInt(instance_id_counter++)); |
@@ -1960,39 +1648,39 @@ void WasmCompiledModule::PrintInstancesChain() { |
} |
Handle<Object> wasm::GetWasmFunctionNameOrNull(Isolate* isolate, |
- Handle<Object> wasm, |
+ Handle<Object> wasm_module, |
uint32_t func_index) { |
- if (!wasm->IsUndefined(isolate)) { |
- DCHECK(IsWasmObject(*wasm)); |
- WasmCompiledModule* compiled_module = |
- GetCompiledModule(JSObject::cast(*wasm)); |
- Handle<ByteArray> func_names = compiled_module->function_names(); |
- // TODO(clemens): Extract this from the module bytes; skip whole function |
- // name table. |
- Handle<Object> name; |
- if (GetWasmFunctionNameFromTable(func_names, func_index).ToHandle(&name)) { |
- return name; |
- } |
+ if (!wasm_module->IsUndefined(isolate)) { |
+ DCHECK(IsWasmModule(*wasm_module)); |
+ WasmModule* module = CppModule(Handle<JSObject>::cast(wasm_module)); |
+ WasmFunction& function = module->functions[func_index]; |
+ Handle<WasmCompiledModule> compiled_module(GetCompiledModule(*wasm_module), |
+ isolate); |
+ MaybeHandle<String> string = ExtractStringFromModuleBytes( |
+ isolate, compiled_module, function.name_offset, function.name_length); |
+ if (!string.is_null()) return string.ToHandleChecked(); |
} |
return isolate->factory()->null_value(); |
} |
-Handle<String> wasm::GetWasmFunctionName(Isolate* isolate, Handle<Object> wasm, |
+Handle<String> wasm::GetWasmFunctionName(Isolate* isolate, |
+ Handle<Object> wasm_module, |
uint32_t func_index) { |
Handle<Object> name_or_null = |
- GetWasmFunctionNameOrNull(isolate, wasm, func_index); |
+ GetWasmFunctionNameOrNull(isolate, wasm_module, func_index); |
if (!name_or_null->IsNull(isolate)) { |
return Handle<String>::cast(name_or_null); |
} |
return isolate->factory()->NewStringFromStaticChars("<WASM UNNAMED>"); |
} |
-bool wasm::IsWasmObject(Object* object) { |
+bool wasm::IsWasmModule(Object* object) { |
+ // TODO(titzer): this can be made reliable with WebAssembly.Module brand. |
if (!object->IsJSObject()) return false; |
JSObject* obj = JSObject::cast(object); |
Isolate* isolate = obj->GetIsolate(); |
- if (obj->GetInternalFieldCount() != kWasmModuleInternalFieldCount) { |
+ if (obj->GetInternalFieldCount() != kWasmInstanceInternalFieldCount) { |
return false; |
} |
@@ -2008,42 +1696,42 @@ bool wasm::IsWasmObject(Object* object) { |
return true; |
} |
-WasmCompiledModule* wasm::GetCompiledModule(JSObject* wasm) { |
- return WasmCompiledModule::cast(wasm->GetInternalField(kWasmCompiledModule)); |
+WasmCompiledModule* wasm::GetCompiledModule(Object* wasm_module) { |
+ DCHECK(IsWasmModule(wasm_module)); |
+ return WasmCompiledModule::cast( |
+ JSObject::cast(wasm_module)->GetInternalField(kWasmCompiledModule)); |
} |
-bool wasm::WasmIsAsmJs(Object* wasm, Isolate* isolate) { |
- if (wasm->IsUndefined(isolate)) return false; |
- DCHECK(IsWasmObject(wasm)); |
- WasmCompiledModule* compiled_module = GetCompiledModule(JSObject::cast(wasm)); |
- return compiled_module->has_asm_js_script(); |
+bool wasm::WasmIsAsmJs(Object* instance, Isolate* isolate) { |
+ return IsWasmModule(instance) && |
+ GetCompiledModule(JSObject::cast(instance))->has_asm_js_script(); |
} |
-Handle<Script> wasm::GetAsmWasmScript(Handle<JSObject> wasm) { |
- DCHECK(IsWasmObject(*wasm)); |
- WasmCompiledModule* compiled_module = GetCompiledModule(*wasm); |
+Handle<Script> wasm::GetAsmWasmScript(Handle<JSObject> wasm_module) { |
+ DCHECK(IsWasmModule(*wasm_module)); |
+ WasmCompiledModule* compiled_module = GetCompiledModule(*wasm_module); |
return compiled_module->asm_js_script(); |
} |
-int wasm::GetAsmWasmSourcePosition(Handle<JSObject> wasm, int func_index, |
+int wasm::GetAsmWasmSourcePosition(Handle<JSObject> wasm_module, int func_index, |
int byte_offset) { |
- return WasmDebugInfo::GetAsmJsSourcePosition(GetDebugInfo(wasm), func_index, |
- byte_offset); |
+ return WasmDebugInfo::GetAsmJsSourcePosition(GetDebugInfo(wasm_module), |
+ func_index, byte_offset); |
} |
-Handle<SeqOneByteString> wasm::GetWasmBytes(Handle<JSObject> wasm) { |
- DCHECK(IsWasmObject(*wasm)); |
- WasmCompiledModule* compiled_module = GetCompiledModule(*wasm); |
+Handle<SeqOneByteString> wasm::GetWasmBytes(Handle<JSObject> wasm_module) { |
+ DCHECK(IsWasmModule(*wasm_module)); |
+ WasmCompiledModule* compiled_module = GetCompiledModule(*wasm_module); |
return compiled_module->module_bytes(); |
} |
-Handle<WasmDebugInfo> wasm::GetDebugInfo(Handle<JSObject> wasm) { |
- Handle<Object> info(wasm->GetInternalField(kWasmDebugInfo), |
- wasm->GetIsolate()); |
- if (!info->IsUndefined(wasm->GetIsolate())) |
+Handle<WasmDebugInfo> wasm::GetDebugInfo(Handle<JSObject> wasm_module) { |
+ Handle<Object> info(wasm_module->GetInternalField(kWasmDebugInfo), |
+ wasm_module->GetIsolate()); |
+ if (!info->IsUndefined(wasm_module->GetIsolate())) |
return Handle<WasmDebugInfo>::cast(info); |
- Handle<WasmDebugInfo> new_info = WasmDebugInfo::New(wasm); |
- wasm->SetInternalField(kWasmDebugInfo, *new_info); |
+ Handle<WasmDebugInfo> new_info = WasmDebugInfo::New(wasm_module); |
+ wasm_module->SetInternalField(kWasmDebugInfo, *new_info); |
return new_info; |
} |
@@ -2051,7 +1739,7 @@ bool wasm::UpdateWasmModuleMemory(Handle<JSObject> object, Address old_start, |
Address new_start, uint32_t old_size, |
uint32_t new_size) { |
DisallowHeapAllocation no_allocation; |
- if (!IsWasmObject(*object)) { |
+ if (!IsWasmModule(*object)) { |
return false; |
} |
@@ -2079,72 +1767,34 @@ bool wasm::UpdateWasmModuleMemory(Handle<JSObject> object, Address old_start, |
return true; |
} |
-Handle<FixedArray> wasm::BuildFunctionTable(Isolate* isolate, uint32_t index, |
- const WasmModule* module) { |
- const WasmIndirectFunctionTable* table = &module->function_tables[index]; |
- DCHECK_EQ(table->size, table->values.size()); |
- DCHECK_GE(table->max_size, table->size); |
- Handle<FixedArray> values = |
- isolate->factory()->NewFixedArray(2 * table->max_size, TENURED); |
- for (uint32_t i = 0; i < table->size; ++i) { |
- const WasmFunction* function = &module->functions[table->values[i]]; |
- int32_t index = table->map.Find(function->sig); |
- DCHECK_GE(index, 0); |
- values->set(i, Smi::FromInt(index)); |
- values->set(i + table->max_size, Smi::FromInt(table->values[i])); |
- } |
- // Set the remaining elements to -1 (instead of "undefined"). These |
- // elements are accessed directly as SMIs (without a check). On 64-bit |
- // platforms, it is possible to have the top bits of "undefined" take |
- // small integer values (or zero), which are more likely to be equal to |
- // the signature index we check against. |
- for (uint32_t i = table->size; i < table->max_size; ++i) { |
- values->set(i, Smi::FromInt(-1)); |
- } |
- return values; |
+int wasm::GetNumberOfFunctions(Handle<JSObject> wasm_module) { |
+ WasmModule* module = CppModule(wasm_module); |
+ return static_cast<int>(module->functions.size()); |
} |
-void wasm::PopulateFunctionTable(Handle<FixedArray> table, uint32_t table_size, |
- const std::vector<Handle<Code>>* code_table) { |
- uint32_t max_size = table->length() / 2; |
- for (uint32_t i = max_size; i < max_size + table_size; ++i) { |
- int index = Smi::cast(table->get(static_cast<int>(i)))->value(); |
- DCHECK_GE(index, 0); |
- DCHECK_LT(static_cast<size_t>(index), code_table->size()); |
- table->set(static_cast<int>(i), *(*code_table)[index]); |
- } |
-} |
- |
-int wasm::GetNumberOfFunctions(Handle<JSObject> wasm) { |
- DCHECK(IsWasmObject(*wasm)); |
- WasmCompiledModule* compiled_module = GetCompiledModule(*wasm); |
- ByteArray* func_names_arr = compiled_module->ptr_to_function_names(); |
- // TODO(clemensh): this looks inside an array constructed elsewhere. Refactor. |
- return func_names_arr->get_int(0); |
-} |
- |
-Handle<JSObject> wasm::CreateCompiledModuleObject( |
+Handle<JSObject> wasm::CreateWasmModuleObject( |
Isolate* isolate, Handle<WasmCompiledModule> compiled_module, |
ModuleOrigin origin) { |
- Handle<JSObject> module_obj; |
+ Handle<JSObject> wasm_module; |
if (origin == ModuleOrigin::kWasmOrigin) { |
Handle<JSFunction> module_cons( |
isolate->native_context()->wasm_module_constructor()); |
- module_obj = isolate->factory()->NewJSObject(module_cons); |
+ wasm_module = isolate->factory()->NewJSObject(module_cons); |
} else { |
DCHECK(origin == ModuleOrigin::kAsmJsOrigin); |
Handle<Map> map = isolate->factory()->NewMap( |
JS_OBJECT_TYPE, JSObject::kHeaderSize + kPointerSize); |
- module_obj = isolate->factory()->NewJSObjectFromMap(map, TENURED); |
+ wasm_module = isolate->factory()->NewJSObjectFromMap(map, TENURED); |
} |
- module_obj->SetInternalField(0, *compiled_module); |
+ wasm_module->SetInternalField(0, *compiled_module); |
if (origin == ModuleOrigin::kWasmOrigin) { |
Handle<Symbol> module_sym(isolate->native_context()->wasm_module_sym()); |
- Object::SetProperty(module_obj, module_sym, module_obj, STRICT).Check(); |
+ Object::SetProperty(wasm_module, module_sym, wasm_module, STRICT).Check(); |
} |
- Handle<WeakCell> link_to_module = isolate->factory()->NewWeakCell(module_obj); |
- compiled_module->set_weak_module_object(link_to_module); |
- return module_obj; |
+ Handle<WeakCell> link_to_module = |
+ isolate->factory()->NewWeakCell(wasm_module); |
+ compiled_module->set_weak_wasm_module(link_to_module); |
+ return wasm_module; |
} |
// TODO(clemensh): origin can be inferred from asm_js_script; remove it. |
@@ -2154,17 +1804,23 @@ MaybeHandle<JSObject> wasm::CreateModuleObjectFromBytes( |
const byte* asm_js_offset_tables_start, |
const byte* asm_js_offset_tables_end) { |
MaybeHandle<JSObject> nothing; |
- Zone zone(isolate->allocator()); |
- ModuleResult result = |
- DecodeWasmModule(isolate, &zone, start, end, false, origin); |
- std::unique_ptr<const WasmModule> decoded_module(result.val); |
+ ModuleResult result = DecodeWasmModule(isolate, start, end, false, origin); |
if (result.failed()) { |
+ if (result.val) delete result.val; |
thrower->Failed("Wasm decoding failed", result); |
return nothing; |
} |
+ // The {module_wrapper} will take ownership of the {WasmModule} object, |
+ // and it will be destroyed when the GC reclaims the wrapper object. |
+ Handle<WasmModuleWrapper> module_wrapper = |
+ WasmModuleWrapper::New(isolate, const_cast<WasmModule*>(result.val)); |
+ |
+ // Compile the functions of the module, producing a compiled module. |
MaybeHandle<WasmCompiledModule> maybe_compiled_module = |
- decoded_module->CompileFunctions(isolate, thrower); |
+ result.val->CompileFunctions(isolate, module_wrapper, thrower); |
+ |
if (maybe_compiled_module.is_null()) return nothing; |
+ |
Handle<WasmCompiledModule> compiled_module = |
maybe_compiled_module.ToHandleChecked(); |
@@ -2183,15 +1839,13 @@ MaybeHandle<JSObject> wasm::CreateModuleObjectFromBytes( |
compiled_module->set_asm_js_offset_tables(offset_tables); |
} |
- return CreateCompiledModuleObject(isolate, compiled_module, origin); |
+ return CreateWasmModuleObject(isolate, compiled_module, origin); |
} |
bool wasm::ValidateModuleBytes(Isolate* isolate, const byte* start, |
const byte* end, ErrorThrower* thrower, |
ModuleOrigin origin) { |
- Zone zone(isolate->allocator()); |
- ModuleResult result = |
- DecodeWasmModule(isolate, &zone, start, end, false, origin); |
+ ModuleResult result = DecodeWasmModule(isolate, start, end, false, origin); |
if (result.ok()) { |
DCHECK_NOT_NULL(result.val); |
delete result.val; |
@@ -2203,17 +1857,17 @@ bool wasm::ValidateModuleBytes(Isolate* isolate, const byte* start, |
MaybeHandle<JSArrayBuffer> wasm::GetInstanceMemory(Isolate* isolate, |
Handle<JSObject> instance) { |
Object* mem = instance->GetInternalField(kWasmMemArrayBuffer); |
- DCHECK(IsWasmObject(*instance)); |
+ DCHECK(IsWasmModule(*instance)); |
if (mem->IsUndefined(isolate)) return MaybeHandle<JSArrayBuffer>(); |
return Handle<JSArrayBuffer>(JSArrayBuffer::cast(mem)); |
} |
void SetInstanceMemory(Handle<JSObject> instance, JSArrayBuffer* buffer) { |
DisallowHeapAllocation no_gc; |
- DCHECK(IsWasmObject(*instance)); |
+ DCHECK(IsWasmModule(*instance)); |
instance->SetInternalField(kWasmMemArrayBuffer, buffer); |
WasmCompiledModule* compiled_module = GetCompiledModule(*instance); |
- compiled_module->set_ptr_to_heap(buffer); |
+ compiled_module->set_ptr_to_memory(buffer); |
} |
int32_t wasm::GetInstanceMemorySize(Isolate* isolate, |
@@ -2278,25 +1932,24 @@ int32_t wasm::GrowInstanceMemory(Isolate* isolate, Handle<JSObject> instance, |
} |
void testing::ValidateInstancesChain(Isolate* isolate, |
- Handle<JSObject> module_obj, |
+ Handle<JSObject> wasm_module, |
int instance_count) { |
CHECK_GE(instance_count, 0); |
DisallowHeapAllocation no_gc; |
WasmCompiledModule* compiled_module = |
- WasmCompiledModule::cast(module_obj->GetInternalField(0)); |
- CHECK_EQ( |
- JSObject::cast(compiled_module->ptr_to_weak_module_object()->value()), |
- *module_obj); |
+ WasmCompiledModule::cast(wasm_module->GetInternalField(0)); |
+ CHECK_EQ(JSObject::cast(compiled_module->ptr_to_weak_wasm_module()->value()), |
+ *wasm_module); |
Object* prev = nullptr; |
int found_instances = compiled_module->has_weak_owning_instance() ? 1 : 0; |
WasmCompiledModule* current_instance = compiled_module; |
while (current_instance->has_weak_next_instance()) { |
CHECK((prev == nullptr && !current_instance->has_weak_prev_instance()) || |
current_instance->ptr_to_weak_prev_instance()->value() == prev); |
- CHECK_EQ(current_instance->ptr_to_weak_module_object()->value(), |
- *module_obj); |
+ CHECK_EQ(current_instance->ptr_to_weak_wasm_module()->value(), |
+ *wasm_module); |
CHECK( |
- IsWasmObject(current_instance->ptr_to_weak_owning_instance()->value())); |
+ IsWasmModule(current_instance->ptr_to_weak_owning_instance()->value())); |
prev = current_instance; |
current_instance = WasmCompiledModule::cast( |
current_instance->ptr_to_weak_next_instance()->value()); |
@@ -2307,22 +1960,56 @@ void testing::ValidateInstancesChain(Isolate* isolate, |
} |
void testing::ValidateModuleState(Isolate* isolate, |
- Handle<JSObject> module_obj) { |
+ Handle<JSObject> wasm_module) { |
DisallowHeapAllocation no_gc; |
WasmCompiledModule* compiled_module = |
- WasmCompiledModule::cast(module_obj->GetInternalField(0)); |
- CHECK(compiled_module->has_weak_module_object()); |
- CHECK_EQ(compiled_module->ptr_to_weak_module_object()->value(), *module_obj); |
+ WasmCompiledModule::cast(wasm_module->GetInternalField(0)); |
+ CHECK(compiled_module->has_weak_wasm_module()); |
+ CHECK_EQ(compiled_module->ptr_to_weak_wasm_module()->value(), *wasm_module); |
CHECK(!compiled_module->has_weak_prev_instance()); |
CHECK(!compiled_module->has_weak_next_instance()); |
CHECK(!compiled_module->has_weak_owning_instance()); |
} |
void testing::ValidateOrphanedInstance(Isolate* isolate, |
- Handle<JSObject> instance) { |
+ Handle<JSObject> wasm_module) { |
DisallowHeapAllocation no_gc; |
- CHECK(IsWasmObject(*instance)); |
- WasmCompiledModule* compiled_module = GetCompiledModule(*instance); |
- CHECK(compiled_module->has_weak_module_object()); |
- CHECK(compiled_module->ptr_to_weak_module_object()->cleared()); |
+ CHECK(IsWasmModule(*wasm_module)); |
+ WasmCompiledModule* compiled_module = GetCompiledModule(*wasm_module); |
+ CHECK(compiled_module->has_weak_wasm_module()); |
+ CHECK(compiled_module->ptr_to_weak_wasm_module()->cleared()); |
+} |
+ |
+uint32_t WasmCompiledModule::min_memory_pages() const { |
+ return reinterpret_cast<WasmModuleWrapper*>(*module_wrapper()) |
+ ->get() |
+ ->min_mem_pages; |
+} |
+ |
+void WasmCompiledModule::RecreateModuleWrapper(Isolate* isolate, |
+ Handle<FixedArray> array) { |
Mircea Trofin
2016/10/15 17:38:41
why not pass this guy as a Handle<WasmCompiledModu
|
+ Handle<WasmCompiledModule> compiled_module( |
+ reinterpret_cast<WasmCompiledModule*>(*array), isolate); |
+ |
+ WasmModule* module = nullptr; |
+ { |
+ Handle<SeqOneByteString> module_bytes = compiled_module->module_bytes(); |
+ // We parse the module again directly from the module bytes; disable GC. |
+ DisallowHeapAllocation no_allocation; |
+ const byte* start = |
+ reinterpret_cast<const byte*>(module_bytes->GetCharsAddress()); |
+ const byte* end = start + module_bytes->length(); |
+ // TODO(titzer): remember the module origin in the compiled_module |
+ ModuleResult result = |
+ DecodeWasmModule(isolate, start, end, false, kWasmOrigin); |
Mircea Trofin
2016/10/15 17:38:40
Could you add a TODO to avoid decoding the entire
|
+ CHECK(result.ok()); |
+ CHECK_NOT_NULL(result.val); |
+ module = const_cast<WasmModule*>(result.val); |
+ } |
+ |
+ Handle<WasmModuleWrapper> module_wrapper = |
+ WasmModuleWrapper::New(isolate, module); |
+ |
+ compiled_module->set_module_wrapper(module_wrapper); |
+ DCHECK(WasmCompiledModule::IsWasmCompiledModule(*compiled_module)); |
} |