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

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

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

Powered by Google App Engine
This is Rietveld 408576698