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

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