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

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

Issue 2345593003: [wasm] Master CL for Binary 0xC changes. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Fix test failures and TSAN races. 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
« no previous file with comments | « src/wasm/wasm-module.h ('k') | src/wasm/wasm-opcodes.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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"
11 #include "src/objects.h" 11 #include "src/objects.h"
12 #include "src/property-descriptor.h" 12 #include "src/property-descriptor.h"
13 #include "src/simulator.h" 13 #include "src/simulator.h"
14 #include "src/snapshot/snapshot.h" 14 #include "src/snapshot/snapshot.h"
15 #include "src/v8.h" 15 #include "src/v8.h"
16 16
17 #include "src/wasm/ast-decoder.h" 17 #include "src/wasm/ast-decoder.h"
18 #include "src/wasm/module-decoder.h" 18 #include "src/wasm/module-decoder.h"
19 #include "src/wasm/wasm-debug.h" 19 #include "src/wasm/wasm-debug.h"
20 #include "src/wasm/wasm-function-name-table.h" 20 #include "src/wasm/wasm-function-name-table.h"
21 #include "src/wasm/wasm-js.h"
21 #include "src/wasm/wasm-module.h" 22 #include "src/wasm/wasm-module.h"
22 #include "src/wasm/wasm-result.h" 23 #include "src/wasm/wasm-result.h"
23 24
24 #include "src/compiler/wasm-compiler.h" 25 #include "src/compiler/wasm-compiler.h"
25 26
26 namespace v8 { 27 namespace v8 {
27 namespace internal { 28 namespace internal {
28 namespace wasm { 29 namespace wasm {
29 30
31 const char* SectionName(WasmSectionCode code) {
32 switch (code) {
33 case kUnknownSectionCode:
34 return "Unknown";
35 case kTypeSectionCode:
36 return "Type";
37 case kImportSectionCode:
38 return "Import";
39 case kFunctionSectionCode:
40 return "Function";
41 case kTableSectionCode:
42 return "Table";
43 case kMemorySectionCode:
44 return "Memory";
45 case kGlobalSectionCode:
46 return "Global";
47 case kExportSectionCode:
48 return "Export";
49 case kStartSectionCode:
50 return "Start";
51 case kCodeSectionCode:
52 return "Code";
53 case kElementSectionCode:
54 return "Element";
55 case kDataSectionCode:
56 return "Data";
57 case kNameSectionCode:
58 return "Name";
59 default:
60 return "<unknown>";
61 }
62 }
63
30 enum JSFunctionExportInternalField { 64 enum JSFunctionExportInternalField {
31 kInternalModuleInstance, 65 kInternalModuleInstance,
32 kInternalArity, 66 kInternalArity,
33 kInternalSignature 67 kInternalSignature
34 }; 68 };
35 69
36 static const int kPlaceholderMarker = 1000000000; 70 static const int kPlaceholderMarker = 1000000000;
37 71
38 static const char* wasmSections[] = {
39 #define F(enumerator, order, string) string,
40 FOR_EACH_WASM_SECTION_TYPE(F)
41 #undef F
42 "<unknown>" // entry for "Max"
43 };
44
45 static uint8_t wasmSectionsLengths[]{
46 #define F(enumerator, order, string) sizeof(string) - 1,
47 FOR_EACH_WASM_SECTION_TYPE(F)
48 #undef F
49 9 // entry for "Max"
50 };
51
52 static uint8_t wasmSectionsOrders[]{
53 #define F(enumerator, order, string) order,
54 FOR_EACH_WASM_SECTION_TYPE(F)
55 #undef F
56 0 // entry for "Max"
57 };
58
59 static_assert(sizeof(wasmSections) / sizeof(wasmSections[0]) ==
60 (size_t)WasmSection::Code::Max + 1,
61 "expected enum WasmSection::Code to be monotonic from 0");
62
63 WasmSection::Code WasmSection::begin() { return (WasmSection::Code)0; }
64 WasmSection::Code WasmSection::end() { return WasmSection::Code::Max; }
65 WasmSection::Code WasmSection::next(WasmSection::Code code) {
66 return (WasmSection::Code)(1 + (uint32_t)code);
67 }
68
69 const char* WasmSection::getName(WasmSection::Code code) {
70 return wasmSections[(size_t)code];
71 }
72
73 size_t WasmSection::getNameLength(WasmSection::Code code) {
74 return wasmSectionsLengths[(size_t)code];
75 }
76
77 int WasmSection::getOrder(WasmSection::Code code) {
78 return wasmSectionsOrders[(size_t)code];
79 }
80
81 WasmSection::Code WasmSection::lookup(const byte* string, uint32_t length) {
82 // TODO(jfb) Linear search, it may be better to do a common-prefix search.
83 for (Code i = begin(); i != end(); i = next(i)) {
84 if (getNameLength(i) == length && 0 == memcmp(getName(i), string, length)) {
85 return i;
86 }
87 }
88 return Code::Max;
89 }
90
91 std::ostream& operator<<(std::ostream& os, const WasmModule& module) { 72 std::ostream& operator<<(std::ostream& os, const WasmModule& module) {
92 os << "WASM module with "; 73 os << "WASM module with ";
93 os << (module.min_mem_pages * module.kPageSize) << " min mem"; 74 os << (module.min_mem_pages * module.kPageSize) << " min mem";
94 os << (module.max_mem_pages * module.kPageSize) << " max mem"; 75 os << (module.max_mem_pages * module.kPageSize) << " max mem";
95 os << module.functions.size() << " functions"; 76 os << module.functions.size() << " functions";
96 os << module.functions.size() << " globals"; 77 os << module.functions.size() << " globals";
97 os << module.functions.size() << " data segments"; 78 os << module.functions.size() << " data segments";
98 return os; 79 return os;
99 } 80 }
100 81
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
151 DCHECK_NOT_NULL(deopt_data); 132 DCHECK_NOT_NULL(deopt_data);
152 DCHECK(deopt_data->length() == 2); 133 DCHECK(deopt_data->length() == 2);
153 Object* weak_link = deopt_data->get(0); 134 Object* weak_link = deopt_data->get(0);
154 if (weak_link == undefined) return undefined; 135 if (weak_link == undefined) return undefined;
155 WeakCell* cell = WeakCell::cast(weak_link); 136 WeakCell* cell = WeakCell::cast(weak_link);
156 return cell->value(); 137 return cell->value();
157 } 138 }
158 139
159 namespace { 140 namespace {
160 // Internal constants for the layout of the module object. 141 // Internal constants for the layout of the module object.
161 enum WasmInstanceFields { 142 enum WasmInstanceObjectFields {
162 kWasmCompiledModule = 0, 143 kWasmCompiledModule = 0,
163 kWasmModuleFunctionTable, 144 kWasmModuleFunctionTable,
164 kWasmModuleCodeTable, 145 kWasmModuleCodeTable,
165 kWasmMemArrayBuffer, 146 kWasmMemArrayBuffer,
166 kWasmGlobalsArrayBuffer, 147 kWasmGlobalsArrayBuffer,
167 // TODO(clemensh): Remove function name array, extract names from module 148 // TODO(clemensh): Remove function name array, extract names from module
168 // bytes. 149 // bytes.
169 kWasmFunctionNamesArray, 150 kWasmFunctionNamesArray,
170 kWasmModuleBytesString, 151 kWasmModuleBytesString,
171 kWasmDebugInfo, 152 kWasmDebugInfo,
153 kWasmNumImportedFunctions,
172 kWasmModuleInternalFieldCount 154 kWasmModuleInternalFieldCount
173 }; 155 };
174 156
175 // TODO(mtrofin): Unnecessary once we stop using JS Heap for wasm code. 157 // TODO(mtrofin): Unnecessary once we stop using JS Heap for wasm code.
176 // For now, each field is expected to have the type commented by its side. 158 // For now, each field is expected to have the type commented by its side.
177 // The elements typed as "maybe" are optional. The others are mandatory. Since 159 // The elements typed as "maybe" are optional. The others are mandatory. Since
178 // the compiled module is either obtained from the current v8 instance, or from 160 // the compiled module is either obtained from the current v8 instance, or from
179 // a snapshot produced by a compatible (==identical) v8 instance, we simply 161 // a snapshot produced by a compatible (==identical) v8 instance, we simply
180 // fail at instantiation time, in the face of invalid data. 162 // fail at instantiation time, in the face of invalid data.
181 enum CompiledWasmObjectFields { 163 enum WasmCompiledModule {
182 kFunctions, // FixedArray of Code 164 kCodeTable, // FixedArray of Code
183 kImportData, // maybe FixedArray of FixedArray respecting the 165 kImportData, // maybe FixedArray of FixedArray respecting the
184 // WasmImportMetadata structure. 166 // WasmImportData structure.
185 kImportMap, // FixedArray. The i-th element is the Code object used for 167 kExportData, // maybe FixedArray of FixedArray of WasmExportData
186 // import i 168 // structure
187 kExports, // maybe FixedArray of FixedArray of WasmExportMetadata 169 kStartupData, // maybe FixedArray of WasmExportData structure
188 // structure
189 kStartupFunction, // maybe FixedArray of WasmExportMetadata structure
190 kTableOfIndirectFunctionTables, // maybe FixedArray of FixedArray of 170 kTableOfIndirectFunctionTables, // maybe FixedArray of FixedArray of
191 // WasmIndirectFunctionTableMetadata 171 // WasmIndirectFunctionTableData
192 kModuleBytes, // maybe String 172 kModuleBytes, // maybe String
193 kFunctionNameTable, // maybe ByteArray 173 kFunctionNameTable, // maybe ByteArray
194 kMinRequiredMemory, // Smi. an uint32_t 174 kMinRequiredMemory, // Smi. an uint32_t
195 // The following 2 are either together present or absent: 175 // The following 2 are either together present or absent:
196 kDataSegmentsInfo, // maybe FixedArray of FixedArray respecting the 176 kDataSegmentsInfo, // maybe FixedArray of FixedArray respecting the
197 // WasmSegmentInfo structure 177 // WasmSegmentInfo structure
198 kDataSegments, // maybe ByteArray. 178 kDataSegments, // maybe ByteArray.
199 179
200 kGlobalsSize, // Smi. an uint32_t 180 kGlobalsSize, // Smi. an uint32_t
201 kMemSize, // Smi.an uint32_t 181 kMemSize, // Smi.an uint32_t
202 kMemStart, // MaybeHandle<ArrayBuffer> 182 kMemStart, // MaybeHandle<ArrayBuffer>
203 kExportMem, // Smi. bool 183 kExportMem, // Smi. bool
204 kOrigin, // Smi. ModuleOrigin 184 kOrigin, // Smi. ModuleOrigin
205 kNextInstance, // WeakCell. See compiled code cloning. 185 kNextInstance, // WeakCell. See compiled code cloning.
206 kPrevInstance, // WeakCell. See compiled code cloning. 186 kPrevInstance, // WeakCell. See compiled code cloning.
207 kOwningInstance, // WeakCell, pointing to the owning instance. 187 kOwningInstance, // WeakCell, pointing to the owning instance.
208 kModuleObject, // WeakCell, pointing to the module object. 188 kModuleObject, // WeakCell, pointing to the module object.
209 kCompiledWasmObjectTableSize // Sentinel value. 189 kWasmCompiledModuleSize // Sentinel value.
210 }; 190 };
211 191
212 enum WasmImportMetadata { 192 enum WasmImportData {
213 kModuleName, // String 193 kModuleName, // String
214 kFunctionName, // maybe String 194 kFunctionName, // maybe String
215 kOutputCount, // Smi. an uint32_t 195 kOutputCount, // Smi. an uint32_t
216 kSignature, // ByteArray. A copy of the data in FunctionSig 196 kSignature, // ByteArray. A copy of the data in FunctionSig
217 kWasmImportDataTableSize // Sentinel value. 197 kWasmImportDataSize // Sentinel value.
218 }; 198 };
219 199
220 enum WasmExportMetadata { 200 enum WasmExportData {
221 kExportCode, // Code 201 kExportName, // String
222 kExportName, // String 202 kExportArity, // Smi, an int
223 kExportArity, // Smi, an int 203 kExportedFunctionIndex, // Smi, an uint32_t
224 kExportedFunctionIndex, // Smi, an uint32_t 204 kExportedSignature, // ByteArray. A copy of the data in FunctionSig
225 kExportedSignature, // ByteArray. A copy of the data in FunctionSig 205 kWasmExportDataSize // Sentinel value.
226 kWasmExportMetadataTableSize // Sentinel value.
227 }; 206 };
228 207
229 enum WasmSegmentInfo { 208 enum WasmSegmentInfo {
230 kDestAddr, // Smi. an uint32_t 209 kDestAddr, // Smi. an uint32_t
231 kSourceSize, // Smi. an uint32_t 210 kSourceSize, // Smi. an uint32_t
232 kWasmSegmentInfoSize // Sentinel value. 211 kWasmSegmentInfoSize // Sentinel value.
233 }; 212 };
234 213
235 enum WasmIndirectFunctionTableMetadata { 214 enum WasmIndirectFunctionTableData {
236 kSize, // Smi. an uint32_t 215 kSize, // Smi. an uint32_t
237 kTable, // FixedArray of indirect function table 216 kTable, // FixedArray of indirect function table
238 kWasmIndirectFunctionTableMetadataSize // Sentinel value. 217 kWasmIndirectFunctionTableDataSize // Sentinel value.
239 }; 218 };
240 219
241 uint32_t GetMinModuleMemSize(const WasmModule* module) { 220 uint32_t GetMinModuleMemSize(const WasmModule* module) {
242 return WasmModule::kPageSize * module->min_mem_pages; 221 return WasmModule::kPageSize * module->min_mem_pages;
243 } 222 }
244 223
245 void LoadDataSegments(Handle<FixedArray> compiled_module, Address mem_addr, 224 void LoadDataSegments(Handle<FixedArray> compiled_module, Address mem_addr,
246 size_t mem_size) { 225 size_t mem_size) {
247 Isolate* isolate = compiled_module->GetIsolate(); 226 Isolate* isolate = compiled_module->GetIsolate();
248 MaybeHandle<ByteArray> maybe_data = 227 MaybeHandle<ByteArray> maybe_data =
(...skipping 23 matching lines...) Expand all
272 last_extraction_pos += source_size; 251 last_extraction_pos += source_size;
273 } 252 }
274 } 253 }
275 254
276 void SaveDataSegmentInfo(Factory* factory, const WasmModule* module, 255 void SaveDataSegmentInfo(Factory* factory, const WasmModule* module,
277 Handle<FixedArray> compiled_module) { 256 Handle<FixedArray> compiled_module) {
278 Handle<FixedArray> segments = factory->NewFixedArray( 257 Handle<FixedArray> segments = factory->NewFixedArray(
279 static_cast<int>(module->data_segments.size()), TENURED); 258 static_cast<int>(module->data_segments.size()), TENURED);
280 uint32_t data_size = 0; 259 uint32_t data_size = 0;
281 for (const WasmDataSegment& segment : module->data_segments) { 260 for (const WasmDataSegment& segment : module->data_segments) {
282 if (!segment.init) continue;
283 if (segment.source_size == 0) continue; 261 if (segment.source_size == 0) continue;
284 data_size += segment.source_size; 262 data_size += segment.source_size;
285 } 263 }
286 Handle<ByteArray> data = factory->NewByteArray(data_size, TENURED); 264 Handle<ByteArray> data = factory->NewByteArray(data_size, TENURED);
287 265
288 uint32_t last_insertion_pos = 0; 266 uint32_t last_insertion_pos = 0;
289 for (uint32_t i = 0; i < module->data_segments.size(); ++i) { 267 for (uint32_t i = 0; i < module->data_segments.size(); ++i) {
290 const WasmDataSegment& segment = module->data_segments[i]; 268 const WasmDataSegment& segment = module->data_segments[i];
291 if (!segment.init) continue;
292 if (segment.source_size == 0) continue; 269 if (segment.source_size == 0) continue;
293 Handle<ByteArray> js_segment = 270 Handle<ByteArray> js_segment =
294 factory->NewByteArray(kWasmSegmentInfoSize * sizeof(uint32_t), TENURED); 271 factory->NewByteArray(kWasmSegmentInfoSize * sizeof(uint32_t), TENURED);
295 js_segment->set_int(kDestAddr, segment.dest_addr); 272 // TODO(titzer): add support for global offsets for dest_addr
273 CHECK_EQ(WasmInitExpr::kI32Const, segment.dest_addr.kind);
274 js_segment->set_int(kDestAddr, segment.dest_addr.val.i32_const);
296 js_segment->set_int(kSourceSize, segment.source_size); 275 js_segment->set_int(kSourceSize, segment.source_size);
297 segments->set(i, *js_segment); 276 segments->set(i, *js_segment);
298 data->copy_in(last_insertion_pos, 277 data->copy_in(last_insertion_pos,
299 module->module_start + segment.source_offset, 278 module->module_start + segment.source_offset,
300 segment.source_size); 279 segment.source_size);
301 last_insertion_pos += segment.source_size; 280 last_insertion_pos += segment.source_size;
302 } 281 }
303 compiled_module->set(kDataSegmentsInfo, *segments); 282 compiled_module->set(kDataSegmentsInfo, *segments);
304 compiled_module->set(kDataSegments, *data); 283 compiled_module->set(kDataSegments, *data);
305 } 284 }
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
394 // TODO(titzer): placeholder code objects are somewhat dangerous. 373 // TODO(titzer): placeholder code objects are somewhat dangerous.
395 static byte buffer[] = {0, 0, 0, 0, 0, 0, 0, 0}; // fake instructions. 374 static byte buffer[] = {0, 0, 0, 0, 0, 0, 0, 0}; // fake instructions.
396 static CodeDesc desc = { 375 static CodeDesc desc = {
397 buffer, arraysize(buffer), arraysize(buffer), 0, 0, nullptr, 0, nullptr}; 376 buffer, arraysize(buffer), arraysize(buffer), 0, 0, nullptr, 0, nullptr};
398 Handle<Code> code = factory->NewCode(desc, Code::KindField::encode(kind), 377 Handle<Code> code = factory->NewCode(desc, Code::KindField::encode(kind),
399 Handle<Object>::null()); 378 Handle<Object>::null());
400 code->set_constant_pool_offset(static_cast<int>(index) + kPlaceholderMarker); 379 code->set_constant_pool_offset(static_cast<int>(index) + kPlaceholderMarker);
401 return code; 380 return code;
402 } 381 }
403 382
404 // TODO(mtrofin): remove when we stop relying on placeholders. 383 bool LinkFunction(Handle<Code> unlinked,
405 void InitializePlaceholders(Factory* factory, 384 std::vector<Handle<Code>>& code_table) {
406 std::vector<Handle<Code>>* placeholders,
407 size_t size) {
408 DCHECK(placeholders->empty());
409 placeholders->reserve(size);
410
411 for (uint32_t i = 0; i < size; ++i) {
412 placeholders->push_back(CreatePlaceholder(factory, i, Code::WASM_FUNCTION));
413 }
414 }
415
416 bool LinkFunction(Isolate* isolate, Handle<Code> unlinked,
417 Handle<FixedArray> code_targets,
418 Code::Kind kind = Code::WASM_FUNCTION) {
419 bool modified = false; 385 bool modified = false;
420 int mode_mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET); 386 int mode_mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET);
421 AllowDeferredHandleDereference embedding_raw_address; 387 AllowDeferredHandleDereference embedding_raw_address;
422 for (RelocIterator it(*unlinked, mode_mask); !it.done(); it.next()) { 388 for (RelocIterator it(*unlinked, mode_mask); !it.done(); it.next()) {
423 Code* target = Code::GetCodeFromTargetAddress(it.rinfo()->target_address()); 389 RelocInfo::Mode mode = it.rinfo()->rmode();
424 if (target->kind() == kind && 390 if (RelocInfo::IsCodeTarget(mode)) {
425 target->constant_pool_offset() >= kPlaceholderMarker) { 391 Code* target =
426 // Patch direct calls to placeholder code objects. 392 Code::GetCodeFromTargetAddress(it.rinfo()->target_address());
427 uint32_t index = target->constant_pool_offset() - kPlaceholderMarker; 393 if (target->constant_pool_offset() < kPlaceholderMarker) continue;
428 CHECK(index < static_cast<uint32_t>(code_targets->length())); 394 switch (target->kind()) {
429 Handle<Code> new_target = 395 case Code::WASM_FUNCTION: // fall through
430 code_targets->GetValueChecked<Code>(isolate, index); 396 case Code::WASM_TO_JS_FUNCTION: // fall through
431 if (target != *new_target) { 397 case Code::JS_TO_WASM_FUNCTION: {
432 it.rinfo()->set_target_address(new_target->instruction_start(), 398 // Patch direct calls to placeholder code objects.
433 UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH); 399 uint32_t index = target->constant_pool_offset() - kPlaceholderMarker;
434 modified = true; 400 Handle<Code> new_target = code_table[index];
401 if (target != *new_target) {
402 it.rinfo()->set_target_address(new_target->instruction_start(),
403 UPDATE_WRITE_BARRIER,
404 SKIP_ICACHE_FLUSH);
405 modified = true;
406 }
407 break;
408 }
409 default:
410 break;
435 } 411 }
436 } 412 }
437 } 413 }
438 return modified; 414 return modified;
439 } 415 }
440 416
441 void LinkModuleFunctions(Isolate* isolate, Handle<FixedArray> functions) { 417 void FlushICache(Isolate* isolate, Handle<FixedArray> functions) {
442 for (int i = 0; i < functions->length(); ++i) {
443 Handle<Code> code = functions->GetValueChecked<Code>(isolate, i);
444 LinkFunction(isolate, code, functions);
445 }
446 }
447
448 void FlushAssemblyCache(Isolate* isolate, Handle<FixedArray> functions) {
449 for (int i = 0; i < functions->length(); ++i) { 418 for (int i = 0; i < functions->length(); ++i) {
450 Handle<Code> code = functions->GetValueChecked<Code>(isolate, i); 419 Handle<Code> code = functions->GetValueChecked<Code>(isolate, i);
451 Assembler::FlushICache(isolate, code->instruction_start(), 420 Assembler::FlushICache(isolate, code->instruction_start(),
452 code->instruction_size()); 421 code->instruction_size());
453 } 422 }
454 } 423 }
424 } // namespace
455 425
456 void SetRuntimeSupport(Isolate* isolate, Handle<JSObject> js_object) { 426 uint32_t GetNumImportedFunctions(Handle<JSObject> wasm_object) {
457 Handle<FixedArray> functions = Handle<FixedArray>( 427 return static_cast<uint32_t>(
458 FixedArray::cast(js_object->GetInternalField(kWasmModuleCodeTable))); 428 Smi::cast(wasm_object->GetInternalField(kWasmNumImportedFunctions))
459 Handle<WeakCell> weak_link = isolate->factory()->NewWeakCell(js_object); 429 ->value());
460
461 for (int i = FLAG_skip_compiling_wasm_funcs; i < functions->length(); ++i) {
462 Handle<Code> code = functions->GetValueChecked<Code>(isolate, i);
463 Handle<FixedArray> deopt_data =
464 isolate->factory()->NewFixedArray(2, TENURED);
465 deopt_data->set(0, *weak_link);
466 deopt_data->set(1, Smi::FromInt(static_cast<int>(i)));
467 deopt_data->set_length(2);
468 code->set_deoptimization_data(*deopt_data);
469 }
470 } 430 }
471 431
472 } // namespace
473
474 WasmModule::WasmModule(byte* module_start) 432 WasmModule::WasmModule(byte* module_start)
475 : module_start(module_start), 433 : module_start(module_start),
476 module_end(nullptr), 434 module_end(nullptr),
477 min_mem_pages(0), 435 min_mem_pages(0),
478 max_mem_pages(0), 436 max_mem_pages(0),
479 mem_export(false), 437 mem_export(false),
480 mem_external(false),
481 start_function_index(-1), 438 start_function_index(-1),
482 origin(kWasmOrigin), 439 origin(kWasmOrigin),
483 globals_size(0), 440 globals_size(0),
441 num_imported_functions(0),
442 num_declared_functions(0),
443 num_exported_functions(0),
484 pending_tasks(new base::Semaphore(0)) {} 444 pending_tasks(new base::Semaphore(0)) {}
485 445
486 static MaybeHandle<JSFunction> ReportFFIError( 446 static MaybeHandle<JSFunction> ReportFFIError(
487 ErrorThrower* thrower, const char* error, uint32_t index, 447 ErrorThrower* thrower, const char* error, uint32_t index,
488 Handle<String> module_name, MaybeHandle<String> function_name) { 448 Handle<String> module_name, MaybeHandle<String> function_name) {
489 Handle<String> function_name_handle; 449 Handle<String> function_name_handle;
490 if (function_name.ToHandle(&function_name_handle)) { 450 if (function_name.ToHandle(&function_name_handle)) {
491 thrower->Error("Import #%d module=\"%.*s\" function=\"%.*s\" error: %s", 451 thrower->Error("Import #%d module=\"%.*s\" function=\"%.*s\" error: %s",
492 index, module_name->length(), module_name->ToCString().get(), 452 index, module_name->length(), module_name->ToCString().get(),
493 function_name_handle->length(), 453 function_name_handle->length(),
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
553 bool FetchAndExecuteCompilationUnit( 513 bool FetchAndExecuteCompilationUnit(
554 Isolate* isolate, 514 Isolate* isolate,
555 std::vector<compiler::WasmCompilationUnit*>* compilation_units, 515 std::vector<compiler::WasmCompilationUnit*>* compilation_units,
556 std::queue<compiler::WasmCompilationUnit*>* executed_units, 516 std::queue<compiler::WasmCompilationUnit*>* executed_units,
557 base::Mutex* result_mutex, base::AtomicNumber<size_t>* next_unit) { 517 base::Mutex* result_mutex, base::AtomicNumber<size_t>* next_unit) {
558 DisallowHeapAllocation no_allocation; 518 DisallowHeapAllocation no_allocation;
559 DisallowHandleAllocation no_handles; 519 DisallowHandleAllocation no_handles;
560 DisallowHandleDereference no_deref; 520 DisallowHandleDereference no_deref;
561 DisallowCodeDependencyChange no_dependency_change; 521 DisallowCodeDependencyChange no_dependency_change;
562 522
563 // - 1 because AtomicIntrement returns the value after the atomic increment. 523 // - 1 because AtomicIncrement returns the value after the atomic increment.
564 size_t index = next_unit->Increment(1) - 1; 524 size_t index = next_unit->Increment(1) - 1;
565 if (index >= compilation_units->size()) { 525 if (index >= compilation_units->size()) {
566 return false; 526 return false;
567 } 527 }
568 528
569 compiler::WasmCompilationUnit* unit = compilation_units->at(index); 529 compiler::WasmCompilationUnit* unit = compilation_units->at(index);
570 if (unit != nullptr) { 530 if (unit != nullptr) {
571 unit->ExecuteCompilation(); 531 unit->ExecuteCompilation();
572 { 532 base::LockGuard<base::Mutex> guard(result_mutex);
573 base::LockGuard<base::Mutex> guard(result_mutex); 533 executed_units->push(unit);
574 executed_units->push(unit);
575 }
576 } 534 }
577 return true; 535 return true;
578 } 536 }
579 537
580 class WasmCompilationTask : public CancelableTask { 538 class WasmCompilationTask : public CancelableTask {
581 public: 539 public:
582 WasmCompilationTask( 540 WasmCompilationTask(
583 Isolate* isolate, 541 Isolate* isolate,
584 std::vector<compiler::WasmCompilationUnit*>* compilation_units, 542 std::vector<compiler::WasmCompilationUnit*>* compilation_units,
585 std::queue<compiler::WasmCompilationUnit*>* executed_units, 543 std::queue<compiler::WasmCompilationUnit*>* executed_units,
(...skipping 22 matching lines...) Expand all
608 base::Mutex* result_mutex_; 566 base::Mutex* result_mutex_;
609 base::AtomicNumber<size_t>* next_unit_; 567 base::AtomicNumber<size_t>* next_unit_;
610 }; 568 };
611 569
612 static void RecordStats(Isolate* isolate, Code* code) { 570 static void RecordStats(Isolate* isolate, Code* code) {
613 isolate->counters()->wasm_generated_code_size()->Increment(code->body_size()); 571 isolate->counters()->wasm_generated_code_size()->Increment(code->body_size());
614 isolate->counters()->wasm_reloc_size()->Increment( 572 isolate->counters()->wasm_reloc_size()->Increment(
615 code->relocation_info()->length()); 573 code->relocation_info()->length());
616 } 574 }
617 575
618 static void RecordStats(Isolate* isolate,
619 const std::vector<Handle<Code>>& functions) {
620 for (Handle<Code> c : functions) RecordStats(isolate, *c);
621 }
622
623 static void RecordStats(Isolate* isolate, Handle<FixedArray> functions) { 576 static void RecordStats(Isolate* isolate, Handle<FixedArray> functions) {
624 DisallowHeapAllocation no_gc; 577 DisallowHeapAllocation no_gc;
625 for (int i = 0; i < functions->length(); ++i) { 578 for (int i = 0; i < functions->length(); ++i) {
626 RecordStats(isolate, Code::cast(functions->get(i))); 579 RecordStats(isolate, Code::cast(functions->get(i)));
627 } 580 }
628 } 581 }
629 582
630 Address GetGlobalStartAddressFromCodeTemplate(Object* undefined, 583 Address GetGlobalStartAddressFromCodeTemplate(Object* undefined,
631 JSObject* owner) { 584 JSObject* owner) {
632 Address old_address = nullptr; 585 Address old_address = nullptr;
633 Object* stored_value = owner->GetInternalField(kWasmGlobalsArrayBuffer); 586 Object* stored_value = owner->GetInternalField(kWasmGlobalsArrayBuffer);
634 if (stored_value != undefined) { 587 if (stored_value != undefined) {
635 old_address = static_cast<Address>( 588 old_address = static_cast<Address>(
636 JSArrayBuffer::cast(stored_value)->backing_store()); 589 JSArrayBuffer::cast(stored_value)->backing_store());
637 } 590 }
638 return old_address; 591 return old_address;
639 } 592 }
640 593
641 Handle<FixedArray> GetImportsMetadata(Factory* factory, 594 Handle<FixedArray> GetImportsData(Factory* factory, const WasmModule* module) {
642 const WasmModule* module) {
643 Handle<FixedArray> ret = factory->NewFixedArray( 595 Handle<FixedArray> ret = factory->NewFixedArray(
644 static_cast<int>(module->import_table.size()), TENURED); 596 static_cast<int>(module->import_table.size()), TENURED);
645 for (size_t i = 0; i < module->import_table.size(); ++i) { 597 for (size_t i = 0; i < module->import_table.size(); ++i) {
646 const WasmImport& import = module->import_table[i]; 598 const WasmImport& import = module->import_table[i];
599 if (import.kind != kExternalFunction) continue;
647 WasmName module_name = module->GetNameOrNull(import.module_name_offset, 600 WasmName module_name = module->GetNameOrNull(import.module_name_offset,
648 import.module_name_length); 601 import.module_name_length);
649 WasmName function_name = module->GetNameOrNull(import.function_name_offset, 602 WasmName function_name = module->GetNameOrNull(import.field_name_offset,
650 import.function_name_length); 603 import.field_name_length);
651 604
652 Handle<String> module_name_string = 605 Handle<String> module_name_string =
653 factory->InternalizeUtf8String(module_name); 606 factory->InternalizeUtf8String(module_name);
654 Handle<String> function_name_string = 607 Handle<String> function_name_string =
655 function_name.is_empty() 608 function_name.is_empty()
656 ? Handle<String>::null() 609 ? Handle<String>::null()
657 : factory->InternalizeUtf8String(function_name); 610 : factory->InternalizeUtf8String(function_name);
658 Handle<ByteArray> sig = 611 FunctionSig* fsig = module->functions[import.index].sig;
659 factory->NewByteArray(static_cast<int>(import.sig->parameter_count() + 612 Handle<ByteArray> sig = factory->NewByteArray(
660 import.sig->return_count()), 613 static_cast<int>(fsig->parameter_count() + fsig->return_count()),
661 TENURED); 614 TENURED);
662 sig->copy_in(0, reinterpret_cast<const byte*>(import.sig->raw_data()), 615 sig->copy_in(0, reinterpret_cast<const byte*>(fsig->raw_data()),
663 sig->length()); 616 sig->length());
664 Handle<FixedArray> encoded_import = 617 Handle<FixedArray> encoded_import =
665 factory->NewFixedArray(kWasmImportDataTableSize, TENURED); 618 factory->NewFixedArray(kWasmImportDataSize, TENURED);
666 encoded_import->set(kModuleName, *module_name_string); 619 encoded_import->set(kModuleName, *module_name_string);
667 if (!function_name_string.is_null()) { 620 if (!function_name_string.is_null()) {
668 encoded_import->set(kFunctionName, *function_name_string); 621 encoded_import->set(kFunctionName, *function_name_string);
669 } 622 }
670 encoded_import->set( 623 encoded_import->set(kOutputCount,
671 kOutputCount, 624 Smi::FromInt(static_cast<int>(fsig->return_count())));
672 Smi::FromInt(static_cast<int>(import.sig->return_count())));
673 encoded_import->set(kSignature, *sig); 625 encoded_import->set(kSignature, *sig);
674 ret->set(static_cast<int>(i), *encoded_import); 626 ret->set(static_cast<int>(i), *encoded_import);
675 } 627 }
676 return ret; 628 return ret;
677 } 629 }
678 630
679 bool CompileWrappersToImportedFunctions(Isolate* isolate, 631 Handle<Code> CompileImportWrapper(Isolate* isolate,
680 const Handle<JSReceiver> ffi, 632 const Handle<JSReceiver> ffi, int index,
681 std::vector<Handle<Code>>& imports, 633 Handle<FixedArray> import_data,
682 Handle<FixedArray> import_data, 634 ErrorThrower* thrower) {
683 ErrorThrower* thrower) { 635 Handle<FixedArray> data =
684 uint32_t import_count = static_cast<uint32_t>(import_data->length()); 636 import_data->GetValueChecked<FixedArray>(isolate, index);
685 if (import_count > 0) { 637 Handle<String> module_name =
686 imports.reserve(import_count); 638 data->GetValueChecked<String>(isolate, kModuleName);
687 for (uint32_t index = 0; index < import_count; ++index) { 639 MaybeHandle<String> function_name =
688 Handle<FixedArray> data = 640 data->GetValue<String>(isolate, kFunctionName);
689 import_data->GetValueChecked<FixedArray>(isolate, index);
690 Handle<String> module_name =
691 data->GetValueChecked<String>(isolate, kModuleName);
692 MaybeHandle<String> function_name =
693 data->GetValue<String>(isolate, kFunctionName);
694 641
695 // TODO(mtrofin): this is an uint32_t, actually. We should rationalize 642 // TODO(mtrofin): this is an uint32_t, actually. We should rationalize
696 // it when we rationalize signed/unsigned stuff. 643 // it when we rationalize signed/unsigned stuff.
697 int ret_count = Smi::cast(data->get(kOutputCount))->value(); 644 int ret_count = Smi::cast(data->get(kOutputCount))->value();
698 CHECK(ret_count >= 0); 645 CHECK_GE(ret_count, 0);
699 Handle<ByteArray> sig_data = 646 Handle<ByteArray> sig_data =
700 data->GetValueChecked<ByteArray>(isolate, kSignature); 647 data->GetValueChecked<ByteArray>(isolate, kSignature);
701 int sig_data_size = sig_data->length(); 648 int sig_data_size = sig_data->length();
702 int param_count = sig_data_size - ret_count; 649 int param_count = sig_data_size - ret_count;
703 CHECK(param_count >= 0); 650 CHECK(param_count >= 0);
704 651
705 MaybeHandle<JSReceiver> function = LookupFunction( 652 MaybeHandle<JSReceiver> function = LookupFunction(
706 thrower, isolate->factory(), ffi, index, module_name, function_name); 653 thrower, isolate->factory(), ffi, index, module_name, function_name);
707 if (function.is_null()) return false; 654 if (function.is_null()) return Handle<Code>::null();
708 Handle<Code> code; 655 Handle<Code> code;
709 Handle<JSReceiver> target = function.ToHandleChecked(); 656 Handle<JSReceiver> target = function.ToHandleChecked();
710 bool isMatch = false; 657 bool isMatch = false;
711 Handle<Code> export_wrapper_code; 658 Handle<Code> export_wrapper_code;
712 if (target->IsJSFunction()) { 659 if (target->IsJSFunction()) {
713 Handle<JSFunction> func = Handle<JSFunction>::cast(target); 660 Handle<JSFunction> func = Handle<JSFunction>::cast(target);
714 export_wrapper_code = handle(func->code()); 661 export_wrapper_code = handle(func->code());
715 if (export_wrapper_code->kind() == Code::JS_TO_WASM_FUNCTION) { 662 if (export_wrapper_code->kind() == Code::JS_TO_WASM_FUNCTION) {
716 int exported_param_count = 663 int exported_param_count =
717 Smi::cast(func->GetInternalField(kInternalArity))->value(); 664 Smi::cast(func->GetInternalField(kInternalArity))->value();
718 Handle<ByteArray> exportedSig = Handle<ByteArray>( 665 Handle<ByteArray> exportedSig = Handle<ByteArray>(
719 ByteArray::cast(func->GetInternalField(kInternalSignature))); 666 ByteArray::cast(func->GetInternalField(kInternalSignature)));
720 if (exported_param_count == param_count && 667 if (exported_param_count == param_count &&
721 exportedSig->length() == sig_data->length() && 668 exportedSig->length() == sig_data->length() &&
722 memcmp(exportedSig->data(), sig_data->data(), 669 memcmp(exportedSig->data(), sig_data->data(),
723 exportedSig->length()) == 0) { 670 exportedSig->length()) == 0) {
724 isMatch = true; 671 isMatch = true;
725 }
726 }
727 } 672 }
728 if (isMatch) {
729 int wasm_count = 0;
730 int const mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET);
731 for (RelocIterator it(*export_wrapper_code, mask); !it.done();
732 it.next()) {
733 RelocInfo* rinfo = it.rinfo();
734 Address target_address = rinfo->target_address();
735 Code* target = Code::GetCodeFromTargetAddress(target_address);
736 if (target->kind() == Code::WASM_FUNCTION) {
737 ++wasm_count;
738 code = handle(target);
739 }
740 }
741 DCHECK(wasm_count == 1);
742 } else {
743 // Copy the signature to avoid a raw pointer into a heap object when
744 // GC can happen.
745 Zone zone(isolate->allocator());
746 MachineRepresentation* reps =
747 zone.NewArray<MachineRepresentation>(sig_data_size);
748 memcpy(reps, sig_data->data(),
749 sizeof(MachineRepresentation) * sig_data_size);
750 FunctionSig sig(ret_count, param_count, reps);
751
752 code = compiler::CompileWasmToJSWrapper(isolate, target, &sig, index,
753 module_name, function_name);
754 }
755 imports.push_back(code);
756 } 673 }
757 } 674 }
758 return true; 675 if (isMatch) {
676 int wasm_count = 0;
677 int const mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET);
678 for (RelocIterator it(*export_wrapper_code, mask); !it.done(); it.next()) {
679 RelocInfo* rinfo = it.rinfo();
680 Address target_address = rinfo->target_address();
681 Code* target = Code::GetCodeFromTargetAddress(target_address);
682 if (target->kind() == Code::WASM_FUNCTION) {
683 ++wasm_count;
684 code = handle(target);
685 }
686 }
687 DCHECK(wasm_count == 1);
688 return code;
689 } else {
690 // Copy the signature to avoid a raw pointer into a heap object when
691 // GC can happen.
692 Zone zone(isolate->allocator());
693 MachineRepresentation* reps =
694 zone.NewArray<MachineRepresentation>(sig_data_size);
695 memcpy(reps, sig_data->data(),
696 sizeof(MachineRepresentation) * sig_data_size);
697 FunctionSig sig(ret_count, param_count, reps);
698
699 return compiler::CompileWasmToJSWrapper(isolate, target, &sig, index,
700 module_name, function_name);
701 }
759 } 702 }
760 703
761 void InitializeParallelCompilation( 704 void InitializeParallelCompilation(
762 Isolate* isolate, const std::vector<WasmFunction>& functions, 705 Isolate* isolate, const std::vector<WasmFunction>& functions,
763 std::vector<compiler::WasmCompilationUnit*>& compilation_units, 706 std::vector<compiler::WasmCompilationUnit*>& compilation_units,
764 ModuleEnv& module_env, ErrorThrower* thrower) { 707 ModuleEnv& module_env, ErrorThrower* thrower) {
765 for (uint32_t i = FLAG_skip_compiling_wasm_funcs; i < functions.size(); ++i) { 708 for (uint32_t i = FLAG_skip_compiling_wasm_funcs; i < functions.size(); ++i) {
766 compilation_units[i] = new compiler::WasmCompilationUnit( 709 const WasmFunction* func = &functions[i];
767 thrower, isolate, &module_env, &functions[i], i); 710 compilation_units[i] =
711 func->imported ? nullptr : new compiler::WasmCompilationUnit(
712 thrower, isolate, &module_env, func, i);
768 } 713 }
769 } 714 }
770 715
771 uint32_t* StartCompilationTasks( 716 uint32_t* StartCompilationTasks(
772 Isolate* isolate, 717 Isolate* isolate,
773 std::vector<compiler::WasmCompilationUnit*>& compilation_units, 718 std::vector<compiler::WasmCompilationUnit*>& compilation_units,
774 std::queue<compiler::WasmCompilationUnit*>& executed_units, 719 std::queue<compiler::WasmCompilationUnit*>& executed_units,
775 base::Semaphore* pending_tasks, base::Mutex& result_mutex, 720 base::Semaphore* pending_tasks, base::Mutex& result_mutex,
776 base::AtomicNumber<size_t>& next_unit) { 721 base::AtomicNumber<size_t>& next_unit) {
777 const size_t num_tasks = 722 const size_t num_tasks =
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
887 } 832 }
888 833
889 void CompileSequentially(Isolate* isolate, const WasmModule* module, 834 void CompileSequentially(Isolate* isolate, const WasmModule* module,
890 std::vector<Handle<Code>>& functions, 835 std::vector<Handle<Code>>& functions,
891 ErrorThrower* thrower, ModuleEnv* module_env) { 836 ErrorThrower* thrower, ModuleEnv* module_env) {
892 DCHECK(!thrower->error()); 837 DCHECK(!thrower->error());
893 838
894 for (uint32_t i = FLAG_skip_compiling_wasm_funcs; 839 for (uint32_t i = FLAG_skip_compiling_wasm_funcs;
895 i < module->functions.size(); ++i) { 840 i < module->functions.size(); ++i) {
896 const WasmFunction& func = module->functions[i]; 841 const WasmFunction& func = module->functions[i];
842 if (func.imported) continue; // Imports are compiled at instantiation time.
897 843
898 DCHECK_EQ(i, func.func_index);
899 WasmName str = module->GetName(func.name_offset, func.name_length); 844 WasmName str = module->GetName(func.name_offset, func.name_length);
900 Handle<Code> code = Handle<Code>::null(); 845 Handle<Code> code = Handle<Code>::null();
901 // Compile the function. 846 // Compile the function.
902 code = compiler::WasmCompilationUnit::CompileWasmFunction( 847 code = compiler::WasmCompilationUnit::CompileWasmFunction(
903 thrower, isolate, module_env, &func); 848 thrower, isolate, module_env, &func);
904 if (code.is_null()) { 849 if (code.is_null()) {
905 thrower->Error("Compilation of #%d:%.*s failed.", i, str.length(), 850 thrower->Error("Compilation of #%d:%.*s failed.", i, str.length(),
906 str.start()); 851 str.start());
907 break; 852 break;
908 } 853 }
909 // Install the code into the linker table. 854 // Install the code into the linker table.
910 functions[i] = code; 855 functions[i] = code;
911 } 856 }
912 } 857 }
913 858
914 void SetDebugSupport(Factory* factory, Handle<FixedArray> compiled_module, 859 void PatchDirectCalls(Handle<FixedArray> old_functions,
915 Handle<JSObject> js_object) { 860 Handle<FixedArray> new_functions, int start) {
916 Isolate* isolate = compiled_module->GetIsolate();
917 MaybeHandle<String> module_bytes_string =
918 compiled_module->GetValue<String>(isolate, kModuleBytes);
919 if (!module_bytes_string.is_null()) {
920 js_object->SetInternalField(kWasmModuleBytesString,
921 *module_bytes_string.ToHandleChecked());
922 }
923
924 MaybeHandle<ByteArray> function_name_table =
925 compiled_module->GetValue<ByteArray>(isolate, kFunctionNameTable);
926 if (!function_name_table.is_null()) {
927 js_object->SetInternalField(kWasmFunctionNamesArray,
928 *function_name_table.ToHandleChecked());
929 }
930 }
931
932 bool SetupGlobals(Isolate* isolate, MaybeHandle<JSObject> template_owner,
933 Handle<FixedArray> compiled_module, Handle<JSObject> instance,
934 ErrorThrower* thrower) {
935 uint32_t globals_size = static_cast<uint32_t>(
936 Smi::cast(compiled_module->get(kGlobalsSize))->value());
937 if (globals_size > 0) {
938 Handle<JSArrayBuffer> globals_buffer =
939 NewArrayBuffer(isolate, globals_size);
940 if (globals_buffer.is_null()) {
941 thrower->Error("Out of memory: wasm globals");
942 return false;
943 }
944 Address old_address =
945 template_owner.is_null()
946 ? nullptr
947 : GetGlobalStartAddressFromCodeTemplate(
948 *isolate->factory()->undefined_value(),
949 JSObject::cast(*template_owner.ToHandleChecked()));
950 RelocateGlobals(instance, old_address,
951 static_cast<Address>(globals_buffer->backing_store()));
952 instance->SetInternalField(kWasmGlobalsArrayBuffer, *globals_buffer);
953 }
954 return true;
955 }
956
957 bool SetupInstanceHeap(Isolate* isolate, Handle<FixedArray> compiled_module,
958 Handle<JSObject> instance, Handle<JSArrayBuffer> memory,
959 ErrorThrower* thrower) {
960 uint32_t min_mem_pages = static_cast<uint32_t>(
961 Smi::cast(compiled_module->get(kMinRequiredMemory))->value());
962 isolate->counters()->wasm_min_mem_pages_count()->AddSample(min_mem_pages);
963 // TODO(wasm): re-enable counter for max_mem_pages when we use that field.
964
965 if (memory.is_null() && min_mem_pages > 0) {
966 memory = AllocateMemory(thrower, isolate, min_mem_pages);
967 if (memory.is_null()) {
968 return false;
969 }
970 }
971
972 if (!memory.is_null()) {
973 instance->SetInternalField(kWasmMemArrayBuffer, *memory);
974 Address mem_start = static_cast<Address>(memory->backing_store());
975 uint32_t mem_size = static_cast<uint32_t>(memory->byte_length()->Number());
976 uint32_t old_mem_size = static_cast<uint32_t>(
977 compiled_module->GetValueChecked<HeapNumber>(isolate, kMemSize)
978 ->value());
979 MaybeHandle<JSArrayBuffer> old_mem =
980 compiled_module->GetValue<JSArrayBuffer>(isolate, kMemStart);
981 Address old_mem_start =
982 old_mem.is_null()
983 ? nullptr
984 : static_cast<Address>(old_mem.ToHandleChecked()->backing_store());
985 RelocateInstanceCode(instance, old_mem_start, mem_start, old_mem_size,
986 mem_size);
987 LoadDataSegments(compiled_module, mem_start, mem_size);
988 compiled_module->GetValueChecked<HeapNumber>(isolate, kMemSize)
989 ->set_value(static_cast<double>(mem_size));
990 compiled_module->set(kMemStart, *memory);
991 }
992 return true;
993 }
994
995 void FixupFunctionsAndImports(Handle<FixedArray> old_functions,
996 Handle<FixedArray> new_functions,
997 MaybeHandle<FixedArray> maybe_old_imports,
998 MaybeHandle<FixedArray> maybe_new_imports) {
999 DCHECK_EQ(new_functions->length(), old_functions->length()); 861 DCHECK_EQ(new_functions->length(), old_functions->length());
1000 862
1001 DisallowHeapAllocation no_gc; 863 DisallowHeapAllocation no_gc;
1002 std::map<Code*, Code*> old_to_new_code; 864 std::map<Code*, Code*> old_to_new_code;
1003 for (int i = 0; i < new_functions->length(); ++i) { 865 for (int i = 0; i < new_functions->length(); ++i) {
1004 old_to_new_code.insert(std::make_pair(Code::cast(old_functions->get(i)), 866 old_to_new_code.insert(std::make_pair(Code::cast(old_functions->get(i)),
1005 Code::cast(new_functions->get(i)))); 867 Code::cast(new_functions->get(i))));
1006 } 868 }
1007 DCHECK_EQ(maybe_old_imports.is_null(), maybe_new_imports.is_null());
1008 if (!maybe_old_imports.is_null()) {
1009 Handle<FixedArray> old_imports = maybe_old_imports.ToHandleChecked();
1010 Handle<FixedArray> new_imports = maybe_new_imports.ToHandleChecked();
1011 DCHECK_EQ(new_imports->length(), old_imports->length());
1012 for (int i = 0; i < new_imports->length(); ++i) {
1013 old_to_new_code.insert(std::make_pair(Code::cast(old_imports->get(i)),
1014 Code::cast(new_imports->get(i))));
1015 }
1016 }
1017 int mode_mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET); 869 int mode_mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET);
1018 AllowDeferredHandleDereference embedding_raw_address; 870 AllowDeferredHandleDereference embedding_raw_address;
1019 for (int i = 0; i < new_functions->length(); ++i) { 871 for (int i = start; i < new_functions->length(); ++i) {
1020 Code* wasm_function = Code::cast(new_functions->get(i)); 872 Code* wasm_function = Code::cast(new_functions->get(i));
1021 for (RelocIterator it(wasm_function, mode_mask); !it.done(); it.next()) { 873 for (RelocIterator it(wasm_function, mode_mask); !it.done(); it.next()) {
1022 Code* old_code = 874 Code* old_code =
1023 Code::GetCodeFromTargetAddress(it.rinfo()->target_address()); 875 Code::GetCodeFromTargetAddress(it.rinfo()->target_address());
1024 if (old_code->kind() == Code::WASM_TO_JS_FUNCTION || 876 if (old_code->kind() == Code::WASM_TO_JS_FUNCTION ||
1025 old_code->kind() == Code::WASM_FUNCTION) { 877 old_code->kind() == Code::WASM_FUNCTION) {
1026 auto found = old_to_new_code.find(old_code); 878 auto found = old_to_new_code.find(old_code);
1027 DCHECK(found != old_to_new_code.end()); 879 DCHECK(found != old_to_new_code.end());
1028 Code* new_code = found->second; 880 Code* new_code = found->second;
1029 // Avoid redundant updates, expected for wasm functions, if we're at the 881 if (new_code != old_code) {
1030 // first instance. 882 it.rinfo()->set_target_address(new_code->instruction_start(),
1031 if (new_code == old_code) { 883 UPDATE_WRITE_BARRIER,
1032 DCHECK(new_code->kind() == Code::WASM_FUNCTION); 884 SKIP_ICACHE_FLUSH);
1033 continue;
1034 } 885 }
1035 it.rinfo()->set_target_address(new_code->instruction_start(),
1036 UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
1037 } 886 }
1038 } 887 }
1039 } 888 }
1040 } 889 }
1041 890
1042 bool SetupImports(Isolate* isolate, Handle<FixedArray> compiled_module,
1043 Handle<JSObject> instance, ErrorThrower* thrower,
1044 Handle<JSReceiver> ffi) {
1045 //-------------------------------------------------------------------------
1046 // Compile wrappers to imported functions.
1047 //-------------------------------------------------------------------------
1048 std::vector<Handle<Code>> import_code;
1049 MaybeHandle<FixedArray> maybe_import_data =
1050 compiled_module->GetValue<FixedArray>(isolate, kImportData);
1051 Handle<FixedArray> import_data;
1052 if (maybe_import_data.ToHandle(&import_data)) {
1053 if (!CompileWrappersToImportedFunctions(isolate, ffi, import_code,
1054 import_data, thrower)) {
1055 return false;
1056 }
1057 }
1058
1059 RecordStats(isolate, import_code);
1060 if (import_code.empty()) return true;
1061
1062 Handle<FixedArray> new_imports =
1063 isolate->factory()->NewFixedArray(static_cast<int>(import_code.size()));
1064 for (int i = 0; i < new_imports->length(); ++i) {
1065 new_imports->set(i, *import_code[i]);
1066 }
1067 compiled_module->set(kImportMap, *new_imports);
1068 return true;
1069 }
1070
1071 bool SetupExportsObject(Handle<FixedArray> compiled_module, Isolate* isolate,
1072 Handle<JSObject> instance, ErrorThrower* thrower) {
1073 Factory* factory = isolate->factory();
1074 bool mem_export =
1075 static_cast<bool>(Smi::cast(compiled_module->get(kExportMem))->value());
1076 ModuleOrigin origin = static_cast<ModuleOrigin>(
1077 Smi::cast(compiled_module->get(kOrigin))->value());
1078
1079 MaybeHandle<FixedArray> maybe_exports =
1080 compiled_module->GetValue<FixedArray>(isolate, kExports);
1081 if (!maybe_exports.is_null() || mem_export) {
1082 PropertyDescriptor desc;
1083 desc.set_writable(false);
1084
1085 Handle<JSObject> exports_object = instance;
1086 if (origin == kWasmOrigin) {
1087 // Create the "exports" object.
1088 Handle<JSFunction> object_function = Handle<JSFunction>(
1089 isolate->native_context()->object_function(), isolate);
1090 exports_object = factory->NewJSObject(object_function, TENURED);
1091 Handle<String> exports_name = factory->InternalizeUtf8String("exports");
1092 JSObject::AddProperty(instance, exports_name, exports_object, READ_ONLY);
1093 }
1094 Handle<FixedArray> exports;
1095 if (maybe_exports.ToHandle(&exports)) {
1096 int exports_size = exports->length();
1097 for (int i = 0; i < exports_size; ++i) {
1098 if (thrower->error()) return false;
1099 Handle<FixedArray> export_metadata =
1100 exports->GetValueChecked<FixedArray>(isolate, i);
1101 Handle<Code> export_code =
1102 export_metadata->GetValueChecked<Code>(isolate, kExportCode);
1103 RecordStats(isolate, *export_code);
1104 Handle<String> name =
1105 export_metadata->GetValueChecked<String>(isolate, kExportName);
1106 int arity = Smi::cast(export_metadata->get(kExportArity))->value();
1107 MaybeHandle<ByteArray> signature =
1108 export_metadata->GetValue<ByteArray>(isolate, kExportedSignature);
1109 Handle<JSFunction> function = WrapExportCodeAsJSFunction(
1110 isolate, export_code, name, arity, signature, instance);
1111 desc.set_value(function);
1112 Maybe<bool> status = JSReceiver::DefineOwnProperty(
1113 isolate, exports_object, name, &desc, Object::THROW_ON_ERROR);
1114 if (!status.IsJust()) {
1115 thrower->Error("export of %.*s failed.", name->length(),
1116 name->ToCString().get());
1117 return false;
1118 }
1119 }
1120 }
1121 if (mem_export) {
1122 // Export the memory as a named property.
1123 Handle<String> name = factory->InternalizeUtf8String("memory");
1124 Handle<JSArrayBuffer> memory = Handle<JSArrayBuffer>(
1125 JSArrayBuffer::cast(instance->GetInternalField(kWasmMemArrayBuffer)));
1126 JSObject::AddProperty(exports_object, name, memory, READ_ONLY);
1127 }
1128 }
1129 return true;
1130 }
1131
1132 #define GET_COMPILED_MODULE_WEAK_RELATION_OR_NULL(Field) \ 891 #define GET_COMPILED_MODULE_WEAK_RELATION_OR_NULL(Field) \
1133 WeakCell* Get##Field(const FixedArray* compiled_module) { \ 892 WeakCell* Get##Field(const FixedArray* compiled_module) { \
1134 Object* obj = compiled_module->get(k##Field); \ 893 Object* obj = compiled_module->get(k##Field); \
1135 DCHECK_NOT_NULL(obj); \ 894 DCHECK_NOT_NULL(obj); \
1136 if (obj->IsWeakCell()) { \ 895 if (obj->IsWeakCell()) { \
1137 return WeakCell::cast(obj); \ 896 return WeakCell::cast(obj); \
1138 } else { \ 897 } else { \
1139 return nullptr; \ 898 return nullptr; \
1140 } \ 899 } \
1141 } 900 }
(...skipping 17 matching lines...) Expand all
1159 918
1160 if (old_mem_size > 0) { 919 if (old_mem_size > 0) {
1161 CHECK_NE(mem_start, undefined); 920 CHECK_NE(mem_start, undefined);
1162 old_mem_address = 921 old_mem_address =
1163 static_cast<Address>(JSArrayBuffer::cast(mem_start)->backing_store()); 922 static_cast<Address>(JSArrayBuffer::cast(mem_start)->backing_store());
1164 } 923 }
1165 int mode_mask = RelocInfo::ModeMask(RelocInfo::WASM_MEMORY_REFERENCE) | 924 int mode_mask = RelocInfo::ModeMask(RelocInfo::WASM_MEMORY_REFERENCE) |
1166 RelocInfo::ModeMask(RelocInfo::WASM_MEMORY_SIZE_REFERENCE) | 925 RelocInfo::ModeMask(RelocInfo::WASM_MEMORY_SIZE_REFERENCE) |
1167 RelocInfo::ModeMask(RelocInfo::WASM_GLOBAL_REFERENCE); 926 RelocInfo::ModeMask(RelocInfo::WASM_GLOBAL_REFERENCE);
1168 927
1169 Object* fct_obj = compiled_module->get(kFunctions); 928 Object* fct_obj = compiled_module->get(kCodeTable);
1170 if (fct_obj != nullptr && fct_obj != undefined && 929 if (fct_obj != nullptr && fct_obj != undefined &&
1171 (old_mem_size > 0 || globals_start != nullptr)) { 930 (old_mem_size > 0 || globals_start != nullptr)) {
1172 FixedArray* functions = FixedArray::cast(fct_obj); 931 FixedArray* functions = FixedArray::cast(fct_obj);
1173 for (int i = 0; i < functions->length(); ++i) { 932 for (int i = 0; i < functions->length(); ++i) {
1174 Code* code = Code::cast(functions->get(i)); 933 Code* code = Code::cast(functions->get(i));
1175 bool changed = false; 934 bool changed = false;
1176 for (RelocIterator it(code, mode_mask); !it.done(); it.next()) { 935 for (RelocIterator it(code, mode_mask); !it.done(); it.next()) {
1177 RelocInfo::Mode mode = it.rinfo()->rmode(); 936 RelocInfo::Mode mode = it.rinfo()->rmode();
1178 if (RelocInfo::IsWasmMemoryReference(mode) || 937 if (RelocInfo::IsWasmMemoryReference(mode) ||
1179 RelocInfo::IsWasmMemorySizeReference(mode)) { 938 RelocInfo::IsWasmMemorySizeReference(mode)) {
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1246 } 1005 }
1247 1006
1248 } // namespace 1007 } // namespace
1249 1008
1250 MaybeHandle<FixedArray> WasmModule::CompileFunctions( 1009 MaybeHandle<FixedArray> WasmModule::CompileFunctions(
1251 Isolate* isolate, ErrorThrower* thrower) const { 1010 Isolate* isolate, ErrorThrower* thrower) const {
1252 Factory* factory = isolate->factory(); 1011 Factory* factory = isolate->factory();
1253 1012
1254 MaybeHandle<FixedArray> nothing; 1013 MaybeHandle<FixedArray> nothing;
1255 1014
1256 WasmModuleInstance temp_instance_for_compilation(this); 1015 WasmModuleInstance temp_instance(this);
1257 temp_instance_for_compilation.context = isolate->native_context(); 1016 temp_instance.context = isolate->native_context();
1258 temp_instance_for_compilation.mem_size = GetMinModuleMemSize(this); 1017 temp_instance.mem_size = GetMinModuleMemSize(this);
1259 temp_instance_for_compilation.mem_start = nullptr; 1018 temp_instance.mem_start = nullptr;
1260 temp_instance_for_compilation.globals_start = nullptr; 1019 temp_instance.globals_start = nullptr;
1261 1020
1262 MaybeHandle<FixedArray> indirect_table = 1021 MaybeHandle<FixedArray> indirect_table =
1263 function_tables.size() 1022 function_tables.size()
1264 ? factory->NewFixedArray(static_cast<int>(function_tables.size()), 1023 ? factory->NewFixedArray(static_cast<int>(function_tables.size()),
1265 TENURED) 1024 TENURED)
1266 : MaybeHandle<FixedArray>(); 1025 : MaybeHandle<FixedArray>();
1267 for (uint32_t i = 0; i < function_tables.size(); ++i) { 1026 for (uint32_t i = 0; i < function_tables.size(); ++i) {
1268 Handle<FixedArray> values = wasm::BuildFunctionTable(isolate, i, this); 1027 Handle<FixedArray> values = wasm::BuildFunctionTable(isolate, i, this);
1269 temp_instance_for_compilation.function_tables[i] = values; 1028 temp_instance.function_tables[i] = values;
1270 1029
1271 Handle<FixedArray> metadata = isolate->factory()->NewFixedArray( 1030 Handle<FixedArray> metadata = isolate->factory()->NewFixedArray(
1272 kWasmIndirectFunctionTableMetadataSize, TENURED); 1031 kWasmIndirectFunctionTableDataSize, TENURED);
1273 metadata->set(kSize, Smi::FromInt(function_tables[i].size)); 1032 metadata->set(kSize, Smi::FromInt(function_tables[i].size));
1274 metadata->set(kTable, *values); 1033 metadata->set(kTable, *values);
1275 indirect_table.ToHandleChecked()->set(i, *metadata); 1034 indirect_table.ToHandleChecked()->set(i, *metadata);
1276 } 1035 }
1277 1036
1278 HistogramTimerScope wasm_compile_module_time_scope( 1037 HistogramTimerScope wasm_compile_module_time_scope(
1279 isolate->counters()->wasm_compile_module_time()); 1038 isolate->counters()->wasm_compile_module_time());
1280 1039
1281 ModuleEnv module_env; 1040 ModuleEnv module_env;
1282 module_env.module = this; 1041 module_env.module = this;
1283 module_env.instance = &temp_instance_for_compilation; 1042 module_env.instance = &temp_instance;
1284 module_env.origin = origin; 1043 module_env.origin = origin;
1285 InitializePlaceholders(factory, &module_env.placeholders, functions.size());
1286 1044
1287 Handle<FixedArray> compiled_functions = 1045 // The {code_table} array contains import wrappers and functions (which
1288 factory->NewFixedArray(static_cast<int>(functions.size()), TENURED); 1046 // are both included in {functions.size()}, and export wrappers.
1047 int code_table_size =
1048 static_cast<int>(functions.size() + num_exported_functions);
1049 Handle<FixedArray> code_table =
1050 factory->NewFixedArray(static_cast<int>(code_table_size), TENURED);
1289 1051
1290 MaybeHandle<FixedArray> maybe_imports; 1052 // Initialize the code table with placeholders.
1291 if (import_table.size() > 0) { 1053 for (uint32_t i = 0; i < functions.size(); i++) {
1292 temp_instance_for_compilation.import_code.resize(import_table.size()); 1054 Code::Kind kind = Code::WASM_FUNCTION;
1293 Handle<FixedArray> imports = 1055 if (i < num_imported_functions) kind = Code::WASM_TO_JS_FUNCTION;
1294 factory->NewFixedArray(static_cast<int>(import_table.size())); 1056 Handle<Code> placeholder = CreatePlaceholder(factory, i, kind);
1295 for (uint32_t i = 0; i < import_table.size(); ++i) { 1057 code_table->set(static_cast<int>(i), *placeholder);
1296 Handle<Code> placeholder = 1058 temp_instance.function_code[i] = placeholder;
1297 CreatePlaceholder(factory, i, Code::WASM_TO_JS_FUNCTION);
1298 temp_instance_for_compilation.import_code[i] = placeholder;
1299 imports->set(i, *placeholder);
1300 }
1301 maybe_imports = imports;
1302 } 1059 }
1060
1303 isolate->counters()->wasm_functions_per_module()->AddSample( 1061 isolate->counters()->wasm_functions_per_module()->AddSample(
1304 static_cast<int>(functions.size())); 1062 static_cast<int>(functions.size()));
1305 if (FLAG_wasm_num_compilation_tasks != 0) { 1063 if (!FLAG_trace_wasm_decoder && FLAG_wasm_num_compilation_tasks != 0) {
1306 CompileInParallel(isolate, this, 1064 // Avoid a race condition by collecting results into a second vector.
1307 temp_instance_for_compilation.function_code, thrower, 1065 std::vector<Handle<Code>> results;
1308 &module_env); 1066 results.reserve(temp_instance.function_code.size());
1067 for (size_t i = 0; i < temp_instance.function_code.size(); i++) {
1068 results.push_back(temp_instance.function_code[i]);
1069 }
1070 CompileInParallel(isolate, this, results, thrower, &module_env);
1071
1072 for (size_t i = 0; i < results.size(); i++) {
1073 temp_instance.function_code[i] = results[i];
1074 }
1309 } else { 1075 } else {
1310 CompileSequentially(isolate, this, 1076 CompileSequentially(isolate, this, temp_instance.function_code, thrower,
1311 temp_instance_for_compilation.function_code, thrower,
1312 &module_env); 1077 &module_env);
1313 } 1078 }
1314 if (thrower->error()) return nothing; 1079 if (thrower->error()) return nothing;
1315 1080
1316 // At this point, compilation has completed. Update the code table. 1081 // At this point, compilation has completed. Update the code table.
1317 for (size_t i = FLAG_skip_compiling_wasm_funcs; 1082 for (size_t i = FLAG_skip_compiling_wasm_funcs;
1318 i < temp_instance_for_compilation.function_code.size(); ++i) { 1083 i < temp_instance.function_code.size(); ++i) {
1319 Code* code = *temp_instance_for_compilation.function_code[i]; 1084 Code* code = *temp_instance.function_code[i];
1320 compiled_functions->set(static_cast<int>(i), code); 1085 code_table->set(static_cast<int>(i), code);
1321 } 1086 }
1322 1087
1323 LinkModuleFunctions(isolate, compiled_functions); 1088 // Link the functions in the module.
1324 1089 for (size_t i = FLAG_skip_compiling_wasm_funcs;
1325 // TODO(mtrofin): do we need to flush the cache here? 1090 i < temp_instance.function_code.size(); ++i) {
1326 FlushAssemblyCache(isolate, compiled_functions); 1091 Handle<Code> code = temp_instance.function_code[i];
1092 bool modified = LinkFunction(code, temp_instance.function_code);
1093 if (modified) {
1094 // TODO(mtrofin): do we need to flush the cache here?
1095 Assembler::FlushICache(isolate, code->instruction_start(),
1096 code->instruction_size());
1097 }
1098 }
1327 1099
1328 // Create the compiled module object, and populate with compiled functions 1100 // Create the compiled module object, and populate with compiled functions
1329 // and information needed at instantiation time. This object needs to be 1101 // and information needed at instantiation time. This object needs to be
1330 // serializable. Instantiation may occur off a deserialized version of this 1102 // serializable. Instantiation may occur off a deserialized version of this
1331 // object. 1103 // object.
1332 Handle<FixedArray> ret = 1104 Handle<FixedArray> ret =
1333 factory->NewFixedArray(kCompiledWasmObjectTableSize, TENURED); 1105 factory->NewFixedArray(kWasmCompiledModuleSize, TENURED);
1334 ret->set(kFunctions, *compiled_functions); 1106 ret->set(kCodeTable, *code_table);
1335 if (!indirect_table.is_null()) { 1107 if (!indirect_table.is_null()) {
1336 ret->set(kTableOfIndirectFunctionTables, *indirect_table.ToHandleChecked()); 1108 ret->set(kTableOfIndirectFunctionTables, *indirect_table.ToHandleChecked());
1337 } 1109 }
1338 if (!maybe_imports.is_null()) { 1110 Handle<FixedArray> import_data = GetImportsData(factory, this);
1339 ret->set(kImportMap, *maybe_imports.ToHandleChecked());
1340 }
1341 Handle<FixedArray> import_data = GetImportsMetadata(factory, this);
1342 ret->set(kImportData, *import_data); 1111 ret->set(kImportData, *import_data);
1343 1112
1344 // Compile export functions. 1113 // Compile exported function wrappers.
1345 int export_size = static_cast<int>(export_table.size()); 1114 int export_size = static_cast<int>(num_exported_functions);
1346 Handle<Code> startup_fct;
1347 if (export_size > 0) { 1115 if (export_size > 0) {
1348 Handle<FixedArray> exports = factory->NewFixedArray(export_size, TENURED); 1116 Handle<FixedArray> exports = factory->NewFixedArray(export_size, TENURED);
1349 for (int i = 0; i < export_size; ++i) { 1117 int index = -1;
1350 Handle<FixedArray> export_metadata = 1118
1351 factory->NewFixedArray(kWasmExportMetadataTableSize, TENURED); 1119 for (const WasmExport& exp : export_table) {
1352 const WasmExport& exp = export_table[i]; 1120 if (exp.kind != kExternalFunction)
1353 FunctionSig* funcSig = functions[exp.func_index].sig; 1121 continue; // skip non-function exports.
1122 index++;
1123 Handle<FixedArray> export_data =
1124 factory->NewFixedArray(kWasmExportDataSize, TENURED);
1125 FunctionSig* funcSig = functions[exp.index].sig;
1354 Handle<ByteArray> exportedSig = 1126 Handle<ByteArray> exportedSig =
1355 factory->NewByteArray(static_cast<int>(funcSig->parameter_count() + 1127 factory->NewByteArray(static_cast<int>(funcSig->parameter_count() +
1356 funcSig->return_count()), 1128 funcSig->return_count()),
1357 TENURED); 1129 TENURED);
1358 exportedSig->copy_in(0, 1130 exportedSig->copy_in(0,
1359 reinterpret_cast<const byte*>(funcSig->raw_data()), 1131 reinterpret_cast<const byte*>(funcSig->raw_data()),
1360 exportedSig->length()); 1132 exportedSig->length());
1361 export_metadata->set(kExportedSignature, *exportedSig); 1133 export_data->set(kExportedSignature, *exportedSig);
1362 WasmName str = GetName(exp.name_offset, exp.name_length); 1134 WasmName str = GetName(exp.name_offset, exp.name_length);
1363 Handle<String> name = factory->InternalizeUtf8String(str); 1135 Handle<String> name = factory->InternalizeUtf8String(str);
1364 Handle<Code> code = 1136 Handle<Code> code = code_table->GetValueChecked<Code>(isolate, exp.index);
1365 temp_instance_for_compilation.function_code[exp.func_index];
1366 Handle<Code> export_code = compiler::CompileJSToWasmWrapper( 1137 Handle<Code> export_code = compiler::CompileJSToWasmWrapper(
1367 isolate, &module_env, code, exp.func_index); 1138 isolate, &module_env, code, exp.index);
1368 if (thrower->error()) return nothing; 1139 if (thrower->error()) return nothing;
1369 export_metadata->set(kExportCode, *export_code); 1140 export_data->set(kExportName, *name);
1370 export_metadata->set(kExportName, *name); 1141 export_data->set(kExportArity,
1371 export_metadata->set( 1142 Smi::FromInt(static_cast<int>(
1372 kExportArity, Smi::FromInt(static_cast<int>( 1143 functions[exp.index].sig->parameter_count())));
1373 functions[exp.func_index].sig->parameter_count()))); 1144 export_data->set(kExportedFunctionIndex,
1374 export_metadata->set(kExportedFunctionIndex, 1145 Smi::FromInt(static_cast<int>(exp.index)));
1375 Smi::FromInt(static_cast<int>(exp.func_index))); 1146 exports->set(index, *export_data);
1376 exports->set(i, *export_metadata); 1147 code_table->set(static_cast<int>(functions.size() + index), *export_code);
1377 if (exp.func_index == start_function_index) {
1378 startup_fct = export_code;
1379 }
1380 } 1148 }
1381 ret->set(kExports, *exports); 1149 ret->set(kExportData, *exports);
1382 } 1150 }
1383 1151
1384 // Compile startup function, if we haven't already. 1152 // Record data for startup function.
1385 if (start_function_index >= 0) { 1153 if (start_function_index >= 0) {
1386 uint32_t index = static_cast<uint32_t>(start_function_index);
1387 HandleScope scope(isolate); 1154 HandleScope scope(isolate);
1388 if (startup_fct.is_null()) { 1155 Handle<FixedArray> startup_data =
1389 Handle<Code> code = temp_instance_for_compilation.function_code[index]; 1156 factory->NewFixedArray(kWasmExportDataSize, TENURED);
1390 DCHECK_EQ(0, functions[index].sig->parameter_count()); 1157 startup_data->set(kExportArity, Smi::FromInt(0));
1391 startup_fct = 1158 startup_data->set(kExportedFunctionIndex,
1392 compiler::CompileJSToWasmWrapper(isolate, &module_env, code, index); 1159 Smi::FromInt(start_function_index));
1393 } 1160 ret->set(kStartupData, *startup_data);
1394 Handle<FixedArray> metadata =
1395 factory->NewFixedArray(kWasmExportMetadataTableSize, TENURED);
1396 metadata->set(kExportCode, *startup_fct);
1397 metadata->set(kExportArity, Smi::FromInt(0));
1398 metadata->set(kExportedFunctionIndex, Smi::FromInt(start_function_index));
1399 ret->set(kStartupFunction, *metadata);
1400 } 1161 }
1401 1162
1402 // TODO(wasm): saving the module bytes for debugging is wasteful. We should 1163 // TODO(wasm): saving the module bytes for debugging is wasteful. We should
1403 // consider downloading this on-demand. 1164 // consider downloading this on-demand.
1404 { 1165 {
1405 size_t module_bytes_len = module_end - module_start; 1166 size_t module_bytes_len = module_end - module_start;
1406 DCHECK_LE(module_bytes_len, static_cast<size_t>(kMaxInt)); 1167 DCHECK_LE(module_bytes_len, static_cast<size_t>(kMaxInt));
1407 Vector<const uint8_t> module_bytes_vec(module_start, 1168 Vector<const uint8_t> module_bytes_vec(module_start,
1408 static_cast<int>(module_bytes_len)); 1169 static_cast<int>(module_bytes_len));
1409 Handle<String> module_bytes_string = 1170 Handle<String> module_bytes_string =
1410 factory->NewStringFromOneByte(module_bytes_vec, TENURED) 1171 factory->NewStringFromOneByte(module_bytes_vec, TENURED)
1411 .ToHandleChecked(); 1172 .ToHandleChecked();
1412 ret->set(kModuleBytes, *module_bytes_string); 1173 ret->set(kModuleBytes, *module_bytes_string);
1413 } 1174 }
1414 1175
1415 Handle<ByteArray> function_name_table = 1176 Handle<ByteArray> function_name_table =
1416 BuildFunctionNamesTable(isolate, module_env.module); 1177 BuildFunctionNamesTable(isolate, module_env.module);
1417 ret->set(kFunctionNameTable, *function_name_table); 1178 ret->set(kFunctionNameTable, *function_name_table);
1418 ret->set(kMinRequiredMemory, Smi::FromInt(min_mem_pages)); 1179 ret->set(kMinRequiredMemory, Smi::FromInt(min_mem_pages));
1419 if (data_segments.size() > 0) SaveDataSegmentInfo(factory, this, ret); 1180 if (data_segments.size() > 0) SaveDataSegmentInfo(factory, this, ret);
1420 ret->set(kGlobalsSize, Smi::FromInt(globals_size)); 1181 ret->set(kGlobalsSize, Smi::FromInt(globals_size));
1421 ret->set(kExportMem, Smi::FromInt(mem_export)); 1182 ret->set(kExportMem, Smi::FromInt(mem_export));
1422 ret->set(kOrigin, Smi::FromInt(origin)); 1183 ret->set(kOrigin, Smi::FromInt(origin));
1423 Handle<HeapNumber> size_as_object = factory->NewHeapNumber( 1184 Handle<HeapNumber> size_as_object = factory->NewHeapNumber(
1424 static_cast<double>(temp_instance_for_compilation.mem_size), MUTABLE, 1185 static_cast<double>(temp_instance.mem_size), MUTABLE, TENURED);
1425 TENURED);
1426 ret->set(kMemSize, *size_as_object); 1186 ret->set(kMemSize, *size_as_object);
1427 return ret; 1187 return ret;
1428 } 1188 }
1429 1189
1430 void PatchJSWrapper(Isolate* isolate, Handle<Code> wrapper, 1190 void PatchJSWrapper(Isolate* isolate, Handle<Code> wrapper,
1431 Handle<Code> new_target) { 1191 Handle<Code> new_target) {
1432 AllowDeferredHandleDereference embedding_raw_address; 1192 AllowDeferredHandleDereference embedding_raw_address;
1433 bool seen = false; 1193 bool seen = false;
1434 for (RelocIterator it(*wrapper, 1 << RelocInfo::CODE_TARGET); !it.done(); 1194 for (RelocIterator it(*wrapper, 1 << RelocInfo::CODE_TARGET); !it.done();
1435 it.next()) { 1195 it.next()) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1469 ->GetValueChecked<FixedArray>(isolate, kTable); 1229 ->GetValueChecked<FixedArray>(isolate, kTable);
1470 for (int fct_index = 0; fct_index < wasm_functions->length(); ++fct_index) { 1230 for (int fct_index = 0; fct_index < wasm_functions->length(); ++fct_index) {
1471 Handle<Code> wasm_function = 1231 Handle<Code> wasm_function =
1472 wasm_functions->GetValueChecked<Code>(isolate, fct_index); 1232 wasm_functions->GetValueChecked<Code>(isolate, fct_index);
1473 PatchFunctionTable(wasm_function, table_to_replace, cloned_table); 1233 PatchFunctionTable(wasm_function, table_to_replace, cloned_table);
1474 } 1234 }
1475 } 1235 }
1476 return cloned_indirect_tables; 1236 return cloned_indirect_tables;
1477 } 1237 }
1478 1238
1479 Handle<FixedArray> CloneModuleForInstance(Isolate* isolate, 1239 // Instantiates a WASM module, creating a WebAssembly.Instance from a
1480 Handle<JSObject> module_object, 1240 // WebAssembly.Module.
1481 bool* template_is_owned,
1482 Handle<FixedArray>* module_template) {
1483 Factory* factory = isolate->factory();
1484
1485 Handle<FixedArray> original;
1486 for (int i = 0; i < 2; ++i) {
1487 original = handle(FixedArray::cast(module_object->GetInternalField(0)));
1488 if (GetOwningInstance(*original) == nullptr) {
1489 *template_is_owned = false;
1490 *module_template = original;
1491 return original;
1492 }
1493 if (i < 1) {
1494 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags,
1495 GarbageCollectionReason::kRuntime);
1496 }
1497 }
1498 *template_is_owned = true;
1499 *module_template = original;
1500
1501 // We insert the latest clone in front.
1502 Handle<FixedArray> clone = factory->CopyFixedArray(original);
1503 Handle<WeakCell> weak_link_to_wasm_obj =
1504 original->GetValueChecked<WeakCell>(isolate, kModuleObject);
1505
1506 clone->set(kModuleObject, *weak_link_to_wasm_obj);
1507 Handle<WeakCell> link_to_original = factory->NewWeakCell(original);
1508 clone->set(kNextInstance, *link_to_original);
1509 Handle<WeakCell> link_to_clone = factory->NewWeakCell(clone);
1510 original->set(kPrevInstance, *link_to_clone);
1511 JSObject::cast(weak_link_to_wasm_obj->value())->SetInternalField(0, *clone);
1512
1513 // Clone each wasm code object.
1514 Handle<FixedArray> orig_wasm_functions =
1515 original->GetValueChecked<FixedArray>(isolate, kFunctions);
1516 Handle<FixedArray> clone_wasm_functions =
1517 factory->CopyFixedArray(orig_wasm_functions);
1518 clone->set(kFunctions, *clone_wasm_functions);
1519 for (int i = 0; i < clone_wasm_functions->length(); ++i) {
1520 Handle<Code> orig_code =
1521 clone_wasm_functions->GetValueChecked<Code>(isolate, i);
1522 Handle<Code> cloned_code = factory->CopyCode(orig_code);
1523 clone_wasm_functions->set(i, *cloned_code);
1524 }
1525
1526 MaybeHandle<FixedArray> maybe_orig_exports =
1527 original->GetValue<FixedArray>(isolate, kExports);
1528 Handle<FixedArray> orig_exports;
1529 if (maybe_orig_exports.ToHandle(&orig_exports)) {
1530 Handle<FixedArray> cloned_exports = factory->CopyFixedArray(orig_exports);
1531 clone->set(kExports, *cloned_exports);
1532 for (int i = 0; i < orig_exports->length(); ++i) {
1533 Handle<FixedArray> export_metadata =
1534 orig_exports->GetValueChecked<FixedArray>(isolate, i);
1535 Handle<FixedArray> clone_metadata =
1536 factory->CopyFixedArray(export_metadata);
1537 cloned_exports->set(i, *clone_metadata);
1538 Handle<Code> orig_code =
1539 export_metadata->GetValueChecked<Code>(isolate, kExportCode);
1540 Handle<Code> cloned_code = factory->CopyCode(orig_code);
1541 clone_metadata->set(kExportCode, *cloned_code);
1542 // TODO(wasm): This is actually a uint32_t, but since FixedArray indexes
1543 // in int, we are taking the risk of invalid values.
1544 int exported_fct_index =
1545 Smi::cast(export_metadata->get(kExportedFunctionIndex))->value();
1546 CHECK_GE(exported_fct_index, 0);
1547 CHECK_LT(exported_fct_index, clone_wasm_functions->length());
1548 Handle<Code> new_target = clone_wasm_functions->GetValueChecked<Code>(
1549 isolate, exported_fct_index);
1550 PatchJSWrapper(isolate, cloned_code, new_target);
1551 }
1552 }
1553
1554 MaybeHandle<FixedArray> maybe_startup =
1555 original->GetValue<FixedArray>(isolate, kStartupFunction);
1556 if (!maybe_startup.is_null()) {
1557 Handle<FixedArray> startup_metadata =
1558 factory->CopyFixedArray(maybe_startup.ToHandleChecked());
1559 Handle<Code> startup_fct_clone = factory->CopyCode(
1560 startup_metadata->GetValueChecked<Code>(isolate, kExportCode));
1561 startup_metadata->set(kExportCode, *startup_fct_clone);
1562 clone->set(kStartupFunction, *startup_metadata);
1563 // TODO(wasm): see todo above about int vs size_t indexing in FixedArray.
1564 int startup_fct_index =
1565 Smi::cast(startup_metadata->get(kExportedFunctionIndex))->value();
1566 CHECK_GE(startup_fct_index, 0);
1567 CHECK_LT(startup_fct_index, clone_wasm_functions->length());
1568 Handle<Code> new_target =
1569 clone_wasm_functions->GetValueChecked<Code>(isolate, startup_fct_index);
1570 PatchJSWrapper(isolate, startup_fct_clone, new_target);
1571 }
1572 clone->set(kImportMap, *isolate->factory()->undefined_value());
1573 return clone;
1574 }
1575
1576 // Instantiates a wasm module as a JSObject.
1577 // * allocates a backing store of {mem_size} bytes.
1578 // * installs a named property "memory" for that buffer if exported
1579 // * installs named properties on the object for exported functions
1580 // * compiles wasm code to machine code
1581 MaybeHandle<JSObject> WasmModule::Instantiate(Isolate* isolate, 1241 MaybeHandle<JSObject> WasmModule::Instantiate(Isolate* isolate,
1242 ErrorThrower* thrower,
1582 Handle<JSObject> module_object, 1243 Handle<JSObject> module_object,
1583 Handle<JSReceiver> ffi, 1244 Handle<JSReceiver> ffi,
1584 Handle<JSArrayBuffer> memory) { 1245 Handle<JSArrayBuffer> memory) {
1246 MaybeHandle<JSObject> nothing;
1585 HistogramTimerScope wasm_instantiate_module_time_scope( 1247 HistogramTimerScope wasm_instantiate_module_time_scope(
1586 isolate->counters()->wasm_instantiate_module_time()); 1248 isolate->counters()->wasm_instantiate_module_time());
1587 ErrorThrower thrower(isolate, "WasmModule::Instantiate()");
1588 Factory* factory = isolate->factory(); 1249 Factory* factory = isolate->factory();
1589 1250
1590 bool template_is_owned = false; 1251 //--------------------------------------------------------------------------
1591 Handle<FixedArray> compiled_module_template; 1252 // Reuse the compiled module (if no owner), otherwise clone.
1592 Handle<FixedArray> compiled_module = CloneModuleForInstance( 1253 //--------------------------------------------------------------------------
1593 isolate, module_object, &template_is_owned, &compiled_module_template); 1254 Handle<FixedArray> compiled_module;
1594 1255 Handle<FixedArray> code_table;
1595 MaybeHandle<JSObject> template_owner; 1256 Handle<FixedArray> old_code_table;
1596 if (template_is_owned) { 1257 Handle<JSObject> owner;
1597 Handle<WeakCell> weak_owner = 1258 {
1598 compiled_module_template->GetValueChecked<WeakCell>(isolate, 1259 Handle<FixedArray> original(
1599 kOwningInstance); 1260 FixedArray::cast(module_object->GetInternalField(0)), isolate);
1600 template_owner = handle(JSObject::cast(weak_owner->value())); 1261 // Always make a new copy of the code_table, since the old_code_table
1601 } 1262 // may still have placeholders for imports.
1602 // These fields are compulsory. 1263 old_code_table = original->GetValueChecked<FixedArray>(isolate, kCodeTable);
1603 Handle<FixedArray> code_table = 1264 code_table = factory->CopyFixedArray(old_code_table);
1604 compiled_module->GetValueChecked<FixedArray>(isolate, kFunctions); 1265
1605 1266 WeakCell* tmp = GetOwningInstance(*original);
1606 RecordStats(isolate, code_table); 1267 if (tmp != nullptr) {
1607 1268 // There is already an owner, clone everything.
1608 MaybeHandle<JSObject> nothing; 1269 owner = Handle<JSObject>(JSObject::cast(tmp->value()), isolate);
1609 1270 // Insert the latest clone in front.
1271 compiled_module = factory->CopyFixedArray(original);
1272 Handle<WeakCell> weak_link_to_wasm_obj =
1273 original->GetValueChecked<WeakCell>(isolate, kModuleObject);
1274
1275 compiled_module->set(kModuleObject, *weak_link_to_wasm_obj);
1276 Handle<WeakCell> link_to_original = factory->NewWeakCell(original);
1277 compiled_module->set(kNextInstance, *link_to_original);
1278 Handle<WeakCell> link_to_clone = factory->NewWeakCell(compiled_module);
1279 original->set(kPrevInstance, *link_to_clone);
1280 JSObject::cast(weak_link_to_wasm_obj->value())
1281 ->SetInternalField(0, *compiled_module);
1282
1283 // Clone the code for WASM functions and exports.
1284 for (int i = 0; i < code_table->length(); ++i) {
1285 Handle<Code> orig_code = code_table->GetValueChecked<Code>(isolate, i);
1286 switch (orig_code->kind()) {
1287 case Code::WASM_TO_JS_FUNCTION:
1288 // Imports will be overwritten with newly compiled wrappers.
1289 break;
1290 case Code::JS_TO_WASM_FUNCTION:
1291 case Code::WASM_FUNCTION: {
1292 Handle<Code> code = factory->CopyCode(orig_code);
1293 code_table->set(i, *code);
1294 break;
1295 }
1296 default:
1297 UNREACHABLE();
1298 }
1299 }
1300 RecordStats(isolate, code_table);
1301 } else {
1302 // There was no owner, so we can reuse the original.
1303 compiled_module = original;
1304 }
1305 compiled_module->set(kCodeTable, *code_table);
1306 }
1307
1308 //--------------------------------------------------------------------------
1309 // Allocate the instance object.
1310 //--------------------------------------------------------------------------
1610 Handle<Map> map = factory->NewMap( 1311 Handle<Map> map = factory->NewMap(
1611 JS_OBJECT_TYPE, 1312 JS_OBJECT_TYPE,
1612 JSObject::kHeaderSize + kWasmModuleInternalFieldCount * kPointerSize); 1313 JSObject::kHeaderSize + kWasmModuleInternalFieldCount * kPointerSize);
1613 Handle<JSObject> js_object = factory->NewJSObjectFromMap(map, TENURED); 1314 Handle<JSObject> instance = factory->NewJSObjectFromMap(map, TENURED);
1614 js_object->SetInternalField(kWasmModuleCodeTable, *code_table); 1315 instance->SetInternalField(kWasmModuleCodeTable, *code_table);
1615 1316
1616 // Remember the old imports, for the case when we are at the first instance - 1317 //--------------------------------------------------------------------------
1617 // they will be replaced with the instance's actual imports in SetupImports. 1318 // Set up the memory for the new instance.
1618 MaybeHandle<FixedArray> old_imports = 1319 //--------------------------------------------------------------------------
1619 compiled_module_template->GetValue<FixedArray>(isolate, kImportMap); 1320 MaybeHandle<JSArrayBuffer> old_memory;
1620 if (!(SetupInstanceHeap(isolate, compiled_module, js_object, memory, 1321 // TODO(titzer): handle imported memory properly.
1621 &thrower) && 1322
1622 SetupGlobals(isolate, template_owner, compiled_module, js_object, 1323 uint32_t min_mem_pages = static_cast<uint32_t>(
1623 &thrower) && 1324 Smi::cast(compiled_module->get(kMinRequiredMemory))->value());
1624 SetupImports(isolate, compiled_module, js_object, &thrower, ffi) && 1325 isolate->counters()->wasm_min_mem_pages_count()->AddSample(min_mem_pages);
1625 SetupExportsObject(compiled_module, isolate, js_object, &thrower))) { 1326 // TODO(wasm): re-enable counter for max_mem_pages when we use that field.
1626 return nothing; 1327
1627 } 1328 if (memory.is_null() && min_mem_pages > 0) {
1628 1329 memory = AllocateMemory(thrower, isolate, min_mem_pages);
1629 FixupFunctionsAndImports( 1330 if (memory.is_null()) return nothing; // failed to allocate memory
1630 compiled_module_template->GetValueChecked<FixedArray>(isolate, 1331 }
1631 kFunctions), 1332
1632 code_table, old_imports, 1333 if (!memory.is_null()) {
1633 compiled_module->GetValue<FixedArray>(isolate, kImportMap)); 1334 instance->SetInternalField(kWasmMemArrayBuffer, *memory);
1634 1335 Address mem_start = static_cast<Address>(memory->backing_store());
1635 SetDebugSupport(factory, compiled_module, js_object); 1336 uint32_t mem_size = static_cast<uint32_t>(memory->byte_length()->Number());
1636 SetRuntimeSupport(isolate, js_object); 1337 LoadDataSegments(compiled_module, mem_start, mem_size);
1637 1338
1638 FlushAssemblyCache(isolate, code_table); 1339 uint32_t old_mem_size = static_cast<uint32_t>(
1639 1340 compiled_module->GetValueChecked<HeapNumber>(isolate, kMemSize)
1341 ->value());
1342 MaybeHandle<JSArrayBuffer> old_mem =
1343 compiled_module->GetValue<JSArrayBuffer>(isolate, kMemStart);
1344 Address old_mem_start =
1345 old_mem.is_null()
1346 ? nullptr
1347 : static_cast<Address>(old_mem.ToHandleChecked()->backing_store());
1348 RelocateInstanceCode(instance, old_mem_start, mem_start, old_mem_size,
1349 mem_size);
1350 compiled_module->GetValueChecked<HeapNumber>(isolate, kMemSize)
1351 ->set_value(static_cast<double>(mem_size));
1352 compiled_module->set(kMemStart, *memory);
1353 }
1354
1355 //--------------------------------------------------------------------------
1356 // Set up the globals for the new instance.
1357 //--------------------------------------------------------------------------
1358 MaybeHandle<JSArrayBuffer> old_globals;
1359 MaybeHandle<JSArrayBuffer> globals;
1360 uint32_t globals_size = static_cast<uint32_t>(
1361 Smi::cast(compiled_module->get(kGlobalsSize))->value());
1362 if (globals_size > 0) {
1363 Handle<JSArrayBuffer> global_buffer = NewArrayBuffer(isolate, globals_size);
1364 globals = global_buffer;
1365 if (globals.is_null()) {
1366 thrower->Error("Out of memory: wasm globals");
1367 return nothing;
1368 }
1369 Address old_address =
1370 owner.is_null() ? nullptr : GetGlobalStartAddressFromCodeTemplate(
1371 *isolate->factory()->undefined_value(),
1372 JSObject::cast(*owner));
1373 RelocateGlobals(instance, old_address,
1374 static_cast<Address>(global_buffer->backing_store()));
1375 instance->SetInternalField(kWasmGlobalsArrayBuffer, *global_buffer);
1376 }
1377
1378 //--------------------------------------------------------------------------
1379 // Compile the import wrappers for the new instance.
1380 //--------------------------------------------------------------------------
1381 // TODO(titzer): handle imported globals and function tables.
1382 Handle<FixedArray> import_data;
1383 int num_imported_functions = 0;
1384 if (compiled_module->GetValue<FixedArray>(isolate, kImportData)
1385 .ToHandle(&import_data)) {
1386 num_imported_functions = import_data->length();
1387 for (int index = 0; index < num_imported_functions; index++) {
1388 Handle<Code> import_wrapper =
1389 CompileImportWrapper(isolate, ffi, index, import_data, thrower);
1390 if (thrower->error()) return nothing;
1391 code_table->set(index, *import_wrapper);
1392 RecordStats(isolate, *import_wrapper);
1393 }
1394 }
1395
1396 //--------------------------------------------------------------------------
1397 // Set up the debug support for the new instance.
1398 //--------------------------------------------------------------------------
1399 MaybeHandle<String> module_bytes_string =
1400 compiled_module->GetValue<String>(isolate, kModuleBytes);
1401 if (!module_bytes_string.is_null()) {
1402 instance->SetInternalField(kWasmModuleBytesString,
1403 *module_bytes_string.ToHandleChecked());
1404 }
1405
1406 MaybeHandle<ByteArray> function_name_table =
1407 compiled_module->GetValue<ByteArray>(isolate, kFunctionNameTable);
1408 if (!function_name_table.is_null()) {
1409 Handle<ByteArray> handle = function_name_table.ToHandleChecked();
1410 instance->SetInternalField(kWasmFunctionNamesArray, *handle);
1411 }
1412
1413 {
1414 Handle<Object> handle = factory->NewNumber(num_imported_functions);
1415 instance->SetInternalField(kWasmNumImportedFunctions, *handle);
1416 }
1417
1418 //--------------------------------------------------------------------------
1419 // Set up the runtime support for the new instance.
1420 //--------------------------------------------------------------------------
1421 Handle<WeakCell> weak_link = isolate->factory()->NewWeakCell(instance);
1422
1423 for (int i = num_imported_functions + FLAG_skip_compiling_wasm_funcs;
1424 i < code_table->length(); ++i) {
1425 Handle<Code> code = code_table->GetValueChecked<Code>(isolate, i);
1426 if (code->kind() == Code::WASM_FUNCTION) {
1427 Handle<FixedArray> deopt_data =
1428 isolate->factory()->NewFixedArray(2, TENURED);
1429 deopt_data->set(0, *weak_link);
1430 deopt_data->set(1, Smi::FromInt(static_cast<int>(i)));
1431 deopt_data->set_length(2);
1432 code->set_deoptimization_data(*deopt_data);
1433 }
1434 }
1435
1436 //--------------------------------------------------------------------------
1437 // Set up the indirect function tables for the new instance.
1438 //--------------------------------------------------------------------------
1640 { 1439 {
1641 std::vector<Handle<Code>> functions( 1440 std::vector<Handle<Code>> functions(
1642 static_cast<size_t>(code_table->length())); 1441 static_cast<size_t>(code_table->length()));
1643 for (int i = 0; i < code_table->length(); ++i) { 1442 for (int i = 0; i < code_table->length(); ++i) {
1644 functions[static_cast<size_t>(i)] = 1443 functions[i] = code_table->GetValueChecked<Code>(isolate, i);
1645 code_table->GetValueChecked<Code>(isolate, i);
1646 } 1444 }
1647 1445
1648 MaybeHandle<FixedArray> maybe_indirect_tables = 1446 MaybeHandle<FixedArray> maybe_indirect_tables =
1649 compiled_module->GetValue<FixedArray>(isolate, 1447 compiled_module->GetValue<FixedArray>(isolate,
1650 kTableOfIndirectFunctionTables); 1448 kTableOfIndirectFunctionTables);
1651 Handle<FixedArray> indirect_tables_template; 1449 Handle<FixedArray> indirect_tables_template;
1652 if (maybe_indirect_tables.ToHandle(&indirect_tables_template)) { 1450 if (maybe_indirect_tables.ToHandle(&indirect_tables_template)) {
1653 Handle<FixedArray> to_replace = 1451 Handle<FixedArray> to_replace =
1654 template_owner.is_null() 1452 owner.is_null() ? indirect_tables_template
1655 ? indirect_tables_template 1453 : handle(FixedArray::cast(owner->GetInternalField(
1656 : handle(FixedArray::cast( 1454 kWasmModuleFunctionTable)));
1657 template_owner.ToHandleChecked()->GetInternalField(
1658 kWasmModuleFunctionTable)));
1659 Handle<FixedArray> indirect_tables = SetupIndirectFunctionTable( 1455 Handle<FixedArray> indirect_tables = SetupIndirectFunctionTable(
1660 isolate, code_table, indirect_tables_template, to_replace); 1456 isolate, code_table, indirect_tables_template, to_replace);
1661 for (int i = 0; i < indirect_tables->length(); ++i) { 1457 for (int i = 0; i < indirect_tables->length(); ++i) {
1662 Handle<FixedArray> metadata = 1458 Handle<FixedArray> metadata =
1663 indirect_tables->GetValueChecked<FixedArray>(isolate, i); 1459 indirect_tables->GetValueChecked<FixedArray>(isolate, i);
1664 uint32_t size = Smi::cast(metadata->get(kSize))->value(); 1460 uint32_t size = Smi::cast(metadata->get(kSize))->value();
1665 Handle<FixedArray> table = 1461 Handle<FixedArray> table =
1666 metadata->GetValueChecked<FixedArray>(isolate, kTable); 1462 metadata->GetValueChecked<FixedArray>(isolate, kTable);
1667 wasm::PopulateFunctionTable(table, size, &functions); 1463 wasm::PopulateFunctionTable(table, size, &functions);
1668 } 1464 }
1669 js_object->SetInternalField(kWasmModuleFunctionTable, *indirect_tables); 1465 instance->SetInternalField(kWasmModuleFunctionTable, *indirect_tables);
1670 } 1466 }
1671 } 1467 }
1672 1468
1469 //--------------------------------------------------------------------------
1470 // Set up the exports object for the new instance.
1471 //--------------------------------------------------------------------------
1472 bool mem_export =
1473 static_cast<bool>(Smi::cast(compiled_module->get(kExportMem))->value());
1474 ModuleOrigin origin = static_cast<ModuleOrigin>(
1475 Smi::cast(compiled_module->get(kOrigin))->value());
1476
1477 MaybeHandle<FixedArray> maybe_exports =
1478 compiled_module->GetValue<FixedArray>(isolate, kExportData);
1479 if (!maybe_exports.is_null() || mem_export) {
1480 PropertyDescriptor desc;
1481 desc.set_writable(false);
1482
1483 Handle<JSObject> exports_object = instance;
1484 if (origin == kWasmOrigin) {
1485 // Create the "exports" object.
1486 Handle<JSFunction> object_function = Handle<JSFunction>(
1487 isolate->native_context()->object_function(), isolate);
1488 exports_object = factory->NewJSObject(object_function, TENURED);
1489 Handle<String> exports_name = factory->InternalizeUtf8String("exports");
1490 JSObject::AddProperty(instance, exports_name, exports_object, READ_ONLY);
1491 }
1492 Handle<FixedArray> exports;
1493 int first_export = -1;
1494 // TODO(wasm): another iteration over the code objects.
1495 for (int i = 0; i < code_table->length(); i++) {
1496 Handle<Code> code = code_table->GetValueChecked<Code>(isolate, i);
1497 if (code->kind() == Code::JS_TO_WASM_FUNCTION) {
1498 first_export = i;
1499 break;
1500 }
1501 }
1502 if (maybe_exports.ToHandle(&exports)) {
1503 int export_size = exports->length();
1504 for (int i = 0; i < export_size; ++i) {
1505 Handle<FixedArray> export_data =
1506 exports->GetValueChecked<FixedArray>(isolate, i);
1507 Handle<String> name =
1508 export_data->GetValueChecked<String>(isolate, kExportName);
1509 int arity = Smi::cast(export_data->get(kExportArity))->value();
1510 MaybeHandle<ByteArray> signature =
1511 export_data->GetValue<ByteArray>(isolate, kExportedSignature);
1512 Handle<Code> export_code =
1513 code_table->GetValueChecked<Code>(isolate, first_export + i);
1514 Handle<JSFunction> function = WrapExportCodeAsJSFunction(
1515 isolate, export_code, name, arity, signature, instance);
1516 desc.set_value(function);
1517 Maybe<bool> status = JSReceiver::DefineOwnProperty(
1518 isolate, exports_object, name, &desc, Object::THROW_ON_ERROR);
1519 if (!status.IsJust()) {
1520 thrower->Error("export of %.*s failed.", name->length(),
1521 name->ToCString().get());
1522 return nothing;
1523 }
1524 }
1525 }
1526 if (mem_export) {
1527 // Export the memory as a named property.
1528 Handle<JSArrayBuffer> buffer = Handle<JSArrayBuffer>(
1529 JSArrayBuffer::cast(instance->GetInternalField(kWasmMemArrayBuffer)));
1530 Handle<Object> memory_object =
1531 WasmJs::CreateWasmMemoryObject(isolate, buffer, false, 0);
1532 // TODO(titzer): export the memory with the correct name.
1533 Handle<String> name = factory->InternalizeUtf8String("memory");
1534 JSObject::AddProperty(exports_object, name, memory_object, READ_ONLY);
1535 }
1536 }
1537
1538 if (num_imported_functions > 0 || !owner.is_null()) {
1539 // If the code was cloned, or new imports were compiled, patch.
1540 PatchDirectCalls(old_code_table, code_table, num_imported_functions);
1541 }
1542
1543 FlushICache(isolate, code_table);
1544
1545 //--------------------------------------------------------------------------
1673 // Run the start function if one was specified. 1546 // Run the start function if one was specified.
1674 MaybeHandle<FixedArray> maybe_startup_fct = 1547 //--------------------------------------------------------------------------
1675 compiled_module->GetValue<FixedArray>(isolate, kStartupFunction); 1548 Handle<FixedArray> startup_data;
1676 Handle<FixedArray> metadata; 1549 if (compiled_module->GetValue<FixedArray>(isolate, kStartupData)
1677 if (maybe_startup_fct.ToHandle(&metadata)) { 1550 .ToHandle(&startup_data)) {
1678 HandleScope scope(isolate); 1551 HandleScope scope(isolate);
1552 int32_t start_index =
1553 startup_data->GetValueChecked<Smi>(isolate, kExportedFunctionIndex)
1554 ->value();
1679 Handle<Code> startup_code = 1555 Handle<Code> startup_code =
1680 metadata->GetValueChecked<Code>(isolate, kExportCode); 1556 code_table->GetValueChecked<Code>(isolate, start_index);
1681 int arity = Smi::cast(metadata->get(kExportArity))->value(); 1557 int arity = Smi::cast(startup_data->get(kExportArity))->value();
1682 MaybeHandle<ByteArray> startup_signature = 1558 MaybeHandle<ByteArray> startup_signature =
1683 metadata->GetValue<ByteArray>(isolate, kExportedSignature); 1559 startup_data->GetValue<ByteArray>(isolate, kExportedSignature);
1684 Handle<JSFunction> startup_fct = WrapExportCodeAsJSFunction( 1560 Handle<JSFunction> startup_fct = WrapExportCodeAsJSFunction(
1685 isolate, startup_code, factory->InternalizeUtf8String("start"), arity, 1561 isolate, startup_code, factory->InternalizeUtf8String("start"), arity,
1686 startup_signature, js_object); 1562 startup_signature, instance);
1687 RecordStats(isolate, *startup_code); 1563 RecordStats(isolate, *startup_code);
1688 // Call the JS function. 1564 // Call the JS function.
1689 Handle<Object> undefined = isolate->factory()->undefined_value(); 1565 Handle<Object> undefined = isolate->factory()->undefined_value();
1690 MaybeHandle<Object> retval = 1566 MaybeHandle<Object> retval =
1691 Execution::Call(isolate, startup_fct, undefined, 0, nullptr); 1567 Execution::Call(isolate, startup_fct, undefined, 0, nullptr);
1692 1568
1693 if (retval.is_null()) { 1569 if (retval.is_null()) {
1694 thrower.Error("WASM.instantiateModule(): start function failed"); 1570 thrower->Error("WASM.instantiateModule(): start function failed");
1695 return nothing; 1571 return nothing;
1696 } 1572 }
1697 } 1573 }
1698 1574
1699 DCHECK(wasm::IsWasmObject(*js_object)); 1575 DCHECK(wasm::IsWasmObject(*instance));
1700 1576
1701 if (!compiled_module->GetValue<WeakCell>(isolate, kModuleObject).is_null()) { 1577 if (!compiled_module->GetValue<WeakCell>(isolate, kModuleObject).is_null()) {
1702 js_object->SetInternalField(kWasmCompiledModule, *compiled_module); 1578 instance->SetInternalField(kWasmCompiledModule, *compiled_module);
1703 Handle<WeakCell> link_to_owner = factory->NewWeakCell(js_object); 1579 Handle<WeakCell> link_to_owner = factory->NewWeakCell(instance);
1704 compiled_module->set(kOwningInstance, *link_to_owner); 1580 compiled_module->set(kOwningInstance, *link_to_owner);
1705 1581
1706 Handle<Object> global_handle = 1582 Handle<Object> global_handle = isolate->global_handles()->Create(*instance);
1707 isolate->global_handles()->Create(*js_object);
1708 GlobalHandles::MakeWeak(global_handle.location(), global_handle.location(), 1583 GlobalHandles::MakeWeak(global_handle.location(), global_handle.location(),
1709 &InstanceFinalizer, 1584 &InstanceFinalizer,
1710 v8::WeakCallbackType::kFinalizer); 1585 v8::WeakCallbackType::kFinalizer);
1711 } 1586 }
1712 1587
1713 return js_object; 1588 return instance;
1714 }
1715
1716 // TODO(mtrofin): remove this once we move to WASM_DIRECT_CALL
1717 Handle<Code> ModuleEnv::GetCodeOrPlaceholder(uint32_t index) const {
1718 DCHECK(IsValidFunction(index));
1719 if (!placeholders.empty()) return placeholders[index];
1720 DCHECK_NOT_NULL(instance);
1721 return instance->function_code[index];
1722 }
1723
1724 Handle<Code> ModuleEnv::GetImportCode(uint32_t index) {
1725 DCHECK(IsValidImport(index));
1726 return instance ? instance->import_code[index] : Handle<Code>::null();
1727 } 1589 }
1728 1590
1729 compiler::CallDescriptor* ModuleEnv::GetCallDescriptor(Zone* zone, 1591 compiler::CallDescriptor* ModuleEnv::GetCallDescriptor(Zone* zone,
1730 uint32_t index) { 1592 uint32_t index) {
1731 DCHECK(IsValidFunction(index)); 1593 DCHECK(IsValidFunction(index));
1732 // Always make a direct call to whatever is in the table at that location. 1594 // Always make a direct call to whatever is in the table at that location.
1733 // A wrapper will be generated for FFI calls. 1595 // A wrapper will be generated for FFI calls.
1734 const WasmFunction* function = &module->functions[index]; 1596 const WasmFunction* function = &module->functions[index];
1735 return GetWasmCallDescriptor(zone, function->sig); 1597 return GetWasmCallDescriptor(zone, function->sig);
1736 } 1598 }
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after
1987 FixedArray* compiled_module = 1849 FixedArray* compiled_module =
1988 FixedArray::cast(instance->GetInternalField(kWasmCompiledModule)); 1850 FixedArray::cast(instance->GetInternalField(kWasmCompiledModule));
1989 CHECK_NOT_NULL(GetModuleObject(compiled_module)); 1851 CHECK_NOT_NULL(GetModuleObject(compiled_module));
1990 CHECK(GetModuleObject(compiled_module)->cleared()); 1852 CHECK(GetModuleObject(compiled_module)->cleared());
1991 } 1853 }
1992 1854
1993 } // namespace testing 1855 } // namespace testing
1994 } // namespace wasm 1856 } // namespace wasm
1995 } // namespace internal 1857 } // namespace internal
1996 } // namespace v8 1858 } // namespace v8
OLDNEW
« no previous file with comments | « src/wasm/wasm-module.h ('k') | src/wasm/wasm-opcodes.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698