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