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

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

Issue 2390113003: [wasm] Refactor import handling for 0xC. (Closed)
Patch Set: Add support for exported globals. 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 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
58 // TODO(clemensh): Remove function name array, extract names from module 58 // TODO(clemensh): Remove function name array, extract names from module
59 // bytes. 59 // bytes.
60 kWasmFunctionNamesArray, 60 kWasmFunctionNamesArray,
61 kWasmModuleBytesString, 61 kWasmModuleBytesString,
62 kWasmDebugInfo, 62 kWasmDebugInfo,
63 kWasmNumImportedFunctions, 63 kWasmNumImportedFunctions,
64 kWasmModuleInternalFieldCount 64 kWasmModuleInternalFieldCount
65 }; 65 };
66 66
67 enum WasmImportData { 67 enum WasmImportData {
68 kImportKind, // Smi. an ExternalKind
69 kImportGlobalType, // Smi. Type for globals.
70 kImportIndex, // Smi. index for the import.
68 kModuleName, // String 71 kModuleName, // String
69 kFunctionName, // maybe String 72 kFunctionName, // maybe String
70 kOutputCount, // Smi. an uint32_t 73 kOutputCount, // Smi. an uint32_t
71 kSignature, // ByteArray. A copy of the data in FunctionSig 74 kSignature, // ByteArray. A copy of the data in FunctionSig
72 kWasmImportDataSize // Sentinel value. 75 kWasmImportDataSize // Sentinel value.
73 }; 76 };
74 77
75 enum WasmExportData { 78 enum WasmExportData {
76 kExportName, // String 79 kExportKind, // Smi. an ExternalKind
77 kExportArity, // Smi, an int 80 kExportGlobalType, // Smi. Type for globals.
78 kExportedFunctionIndex, // Smi, an uint32_t 81 kExportName, // String
79 kExportedSignature, // ByteArray. A copy of the data in FunctionSig 82 kExportArity, // Smi, an int
80 kWasmExportDataSize // Sentinel value. 83 kExportIndex, // Smi, an uint32_t
84 kExportedSignature, // ByteArray. A copy of the data in FunctionSig
85 kWasmExportDataSize // Sentinel value.
86 };
87
88 enum WasmGlobalInitData {
89 kGlobalInitKind, // 0 = constant, 1 = global index
90 kGlobalInitType, // Smi. Type for globals.
91 kGlobalInitIndex, // Smi, an uint32_t
92 kGlobalInitValue, // Number.
93 kWasmGlobalInitDataSize
81 }; 94 };
82 95
83 enum WasmSegmentInfo { 96 enum WasmSegmentInfo {
84 kDestAddr, // Smi. an uint32_t 97 kDestInitKind, // 0 = constant, 1 = global index
98 kDestAddrValue, // Smi. an uint32_t
85 kSourceSize, // Smi. an uint32_t 99 kSourceSize, // Smi. an uint32_t
86 kWasmSegmentInfoSize // Sentinel value. 100 kWasmSegmentInfoSize // Sentinel value.
87 }; 101 };
88 102
89 enum WasmIndirectFunctionTableData { 103 enum WasmIndirectFunctionTableData {
90 kSize, // Smi. an uint32_t 104 kSize, // Smi. an uint32_t
91 kTable, // FixedArray of indirect function table 105 kTable, // FixedArray of indirect function table
92 kWasmIndirectFunctionTableDataSize // Sentinel value. 106 kWasmIndirectFunctionTableDataSize // Sentinel value.
93 }; 107 };
94 108
109 byte* raw_buffer_ptr(MaybeHandle<JSArrayBuffer> buffer, int offset) {
Mircea Trofin 2016/10/05 16:21:09 The name strikes me as too generic. How about GetR
titzer 2016/10/05 18:29:38 Not sure that name is better, it's just longer. N
110 return static_cast<byte*>(buffer.ToHandleChecked()->backing_store()) + offset;
111 }
112
95 uint32_t GetMinModuleMemSize(const WasmModule* module) { 113 uint32_t GetMinModuleMemSize(const WasmModule* module) {
96 return WasmModule::kPageSize * module->min_mem_pages; 114 return WasmModule::kPageSize * module->min_mem_pages;
97 } 115 }
98 116
99 void LoadDataSegments(Handle<WasmCompiledModule> compiled_module,
100 Address mem_addr, size_t mem_size) {
101 CHECK(compiled_module->has_data_segments() ==
102 compiled_module->has_data_segments_info());
103
104 // If we have neither, we're done.
105 if (!compiled_module->has_data_segments()) return;
106
107 Handle<ByteArray> data = compiled_module->data_segments();
108 Handle<FixedArray> segments = compiled_module->data_segments_info();
109
110 uint32_t last_extraction_pos = 0;
111 for (int i = 0; i < segments->length(); ++i) {
112 Handle<ByteArray> segment =
113 Handle<ByteArray>(ByteArray::cast(segments->get(i)));
114 uint32_t dest_addr = static_cast<uint32_t>(segment->get_int(kDestAddr));
115 uint32_t source_size = static_cast<uint32_t>(segment->get_int(kSourceSize));
116 CHECK_LT(dest_addr, mem_size);
117 CHECK_LE(source_size, mem_size);
118 CHECK_LE(dest_addr, mem_size - source_size);
119 byte* addr = mem_addr + dest_addr;
120 data->copy_out(last_extraction_pos, addr, source_size);
121 last_extraction_pos += source_size;
122 }
123 }
124
125 void SaveDataSegmentInfo(Factory* factory, const WasmModule* module, 117 void SaveDataSegmentInfo(Factory* factory, const WasmModule* module,
126 Handle<WasmCompiledModule> compiled_module) { 118 Handle<WasmCompiledModule> compiled_module) {
127 Handle<FixedArray> segments = factory->NewFixedArray( 119 Handle<FixedArray> segments = factory->NewFixedArray(
128 static_cast<int>(module->data_segments.size()), TENURED); 120 static_cast<int>(module->data_segments.size()), TENURED);
129 uint32_t data_size = 0; 121 uint32_t data_size = 0;
130 for (const WasmDataSegment& segment : module->data_segments) { 122 for (const WasmDataSegment& segment : module->data_segments) {
131 if (segment.source_size == 0) continue; 123 if (segment.source_size == 0) continue;
132 data_size += segment.source_size; 124 data_size += segment.source_size;
133 } 125 }
134 Handle<ByteArray> data = factory->NewByteArray(data_size, TENURED); 126 Handle<ByteArray> data = factory->NewByteArray(data_size, TENURED);
135 127
136 uint32_t last_insertion_pos = 0; 128 uint32_t last_insertion_pos = 0;
137 for (uint32_t i = 0; i < module->data_segments.size(); ++i) { 129 for (uint32_t i = 0; i < module->data_segments.size(); ++i) {
138 const WasmDataSegment& segment = module->data_segments[i]; 130 const WasmDataSegment& segment = module->data_segments[i];
139 if (segment.source_size == 0) continue; 131 if (segment.source_size == 0) continue;
140 Handle<ByteArray> js_segment = 132 Handle<ByteArray> js_segment =
141 factory->NewByteArray(kWasmSegmentInfoSize * sizeof(uint32_t), TENURED); 133 factory->NewByteArray(kWasmSegmentInfoSize * sizeof(uint32_t), TENURED);
142 // TODO(titzer): add support for global offsets for dest_addr 134 // TODO(titzer): add support for global offsets for dest_addr
143 CHECK_EQ(WasmInitExpr::kI32Const, segment.dest_addr.kind); 135 CHECK_EQ(WasmInitExpr::kI32Const, segment.dest_addr.kind);
144 js_segment->set_int(kDestAddr, segment.dest_addr.val.i32_const); 136 js_segment->set_int(kDestAddrValue, segment.dest_addr.val.i32_const);
145 js_segment->set_int(kSourceSize, segment.source_size); 137 js_segment->set_int(kSourceSize, segment.source_size);
146 segments->set(i, *js_segment); 138 segments->set(i, *js_segment);
147 data->copy_in(last_insertion_pos, 139 data->copy_in(last_insertion_pos,
148 module->module_start + segment.source_offset, 140 module->module_start + segment.source_offset,
149 segment.source_size); 141 segment.source_size);
150 last_insertion_pos += segment.source_size; 142 last_insertion_pos += segment.source_size;
151 } 143 }
152 compiled_module->set_data_segments_info(segments); 144 compiled_module->set_data_segments_info(segments);
153 compiled_module->set_data_segments(data); 145 compiled_module->set_data_segments(data);
154 } 146 }
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 AllowDeferredHandleDereference embedding_raw_address; 190 AllowDeferredHandleDereference embedding_raw_address;
199 int mask = (1 << RelocInfo::WASM_MEMORY_REFERENCE) | 191 int mask = (1 << RelocInfo::WASM_MEMORY_REFERENCE) |
200 (1 << RelocInfo::WASM_MEMORY_SIZE_REFERENCE); 192 (1 << RelocInfo::WASM_MEMORY_SIZE_REFERENCE);
201 for (RelocIterator it(*function, mask); !it.done(); it.next()) { 193 for (RelocIterator it(*function, mask); !it.done(); it.next()) {
202 it.rinfo()->update_wasm_memory_reference(old_start, start, prev_size, 194 it.rinfo()->update_wasm_memory_reference(old_start, start, prev_size,
203 new_size); 195 new_size);
204 } 196 }
205 } 197 }
206 } 198 }
207 199
208 // Allocate memory for a module instance as a new JSArrayBuffer.
209 Handle<JSArrayBuffer> AllocateMemory(ErrorThrower* thrower, Isolate* isolate,
210 uint32_t min_mem_pages) {
211 if (min_mem_pages > WasmModule::kMaxMemPages) {
212 thrower->Error("Out of memory: wasm memory too large");
213 return Handle<JSArrayBuffer>::null();
214 }
215 Handle<JSArrayBuffer> mem_buffer =
216 NewArrayBuffer(isolate, min_mem_pages * WasmModule::kPageSize);
217
218 if (mem_buffer.is_null()) {
219 thrower->Error("Out of memory: wasm memory");
220 }
221 return mem_buffer;
222 }
223
224 void RelocateGlobals(Handle<JSObject> instance, Address old_start, 200 void RelocateGlobals(Handle<JSObject> instance, Address old_start,
225 Address globals_start) { 201 Address globals_start) {
226 Handle<FixedArray> functions = Handle<FixedArray>( 202 Handle<FixedArray> functions = Handle<FixedArray>(
227 FixedArray::cast(instance->GetInternalField(kWasmModuleCodeTable))); 203 FixedArray::cast(instance->GetInternalField(kWasmModuleCodeTable)));
228 uint32_t function_count = static_cast<uint32_t>(functions->length()); 204 uint32_t function_count = static_cast<uint32_t>(functions->length());
229 for (uint32_t i = 0; i < function_count; ++i) { 205 for (uint32_t i = 0; i < function_count; ++i) {
230 Handle<Code> function = Handle<Code>(Code::cast(functions->get(i))); 206 Handle<Code> function = Handle<Code>(Code::cast(functions->get(i)));
231 AllowDeferredHandleDereference embedding_raw_address; 207 AllowDeferredHandleDereference embedding_raw_address;
232 int mask = 1 << RelocInfo::WASM_GLOBAL_REFERENCE; 208 int mask = 1 << RelocInfo::WASM_GLOBAL_REFERENCE;
233 for (RelocIterator it(*function, mask); !it.done(); it.next()) { 209 for (RelocIterator it(*function, mask); !it.done(); it.next()) {
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
368 JSObject* owner) { 344 JSObject* owner) {
369 Address old_address = nullptr; 345 Address old_address = nullptr;
370 Object* stored_value = owner->GetInternalField(kWasmGlobalsArrayBuffer); 346 Object* stored_value = owner->GetInternalField(kWasmGlobalsArrayBuffer);
371 if (stored_value != undefined) { 347 if (stored_value != undefined) {
372 old_address = static_cast<Address>( 348 old_address = static_cast<Address>(
373 JSArrayBuffer::cast(stored_value)->backing_store()); 349 JSArrayBuffer::cast(stored_value)->backing_store());
374 } 350 }
375 return old_address; 351 return old_address;
376 } 352 }
377 353
378 Handle<FixedArray> GetImportsData(Factory* factory, const WasmModule* module) { 354 Handle<FixedArray> EncodeImports(Factory* factory, const WasmModule* module) {
379 Handle<FixedArray> ret = factory->NewFixedArray( 355 Handle<FixedArray> ret = factory->NewFixedArray(
380 static_cast<int>(module->import_table.size()), TENURED); 356 static_cast<int>(module->import_table.size()), TENURED);
357
381 for (size_t i = 0; i < module->import_table.size(); ++i) { 358 for (size_t i = 0; i < module->import_table.size(); ++i) {
382 const WasmImport& import = module->import_table[i]; 359 const WasmImport& import = module->import_table[i];
383 if (import.kind != kExternalFunction) continue; 360 Handle<FixedArray> encoded_import =
361 factory->NewFixedArray(kWasmImportDataSize, TENURED);
362 encoded_import->set(kImportKind, Smi::FromInt(import.kind));
363 encoded_import->set(kImportIndex, Smi::FromInt(import.index));
364
365 // Add the module and function name.
384 WasmName module_name = module->GetNameOrNull(import.module_name_offset, 366 WasmName module_name = module->GetNameOrNull(import.module_name_offset,
385 import.module_name_length); 367 import.module_name_length);
386 WasmName function_name = module->GetNameOrNull(import.field_name_offset, 368 WasmName function_name = module->GetNameOrNull(import.field_name_offset,
387 import.field_name_length); 369 import.field_name_length);
388 370
389 Handle<String> module_name_string = 371 Handle<String> module_name_string =
390 factory->InternalizeUtf8String(module_name); 372 factory->InternalizeUtf8String(module_name);
391 Handle<String> function_name_string =
392 function_name.is_empty()
393 ? Handle<String>::null()
394 : factory->InternalizeUtf8String(function_name);
395 FunctionSig* fsig = module->functions[import.index].sig;
396 Handle<ByteArray> sig = factory->NewByteArray(
397 static_cast<int>(fsig->parameter_count() + fsig->return_count()),
398 TENURED);
399 sig->copy_in(0, reinterpret_cast<const byte*>(fsig->raw_data()),
400 sig->length());
401 Handle<FixedArray> encoded_import =
402 factory->NewFixedArray(kWasmImportDataSize, TENURED);
403 encoded_import->set(kModuleName, *module_name_string); 373 encoded_import->set(kModuleName, *module_name_string);
404 if (!function_name_string.is_null()) { 374 if (!function_name.is_empty()) {
375 Handle<String> function_name_string =
376 factory->InternalizeUtf8String(function_name);
405 encoded_import->set(kFunctionName, *function_name_string); 377 encoded_import->set(kFunctionName, *function_name_string);
406 } 378 }
407 encoded_import->set(kOutputCount, 379
408 Smi::FromInt(static_cast<int>(fsig->return_count()))); 380 switch (import.kind) {
409 encoded_import->set(kSignature, *sig); 381 case kExternalFunction: {
382 // Encode the signature into the import.
383 FunctionSig* fsig = module->functions[import.index].sig;
384 Handle<ByteArray> sig = factory->NewByteArray(
385 static_cast<int>(fsig->parameter_count() + fsig->return_count()),
386 TENURED);
387 sig->copy_in(0, reinterpret_cast<const byte*>(fsig->raw_data()),
388 sig->length());
389 encoded_import->set(
390 kOutputCount, Smi::FromInt(static_cast<int>(fsig->return_count())));
391 encoded_import->set(kSignature, *sig);
392 break;
393 }
394 case kExternalTable:
395 // Nothing extra required for imported tables.
396 break;
397 case kExternalMemory:
398 // Nothing extra required for imported memories.
399 break;
400 case kExternalGlobal: {
401 // Encode the offset and the global type into the import.
402 const WasmGlobal& global = module->globals[import.index];
403 TRACE("import[%zu].type = %s\n", i, WasmOpcodes::TypeName(global.type));
404 encoded_import->set(
405 kImportGlobalType,
406 Smi::FromInt(WasmOpcodes::LocalTypeCodeFor(global.type)));
407 encoded_import->set(kImportIndex, Smi::FromInt(global.offset));
408 break;
409 }
410 }
410 ret->set(static_cast<int>(i), *encoded_import); 411 ret->set(static_cast<int>(i), *encoded_import);
411 } 412 }
412 return ret; 413 return ret;
413 } 414 }
414 415
415 static MaybeHandle<JSFunction> ReportFFIError(
416 ErrorThrower* thrower, const char* error, uint32_t index,
417 Handle<String> module_name, MaybeHandle<String> function_name) {
418 Handle<String> function_name_handle;
419 if (function_name.ToHandle(&function_name_handle)) {
420 thrower->Error("Import #%d module=\"%.*s\" function=\"%.*s\" error: %s",
421 index, module_name->length(), module_name->ToCString().get(),
422 function_name_handle->length(),
423 function_name_handle->ToCString().get(), error);
424 } else {
425 thrower->Error("Import #%d module=\"%.*s\" error: %s", index,
426 module_name->length(), module_name->ToCString().get(),
427 error);
428 }
429 thrower->Error("Import ");
430 return MaybeHandle<JSFunction>();
431 }
432
433 static MaybeHandle<JSReceiver> LookupFunction(
434 ErrorThrower* thrower, Factory* factory, Handle<JSReceiver> ffi,
435 uint32_t index, Handle<String> module_name,
436 MaybeHandle<String> function_name) {
437 if (ffi.is_null()) {
438 return ReportFFIError(thrower, "FFI is not an object", index, module_name,
439 function_name);
440 }
441
442 // Look up the module first.
443 MaybeHandle<Object> result = Object::GetProperty(ffi, module_name);
444 if (result.is_null()) {
445 return ReportFFIError(thrower, "module not found", index, module_name,
446 function_name);
447 }
448
449 Handle<Object> module = result.ToHandleChecked();
450
451 if (!module->IsJSReceiver()) {
452 return ReportFFIError(thrower, "module is not an object or function", index,
453 module_name, function_name);
454 }
455
456 Handle<Object> function;
457 if (!function_name.is_null()) {
458 // Look up the function in the module.
459 MaybeHandle<Object> result =
460 Object::GetProperty(module, function_name.ToHandleChecked());
461 if (result.is_null()) {
462 return ReportFFIError(thrower, "function not found", index, module_name,
463 function_name);
464 }
465 function = result.ToHandleChecked();
466 } else {
467 // No function specified. Use the "default export".
468 function = module;
469 }
470
471 if (!function->IsCallable()) {
472 return ReportFFIError(thrower, "not a callable", index, module_name,
473 function_name);
474 }
475
476 return Handle<JSReceiver>::cast(function);
477 }
478
479 Handle<Code> CompileImportWrapper(Isolate* isolate,
480 const Handle<JSReceiver> ffi, int index,
481 Handle<FixedArray> import_data,
482 ErrorThrower* thrower) {
483 Handle<FixedArray> data =
484 import_data->GetValueChecked<FixedArray>(isolate, index);
485 Handle<String> module_name =
486 data->GetValueChecked<String>(isolate, kModuleName);
487 MaybeHandle<String> function_name =
488 data->GetValue<String>(isolate, kFunctionName);
489
490 // TODO(mtrofin): this is an uint32_t, actually. We should rationalize
491 // it when we rationalize signed/unsigned stuff.
492 int ret_count = Smi::cast(data->get(kOutputCount))->value();
493 CHECK_GE(ret_count, 0);
494 Handle<ByteArray> sig_data =
495 data->GetValueChecked<ByteArray>(isolate, kSignature);
496 int sig_data_size = sig_data->length();
497 int param_count = sig_data_size - ret_count;
498 CHECK(param_count >= 0);
499
500 MaybeHandle<JSReceiver> function = LookupFunction(
501 thrower, isolate->factory(), ffi, index, module_name, function_name);
502 if (function.is_null()) return Handle<Code>::null();
503 Handle<Code> code;
504 Handle<JSReceiver> target = function.ToHandleChecked();
505 bool isMatch = false;
506 Handle<Code> export_wrapper_code;
507 if (target->IsJSFunction()) {
508 Handle<JSFunction> func = Handle<JSFunction>::cast(target);
509 export_wrapper_code = handle(func->code());
510 if (export_wrapper_code->kind() == Code::JS_TO_WASM_FUNCTION) {
511 int exported_param_count =
512 Smi::cast(func->GetInternalField(kInternalArity))->value();
513 Handle<ByteArray> exportedSig = Handle<ByteArray>(
514 ByteArray::cast(func->GetInternalField(kInternalSignature)));
515 if (exported_param_count == param_count &&
516 exportedSig->length() == sig_data->length() &&
517 memcmp(exportedSig->data(), sig_data->data(),
518 exportedSig->length()) == 0) {
519 isMatch = true;
520 }
521 }
522 }
523 if (isMatch) {
524 int wasm_count = 0;
525 int const mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET);
526 for (RelocIterator it(*export_wrapper_code, mask); !it.done(); it.next()) {
527 RelocInfo* rinfo = it.rinfo();
528 Address target_address = rinfo->target_address();
529 Code* target = Code::GetCodeFromTargetAddress(target_address);
530 if (target->kind() == Code::WASM_FUNCTION) {
531 ++wasm_count;
532 code = handle(target);
533 }
534 }
535 DCHECK(wasm_count == 1);
536 return code;
537 } else {
538 // Copy the signature to avoid a raw pointer into a heap object when
539 // GC can happen.
540 Zone zone(isolate->allocator());
541 MachineRepresentation* reps =
542 zone.NewArray<MachineRepresentation>(sig_data_size);
543 memcpy(reps, sig_data->data(),
544 sizeof(MachineRepresentation) * sig_data_size);
545 FunctionSig sig(ret_count, param_count, reps);
546
547 return compiler::CompileWasmToJSWrapper(isolate, target, &sig, index,
548 module_name, function_name);
549 }
550 }
551
552 void InitializeParallelCompilation( 416 void InitializeParallelCompilation(
553 Isolate* isolate, const std::vector<WasmFunction>& functions, 417 Isolate* isolate, const std::vector<WasmFunction>& functions,
554 std::vector<compiler::WasmCompilationUnit*>& compilation_units, 418 std::vector<compiler::WasmCompilationUnit*>& compilation_units,
555 ModuleEnv& module_env, ErrorThrower* thrower) { 419 ModuleEnv& module_env, ErrorThrower* thrower) {
556 for (uint32_t i = FLAG_skip_compiling_wasm_funcs; i < functions.size(); ++i) { 420 for (uint32_t i = FLAG_skip_compiling_wasm_funcs; i < functions.size(); ++i) {
557 const WasmFunction* func = &functions[i]; 421 const WasmFunction* func = &functions[i];
558 compilation_units[i] = 422 compilation_units[i] =
559 func->imported ? nullptr : new compiler::WasmCompilationUnit( 423 func->imported ? nullptr : new compiler::WasmCompilationUnit(
560 thrower, isolate, &module_env, func, i); 424 thrower, isolate, &module_env, func, i);
561 } 425 }
(...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after
1001 max_mem_pages(0), 865 max_mem_pages(0),
1002 mem_export(false), 866 mem_export(false),
1003 start_function_index(-1), 867 start_function_index(-1),
1004 origin(kWasmOrigin), 868 origin(kWasmOrigin),
1005 globals_size(0), 869 globals_size(0),
1006 num_imported_functions(0), 870 num_imported_functions(0),
1007 num_declared_functions(0), 871 num_declared_functions(0),
1008 num_exported_functions(0), 872 num_exported_functions(0),
1009 pending_tasks(new base::Semaphore(0)) {} 873 pending_tasks(new base::Semaphore(0)) {}
1010 874
875 void EncodeInit(const WasmModule* module, Factory* factory,
876 Handle<FixedArray> entry, int kind_index, int value_index,
877 const WasmInitExpr& expr) {
878 entry->set(kind_index, Smi::FromInt(0));
879
880 switch (expr.kind) {
881 case WasmInitExpr::kGlobalIndex: {
882 TRACE(" kind = 1, global index %u\n", expr.val.global_index);
883 entry->set(kind_index, Smi::FromInt(1));
884 uint32_t offset = module->globals[expr.val.global_index].offset;
885 entry->set(value_index, Smi::FromInt(offset));
886 break;
887 }
888 case WasmInitExpr::kI32Const:
889 TRACE(" kind = 0, i32 = %d\n", expr.val.i32_const);
890 entry->set(value_index, *factory->NewNumber(expr.val.i32_const));
891 break;
892 case WasmInitExpr::kI64Const:
893 // TODO(titzer): implement initializers for i64 globals.
894 UNREACHABLE();
895 break;
896 case WasmInitExpr::kF32Const:
897 TRACE(" kind = 0, f32 = %f\n", expr.val.f32_const);
898 entry->set(value_index, *factory->NewNumber(expr.val.f32_const));
899 break;
900 case WasmInitExpr::kF64Const:
901 TRACE(" kind = 0, f64 = %lf\n", expr.val.f64_const);
902 entry->set(value_index, *factory->NewNumber(expr.val.f64_const));
903 break;
904 default:
905 UNREACHABLE();
906 }
907 }
908
1011 MaybeHandle<WasmCompiledModule> WasmModule::CompileFunctions( 909 MaybeHandle<WasmCompiledModule> WasmModule::CompileFunctions(
1012 Isolate* isolate, ErrorThrower* thrower) const { 910 Isolate* isolate, ErrorThrower* thrower) const {
1013 Factory* factory = isolate->factory(); 911 Factory* factory = isolate->factory();
1014 912
1015 MaybeHandle<WasmCompiledModule> nothing; 913 MaybeHandle<WasmCompiledModule> nothing;
1016 914
1017 WasmModuleInstance temp_instance(this); 915 WasmModuleInstance temp_instance(this);
1018 temp_instance.context = isolate->native_context(); 916 temp_instance.context = isolate->native_context();
1019 temp_instance.mem_size = GetMinModuleMemSize(this); 917 temp_instance.mem_size = GetMinModuleMemSize(this);
1020 temp_instance.mem_start = nullptr; 918 temp_instance.mem_start = nullptr;
(...skipping 24 matching lines...) Expand all
1045 module_env.origin = origin; 943 module_env.origin = origin;
1046 944
1047 // The {code_table} array contains import wrappers and functions (which 945 // The {code_table} array contains import wrappers and functions (which
1048 // are both included in {functions.size()}, and export wrappers. 946 // are both included in {functions.size()}, and export wrappers.
1049 int code_table_size = 947 int code_table_size =
1050 static_cast<int>(functions.size() + num_exported_functions); 948 static_cast<int>(functions.size() + num_exported_functions);
1051 Handle<FixedArray> code_table = 949 Handle<FixedArray> code_table =
1052 factory->NewFixedArray(static_cast<int>(code_table_size), TENURED); 950 factory->NewFixedArray(static_cast<int>(code_table_size), TENURED);
1053 951
1054 // Initialize the code table with placeholders. 952 // Initialize the code table with placeholders.
1055 for (uint32_t i = 0; i < functions.size(); i++) { 953 for (uint32_t i = 0; i < functions.size(); ++i) {
1056 Code::Kind kind = Code::WASM_FUNCTION; 954 Code::Kind kind = Code::WASM_FUNCTION;
1057 if (i < num_imported_functions) kind = Code::WASM_TO_JS_FUNCTION; 955 if (i < num_imported_functions) kind = Code::WASM_TO_JS_FUNCTION;
1058 Handle<Code> placeholder = CreatePlaceholder(factory, i, kind); 956 Handle<Code> placeholder = CreatePlaceholder(factory, i, kind);
1059 code_table->set(static_cast<int>(i), *placeholder); 957 code_table->set(static_cast<int>(i), *placeholder);
1060 temp_instance.function_code[i] = placeholder; 958 temp_instance.function_code[i] = placeholder;
1061 } 959 }
1062 960
1063 isolate->counters()->wasm_functions_per_module()->AddSample( 961 isolate->counters()->wasm_functions_per_module()->AddSample(
1064 static_cast<int>(functions.size())); 962 static_cast<int>(functions.size()));
1065 if (!FLAG_trace_wasm_decoder && FLAG_wasm_num_compilation_tasks != 0) { 963 if (!FLAG_trace_wasm_decoder && FLAG_wasm_num_compilation_tasks != 0) {
1066 // Avoid a race condition by collecting results into a second vector. 964 // Avoid a race condition by collecting results into a second vector.
1067 std::vector<Handle<Code>> results; 965 std::vector<Handle<Code>> results;
1068 results.reserve(temp_instance.function_code.size()); 966 results.reserve(temp_instance.function_code.size());
1069 for (size_t i = 0; i < temp_instance.function_code.size(); i++) { 967 for (size_t i = 0; i < temp_instance.function_code.size(); ++i) {
1070 results.push_back(temp_instance.function_code[i]); 968 results.push_back(temp_instance.function_code[i]);
1071 } 969 }
1072 CompileInParallel(isolate, this, results, thrower, &module_env); 970 CompileInParallel(isolate, this, results, thrower, &module_env);
1073 971
1074 for (size_t i = 0; i < results.size(); i++) { 972 for (size_t i = 0; i < results.size(); ++i) {
1075 temp_instance.function_code[i] = results[i]; 973 temp_instance.function_code[i] = results[i];
1076 } 974 }
1077 } else { 975 } else {
1078 CompileSequentially(isolate, this, temp_instance.function_code, thrower, 976 CompileSequentially(isolate, this, temp_instance.function_code, thrower,
1079 &module_env); 977 &module_env);
1080 } 978 }
1081 if (thrower->error()) return nothing; 979 if (thrower->error()) return nothing;
1082 980
1083 // At this point, compilation has completed. Update the code table. 981 // At this point, compilation has completed. Update the code table.
1084 for (size_t i = FLAG_skip_compiling_wasm_funcs; 982 for (size_t i = FLAG_skip_compiling_wasm_funcs;
(...skipping 11 matching lines...) Expand all
1096 // TODO(mtrofin): do we need to flush the cache here? 994 // TODO(mtrofin): do we need to flush the cache here?
1097 Assembler::FlushICache(isolate, code->instruction_start(), 995 Assembler::FlushICache(isolate, code->instruction_start(),
1098 code->instruction_size()); 996 code->instruction_size());
1099 } 997 }
1100 } 998 }
1101 999
1102 // Create the compiled module object, and populate with compiled functions 1000 // Create the compiled module object, and populate with compiled functions
1103 // and information needed at instantiation time. This object needs to be 1001 // and information needed at instantiation time. This object needs to be
1104 // serializable. Instantiation may occur off a deserialized version of this 1002 // serializable. Instantiation may occur off a deserialized version of this
1105 // object. 1003 // object.
1106 Handle<WasmCompiledModule> ret = WasmCompiledModule::New( 1004 Handle<WasmCompiledModule> ret =
1107 isolate, min_mem_pages, globals_size, mem_export, origin); 1005 WasmCompiledModule::New(isolate, min_mem_pages, globals_size, origin);
Mircea Trofin 2016/10/05 16:21:09 Weird, this isn't a change. Git cl format did this
titzer 2016/10/05 18:29:39 I removed a parameter that is no longer needed.
1108 ret->set_code_table(code_table); 1006 ret->set_code_table(code_table);
1109 if (!indirect_table.is_null()) { 1007 if (!indirect_table.is_null()) {
1110 ret->set_indirect_function_tables(indirect_table.ToHandleChecked()); 1008 ret->set_indirect_function_tables(indirect_table.ToHandleChecked());
1111 } 1009 }
1112 Handle<FixedArray> import_data = GetImportsData(factory, this);
1113 ret->set_import_data(import_data);
1114 1010
1115 // Compile exported function wrappers. 1011 // Create and set import data.
1116 int export_size = static_cast<int>(num_exported_functions); 1012 ret->set_imports(EncodeImports(factory, this));
1013
1014 // Create and set export data.
1015 int export_size = static_cast<int>(export_table.size());
1117 if (export_size > 0) { 1016 if (export_size > 0) {
1118 Handle<FixedArray> exports = factory->NewFixedArray(export_size, TENURED); 1017 Handle<FixedArray> exports = factory->NewFixedArray(export_size, TENURED);
1119 int index = -1; 1018 int index = 0;
1019 int func_index = 0;
1120 1020
1121 for (const WasmExport& exp : export_table) { 1021 for (const WasmExport& exp : export_table) {
1122 if (exp.kind != kExternalFunction) 1022 if (thrower->error()) return nothing;
1123 continue; // skip non-function exports. 1023 Handle<FixedArray> encoded_export =
1124 index++;
1125 Handle<FixedArray> export_data =
1126 factory->NewFixedArray(kWasmExportDataSize, TENURED); 1024 factory->NewFixedArray(kWasmExportDataSize, TENURED);
1127 FunctionSig* funcSig = functions[exp.index].sig;
1128 Handle<ByteArray> exportedSig =
1129 factory->NewByteArray(static_cast<int>(funcSig->parameter_count() +
1130 funcSig->return_count()),
1131 TENURED);
1132 exportedSig->copy_in(0,
1133 reinterpret_cast<const byte*>(funcSig->raw_data()),
1134 exportedSig->length());
1135 export_data->set(kExportedSignature, *exportedSig);
1136 WasmName str = GetName(exp.name_offset, exp.name_length); 1025 WasmName str = GetName(exp.name_offset, exp.name_length);
1137 Handle<String> name = factory->InternalizeUtf8String(str); 1026 Handle<String> name = factory->InternalizeUtf8String(str);
1138 Handle<Code> code = code_table->GetValueChecked<Code>(isolate, exp.index); 1027 encoded_export->set(kExportKind, Smi::FromInt(exp.kind));
1139 Handle<Code> export_code = compiler::CompileJSToWasmWrapper( 1028 encoded_export->set(kExportName, *name);
1140 isolate, &module_env, code, exp.index); 1029 encoded_export->set(kExportIndex,
1141 if (thrower->error()) return nothing; 1030 Smi::FromInt(static_cast<int>(exp.index)));
1142 export_data->set(kExportName, *name); 1031 exports->set(index, *encoded_export);
1143 export_data->set(kExportArity, 1032
1144 Smi::FromInt(static_cast<int>( 1033 switch (exp.kind) {
1145 functions[exp.index].sig->parameter_count()))); 1034 case kExternalFunction: {
1146 export_data->set(kExportedFunctionIndex, 1035 // Copy the signature and arity.
1147 Smi::FromInt(static_cast<int>(exp.index))); 1036 FunctionSig* funcSig = functions[exp.index].sig;
1148 exports->set(index, *export_data); 1037 Handle<ByteArray> exportedSig = factory->NewByteArray(
1149 code_table->set(static_cast<int>(functions.size() + index), *export_code); 1038 static_cast<int>(funcSig->parameter_count() +
1039 funcSig->return_count()),
1040 TENURED);
1041 exportedSig->copy_in(
1042 0, reinterpret_cast<const byte*>(funcSig->raw_data()),
1043 exportedSig->length());
1044 encoded_export->set(kExportedSignature, *exportedSig);
1045 encoded_export->set(
1046 kExportArity,
1047 Smi::FromInt(static_cast<int>(funcSig->parameter_count())));
1048
1049 // Compile a wrapper for an exported function.
1050 Handle<Code> code =
1051 code_table->GetValueChecked<Code>(isolate, exp.index);
1052 Handle<Code> export_code = compiler::CompileJSToWasmWrapper(
1053 isolate, &module_env, code, exp.index);
1054 int code_table_index =
1055 static_cast<int>(functions.size() + func_index);
1056 code_table->set(code_table_index, *export_code);
1057 encoded_export->set(kExportIndex, Smi::FromInt(code_table_index));
1058 func_index++;
1059 }
1060 case kExternalTable:
1061 // Nothing special about exported tables.
1062 break;
1063 case kExternalMemory:
1064 // Nothing special about exported tables.
1065 break;
1066 case kExternalGlobal: {
1067 // Encode the global type and the global offset.
1068 const WasmGlobal& global = globals[exp.index];
1069 encoded_export->set(
1070 kExportGlobalType,
1071 Smi::FromInt(WasmOpcodes::LocalTypeCodeFor(global.type)));
1072 encoded_export->set(kExportIndex, Smi::FromInt(global.offset));
1073 break;
1074 }
1075 }
1076 index++;
1150 } 1077 }
1151 ret->set_exports(exports); 1078 ret->set_exports(exports);
1152 } 1079 }
1153 1080
1081 // Create and set init data.
1082 int init_size = static_cast<int>(globals.size());
1083 if (init_size > 0) {
1084 Handle<FixedArray> inits = factory->NewFixedArray(init_size, TENURED);
1085 int index = 0;
1086 for (const WasmGlobal& global : globals) {
1087 // Skip globals that have no initializer (e.g. imported ones).
1088 if (global.init.kind == WasmInitExpr::kNone) continue;
1089
1090 Handle<FixedArray> encoded_init =
1091 factory->NewFixedArray(kWasmGlobalInitDataSize, TENURED);
1092 inits->set(index, *encoded_init);
1093 TRACE("init[%d].type = %s\n", index, WasmOpcodes::TypeName(global.type));
1094
1095 encoded_init->set(
1096 kGlobalInitType,
1097 Smi::FromInt(WasmOpcodes::LocalTypeCodeFor(global.type)));
1098 encoded_init->set(kGlobalInitIndex, Smi::FromInt(global.offset));
1099 EncodeInit(this, factory, encoded_init, kGlobalInitKind, kGlobalInitValue,
1100 global.init);
1101 index++;
1102 }
1103 inits->set_length(index);
1104 ret->set_inits(inits);
1105 }
1106
1154 // Record data for startup function. 1107 // Record data for startup function.
1155 if (start_function_index >= 0) { 1108 if (start_function_index >= 0) {
1156 HandleScope scope(isolate); 1109 HandleScope scope(isolate);
1157 Handle<FixedArray> startup_data = 1110 Handle<FixedArray> startup_data =
1158 factory->NewFixedArray(kWasmExportDataSize, TENURED); 1111 factory->NewFixedArray(kWasmExportDataSize, TENURED);
1159 startup_data->set(kExportArity, Smi::FromInt(0)); 1112 startup_data->set(kExportArity, Smi::FromInt(0));
1160 startup_data->set(kExportedFunctionIndex, 1113 startup_data->set(kExportIndex, Smi::FromInt(start_function_index));
1161 Smi::FromInt(start_function_index));
1162 ret->set_startup_function(startup_data); 1114 ret->set_startup_function(startup_data);
1163 } 1115 }
1164 1116
1165 // TODO(wasm): saving the module bytes for debugging is wasteful. We should 1117 // TODO(wasm): saving the module bytes for debugging is wasteful. We should
1166 // consider downloading this on-demand. 1118 // consider downloading this on-demand.
1167 { 1119 {
1168 size_t module_bytes_len = module_end - module_start; 1120 size_t module_bytes_len = module_end - module_start;
1169 DCHECK_LE(module_bytes_len, static_cast<size_t>(kMaxInt)); 1121 DCHECK_LE(module_bytes_len, static_cast<size_t>(kMaxInt));
1170 Vector<const uint8_t> module_bytes_vec(module_start, 1122 Vector<const uint8_t> module_bytes_vec(module_start,
1171 static_cast<int>(module_bytes_len)); 1123 static_cast<int>(module_bytes_len));
1172 Handle<String> module_bytes_string = 1124 Handle<String> module_bytes_string =
1173 factory->NewStringFromOneByte(module_bytes_vec, TENURED) 1125 factory->NewStringFromOneByte(module_bytes_vec, TENURED)
1174 .ToHandleChecked(); 1126 .ToHandleChecked();
1175 ret->set_module_bytes(module_bytes_string); 1127 ret->set_module_bytes(module_bytes_string);
1176 } 1128 }
1177 1129
1178 Handle<ByteArray> function_name_table = 1130 Handle<ByteArray> function_name_table =
1179 BuildFunctionNamesTable(isolate, module_env.module); 1131 BuildFunctionNamesTable(isolate, module_env.module);
1180 ret->set_function_names(function_name_table); 1132 ret->set_function_names(function_name_table);
1181 if (data_segments.size() > 0) SaveDataSegmentInfo(factory, this, ret); 1133 if (data_segments.size() > 0) SaveDataSegmentInfo(factory, this, ret);
1182 DCHECK_EQ(ret->default_mem_size(), temp_instance.mem_size); 1134 DCHECK_EQ(ret->default_mem_size(), temp_instance.mem_size);
1183 return ret; 1135 return ret;
1184 } 1136 }
1185 1137
1138 // A helper class to simplify instantiating a module from a compiled module.
1139 // It closes over the {Isolate}, the {ErrorThrower}, the {WasmCompiledModule},
1140 // etc.
1141 class WasmModuleInstantiateHelper {
Mircea Trofin 2016/10/05 16:21:08 If not *Pipeline, how about WasmModuleInstanceBuil
titzer 2016/10/05 18:29:39 WasmInstanceBuilder FTW
1142 public:
1143 Isolate* isolate_;
Mircea Trofin 2016/10/05 16:21:09 since this is a class, could you make these privat
titzer 2016/10/05 18:29:39 Since this is entirely contained in the CC file (a
Mircea Trofin 2016/10/05 18:41:00 Consistency with everywhere else in the codebase?
1144 ErrorThrower* thrower_;
1145 Handle<JSObject> module_object_;
1146 Handle<JSReceiver> ffi_;
1147 Handle<JSArrayBuffer> memory_;
1148 Handle<WasmCompiledModule> compiled_module_;
1149
1150 WasmModuleInstantiateHelper(Isolate* isolate, ErrorThrower* thrower,
1151 Handle<JSObject> module_object,
1152 Handle<JSReceiver> ffi,
1153 Handle<JSArrayBuffer> memory)
1154 : isolate_(isolate),
1155 thrower_(thrower),
1156 module_object_(module_object),
1157 ffi_(ffi),
1158 memory_(memory) {}
1159
1160 // Helper routine to print out errors with imports (FFI).
1161 MaybeHandle<JSFunction> ReportFFIError(const char* error, uint32_t index,
1162 Handle<String> module_name,
1163 MaybeHandle<String> function_name) {
1164 Handle<String> function_name_handle;
1165 if (function_name.ToHandle(&function_name_handle)) {
1166 thrower_->Error("Import #%d module=\"%.*s\" function=\"%.*s\" error: %s",
1167 index, module_name->length(),
1168 module_name->ToCString().get(),
1169 function_name_handle->length(),
1170 function_name_handle->ToCString().get(), error);
1171 } else {
1172 thrower_->Error("Import #%d module=\"%.*s\" error: %s", index,
1173 module_name->length(), module_name->ToCString().get(),
1174 error);
1175 }
1176 thrower_->Error("Import ");
1177 return MaybeHandle<JSFunction>();
1178 }
1179
1180 // Look up an import value in the {ffi_} object.
1181 MaybeHandle<Object> LookupImport(uint32_t index, Handle<String> module_name,
1182 MaybeHandle<String> import_name) {
1183 if (ffi_.is_null()) {
1184 return ReportFFIError("FFI is not an object", index, module_name,
1185 import_name);
1186 }
1187
1188 // Look up the module first.
1189 MaybeHandle<Object> result = Object::GetProperty(ffi_, module_name);
1190 if (result.is_null()) {
1191 return ReportFFIError("module not found", index, module_name,
1192 import_name);
1193 }
1194
1195 Handle<Object> module = result.ToHandleChecked();
1196
1197 if (!import_name.is_null()) {
1198 // Look up the value in the module.
1199 if (!module->IsJSReceiver()) {
1200 return ReportFFIError("module is not an object or function", index,
1201 module_name, import_name);
1202 }
1203
1204 result = Object::GetProperty(module, import_name.ToHandleChecked());
1205 if (result.is_null()) {
1206 return ReportFFIError("import not found", index, module_name,
1207 import_name);
1208 }
1209 } else {
1210 // No function specified. Use the "default export".
1211 result = module;
1212 }
1213
1214 return result;
1215 }
1216
1217 // Load data segments into the memory.
1218 void LoadDataSegments(Address mem_addr, size_t mem_size) {
1219 CHECK(compiled_module_->has_data_segments() ==
1220 compiled_module_->has_data_segments_info());
1221
1222 // If we have neither, we're done.
1223 if (!compiled_module_->has_data_segments()) return;
1224
1225 Handle<ByteArray> data = compiled_module_->data_segments();
1226 Handle<FixedArray> segments = compiled_module_->data_segments_info();
1227
1228 uint32_t last_extraction_pos = 0;
1229 for (int i = 0; i < segments->length(); ++i) {
1230 Handle<ByteArray> segment =
1231 Handle<ByteArray>(ByteArray::cast(segments->get(i)));
1232 uint32_t dest_addr =
1233 static_cast<uint32_t>(segment->get_int(kDestAddrValue));
1234 uint32_t source_size =
1235 static_cast<uint32_t>(segment->get_int(kSourceSize));
1236 CHECK_LT(dest_addr, mem_size);
1237 CHECK_LE(source_size, mem_size);
1238 CHECK_LE(dest_addr, mem_size - source_size);
1239 byte* addr = mem_addr + dest_addr;
1240 data->copy_out(last_extraction_pos, addr, source_size);
1241 last_extraction_pos += source_size;
1242 }
1243 }
1244
1245 Handle<Code> CompileImportWrapper(int index, Handle<FixedArray> data,
1246 Handle<JSReceiver> target,
1247 Handle<String> module_name,
1248 MaybeHandle<String> import_name) {
1249 // TODO(mtrofin): this is an uint32_t, actually. We should rationalize
1250 // it when we rationalize signed/unsigned stuff.
1251 int ret_count = Smi::cast(data->get(kOutputCount))->value();
1252 CHECK_GE(ret_count, 0);
1253 Handle<ByteArray> sig_data =
1254 data->GetValueChecked<ByteArray>(isolate_, kSignature);
1255 int sig_data_size = sig_data->length();
1256 int param_count = sig_data_size - ret_count;
1257 CHECK(param_count >= 0);
1258
1259 Handle<Code> code;
1260 bool isMatch = false;
1261 Handle<Code> export_wrapper_code;
1262 if (target->IsJSFunction()) {
1263 Handle<JSFunction> func = Handle<JSFunction>::cast(target);
1264 export_wrapper_code = handle(func->code());
1265 if (export_wrapper_code->kind() == Code::JS_TO_WASM_FUNCTION) {
1266 int exported_param_count =
1267 Smi::cast(func->GetInternalField(kInternalArity))->value();
1268 Handle<ByteArray> exportedSig = Handle<ByteArray>(
1269 ByteArray::cast(func->GetInternalField(kInternalSignature)));
1270 if (exported_param_count == param_count &&
1271 exportedSig->length() == sig_data->length() &&
1272 memcmp(exportedSig->data(), sig_data->data(),
1273 exportedSig->length()) == 0) {
1274 isMatch = true;
1275 }
1276 }
1277 }
1278 if (isMatch) {
1279 int wasm_count = 0;
1280 int const mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET);
1281 for (RelocIterator it(*export_wrapper_code, mask); !it.done();
1282 it.next()) {
1283 RelocInfo* rinfo = it.rinfo();
1284 Address target_address = rinfo->target_address();
1285 Code* target = Code::GetCodeFromTargetAddress(target_address);
1286 if (target->kind() == Code::WASM_FUNCTION) {
1287 ++wasm_count;
1288 code = handle(target);
1289 }
1290 }
1291 DCHECK(wasm_count == 1);
1292 return code;
1293 } else {
1294 // Copy the signature to avoid a raw pointer into a heap object when
1295 // GC can happen.
1296 Zone zone(isolate_->allocator());
1297 MachineRepresentation* reps =
1298 zone.NewArray<MachineRepresentation>(sig_data_size);
1299 memcpy(reps, sig_data->data(),
1300 sizeof(MachineRepresentation) * sig_data_size);
1301 FunctionSig sig(ret_count, param_count, reps);
1302
1303 return compiler::CompileWasmToJSWrapper(isolate_, target, &sig, index,
1304 module_name, import_name);
1305 }
1306 }
1307
1308 void WriteGlobalValue(MaybeHandle<JSArrayBuffer> globals, uint32_t offset,
1309 Handle<Object> value, int type) {
1310 double num;
Mircea Trofin 2016/10/05 16:21:09 double num = 0.0
titzer 2016/10/05 18:29:39 Done.
1311 if (value->IsSmi()) {
1312 num = Smi::cast(*value)->value();
1313 } else if (value->IsHeapNumber()) {
1314 num = HeapNumber::cast(*value)->value();
1315 } else {
1316 UNREACHABLE();
1317 }
1318 TRACE("init [globals+%u] = %lf, type = %d\n", offset, num, type);
1319 byte* ptr = raw_buffer_ptr(globals, offset);
1320 switch (type) {
1321 case kLocalI32:
1322 *reinterpret_cast<int32_t*>(ptr) = static_cast<int32_t>(num);
1323 break;
1324 case kLocalI64:
1325 // TODO(titzer): initialization of imported i64 globals.
1326 UNREACHABLE();
1327 break;
1328 case kLocalF32:
1329 *reinterpret_cast<float*>(ptr) = static_cast<float>(num);
1330 break;
1331 case kLocalF64:
1332 *reinterpret_cast<double*>(ptr) = num;
1333 break;
1334 default:
1335 UNREACHABLE();
1336 }
1337 }
1338
1339 // Process the imports, including functions, tables, globals, and memory, in
1340 // order, loading them from the {ffi_} object. Returns the number of imported
1341 // functions.
1342 int ProcessImports(MaybeHandle<JSArrayBuffer> globals,
1343 Handle<FixedArray> code_table) {
1344 int num_imported_functions = 0;
1345 if (!compiled_module_->has_imports()) return num_imported_functions;
1346
1347 Handle<FixedArray> imports = compiled_module_->imports();
1348 for (int index = 0; index < imports->length(); index++) {
Mircea Trofin 2016/10/05 16:21:09 ++index - for consistency with the file
titzer 2016/10/05 18:29:39 Done.
1349 Handle<FixedArray> data =
1350 imports->GetValueChecked<FixedArray>(isolate_, index);
1351
1352 Handle<String> module_name =
1353 data->GetValueChecked<String>(isolate_, kModuleName);
1354 MaybeHandle<String> function_name =
1355 data->GetValue<String>(isolate_, kFunctionName);
1356
1357 MaybeHandle<Object> result =
1358 LookupImport(index, module_name, function_name);
1359 if (thrower_->error()) return 0;
Mircea Trofin 2016/10/05 16:21:09 should it return -1, because error?
titzer 2016/10/05 18:29:39 Done.
1360
1361 WasmExternalKind kind = static_cast<WasmExternalKind>(
1362 Smi::cast(data->get(kImportKind))->value());
1363 switch (kind) {
1364 case kExternalFunction: {
1365 // Function imports must be callable.
1366 Handle<Object> function = result.ToHandleChecked();
1367 if (!function->IsCallable()) {
1368 ReportFFIError("function import requires a callable", index,
1369 module_name, function_name);
1370 return 0;
Mircea Trofin 2016/10/05 16:21:09 same here
titzer 2016/10/05 18:29:39 Done.
1371 }
1372
1373 Handle<Code> import_wrapper = CompileImportWrapper(
1374 index, data, Handle<JSReceiver>::cast(function), module_name,
1375 function_name);
1376 int func_index = Smi::cast(data->get(kImportIndex))->value();
1377 code_table->set(func_index, *import_wrapper);
1378 RecordStats(isolate_, *import_wrapper);
1379 num_imported_functions++;
1380 break;
1381 }
1382 case kExternalTable:
1383 // TODO(titzer): Table imports must be a WebAssembly.Table.
1384 break;
1385 case kExternalMemory:
1386 // TODO(titzer): Memory imports must be a WebAssembly.Memory.
1387 break;
1388 case kExternalGlobal: {
1389 // Global imports are converted to numbers and written into the
1390 // {globals} array buffer.
1391 Handle<Object> object = result.ToHandleChecked();
1392 MaybeHandle<Object> number = Object::ToNumber(object);
1393 if (number.is_null()) {
1394 ReportFFIError("global import could not be converted to number",
1395 index, module_name, function_name);
1396 return 0;
Mircea Trofin 2016/10/05 16:21:09 same here
titzer 2016/10/05 18:29:39 Done.
1397 }
1398 Handle<Object> val = number.ToHandleChecked();
1399 int offset = Smi::cast(data->get(kImportIndex))->value();
1400 int type = Smi::cast(data->get(kImportGlobalType))->value();
1401 WriteGlobalValue(globals, offset, val, type);
1402 break;
1403 }
1404 default:
1405 UNREACHABLE();
1406 break;
1407 }
1408 }
1409 return num_imported_functions;
1410 }
1411
1412 // Process initialization of globals.
1413 void ProcessInits(MaybeHandle<JSArrayBuffer> globals) {
1414 if (!compiled_module_->has_inits()) return;
1415
1416 Handle<FixedArray> inits = compiled_module_->inits();
1417 for (int index = 0; index < inits->length(); index++) {
Mircea Trofin 2016/10/05 16:21:09 ++index, for consistency
titzer 2016/10/05 18:29:38 Done.
1418 Handle<FixedArray> data =
1419 inits->GetValueChecked<FixedArray>(isolate_, index);
1420
1421 int offset = Smi::cast(data->get(kGlobalInitIndex))->value();
1422 Handle<Object> val(data->get(kGlobalInitValue), isolate_);
1423 int type = Smi::cast(data->get(kGlobalInitType))->value();
1424 if (Smi::cast(data->get(kGlobalInitKind))->value() == 0) {
1425 // Initialize with a constant.
1426 WriteGlobalValue(globals, offset, val, type);
1427 } else {
1428 // Initialize with another global.
1429 int old_offset = Smi::cast(*val)->value();
1430 TRACE("init [globals+%u] = [globals+%d]\n", offset, old_offset);
1431 int size = 4;
Mircea Trofin 2016/10/05 16:21:09 what's "4"?
titzer 2016/10/05 18:29:38 Done.
1432 if (type == kLocalI64 || type == kLocalF64) size = 8;
Mircea Trofin 2016/10/05 16:21:09 what's "8"? could we set size to one of the size
titzer 2016/10/05 18:29:38 Done.
1433 memcpy(raw_buffer_ptr(globals, offset),
1434 raw_buffer_ptr(globals, old_offset), size);
1435 }
1436 }
1437 }
1438
1439 // Allocate memory for a module instance as a new JSArrayBuffer.
1440 Handle<JSArrayBuffer> AllocateMemory(uint32_t min_mem_pages) {
1441 if (min_mem_pages > WasmModule::kMaxMemPages) {
1442 thrower_->Error("Out of memory: wasm memory too large");
1443 return Handle<JSArrayBuffer>::null();
1444 }
1445 Handle<JSArrayBuffer> mem_buffer =
1446 NewArrayBuffer(isolate_, min_mem_pages * WasmModule::kPageSize);
1447
1448 if (mem_buffer.is_null()) {
1449 thrower_->Error("Out of memory: wasm memory");
1450 }
1451 return mem_buffer;
1452 }
1453
1454 // Process the exports, creating wrappers for functions, tables, memories,
1455 // and globals.
1456 void ProcessExports(MaybeHandle<JSArrayBuffer> globals,
1457 Handle<FixedArray> code_table,
1458 Handle<JSObject> instance) {
1459 if (!compiled_module_->has_exports()) return;
1460
1461 Handle<JSObject> exports_object = instance;
1462 if (compiled_module_->origin() == kWasmOrigin) {
1463 // Create the "exports" object.
1464 Handle<JSFunction> object_function = Handle<JSFunction>(
1465 isolate_->native_context()->object_function(), isolate_);
1466 exports_object =
1467 isolate_->factory()->NewJSObject(object_function, TENURED);
1468 Handle<String> exports_name =
1469 isolate_->factory()->InternalizeUtf8String("exports");
1470 JSObject::AddProperty(instance, exports_name, exports_object, READ_ONLY);
1471 }
1472
1473 PropertyDescriptor desc;
1474 desc.set_writable(false);
1475
1476 Handle<FixedArray> exports = compiled_module_->exports();
1477
1478 for (int i = 0; i < exports->length(); ++i) {
1479 Handle<FixedArray> export_data =
1480 exports->GetValueChecked<FixedArray>(isolate_, i);
1481 Handle<String> name =
1482 export_data->GetValueChecked<String>(isolate_, kExportName);
1483 WasmExternalKind kind = static_cast<WasmExternalKind>(
1484 Smi::cast(export_data->get(kExportKind))->value());
1485 switch (kind) {
1486 case kExternalFunction: {
1487 // Wrap and export the code as a JSFunction.
1488 int code_table_index =
1489 Smi::cast(export_data->get(kExportIndex))->value();
1490 Handle<Code> export_code =
1491 code_table->GetValueChecked<Code>(isolate_, code_table_index);
1492 int arity = Smi::cast(export_data->get(kExportArity))->value();
1493 MaybeHandle<ByteArray> signature =
1494 export_data->GetValue<ByteArray>(isolate_, kExportedSignature);
1495 desc.set_value(WrapExportCodeAsJSFunction(
1496 isolate_, export_code, name, arity, signature, instance));
1497 break;
1498 }
1499 case kExternalTable:
1500 // TODO(titzer): create a WebAssembly.Table instance.
1501 // TODO(titzer): should it have the same identity as an import?
1502 break;
1503 case kExternalMemory: {
1504 // TODO(titzer): should memory have the same identity as an
1505 // import?
1506 Handle<JSArrayBuffer> buffer =
1507 Handle<JSArrayBuffer>(JSArrayBuffer::cast(
1508 instance->GetInternalField(kWasmMemArrayBuffer)));
1509 desc.set_value(
1510 WasmJs::CreateWasmMemoryObject(isolate_, buffer, false, 0));
1511 break;
1512 }
1513 case kExternalGlobal: {
1514 // Export the value of the global variable as a number.
1515 int offset = Smi::cast(export_data->get(kExportIndex))->value();
1516 byte* ptr = raw_buffer_ptr(globals, offset);
1517 double num = 0;
1518 switch (Smi::cast(export_data->get(kExportGlobalType))->value()) {
1519 case kLocalI32:
1520 num = *reinterpret_cast<int32_t*>(ptr);
1521 break;
1522 case kLocalF32:
1523 num = *reinterpret_cast<float*>(ptr);
1524 break;
1525 case kLocalF64:
1526 num = *reinterpret_cast<double*>(ptr);
1527 break;
1528 default:
1529 UNREACHABLE();
1530 }
1531 desc.set_value(isolate_->factory()->NewNumber(num));
1532 break;
1533 }
1534 default:
1535 UNREACHABLE();
1536 break;
1537 }
1538
1539 Maybe<bool> status = JSReceiver::DefineOwnProperty(
1540 isolate_, exports_object, name, &desc, Object::THROW_ON_ERROR);
1541 if (!status.IsJust()) {
1542 thrower_->Error("export of %.*s failed.", name->length(),
1543 name->ToCString().get());
1544 return;
1545 }
1546 }
1547 }
1548
1549 // Instantiate a module, creating an instance.
1550 MaybeHandle<JSObject> Instantiate() {
1551 MaybeHandle<JSObject> nothing;
1552 HistogramTimerScope wasm_instantiate_module_time_scope(
1553 isolate_->counters()->wasm_instantiate_module_time());
1554 Factory* factory = isolate_->factory();
1555
1556 //--------------------------------------------------------------------------
1557 // Reuse the compiled module (if no owner), otherwise clone.
1558 //--------------------------------------------------------------------------
1559 Handle<FixedArray> code_table;
1560 Handle<FixedArray> old_code_table;
1561 Handle<JSObject> owner;
1562 // If we don't clone, this will be null(). Otherwise, this will
1563 // be a weak link to the original. If we lose the original to GC,
1564 // this will be a cleared. We'll link the instances chain last.
1565 MaybeHandle<WeakCell> link_to_original;
1566
1567 TRACE("Starting new module instantiation\n");
1568 {
1569 Handle<WasmCompiledModule> original(
1570 WasmCompiledModule::cast(module_object_->GetInternalField(0)),
1571 isolate_);
1572 // Always make a new copy of the code_table, since the old_code_table
1573 // may still have placeholders for imports.
1574 old_code_table = original->code_table();
1575 code_table = factory->CopyFixedArray(old_code_table);
1576
1577 if (original->has_weak_owning_instance()) {
1578 WeakCell* tmp = original->ptr_to_weak_owning_instance();
1579 DCHECK(!tmp->cleared());
1580 // There is already an owner, clone everything.
1581 owner = Handle<JSObject>(JSObject::cast(tmp->value()), isolate_);
1582 // Insert the latest clone in front.
1583 TRACE("Cloning from %d\n", original->instance_id());
1584 compiled_module_ = WasmCompiledModule::Clone(isolate_, original);
1585 // Replace the strong reference to point to the new instance here.
1586 // This allows any of the other instances, including the original,
1587 // to be collected.
1588 module_object_->SetInternalField(0, *compiled_module_);
1589 compiled_module_->set_weak_module_object(
1590 original->weak_module_object());
1591 link_to_original = factory->NewWeakCell(original);
1592 // Don't link to original here. We remember the original
1593 // as a weak link. If that link isn't clear by the time we finish
1594 // instantiating this instance, then we link it at that time.
1595 compiled_module_->reset_weak_next_instance();
1596
1597 // Clone the code for WASM functions and exports.
1598 for (int i = 0; i < code_table->length(); ++i) {
1599 Handle<Code> orig_code =
1600 code_table->GetValueChecked<Code>(isolate_, i);
1601 switch (orig_code->kind()) {
1602 case Code::WASM_TO_JS_FUNCTION:
1603 // Imports will be overwritten with newly compiled wrappers.
1604 break;
1605 case Code::JS_TO_WASM_FUNCTION:
1606 case Code::WASM_FUNCTION: {
1607 Handle<Code> code = factory->CopyCode(orig_code);
1608 code_table->set(i, *code);
1609 break;
1610 }
1611 default:
1612 UNREACHABLE();
1613 }
1614 }
1615 RecordStats(isolate_, code_table);
1616 } else {
1617 // There was no owner, so we can reuse the original.
1618 compiled_module_ = original;
1619 TRACE("Reusing existing instance %d\n",
1620 compiled_module_->instance_id());
1621 }
1622 compiled_module_->set_code_table(code_table);
1623 }
1624
1625 //--------------------------------------------------------------------------
1626 // Allocate the instance object.
1627 //--------------------------------------------------------------------------
1628 Handle<Map> map = factory->NewMap(
1629 JS_OBJECT_TYPE,
1630 JSObject::kHeaderSize + kWasmModuleInternalFieldCount * kPointerSize);
1631 Handle<JSObject> instance = factory->NewJSObjectFromMap(map, TENURED);
1632 instance->SetInternalField(kWasmModuleCodeTable, *code_table);
1633
1634 //--------------------------------------------------------------------------
1635 // Set up the memory for the new instance.
1636 //--------------------------------------------------------------------------
1637 MaybeHandle<JSArrayBuffer> old_memory;
1638 // TODO(titzer): handle imported memory properly.
1639
1640 uint32_t min_mem_pages = compiled_module_->min_memory_pages();
1641 isolate_->counters()->wasm_min_mem_pages_count()->AddSample(min_mem_pages);
1642 // TODO(wasm): re-enable counter for max_mem_pages when we use that field.
1643
1644 if (memory_.is_null() && min_mem_pages > 0) {
1645 memory_ = AllocateMemory(min_mem_pages);
1646 if (memory_.is_null()) return nothing; // failed to allocate memory
1647 }
1648
1649 if (!memory_.is_null()) {
1650 instance->SetInternalField(kWasmMemArrayBuffer, *memory_);
1651 Address mem_start = static_cast<Address>(memory_->backing_store());
1652 uint32_t mem_size =
1653 static_cast<uint32_t>(memory_->byte_length()->Number());
1654 LoadDataSegments(mem_start, mem_size);
1655
1656 uint32_t old_mem_size = compiled_module_->has_heap()
1657 ? compiled_module_->mem_size()
1658 : compiled_module_->default_mem_size();
1659 Address old_mem_start =
1660 compiled_module_->has_heap()
1661 ? static_cast<Address>(compiled_module_->heap()->backing_store())
1662 : nullptr;
1663 RelocateInstanceCode(instance, old_mem_start, mem_start, old_mem_size,
1664 mem_size);
1665 compiled_module_->set_heap(memory_);
1666 }
1667
1668 //--------------------------------------------------------------------------
1669 // Set up the globals for the new instance.
1670 //--------------------------------------------------------------------------
1671 MaybeHandle<JSArrayBuffer> old_globals;
1672 MaybeHandle<JSArrayBuffer> globals;
1673 uint32_t globals_size = compiled_module_->globals_size();
1674 if (globals_size > 0) {
1675 Handle<JSArrayBuffer> global_buffer =
1676 NewArrayBuffer(isolate_, globals_size);
1677 globals = global_buffer;
1678 if (globals.is_null()) {
1679 thrower_->Error("Out of memory: wasm globals");
1680 return nothing;
1681 }
1682 Address old_address =
1683 owner.is_null() ? nullptr : GetGlobalStartAddressFromCodeTemplate(
1684 *factory->undefined_value(),
1685 JSObject::cast(*owner));
1686 RelocateGlobals(instance, old_address,
1687 static_cast<Address>(global_buffer->backing_store()));
1688 instance->SetInternalField(kWasmGlobalsArrayBuffer, *global_buffer);
1689 }
1690
1691 //--------------------------------------------------------------------------
1692 // Process the imports for the module.
1693 //--------------------------------------------------------------------------
1694 int num_imported_functions = ProcessImports(globals, code_table);
1695
1696 //--------------------------------------------------------------------------
1697 // Process the initialization for the module's globals.
1698 //--------------------------------------------------------------------------
1699 ProcessInits(globals);
1700
1701 //--------------------------------------------------------------------------
1702 // Set up the debug support for the new instance.
1703 //--------------------------------------------------------------------------
1704 // TODO(wasm): avoid referencing this stuff from the instance, use it off
1705 // the compiled module instead. See the following 3 assignments:
1706 if (compiled_module_->has_module_bytes()) {
1707 instance->SetInternalField(kWasmModuleBytesString,
1708 compiled_module_->ptr_to_module_bytes());
1709 }
1710
1711 if (compiled_module_->has_function_names()) {
1712 instance->SetInternalField(kWasmFunctionNamesArray,
1713 compiled_module_->ptr_to_function_names());
1714 }
1715
1716 {
1717 Handle<Object> handle = factory->NewNumber(num_imported_functions);
1718 instance->SetInternalField(kWasmNumImportedFunctions, *handle);
1719 }
1720
1721 //--------------------------------------------------------------------------
1722 // Set up the runtime support for the new instance.
1723 //--------------------------------------------------------------------------
1724 Handle<WeakCell> weak_link = factory->NewWeakCell(instance);
1725
1726 for (int i = num_imported_functions + FLAG_skip_compiling_wasm_funcs;
1727 i < code_table->length(); ++i) {
1728 Handle<Code> code = code_table->GetValueChecked<Code>(isolate_, i);
1729 if (code->kind() == Code::WASM_FUNCTION) {
1730 Handle<FixedArray> deopt_data = factory->NewFixedArray(2, TENURED);
1731 deopt_data->set(0, *weak_link);
1732 deopt_data->set(1, Smi::FromInt(static_cast<int>(i)));
1733 deopt_data->set_length(2);
1734 code->set_deoptimization_data(*deopt_data);
1735 }
1736 }
1737
1738 //--------------------------------------------------------------------------
1739 // Set up the indirect function tables for the new instance.
1740 //--------------------------------------------------------------------------
1741 {
1742 std::vector<Handle<Code>> functions(
1743 static_cast<size_t>(code_table->length()));
1744 for (int i = 0; i < code_table->length(); ++i) {
1745 functions[i] = code_table->GetValueChecked<Code>(isolate_, i);
1746 }
1747
1748 if (compiled_module_->has_indirect_function_tables()) {
1749 Handle<FixedArray> indirect_tables_template =
1750 compiled_module_->indirect_function_tables();
1751 Handle<FixedArray> to_replace =
1752 owner.is_null() ? indirect_tables_template
1753 : handle(FixedArray::cast(owner->GetInternalField(
1754 kWasmModuleFunctionTable)));
1755 Handle<FixedArray> indirect_tables = SetupIndirectFunctionTable(
1756 isolate_, code_table, indirect_tables_template, to_replace);
1757 for (int i = 0; i < indirect_tables->length(); ++i) {
1758 Handle<FixedArray> metadata =
1759 indirect_tables->GetValueChecked<FixedArray>(isolate_, i);
1760 uint32_t size = Smi::cast(metadata->get(kSize))->value();
1761 Handle<FixedArray> table =
1762 metadata->GetValueChecked<FixedArray>(isolate_, kTable);
1763 PopulateFunctionTable(table, size, &functions);
1764 }
1765 instance->SetInternalField(kWasmModuleFunctionTable, *indirect_tables);
1766 }
1767 }
1768
1769 //--------------------------------------------------------------------------
1770 // Set up the exports object for the new instance.
1771 //--------------------------------------------------------------------------
1772 ProcessExports(globals, code_table, instance);
1773
1774 if (num_imported_functions > 0 || !owner.is_null()) {
1775 // If the code was cloned, or new imports were compiled, patch.
1776 PatchDirectCalls(old_code_table, code_table, num_imported_functions);
1777 }
1778
1779 FlushICache(isolate_, code_table);
1780
1781 //--------------------------------------------------------------------------
1782 // Run the start function if one was specified.
1783 //--------------------------------------------------------------------------
1784 if (compiled_module_->has_startup_function()) {
1785 Handle<FixedArray> startup_data = compiled_module_->startup_function();
1786 HandleScope scope(isolate_);
1787 int32_t start_index =
1788 startup_data->GetValueChecked<Smi>(isolate_, kExportIndex)->value();
1789 Handle<Code> startup_code =
1790 code_table->GetValueChecked<Code>(isolate_, start_index);
1791 int arity = Smi::cast(startup_data->get(kExportArity))->value();
1792 MaybeHandle<ByteArray> startup_signature =
1793 startup_data->GetValue<ByteArray>(isolate_, kExportedSignature);
1794 Handle<JSFunction> startup_fct = WrapExportCodeAsJSFunction(
1795 isolate_, startup_code, factory->InternalizeUtf8String("start"),
1796 arity, startup_signature, instance);
1797 RecordStats(isolate_, *startup_code);
1798 // Call the JS function.
1799 Handle<Object> undefined = factory->undefined_value();
1800 MaybeHandle<Object> retval =
1801 Execution::Call(isolate_, startup_fct, undefined, 0, nullptr);
1802
1803 if (retval.is_null()) {
1804 thrower_->Error("WASM.instantiateModule(): start function failed");
1805 return nothing;
1806 }
1807 }
1808
1809 DCHECK(wasm::IsWasmObject(*instance));
1810
1811 {
1812 Handle<WeakCell> link_to_owner = factory->NewWeakCell(instance);
1813
1814 Handle<Object> global_handle =
1815 isolate_->global_handles()->Create(*instance);
1816 Handle<WeakCell> link_to_clone = factory->NewWeakCell(compiled_module_);
1817 {
1818 DisallowHeapAllocation no_gc;
1819 compiled_module_->set_weak_owning_instance(link_to_owner);
1820 Handle<WeakCell> next;
1821 if (link_to_original.ToHandle(&next) && !next->cleared()) {
1822 WasmCompiledModule* original =
1823 WasmCompiledModule::cast(next->value());
1824 DCHECK(original->has_weak_owning_instance());
1825 DCHECK(!original->weak_owning_instance()->cleared());
1826 compiled_module_->set_weak_next_instance(next);
1827 original->set_weak_prev_instance(link_to_clone);
1828 }
1829
1830 compiled_module_->set_weak_owning_instance(link_to_owner);
1831 instance->SetInternalField(kWasmCompiledModule, *compiled_module_);
1832 GlobalHandles::MakeWeak(global_handle.location(),
1833 global_handle.location(), &InstanceFinalizer,
1834 v8::WeakCallbackType::kFinalizer);
1835 }
1836 }
1837 TRACE("Finishing instance %d\n", compiled_module_->instance_id());
1838 TRACE_CHAIN(WasmCompiledModule::cast(module_object_->GetInternalField(0)));
1839 return instance;
1840 }
1841 };
1842
1186 // Instantiates a WASM module, creating a WebAssembly.Instance from a 1843 // Instantiates a WASM module, creating a WebAssembly.Instance from a
1187 // WebAssembly.Module. 1844 // WebAssembly.Module.
1188 MaybeHandle<JSObject> WasmModule::Instantiate(Isolate* isolate, 1845 MaybeHandle<JSObject> WasmModule::Instantiate(Isolate* isolate,
1189 ErrorThrower* thrower, 1846 ErrorThrower* thrower,
1190 Handle<JSObject> module_object, 1847 Handle<JSObject> module_object,
1191 Handle<JSReceiver> ffi, 1848 Handle<JSReceiver> ffi,
1192 Handle<JSArrayBuffer> memory) { 1849 Handle<JSArrayBuffer> memory) {
1193 MaybeHandle<JSObject> nothing; 1850 WasmModuleInstantiateHelper helper(isolate, thrower, module_object, ffi,
1194 HistogramTimerScope wasm_instantiate_module_time_scope( 1851 memory);
1195 isolate->counters()->wasm_instantiate_module_time()); 1852 return helper.Instantiate();
1196 Factory* factory = isolate->factory();
1197
1198 //--------------------------------------------------------------------------
1199 // Reuse the compiled module (if no owner), otherwise clone.
1200 //--------------------------------------------------------------------------
1201 Handle<WasmCompiledModule> compiled_module;
1202 Handle<FixedArray> code_table;
1203 Handle<FixedArray> old_code_table;
1204 Handle<JSObject> owner;
1205 // If we don't clone, this will be null(). Otherwise, this will
1206 // be a weak link to the original. If we lose the original to GC,
1207 // this will be a cleared. We'll link the instances chain last.
1208 MaybeHandle<WeakCell> link_to_original;
1209
1210 TRACE("Starting new module instantiation\n");
1211 {
1212 Handle<WasmCompiledModule> original(
1213 WasmCompiledModule::cast(module_object->GetInternalField(0)), isolate);
1214 // Always make a new copy of the code_table, since the old_code_table
1215 // may still have placeholders for imports.
1216 old_code_table = original->code_table();
1217 code_table = factory->CopyFixedArray(old_code_table);
1218
1219 if (original->has_weak_owning_instance()) {
1220 WeakCell* tmp = original->ptr_to_weak_owning_instance();
1221 DCHECK(!tmp->cleared());
1222 // There is already an owner, clone everything.
1223 owner = Handle<JSObject>(JSObject::cast(tmp->value()), isolate);
1224 // Insert the latest clone in front.
1225 TRACE("Cloning from %d\n", original->instance_id());
1226 compiled_module = WasmCompiledModule::Clone(isolate, original);
1227 // Replace the strong reference to point to the new instance here.
1228 // This allows any of the other instances, including the original,
1229 // to be collected.
1230 module_object->SetInternalField(0, *compiled_module);
1231 compiled_module->set_weak_module_object(original->weak_module_object());
1232 link_to_original = factory->NewWeakCell(original);
1233 // Don't link to original here. We remember the original
1234 // as a weak link. If that link isn't clear by the time we finish
1235 // instantiating this instance, then we link it at that time.
1236 compiled_module->reset_weak_next_instance();
1237
1238 // Clone the code for WASM functions and exports.
1239 for (int i = 0; i < code_table->length(); ++i) {
1240 Handle<Code> orig_code = code_table->GetValueChecked<Code>(isolate, i);
1241 switch (orig_code->kind()) {
1242 case Code::WASM_TO_JS_FUNCTION:
1243 // Imports will be overwritten with newly compiled wrappers.
1244 break;
1245 case Code::JS_TO_WASM_FUNCTION:
1246 case Code::WASM_FUNCTION: {
1247 Handle<Code> code = factory->CopyCode(orig_code);
1248 code_table->set(i, *code);
1249 break;
1250 }
1251 default:
1252 UNREACHABLE();
1253 }
1254 }
1255 RecordStats(isolate, code_table);
1256 } else {
1257 // There was no owner, so we can reuse the original.
1258 compiled_module = original;
1259 TRACE("Reusing existing instance %d\n", compiled_module->instance_id());
1260 }
1261 compiled_module->set_code_table(code_table);
1262 }
1263
1264 //--------------------------------------------------------------------------
1265 // Allocate the instance object.
1266 //--------------------------------------------------------------------------
1267 Handle<Map> map = factory->NewMap(
1268 JS_OBJECT_TYPE,
1269 JSObject::kHeaderSize + kWasmModuleInternalFieldCount * kPointerSize);
1270 Handle<JSObject> instance = factory->NewJSObjectFromMap(map, TENURED);
1271 instance->SetInternalField(kWasmModuleCodeTable, *code_table);
1272
1273 //--------------------------------------------------------------------------
1274 // Set up the memory for the new instance.
1275 //--------------------------------------------------------------------------
1276 MaybeHandle<JSArrayBuffer> old_memory;
1277 // TODO(titzer): handle imported memory properly.
1278
1279 uint32_t min_mem_pages = compiled_module->min_memory_pages();
1280 isolate->counters()->wasm_min_mem_pages_count()->AddSample(min_mem_pages);
1281 // TODO(wasm): re-enable counter for max_mem_pages when we use that field.
1282
1283 if (memory.is_null() && min_mem_pages > 0) {
1284 memory = AllocateMemory(thrower, isolate, min_mem_pages);
1285 if (memory.is_null()) return nothing; // failed to allocate memory
1286 }
1287
1288 if (!memory.is_null()) {
1289 instance->SetInternalField(kWasmMemArrayBuffer, *memory);
1290 Address mem_start = static_cast<Address>(memory->backing_store());
1291 uint32_t mem_size = static_cast<uint32_t>(memory->byte_length()->Number());
1292 LoadDataSegments(compiled_module, mem_start, mem_size);
1293
1294 uint32_t old_mem_size = compiled_module->has_heap()
1295 ? compiled_module->mem_size()
1296 : compiled_module->default_mem_size();
1297 Address old_mem_start =
1298 compiled_module->has_heap()
1299 ? static_cast<Address>(compiled_module->heap()->backing_store())
1300 : nullptr;
1301 RelocateInstanceCode(instance, old_mem_start, mem_start, old_mem_size,
1302 mem_size);
1303 compiled_module->set_heap(memory);
1304 }
1305
1306 //--------------------------------------------------------------------------
1307 // Set up the globals for the new instance.
1308 //--------------------------------------------------------------------------
1309 MaybeHandle<JSArrayBuffer> old_globals;
1310 MaybeHandle<JSArrayBuffer> globals;
1311 uint32_t globals_size = compiled_module->globals_size();
1312 if (globals_size > 0) {
1313 Handle<JSArrayBuffer> global_buffer = NewArrayBuffer(isolate, globals_size);
1314 globals = global_buffer;
1315 if (globals.is_null()) {
1316 thrower->Error("Out of memory: wasm globals");
1317 return nothing;
1318 }
1319 Address old_address =
1320 owner.is_null() ? nullptr : GetGlobalStartAddressFromCodeTemplate(
1321 *isolate->factory()->undefined_value(),
1322 JSObject::cast(*owner));
1323 RelocateGlobals(instance, old_address,
1324 static_cast<Address>(global_buffer->backing_store()));
1325 instance->SetInternalField(kWasmGlobalsArrayBuffer, *global_buffer);
1326 }
1327
1328 //--------------------------------------------------------------------------
1329 // Compile the import wrappers for the new instance.
1330 //--------------------------------------------------------------------------
1331 // TODO(titzer): handle imported globals and function tables.
1332 int num_imported_functions = 0;
1333 if (compiled_module->has_import_data()) {
1334 Handle<FixedArray> import_data = compiled_module->import_data();
1335 num_imported_functions = import_data->length();
1336 for (int index = 0; index < num_imported_functions; index++) {
1337 Handle<Code> import_wrapper =
1338 CompileImportWrapper(isolate, ffi, index, import_data, thrower);
1339 if (thrower->error()) return nothing;
1340 code_table->set(index, *import_wrapper);
1341 RecordStats(isolate, *import_wrapper);
1342 }
1343 }
1344
1345 //--------------------------------------------------------------------------
1346 // Set up the debug support for the new instance.
1347 //--------------------------------------------------------------------------
1348 // TODO(wasm): avoid referencing this stuff from the instance, use it off
1349 // the compiled module instead. See the following 3 assignments:
1350 if (compiled_module->has_module_bytes()) {
1351 instance->SetInternalField(kWasmModuleBytesString,
1352 compiled_module->ptr_to_module_bytes());
1353 }
1354
1355 if (compiled_module->has_function_names()) {
1356 instance->SetInternalField(kWasmFunctionNamesArray,
1357 compiled_module->ptr_to_function_names());
1358 }
1359
1360 {
1361 Handle<Object> handle = factory->NewNumber(num_imported_functions);
1362 instance->SetInternalField(kWasmNumImportedFunctions, *handle);
1363 }
1364
1365 //--------------------------------------------------------------------------
1366 // Set up the runtime support for the new instance.
1367 //--------------------------------------------------------------------------
1368 Handle<WeakCell> weak_link = isolate->factory()->NewWeakCell(instance);
1369
1370 for (int i = num_imported_functions + FLAG_skip_compiling_wasm_funcs;
1371 i < code_table->length(); ++i) {
1372 Handle<Code> code = code_table->GetValueChecked<Code>(isolate, i);
1373 if (code->kind() == Code::WASM_FUNCTION) {
1374 Handle<FixedArray> deopt_data =
1375 isolate->factory()->NewFixedArray(2, TENURED);
1376 deopt_data->set(0, *weak_link);
1377 deopt_data->set(1, Smi::FromInt(static_cast<int>(i)));
1378 deopt_data->set_length(2);
1379 code->set_deoptimization_data(*deopt_data);
1380 }
1381 }
1382
1383 //--------------------------------------------------------------------------
1384 // Set up the indirect function tables for the new instance.
1385 //--------------------------------------------------------------------------
1386 {
1387 std::vector<Handle<Code>> functions(
1388 static_cast<size_t>(code_table->length()));
1389 for (int i = 0; i < code_table->length(); ++i) {
1390 functions[i] = code_table->GetValueChecked<Code>(isolate, i);
1391 }
1392
1393 if (compiled_module->has_indirect_function_tables()) {
1394 Handle<FixedArray> indirect_tables_template =
1395 compiled_module->indirect_function_tables();
1396 Handle<FixedArray> to_replace =
1397 owner.is_null() ? indirect_tables_template
1398 : handle(FixedArray::cast(owner->GetInternalField(
1399 kWasmModuleFunctionTable)));
1400 Handle<FixedArray> indirect_tables = SetupIndirectFunctionTable(
1401 isolate, code_table, indirect_tables_template, to_replace);
1402 for (int i = 0; i < indirect_tables->length(); ++i) {
1403 Handle<FixedArray> metadata =
1404 indirect_tables->GetValueChecked<FixedArray>(isolate, i);
1405 uint32_t size = Smi::cast(metadata->get(kSize))->value();
1406 Handle<FixedArray> table =
1407 metadata->GetValueChecked<FixedArray>(isolate, kTable);
1408 PopulateFunctionTable(table, size, &functions);
1409 }
1410 instance->SetInternalField(kWasmModuleFunctionTable, *indirect_tables);
1411 }
1412 }
1413
1414 //--------------------------------------------------------------------------
1415 // Set up the exports object for the new instance.
1416 //--------------------------------------------------------------------------
1417 bool mem_export = compiled_module->export_memory();
1418 ModuleOrigin origin = compiled_module->origin();
1419
1420 if (compiled_module->has_exports() || mem_export) {
1421 PropertyDescriptor desc;
1422 desc.set_writable(false);
1423
1424 Handle<JSObject> exports_object = instance;
1425 if (origin == kWasmOrigin) {
1426 // Create the "exports" object.
1427 Handle<JSFunction> object_function = Handle<JSFunction>(
1428 isolate->native_context()->object_function(), isolate);
1429 exports_object = factory->NewJSObject(object_function, TENURED);
1430 Handle<String> exports_name = factory->InternalizeUtf8String("exports");
1431 JSObject::AddProperty(instance, exports_name, exports_object, READ_ONLY);
1432 }
1433 int first_export = -1;
1434 // TODO(wasm): another iteration over the code objects.
1435 for (int i = 0; i < code_table->length(); i++) {
1436 Handle<Code> code = code_table->GetValueChecked<Code>(isolate, i);
1437 if (code->kind() == Code::JS_TO_WASM_FUNCTION) {
1438 first_export = i;
1439 break;
1440 }
1441 }
1442 if (compiled_module->has_exports()) {
1443 Handle<FixedArray> exports = compiled_module->exports();
1444 int export_size = exports->length();
1445 for (int i = 0; i < export_size; ++i) {
1446 Handle<FixedArray> export_data =
1447 exports->GetValueChecked<FixedArray>(isolate, i);
1448 Handle<String> name =
1449 export_data->GetValueChecked<String>(isolate, kExportName);
1450 int arity = Smi::cast(export_data->get(kExportArity))->value();
1451 MaybeHandle<ByteArray> signature =
1452 export_data->GetValue<ByteArray>(isolate, kExportedSignature);
1453 Handle<Code> export_code =
1454 code_table->GetValueChecked<Code>(isolate, first_export + i);
1455 Handle<JSFunction> function = WrapExportCodeAsJSFunction(
1456 isolate, export_code, name, arity, signature, instance);
1457 desc.set_value(function);
1458 Maybe<bool> status = JSReceiver::DefineOwnProperty(
1459 isolate, exports_object, name, &desc, Object::THROW_ON_ERROR);
1460 if (!status.IsJust()) {
1461 thrower->Error("export of %.*s failed.", name->length(),
1462 name->ToCString().get());
1463 return nothing;
1464 }
1465 }
1466 }
1467 if (mem_export) {
1468 // Export the memory as a named property.
1469 Handle<JSArrayBuffer> buffer = Handle<JSArrayBuffer>(
1470 JSArrayBuffer::cast(instance->GetInternalField(kWasmMemArrayBuffer)));
1471 Handle<Object> memory_object =
1472 WasmJs::CreateWasmMemoryObject(isolate, buffer, false, 0);
1473 // TODO(titzer): export the memory with the correct name.
1474 Handle<String> name = factory->InternalizeUtf8String("memory");
1475 JSObject::AddProperty(exports_object, name, memory_object, READ_ONLY);
1476 }
1477 }
1478
1479 if (num_imported_functions > 0 || !owner.is_null()) {
1480 // If the code was cloned, or new imports were compiled, patch.
1481 PatchDirectCalls(old_code_table, code_table, num_imported_functions);
1482 }
1483
1484 FlushICache(isolate, code_table);
1485
1486 //--------------------------------------------------------------------------
1487 // Run the start function if one was specified.
1488 //--------------------------------------------------------------------------
1489 if (compiled_module->has_startup_function()) {
1490 Handle<FixedArray> startup_data = compiled_module->startup_function();
1491 HandleScope scope(isolate);
1492 int32_t start_index =
1493 startup_data->GetValueChecked<Smi>(isolate, kExportedFunctionIndex)
1494 ->value();
1495 Handle<Code> startup_code =
1496 code_table->GetValueChecked<Code>(isolate, start_index);
1497 int arity = Smi::cast(startup_data->get(kExportArity))->value();
1498 MaybeHandle<ByteArray> startup_signature =
1499 startup_data->GetValue<ByteArray>(isolate, kExportedSignature);
1500 Handle<JSFunction> startup_fct = WrapExportCodeAsJSFunction(
1501 isolate, startup_code, factory->InternalizeUtf8String("start"), arity,
1502 startup_signature, instance);
1503 RecordStats(isolate, *startup_code);
1504 // Call the JS function.
1505 Handle<Object> undefined = isolate->factory()->undefined_value();
1506 MaybeHandle<Object> retval =
1507 Execution::Call(isolate, startup_fct, undefined, 0, nullptr);
1508
1509 if (retval.is_null()) {
1510 thrower->Error("WASM.instantiateModule(): start function failed");
1511 return nothing;
1512 }
1513 }
1514
1515 DCHECK(wasm::IsWasmObject(*instance));
1516
1517 {
1518 Handle<WeakCell> link_to_owner = factory->NewWeakCell(instance);
1519
1520 Handle<Object> global_handle = isolate->global_handles()->Create(*instance);
1521 Handle<WeakCell> link_to_clone = factory->NewWeakCell(compiled_module);
1522 {
1523 DisallowHeapAllocation no_gc;
1524 compiled_module->set_weak_owning_instance(link_to_owner);
1525 Handle<WeakCell> next;
1526 if (link_to_original.ToHandle(&next) && !next->cleared()) {
1527 WasmCompiledModule* original = WasmCompiledModule::cast(next->value());
1528 DCHECK(original->has_weak_owning_instance());
1529 DCHECK(!original->weak_owning_instance()->cleared());
1530 compiled_module->set_weak_next_instance(next);
1531 original->set_weak_prev_instance(link_to_clone);
1532 }
1533
1534 compiled_module->set_weak_owning_instance(link_to_owner);
1535 instance->SetInternalField(kWasmCompiledModule, *compiled_module);
1536 GlobalHandles::MakeWeak(global_handle.location(),
1537 global_handle.location(), &InstanceFinalizer,
1538 v8::WeakCallbackType::kFinalizer);
1539 }
1540 }
1541 TRACE("Finishing instance %d\n", compiled_module->instance_id());
1542 TRACE_CHAIN(WasmCompiledModule::cast(module_object->GetInternalField(0)));
1543 return instance;
1544 } 1853 }
1545 1854
1546 #if DEBUG
1547 uint32_t WasmCompiledModule::instance_id_counter_ = 0;
1548 #endif
1549
1550 Handle<WasmCompiledModule> WasmCompiledModule::New(Isolate* isolate, 1855 Handle<WasmCompiledModule> WasmCompiledModule::New(Isolate* isolate,
1551 uint32_t min_memory_pages, 1856 uint32_t min_memory_pages,
1552 uint32_t globals_size, 1857 uint32_t globals_size,
1553 bool export_memory,
1554 ModuleOrigin origin) { 1858 ModuleOrigin origin) {
1555 Handle<FixedArray> ret = 1859 Handle<FixedArray> ret =
1556 isolate->factory()->NewFixedArray(PropertyIndices::Count, TENURED); 1860 isolate->factory()->NewFixedArray(PropertyIndices::Count, TENURED);
1557 // Globals size is expected to fit into an int without overflow. This is not 1861 // Globals size is expected to fit into an int without overflow. This is not
1558 // supported by the spec at the moment, however, we don't support array 1862 // supported by the spec at the moment, however, we don't support array
1559 // buffer sizes over 1g, so, for now, we avoid alocating a HeapNumber for 1863 // buffer sizes over 1g, so, for now, we avoid alocating a HeapNumber for
1560 // the globals size. The CHECK guards this assumption. 1864 // the globals size. The CHECK guards this assumption.
1561 CHECK_GE(static_cast<int>(globals_size), 0); 1865 CHECK_GE(static_cast<int>(globals_size), 0);
1562 ret->set(kID_min_memory_pages, 1866 ret->set(kID_min_memory_pages,
1563 Smi::FromInt(static_cast<int>(min_memory_pages))); 1867 Smi::FromInt(static_cast<int>(min_memory_pages)));
1564 ret->set(kID_globals_size, Smi::FromInt(static_cast<int>(globals_size))); 1868 ret->set(kID_globals_size, Smi::FromInt(static_cast<int>(globals_size)));
1565 ret->set(kID_export_memory, Smi::FromInt(static_cast<int>(export_memory)));
1566 ret->set(kID_origin, Smi::FromInt(static_cast<int>(origin))); 1869 ret->set(kID_origin, Smi::FromInt(static_cast<int>(origin)));
1567 WasmCompiledModule::cast(*ret)->Init(); 1870 WasmCompiledModule::cast(*ret)->Init();
1568 return handle(WasmCompiledModule::cast(*ret)); 1871 return handle(WasmCompiledModule::cast(*ret));
1569 } 1872 }
1570 1873
1571 void WasmCompiledModule::Init() { 1874 void WasmCompiledModule::Init() {
1572 #if DEBUG 1875 #if DEBUG
1573 set(kID_instance_id, Smi::FromInt(instance_id_counter_++)); 1876 static uint32_t instance_id_counter = 0;
1877 set(kID_instance_id, Smi::FromInt(instance_id_counter++));
1574 TRACE("New compiled module id: %d\n", instance_id()); 1878 TRACE("New compiled module id: %d\n", instance_id());
1575 #endif 1879 #endif
1576 } 1880 }
1577 1881
1578 void WasmCompiledModule::PrintInstancesChain() { 1882 void WasmCompiledModule::PrintInstancesChain() {
1579 #if DEBUG 1883 #if DEBUG
1580 if (!FLAG_trace_wasm_instances) return; 1884 if (!FLAG_trace_wasm_instances) return;
1581 for (WasmCompiledModule* current = this; current != nullptr;) { 1885 for (WasmCompiledModule* current = this; current != nullptr;) {
1582 PrintF("->%d", current->instance_id()); 1886 PrintF("->%d", current->instance_id());
1583 if (current->ptr_to_weak_next_instance() == nullptr) break; 1887 if (current->ptr_to_weak_next_instance() == nullptr) break;
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
1667 if (!IsWasmObject(*object)) { 1971 if (!IsWasmObject(*object)) {
1668 return false; 1972 return false;
1669 } 1973 }
1670 1974
1671 // Get code table associated with the module js_object 1975 // Get code table associated with the module js_object
1672 Object* obj = object->GetInternalField(kWasmModuleCodeTable); 1976 Object* obj = object->GetInternalField(kWasmModuleCodeTable);
1673 Handle<FixedArray> code_table(FixedArray::cast(obj)); 1977 Handle<FixedArray> code_table(FixedArray::cast(obj));
1674 1978
1675 // Iterate through the code objects in the code table and update relocation 1979 // Iterate through the code objects in the code table and update relocation
1676 // information 1980 // information
1677 for (int i = 0; i < code_table->length(); i++) { 1981 for (int i = 0; i < code_table->length(); ++i) {
1678 obj = code_table->get(i); 1982 obj = code_table->get(i);
1679 Handle<Code> code(Code::cast(obj)); 1983 Handle<Code> code(Code::cast(obj));
1680 1984
1681 int mode_mask = RelocInfo::ModeMask(RelocInfo::WASM_MEMORY_REFERENCE) | 1985 int mode_mask = RelocInfo::ModeMask(RelocInfo::WASM_MEMORY_REFERENCE) |
1682 RelocInfo::ModeMask(RelocInfo::WASM_MEMORY_SIZE_REFERENCE); 1986 RelocInfo::ModeMask(RelocInfo::WASM_MEMORY_SIZE_REFERENCE);
1683 for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) { 1987 for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) {
1684 RelocInfo::Mode mode = it.rinfo()->rmode(); 1988 RelocInfo::Mode mode = it.rinfo()->rmode();
1685 if (RelocInfo::IsWasmMemoryReference(mode) || 1989 if (RelocInfo::IsWasmMemoryReference(mode) ||
1686 RelocInfo::IsWasmMemorySizeReference(mode)) { 1990 RelocInfo::IsWasmMemorySizeReference(mode)) {
1687 it.rinfo()->update_wasm_memory_reference(old_start, new_start, old_size, 1991 it.rinfo()->update_wasm_memory_reference(old_start, new_start, old_size,
(...skipping 14 matching lines...) Expand all
1702 for (uint32_t i = 0; i < table->size; ++i) { 2006 for (uint32_t i = 0; i < table->size; ++i) {
1703 const WasmFunction* function = &module->functions[table->values[i]]; 2007 const WasmFunction* function = &module->functions[table->values[i]];
1704 values->set(i, Smi::FromInt(function->sig_index)); 2008 values->set(i, Smi::FromInt(function->sig_index));
1705 values->set(i + table->max_size, Smi::FromInt(table->values[i])); 2009 values->set(i + table->max_size, Smi::FromInt(table->values[i]));
1706 } 2010 }
1707 // Set the remaining elements to -1 (instead of "undefined"). These 2011 // Set the remaining elements to -1 (instead of "undefined"). These
1708 // elements are accessed directly as SMIs (without a check). On 64-bit 2012 // elements are accessed directly as SMIs (without a check). On 64-bit
1709 // platforms, it is possible to have the top bits of "undefined" take 2013 // platforms, it is possible to have the top bits of "undefined" take
1710 // small integer values (or zero), which are more likely to be equal to 2014 // small integer values (or zero), which are more likely to be equal to
1711 // the signature index we check against. 2015 // the signature index we check against.
1712 for (uint32_t i = table->size; i < table->max_size; i++) { 2016 for (uint32_t i = table->size; i < table->max_size; ++i) {
1713 values->set(i, Smi::FromInt(-1)); 2017 values->set(i, Smi::FromInt(-1));
1714 } 2018 }
1715 return values; 2019 return values;
1716 } 2020 }
1717 2021
1718 void PopulateFunctionTable(Handle<FixedArray> table, uint32_t table_size, 2022 void PopulateFunctionTable(Handle<FixedArray> table, uint32_t table_size,
1719 const std::vector<Handle<Code>>* code_table) { 2023 const std::vector<Handle<Code>>* code_table) {
1720 uint32_t max_size = table->length() / 2; 2024 uint32_t max_size = table->length() / 2;
1721 for (uint32_t i = max_size; i < max_size + table_size; ++i) { 2025 for (uint32_t i = max_size; i < max_size + table_size; ++i) {
1722 int index = Smi::cast(table->get(static_cast<int>(i)))->value(); 2026 int index = Smi::cast(table->get(static_cast<int>(i)))->value();
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
1902 WasmCompiledModule* compiled_module = 2206 WasmCompiledModule* compiled_module =
1903 WasmCompiledModule::cast(instance->GetInternalField(kWasmCompiledModule)); 2207 WasmCompiledModule::cast(instance->GetInternalField(kWasmCompiledModule));
1904 CHECK(compiled_module->has_weak_module_object()); 2208 CHECK(compiled_module->has_weak_module_object());
1905 CHECK(compiled_module->ptr_to_weak_module_object()->cleared()); 2209 CHECK(compiled_module->ptr_to_weak_module_object()->cleared());
1906 } 2210 }
1907 2211
1908 } // namespace testing 2212 } // namespace testing
1909 } // namespace wasm 2213 } // namespace wasm
1910 } // namespace internal 2214 } // namespace internal
1911 } // namespace v8 2215 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698