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