Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(580)

Side by Side Diff: src/wasm/wasm-module.cc

Issue 2424623002: [wasm] Use a Managed<WasmModule> to hold metadata about modules. (Closed)
Patch Set: Review comments Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698