Chromium Code Reviews| OLD | NEW | 
|---|---|
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include <memory> | 5 #include <memory> | 
| 6 | 6 | 
| 7 #include "src/base/atomic-utils.h" | 7 #include "src/base/atomic-utils.h" | 
| 8 #include "src/code-stubs.h" | 8 #include "src/code-stubs.h" | 
| 9 | 9 | 
| 10 #include "src/macro-assembler.h" | 10 #include "src/macro-assembler.h" | 
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 45 enum JSFunctionExportInternalField { | 45 enum JSFunctionExportInternalField { | 
| 46 kInternalModuleInstance, | 46 kInternalModuleInstance, | 
| 47 kInternalArity, | 47 kInternalArity, | 
| 48 kInternalSignature | 48 kInternalSignature | 
| 49 }; | 49 }; | 
| 50 | 50 | 
| 51 // Internal constants for the layout of the module object. | 51 // Internal constants for the layout of the module object. | 
| 52 enum WasmInstanceObjectFields { | 52 enum WasmInstanceObjectFields { | 
| 53 kWasmCompiledModule = 0, | 53 kWasmCompiledModule = 0, | 
| 54 kWasmModuleFunctionTable, | 54 kWasmModuleFunctionTable, | 
| 55 kWasmModuleCodeTable, | 55 kWasmModuleCodeTable, // TODO(titzer): code_table is in compiled module | 
| 56 kWasmMemObject, | 56 kWasmMemObject, | 
| 57 kWasmMemArrayBuffer, | 57 kWasmMemArrayBuffer, | 
| 58 kWasmGlobalsArrayBuffer, | 58 kWasmGlobalsArrayBuffer, | 
| 59 kWasmDebugInfo, | 59 kWasmDebugInfo, | 
| 60 kWasmModuleInternalFieldCount | 60 kWasmInstanceInternalFieldCount | 
| 61 }; | |
| 62 | |
| 63 enum WasmImportData { | |
| 64 kImportKind, // Smi. an ExternalKind | |
| 65 kImportGlobalType, // Smi. Type for globals. | |
| 66 kImportIndex, // Smi. index for the import. | |
| 67 kModuleName, // String | |
| 68 kFunctionName, // maybe String | |
| 69 kOutputCount, // Smi. an uint32_t | |
| 70 kSignature, // ByteArray. A copy of the data in FunctionSig | |
| 71 kWasmImportDataSize // Sentinel value. | |
| 72 }; | |
| 73 | |
| 74 enum WasmExportData { | |
| 75 kExportKind, // Smi. an ExternalKind | |
| 76 kExportGlobalType, // Smi. Type for globals. | |
| 77 kExportName, // String | |
| 78 kExportArity, // Smi, an int | |
| 79 kExportIndex, // Smi, an uint32_t | |
| 80 kExportedSignature, // ByteArray. A copy of the data in FunctionSig | |
| 81 kWasmExportDataSize // Sentinel value. | |
| 82 }; | |
| 83 | |
| 84 enum WasmGlobalInitData { | |
| 85 kGlobalInitKind, // 0 = constant, 1 = global index | |
| 86 kGlobalInitType, // Smi. Type for globals. | |
| 87 kGlobalInitIndex, // Smi, an uint32_t | |
| 88 kGlobalInitValue, // Number. | |
| 89 kWasmGlobalInitDataSize | |
| 90 }; | |
| 91 | |
| 92 enum WasmSegmentInfo { | |
| 93 kDestAddrKind, // 0 = constant, 1 = global index | |
| 94 kDestAddrValue, // Smi. an uint32_t | |
| 95 kSourceSize, // Smi. an uint32_t | |
| 96 kWasmSegmentInfoSize // Sentinel value. | |
| 97 }; | |
| 98 | |
| 99 enum WasmIndirectFunctionTableData { | |
| 100 kSize, // Smi. an uint32_t | |
| 101 kTable, // FixedArray of indirect function table | |
| 102 kWasmIndirectFunctionTableDataSize // Sentinel value. | |
| 103 }; | 61 }; | 
| 104 | 62 | 
| 105 byte* raw_buffer_ptr(MaybeHandle<JSArrayBuffer> buffer, int offset) { | 63 byte* raw_buffer_ptr(MaybeHandle<JSArrayBuffer> buffer, int offset) { | 
| 106 return static_cast<byte*>(buffer.ToHandleChecked()->backing_store()) + offset; | 64 return static_cast<byte*>(buffer.ToHandleChecked()->backing_store()) + offset; | 
| 107 } | 65 } | 
| 108 | 66 | 
| 109 uint32_t GetMinModuleMemSize(const WasmModule* module) { | 67 uint32_t GetMinModuleMemSize(const WasmModule* module) { | 
| 110 return WasmModule::kPageSize * module->min_mem_pages; | 68 return WasmModule::kPageSize * module->min_mem_pages; | 
| 111 } | 69 } | 
| 112 | 70 | 
| 113 void SaveDataSegmentInfo(Factory* factory, const WasmModule* module, | 71 MaybeHandle<String> ExtractStringFromModuleBytes( | 
| 114 Handle<WasmCompiledModule> compiled_module) { | 72 Isolate* isolate, Handle<WasmCompiledModule> compiled_module, | 
| 115 Handle<FixedArray> segments = factory->NewFixedArray( | 73 uint32_t offset, uint32_t size) { | 
| 116 static_cast<int>(module->data_segments.size()), TENURED); | 74 Handle<SeqOneByteString> module_bytes = compiled_module->module_bytes(); | 
| 117 uint32_t data_size = 0; | 75 Address raw = module_bytes->GetCharsAddress() + offset; | 
| 118 for (const WasmDataSegment& segment : module->data_segments) { | 76 if (!unibrow::Utf8::Validate(reinterpret_cast<const byte*>(raw), size)) | 
| 119 if (segment.source_size == 0) continue; | 77 return {}; | 
| 120 data_size += segment.source_size; | 78 Vector<const char> vec(reinterpret_cast<const char*>(raw), size); | 
| 121 } | 79 // TODO(titzer): can't GC move the underlying storage during this call? | 
| 122 Handle<ByteArray> data = factory->NewByteArray(data_size, TENURED); | 80 return isolate->factory()->NewStringFromUtf8(vec); | 
| 
 
Mircea Trofin
2016/10/15 17:38:40
Shouldn't we worry about GC happening when: alloca
 
 | |
| 123 | |
| 124 uint32_t last_insertion_pos = 0; | |
| 125 for (uint32_t i = 0; i < module->data_segments.size(); ++i) { | |
| 126 const WasmDataSegment& segment = module->data_segments[i]; | |
| 127 if (segment.source_size == 0) continue; | |
| 128 Handle<ByteArray> js_segment = | |
| 129 factory->NewByteArray(kWasmSegmentInfoSize * sizeof(uint32_t), TENURED); | |
| 130 if (segment.dest_addr.kind == WasmInitExpr::kGlobalIndex) { | |
| 131 // The destination address is the value of a global variable. | |
| 132 js_segment->set_int(kDestAddrKind, 1); | |
| 133 uint32_t offset = | |
| 134 module->globals[segment.dest_addr.val.global_index].offset; | |
| 135 js_segment->set_int(kDestAddrValue, static_cast<int>(offset)); | |
| 136 } else { | |
| 137 // The destination address is a constant. | |
| 138 CHECK_EQ(WasmInitExpr::kI32Const, segment.dest_addr.kind); | |
| 139 js_segment->set_int(kDestAddrKind, 0); | |
| 140 js_segment->set_int(kDestAddrValue, segment.dest_addr.val.i32_const); | |
| 141 } | |
| 142 js_segment->set_int(kSourceSize, segment.source_size); | |
| 143 segments->set(i, *js_segment); | |
| 144 data->copy_in(last_insertion_pos, | |
| 145 module->module_start + segment.source_offset, | |
| 146 segment.source_size); | |
| 147 last_insertion_pos += segment.source_size; | |
| 148 } | |
| 149 compiled_module->set_data_segments_info(segments); | |
| 150 compiled_module->set_data_segments(data); | |
| 151 } | 81 } | 
| 152 | 82 | 
| 153 void PatchFunctionTable(Handle<Code> code, | 83 void ReplaceReferenceInCode(Handle<Code> code, Handle<Object> old_ref, | 
| 154 Handle<FixedArray> old_indirect_table, | 84 Handle<Object> new_ref) { | 
| 155 Handle<FixedArray> new_indirect_table) { | |
| 156 for (RelocIterator it(*code, 1 << RelocInfo::EMBEDDED_OBJECT); !it.done(); | 85 for (RelocIterator it(*code, 1 << RelocInfo::EMBEDDED_OBJECT); !it.done(); | 
| 157 it.next()) { | 86 it.next()) { | 
| 158 if (it.rinfo()->target_object() == *old_indirect_table) { | 87 if (it.rinfo()->target_object() == *old_ref) { | 
| 159 it.rinfo()->set_target_object(*new_indirect_table); | 88 it.rinfo()->set_target_object(*new_ref); | 
| 160 } | 89 } | 
| 161 } | 90 } | 
| 162 } | 91 } | 
| 163 | 92 | 
| 164 Handle<JSArrayBuffer> NewArrayBuffer(Isolate* isolate, size_t size) { | 93 Handle<JSArrayBuffer> NewArrayBuffer(Isolate* isolate, size_t size) { | 
| 165 if (size > (WasmModule::kMaxMemPages * WasmModule::kPageSize)) { | 94 if (size > (WasmModule::kMaxMemPages * WasmModule::kPageSize)) { | 
| 166 // TODO(titzer): lift restriction on maximum memory allocated here. | 95 // TODO(titzer): lift restriction on maximum memory allocated here. | 
| 167 return Handle<JSArrayBuffer>::null(); | 96 return Handle<JSArrayBuffer>::null(); | 
| 168 } | 97 } | 
| 169 void* memory = isolate->array_buffer_allocator()->Allocate(size); | 98 void* memory = isolate->array_buffer_allocator()->Allocate(size); | 
| 170 if (memory == nullptr) { | 99 if (memory == nullptr) { | 
| 171 return Handle<JSArrayBuffer>::null(); | 100 return Handle<JSArrayBuffer>::null(); | 
| 172 } | 101 } | 
| 173 | 102 | 
| 174 #if DEBUG | 103 #if DEBUG | 
| 175 // Double check the API allocator actually zero-initialized the memory. | 104 // Double check the API allocator actually zero-initialized the memory. | 
| 176 const byte* bytes = reinterpret_cast<const byte*>(memory); | 105 const byte* bytes = reinterpret_cast<const byte*>(memory); | 
| 177 for (size_t i = 0; i < size; ++i) { | 106 for (size_t i = 0; i < size; ++i) { | 
| 178 DCHECK_EQ(0, bytes[i]); | 107 DCHECK_EQ(0, bytes[i]); | 
| 179 } | 108 } | 
| 180 #endif | 109 #endif | 
| 181 | 110 | 
| 182 Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer(); | 111 Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer(); | 
| 183 JSArrayBuffer::Setup(buffer, isolate, false, memory, static_cast<int>(size)); | 112 JSArrayBuffer::Setup(buffer, isolate, false, memory, static_cast<int>(size)); | 
| 184 buffer->set_is_neuterable(false); | 113 buffer->set_is_neuterable(false); | 
| 185 return buffer; | 114 return buffer; | 
| 186 } | 115 } | 
| 187 | 116 | 
| 188 void RelocateInstanceCode(Handle<JSObject> instance, Address old_start, | 117 void RelocateInstanceCode(Handle<FixedArray> code_table, Address old_start, | 
| 189 Address start, uint32_t prev_size, | 118 Address start, uint32_t prev_size, | 
| 190 uint32_t new_size) { | 119 uint32_t new_size) { | 
| 191 Handle<FixedArray> functions = Handle<FixedArray>( | 120 for (int i = 0; i < code_table->length(); ++i) { | 
| 192 FixedArray::cast(instance->GetInternalField(kWasmModuleCodeTable))); | 121 DCHECK(code_table->get(i)->IsCode()); | 
| 193 for (int i = 0; i < functions->length(); ++i) { | 122 Handle<Code> code = Handle<Code>(Code::cast(code_table->get(i))); | 
| 194 Handle<Code> function = Handle<Code>(Code::cast(functions->get(i))); | |
| 195 AllowDeferredHandleDereference embedding_raw_address; | 123 AllowDeferredHandleDereference embedding_raw_address; | 
| 196 int mask = (1 << RelocInfo::WASM_MEMORY_REFERENCE) | | 124 int mask = (1 << RelocInfo::WASM_MEMORY_REFERENCE) | | 
| 197 (1 << RelocInfo::WASM_MEMORY_SIZE_REFERENCE); | 125 (1 << RelocInfo::WASM_MEMORY_SIZE_REFERENCE); | 
| 198 for (RelocIterator it(*function, mask); !it.done(); it.next()) { | 126 for (RelocIterator it(*code, mask); !it.done(); it.next()) { | 
| 199 it.rinfo()->update_wasm_memory_reference(old_start, start, prev_size, | 127 it.rinfo()->update_wasm_memory_reference(old_start, start, prev_size, | 
| 200 new_size); | 128 new_size); | 
| 201 } | 129 } | 
| 202 } | 130 } | 
| 203 } | 131 } | 
| 204 | 132 | 
| 205 void RelocateGlobals(Handle<JSObject> instance, Address old_start, | 133 void RelocateGlobals(Handle<FixedArray> code_table, Address old_start, | 
| 206 Address globals_start) { | 134 Address globals_start) { | 
| 207 Handle<FixedArray> functions = Handle<FixedArray>( | 135 for (int i = 0; i < code_table->length(); ++i) { | 
| 208 FixedArray::cast(instance->GetInternalField(kWasmModuleCodeTable))); | 136 DCHECK(code_table->get(i)->IsCode()); | 
| 209 uint32_t function_count = static_cast<uint32_t>(functions->length()); | 137 Handle<Code> code = Handle<Code>(Code::cast(code_table->get(i))); | 
| 210 for (uint32_t i = 0; i < function_count; ++i) { | |
| 211 Handle<Code> function = Handle<Code>(Code::cast(functions->get(i))); | |
| 212 AllowDeferredHandleDereference embedding_raw_address; | 138 AllowDeferredHandleDereference embedding_raw_address; | 
| 213 int mask = 1 << RelocInfo::WASM_GLOBAL_REFERENCE; | 139 int mask = 1 << RelocInfo::WASM_GLOBAL_REFERENCE; | 
| 214 for (RelocIterator it(*function, mask); !it.done(); it.next()) { | 140 for (RelocIterator it(*code, mask); !it.done(); it.next()) { | 
| 215 it.rinfo()->update_wasm_global_reference(old_start, globals_start); | 141 it.rinfo()->update_wasm_global_reference(old_start, globals_start); | 
| 216 } | 142 } | 
| 217 } | 143 } | 
| 218 } | 144 } | 
| 219 | 145 | 
| 220 Handle<Code> CreatePlaceholder(Factory* factory, uint32_t index, | 146 Handle<Code> CreatePlaceholder(Factory* factory, uint32_t index, | 
| 221 Code::Kind kind) { | 147 Code::Kind kind) { | 
| 222 // Create a placeholder code object and encode the corresponding index in | 148 // Create a placeholder code object and encode the corresponding index in | 
| 223 // the {constant_pool_offset} field of the code object. | 149 // the {constant_pool_offset} field of the code object. | 
| 224 // TODO(titzer): placeholder code objects are somewhat dangerous. | 150 // TODO(titzer): placeholder code objects are somewhat dangerous. | 
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 258 break; | 184 break; | 
| 259 } | 185 } | 
| 260 default: | 186 default: | 
| 261 break; | 187 break; | 
| 262 } | 188 } | 
| 263 } | 189 } | 
| 264 } | 190 } | 
| 265 return modified; | 191 return modified; | 
| 266 } | 192 } | 
| 267 | 193 | 
| 268 void FlushICache(Isolate* isolate, Handle<FixedArray> functions) { | 194 void FlushICache(Isolate* isolate, Handle<FixedArray> code_table) { | 
| 269 for (int i = 0; i < functions->length(); ++i) { | 195 for (int i = 0; i < code_table->length(); ++i) { | 
| 270 Handle<Code> code = functions->GetValueChecked<Code>(isolate, i); | 196 Handle<Code> code = code_table->GetValueChecked<Code>(isolate, i); | 
| 271 Assembler::FlushICache(isolate, code->instruction_start(), | 197 Assembler::FlushICache(isolate, code->instruction_start(), | 
| 272 code->instruction_size()); | 198 code->instruction_size()); | 
| 273 } | 199 } | 
| 274 } | 200 } | 
| 275 | 201 | 
| 276 // Fetches the compilation unit of a wasm function and executes its parallel | 202 // Fetches the compilation unit of a wasm function and executes its parallel | 
| 277 // phase. | 203 // phase. | 
| 278 bool FetchAndExecuteCompilationUnit( | 204 bool FetchAndExecuteCompilationUnit( | 
| 279 Isolate* isolate, | 205 Isolate* isolate, | 
| 280 std::vector<compiler::WasmCompilationUnit*>* compilation_units, | 206 std::vector<compiler::WasmCompilationUnit*>* compilation_units, | 
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 349 JSObject* owner) { | 275 JSObject* owner) { | 
| 350 Address old_address = nullptr; | 276 Address old_address = nullptr; | 
| 351 Object* stored_value = owner->GetInternalField(kWasmGlobalsArrayBuffer); | 277 Object* stored_value = owner->GetInternalField(kWasmGlobalsArrayBuffer); | 
| 352 if (stored_value != undefined) { | 278 if (stored_value != undefined) { | 
| 353 old_address = static_cast<Address>( | 279 old_address = static_cast<Address>( | 
| 354 JSArrayBuffer::cast(stored_value)->backing_store()); | 280 JSArrayBuffer::cast(stored_value)->backing_store()); | 
| 355 } | 281 } | 
| 356 return old_address; | 282 return old_address; | 
| 357 } | 283 } | 
| 358 | 284 | 
| 359 Handle<FixedArray> EncodeImports(Factory* factory, const WasmModule* module) { | |
| 360 // TODO(wasm): Encode this in one big FixedArray. | |
| 361 Handle<FixedArray> ret = factory->NewFixedArray( | |
| 362 static_cast<int>(module->import_table.size()), TENURED); | |
| 363 | |
| 364 for (size_t i = 0; i < module->import_table.size(); ++i) { | |
| 365 const WasmImport& import = module->import_table[i]; | |
| 366 Handle<FixedArray> encoded_import = | |
| 367 factory->NewFixedArray(kWasmImportDataSize, TENURED); | |
| 368 encoded_import->set(kImportKind, Smi::FromInt(import.kind)); | |
| 369 encoded_import->set(kImportIndex, Smi::FromInt(import.index)); | |
| 370 | |
| 371 // Add the module and function name. | |
| 372 WasmName module_name = module->GetNameOrNull(import.module_name_offset, | |
| 373 import.module_name_length); | |
| 374 WasmName function_name = module->GetNameOrNull(import.field_name_offset, | |
| 375 import.field_name_length); | |
| 376 | |
| 377 Handle<String> module_name_string = | |
| 378 factory->InternalizeUtf8String(module_name); | |
| 379 encoded_import->set(kModuleName, *module_name_string); | |
| 380 if (!function_name.is_empty()) { | |
| 381 Handle<String> function_name_string = | |
| 382 factory->InternalizeUtf8String(function_name); | |
| 383 encoded_import->set(kFunctionName, *function_name_string); | |
| 384 } | |
| 385 | |
| 386 switch (import.kind) { | |
| 387 case kExternalFunction: { | |
| 388 // Encode the signature into the import. | |
| 389 FunctionSig* fsig = module->functions[import.index].sig; | |
| 390 Handle<ByteArray> sig = factory->NewByteArray( | |
| 391 static_cast<int>(fsig->parameter_count() + fsig->return_count()), | |
| 392 TENURED); | |
| 393 sig->copy_in(0, reinterpret_cast<const byte*>(fsig->raw_data()), | |
| 394 sig->length()); | |
| 395 encoded_import->set( | |
| 396 kOutputCount, Smi::FromInt(static_cast<int>(fsig->return_count()))); | |
| 397 encoded_import->set(kSignature, *sig); | |
| 398 break; | |
| 399 } | |
| 400 case kExternalTable: | |
| 401 // Nothing extra required for imported tables. | |
| 402 break; | |
| 403 case kExternalMemory: | |
| 404 // Nothing extra required for imported memories. | |
| 405 break; | |
| 406 case kExternalGlobal: { | |
| 407 // Encode the offset and the global type into the import. | |
| 408 const WasmGlobal& global = module->globals[import.index]; | |
| 409 TRACE("import[%zu].type = %s\n", i, WasmOpcodes::TypeName(global.type)); | |
| 410 encoded_import->set( | |
| 411 kImportGlobalType, | |
| 412 Smi::FromInt(WasmOpcodes::LocalTypeCodeFor(global.type))); | |
| 413 encoded_import->set(kImportIndex, Smi::FromInt(global.offset)); | |
| 414 break; | |
| 415 } | |
| 416 } | |
| 417 ret->set(static_cast<int>(i), *encoded_import); | |
| 418 } | |
| 419 return ret; | |
| 420 } | |
| 421 | |
| 422 void InitializeParallelCompilation( | 285 void InitializeParallelCompilation( | 
| 423 Isolate* isolate, const std::vector<WasmFunction>& functions, | 286 Isolate* isolate, const std::vector<WasmFunction>& functions, | 
| 424 std::vector<compiler::WasmCompilationUnit*>& compilation_units, | 287 std::vector<compiler::WasmCompilationUnit*>& compilation_units, | 
| 425 ModuleEnv& module_env, ErrorThrower* thrower) { | 288 ModuleEnv& module_env, ErrorThrower* thrower) { | 
| 426 for (uint32_t i = FLAG_skip_compiling_wasm_funcs; i < functions.size(); ++i) { | 289 for (uint32_t i = FLAG_skip_compiling_wasm_funcs; i < functions.size(); ++i) { | 
| 427 const WasmFunction* func = &functions[i]; | 290 const WasmFunction* func = &functions[i]; | 
| 428 compilation_units[i] = | 291 compilation_units[i] = | 
| 429 func->imported ? nullptr : new compiler::WasmCompilationUnit( | 292 func->imported ? nullptr : new compiler::WasmCompilationUnit( | 
| 430 thrower, isolate, &module_env, func, i); | 293 thrower, isolate, &module_env, func, i); | 
| 431 } | 294 } | 
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 603 } | 466 } | 
| 604 } | 467 } | 
| 605 } | 468 } | 
| 606 } | 469 } | 
| 607 } | 470 } | 
| 608 | 471 | 
| 609 static void ResetCompiledModule(Isolate* isolate, JSObject* owner, | 472 static void ResetCompiledModule(Isolate* isolate, JSObject* owner, | 
| 610 WasmCompiledModule* compiled_module) { | 473 WasmCompiledModule* compiled_module) { | 
| 611 TRACE("Resetting %d\n", compiled_module->instance_id()); | 474 TRACE("Resetting %d\n", compiled_module->instance_id()); | 
| 612 Object* undefined = *isolate->factory()->undefined_value(); | 475 Object* undefined = *isolate->factory()->undefined_value(); | 
| 613 uint32_t old_mem_size = compiled_module->has_heap() | 476 uint32_t old_mem_size = compiled_module->has_memory() | 
| 614 ? compiled_module->mem_size() | 477 ? compiled_module->mem_size() | 
| 615 : compiled_module->default_mem_size(); | 478 : compiled_module->default_mem_size(); | 
| 616 uint32_t default_mem_size = compiled_module->default_mem_size(); | 479 uint32_t default_mem_size = compiled_module->default_mem_size(); | 
| 617 Object* mem_start = compiled_module->ptr_to_heap(); | 480 Object* mem_start = compiled_module->ptr_to_memory(); | 
| 618 Address old_mem_address = nullptr; | 481 Address old_mem_address = nullptr; | 
| 619 Address globals_start = | 482 Address globals_start = | 
| 620 GetGlobalStartAddressFromCodeTemplate(undefined, owner); | 483 GetGlobalStartAddressFromCodeTemplate(undefined, owner); | 
| 621 | 484 | 
| 485 // TODO(titzer): reset the function tables as well. | |
| 486 | |
| 622 if (old_mem_size > 0) { | 487 if (old_mem_size > 0) { | 
| 623 CHECK_NE(mem_start, undefined); | 488 CHECK_NE(mem_start, undefined); | 
| 624 old_mem_address = | 489 old_mem_address = | 
| 625 static_cast<Address>(JSArrayBuffer::cast(mem_start)->backing_store()); | 490 static_cast<Address>(JSArrayBuffer::cast(mem_start)->backing_store()); | 
| 626 } | 491 } | 
| 627 int mode_mask = RelocInfo::ModeMask(RelocInfo::WASM_MEMORY_REFERENCE) | | 492 int mode_mask = RelocInfo::ModeMask(RelocInfo::WASM_MEMORY_REFERENCE) | | 
| 628 RelocInfo::ModeMask(RelocInfo::WASM_MEMORY_SIZE_REFERENCE) | | 493 RelocInfo::ModeMask(RelocInfo::WASM_MEMORY_SIZE_REFERENCE) | | 
| 629 RelocInfo::ModeMask(RelocInfo::WASM_GLOBAL_REFERENCE); | 494 RelocInfo::ModeMask(RelocInfo::WASM_GLOBAL_REFERENCE); | 
| 630 | 495 | 
| 631 Object* fct_obj = compiled_module->ptr_to_code_table(); | 496 Object* fct_obj = compiled_module->ptr_to_code_table(); | 
| (...skipping 15 matching lines...) Expand all Loading... | |
| 647 it.rinfo()->update_wasm_global_reference(globals_start, nullptr); | 512 it.rinfo()->update_wasm_global_reference(globals_start, nullptr); | 
| 648 changed = true; | 513 changed = true; | 
| 649 } | 514 } | 
| 650 } | 515 } | 
| 651 if (changed) { | 516 if (changed) { | 
| 652 Assembler::FlushICache(isolate, code->instruction_start(), | 517 Assembler::FlushICache(isolate, code->instruction_start(), | 
| 653 code->instruction_size()); | 518 code->instruction_size()); | 
| 654 } | 519 } | 
| 655 } | 520 } | 
| 656 } | 521 } | 
| 657 compiled_module->reset_heap(); | 522 compiled_module->reset_memory(); | 
| 658 } | 523 } | 
| 659 | 524 | 
| 660 static void InstanceFinalizer(const v8::WeakCallbackInfo<void>& data) { | 525 static void InstanceFinalizer(const v8::WeakCallbackInfo<void>& data) { | 
| 661 JSObject** p = reinterpret_cast<JSObject**>(data.GetParameter()); | 526 JSObject** p = reinterpret_cast<JSObject**>(data.GetParameter()); | 
| 662 JSObject* owner = *p; | 527 JSObject* owner = *p; | 
| 663 WasmCompiledModule* compiled_module = GetCompiledModule(owner); | 528 WasmCompiledModule* compiled_module = GetCompiledModule(owner); | 
| 664 TRACE("Finalizing %d {\n", compiled_module->instance_id()); | 529 TRACE("Finalizing %d {\n", compiled_module->instance_id()); | 
| 665 Isolate* isolate = reinterpret_cast<Isolate*>(data.GetIsolate()); | 530 Isolate* isolate = reinterpret_cast<Isolate*>(data.GetIsolate()); | 
| 666 DCHECK(compiled_module->has_weak_module_object()); | 531 DCHECK(compiled_module->has_weak_wasm_module()); | 
| 667 WeakCell* weak_module_obj = compiled_module->ptr_to_weak_module_object(); | 532 WeakCell* weak_wasm_module = compiled_module->ptr_to_weak_wasm_module(); | 
| 668 | 533 | 
| 669 // weak_module_obj may have been cleared, meaning the module object | 534 // weak_wasm_module may have been cleared, meaning the module object | 
| 670 // was GC-ed. In that case, there won't be any new instances created, | 535 // was GC-ed. In that case, there won't be any new instances created, | 
| 671 // and we don't need to maintain the links between instances. | 536 // and we don't need to maintain the links between instances. | 
| 672 if (!weak_module_obj->cleared()) { | 537 if (!weak_wasm_module->cleared()) { | 
| 673 JSObject* module_obj = JSObject::cast(weak_module_obj->value()); | 538 JSObject* wasm_module = JSObject::cast(weak_wasm_module->value()); | 
| 674 WasmCompiledModule* current_template = | 539 WasmCompiledModule* current_template = | 
| 675 WasmCompiledModule::cast(module_obj->GetInternalField(0)); | 540 WasmCompiledModule::cast(wasm_module->GetInternalField(0)); | 
| 676 | 541 | 
| 677 TRACE("chain before {\n"); | 542 TRACE("chain before {\n"); | 
| 678 TRACE_CHAIN(current_template); | 543 TRACE_CHAIN(current_template); | 
| 679 TRACE("}\n"); | 544 TRACE("}\n"); | 
| 680 | 545 | 
| 681 DCHECK(!current_template->has_weak_prev_instance()); | 546 DCHECK(!current_template->has_weak_prev_instance()); | 
| 682 WeakCell* next = compiled_module->ptr_to_weak_next_instance(); | 547 WeakCell* next = compiled_module->ptr_to_weak_next_instance(); | 
| 683 WeakCell* prev = compiled_module->ptr_to_weak_prev_instance(); | 548 WeakCell* prev = compiled_module->ptr_to_weak_prev_instance(); | 
| 684 | 549 | 
| 685 if (current_template == compiled_module) { | 550 if (current_template == compiled_module) { | 
| 686 if (next == nullptr) { | 551 if (next == nullptr) { | 
| 687 ResetCompiledModule(isolate, owner, compiled_module); | 552 ResetCompiledModule(isolate, owner, compiled_module); | 
| 688 } else { | 553 } else { | 
| 689 DCHECK(next->value()->IsFixedArray()); | 554 DCHECK(next->value()->IsFixedArray()); | 
| 690 module_obj->SetInternalField(0, next->value()); | 555 wasm_module->SetInternalField(0, next->value()); | 
| 691 DCHECK_NULL(prev); | 556 DCHECK_NULL(prev); | 
| 692 WasmCompiledModule::cast(next->value())->reset_weak_prev_instance(); | 557 WasmCompiledModule::cast(next->value())->reset_weak_prev_instance(); | 
| 693 } | 558 } | 
| 694 } else { | 559 } else { | 
| 695 DCHECK(!(prev == nullptr && next == nullptr)); | 560 DCHECK(!(prev == nullptr && next == nullptr)); | 
| 696 // the only reason prev or next would be cleared is if the | 561 // the only reason prev or next would be cleared is if the | 
| 697 // respective objects got collected, but if that happened, | 562 // respective objects got collected, but if that happened, | 
| 698 // we would have relinked the list. | 563 // we would have relinked the list. | 
| 699 if (prev != nullptr) { | 564 if (prev != nullptr) { | 
| 700 DCHECK(!prev->cleared()); | 565 DCHECK(!prev->cleared()); | 
| 701 if (next == nullptr) { | 566 if (next == nullptr) { | 
| 702 WasmCompiledModule::cast(prev->value())->reset_weak_next_instance(); | 567 WasmCompiledModule::cast(prev->value())->reset_weak_next_instance(); | 
| 703 } else { | 568 } else { | 
| 704 WasmCompiledModule::cast(prev->value()) | 569 WasmCompiledModule::cast(prev->value()) | 
| 705 ->set_ptr_to_weak_next_instance(next); | 570 ->set_ptr_to_weak_next_instance(next); | 
| 706 } | 571 } | 
| 707 } | 572 } | 
| 708 if (next != nullptr) { | 573 if (next != nullptr) { | 
| 709 DCHECK(!next->cleared()); | 574 DCHECK(!next->cleared()); | 
| 710 if (prev == nullptr) { | 575 if (prev == nullptr) { | 
| 711 WasmCompiledModule::cast(next->value())->reset_weak_prev_instance(); | 576 WasmCompiledModule::cast(next->value())->reset_weak_prev_instance(); | 
| 712 } else { | 577 } else { | 
| 713 WasmCompiledModule::cast(next->value()) | 578 WasmCompiledModule::cast(next->value()) | 
| 714 ->set_ptr_to_weak_prev_instance(prev); | 579 ->set_ptr_to_weak_prev_instance(prev); | 
| 715 } | 580 } | 
| 716 } | 581 } | 
| 717 } | 582 } | 
| 718 TRACE("chain after {\n"); | 583 TRACE("chain after {\n"); | 
| 719 TRACE_CHAIN(WasmCompiledModule::cast(module_obj->GetInternalField(0))); | 584 TRACE_CHAIN(WasmCompiledModule::cast(wasm_module->GetInternalField(0))); | 
| 720 TRACE("}\n"); | 585 TRACE("}\n"); | 
| 721 } | 586 } | 
| 722 compiled_module->reset_weak_owning_instance(); | 587 compiled_module->reset_weak_owning_instance(); | 
| 723 GlobalHandles::Destroy(reinterpret_cast<Object**>(p)); | 588 GlobalHandles::Destroy(reinterpret_cast<Object**>(p)); | 
| 724 TRACE("}\n"); | 589 TRACE("}\n"); | 
| 725 } | 590 } | 
| 726 | 591 | 
| 727 Handle<FixedArray> SetupIndirectFunctionTable( | |
| 728 Isolate* isolate, Handle<FixedArray> wasm_functions, | |
| 729 Handle<FixedArray> indirect_table_template, | |
| 730 Handle<FixedArray> tables_to_replace) { | |
| 731 Factory* factory = isolate->factory(); | |
| 732 Handle<FixedArray> cloned_indirect_tables = | |
| 733 factory->CopyFixedArray(indirect_table_template); | |
| 734 for (int i = 0; i < cloned_indirect_tables->length(); ++i) { | |
| 735 Handle<FixedArray> orig_metadata = | |
| 736 cloned_indirect_tables->GetValueChecked<FixedArray>(isolate, i); | |
| 737 Handle<FixedArray> cloned_metadata = factory->CopyFixedArray(orig_metadata); | |
| 738 cloned_indirect_tables->set(i, *cloned_metadata); | |
| 739 | |
| 740 Handle<FixedArray> orig_table = | |
| 741 cloned_metadata->GetValueChecked<FixedArray>(isolate, kTable); | |
| 742 Handle<FixedArray> cloned_table = factory->CopyFixedArray(orig_table); | |
| 743 cloned_metadata->set(kTable, *cloned_table); | |
| 744 // Patch the cloned code to refer to the cloned kTable. | |
| 745 Handle<FixedArray> table_to_replace = | |
| 746 tables_to_replace->GetValueChecked<FixedArray>(isolate, i) | |
| 747 ->GetValueChecked<FixedArray>(isolate, kTable); | |
| 748 for (int fct_index = 0; fct_index < wasm_functions->length(); ++fct_index) { | |
| 749 Handle<Code> wasm_function = | |
| 750 wasm_functions->GetValueChecked<Code>(isolate, fct_index); | |
| 751 PatchFunctionTable(wasm_function, table_to_replace, cloned_table); | |
| 752 } | |
| 753 } | |
| 754 return cloned_indirect_tables; | |
| 755 } | |
| 756 | |
| 757 } // namespace | 592 } // namespace | 
| 758 | 593 | 
| 759 const char* wasm::SectionName(WasmSectionCode code) { | 594 const char* wasm::SectionName(WasmSectionCode code) { | 
| 760 switch (code) { | 595 switch (code) { | 
| 761 case kUnknownSectionCode: | 596 case kUnknownSectionCode: | 
| 762 return "Unknown"; | 597 return "Unknown"; | 
| 763 case kTypeSectionCode: | 598 case kTypeSectionCode: | 
| 764 return "Type"; | 599 return "Type"; | 
| 765 case kImportSectionCode: | 600 case kImportSectionCode: | 
| 766 return "Import"; | 601 return "Import"; | 
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 817 } else { | 652 } else { | 
| 818 os << "+" << pair.function_->func_index; | 653 os << "+" << pair.function_->func_index; | 
| 819 } | 654 } | 
| 820 } else { | 655 } else { | 
| 821 os << "?"; | 656 os << "?"; | 
| 822 } | 657 } | 
| 823 return os; | 658 return os; | 
| 824 } | 659 } | 
| 825 | 660 | 
| 826 Handle<JSFunction> wasm::WrapExportCodeAsJSFunction( | 661 Handle<JSFunction> wasm::WrapExportCodeAsJSFunction( | 
| 827 Isolate* isolate, Handle<Code> export_code, Handle<String> name, int arity, | 662 Isolate* isolate, Handle<Code> export_code, Handle<String> name, | 
| 828 MaybeHandle<ByteArray> maybe_signature, Handle<JSObject> module_instance) { | 663 FunctionSig* sig, Handle<JSObject> module_instance) { | 
| 829 Handle<SharedFunctionInfo> shared = | 664 Handle<SharedFunctionInfo> shared = | 
| 830 isolate->factory()->NewSharedFunctionInfo(name, export_code, false); | 665 isolate->factory()->NewSharedFunctionInfo(name, export_code, false); | 
| 666 int arity = static_cast<int>(sig->parameter_count()); | |
| 831 shared->set_length(arity); | 667 shared->set_length(arity); | 
| 832 shared->set_internal_formal_parameter_count(arity); | 668 shared->set_internal_formal_parameter_count(arity); | 
| 833 Handle<JSFunction> function = isolate->factory()->NewFunction( | 669 Handle<JSFunction> function = isolate->factory()->NewFunction( | 
| 834 isolate->wasm_function_map(), name, export_code); | 670 isolate->wasm_function_map(), name, export_code); | 
| 835 function->set_shared(*shared); | 671 function->set_shared(*shared); | 
| 836 | 672 | 
| 673 // TODO(titzer): embed the function index and get the signature from | |
| 674 // the underlying WasmModuleWrapper. | |
| 837 function->SetInternalField(kInternalModuleInstance, *module_instance); | 675 function->SetInternalField(kInternalModuleInstance, *module_instance); | 
| 838 // add another Internal Field as the function arity | 676 // add another Internal Field as the function arity | 
| 839 function->SetInternalField(kInternalArity, Smi::FromInt(arity)); | 677 function->SetInternalField(kInternalArity, Smi::FromInt(arity)); | 
| 840 // add another Internal Field as the signature of the foreign function | 678 // add another Internal Field as the signature of the foreign function | 
| 841 Handle<ByteArray> signature; | 679 int size = static_cast<int>(sig->return_count() + sig->parameter_count()); | 
| 842 if (maybe_signature.ToHandle(&signature)) { | 680 Handle<ByteArray> signature = isolate->factory()->NewByteArray(size); | 
| 843 function->SetInternalField(kInternalSignature, *signature); | 681 // TODO(titzer): don't use raw_data() from FunctionSig. | 
| 844 } | 682 signature->copy_in(0, reinterpret_cast<const byte*>(sig->raw_data()), size); | 
| 683 function->SetInternalField(kInternalSignature, *signature); | |
| 845 return function; | 684 return function; | 
| 846 } | 685 } | 
| 847 | 686 | 
| 848 Object* wasm::GetOwningWasmInstance(Code* code) { | 687 Object* wasm::GetOwningWasmInstance(Code* code) { | 
| 849 DCHECK(code->kind() == Code::WASM_FUNCTION); | 688 DCHECK(code->kind() == Code::WASM_FUNCTION); | 
| 850 DisallowHeapAllocation no_gc; | 689 DisallowHeapAllocation no_gc; | 
| 851 FixedArray* deopt_data = code->deoptimization_data(); | 690 FixedArray* deopt_data = code->deoptimization_data(); | 
| 852 DCHECK_NOT_NULL(deopt_data); | 691 DCHECK_NOT_NULL(deopt_data); | 
| 853 DCHECK(deopt_data->length() == 2); | 692 DCHECK(deopt_data->length() == 2); | 
| 854 Object* weak_link = deopt_data->get(0); | 693 Object* weak_link = deopt_data->get(0); | 
| 855 if (!weak_link->IsWeakCell()) return nullptr; | 694 if (!weak_link->IsWeakCell()) return nullptr; | 
| 856 WeakCell* cell = WeakCell::cast(weak_link); | 695 WeakCell* cell = WeakCell::cast(weak_link); | 
| 857 return cell->value(); | 696 return cell->value(); | 
| 858 } | 697 } | 
| 859 | 698 | 
| 860 int wasm::GetNumImportedFunctions(Handle<JSObject> wasm_object) { | 699 WasmModule* CppModule(Handle<JSObject> wasm_module) { | 
| 
 
Mircea Trofin
2016/10/15 17:38:40
GetCppModule? (as opposed to Create)
 
 | |
| 861 // TODO(wasm): Cache this number if it ever becomes a performance problem. | 700 DCHECK(IsWasmModule(*wasm_module)); | 
| 862 DCHECK(IsWasmObject(*wasm_object)); | 701 return reinterpret_cast<WasmModuleWrapper*>( | 
| 863 WasmCompiledModule* compiled_module = GetCompiledModule(*wasm_object); | 702 *GetCompiledModule(*wasm_module)->module_wrapper()) | 
| 864 Handle<FixedArray> imports = | 703 ->get(); | 
| 865 WasmCompiledModule::cast(compiled_module)->imports(); | |
| 866 int num_imports = imports->length(); | |
| 867 int num_imported_functions = 0; | |
| 868 for (int i = 0; i < num_imports; ++i) { | |
| 869 FixedArray* encoded_import = FixedArray::cast(imports->get(i)); | |
| 870 int kind = Smi::cast(encoded_import->get(kImportKind))->value(); | |
| 871 if (kind == kExternalFunction) ++num_imported_functions; | |
| 872 } | |
| 873 return num_imported_functions; | |
| 874 } | 704 } | 
| 875 | 705 | 
| 876 WasmModule::WasmModule(byte* module_start) | 706 int wasm::GetNumImportedFunctions(Handle<JSObject> wasm_module) { | 
| 877 : module_start(module_start), | 707 return static_cast<int>(CppModule(wasm_module)->num_imported_functions); | 
| 878 module_end(nullptr), | 708 } | 
| 879 min_mem_pages(0), | 709 | 
| 880 max_mem_pages(0), | 710 WasmModule::WasmModule(Zone* owned, const byte* module_start) | 
| 881 mem_export(false), | 711 : owned_zone(owned), | 
| 882 start_function_index(-1), | 712 module_start(module_start), | 
| 883 origin(kWasmOrigin), | |
| 884 globals_size(0), | |
| 885 num_imported_functions(0), | |
| 886 num_declared_functions(0), | |
| 887 num_exported_functions(0), | |
| 888 pending_tasks(new base::Semaphore(0)) {} | 713 pending_tasks(new base::Semaphore(0)) {} | 
| 889 | 714 | 
| 890 namespace { | |
| 891 | |
| 892 void EncodeInit(const WasmModule* module, Factory* factory, | |
| 893 Handle<FixedArray> entry, int kind_index, int value_index, | |
| 894 const WasmInitExpr& expr) { | |
| 895 entry->set(kind_index, Smi::kZero); | |
| 896 | |
| 897 Handle<Object> value; | |
| 898 switch (expr.kind) { | |
| 899 case WasmInitExpr::kGlobalIndex: { | |
| 900 TRACE(" kind = 1, global index %u\n", expr.val.global_index); | |
| 901 entry->set(kind_index, Smi::FromInt(1)); | |
| 902 uint32_t offset = module->globals[expr.val.global_index].offset; | |
| 903 entry->set(value_index, Smi::FromInt(offset)); | |
| 904 return; | |
| 905 } | |
| 906 case WasmInitExpr::kI32Const: | |
| 907 TRACE(" kind = 0, i32 = %d\n", expr.val.i32_const); | |
| 908 value = factory->NewNumber(expr.val.i32_const); | |
| 909 break; | |
| 910 case WasmInitExpr::kI64Const: | |
| 911 // TODO(titzer): implement initializers for i64 globals. | |
| 912 UNREACHABLE(); | |
| 913 break; | |
| 914 case WasmInitExpr::kF32Const: | |
| 915 TRACE(" kind = 0, f32 = %f\n", expr.val.f32_const); | |
| 916 value = factory->NewNumber(expr.val.f32_const); | |
| 917 break; | |
| 918 case WasmInitExpr::kF64Const: | |
| 919 TRACE(" kind = 0, f64 = %lf\n", expr.val.f64_const); | |
| 920 value = factory->NewNumber(expr.val.f64_const); | |
| 921 break; | |
| 922 default: | |
| 923 UNREACHABLE(); | |
| 924 } | |
| 925 entry->set(value_index, *value); | |
| 926 } | |
| 927 | |
| 928 } // namespace | |
| 929 | |
| 930 MaybeHandle<WasmCompiledModule> WasmModule::CompileFunctions( | 715 MaybeHandle<WasmCompiledModule> WasmModule::CompileFunctions( | 
| 931 Isolate* isolate, ErrorThrower* thrower) const { | 716 Isolate* isolate, Handle<WasmModuleWrapper> module_wrapper, | 
| 717 ErrorThrower* thrower) const { | |
| 932 Factory* factory = isolate->factory(); | 718 Factory* factory = isolate->factory(); | 
| 933 | 719 | 
| 934 MaybeHandle<WasmCompiledModule> nothing; | 720 MaybeHandle<WasmCompiledModule> nothing; | 
| 935 | 721 | 
| 936 WasmInstance temp_instance(this); | 722 WasmInstance temp_instance(this); | 
| 937 temp_instance.context = isolate->native_context(); | 723 temp_instance.context = isolate->native_context(); | 
| 938 temp_instance.mem_size = GetMinModuleMemSize(this); | 724 temp_instance.mem_size = GetMinModuleMemSize(this); | 
| 939 temp_instance.mem_start = nullptr; | 725 temp_instance.mem_start = nullptr; | 
| 940 temp_instance.globals_start = nullptr; | 726 temp_instance.globals_start = nullptr; | 
| 941 | 727 | 
| 942 MaybeHandle<FixedArray> indirect_table = | 728 // Initialize the indirect tables with placeholders. | 
| 943 function_tables.size() | 729 Handle<FixedArray> function_tables; | 
| 
 
Mircea Trofin
2016/10/15 17:38:40
I thought we're supposed to use MaybeHandle whenev
 
 | |
| 944 ? factory->NewFixedArray(static_cast<int>(function_tables.size()), | 730 int function_table_count = static_cast<int>(this->function_tables.size()); | 
| 945 TENURED) | 731 if (function_table_count > 0) { | 
| 946 : MaybeHandle<FixedArray>(); | 732 function_tables = factory->NewFixedArray(function_table_count); | 
| 947 for (uint32_t i = 0; i < function_tables.size(); ++i) { | 733 for (int i = 0; i < function_table_count; ++i) { | 
| 948 Handle<FixedArray> values = wasm::BuildFunctionTable(isolate, i, this); | 734 temp_instance.function_tables[i] = factory->NewFixedArray(0); | 
| 949 temp_instance.function_tables[i] = values; | 735 function_tables->set(i, *temp_instance.function_tables[i]); | 
| 950 | 736 } | 
| 951 Handle<FixedArray> metadata = isolate->factory()->NewFixedArray( | |
| 952 kWasmIndirectFunctionTableDataSize, TENURED); | |
| 953 metadata->set(kSize, Smi::FromInt(function_tables[i].size)); | |
| 954 metadata->set(kTable, *values); | |
| 955 indirect_table.ToHandleChecked()->set(i, *metadata); | |
| 956 } | 737 } | 
| 957 | 738 | 
| 958 HistogramTimerScope wasm_compile_module_time_scope( | 739 HistogramTimerScope wasm_compile_module_time_scope( | 
| 959 isolate->counters()->wasm_compile_module_time()); | 740 isolate->counters()->wasm_compile_module_time()); | 
| 960 | 741 | 
| 961 ModuleEnv module_env; | 742 ModuleEnv module_env; | 
| 962 module_env.module = this; | 743 module_env.module = this; | 
| 963 module_env.instance = &temp_instance; | 744 module_env.instance = &temp_instance; | 
| 964 module_env.origin = origin; | 745 module_env.origin = origin; | 
| 965 | 746 | 
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1016 Assembler::FlushICache(isolate, code->instruction_start(), | 797 Assembler::FlushICache(isolate, code->instruction_start(), | 
| 1017 code->instruction_size()); | 798 code->instruction_size()); | 
| 1018 } | 799 } | 
| 1019 } | 800 } | 
| 1020 | 801 | 
| 1021 // Create the compiled module object, and populate with compiled functions | 802 // Create the compiled module object, and populate with compiled functions | 
| 1022 // and information needed at instantiation time. This object needs to be | 803 // and information needed at instantiation time. This object needs to be | 
| 1023 // serializable. Instantiation may occur off a deserialized version of this | 804 // serializable. Instantiation may occur off a deserialized version of this | 
| 1024 // object. | 805 // object. | 
| 1025 Handle<WasmCompiledModule> ret = | 806 Handle<WasmCompiledModule> ret = | 
| 1026 WasmCompiledModule::New(isolate, min_mem_pages, globals_size, origin); | 807 WasmCompiledModule::New(isolate, module_wrapper); | 
| 1027 ret->set_code_table(code_table); | 808 ret->set_code_table(code_table); | 
| 1028 if (!indirect_table.is_null()) { | 809 if (function_table_count > 0) { | 
| 1029 ret->set_indirect_function_tables(indirect_table.ToHandleChecked()); | 810 ret->set_function_tables(function_tables); | 
| 1030 } | 811 } | 
| 1031 | 812 | 
| 1032 // Create and set import data. | 813 // Compile JS->WASM wrappers for exported functions. | 
| 1033 Handle<FixedArray> imports = EncodeImports(factory, this); | 814 int func_index = 0; | 
| 1034 ret->set_imports(imports); | 815 for (auto exp : export_table) { | 
| 
 
Mircea Trofin
2016/10/15 17:38:40
I know auto is allowed for iterators, but since we
 
 | |
| 1035 | 816 if (exp.kind != kExternalFunction) continue; | 
| 1036 // Create and set export data. | 817 Handle<Code> wasm_code = | 
| 1037 int export_size = static_cast<int>(export_table.size()); | 818 code_table->GetValueChecked<Code>(isolate, exp.index); | 
| 1038 if (export_size > 0) { | 819 Handle<Code> wrapper_code = compiler::CompileJSToWasmWrapper( | 
| 1039 Handle<FixedArray> exports = factory->NewFixedArray(export_size, TENURED); | 820 isolate, &module_env, wasm_code, exp.index); | 
| 1040 int index = 0; | 821 int export_index = static_cast<int>(functions.size() + func_index); | 
| 1041 int func_index = 0; | 822 code_table->set(export_index, *wrapper_code); | 
| 1042 | 823 func_index++; | 
| 
 
Mircea Trofin
2016/10/15 17:38:40
++func_index;
 
 | |
| 1043 for (const WasmExport& exp : export_table) { | |
| 1044 if (thrower->error()) return nothing; | |
| 1045 Handle<FixedArray> encoded_export = | |
| 1046 factory->NewFixedArray(kWasmExportDataSize, TENURED); | |
| 1047 WasmName str = GetName(exp.name_offset, exp.name_length); | |
| 1048 Handle<String> name = factory->InternalizeUtf8String(str); | |
| 1049 encoded_export->set(kExportKind, Smi::FromInt(exp.kind)); | |
| 1050 encoded_export->set(kExportName, *name); | |
| 1051 encoded_export->set(kExportIndex, | |
| 1052 Smi::FromInt(static_cast<int>(exp.index))); | |
| 1053 exports->set(index, *encoded_export); | |
| 1054 | |
| 1055 switch (exp.kind) { | |
| 1056 case kExternalFunction: { | |
| 1057 // Copy the signature and arity. | |
| 1058 FunctionSig* funcSig = functions[exp.index].sig; | |
| 1059 Handle<ByteArray> exportedSig = factory->NewByteArray( | |
| 1060 static_cast<int>(funcSig->parameter_count() + | |
| 1061 funcSig->return_count()), | |
| 1062 TENURED); | |
| 1063 exportedSig->copy_in( | |
| 1064 0, reinterpret_cast<const byte*>(funcSig->raw_data()), | |
| 1065 exportedSig->length()); | |
| 1066 encoded_export->set(kExportedSignature, *exportedSig); | |
| 1067 encoded_export->set( | |
| 1068 kExportArity, | |
| 1069 Smi::FromInt(static_cast<int>(funcSig->parameter_count()))); | |
| 1070 | |
| 1071 // Compile a wrapper for an exported function. | |
| 1072 Handle<Code> code = | |
| 1073 code_table->GetValueChecked<Code>(isolate, exp.index); | |
| 1074 Handle<Code> export_code = compiler::CompileJSToWasmWrapper( | |
| 1075 isolate, &module_env, code, exp.index); | |
| 1076 int code_table_index = | |
| 1077 static_cast<int>(functions.size() + func_index); | |
| 1078 code_table->set(code_table_index, *export_code); | |
| 1079 encoded_export->set(kExportIndex, Smi::FromInt(code_table_index)); | |
| 1080 ++func_index; | |
| 1081 } | |
| 1082 case kExternalTable: | |
| 1083 // Nothing special about exported tables. | |
| 1084 break; | |
| 1085 case kExternalMemory: | |
| 1086 // Nothing special about exported tables. | |
| 1087 break; | |
| 1088 case kExternalGlobal: { | |
| 1089 // Encode the global type and the global offset. | |
| 1090 const WasmGlobal& global = globals[exp.index]; | |
| 1091 encoded_export->set( | |
| 1092 kExportGlobalType, | |
| 1093 Smi::FromInt(WasmOpcodes::LocalTypeCodeFor(global.type))); | |
| 1094 encoded_export->set(kExportIndex, Smi::FromInt(global.offset)); | |
| 1095 break; | |
| 1096 } | |
| 1097 } | |
| 1098 ++index; | |
| 1099 } | |
| 1100 ret->set_exports(exports); | |
| 1101 } | |
| 1102 | |
| 1103 // Create and set init data. | |
| 1104 int init_size = static_cast<int>(globals.size()); | |
| 1105 if (init_size > 0) { | |
| 1106 Handle<FixedArray> inits = factory->NewFixedArray(init_size, TENURED); | |
| 1107 int index = 0; | |
| 1108 for (const WasmGlobal& global : globals) { | |
| 1109 // Skip globals that have no initializer (e.g. imported ones). | |
| 1110 if (global.init.kind == WasmInitExpr::kNone) continue; | |
| 1111 | |
| 1112 Handle<FixedArray> encoded_init = | |
| 1113 factory->NewFixedArray(kWasmGlobalInitDataSize, TENURED); | |
| 1114 inits->set(index, *encoded_init); | |
| 1115 TRACE("init[%d].type = %s\n", index, WasmOpcodes::TypeName(global.type)); | |
| 1116 | |
| 1117 encoded_init->set( | |
| 1118 kGlobalInitType, | |
| 1119 Smi::FromInt(WasmOpcodes::LocalTypeCodeFor(global.type))); | |
| 1120 encoded_init->set(kGlobalInitIndex, Smi::FromInt(global.offset)); | |
| 1121 EncodeInit(this, factory, encoded_init, kGlobalInitKind, kGlobalInitValue, | |
| 1122 global.init); | |
| 1123 ++index; | |
| 1124 } | |
| 1125 inits->Shrink(index); | |
| 1126 ret->set_inits(inits); | |
| 1127 } | |
| 1128 | |
| 1129 // Record data for startup function. | |
| 1130 if (start_function_index >= 0) { | |
| 1131 HandleScope scope(isolate); | |
| 1132 Handle<FixedArray> startup_data = | |
| 1133 factory->NewFixedArray(kWasmExportDataSize, TENURED); | |
| 1134 startup_data->set(kExportArity, Smi::kZero); | |
| 1135 startup_data->set(kExportIndex, Smi::FromInt(start_function_index)); | |
| 1136 ret->set_startup_function(startup_data); | |
| 1137 } | 824 } | 
| 1138 | 825 | 
| 1139 // TODO(wasm): saving the module bytes for debugging is wasteful. We should | 826 // TODO(wasm): saving the module bytes for debugging is wasteful. We should | 
| 1140 // consider downloading this on-demand. | 827 // consider downloading this on-demand. | 
| 1141 { | 828 { | 
| 1142 size_t module_bytes_len = module_end - module_start; | 829 size_t module_bytes_len = module_end - module_start; | 
| 1143 DCHECK_LE(module_bytes_len, static_cast<size_t>(kMaxInt)); | 830 DCHECK_LE(module_bytes_len, static_cast<size_t>(kMaxInt)); | 
| 1144 Vector<const uint8_t> module_bytes_vec(module_start, | 831 Vector<const uint8_t> module_bytes_vec(module_start, | 
| 1145 static_cast<int>(module_bytes_len)); | 832 static_cast<int>(module_bytes_len)); | 
| 1146 Handle<String> module_bytes_string = | 833 Handle<String> module_bytes_string = | 
| 1147 factory->NewStringFromOneByte(module_bytes_vec, TENURED) | 834 factory->NewStringFromOneByte(module_bytes_vec, TENURED) | 
| 1148 .ToHandleChecked(); | 835 .ToHandleChecked(); | 
| 1149 DCHECK(module_bytes_string->IsSeqOneByteString()); | 836 DCHECK(module_bytes_string->IsSeqOneByteString()); | 
| 1150 ret->set_module_bytes(Handle<SeqOneByteString>::cast(module_bytes_string)); | 837 ret->set_module_bytes(Handle<SeqOneByteString>::cast(module_bytes_string)); | 
| 1151 } | 838 } | 
| 1152 | 839 | 
| 1153 Handle<ByteArray> function_name_table = | |
| 1154 BuildFunctionNamesTable(isolate, module_env.module); | |
| 1155 ret->set_function_names(function_name_table); | |
| 1156 if (data_segments.size() > 0) SaveDataSegmentInfo(factory, this, ret); | |
| 1157 DCHECK_EQ(ret->default_mem_size(), temp_instance.mem_size); | 840 DCHECK_EQ(ret->default_mem_size(), temp_instance.mem_size); | 
| 1158 return ret; | 841 return ret; | 
| 1159 } | 842 } | 
| 1160 | 843 | 
| 1161 // A helper class to simplify instantiating a module from a compiled module. | 844 // A helper class to simplify instantiating a module from a compiled module. | 
| 1162 // It closes over the {Isolate}, the {ErrorThrower}, the {WasmCompiledModule}, | 845 // It closes over the {Isolate}, the {ErrorThrower}, the {WasmCompiledModule}, | 
| 1163 // etc. | 846 // etc. | 
| 1164 class WasmInstanceBuilder { | 847 class WasmInstanceBuilder { | 
| 1165 public: | 848 public: | 
| 1166 WasmInstanceBuilder(Isolate* isolate, ErrorThrower* thrower, | 849 WasmInstanceBuilder(Isolate* isolate, ErrorThrower* thrower, | 
| 1167 Handle<JSObject> module_object, Handle<JSReceiver> ffi, | 850 Handle<JSObject> wasm_module, Handle<JSReceiver> ffi, | 
| 1168 Handle<JSArrayBuffer> memory) | 851 Handle<JSArrayBuffer> memory) | 
| 1169 : isolate_(isolate), | 852 : isolate_(isolate), | 
| 1170 thrower_(thrower), | 853 thrower_(thrower), | 
| 1171 module_object_(module_object), | 854 wasm_module_(wasm_module), | 
| 1172 ffi_(ffi), | 855 ffi_(ffi), | 
| 1173 memory_(memory) {} | 856 memory_(memory) {} | 
| 1174 | 857 | 
| 1175 // Build an instance, in all of its glory. | 858 // Build an instance, in all of its glory. | 
| 1176 MaybeHandle<JSObject> Build() { | 859 MaybeHandle<JSObject> Build() { | 
| 1177 MaybeHandle<JSObject> nothing; | 860 MaybeHandle<JSObject> nothing; | 
| 1178 HistogramTimerScope wasm_instantiate_module_time_scope( | 861 HistogramTimerScope wasm_instantiate_module_time_scope( | 
| 1179 isolate_->counters()->wasm_instantiate_module_time()); | 862 isolate_->counters()->wasm_instantiate_module_time()); | 
| 1180 Factory* factory = isolate_->factory(); | 863 Factory* factory = isolate_->factory(); | 
| 1181 | 864 | 
| 1182 //-------------------------------------------------------------------------- | 865 //-------------------------------------------------------------------------- | 
| 1183 // Reuse the compiled module (if no owner), otherwise clone. | 866 // Reuse the compiled module (if no owner), otherwise clone. | 
| 1184 //-------------------------------------------------------------------------- | 867 //-------------------------------------------------------------------------- | 
| 1185 Handle<FixedArray> code_table; | 868 Handle<FixedArray> code_table; | 
| 1186 Handle<FixedArray> old_code_table; | 869 Handle<FixedArray> old_code_table; | 
| 1187 MaybeHandle<JSObject> owner; | 870 MaybeHandle<JSObject> owner; | 
| 1188 | 871 | 
| 1189 TRACE("Starting new module instantiation\n"); | 872 TRACE("Starting new module instantiation\n"); | 
| 1190 { | 873 { | 
| 1191 // Root the owner, if any, before doing any allocations, which | 874 // Root the owner, if any, before doing any allocations, which | 
| 1192 // may trigger GC. | 875 // may trigger GC. | 
| 1193 // Both owner and original template need to be in sync. Even | 876 // Both owner and original template need to be in sync. Even | 
| 1194 // after we lose the original template handle, the code | 877 // after we lose the original template handle, the code | 
| 1195 // objects we copied from it have data relative to the | 878 // objects we copied from it have data relative to the | 
| 1196 // instance - such as globals addresses. | 879 // instance - such as globals addresses. | 
| 1197 Handle<WasmCompiledModule> original; | 880 Handle<WasmCompiledModule> original; | 
| 1198 { | 881 { | 
| 1199 DisallowHeapAllocation no_gc; | 882 DisallowHeapAllocation no_gc; | 
| 1200 original = handle( | 883 original = | 
| 1201 WasmCompiledModule::cast(module_object_->GetInternalField(0))); | 884 handle(WasmCompiledModule::cast(wasm_module_->GetInternalField(0))); | 
| 1202 if (original->has_weak_owning_instance()) { | 885 if (original->has_weak_owning_instance()) { | 
| 1203 owner = | 886 owner = | 
| 1204 handle(JSObject::cast(original->weak_owning_instance()->value())); | 887 handle(JSObject::cast(original->weak_owning_instance()->value())); | 
| 1205 } | 888 } | 
| 1206 } | 889 } | 
| 1207 DCHECK(!original.is_null()); | 890 DCHECK(!original.is_null()); | 
| 1208 // Always make a new copy of the code_table, since the old_code_table | 891 // Always make a new copy of the code_table, since the old_code_table | 
| 1209 // may still have placeholders for imports. | 892 // may still have placeholders for imports. | 
| 1210 old_code_table = original->code_table(); | 893 old_code_table = original->code_table(); | 
| 1211 code_table = factory->CopyFixedArray(old_code_table); | 894 code_table = factory->CopyFixedArray(old_code_table); | 
| 1212 | 895 | 
| 1213 if (original->has_weak_owning_instance()) { | 896 if (original->has_weak_owning_instance()) { | 
| 1214 // Clone, but don't insert yet the clone in the instances chain. | 897 // Clone, but don't insert yet the clone in the instances chain. | 
| 1215 // We do that last. Since we are holding on to the owner instance, | 898 // We do that last. Since we are holding on to the owner instance, | 
| 1216 // the owner + original state used for cloning and patching | 899 // the owner + original state used for cloning and patching | 
| 1217 // won't be mutated by possible finalizer runs. | 900 // won't be mutated by possible finalizer runs. | 
| 1218 DCHECK(!owner.is_null()); | 901 DCHECK(!owner.is_null()); | 
| 1219 TRACE("Cloning from %d\n", original->instance_id()); | 902 TRACE("Cloning from %d\n", original->instance_id()); | 
| 1220 compiled_module_ = WasmCompiledModule::Clone(isolate_, original); | 903 compiled_module_ = WasmCompiledModule::Clone(isolate_, original); | 
| 904 // Avoid creating too many handles in the outer scope. | |
| 905 HandleScope scope(isolate_); | |
| 1221 | 906 | 
| 1222 // Clone the code for WASM functions and exports. | 907 // Clone the code for WASM functions and exports. | 
| 1223 for (int i = 0; i < code_table->length(); ++i) { | 908 for (int i = 0; i < code_table->length(); ++i) { | 
| 1224 Handle<Code> orig_code = | 909 Handle<Code> orig_code = | 
| 1225 code_table->GetValueChecked<Code>(isolate_, i); | 910 code_table->GetValueChecked<Code>(isolate_, i); | 
| 1226 switch (orig_code->kind()) { | 911 switch (orig_code->kind()) { | 
| 1227 case Code::WASM_TO_JS_FUNCTION: | 912 case Code::WASM_TO_JS_FUNCTION: | 
| 1228 // Imports will be overwritten with newly compiled wrappers. | 913 // Imports will be overwritten with newly compiled wrappers. | 
| 1229 break; | 914 break; | 
| 1230 case Code::JS_TO_WASM_FUNCTION: | 915 case Code::JS_TO_WASM_FUNCTION: | 
| 1231 case Code::WASM_FUNCTION: { | 916 case Code::WASM_FUNCTION: { | 
| 1232 Handle<Code> code = factory->CopyCode(orig_code); | 917 Handle<Code> code = factory->CopyCode(orig_code); | 
| 1233 code_table->set(i, *code); | 918 code_table->set(i, *code); | 
| 1234 break; | 919 break; | 
| 1235 } | 920 } | 
| 1236 default: | 921 default: | 
| 1237 UNREACHABLE(); | 922 UNREACHABLE(); | 
| 1238 } | 923 } | 
| 1239 } | 924 } | 
| 1240 RecordStats(isolate_, code_table); | 925 RecordStats(isolate_, code_table); | 
| 1241 } else { | 926 } else { | 
| 1242 // There was no owner, so we can reuse the original. | 927 // There was no owner, so we can reuse the original. | 
| 1243 compiled_module_ = original; | 928 compiled_module_ = original; | 
| 1244 TRACE("Reusing existing instance %d\n", | 929 TRACE("Reusing existing instance %d\n", | 
| 1245 compiled_module_->instance_id()); | 930 compiled_module_->instance_id()); | 
| 1246 } | 931 } | 
| 1247 compiled_module_->set_code_table(code_table); | 932 compiled_module_->set_code_table(code_table); | 
| 1248 } | 933 } | 
| 934 module_ = reinterpret_cast<WasmModuleWrapper*>( | |
| 935 *compiled_module_->module_wrapper()) | |
| 936 ->get(); | |
| 1249 | 937 | 
| 1250 //-------------------------------------------------------------------------- | 938 //-------------------------------------------------------------------------- | 
| 1251 // Allocate the instance object. | 939 // Allocate the instance object. | 
| 1252 //-------------------------------------------------------------------------- | 940 //-------------------------------------------------------------------------- | 
| 1253 Handle<Map> map = factory->NewMap( | 941 Handle<Map> map = factory->NewMap( | 
| 1254 JS_OBJECT_TYPE, | 942 JS_OBJECT_TYPE, | 
| 1255 JSObject::kHeaderSize + kWasmModuleInternalFieldCount * kPointerSize); | 943 JSObject::kHeaderSize + kWasmInstanceInternalFieldCount * kPointerSize); | 
| 1256 Handle<JSObject> instance = factory->NewJSObjectFromMap(map, TENURED); | 944 Handle<JSObject> instance = factory->NewJSObjectFromMap(map, TENURED); | 
| 1257 instance->SetInternalField(kWasmModuleCodeTable, *code_table); | 945 instance->SetInternalField(kWasmModuleCodeTable, *code_table); | 
| 1258 instance->SetInternalField(kWasmMemObject, *factory->undefined_value()); | 946 instance->SetInternalField(kWasmMemObject, *factory->undefined_value()); | 
| 1259 | 947 | 
| 1260 //-------------------------------------------------------------------------- | 948 //-------------------------------------------------------------------------- | 
| 1261 // Set up the globals for the new instance. | 949 // Set up the globals for the new instance. | 
| 1262 //-------------------------------------------------------------------------- | 950 //-------------------------------------------------------------------------- | 
| 1263 MaybeHandle<JSArrayBuffer> old_globals; | 951 MaybeHandle<JSArrayBuffer> old_globals; | 
| 1264 MaybeHandle<JSArrayBuffer> globals; | 952 MaybeHandle<JSArrayBuffer> globals; | 
| 1265 uint32_t globals_size = compiled_module_->globals_size(); | 953 uint32_t globals_size = module_->globals_size; | 
| 1266 if (globals_size > 0) { | 954 if (globals_size > 0) { | 
| 1267 Handle<JSArrayBuffer> global_buffer = | 955 Handle<JSArrayBuffer> global_buffer = | 
| 1268 NewArrayBuffer(isolate_, globals_size); | 956 NewArrayBuffer(isolate_, globals_size); | 
| 1269 globals = global_buffer; | 957 globals = global_buffer; | 
| 1270 if (globals.is_null()) { | 958 if (globals.is_null()) { | 
| 1271 thrower_->Error("Out of memory: wasm globals"); | 959 thrower_->Error("Out of memory: wasm globals"); | 
| 1272 return nothing; | 960 return nothing; | 
| 1273 } | 961 } | 
| 1274 Address old_address = owner.is_null() | 962 Address old_address = owner.is_null() | 
| 1275 ? nullptr | 963 ? nullptr | 
| 1276 : GetGlobalStartAddressFromCodeTemplate( | 964 : GetGlobalStartAddressFromCodeTemplate( | 
| 1277 *factory->undefined_value(), | 965 *factory->undefined_value(), | 
| 1278 JSObject::cast(*owner.ToHandleChecked())); | 966 JSObject::cast(*owner.ToHandleChecked())); | 
| 1279 RelocateGlobals(instance, old_address, | 967 RelocateGlobals(code_table, old_address, | 
| 1280 static_cast<Address>(global_buffer->backing_store())); | 968 static_cast<Address>(global_buffer->backing_store())); | 
| 1281 instance->SetInternalField(kWasmGlobalsArrayBuffer, *global_buffer); | 969 instance->SetInternalField(kWasmGlobalsArrayBuffer, *global_buffer); | 
| 1282 } | 970 } | 
| 1283 | 971 | 
| 1284 //-------------------------------------------------------------------------- | 972 //-------------------------------------------------------------------------- | 
| 1285 // Process the imports for the module. | 973 // Process the imports for the module. | 
| 1286 //-------------------------------------------------------------------------- | 974 //-------------------------------------------------------------------------- | 
| 1287 int num_imported_functions = ProcessImports(globals, code_table, instance); | 975 int num_imported_functions = ProcessImports(globals, code_table, instance); | 
| 1288 if (num_imported_functions < 0) return nothing; | 976 if (num_imported_functions < 0) return nothing; | 
| 1289 | 977 | 
| 1290 //-------------------------------------------------------------------------- | 978 //-------------------------------------------------------------------------- | 
| 1291 // Process the initialization for the module's globals. | 979 // Process the initialization for the module's globals. | 
| 1292 //-------------------------------------------------------------------------- | 980 //-------------------------------------------------------------------------- | 
| 1293 ProcessInits(globals); | 981 InitGlobals(globals); | 
| 1294 | 982 | 
| 1295 //-------------------------------------------------------------------------- | 983 //-------------------------------------------------------------------------- | 
| 1296 // Set up the memory for the new instance. | 984 // Set up the memory for the new instance. | 
| 1297 //-------------------------------------------------------------------------- | 985 //-------------------------------------------------------------------------- | 
| 1298 MaybeHandle<JSArrayBuffer> old_memory; | 986 MaybeHandle<JSArrayBuffer> old_memory; | 
| 1299 // TODO(titzer): handle imported memory properly. | 987 // TODO(titzer): handle imported memory properly. | 
| 1300 | 988 | 
| 1301 uint32_t min_mem_pages = compiled_module_->min_memory_pages(); | 989 uint32_t min_mem_pages = module_->min_mem_pages; | 
| 1302 isolate_->counters()->wasm_min_mem_pages_count()->AddSample(min_mem_pages); | 990 isolate_->counters()->wasm_min_mem_pages_count()->AddSample(min_mem_pages); | 
| 1303 // TODO(wasm): re-enable counter for max_mem_pages when we use that field. | 991 // TODO(wasm): re-enable counter for max_mem_pages when we use that field. | 
| 1304 | 992 | 
| 1305 if (memory_.is_null() && min_mem_pages > 0) { | 993 if (memory_.is_null() && min_mem_pages > 0) { | 
| 1306 memory_ = AllocateMemory(min_mem_pages); | 994 memory_ = AllocateMemory(min_mem_pages); | 
| 1307 if (memory_.is_null()) return nothing; // failed to allocate memory | 995 if (memory_.is_null()) return nothing; // failed to allocate memory | 
| 1308 } | 996 } | 
| 1309 | 997 | 
| 1310 if (!memory_.is_null()) { | 998 if (!memory_.is_null()) { | 
| 1311 instance->SetInternalField(kWasmMemArrayBuffer, *memory_); | 999 instance->SetInternalField(kWasmMemArrayBuffer, *memory_); | 
| 1312 Address mem_start = static_cast<Address>(memory_->backing_store()); | 1000 Address mem_start = static_cast<Address>(memory_->backing_store()); | 
| 1313 uint32_t mem_size = | 1001 uint32_t mem_size = | 
| 1314 static_cast<uint32_t>(memory_->byte_length()->Number()); | 1002 static_cast<uint32_t>(memory_->byte_length()->Number()); | 
| 1315 LoadDataSegments(globals, mem_start, mem_size); | 1003 LoadDataSegments(globals, mem_start, mem_size); | 
| 1316 | 1004 | 
| 1317 uint32_t old_mem_size = compiled_module_->has_heap() | 1005 uint32_t old_mem_size = compiled_module_->has_memory() | 
| 1318 ? compiled_module_->mem_size() | 1006 ? compiled_module_->mem_size() | 
| 1319 : compiled_module_->default_mem_size(); | 1007 : compiled_module_->default_mem_size(); | 
| 1320 Address old_mem_start = | 1008 Address old_mem_start = | 
| 1321 compiled_module_->has_heap() | 1009 compiled_module_->has_memory() | 
| 1322 ? static_cast<Address>(compiled_module_->heap()->backing_store()) | 1010 ? static_cast<Address>( | 
| 1011 compiled_module_->memory()->backing_store()) | |
| 1323 : nullptr; | 1012 : nullptr; | 
| 1324 RelocateInstanceCode(instance, old_mem_start, mem_start, old_mem_size, | 1013 RelocateInstanceCode(code_table, old_mem_start, mem_start, old_mem_size, | 
| 1325 mem_size); | 1014 mem_size); | 
| 1326 compiled_module_->set_heap(memory_); | 1015 compiled_module_->set_memory(memory_); | 
| 1327 } | 1016 } | 
| 1328 | 1017 | 
| 1329 //-------------------------------------------------------------------------- | 1018 //-------------------------------------------------------------------------- | 
| 1330 // Set up the runtime support for the new instance. | 1019 // Set up the runtime support for the new instance. | 
| 1331 //-------------------------------------------------------------------------- | 1020 //-------------------------------------------------------------------------- | 
| 1332 Handle<WeakCell> weak_link = factory->NewWeakCell(instance); | 1021 Handle<WeakCell> weak_link = factory->NewWeakCell(instance); | 
| 1333 | 1022 | 
| 1334 for (int i = num_imported_functions + FLAG_skip_compiling_wasm_funcs; | 1023 for (int i = num_imported_functions + FLAG_skip_compiling_wasm_funcs; | 
| 1335 i < code_table->length(); ++i) { | 1024 i < code_table->length(); ++i) { | 
| 1336 Handle<Code> code = code_table->GetValueChecked<Code>(isolate_, i); | 1025 Handle<Code> code = code_table->GetValueChecked<Code>(isolate_, i); | 
| 1337 if (code->kind() == Code::WASM_FUNCTION) { | 1026 if (code->kind() == Code::WASM_FUNCTION) { | 
| 1338 Handle<FixedArray> deopt_data = factory->NewFixedArray(2, TENURED); | 1027 Handle<FixedArray> deopt_data = factory->NewFixedArray(2, TENURED); | 
| 1339 deopt_data->set(0, *weak_link); | 1028 deopt_data->set(0, *weak_link); | 
| 1340 deopt_data->set(1, Smi::FromInt(static_cast<int>(i))); | 1029 deopt_data->set(1, Smi::FromInt(static_cast<int>(i))); | 
| 1341 deopt_data->set_length(2); | 1030 deopt_data->set_length(2); | 
| 1342 code->set_deoptimization_data(*deopt_data); | 1031 code->set_deoptimization_data(*deopt_data); | 
| 1343 } | 1032 } | 
| 1344 } | 1033 } | 
| 1345 | 1034 | 
| 1346 //-------------------------------------------------------------------------- | 1035 //-------------------------------------------------------------------------- | 
| 1347 // Set up the indirect function tables for the new instance. | 1036 // Set up the indirect function tables for the new instance. | 
| 1348 //-------------------------------------------------------------------------- | 1037 //-------------------------------------------------------------------------- | 
| 1349 { | 1038 int function_table_count = | 
| 1350 std::vector<Handle<Code>> functions( | 1039 static_cast<int>(module_->function_tables.size()); | 
| 1351 static_cast<size_t>(code_table->length())); | 1040 if (function_table_count > 0) { | 
| 1352 for (int i = 0; i < code_table->length(); ++i) { | 1041 Handle<FixedArray> old_function_tables = | 
| 1353 functions[i] = code_table->GetValueChecked<Code>(isolate_, i); | 1042 compiled_module_->function_tables(); | 
| 1043 Handle<FixedArray> new_function_tables = | |
| 1044 factory->NewFixedArray(function_table_count); | |
| 1045 for (int index = 0; index < function_table_count; index++) { | |
| 1046 WasmIndirectFunctionTable& table = module_->function_tables[index]; | |
| 1047 uint32_t size = table.max_size; | |
| 1048 Handle<FixedArray> new_table = factory->NewFixedArray(size * 2); | |
| 1049 for (int i = 0; i < new_table->length(); i++) { | |
| 
 
Mircea Trofin
2016/10/15 17:38:40
++i
 
 | |
| 1050 static const int kInvalidSigIndex = -1; | |
| 1051 // Fill the table with invalid signature indexes so that uninitialized | |
| 1052 // entries will always fail the signature check. | |
| 1053 new_table->set(i, Smi::FromInt(kInvalidSigIndex)); | |
| 1054 } | |
| 1055 for (auto table_init : module_->table_inits) { | |
| 
 
Mircea Trofin
2016/10/15 17:38:40
same comment about auto as above.
 
 | |
| 1056 // TODO(titzer): proper bounds check of the initialization. | |
| 1057 uint32_t base = EvalUint32InitExpr(globals, table_init.offset); | |
| 1058 for (size_t i = 0; i < table_init.entries.size(); i++) { | |
| 
 
Mircea Trofin
2016/10/15 17:38:40
++i
 
 | |
| 1059 FunctionSig* sig = module_->functions[table_init.entries[i]].sig; | |
| 1060 int32_t sig_index = table.map.Find(sig); | |
| 1061 new_table->set(static_cast<int>(i + base), Smi::FromInt(sig_index)); | |
| 1062 new_table->set(static_cast<int>(i + base + size), | |
| 1063 code_table->get(table_init.entries[i])); | |
| 1064 } | |
| 1065 } | |
| 1066 new_function_tables->set(static_cast<int>(index), *new_table); | |
| 1354 } | 1067 } | 
| 1355 | 1068 // Patch all code that has references to the old indirect table. | 
| 1356 if (compiled_module_->has_indirect_function_tables()) { | 1069 for (int i = 0; i < code_table->length(); i++) { | 
| 
 
Mircea Trofin
2016/10/15 17:38:40
++i
 
 | |
| 1357 Handle<FixedArray> indirect_tables_template = | 1070 if (!code_table->get(i)->IsCode()) continue; | 
| 1358 compiled_module_->indirect_function_tables(); | 1071 Handle<Code> code(Code::cast(code_table->get(i)), isolate_); | 
| 1359 Handle<FixedArray> to_replace = | 1072 for (int j = 0; j < function_table_count; j++) { | 
| 
 
Mircea Trofin
2016/10/15 17:38:41
++j
 
 | |
| 1360 owner.is_null() ? indirect_tables_template | 1073 ReplaceReferenceInCode( | 
| 1361 : handle(FixedArray::cast( | 1074 code, Handle<Object>(old_function_tables->get(j), isolate_), | 
| 1362 owner.ToHandleChecked()->GetInternalField( | 1075 Handle<Object>(new_function_tables->get(j), isolate_)); | 
| 1363 kWasmModuleFunctionTable))); | |
| 1364 Handle<FixedArray> indirect_tables = SetupIndirectFunctionTable( | |
| 1365 isolate_, code_table, indirect_tables_template, to_replace); | |
| 1366 for (int i = 0; i < indirect_tables->length(); ++i) { | |
| 1367 Handle<FixedArray> metadata = | |
| 1368 indirect_tables->GetValueChecked<FixedArray>(isolate_, i); | |
| 1369 uint32_t size = Smi::cast(metadata->get(kSize))->value(); | |
| 1370 Handle<FixedArray> table = | |
| 1371 metadata->GetValueChecked<FixedArray>(isolate_, kTable); | |
| 1372 PopulateFunctionTable(table, size, &functions); | |
| 1373 } | 1076 } | 
| 1374 instance->SetInternalField(kWasmModuleFunctionTable, *indirect_tables); | |
| 1375 } | 1077 } | 
| 1078 compiled_module_->set_function_tables(new_function_tables); | |
| 1376 } | 1079 } | 
| 1377 | 1080 | 
| 1378 //-------------------------------------------------------------------------- | 1081 //-------------------------------------------------------------------------- | 
| 1379 // Set up the exports object for the new instance. | 1082 // Set up the exports object for the new instance. | 
| 1380 //-------------------------------------------------------------------------- | 1083 //-------------------------------------------------------------------------- | 
| 1381 ProcessExports(globals, code_table, instance); | 1084 ProcessExports(globals, code_table, instance); | 
| 1382 | 1085 | 
| 1383 if (num_imported_functions > 0 || !owner.is_null()) { | 1086 if (num_imported_functions > 0 || !owner.is_null()) { | 
| 1384 // If the code was cloned, or new imports were compiled, patch. | 1087 // If the code was cloned, or new imports were compiled, patch. | 
| 1385 PatchDirectCalls(old_code_table, code_table, num_imported_functions); | 1088 PatchDirectCalls(old_code_table, code_table, num_imported_functions); | 
| 1386 } | 1089 } | 
| 1387 | 1090 | 
| 1388 FlushICache(isolate_, code_table); | 1091 FlushICache(isolate_, code_table); | 
| 1389 | 1092 | 
| 1390 //-------------------------------------------------------------------------- | 1093 //-------------------------------------------------------------------------- | 
| 1391 // Run the start function if one was specified. | 1094 // Run the start function if one was specified. | 
| 1392 //-------------------------------------------------------------------------- | 1095 //-------------------------------------------------------------------------- | 
| 1393 if (compiled_module_->has_startup_function()) { | 1096 if (module_->start_function_index >= 0) { | 
| 1394 Handle<FixedArray> startup_data = compiled_module_->startup_function(); | |
| 1395 HandleScope scope(isolate_); | 1097 HandleScope scope(isolate_); | 
| 1396 int32_t start_index = | 1098 int32_t start_index = module_->start_function_index; | 
| 1397 startup_data->GetValueChecked<Smi>(isolate_, kExportIndex)->value(); | |
| 1398 Handle<Code> startup_code = | 1099 Handle<Code> startup_code = | 
| 1399 code_table->GetValueChecked<Code>(isolate_, start_index); | 1100 code_table->GetValueChecked<Code>(isolate_, start_index); | 
| 1400 int arity = Smi::cast(startup_data->get(kExportArity))->value(); | 1101 FunctionSig* sig = module_->functions[start_index].sig; | 
| 1401 MaybeHandle<ByteArray> startup_signature = | |
| 1402 startup_data->GetValue<ByteArray>(isolate_, kExportedSignature); | |
| 1403 Handle<JSFunction> startup_fct = WrapExportCodeAsJSFunction( | 1102 Handle<JSFunction> startup_fct = WrapExportCodeAsJSFunction( | 
| 1404 isolate_, startup_code, factory->InternalizeUtf8String("start"), | 1103 isolate_, startup_code, factory->InternalizeUtf8String("start"), sig, | 
| 1405 arity, startup_signature, instance); | 1104 instance); | 
| 1406 RecordStats(isolate_, *startup_code); | 1105 RecordStats(isolate_, *startup_code); | 
| 1407 // Call the JS function. | 1106 // Call the JS function. | 
| 1408 Handle<Object> undefined = factory->undefined_value(); | 1107 Handle<Object> undefined = factory->undefined_value(); | 
| 1409 MaybeHandle<Object> retval = | 1108 MaybeHandle<Object> retval = | 
| 1410 Execution::Call(isolate_, startup_fct, undefined, 0, nullptr); | 1109 Execution::Call(isolate_, startup_fct, undefined, 0, nullptr); | 
| 1411 | 1110 | 
| 1412 if (retval.is_null()) { | 1111 if (retval.is_null()) { | 
| 1413 thrower_->Error("WASM.instantiateModule(): start function failed"); | 1112 thrower_->Error("WASM.instantiateModule(): start function failed"); | 
| 1414 return nothing; | 1113 return nothing; | 
| 1415 } | 1114 } | 
| (...skipping 15 matching lines...) Expand all Loading... | |
| 1431 original = handle(GetCompiledModule(*owner.ToHandleChecked())); | 1130 original = handle(GetCompiledModule(*owner.ToHandleChecked())); | 
| 1432 link_to_original = factory->NewWeakCell(original.ToHandleChecked()); | 1131 link_to_original = factory->NewWeakCell(original.ToHandleChecked()); | 
| 1433 } | 1132 } | 
| 1434 // Publish the new instance to the instances chain. | 1133 // Publish the new instance to the instances chain. | 
| 1435 { | 1134 { | 
| 1436 DisallowHeapAllocation no_gc; | 1135 DisallowHeapAllocation no_gc; | 
| 1437 if (!link_to_original.is_null()) { | 1136 if (!link_to_original.is_null()) { | 
| 1438 compiled_module_->set_weak_next_instance( | 1137 compiled_module_->set_weak_next_instance( | 
| 1439 link_to_original.ToHandleChecked()); | 1138 link_to_original.ToHandleChecked()); | 
| 1440 original.ToHandleChecked()->set_weak_prev_instance(link_to_clone); | 1139 original.ToHandleChecked()->set_weak_prev_instance(link_to_clone); | 
| 1441 compiled_module_->set_weak_module_object( | 1140 compiled_module_->set_weak_wasm_module( | 
| 1442 original.ToHandleChecked()->weak_module_object()); | 1141 original.ToHandleChecked()->weak_wasm_module()); | 
| 1443 } | 1142 } | 
| 1444 module_object_->SetInternalField(0, *compiled_module_); | 1143 wasm_module_->SetInternalField(0, *compiled_module_); | 
| 1445 instance->SetInternalField(kWasmCompiledModule, *compiled_module_); | 1144 instance->SetInternalField(kWasmCompiledModule, *compiled_module_); | 
| 1446 compiled_module_->set_weak_owning_instance(link_to_owning_instance); | 1145 compiled_module_->set_weak_owning_instance(link_to_owning_instance); | 
| 1447 GlobalHandles::MakeWeak(global_handle.location(), | 1146 GlobalHandles::MakeWeak(global_handle.location(), | 
| 1448 global_handle.location(), &InstanceFinalizer, | 1147 global_handle.location(), &InstanceFinalizer, | 
| 1449 v8::WeakCallbackType::kFinalizer); | 1148 v8::WeakCallbackType::kFinalizer); | 
| 1450 } | 1149 } | 
| 1451 } | 1150 } | 
| 1452 | 1151 | 
| 1453 DCHECK(wasm::IsWasmObject(*instance)); | 1152 DCHECK(wasm::IsWasmModule(*instance)); | 
| 1454 | 1153 | 
| 1455 TRACE("Finishing instance %d\n", compiled_module_->instance_id()); | 1154 TRACE("Finishing instance %d\n", compiled_module_->instance_id()); | 
| 1456 TRACE_CHAIN(WasmCompiledModule::cast(module_object_->GetInternalField(0))); | 1155 TRACE_CHAIN(WasmCompiledModule::cast(wasm_module_->GetInternalField(0))); | 
| 1457 return instance; | 1156 return instance; | 
| 1458 } | 1157 } | 
| 1459 | 1158 | 
| 1460 private: | 1159 private: | 
| 1461 Isolate* isolate_; | 1160 Isolate* isolate_; | 
| 1161 WasmModule* module_; | |
| 
 
Mircea Trofin
2016/10/15 17:38:40
elsewhere, there was a CppModule API. Could we cal
 
 | |
| 1462 ErrorThrower* thrower_; | 1162 ErrorThrower* thrower_; | 
| 1463 Handle<JSObject> module_object_; | 1163 Handle<JSObject> wasm_module_; | 
| 1464 Handle<JSReceiver> ffi_; | 1164 Handle<JSReceiver> ffi_; | 
| 1465 Handle<JSArrayBuffer> memory_; | 1165 Handle<JSArrayBuffer> memory_; | 
| 1466 Handle<WasmCompiledModule> compiled_module_; | 1166 Handle<WasmCompiledModule> compiled_module_; | 
| 1467 | 1167 | 
| 1468 // Helper routine to print out errors with imports (FFI). | 1168 // Helper routine to print out errors with imports (FFI). | 
| 1469 MaybeHandle<JSFunction> ReportFFIError(const char* error, uint32_t index, | 1169 MaybeHandle<JSFunction> ReportFFIError(const char* error, uint32_t index, | 
| 1470 Handle<String> module_name, | 1170 Handle<String> module_name, | 
| 1471 MaybeHandle<String> function_name) { | 1171 MaybeHandle<String> function_name) { | 
| 1472 Handle<String> function_name_handle; | 1172 Handle<String> function_name_handle; | 
| 1473 if (function_name.ToHandle(&function_name_handle)) { | 1173 if (function_name.ToHandle(&function_name_handle)) { | 
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1515 import_name); | 1215 import_name); | 
| 1516 } | 1216 } | 
| 1517 } else { | 1217 } else { | 
| 1518 // No function specified. Use the "default export". | 1218 // No function specified. Use the "default export". | 
| 1519 result = module; | 1219 result = module; | 
| 1520 } | 1220 } | 
| 1521 | 1221 | 
| 1522 return result; | 1222 return result; | 
| 1523 } | 1223 } | 
| 1524 | 1224 | 
| 1225 uint32_t EvalUint32InitExpr(MaybeHandle<JSArrayBuffer> globals, | |
| 1226 WasmInitExpr& expr) { | |
| 1227 switch (expr.kind) { | |
| 1228 case WasmInitExpr::kI32Const: | |
| 1229 return expr.val.i32_const; | |
| 1230 case WasmInitExpr::kGlobalIndex: { | |
| 1231 uint32_t offset = module_->globals[expr.val.global_index].offset; | |
| 1232 return *reinterpret_cast<uint32_t*>(raw_buffer_ptr(globals, offset)); | |
| 1233 } | |
| 1234 default: | |
| 1235 UNREACHABLE(); | |
| 1236 break; | |
| 1237 } | |
| 1238 } | |
| 1239 | |
| 1525 // Load data segments into the memory. | 1240 // Load data segments into the memory. | 
| 1526 void LoadDataSegments(MaybeHandle<JSArrayBuffer> globals, Address mem_addr, | 1241 void LoadDataSegments(MaybeHandle<JSArrayBuffer> globals, Address mem_addr, | 
| 1527 size_t mem_size) { | 1242 size_t mem_size) { | 
| 1528 CHECK(compiled_module_->has_data_segments() == | 1243 Handle<SeqOneByteString> module_bytes = compiled_module_->module_bytes(); | 
| 1529 compiled_module_->has_data_segments_info()); | 1244 for (auto segment : module_->data_segments) { | 
| 1530 | 1245 uint32_t dest_offset = EvalUint32InitExpr(globals, segment.dest_addr); | 
| 1531 // If we have neither, we're done. | 1246 uint32_t source_size = segment.source_size; | 
| 1532 if (!compiled_module_->has_data_segments()) return; | 1247 if (dest_offset >= mem_size || source_size >= mem_size || | 
| 1533 | 1248 dest_offset >= (mem_size - source_size)) { | 
| 1534 Handle<ByteArray> data = compiled_module_->data_segments(); | 1249 thrower_->RangeError("data segment does not fit into memory"); | 
| 1535 Handle<FixedArray> segments = compiled_module_->data_segments_info(); | |
| 1536 | |
| 1537 uint32_t last_extraction_pos = 0; | |
| 1538 for (int i = 0; i < segments->length(); ++i) { | |
| 1539 Handle<ByteArray> segment = | |
| 1540 Handle<ByteArray>(ByteArray::cast(segments->get(i))); | |
| 1541 uint32_t dest_addr = | |
| 1542 static_cast<uint32_t>(segment->get_int(kDestAddrValue)); | |
| 1543 if (segment->get_int(kDestAddrKind) == 1) { | |
| 1544 // The destination address is the value of a global variable. | |
| 1545 dest_addr = | |
| 1546 *reinterpret_cast<uint32_t*>(raw_buffer_ptr(globals, dest_addr)); | |
| 1547 } | 1250 } | 
| 1548 | 1251 byte* dest = mem_addr + dest_offset; | 
| 1549 uint32_t source_size = | 1252 const byte* src = reinterpret_cast<const byte*>( | 
| 1550 static_cast<uint32_t>(segment->get_int(kSourceSize)); | 1253 module_bytes->GetCharsAddress() + segment.source_offset); | 
| 1551 // TODO(titzer): These should be runtime errors and not CHECKs if | 1254 memcpy(dest, src, source_size); | 
| 1552 // dest_addr is global (and therefore initialized at linktime to an | |
| 1553 // possibly-invalid value). | |
| 1554 CHECK_LT(dest_addr, mem_size); | |
| 1555 CHECK_LE(source_size, mem_size); | |
| 1556 CHECK_LE(dest_addr, mem_size - source_size); | |
| 1557 byte* addr = mem_addr + dest_addr; | |
| 1558 data->copy_out(last_extraction_pos, addr, source_size); | |
| 1559 last_extraction_pos += source_size; | |
| 1560 } | 1255 } | 
| 1561 } | 1256 } | 
| 1562 | 1257 | 
| 1563 Handle<Code> CompileImportWrapper(int index, Handle<FixedArray> data, | 1258 Handle<Code> CompileImportWrapper(int index, const WasmImport& import, | 
| 1564 Handle<JSReceiver> target, | 1259 Handle<JSReceiver> target, | 
| 1565 Handle<String> module_name, | 1260 Handle<String> module_name, | 
| 1566 MaybeHandle<String> import_name) { | 1261 MaybeHandle<String> import_name) { | 
| 1567 // TODO(mtrofin): this is an uint32_t, actually. We should rationalize | 1262 // TODO(mtrofin): this is an uint32_t, actually. We should rationalize | 
| 1568 // it when we rationalize signed/unsigned stuff. | 1263 // it when we rationalize signed/unsigned stuff. | 
| 1569 int ret_count = Smi::cast(data->get(kOutputCount))->value(); | 1264 FunctionSig* sig = module_->functions[import.index].sig; | 
| 1570 CHECK_GE(ret_count, 0); | 1265 int param_count = static_cast<int>(sig->parameter_count()); | 
| 1571 Handle<ByteArray> sig_data = | |
| 1572 data->GetValueChecked<ByteArray>(isolate_, kSignature); | |
| 1573 int sig_data_size = sig_data->length(); | |
| 1574 int param_count = sig_data_size - ret_count; | |
| 1575 CHECK(param_count >= 0); | |
| 1576 | 1266 | 
| 1577 Handle<Code> code; | 1267 Handle<Code> code; | 
| 1578 bool isMatch = false; | 1268 bool isMatch = false; | 
| 1579 Handle<Code> export_wrapper_code; | 1269 Handle<Code> export_wrapper_code; | 
| 1580 if (target->IsJSFunction()) { | 1270 if (target->IsJSFunction()) { | 
| 1581 Handle<JSFunction> func = Handle<JSFunction>::cast(target); | 1271 Handle<JSFunction> func = Handle<JSFunction>::cast(target); | 
| 1582 export_wrapper_code = handle(func->code()); | 1272 export_wrapper_code = handle(func->code()); | 
| 1583 if (export_wrapper_code->kind() == Code::JS_TO_WASM_FUNCTION) { | 1273 if (export_wrapper_code->kind() == Code::JS_TO_WASM_FUNCTION) { | 
| 1584 int exported_param_count = | 1274 int exported_param_count = | 
| 1585 Smi::cast(func->GetInternalField(kInternalArity))->value(); | 1275 Smi::cast(func->GetInternalField(kInternalArity))->value(); | 
| 1586 Handle<ByteArray> exportedSig = Handle<ByteArray>( | 1276 Handle<ByteArray> exportedSig = Handle<ByteArray>( | 
| 
 
Mircea Trofin
2016/10/15 17:38:40
do we still need this, given we now have the nativ
 
 | |
| 1587 ByteArray::cast(func->GetInternalField(kInternalSignature))); | 1277 ByteArray::cast(func->GetInternalField(kInternalSignature))); | 
| 1588 if (exported_param_count == param_count && | 1278 if (exported_param_count == param_count && | 
| 1589 exportedSig->length() == sig_data->length() && | 1279 exportedSig->length() == | 
| 1590 memcmp(exportedSig->GetDataStartAddress(), | 1280 (sig->return_count() + sig->parameter_count()) && | 
| 1591 sig_data->GetDataStartAddress(), | 1281 // TODO(titzer): do not use raw_data() of signature. | 
| 1282 memcmp(exportedSig->GetDataStartAddress(), sig->raw_data(), | |
| 1592 exportedSig->length()) == 0) { | 1283 exportedSig->length()) == 0) { | 
| 1593 isMatch = true; | 1284 isMatch = true; | 
| 1594 } | 1285 } | 
| 1595 } | 1286 } | 
| 1596 } | 1287 } | 
| 1597 if (isMatch) { | 1288 if (isMatch) { | 
| 1289 // Signature matched. Unwrap the JS->WASM wrapper and return the naked | |
| 1290 // WASM function code. | |
| 1598 int wasm_count = 0; | 1291 int wasm_count = 0; | 
| 1599 int const mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET); | 1292 int const mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET); | 
| 1600 for (RelocIterator it(*export_wrapper_code, mask); !it.done(); | 1293 for (RelocIterator it(*export_wrapper_code, mask); !it.done(); | 
| 1601 it.next()) { | 1294 it.next()) { | 
| 1602 RelocInfo* rinfo = it.rinfo(); | 1295 RelocInfo* rinfo = it.rinfo(); | 
| 1603 Address target_address = rinfo->target_address(); | 1296 Address target_address = rinfo->target_address(); | 
| 1604 Code* target = Code::GetCodeFromTargetAddress(target_address); | 1297 Code* target = Code::GetCodeFromTargetAddress(target_address); | 
| 1605 if (target->kind() == Code::WASM_FUNCTION) { | 1298 if (target->kind() == Code::WASM_FUNCTION) { | 
| 1606 ++wasm_count; | 1299 ++wasm_count; | 
| 1607 code = handle(target); | 1300 code = handle(target); | 
| 1608 } | 1301 } | 
| 1609 } | 1302 } | 
| 1610 DCHECK(wasm_count == 1); | 1303 DCHECK(wasm_count == 1); | 
| 1611 return code; | 1304 return code; | 
| 1612 } else { | 1305 } else { | 
| 1613 // Copy the signature to avoid a raw pointer into a heap object when | 1306 // Signature mismatch. Compile a new wrapper for the new signature. | 
| 1614 // GC can happen. | 1307 return compiler::CompileWasmToJSWrapper(isolate_, target, sig, index, | 
| 1615 Zone zone(isolate_->allocator()); | |
| 1616 MachineRepresentation* reps = | |
| 1617 zone.NewArray<MachineRepresentation>(sig_data_size); | |
| 1618 memcpy(reps, sig_data->GetDataStartAddress(), | |
| 1619 sizeof(MachineRepresentation) * sig_data_size); | |
| 1620 FunctionSig sig(ret_count, param_count, reps); | |
| 1621 | |
| 1622 return compiler::CompileWasmToJSWrapper(isolate_, target, &sig, index, | |
| 1623 module_name, import_name); | 1308 module_name, import_name); | 
| 1624 } | 1309 } | 
| 1625 } | 1310 } | 
| 1626 | 1311 | 
| 1627 void WriteGlobalValue(MaybeHandle<JSArrayBuffer> globals, uint32_t offset, | 1312 void WriteGlobalValue(WasmGlobal& global, MaybeHandle<JSArrayBuffer> globals, | 
| 1628 Handle<Object> value, int type) { | 1313 Handle<Object> value) { | 
| 1629 double num = 0; | 1314 double num = 0; | 
| 1630 if (value->IsSmi()) { | 1315 if (value->IsSmi()) { | 
| 1631 num = Smi::cast(*value)->value(); | 1316 num = Smi::cast(*value)->value(); | 
| 1632 } else if (value->IsHeapNumber()) { | 1317 } else if (value->IsHeapNumber()) { | 
| 1633 num = HeapNumber::cast(*value)->value(); | 1318 num = HeapNumber::cast(*value)->value(); | 
| 1634 } else { | 1319 } else { | 
| 1635 UNREACHABLE(); | 1320 UNREACHABLE(); | 
| 1636 } | 1321 } | 
| 1637 TRACE("init [globals+%u] = %lf, type = %d\n", offset, num, type); | 1322 TRACE("init [globals+%u] = %lf, type = %s\n", global.offset, num, | 
| 1638 byte* ptr = raw_buffer_ptr(globals, offset); | 1323 WasmOpcodes::TypeName(global.type)); | 
| 1639 switch (type) { | 1324 switch (global.type) { | 
| 1640 case kLocalI32: | 1325 case kAstI32: | 
| 1641 *reinterpret_cast<int32_t*>(ptr) = static_cast<int32_t>(num); | 1326 *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
 
 | |
| 1642 break; | 1327 break; | 
| 1643 case kLocalI64: | 1328 case kAstI64: | 
| 1644 // TODO(titzer): initialization of imported i64 globals. | 1329 // TODO(titzer): initialization of imported i64 globals. | 
| 1645 UNREACHABLE(); | 1330 UNREACHABLE(); | 
| 1646 break; | 1331 break; | 
| 1647 case kLocalF32: | 1332 case kAstF32: | 
| 1648 *reinterpret_cast<float*>(ptr) = static_cast<float>(num); | 1333 *GetRawGlobalPtr<float>(global, globals) = static_cast<float>(num); | 
| 1649 break; | 1334 break; | 
| 1650 case kLocalF64: | 1335 case kAstF64: | 
| 1651 *reinterpret_cast<double*>(ptr) = num; | 1336 *GetRawGlobalPtr<double>(global, globals) = static_cast<double>(num); | 
| 1652 break; | 1337 break; | 
| 1653 default: | 1338 default: | 
| 1654 UNREACHABLE(); | 1339 UNREACHABLE(); | 
| 1655 } | 1340 } | 
| 1656 } | 1341 } | 
| 1657 | 1342 | 
| 1658 // Process the imports, including functions, tables, globals, and memory, in | 1343 // Process the imports, including functions, tables, globals, and memory, in | 
| 1659 // order, loading them from the {ffi_} object. Returns the number of imported | 1344 // order, loading them from the {ffi_} object. Returns the number of imported | 
| 1660 // functions. | 1345 // functions. | 
| 1661 int ProcessImports(MaybeHandle<JSArrayBuffer> globals, | 1346 int ProcessImports(MaybeHandle<JSArrayBuffer> globals, | 
| 1662 Handle<FixedArray> code_table, Handle<JSObject> instance) { | 1347 Handle<FixedArray> code_table, Handle<JSObject> instance) { | 
| 1663 int num_imported_functions = 0; | 1348 int num_imported_functions = 0; | 
| 1664 if (!compiled_module_->has_imports()) return num_imported_functions; | 1349 for (int index = 0; index < static_cast<int>(module_->import_table.size()); | 
| 1665 | 1350 index++) { | 
| 
 
Mircea Trofin
2016/10/15 17:38:40
++index
 
 | |
| 1666 Handle<FixedArray> imports = compiled_module_->imports(); | 1351 WasmImport& import = module_->import_table[index]; | 
| 1667 for (int index = 0; index < imports->length(); ++index) { | |
| 1668 Handle<FixedArray> data = | |
| 1669 imports->GetValueChecked<FixedArray>(isolate_, index); | |
| 1670 | |
| 1671 Handle<String> module_name = | 1352 Handle<String> module_name = | 
| 1672 data->GetValueChecked<String>(isolate_, kModuleName); | 1353 ExtractStringFromModuleBytes(isolate_, compiled_module_, | 
| 
 
Mircea Trofin
2016/10/15 17:38:40
ExtractString allocates each time we call it. Shou
 
 | |
| 1673 MaybeHandle<String> function_name = | 1354 import.module_name_offset, | 
| 1674 data->GetValue<String>(isolate_, kFunctionName); | 1355 import.module_name_length) | 
| 1356 .ToHandleChecked(); | |
| 1357 Handle<String> function_name = Handle<String>::null(); | |
| 1358 if (import.field_name_length > 0) { | |
| 1359 function_name = ExtractStringFromModuleBytes(isolate_, compiled_module_, | |
| 1360 import.field_name_offset, | |
| 1361 import.field_name_length) | |
| 1362 .ToHandleChecked(); | |
| 1363 } | |
| 1675 | 1364 | 
| 1676 MaybeHandle<Object> result = | 1365 MaybeHandle<Object> result = | 
| 1677 LookupImport(index, module_name, function_name); | 1366 LookupImport(index, module_name, function_name); | 
| 1678 if (thrower_->error()) return -1; | 1367 if (thrower_->error()) return -1; | 
| 1679 | 1368 | 
| 1680 WasmExternalKind kind = static_cast<WasmExternalKind>( | 1369 switch (import.kind) { | 
| 1681 Smi::cast(data->get(kImportKind))->value()); | |
| 1682 switch (kind) { | |
| 1683 case kExternalFunction: { | 1370 case kExternalFunction: { | 
| 1684 // Function imports must be callable. | 1371 // Function imports must be callable. | 
| 1685 Handle<Object> function = result.ToHandleChecked(); | 1372 Handle<Object> function = result.ToHandleChecked(); | 
| 1686 if (!function->IsCallable()) { | 1373 if (!function->IsCallable()) { | 
| 1687 ReportFFIError("function import requires a callable", index, | 1374 ReportFFIError("function import requires a callable", index, | 
| 1688 module_name, function_name); | 1375 module_name, function_name); | 
| 1689 return -1; | 1376 return -1; | 
| 1690 } | 1377 } | 
| 1691 | 1378 | 
| 1692 Handle<Code> import_wrapper = CompileImportWrapper( | 1379 Handle<Code> import_wrapper = CompileImportWrapper( | 
| 1693 index, data, Handle<JSReceiver>::cast(function), module_name, | 1380 index, import, Handle<JSReceiver>::cast(function), module_name, | 
| 1694 function_name); | 1381 function_name); | 
| 1695 int func_index = Smi::cast(data->get(kImportIndex))->value(); | 1382 code_table->set(num_imported_functions, *import_wrapper); | 
| 1696 code_table->set(func_index, *import_wrapper); | |
| 1697 RecordStats(isolate_, *import_wrapper); | 1383 RecordStats(isolate_, *import_wrapper); | 
| 1698 num_imported_functions++; | 1384 num_imported_functions++; | 
| 1699 break; | 1385 break; | 
| 1700 } | 1386 } | 
| 1701 case kExternalTable: | 1387 case kExternalTable: | 
| 1702 // TODO(titzer): Table imports must be a WebAssembly.Table. | 1388 // TODO(titzer): Table imports must be a WebAssembly.Table. | 
| 1703 break; | 1389 break; | 
| 1704 case kExternalMemory: { | 1390 case kExternalMemory: { | 
| 1705 Handle<Object> object = result.ToHandleChecked(); | 1391 Handle<Object> object = result.ToHandleChecked(); | 
| 1706 if (!WasmJs::IsWasmMemoryObject(isolate_, object)) { | 1392 if (!WasmJs::IsWasmMemoryObject(isolate_, object)) { | 
| 1707 ReportFFIError("memory import must be a WebAssembly.Memory object", | 1393 ReportFFIError("memory import must be a WebAssembly.Memory object", | 
| 1708 index, module_name, function_name); | 1394 index, module_name, function_name); | 
| 1709 return -1; | 1395 return -1; | 
| 1710 } | 1396 } | 
| 1711 instance->SetInternalField(kWasmMemObject, *object); | 1397 instance->SetInternalField(kWasmMemObject, *object); | 
| 1712 memory_ = WasmJs::GetWasmMemoryArrayBuffer(isolate_, object); | 1398 memory_ = WasmJs::GetWasmMemoryArrayBuffer(isolate_, object); | 
| 1713 break; | 1399 break; | 
| 1714 } | 1400 } | 
| 1715 case kExternalGlobal: { | 1401 case kExternalGlobal: { | 
| 1716 // Global imports are converted to numbers and written into the | 1402 // Global imports are converted to numbers and written into the | 
| 1717 // {globals} array buffer. | 1403 // {globals} array buffer. | 
| 1718 Handle<Object> object = result.ToHandleChecked(); | 1404 Handle<Object> object = result.ToHandleChecked(); | 
| 1719 MaybeHandle<Object> number = Object::ToNumber(object); | 1405 MaybeHandle<Object> number = Object::ToNumber(object); | 
| 1720 if (number.is_null()) { | 1406 if (number.is_null()) { | 
| 1721 ReportFFIError("global import could not be converted to number", | 1407 ReportFFIError("global import could not be converted to number", | 
| 1722 index, module_name, function_name); | 1408 index, module_name, function_name); | 
| 1723 return -1; | 1409 return -1; | 
| 1724 } | 1410 } | 
| 1725 Handle<Object> val = number.ToHandleChecked(); | 1411 Handle<Object> val = number.ToHandleChecked(); | 
| 1726 int offset = Smi::cast(data->get(kImportIndex))->value(); | 1412 WriteGlobalValue(module_->globals[import.index], globals, val); | 
| 1727 int type = Smi::cast(data->get(kImportGlobalType))->value(); | |
| 1728 WriteGlobalValue(globals, offset, val, type); | |
| 1729 break; | 1413 break; | 
| 1730 } | 1414 } | 
| 1731 default: | 1415 default: | 
| 1732 UNREACHABLE(); | 1416 UNREACHABLE(); | 
| 1733 break; | 1417 break; | 
| 1734 } | 1418 } | 
| 1735 } | 1419 } | 
| 1736 return num_imported_functions; | 1420 return num_imported_functions; | 
| 1737 } | 1421 } | 
| 1738 | 1422 | 
| 1423 template <typename T> | |
| 1424 T* GetRawGlobalPtr(WasmGlobal& global, MaybeHandle<JSArrayBuffer> globals) { | |
| 1425 return reinterpret_cast<T*>(raw_buffer_ptr(globals, global.offset)); | |
| 1426 } | |
| 1427 | |
| 1739 // Process initialization of globals. | 1428 // Process initialization of globals. | 
| 1740 void ProcessInits(MaybeHandle<JSArrayBuffer> globals) { | 1429 void InitGlobals(MaybeHandle<JSArrayBuffer> globals) { | 
| 1741 if (!compiled_module_->has_inits()) return; | 1430 for (auto global : module_->globals) { | 
| 1742 | 1431 switch (global.init.kind) { | 
| 1743 Handle<FixedArray> inits = compiled_module_->inits(); | 1432 case WasmInitExpr::kI32Const: | 
| 1744 for (int index = 0; index < inits->length(); ++index) { | 1433 *GetRawGlobalPtr<int32_t>(global, globals) = | 
| 1745 Handle<FixedArray> data = | 1434 global.init.val.i32_const; | 
| 1746 inits->GetValueChecked<FixedArray>(isolate_, index); | 1435 break; | 
| 1747 | 1436 case WasmInitExpr::kI64Const: | 
| 1748 int offset = Smi::cast(data->get(kGlobalInitIndex))->value(); | 1437 *GetRawGlobalPtr<int64_t>(global, globals) = | 
| 1749 Handle<Object> val(data->get(kGlobalInitValue), isolate_); | 1438 global.init.val.i64_const; | 
| 1750 int type = Smi::cast(data->get(kGlobalInitType))->value(); | 1439 break; | 
| 1751 if (Smi::cast(data->get(kGlobalInitKind))->value() == 0) { | 1440 case WasmInitExpr::kF32Const: | 
| 1752 // Initialize with a constant. | 1441 *GetRawGlobalPtr<float>(global, globals) = global.init.val.f32_const; | 
| 1753 WriteGlobalValue(globals, offset, val, type); | 1442 break; | 
| 1754 } else { | 1443 case WasmInitExpr::kF64Const: | 
| 1755 // Initialize with another global. | 1444 *GetRawGlobalPtr<double>(global, globals) = global.init.val.f64_const; | 
| 1756 int old_offset = Smi::cast(*val)->value(); | 1445 break; | 
| 1757 TRACE("init [globals+%u] = [globals+%d]\n", offset, old_offset); | 1446 case WasmInitExpr::kGlobalIndex: { | 
| 1758 int size = sizeof(int32_t); | 1447 // Initialize with another global. | 
| 1759 if (type == kLocalI64 || type == kLocalF64) size = sizeof(double); | 1448 uint32_t new_offset = global.offset; | 
| 1760 memcpy(raw_buffer_ptr(globals, offset), | 1449 uint32_t old_offset = | 
| 1761 raw_buffer_ptr(globals, old_offset), size); | 1450 module_->globals[global.init.val.global_index].offset; | 
| 1451 TRACE("init [globals+%u] = [globals+%d]\n", global.offset, | |
| 1452 old_offset); | |
| 1453 size_t size = (global.type == kAstI64 || global.type == kAstF64) | |
| 1454 ? size = sizeof(double) | |
| 1455 : sizeof(int32_t); | |
| 1456 memcpy(raw_buffer_ptr(globals, new_offset), | |
| 1457 raw_buffer_ptr(globals, old_offset), size); | |
| 1458 break; | |
| 1459 } | |
| 1460 case WasmInitExpr::kNone: | |
| 1461 // Happens with imported globals. | |
| 1462 break; | |
| 1463 default: | |
| 1464 UNREACHABLE(); | |
| 1465 break; | |
| 1762 } | 1466 } | 
| 1763 } | 1467 } | 
| 1764 } | 1468 } | 
| 1765 | 1469 | 
| 1766 // Allocate memory for a module instance as a new JSArrayBuffer. | 1470 // Allocate memory for a module instance as a new JSArrayBuffer. | 
| 1767 Handle<JSArrayBuffer> AllocateMemory(uint32_t min_mem_pages) { | 1471 Handle<JSArrayBuffer> AllocateMemory(uint32_t min_mem_pages) { | 
| 1768 if (min_mem_pages > WasmModule::kMaxMemPages) { | 1472 if (min_mem_pages > WasmModule::kMaxMemPages) { | 
| 1769 thrower_->Error("Out of memory: wasm memory too large"); | 1473 thrower_->Error("Out of memory: wasm memory too large"); | 
| 1770 return Handle<JSArrayBuffer>::null(); | 1474 return Handle<JSArrayBuffer>::null(); | 
| 1771 } | 1475 } | 
| 1772 Handle<JSArrayBuffer> mem_buffer = | 1476 Handle<JSArrayBuffer> mem_buffer = | 
| 1773 NewArrayBuffer(isolate_, min_mem_pages * WasmModule::kPageSize); | 1477 NewArrayBuffer(isolate_, min_mem_pages * WasmModule::kPageSize); | 
| 1774 | 1478 | 
| 1775 if (mem_buffer.is_null()) { | 1479 if (mem_buffer.is_null()) { | 
| 1776 thrower_->Error("Out of memory: wasm memory"); | 1480 thrower_->Error("Out of memory: wasm memory"); | 
| 1777 } | 1481 } | 
| 1778 return mem_buffer; | 1482 return mem_buffer; | 
| 1779 } | 1483 } | 
| 1780 | 1484 | 
| 1781 // Process the exports, creating wrappers for functions, tables, memories, | 1485 // Process the exports, creating wrappers for functions, tables, memories, | 
| 1782 // and globals. | 1486 // and globals. | 
| 1783 void ProcessExports(MaybeHandle<JSArrayBuffer> globals, | 1487 void ProcessExports(MaybeHandle<JSArrayBuffer> globals, | 
| 1784 Handle<FixedArray> code_table, | 1488 Handle<FixedArray> code_table, | 
| 1785 Handle<JSObject> instance) { | 1489 Handle<JSObject> instance) { | 
| 1786 if (!compiled_module_->has_exports()) return; | 1490 if (module_->export_table.size() == 0) return; | 
| 1787 | 1491 | 
| 1788 Handle<JSObject> exports_object = instance; | 1492 Handle<JSObject> exports_object = instance; | 
| 1789 if (compiled_module_->origin() == kWasmOrigin) { | 1493 if (module_->origin == kWasmOrigin) { | 
| 1790 // Create the "exports" object. | 1494 // Create the "exports" object. | 
| 1791 Handle<JSFunction> object_function = Handle<JSFunction>( | 1495 Handle<JSFunction> object_function = Handle<JSFunction>( | 
| 1792 isolate_->native_context()->object_function(), isolate_); | 1496 isolate_->native_context()->object_function(), isolate_); | 
| 1793 exports_object = | 1497 exports_object = | 
| 1794 isolate_->factory()->NewJSObject(object_function, TENURED); | 1498 isolate_->factory()->NewJSObject(object_function, TENURED); | 
| 1795 Handle<String> exports_name = | 1499 Handle<String> exports_name = | 
| 1796 isolate_->factory()->InternalizeUtf8String("exports"); | 1500 isolate_->factory()->InternalizeUtf8String("exports"); | 
| 1797 JSObject::AddProperty(instance, exports_name, exports_object, READ_ONLY); | 1501 JSObject::AddProperty(instance, exports_name, exports_object, READ_ONLY); | 
| 1798 } | 1502 } | 
| 1799 | 1503 | 
| 1800 PropertyDescriptor desc; | 1504 PropertyDescriptor desc; | 
| 1801 desc.set_writable(false); | 1505 desc.set_writable(false); | 
| 1802 | 1506 | 
| 1803 Handle<FixedArray> exports = compiled_module_->exports(); | 1507 int func_index = 0; | 
| 1804 | 1508 for (auto exp : module_->export_table) { | 
| 
 
Mircea Trofin
2016/10/15 17:38:40
same comment about auto as above.
 
 | |
| 1805 for (int i = 0; i < exports->length(); ++i) { | |
| 1806 Handle<FixedArray> export_data = | |
| 1807 exports->GetValueChecked<FixedArray>(isolate_, i); | |
| 1808 Handle<String> name = | 1509 Handle<String> name = | 
| 1809 export_data->GetValueChecked<String>(isolate_, kExportName); | 1510 ExtractStringFromModuleBytes(isolate_, compiled_module_, | 
| 
 
Mircea Trofin
2016/10/15 17:38:40
same comment about string interning as above
 
 | |
| 1810 WasmExternalKind kind = static_cast<WasmExternalKind>( | 1511 exp.name_offset, exp.name_length) | 
| 1811 Smi::cast(export_data->get(kExportKind))->value()); | 1512 .ToHandleChecked(); | 
| 1812 switch (kind) { | 1513 switch (exp.kind) { | 
| 1813 case kExternalFunction: { | 1514 case kExternalFunction: { | 
| 1814 // Wrap and export the code as a JSFunction. | 1515 // Wrap and export the code as a JSFunction. | 
| 1815 int code_table_index = | 1516 WasmFunction& function = module_->functions[exp.index]; | 
| 1816 Smi::cast(export_data->get(kExportIndex))->value(); | 1517 int export_index = | 
| 1518 static_cast<int>(module_->functions.size() + func_index); | |
| 1817 Handle<Code> export_code = | 1519 Handle<Code> export_code = | 
| 1818 code_table->GetValueChecked<Code>(isolate_, code_table_index); | 1520 code_table->GetValueChecked<Code>(isolate_, export_index); | 
| 1819 int arity = Smi::cast(export_data->get(kExportArity))->value(); | 1521 desc.set_value(WrapExportCodeAsJSFunction(isolate_, export_code, name, | 
| 1820 MaybeHandle<ByteArray> signature = | 1522 function.sig, instance)); | 
| 1821 export_data->GetValue<ByteArray>(isolate_, kExportedSignature); | 1523 func_index++; | 
| 1822 desc.set_value(WrapExportCodeAsJSFunction( | |
| 1823 isolate_, export_code, name, arity, signature, instance)); | |
| 1824 break; | 1524 break; | 
| 1825 } | 1525 } | 
| 1826 case kExternalTable: | 1526 case kExternalTable: | 
| 1827 // TODO(titzer): create a WebAssembly.Table instance. | 1527 // TODO(titzer): create a WebAssembly.Table instance. | 
| 1828 // TODO(titzer): should it have the same identity as an import? | 1528 // TODO(titzer): should it have the same identity as an import? | 
| 1829 break; | 1529 break; | 
| 1830 case kExternalMemory: { | 1530 case kExternalMemory: { | 
| 1831 // Export the memory as a WebAssembly.Memory object. | 1531 // Export the memory as a WebAssembly.Memory object. | 
| 1832 Handle<Object> memory_object( | 1532 Handle<Object> memory_object( | 
| 1833 instance->GetInternalField(kWasmMemObject), isolate_); | 1533 instance->GetInternalField(kWasmMemObject), isolate_); | 
| 1834 if (memory_object->IsUndefined(isolate_)) { | 1534 if (memory_object->IsUndefined(isolate_)) { | 
| 1835 // If there was no imported WebAssembly.Memory object, create one. | 1535 // If there was no imported WebAssembly.Memory object, create one. | 
| 1836 Handle<JSArrayBuffer> buffer( | 1536 Handle<JSArrayBuffer> buffer( | 
| 1837 JSArrayBuffer::cast( | 1537 JSArrayBuffer::cast( | 
| 1838 instance->GetInternalField(kWasmMemArrayBuffer)), | 1538 instance->GetInternalField(kWasmMemArrayBuffer)), | 
| 1839 isolate_); | 1539 isolate_); | 
| 1840 memory_object = | 1540 memory_object = | 
| 1841 WasmJs::CreateWasmMemoryObject(isolate_, buffer, false, 0); | 1541 WasmJs::CreateWasmMemoryObject(isolate_, buffer, false, 0); | 
| 1842 instance->SetInternalField(kWasmMemObject, *memory_object); | 1542 instance->SetInternalField(kWasmMemObject, *memory_object); | 
| 1843 } | 1543 } | 
| 1844 | 1544 | 
| 1845 desc.set_value(memory_object); | 1545 desc.set_value(memory_object); | 
| 1846 break; | 1546 break; | 
| 1847 } | 1547 } | 
| 1848 case kExternalGlobal: { | 1548 case kExternalGlobal: { | 
| 1849 // Export the value of the global variable as a number. | 1549 // Export the value of the global variable as a number. | 
| 1850 int offset = Smi::cast(export_data->get(kExportIndex))->value(); | 1550 WasmGlobal& global = module_->globals[exp.index]; | 
| 1851 byte* ptr = raw_buffer_ptr(globals, offset); | |
| 1852 double num = 0; | 1551 double num = 0; | 
| 1853 switch (Smi::cast(export_data->get(kExportGlobalType))->value()) { | 1552 switch (global.type) { | 
| 1854 case kLocalI32: | 1553 case kAstI32: | 
| 1855 num = *reinterpret_cast<int32_t*>(ptr); | 1554 num = *GetRawGlobalPtr<int32_t>(global, globals); | 
| 1856 break; | 1555 break; | 
| 1857 case kLocalF32: | 1556 case kAstF32: | 
| 1858 num = *reinterpret_cast<float*>(ptr); | 1557 num = *GetRawGlobalPtr<float>(global, globals); | 
| 1859 break; | 1558 break; | 
| 1860 case kLocalF64: | 1559 case kAstF64: | 
| 1861 num = *reinterpret_cast<double*>(ptr); | 1560 num = *GetRawGlobalPtr<double>(global, globals); | 
| 1862 break; | 1561 break; | 
| 1863 default: | 1562 default: | 
| 1864 UNREACHABLE(); | 1563 UNREACHABLE(); | 
| 1865 } | 1564 } | 
| 1866 desc.set_value(isolate_->factory()->NewNumber(num)); | 1565 desc.set_value(isolate_->factory()->NewNumber(num)); | 
| 1867 break; | 1566 break; | 
| 1868 } | 1567 } | 
| 1869 default: | 1568 default: | 
| 1870 UNREACHABLE(); | 1569 UNREACHABLE(); | 
| 1871 break; | 1570 break; | 
| 1872 } | 1571 } | 
| 1873 | 1572 | 
| 1874 v8::Maybe<bool> status = JSReceiver::DefineOwnProperty( | 1573 v8::Maybe<bool> status = JSReceiver::DefineOwnProperty( | 
| 1875 isolate_, exports_object, name, &desc, Object::THROW_ON_ERROR); | 1574 isolate_, exports_object, name, &desc, Object::THROW_ON_ERROR); | 
| 1876 if (!status.IsJust()) { | 1575 if (!status.IsJust()) { | 
| 1877 thrower_->Error("export of %.*s failed.", name->length(), | 1576 thrower_->Error("export of %.*s failed.", name->length(), | 
| 1878 name->ToCString().get()); | 1577 name->ToCString().get()); | 
| 1879 return; | 1578 return; | 
| 1880 } | 1579 } | 
| 1881 } | 1580 } | 
| 1882 } | 1581 } | 
| 1883 }; | 1582 }; | 
| 1884 | 1583 | 
| 1885 // Instantiates a WASM module, creating a WebAssembly.Instance from a | 1584 // Instantiates a WASM module, creating a WebAssembly.Instance from a | 
| 1886 // WebAssembly.Module. | 1585 // WebAssembly.Module. | 
| 1887 MaybeHandle<JSObject> WasmModule::Instantiate(Isolate* isolate, | 1586 MaybeHandle<JSObject> WasmModule::Instantiate(Isolate* isolate, | 
| 1888 ErrorThrower* thrower, | 1587 ErrorThrower* thrower, | 
| 1889 Handle<JSObject> module_object, | 1588 Handle<JSObject> wasm_module, | 
| 1890 Handle<JSReceiver> ffi, | 1589 Handle<JSReceiver> ffi, | 
| 1891 Handle<JSArrayBuffer> memory) { | 1590 Handle<JSArrayBuffer> memory) { | 
| 1892 WasmInstanceBuilder builder(isolate, thrower, module_object, ffi, memory); | 1591 WasmInstanceBuilder builder(isolate, thrower, wasm_module, ffi, memory); | 
| 1893 return builder.Build(); | 1592 return builder.Build(); | 
| 1894 } | 1593 } | 
| 1895 | 1594 | 
| 1896 Handle<WasmCompiledModule> WasmCompiledModule::New(Isolate* isolate, | 1595 Handle<WasmCompiledModule> WasmCompiledModule::New( | 
| 1897 uint32_t min_memory_pages, | 1596 Isolate* isolate, Handle<WasmModuleWrapper> module_wrapper) { | 
| 1898 uint32_t globals_size, | |
| 1899 ModuleOrigin origin) { | |
| 1900 Handle<FixedArray> ret = | 1597 Handle<FixedArray> ret = | 
| 1901 isolate->factory()->NewFixedArray(PropertyIndices::Count, TENURED); | 1598 isolate->factory()->NewFixedArray(PropertyIndices::Count, TENURED); | 
| 1902 // Globals size is expected to fit into an int without overflow. This is not | |
| 1903 // supported by the spec at the moment, however, we don't support array | |
| 1904 // buffer sizes over 1g, so, for now, we avoid alocating a HeapNumber for | |
| 1905 // the globals size. The CHECK guards this assumption. | |
| 1906 CHECK_GE(static_cast<int>(globals_size), 0); | |
| 1907 ret->set(kID_min_memory_pages, | |
| 1908 Smi::FromInt(static_cast<int>(min_memory_pages))); | |
| 1909 ret->set(kID_globals_size, Smi::FromInt(static_cast<int>(globals_size))); | |
| 1910 ret->set(kID_origin, Smi::FromInt(static_cast<int>(origin))); | |
| 1911 | |
| 1912 // WasmCompiledModule::cast would fail since module bytes are not set yet. | 1599 // WasmCompiledModule::cast would fail since module bytes are not set yet. | 
| 1913 Handle<WasmCompiledModule> module(reinterpret_cast<WasmCompiledModule*>(*ret), | 1600 Handle<WasmCompiledModule> compiled_module( | 
| 1914 isolate); | 1601 reinterpret_cast<WasmCompiledModule*>(*ret), isolate); | 
| 1915 module->Init(); | 1602 compiled_module->InitId(); | 
| 1916 return module; | 1603 compiled_module->set_module_wrapper(module_wrapper); | 
| 1604 return compiled_module; | |
| 1917 } | 1605 } | 
| 1918 | 1606 | 
| 1919 void WasmCompiledModule::Init() { | 1607 void WasmCompiledModule::InitId() { | 
| 1920 #if DEBUG | 1608 #if DEBUG | 
| 1921 static uint32_t instance_id_counter = 0; | 1609 static uint32_t instance_id_counter = 0; | 
| 1922 set(kID_instance_id, Smi::FromInt(instance_id_counter++)); | 1610 set(kID_instance_id, Smi::FromInt(instance_id_counter++)); | 
| 1923 TRACE("New compiled module id: %d\n", instance_id()); | 1611 TRACE("New compiled module id: %d\n", instance_id()); | 
| 1924 #endif | 1612 #endif | 
| 1925 } | 1613 } | 
| 1926 | 1614 | 
| 1927 bool WasmCompiledModule::IsWasmCompiledModule(Object* obj) { | 1615 bool WasmCompiledModule::IsWasmCompiledModule(Object* obj) { | 
| 1928 if (!obj->IsFixedArray()) return false; | 1616 if (!obj->IsFixedArray()) return false; | 
| 1929 FixedArray* arr = FixedArray::cast(obj); | 1617 FixedArray* arr = FixedArray::cast(obj); | 
| (...skipping 23 matching lines...) Expand all Loading... | |
| 1953 if (current->ptr_to_weak_next_instance() == nullptr) break; | 1641 if (current->ptr_to_weak_next_instance() == nullptr) break; | 
| 1954 CHECK(!current->ptr_to_weak_next_instance()->cleared()); | 1642 CHECK(!current->ptr_to_weak_next_instance()->cleared()); | 
| 1955 current = | 1643 current = | 
| 1956 WasmCompiledModule::cast(current->ptr_to_weak_next_instance()->value()); | 1644 WasmCompiledModule::cast(current->ptr_to_weak_next_instance()->value()); | 
| 1957 } | 1645 } | 
| 1958 PrintF("\n"); | 1646 PrintF("\n"); | 
| 1959 #endif | 1647 #endif | 
| 1960 } | 1648 } | 
| 1961 | 1649 | 
| 1962 Handle<Object> wasm::GetWasmFunctionNameOrNull(Isolate* isolate, | 1650 Handle<Object> wasm::GetWasmFunctionNameOrNull(Isolate* isolate, | 
| 1963 Handle<Object> wasm, | 1651 Handle<Object> wasm_module, | 
| 1964 uint32_t func_index) { | 1652 uint32_t func_index) { | 
| 1965 if (!wasm->IsUndefined(isolate)) { | 1653 if (!wasm_module->IsUndefined(isolate)) { | 
| 1966 DCHECK(IsWasmObject(*wasm)); | 1654 DCHECK(IsWasmModule(*wasm_module)); | 
| 1967 WasmCompiledModule* compiled_module = | 1655 WasmModule* module = CppModule(Handle<JSObject>::cast(wasm_module)); | 
| 1968 GetCompiledModule(JSObject::cast(*wasm)); | 1656 WasmFunction& function = module->functions[func_index]; | 
| 1969 Handle<ByteArray> func_names = compiled_module->function_names(); | 1657 Handle<WasmCompiledModule> compiled_module(GetCompiledModule(*wasm_module), | 
| 1970 // TODO(clemens): Extract this from the module bytes; skip whole function | 1658 isolate); | 
| 1971 // name table. | 1659 MaybeHandle<String> string = ExtractStringFromModuleBytes( | 
| 1972 Handle<Object> name; | 1660 isolate, compiled_module, function.name_offset, function.name_length); | 
| 1973 if (GetWasmFunctionNameFromTable(func_names, func_index).ToHandle(&name)) { | 1661 if (!string.is_null()) return string.ToHandleChecked(); | 
| 1974 return name; | |
| 1975 } | |
| 1976 } | 1662 } | 
| 1977 return isolate->factory()->null_value(); | 1663 return isolate->factory()->null_value(); | 
| 1978 } | 1664 } | 
| 1979 | 1665 | 
| 1980 Handle<String> wasm::GetWasmFunctionName(Isolate* isolate, Handle<Object> wasm, | 1666 Handle<String> wasm::GetWasmFunctionName(Isolate* isolate, | 
| 1667 Handle<Object> wasm_module, | |
| 1981 uint32_t func_index) { | 1668 uint32_t func_index) { | 
| 1982 Handle<Object> name_or_null = | 1669 Handle<Object> name_or_null = | 
| 1983 GetWasmFunctionNameOrNull(isolate, wasm, func_index); | 1670 GetWasmFunctionNameOrNull(isolate, wasm_module, func_index); | 
| 1984 if (!name_or_null->IsNull(isolate)) { | 1671 if (!name_or_null->IsNull(isolate)) { | 
| 1985 return Handle<String>::cast(name_or_null); | 1672 return Handle<String>::cast(name_or_null); | 
| 1986 } | 1673 } | 
| 1987 return isolate->factory()->NewStringFromStaticChars("<WASM UNNAMED>"); | 1674 return isolate->factory()->NewStringFromStaticChars("<WASM UNNAMED>"); | 
| 1988 } | 1675 } | 
| 1989 | 1676 | 
| 1990 bool wasm::IsWasmObject(Object* object) { | 1677 bool wasm::IsWasmModule(Object* object) { | 
| 1678 // TODO(titzer): this can be made reliable with WebAssembly.Module brand. | |
| 1991 if (!object->IsJSObject()) return false; | 1679 if (!object->IsJSObject()) return false; | 
| 1992 | 1680 | 
| 1993 JSObject* obj = JSObject::cast(object); | 1681 JSObject* obj = JSObject::cast(object); | 
| 1994 Isolate* isolate = obj->GetIsolate(); | 1682 Isolate* isolate = obj->GetIsolate(); | 
| 1995 if (obj->GetInternalFieldCount() != kWasmModuleInternalFieldCount) { | 1683 if (obj->GetInternalFieldCount() != kWasmInstanceInternalFieldCount) { | 
| 1996 return false; | 1684 return false; | 
| 1997 } | 1685 } | 
| 1998 | 1686 | 
| 1999 Object* mem = obj->GetInternalField(kWasmMemArrayBuffer); | 1687 Object* mem = obj->GetInternalField(kWasmMemArrayBuffer); | 
| 2000 if (!obj->GetInternalField(kWasmModuleCodeTable)->IsFixedArray() || | 1688 if (!obj->GetInternalField(kWasmModuleCodeTable)->IsFixedArray() || | 
| 2001 !(mem->IsUndefined(isolate) || mem->IsJSArrayBuffer()) || | 1689 !(mem->IsUndefined(isolate) || mem->IsJSArrayBuffer()) || | 
| 2002 !WasmCompiledModule::IsWasmCompiledModule( | 1690 !WasmCompiledModule::IsWasmCompiledModule( | 
| 2003 obj->GetInternalField(kWasmCompiledModule))) { | 1691 obj->GetInternalField(kWasmCompiledModule))) { | 
| 2004 return false; | 1692 return false; | 
| 2005 } | 1693 } | 
| 2006 | 1694 | 
| 2007 // All checks passed. | 1695 // All checks passed. | 
| 2008 return true; | 1696 return true; | 
| 2009 } | 1697 } | 
| 2010 | 1698 | 
| 2011 WasmCompiledModule* wasm::GetCompiledModule(JSObject* wasm) { | 1699 WasmCompiledModule* wasm::GetCompiledModule(Object* wasm_module) { | 
| 2012 return WasmCompiledModule::cast(wasm->GetInternalField(kWasmCompiledModule)); | 1700 DCHECK(IsWasmModule(wasm_module)); | 
| 1701 return WasmCompiledModule::cast( | |
| 1702 JSObject::cast(wasm_module)->GetInternalField(kWasmCompiledModule)); | |
| 2013 } | 1703 } | 
| 2014 | 1704 | 
| 2015 bool wasm::WasmIsAsmJs(Object* wasm, Isolate* isolate) { | 1705 bool wasm::WasmIsAsmJs(Object* instance, Isolate* isolate) { | 
| 2016 if (wasm->IsUndefined(isolate)) return false; | 1706 return IsWasmModule(instance) && | 
| 2017 DCHECK(IsWasmObject(wasm)); | 1707 GetCompiledModule(JSObject::cast(instance))->has_asm_js_script(); | 
| 2018 WasmCompiledModule* compiled_module = GetCompiledModule(JSObject::cast(wasm)); | |
| 2019 return compiled_module->has_asm_js_script(); | |
| 2020 } | 1708 } | 
| 2021 | 1709 | 
| 2022 Handle<Script> wasm::GetAsmWasmScript(Handle<JSObject> wasm) { | 1710 Handle<Script> wasm::GetAsmWasmScript(Handle<JSObject> wasm_module) { | 
| 2023 DCHECK(IsWasmObject(*wasm)); | 1711 DCHECK(IsWasmModule(*wasm_module)); | 
| 2024 WasmCompiledModule* compiled_module = GetCompiledModule(*wasm); | 1712 WasmCompiledModule* compiled_module = GetCompiledModule(*wasm_module); | 
| 2025 return compiled_module->asm_js_script(); | 1713 return compiled_module->asm_js_script(); | 
| 2026 } | 1714 } | 
| 2027 | 1715 | 
| 2028 int wasm::GetAsmWasmSourcePosition(Handle<JSObject> wasm, int func_index, | 1716 int wasm::GetAsmWasmSourcePosition(Handle<JSObject> wasm_module, int func_index, | 
| 2029 int byte_offset) { | 1717 int byte_offset) { | 
| 2030 return WasmDebugInfo::GetAsmJsSourcePosition(GetDebugInfo(wasm), func_index, | 1718 return WasmDebugInfo::GetAsmJsSourcePosition(GetDebugInfo(wasm_module), | 
| 2031 byte_offset); | 1719 func_index, byte_offset); | 
| 2032 } | 1720 } | 
| 2033 | 1721 | 
| 2034 Handle<SeqOneByteString> wasm::GetWasmBytes(Handle<JSObject> wasm) { | 1722 Handle<SeqOneByteString> wasm::GetWasmBytes(Handle<JSObject> wasm_module) { | 
| 2035 DCHECK(IsWasmObject(*wasm)); | 1723 DCHECK(IsWasmModule(*wasm_module)); | 
| 2036 WasmCompiledModule* compiled_module = GetCompiledModule(*wasm); | 1724 WasmCompiledModule* compiled_module = GetCompiledModule(*wasm_module); | 
| 2037 return compiled_module->module_bytes(); | 1725 return compiled_module->module_bytes(); | 
| 2038 } | 1726 } | 
| 2039 | 1727 | 
| 2040 Handle<WasmDebugInfo> wasm::GetDebugInfo(Handle<JSObject> wasm) { | 1728 Handle<WasmDebugInfo> wasm::GetDebugInfo(Handle<JSObject> wasm_module) { | 
| 2041 Handle<Object> info(wasm->GetInternalField(kWasmDebugInfo), | 1729 Handle<Object> info(wasm_module->GetInternalField(kWasmDebugInfo), | 
| 2042 wasm->GetIsolate()); | 1730 wasm_module->GetIsolate()); | 
| 2043 if (!info->IsUndefined(wasm->GetIsolate())) | 1731 if (!info->IsUndefined(wasm_module->GetIsolate())) | 
| 2044 return Handle<WasmDebugInfo>::cast(info); | 1732 return Handle<WasmDebugInfo>::cast(info); | 
| 2045 Handle<WasmDebugInfo> new_info = WasmDebugInfo::New(wasm); | 1733 Handle<WasmDebugInfo> new_info = WasmDebugInfo::New(wasm_module); | 
| 2046 wasm->SetInternalField(kWasmDebugInfo, *new_info); | 1734 wasm_module->SetInternalField(kWasmDebugInfo, *new_info); | 
| 2047 return new_info; | 1735 return new_info; | 
| 2048 } | 1736 } | 
| 2049 | 1737 | 
| 2050 bool wasm::UpdateWasmModuleMemory(Handle<JSObject> object, Address old_start, | 1738 bool wasm::UpdateWasmModuleMemory(Handle<JSObject> object, Address old_start, | 
| 2051 Address new_start, uint32_t old_size, | 1739 Address new_start, uint32_t old_size, | 
| 2052 uint32_t new_size) { | 1740 uint32_t new_size) { | 
| 2053 DisallowHeapAllocation no_allocation; | 1741 DisallowHeapAllocation no_allocation; | 
| 2054 if (!IsWasmObject(*object)) { | 1742 if (!IsWasmModule(*object)) { | 
| 2055 return false; | 1743 return false; | 
| 2056 } | 1744 } | 
| 2057 | 1745 | 
| 2058 // Get code table associated with the module js_object | 1746 // Get code table associated with the module js_object | 
| 2059 Object* obj = object->GetInternalField(kWasmModuleCodeTable); | 1747 Object* obj = object->GetInternalField(kWasmModuleCodeTable); | 
| 2060 Handle<FixedArray> code_table(FixedArray::cast(obj)); | 1748 Handle<FixedArray> code_table(FixedArray::cast(obj)); | 
| 2061 | 1749 | 
| 2062 // Iterate through the code objects in the code table and update relocation | 1750 // Iterate through the code objects in the code table and update relocation | 
| 2063 // information | 1751 // information | 
| 2064 for (int i = 0; i < code_table->length(); ++i) { | 1752 for (int i = 0; i < code_table->length(); ++i) { | 
| 2065 obj = code_table->get(i); | 1753 obj = code_table->get(i); | 
| 2066 Handle<Code> code(Code::cast(obj)); | 1754 Handle<Code> code(Code::cast(obj)); | 
| 2067 | 1755 | 
| 2068 int mode_mask = RelocInfo::ModeMask(RelocInfo::WASM_MEMORY_REFERENCE) | | 1756 int mode_mask = RelocInfo::ModeMask(RelocInfo::WASM_MEMORY_REFERENCE) | | 
| 2069 RelocInfo::ModeMask(RelocInfo::WASM_MEMORY_SIZE_REFERENCE); | 1757 RelocInfo::ModeMask(RelocInfo::WASM_MEMORY_SIZE_REFERENCE); | 
| 2070 for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) { | 1758 for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) { | 
| 2071 RelocInfo::Mode mode = it.rinfo()->rmode(); | 1759 RelocInfo::Mode mode = it.rinfo()->rmode(); | 
| 2072 if (RelocInfo::IsWasmMemoryReference(mode) || | 1760 if (RelocInfo::IsWasmMemoryReference(mode) || | 
| 2073 RelocInfo::IsWasmMemorySizeReference(mode)) { | 1761 RelocInfo::IsWasmMemorySizeReference(mode)) { | 
| 2074 it.rinfo()->update_wasm_memory_reference(old_start, new_start, old_size, | 1762 it.rinfo()->update_wasm_memory_reference(old_start, new_start, old_size, | 
| 2075 new_size); | 1763 new_size); | 
| 2076 } | 1764 } | 
| 2077 } | 1765 } | 
| 2078 } | 1766 } | 
| 2079 return true; | 1767 return true; | 
| 2080 } | 1768 } | 
| 2081 | 1769 | 
| 2082 Handle<FixedArray> wasm::BuildFunctionTable(Isolate* isolate, uint32_t index, | 1770 int wasm::GetNumberOfFunctions(Handle<JSObject> wasm_module) { | 
| 2083 const WasmModule* module) { | 1771 WasmModule* module = CppModule(wasm_module); | 
| 2084 const WasmIndirectFunctionTable* table = &module->function_tables[index]; | 1772 return static_cast<int>(module->functions.size()); | 
| 2085 DCHECK_EQ(table->size, table->values.size()); | |
| 2086 DCHECK_GE(table->max_size, table->size); | |
| 2087 Handle<FixedArray> values = | |
| 2088 isolate->factory()->NewFixedArray(2 * table->max_size, TENURED); | |
| 2089 for (uint32_t i = 0; i < table->size; ++i) { | |
| 2090 const WasmFunction* function = &module->functions[table->values[i]]; | |
| 2091 int32_t index = table->map.Find(function->sig); | |
| 2092 DCHECK_GE(index, 0); | |
| 2093 values->set(i, Smi::FromInt(index)); | |
| 2094 values->set(i + table->max_size, Smi::FromInt(table->values[i])); | |
| 2095 } | |
| 2096 // Set the remaining elements to -1 (instead of "undefined"). These | |
| 2097 // elements are accessed directly as SMIs (without a check). On 64-bit | |
| 2098 // platforms, it is possible to have the top bits of "undefined" take | |
| 2099 // small integer values (or zero), which are more likely to be equal to | |
| 2100 // the signature index we check against. | |
| 2101 for (uint32_t i = table->size; i < table->max_size; ++i) { | |
| 2102 values->set(i, Smi::FromInt(-1)); | |
| 2103 } | |
| 2104 return values; | |
| 2105 } | 1773 } | 
| 2106 | 1774 | 
| 2107 void wasm::PopulateFunctionTable(Handle<FixedArray> table, uint32_t table_size, | 1775 Handle<JSObject> wasm::CreateWasmModuleObject( | 
| 2108 const std::vector<Handle<Code>>* code_table) { | |
| 2109 uint32_t max_size = table->length() / 2; | |
| 2110 for (uint32_t i = max_size; i < max_size + table_size; ++i) { | |
| 2111 int index = Smi::cast(table->get(static_cast<int>(i)))->value(); | |
| 2112 DCHECK_GE(index, 0); | |
| 2113 DCHECK_LT(static_cast<size_t>(index), code_table->size()); | |
| 2114 table->set(static_cast<int>(i), *(*code_table)[index]); | |
| 2115 } | |
| 2116 } | |
| 2117 | |
| 2118 int wasm::GetNumberOfFunctions(Handle<JSObject> wasm) { | |
| 2119 DCHECK(IsWasmObject(*wasm)); | |
| 2120 WasmCompiledModule* compiled_module = GetCompiledModule(*wasm); | |
| 2121 ByteArray* func_names_arr = compiled_module->ptr_to_function_names(); | |
| 2122 // TODO(clemensh): this looks inside an array constructed elsewhere. Refactor. | |
| 2123 return func_names_arr->get_int(0); | |
| 2124 } | |
| 2125 | |
| 2126 Handle<JSObject> wasm::CreateCompiledModuleObject( | |
| 2127 Isolate* isolate, Handle<WasmCompiledModule> compiled_module, | 1776 Isolate* isolate, Handle<WasmCompiledModule> compiled_module, | 
| 2128 ModuleOrigin origin) { | 1777 ModuleOrigin origin) { | 
| 2129 Handle<JSObject> module_obj; | 1778 Handle<JSObject> wasm_module; | 
| 2130 if (origin == ModuleOrigin::kWasmOrigin) { | 1779 if (origin == ModuleOrigin::kWasmOrigin) { | 
| 2131 Handle<JSFunction> module_cons( | 1780 Handle<JSFunction> module_cons( | 
| 2132 isolate->native_context()->wasm_module_constructor()); | 1781 isolate->native_context()->wasm_module_constructor()); | 
| 2133 module_obj = isolate->factory()->NewJSObject(module_cons); | 1782 wasm_module = isolate->factory()->NewJSObject(module_cons); | 
| 2134 } else { | 1783 } else { | 
| 2135 DCHECK(origin == ModuleOrigin::kAsmJsOrigin); | 1784 DCHECK(origin == ModuleOrigin::kAsmJsOrigin); | 
| 2136 Handle<Map> map = isolate->factory()->NewMap( | 1785 Handle<Map> map = isolate->factory()->NewMap( | 
| 2137 JS_OBJECT_TYPE, JSObject::kHeaderSize + kPointerSize); | 1786 JS_OBJECT_TYPE, JSObject::kHeaderSize + kPointerSize); | 
| 2138 module_obj = isolate->factory()->NewJSObjectFromMap(map, TENURED); | 1787 wasm_module = isolate->factory()->NewJSObjectFromMap(map, TENURED); | 
| 2139 } | 1788 } | 
| 2140 module_obj->SetInternalField(0, *compiled_module); | 1789 wasm_module->SetInternalField(0, *compiled_module); | 
| 2141 if (origin == ModuleOrigin::kWasmOrigin) { | 1790 if (origin == ModuleOrigin::kWasmOrigin) { | 
| 2142 Handle<Symbol> module_sym(isolate->native_context()->wasm_module_sym()); | 1791 Handle<Symbol> module_sym(isolate->native_context()->wasm_module_sym()); | 
| 2143 Object::SetProperty(module_obj, module_sym, module_obj, STRICT).Check(); | 1792 Object::SetProperty(wasm_module, module_sym, wasm_module, STRICT).Check(); | 
| 2144 } | 1793 } | 
| 2145 Handle<WeakCell> link_to_module = isolate->factory()->NewWeakCell(module_obj); | 1794 Handle<WeakCell> link_to_module = | 
| 2146 compiled_module->set_weak_module_object(link_to_module); | 1795 isolate->factory()->NewWeakCell(wasm_module); | 
| 2147 return module_obj; | 1796 compiled_module->set_weak_wasm_module(link_to_module); | 
| 1797 return wasm_module; | |
| 2148 } | 1798 } | 
| 2149 | 1799 | 
| 2150 // TODO(clemensh): origin can be inferred from asm_js_script; remove it. | 1800 // TODO(clemensh): origin can be inferred from asm_js_script; remove it. | 
| 2151 MaybeHandle<JSObject> wasm::CreateModuleObjectFromBytes( | 1801 MaybeHandle<JSObject> wasm::CreateModuleObjectFromBytes( | 
| 2152 Isolate* isolate, const byte* start, const byte* end, ErrorThrower* thrower, | 1802 Isolate* isolate, const byte* start, const byte* end, ErrorThrower* thrower, | 
| 2153 ModuleOrigin origin, Handle<Script> asm_js_script, | 1803 ModuleOrigin origin, Handle<Script> asm_js_script, | 
| 2154 const byte* asm_js_offset_tables_start, | 1804 const byte* asm_js_offset_tables_start, | 
| 2155 const byte* asm_js_offset_tables_end) { | 1805 const byte* asm_js_offset_tables_end) { | 
| 2156 MaybeHandle<JSObject> nothing; | 1806 MaybeHandle<JSObject> nothing; | 
| 2157 Zone zone(isolate->allocator()); | 1807 ModuleResult result = DecodeWasmModule(isolate, start, end, false, origin); | 
| 2158 ModuleResult result = | |
| 2159 DecodeWasmModule(isolate, &zone, start, end, false, origin); | |
| 2160 std::unique_ptr<const WasmModule> decoded_module(result.val); | |
| 2161 if (result.failed()) { | 1808 if (result.failed()) { | 
| 1809 if (result.val) delete result.val; | |
| 2162 thrower->Failed("Wasm decoding failed", result); | 1810 thrower->Failed("Wasm decoding failed", result); | 
| 2163 return nothing; | 1811 return nothing; | 
| 2164 } | 1812 } | 
| 1813 // The {module_wrapper} will take ownership of the {WasmModule} object, | |
| 1814 // and it will be destroyed when the GC reclaims the wrapper object. | |
| 1815 Handle<WasmModuleWrapper> module_wrapper = | |
| 1816 WasmModuleWrapper::New(isolate, const_cast<WasmModule*>(result.val)); | |
| 1817 | |
| 1818 // Compile the functions of the module, producing a compiled module. | |
| 2165 MaybeHandle<WasmCompiledModule> maybe_compiled_module = | 1819 MaybeHandle<WasmCompiledModule> maybe_compiled_module = | 
| 2166 decoded_module->CompileFunctions(isolate, thrower); | 1820 result.val->CompileFunctions(isolate, module_wrapper, thrower); | 
| 1821 | |
| 2167 if (maybe_compiled_module.is_null()) return nothing; | 1822 if (maybe_compiled_module.is_null()) return nothing; | 
| 1823 | |
| 2168 Handle<WasmCompiledModule> compiled_module = | 1824 Handle<WasmCompiledModule> compiled_module = | 
| 2169 maybe_compiled_module.ToHandleChecked(); | 1825 maybe_compiled_module.ToHandleChecked(); | 
| 2170 | 1826 | 
| 2171 DCHECK_EQ(origin == kAsmJsOrigin, !asm_js_script.is_null()); | 1827 DCHECK_EQ(origin == kAsmJsOrigin, !asm_js_script.is_null()); | 
| 2172 DCHECK(!compiled_module->has_asm_js_script()); | 1828 DCHECK(!compiled_module->has_asm_js_script()); | 
| 2173 DCHECK(!compiled_module->has_asm_js_offset_tables()); | 1829 DCHECK(!compiled_module->has_asm_js_offset_tables()); | 
| 2174 if (origin == kAsmJsOrigin) { | 1830 if (origin == kAsmJsOrigin) { | 
| 2175 compiled_module->set_asm_js_script(asm_js_script); | 1831 compiled_module->set_asm_js_script(asm_js_script); | 
| 2176 size_t offset_tables_len = | 1832 size_t offset_tables_len = | 
| 2177 asm_js_offset_tables_end - asm_js_offset_tables_start; | 1833 asm_js_offset_tables_end - asm_js_offset_tables_start; | 
| 2178 DCHECK_GE(static_cast<size_t>(kMaxInt), offset_tables_len); | 1834 DCHECK_GE(static_cast<size_t>(kMaxInt), offset_tables_len); | 
| 2179 Handle<ByteArray> offset_tables = | 1835 Handle<ByteArray> offset_tables = | 
| 2180 isolate->factory()->NewByteArray(static_cast<int>(offset_tables_len)); | 1836 isolate->factory()->NewByteArray(static_cast<int>(offset_tables_len)); | 
| 2181 memcpy(offset_tables->GetDataStartAddress(), asm_js_offset_tables_start, | 1837 memcpy(offset_tables->GetDataStartAddress(), asm_js_offset_tables_start, | 
| 2182 offset_tables_len); | 1838 offset_tables_len); | 
| 2183 compiled_module->set_asm_js_offset_tables(offset_tables); | 1839 compiled_module->set_asm_js_offset_tables(offset_tables); | 
| 2184 } | 1840 } | 
| 2185 | 1841 | 
| 2186 return CreateCompiledModuleObject(isolate, compiled_module, origin); | 1842 return CreateWasmModuleObject(isolate, compiled_module, origin); | 
| 2187 } | 1843 } | 
| 2188 | 1844 | 
| 2189 bool wasm::ValidateModuleBytes(Isolate* isolate, const byte* start, | 1845 bool wasm::ValidateModuleBytes(Isolate* isolate, const byte* start, | 
| 2190 const byte* end, ErrorThrower* thrower, | 1846 const byte* end, ErrorThrower* thrower, | 
| 2191 ModuleOrigin origin) { | 1847 ModuleOrigin origin) { | 
| 2192 Zone zone(isolate->allocator()); | 1848 ModuleResult result = DecodeWasmModule(isolate, start, end, false, origin); | 
| 2193 ModuleResult result = | |
| 2194 DecodeWasmModule(isolate, &zone, start, end, false, origin); | |
| 2195 if (result.ok()) { | 1849 if (result.ok()) { | 
| 2196 DCHECK_NOT_NULL(result.val); | 1850 DCHECK_NOT_NULL(result.val); | 
| 2197 delete result.val; | 1851 delete result.val; | 
| 2198 return true; | 1852 return true; | 
| 2199 } | 1853 } | 
| 2200 return false; | 1854 return false; | 
| 2201 } | 1855 } | 
| 2202 | 1856 | 
| 2203 MaybeHandle<JSArrayBuffer> wasm::GetInstanceMemory(Isolate* isolate, | 1857 MaybeHandle<JSArrayBuffer> wasm::GetInstanceMemory(Isolate* isolate, | 
| 2204 Handle<JSObject> instance) { | 1858 Handle<JSObject> instance) { | 
| 2205 Object* mem = instance->GetInternalField(kWasmMemArrayBuffer); | 1859 Object* mem = instance->GetInternalField(kWasmMemArrayBuffer); | 
| 2206 DCHECK(IsWasmObject(*instance)); | 1860 DCHECK(IsWasmModule(*instance)); | 
| 2207 if (mem->IsUndefined(isolate)) return MaybeHandle<JSArrayBuffer>(); | 1861 if (mem->IsUndefined(isolate)) return MaybeHandle<JSArrayBuffer>(); | 
| 2208 return Handle<JSArrayBuffer>(JSArrayBuffer::cast(mem)); | 1862 return Handle<JSArrayBuffer>(JSArrayBuffer::cast(mem)); | 
| 2209 } | 1863 } | 
| 2210 | 1864 | 
| 2211 void SetInstanceMemory(Handle<JSObject> instance, JSArrayBuffer* buffer) { | 1865 void SetInstanceMemory(Handle<JSObject> instance, JSArrayBuffer* buffer) { | 
| 2212 DisallowHeapAllocation no_gc; | 1866 DisallowHeapAllocation no_gc; | 
| 2213 DCHECK(IsWasmObject(*instance)); | 1867 DCHECK(IsWasmModule(*instance)); | 
| 2214 instance->SetInternalField(kWasmMemArrayBuffer, buffer); | 1868 instance->SetInternalField(kWasmMemArrayBuffer, buffer); | 
| 2215 WasmCompiledModule* compiled_module = GetCompiledModule(*instance); | 1869 WasmCompiledModule* compiled_module = GetCompiledModule(*instance); | 
| 2216 compiled_module->set_ptr_to_heap(buffer); | 1870 compiled_module->set_ptr_to_memory(buffer); | 
| 2217 } | 1871 } | 
| 2218 | 1872 | 
| 2219 int32_t wasm::GetInstanceMemorySize(Isolate* isolate, | 1873 int32_t wasm::GetInstanceMemorySize(Isolate* isolate, | 
| 2220 Handle<JSObject> instance) { | 1874 Handle<JSObject> instance) { | 
| 2221 MaybeHandle<JSArrayBuffer> maybe_mem_buffer = | 1875 MaybeHandle<JSArrayBuffer> maybe_mem_buffer = | 
| 2222 GetInstanceMemory(isolate, instance); | 1876 GetInstanceMemory(isolate, instance); | 
| 2223 Handle<JSArrayBuffer> buffer; | 1877 Handle<JSArrayBuffer> buffer; | 
| 2224 if (!maybe_mem_buffer.ToHandle(&buffer)) { | 1878 if (!maybe_mem_buffer.ToHandle(&buffer)) { | 
| 2225 return 0; | 1879 return 0; | 
| 2226 } else { | 1880 } else { | 
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2271 SetInstanceMemory(instance, *buffer); | 1925 SetInstanceMemory(instance, *buffer); | 
| 2272 if (!UpdateWasmModuleMemory(instance, old_mem_start, new_mem_start, old_size, | 1926 if (!UpdateWasmModuleMemory(instance, old_mem_start, new_mem_start, old_size, | 
| 2273 new_size)) { | 1927 new_size)) { | 
| 2274 return -1; | 1928 return -1; | 
| 2275 } | 1929 } | 
| 2276 DCHECK(old_size % WasmModule::kPageSize == 0); | 1930 DCHECK(old_size % WasmModule::kPageSize == 0); | 
| 2277 return (old_size / WasmModule::kPageSize); | 1931 return (old_size / WasmModule::kPageSize); | 
| 2278 } | 1932 } | 
| 2279 | 1933 | 
| 2280 void testing::ValidateInstancesChain(Isolate* isolate, | 1934 void testing::ValidateInstancesChain(Isolate* isolate, | 
| 2281 Handle<JSObject> module_obj, | 1935 Handle<JSObject> wasm_module, | 
| 2282 int instance_count) { | 1936 int instance_count) { | 
| 2283 CHECK_GE(instance_count, 0); | 1937 CHECK_GE(instance_count, 0); | 
| 2284 DisallowHeapAllocation no_gc; | 1938 DisallowHeapAllocation no_gc; | 
| 2285 WasmCompiledModule* compiled_module = | 1939 WasmCompiledModule* compiled_module = | 
| 2286 WasmCompiledModule::cast(module_obj->GetInternalField(0)); | 1940 WasmCompiledModule::cast(wasm_module->GetInternalField(0)); | 
| 2287 CHECK_EQ( | 1941 CHECK_EQ(JSObject::cast(compiled_module->ptr_to_weak_wasm_module()->value()), | 
| 2288 JSObject::cast(compiled_module->ptr_to_weak_module_object()->value()), | 1942 *wasm_module); | 
| 2289 *module_obj); | |
| 2290 Object* prev = nullptr; | 1943 Object* prev = nullptr; | 
| 2291 int found_instances = compiled_module->has_weak_owning_instance() ? 1 : 0; | 1944 int found_instances = compiled_module->has_weak_owning_instance() ? 1 : 0; | 
| 2292 WasmCompiledModule* current_instance = compiled_module; | 1945 WasmCompiledModule* current_instance = compiled_module; | 
| 2293 while (current_instance->has_weak_next_instance()) { | 1946 while (current_instance->has_weak_next_instance()) { | 
| 2294 CHECK((prev == nullptr && !current_instance->has_weak_prev_instance()) || | 1947 CHECK((prev == nullptr && !current_instance->has_weak_prev_instance()) || | 
| 2295 current_instance->ptr_to_weak_prev_instance()->value() == prev); | 1948 current_instance->ptr_to_weak_prev_instance()->value() == prev); | 
| 2296 CHECK_EQ(current_instance->ptr_to_weak_module_object()->value(), | 1949 CHECK_EQ(current_instance->ptr_to_weak_wasm_module()->value(), | 
| 2297 *module_obj); | 1950 *wasm_module); | 
| 2298 CHECK( | 1951 CHECK( | 
| 2299 IsWasmObject(current_instance->ptr_to_weak_owning_instance()->value())); | 1952 IsWasmModule(current_instance->ptr_to_weak_owning_instance()->value())); | 
| 2300 prev = current_instance; | 1953 prev = current_instance; | 
| 2301 current_instance = WasmCompiledModule::cast( | 1954 current_instance = WasmCompiledModule::cast( | 
| 2302 current_instance->ptr_to_weak_next_instance()->value()); | 1955 current_instance->ptr_to_weak_next_instance()->value()); | 
| 2303 ++found_instances; | 1956 ++found_instances; | 
| 2304 CHECK_LE(found_instances, instance_count); | 1957 CHECK_LE(found_instances, instance_count); | 
| 2305 } | 1958 } | 
| 2306 CHECK_EQ(found_instances, instance_count); | 1959 CHECK_EQ(found_instances, instance_count); | 
| 2307 } | 1960 } | 
| 2308 | 1961 | 
| 2309 void testing::ValidateModuleState(Isolate* isolate, | 1962 void testing::ValidateModuleState(Isolate* isolate, | 
| 2310 Handle<JSObject> module_obj) { | 1963 Handle<JSObject> wasm_module) { | 
| 2311 DisallowHeapAllocation no_gc; | 1964 DisallowHeapAllocation no_gc; | 
| 2312 WasmCompiledModule* compiled_module = | 1965 WasmCompiledModule* compiled_module = | 
| 2313 WasmCompiledModule::cast(module_obj->GetInternalField(0)); | 1966 WasmCompiledModule::cast(wasm_module->GetInternalField(0)); | 
| 2314 CHECK(compiled_module->has_weak_module_object()); | 1967 CHECK(compiled_module->has_weak_wasm_module()); | 
| 2315 CHECK_EQ(compiled_module->ptr_to_weak_module_object()->value(), *module_obj); | 1968 CHECK_EQ(compiled_module->ptr_to_weak_wasm_module()->value(), *wasm_module); | 
| 2316 CHECK(!compiled_module->has_weak_prev_instance()); | 1969 CHECK(!compiled_module->has_weak_prev_instance()); | 
| 2317 CHECK(!compiled_module->has_weak_next_instance()); | 1970 CHECK(!compiled_module->has_weak_next_instance()); | 
| 2318 CHECK(!compiled_module->has_weak_owning_instance()); | 1971 CHECK(!compiled_module->has_weak_owning_instance()); | 
| 2319 } | 1972 } | 
| 2320 | 1973 | 
| 2321 void testing::ValidateOrphanedInstance(Isolate* isolate, | 1974 void testing::ValidateOrphanedInstance(Isolate* isolate, | 
| 2322 Handle<JSObject> instance) { | 1975 Handle<JSObject> wasm_module) { | 
| 2323 DisallowHeapAllocation no_gc; | 1976 DisallowHeapAllocation no_gc; | 
| 2324 CHECK(IsWasmObject(*instance)); | 1977 CHECK(IsWasmModule(*wasm_module)); | 
| 2325 WasmCompiledModule* compiled_module = GetCompiledModule(*instance); | 1978 WasmCompiledModule* compiled_module = GetCompiledModule(*wasm_module); | 
| 2326 CHECK(compiled_module->has_weak_module_object()); | 1979 CHECK(compiled_module->has_weak_wasm_module()); | 
| 2327 CHECK(compiled_module->ptr_to_weak_module_object()->cleared()); | 1980 CHECK(compiled_module->ptr_to_weak_wasm_module()->cleared()); | 
| 2328 } | 1981 } | 
| 1982 | |
| 1983 uint32_t WasmCompiledModule::min_memory_pages() const { | |
| 1984 return reinterpret_cast<WasmModuleWrapper*>(*module_wrapper()) | |
| 1985 ->get() | |
| 1986 ->min_mem_pages; | |
| 1987 } | |
| 1988 | |
| 1989 void WasmCompiledModule::RecreateModuleWrapper(Isolate* isolate, | |
| 1990 Handle<FixedArray> array) { | |
| 
 
Mircea Trofin
2016/10/15 17:38:41
why not pass this guy as a Handle<WasmCompiledModu
 
 | |
| 1991 Handle<WasmCompiledModule> compiled_module( | |
| 1992 reinterpret_cast<WasmCompiledModule*>(*array), isolate); | |
| 1993 | |
| 1994 WasmModule* module = nullptr; | |
| 1995 { | |
| 1996 Handle<SeqOneByteString> module_bytes = compiled_module->module_bytes(); | |
| 1997 // We parse the module again directly from the module bytes; disable GC. | |
| 1998 DisallowHeapAllocation no_allocation; | |
| 1999 const byte* start = | |
| 2000 reinterpret_cast<const byte*>(module_bytes->GetCharsAddress()); | |
| 2001 const byte* end = start + module_bytes->length(); | |
| 2002 // TODO(titzer): remember the module origin in the compiled_module | |
| 2003 ModuleResult result = | |
| 2004 DecodeWasmModule(isolate, start, end, false, kWasmOrigin); | |
| 
 
Mircea Trofin
2016/10/15 17:38:40
Could you add a TODO to avoid decoding the entire
 
 | |
| 2005 CHECK(result.ok()); | |
| 2006 CHECK_NOT_NULL(result.val); | |
| 2007 module = const_cast<WasmModule*>(result.val); | |
| 2008 } | |
| 2009 | |
| 2010 Handle<WasmModuleWrapper> module_wrapper = | |
| 2011 WasmModuleWrapper::New(isolate, module); | |
| 2012 | |
| 2013 compiled_module->set_module_wrapper(module_wrapper); | |
| 2014 DCHECK(WasmCompiledModule::IsWasmCompiledModule(*compiled_module)); | |
| 2015 } | |
| OLD | NEW |