OLD | NEW |
---|---|
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <memory> | 5 #include <memory> |
6 | 6 |
7 #include "src/base/atomic-utils.h" | 7 #include "src/base/atomic-utils.h" |
8 #include "src/code-stubs.h" | 8 #include "src/code-stubs.h" |
9 | 9 |
10 #include "src/macro-assembler.h" | 10 #include "src/macro-assembler.h" |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
151 DCHECK_NOT_NULL(deopt_data); | 151 DCHECK_NOT_NULL(deopt_data); |
152 DCHECK(deopt_data->length() == 2); | 152 DCHECK(deopt_data->length() == 2); |
153 Object* weak_link = deopt_data->get(0); | 153 Object* weak_link = deopt_data->get(0); |
154 if (weak_link == undefined) return undefined; | 154 if (weak_link == undefined) return undefined; |
155 WeakCell* cell = WeakCell::cast(weak_link); | 155 WeakCell* cell = WeakCell::cast(weak_link); |
156 return cell->value(); | 156 return cell->value(); |
157 } | 157 } |
158 | 158 |
159 namespace { | 159 namespace { |
160 // Internal constants for the layout of the module object. | 160 // Internal constants for the layout of the module object. |
161 const int kWasmModuleFunctionTable = 0; | 161 enum WasmInstanceFields { |
162 const int kWasmModuleCodeTable = 1; | 162 kWasmCompiledModule, |
bradnelson
2016/09/02 16:56:59
Optional:
Realize the default is zero, but I've so
Mircea Trofin
2016/09/02 20:55:30
Done.
| |
163 const int kWasmMemArrayBuffer = 2; | 163 kWasmModuleFunctionTable, |
164 const int kWasmGlobalsArrayBuffer = 3; | 164 kWasmModuleCodeTable, |
165 // TODO(clemensh): Remove function name array, extract names from module bytes. | 165 kWasmMemArrayBuffer, |
166 const int kWasmFunctionNamesArray = 4; | 166 kWasmGlobalsArrayBuffer, |
167 const int kWasmModuleBytesString = 5; | 167 // TODO(clemensh): Remove function name array, extract names from module |
168 const int kWasmDebugInfo = 6; | 168 // bytes. |
169 const int kWasmModuleInternalFieldCount = 7; | 169 kWasmFunctionNamesArray, |
170 kWasmModuleBytesString, | |
171 kWasmDebugInfo, | |
172 kWasmModuleInternalFieldCount | |
173 }; | |
170 | 174 |
171 // TODO(mtrofin): Unnecessary once we stop using JS Heap for wasm code. | 175 // TODO(mtrofin): Unnecessary once we stop using JS Heap for wasm code. |
172 // For now, each field is expected to have the type commented by its side. | 176 // For now, each field is expected to have the type commented by its side. |
173 // The elements typed as "maybe" are optional. The others are mandatory. Since | 177 // The elements typed as "maybe" are optional. The others are mandatory. Since |
174 // the compiled module is either obtained from the current v8 instance, or from | 178 // the compiled module is either obtained from the current v8 instance, or from |
175 // a snapshot produced by a compatible (==identical) v8 instance, we simply | 179 // a snapshot produced by a compatible (==identical) v8 instance, we simply |
176 // fail at instantiation time, in the face of invalid data. | 180 // fail at instantiation time, in the face of invalid data. |
177 enum CompiledWasmObjectFields { | 181 enum CompiledWasmObjectFields { |
178 kFunctions, // FixedArray of Code | 182 kFunctions, // FixedArray of Code |
179 kImportData, // maybe FixedArray of FixedArray respecting the | 183 kImportData, // maybe FixedArray of FixedArray respecting the |
180 // WasmImportMetadata structure. | 184 // WasmImportMetadata structure. |
181 kImportMap, // FixedArray. The i-th element is the Code object used for | 185 kImportMap, // FixedArray. The i-th element is the Code object used for |
182 // import i | 186 // import i |
183 kExports, // maybe FixedArray of FixedArray of WasmExportMetadata | 187 kExports, // maybe FixedArray of FixedArray of WasmExportMetadata |
184 // structure | 188 // structure |
185 kStartupFunction, // maybe FixedArray of WasmExportMetadata structure | 189 kStartupFunction, // maybe FixedArray of WasmExportMetadata structure |
186 kTableOfIndirectFunctionTables, // maybe FixedArray of FixedArray of | 190 kTableOfIndirectFunctionTables, // maybe FixedArray of FixedArray of |
187 // WasmIndirectFunctionTableMetadata | 191 // WasmIndirectFunctionTableMetadata |
188 kModuleBytes, // maybe String | 192 kModuleBytes, // maybe String |
189 kFunctionNameTable, // maybe ByteArray | 193 kFunctionNameTable, // maybe ByteArray |
190 kMinRequiredMemory, // Smi. an uint32_t | 194 kMinRequiredMemory, // Smi. an uint32_t |
191 // The following 2 are either together present or absent: | 195 // The following 2 are either together present or absent: |
192 kDataSegmentsInfo, // maybe FixedArray of FixedArray respecting the | 196 kDataSegmentsInfo, // maybe FixedArray of FixedArray respecting the |
193 // WasmSegmentInfo structure | 197 // WasmSegmentInfo structure |
194 kDataSegments, // maybe ByteArray. | 198 kDataSegments, // maybe ByteArray. |
195 | 199 |
196 kGlobalsSize, // Smi. an uint32_t | 200 kGlobalsSize, // Smi. an uint32_t |
201 kMemSize, // Smi.an uint32_t | |
202 kMemStart, // MaybeHandle<ArrayBuffer> | |
197 kExportMem, // Smi. bool | 203 kExportMem, // Smi. bool |
198 kOrigin, // Smi. ModuleOrigin | 204 kOrigin, // Smi. ModuleOrigin |
205 kNextInstance, // WeakCell. See compiled code cloning. | |
206 kPrevInstance, // WeakCell. See compiled code cloning. | |
207 kOwningInstance, // WeakCell, pointing to the owning instance. | |
208 kModuleObject, // WeakCell, pointing to the module object. | |
199 kCompiledWasmObjectTableSize // Sentinel value. | 209 kCompiledWasmObjectTableSize // Sentinel value. |
200 }; | 210 }; |
201 | 211 |
202 enum WasmImportMetadata { | 212 enum WasmImportMetadata { |
203 kModuleName, // String | 213 kModuleName, // String |
204 kFunctionName, // maybe String | 214 kFunctionName, // maybe String |
205 kOutputCount, // Smi. an uint32_t | 215 kOutputCount, // Smi. an uint32_t |
206 kSignature, // ByteArray. A copy of the data in FunctionSig | 216 kSignature, // ByteArray. A copy of the data in FunctionSig |
207 kWasmImportDataTableSize // Sentinel value. | 217 kWasmImportDataTableSize // Sentinel value. |
208 }; | 218 }; |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
322 DCHECK_EQ(0, bytes[i]); | 332 DCHECK_EQ(0, bytes[i]); |
323 } | 333 } |
324 #endif | 334 #endif |
325 | 335 |
326 Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer(); | 336 Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer(); |
327 JSArrayBuffer::Setup(buffer, isolate, false, memory, static_cast<int>(size)); | 337 JSArrayBuffer::Setup(buffer, isolate, false, memory, static_cast<int>(size)); |
328 buffer->set_is_neuterable(false); | 338 buffer->set_is_neuterable(false); |
329 return buffer; | 339 return buffer; |
330 } | 340 } |
331 | 341 |
332 void RelocateInstanceCode(Handle<JSObject> instance, Address start, | 342 void RelocateInstanceCode(Handle<JSObject> instance, Address old_start, |
333 uint32_t prev_size, uint32_t new_size) { | 343 Address start, uint32_t prev_size, |
344 uint32_t new_size) { | |
334 Handle<FixedArray> functions = Handle<FixedArray>( | 345 Handle<FixedArray> functions = Handle<FixedArray>( |
335 FixedArray::cast(instance->GetInternalField(kWasmModuleCodeTable))); | 346 FixedArray::cast(instance->GetInternalField(kWasmModuleCodeTable))); |
336 for (int i = 0; i < functions->length(); ++i) { | 347 for (int i = 0; i < functions->length(); ++i) { |
337 Handle<Code> function = Handle<Code>(Code::cast(functions->get(i))); | 348 Handle<Code> function = Handle<Code>(Code::cast(functions->get(i))); |
338 AllowDeferredHandleDereference embedding_raw_address; | 349 AllowDeferredHandleDereference embedding_raw_address; |
339 int mask = (1 << RelocInfo::WASM_MEMORY_REFERENCE) | | 350 int mask = (1 << RelocInfo::WASM_MEMORY_REFERENCE) | |
340 (1 << RelocInfo::WASM_MEMORY_SIZE_REFERENCE); | 351 (1 << RelocInfo::WASM_MEMORY_SIZE_REFERENCE); |
341 for (RelocIterator it(*function, mask); !it.done(); it.next()) { | 352 for (RelocIterator it(*function, mask); !it.done(); it.next()) { |
342 it.rinfo()->update_wasm_memory_reference(nullptr, start, prev_size, | 353 it.rinfo()->update_wasm_memory_reference(old_start, start, prev_size, |
343 new_size); | 354 new_size); |
344 } | 355 } |
345 } | 356 } |
346 } | 357 } |
347 | 358 |
348 // Allocate memory for a module instance as a new JSArrayBuffer. | 359 // Allocate memory for a module instance as a new JSArrayBuffer. |
349 Handle<JSArrayBuffer> AllocateMemory(ErrorThrower* thrower, Isolate* isolate, | 360 Handle<JSArrayBuffer> AllocateMemory(ErrorThrower* thrower, Isolate* isolate, |
350 uint32_t min_mem_pages) { | 361 uint32_t min_mem_pages) { |
351 if (min_mem_pages > WasmModule::kMaxMemPages) { | 362 if (min_mem_pages > WasmModule::kMaxMemPages) { |
352 thrower->Error("Out of memory: wasm memory too large"); | 363 thrower->Error("Out of memory: wasm memory too large"); |
353 return Handle<JSArrayBuffer>::null(); | 364 return Handle<JSArrayBuffer>::null(); |
354 } | 365 } |
355 Handle<JSArrayBuffer> mem_buffer = | 366 Handle<JSArrayBuffer> mem_buffer = |
356 NewArrayBuffer(isolate, min_mem_pages * WasmModule::kPageSize); | 367 NewArrayBuffer(isolate, min_mem_pages * WasmModule::kPageSize); |
357 | 368 |
358 if (mem_buffer.is_null()) { | 369 if (mem_buffer.is_null()) { |
359 thrower->Error("Out of memory: wasm memory"); | 370 thrower->Error("Out of memory: wasm memory"); |
360 } | 371 } |
361 return mem_buffer; | 372 return mem_buffer; |
362 } | 373 } |
363 | 374 |
364 void RelocateGlobals(Handle<JSObject> instance, Address globals_start) { | 375 void RelocateGlobals(Handle<JSObject> instance, Address old_start, |
376 Address globals_start) { | |
365 Handle<FixedArray> functions = Handle<FixedArray>( | 377 Handle<FixedArray> functions = Handle<FixedArray>( |
366 FixedArray::cast(instance->GetInternalField(kWasmModuleCodeTable))); | 378 FixedArray::cast(instance->GetInternalField(kWasmModuleCodeTable))); |
367 uint32_t function_count = static_cast<uint32_t>(functions->length()); | 379 uint32_t function_count = static_cast<uint32_t>(functions->length()); |
368 for (uint32_t i = 0; i < function_count; ++i) { | 380 for (uint32_t i = 0; i < function_count; ++i) { |
369 Handle<Code> function = Handle<Code>(Code::cast(functions->get(i))); | 381 Handle<Code> function = Handle<Code>(Code::cast(functions->get(i))); |
370 AllowDeferredHandleDereference embedding_raw_address; | 382 AllowDeferredHandleDereference embedding_raw_address; |
371 int mask = 1 << RelocInfo::WASM_GLOBAL_REFERENCE; | 383 int mask = 1 << RelocInfo::WASM_GLOBAL_REFERENCE; |
372 for (RelocIterator it(*function, mask); !it.done(); it.next()) { | 384 for (RelocIterator it(*function, mask); !it.done(); it.next()) { |
373 it.rinfo()->update_wasm_global_reference(nullptr, globals_start); | 385 it.rinfo()->update_wasm_global_reference(old_start, globals_start); |
374 } | 386 } |
375 } | 387 } |
376 } | 388 } |
377 | 389 |
378 Handle<Code> CreatePlaceholder(Factory* factory, uint32_t index, | 390 Handle<Code> CreatePlaceholder(Factory* factory, uint32_t index, |
379 Code::Kind kind) { | 391 Code::Kind kind) { |
380 // Create a placeholder code object and encode the corresponding index in | 392 // Create a placeholder code object and encode the corresponding index in |
381 // the {constant_pool_offset} field of the code object. | 393 // the {constant_pool_offset} field of the code object. |
382 // TODO(titzer): placeholder code objects are somewhat dangerous. | 394 // TODO(titzer): placeholder code objects are somewhat dangerous. |
383 static byte buffer[] = {0, 0, 0, 0, 0, 0, 0, 0}; // fake instructions. | 395 static byte buffer[] = {0, 0, 0, 0, 0, 0, 0, 0}; // fake instructions. |
(...skipping 10 matching lines...) Expand all Loading... | |
394 std::vector<Handle<Code>>* placeholders, | 406 std::vector<Handle<Code>>* placeholders, |
395 size_t size) { | 407 size_t size) { |
396 DCHECK(placeholders->empty()); | 408 DCHECK(placeholders->empty()); |
397 placeholders->reserve(size); | 409 placeholders->reserve(size); |
398 | 410 |
399 for (uint32_t i = 0; i < size; ++i) { | 411 for (uint32_t i = 0; i < size; ++i) { |
400 placeholders->push_back(CreatePlaceholder(factory, i, Code::WASM_FUNCTION)); | 412 placeholders->push_back(CreatePlaceholder(factory, i, Code::WASM_FUNCTION)); |
401 } | 413 } |
402 } | 414 } |
403 | 415 |
404 bool LinkFunction(Handle<Code> unlinked, | 416 bool LinkFunction(Isolate* isolate, Handle<Code> unlinked, |
405 const std::vector<Handle<Code>>& code_targets, | 417 Handle<FixedArray> code_targets, |
406 Code::Kind kind) { | 418 Code::Kind kind = Code::WASM_FUNCTION) { |
407 bool modified = false; | 419 bool modified = false; |
408 int mode_mask = RelocInfo::kCodeTargetMask; | 420 int mode_mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET); |
409 AllowDeferredHandleDereference embedding_raw_address; | 421 AllowDeferredHandleDereference embedding_raw_address; |
410 for (RelocIterator it(*unlinked, mode_mask); !it.done(); it.next()) { | 422 for (RelocIterator it(*unlinked, mode_mask); !it.done(); it.next()) { |
411 RelocInfo::Mode mode = it.rinfo()->rmode(); | 423 Code* target = Code::GetCodeFromTargetAddress(it.rinfo()->target_address()); |
412 if (RelocInfo::IsCodeTarget(mode)) { | 424 if (target->kind() == kind && |
413 Code* target = | 425 target->constant_pool_offset() >= kPlaceholderMarker) { |
414 Code::GetCodeFromTargetAddress(it.rinfo()->target_address()); | 426 // Patch direct calls to placeholder code objects. |
415 if (target->kind() == kind && | 427 uint32_t index = target->constant_pool_offset() - kPlaceholderMarker; |
416 target->constant_pool_offset() >= kPlaceholderMarker) { | 428 CHECK(index < static_cast<uint32_t>(code_targets->length())); |
417 // Patch direct calls to placeholder code objects. | 429 Handle<Code> new_target = |
418 uint32_t index = target->constant_pool_offset() - kPlaceholderMarker; | 430 code_targets->GetValueChecked<Code>(isolate, index); |
419 CHECK(index < code_targets.size()); | 431 if (target != *new_target) { |
420 Handle<Code> new_target = code_targets[index]; | 432 it.rinfo()->set_target_address(new_target->instruction_start(), |
421 if (target != *new_target) { | 433 UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH); |
422 it.rinfo()->set_target_address(new_target->instruction_start(), | 434 modified = true; |
423 UPDATE_WRITE_BARRIER, | |
424 SKIP_ICACHE_FLUSH); | |
425 modified = true; | |
426 } | |
427 } | 435 } |
428 } | 436 } |
429 } | 437 } |
430 return modified; | 438 return modified; |
431 } | 439 } |
432 | 440 |
433 void LinkModuleFunctions(Isolate* isolate, | 441 void LinkModuleFunctions(Isolate* isolate, Handle<FixedArray> functions) { |
434 std::vector<Handle<Code>>& functions) { | 442 for (int i = 0; i < functions->length(); ++i) { |
435 for (size_t i = 0; i < functions.size(); ++i) { | 443 Handle<Code> code = functions->GetValueChecked<Code>(isolate, i); |
436 Handle<Code> code = functions[i]; | 444 LinkFunction(isolate, code, functions); |
437 LinkFunction(code, functions, Code::WASM_FUNCTION); | |
438 } | 445 } |
439 } | 446 } |
440 | 447 |
441 void FlushAssemblyCache(Isolate* isolate, Handle<FixedArray> functions) { | 448 void FlushAssemblyCache(Isolate* isolate, Handle<FixedArray> functions) { |
442 for (int i = 0; i < functions->length(); ++i) { | 449 for (int i = 0; i < functions->length(); ++i) { |
443 Handle<Code> code = functions->GetValueChecked<Code>(isolate, i); | 450 Handle<Code> code = functions->GetValueChecked<Code>(isolate, i); |
444 Assembler::FlushICache(isolate, code->instruction_start(), | 451 Assembler::FlushICache(isolate, code->instruction_start(), |
445 code->instruction_size()); | 452 code->instruction_size()); |
446 } | 453 } |
447 } | 454 } |
448 | 455 |
449 void SetRuntimeSupport(Isolate* isolate, Handle<JSObject> js_object) { | 456 void SetRuntimeSupport(Isolate* isolate, Handle<JSObject> js_object) { |
450 Handle<FixedArray> functions = Handle<FixedArray>( | 457 Handle<FixedArray> functions = Handle<FixedArray>( |
451 FixedArray::cast(js_object->GetInternalField(kWasmModuleCodeTable))); | 458 FixedArray::cast(js_object->GetInternalField(kWasmModuleCodeTable))); |
452 Handle<WeakCell> weak_link = isolate->factory()->NewWeakCell(js_object); | 459 Handle<WeakCell> weak_link = isolate->factory()->NewWeakCell(js_object); |
453 | 460 |
454 for (int i = FLAG_skip_compiling_wasm_funcs; i < functions->length(); ++i) { | 461 for (int i = FLAG_skip_compiling_wasm_funcs; i < functions->length(); ++i) { |
455 Handle<Code> code = functions->GetValueChecked<Code>(isolate, i); | 462 Handle<Code> code = functions->GetValueChecked<Code>(isolate, i); |
456 DCHECK(code->deoptimization_data() == nullptr || | |
bradnelson
2016/09/02 16:57:00
Why?
Mircea Trofin
2016/09/02 20:55:30
Because now the deopt will be valid, but belonging
| |
457 code->deoptimization_data()->length() == 0); | |
458 Handle<FixedArray> deopt_data = | 463 Handle<FixedArray> deopt_data = |
459 isolate->factory()->NewFixedArray(2, TENURED); | 464 isolate->factory()->NewFixedArray(2, TENURED); |
460 deopt_data->set(0, *weak_link); | 465 deopt_data->set(0, *weak_link); |
461 deopt_data->set(1, Smi::FromInt(static_cast<int>(i))); | 466 deopt_data->set(1, Smi::FromInt(static_cast<int>(i))); |
462 deopt_data->set_length(2); | 467 deopt_data->set_length(2); |
463 code->set_deoptimization_data(*deopt_data); | 468 code->set_deoptimization_data(*deopt_data); |
464 } | 469 } |
465 } | 470 } |
466 | 471 |
467 } // namespace | 472 } // namespace |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
614 for (Handle<Code> c : functions) RecordStats(isolate, *c); | 619 for (Handle<Code> c : functions) RecordStats(isolate, *c); |
615 } | 620 } |
616 | 621 |
617 static void RecordStats(Isolate* isolate, Handle<FixedArray> functions) { | 622 static void RecordStats(Isolate* isolate, Handle<FixedArray> functions) { |
618 DisallowHeapAllocation no_gc; | 623 DisallowHeapAllocation no_gc; |
619 for (int i = 0; i < functions->length(); ++i) { | 624 for (int i = 0; i < functions->length(); ++i) { |
620 RecordStats(isolate, Code::cast(functions->get(i))); | 625 RecordStats(isolate, Code::cast(functions->get(i))); |
621 } | 626 } |
622 } | 627 } |
623 | 628 |
629 Address GetGlobalStartAddressFromCodeTemplate(Object* undefined, | |
630 JSObject* owner) { | |
631 Address old_address = nullptr; | |
632 Object* stored_value = owner->GetInternalField(kWasmGlobalsArrayBuffer); | |
633 if (stored_value != undefined) { | |
634 old_address = static_cast<Address>( | |
635 JSArrayBuffer::cast(stored_value)->backing_store()); | |
636 } | |
637 return old_address; | |
638 } | |
639 | |
624 Handle<FixedArray> GetImportsMetadata(Factory* factory, | 640 Handle<FixedArray> GetImportsMetadata(Factory* factory, |
625 const WasmModule* module) { | 641 const WasmModule* module) { |
626 Handle<FixedArray> ret = factory->NewFixedArray( | 642 Handle<FixedArray> ret = factory->NewFixedArray( |
627 static_cast<int>(module->import_table.size()), TENURED); | 643 static_cast<int>(module->import_table.size()), TENURED); |
628 for (size_t i = 0; i < module->import_table.size(); ++i) { | 644 for (size_t i = 0; i < module->import_table.size(); ++i) { |
629 const WasmImport& import = module->import_table[i]; | 645 const WasmImport& import = module->import_table[i]; |
630 WasmName module_name = module->GetNameOrNull(import.module_name_offset, | 646 WasmName module_name = module->GetNameOrNull(import.module_name_offset, |
631 import.module_name_length); | 647 import.module_name_length); |
632 WasmName function_name = module->GetNameOrNull(import.function_name_offset, | 648 WasmName function_name = module->GetNameOrNull(import.function_name_offset, |
633 import.function_name_length); | 649 import.function_name_length); |
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
905 } | 921 } |
906 | 922 |
907 MaybeHandle<ByteArray> function_name_table = | 923 MaybeHandle<ByteArray> function_name_table = |
908 compiled_module->GetValue<ByteArray>(isolate, kFunctionNameTable); | 924 compiled_module->GetValue<ByteArray>(isolate, kFunctionNameTable); |
909 if (!function_name_table.is_null()) { | 925 if (!function_name_table.is_null()) { |
910 js_object->SetInternalField(kWasmFunctionNamesArray, | 926 js_object->SetInternalField(kWasmFunctionNamesArray, |
911 *function_name_table.ToHandleChecked()); | 927 *function_name_table.ToHandleChecked()); |
912 } | 928 } |
913 } | 929 } |
914 | 930 |
915 bool SetupGlobals(Isolate* isolate, Handle<FixedArray> compiled_module, | 931 bool SetupGlobals(Isolate* isolate, MaybeHandle<JSObject> template_owner, |
916 Handle<JSObject> instance, ErrorThrower* thrower) { | 932 Handle<FixedArray> compiled_module, Handle<JSObject> instance, |
933 ErrorThrower* thrower) { | |
917 uint32_t globals_size = static_cast<uint32_t>( | 934 uint32_t globals_size = static_cast<uint32_t>( |
918 Smi::cast(compiled_module->get(kGlobalsSize))->value()); | 935 Smi::cast(compiled_module->get(kGlobalsSize))->value()); |
919 if (globals_size > 0) { | 936 if (globals_size > 0) { |
920 Handle<JSArrayBuffer> globals_buffer = | 937 Handle<JSArrayBuffer> globals_buffer = |
921 NewArrayBuffer(isolate, globals_size); | 938 NewArrayBuffer(isolate, globals_size); |
922 if (globals_buffer.is_null()) { | 939 if (globals_buffer.is_null()) { |
923 thrower->Error("Out of memory: wasm globals"); | 940 thrower->Error("Out of memory: wasm globals"); |
924 return false; | 941 return false; |
925 } | 942 } |
926 RelocateGlobals(instance, | 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, | |
927 static_cast<Address>(globals_buffer->backing_store())); | 950 static_cast<Address>(globals_buffer->backing_store())); |
928 instance->SetInternalField(kWasmGlobalsArrayBuffer, *globals_buffer); | 951 instance->SetInternalField(kWasmGlobalsArrayBuffer, *globals_buffer); |
929 } | 952 } |
930 return true; | 953 return true; |
931 } | 954 } |
932 | 955 |
933 bool SetupInstanceHeap(Isolate* isolate, Handle<FixedArray> compiled_module, | 956 bool SetupInstanceHeap(Isolate* isolate, Handle<FixedArray> compiled_module, |
934 Handle<JSObject> instance, Handle<JSArrayBuffer> memory, | 957 Handle<JSObject> instance, Handle<JSArrayBuffer> memory, |
935 ErrorThrower* thrower) { | 958 ErrorThrower* thrower) { |
936 uint32_t min_mem_pages = static_cast<uint32_t>( | 959 uint32_t min_mem_pages = static_cast<uint32_t>( |
937 Smi::cast(compiled_module->get(kMinRequiredMemory))->value()); | 960 Smi::cast(compiled_module->get(kMinRequiredMemory))->value()); |
938 isolate->counters()->wasm_min_mem_pages_count()->AddSample(min_mem_pages); | 961 isolate->counters()->wasm_min_mem_pages_count()->AddSample(min_mem_pages); |
939 // TODO(wasm): re-enable counter for max_mem_pages when we use that field. | 962 // TODO(wasm): re-enable counter for max_mem_pages when we use that field. |
940 | 963 |
941 if (memory.is_null() && min_mem_pages > 0) { | 964 if (memory.is_null() && min_mem_pages > 0) { |
942 memory = AllocateMemory(thrower, isolate, min_mem_pages); | 965 memory = AllocateMemory(thrower, isolate, min_mem_pages); |
943 if (memory.is_null()) { | 966 if (memory.is_null()) { |
944 return false; | 967 return false; |
945 } | 968 } |
946 } | 969 } |
947 | 970 |
948 if (!memory.is_null()) { | 971 if (!memory.is_null()) { |
949 instance->SetInternalField(kWasmMemArrayBuffer, *memory); | 972 instance->SetInternalField(kWasmMemArrayBuffer, *memory); |
950 Address mem_start = static_cast<Address>(memory->backing_store()); | 973 Address mem_start = static_cast<Address>(memory->backing_store()); |
951 uint32_t mem_size = static_cast<uint32_t>(memory->byte_length()->Number()); | 974 uint32_t mem_size = static_cast<uint32_t>(memory->byte_length()->Number()); |
952 RelocateInstanceCode(instance, mem_start, | 975 uint32_t old_mem_size = static_cast<uint32_t>( |
953 WasmModule::kPageSize * min_mem_pages, mem_size); | 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); | |
954 LoadDataSegments(compiled_module, mem_start, 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); | |
955 } | 990 } |
956 return true; | 991 return true; |
957 } | 992 } |
958 | 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()); | |
999 | |
1000 DisallowHeapAllocation no_gc; | |
1001 std::map<Code*, Code*> old_to_new_code; | |
1002 for (int i = 0; i < new_functions->length(); ++i) { | |
1003 old_to_new_code.insert(std::make_pair(Code::cast(old_functions->get(i)), | |
1004 Code::cast(new_functions->get(i)))); | |
1005 } | |
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); | |
1017 AllowDeferredHandleDereference embedding_raw_address; | |
1018 for (int i = 0; i < new_functions->length(); ++i) { | |
1019 Code* wasm_function = Code::cast(new_functions->get(i)); | |
1020 for (RelocIterator it(wasm_function, mode_mask); !it.done(); it.next()) { | |
1021 Code* old_code = | |
1022 Code::GetCodeFromTargetAddress(it.rinfo()->target_address()); | |
1023 if (old_code->kind() == Code::WASM_TO_JS_FUNCTION || | |
1024 old_code->kind() == Code::WASM_FUNCTION) { | |
1025 auto found = old_to_new_code.find(old_code); | |
1026 DCHECK(found != old_to_new_code.end()); | |
1027 Code* new_code = found->second; | |
1028 // Avoid redundant updates, expected for wasm functions, if we're at the | |
1029 // first instance. | |
1030 if (new_code == old_code) { | |
1031 DCHECK(new_code->kind() == Code::WASM_FUNCTION); | |
1032 continue; | |
1033 } | |
1034 it.rinfo()->set_target_address(new_code->instruction_start(), | |
1035 UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH); | |
1036 } | |
1037 } | |
1038 } | |
1039 } | |
1040 | |
959 bool SetupImports(Isolate* isolate, Handle<FixedArray> compiled_module, | 1041 bool SetupImports(Isolate* isolate, Handle<FixedArray> compiled_module, |
960 Handle<JSObject> instance, ErrorThrower* thrower, | 1042 Handle<JSObject> instance, ErrorThrower* thrower, |
961 Handle<JSReceiver> ffi) { | 1043 Handle<JSReceiver> ffi) { |
962 //------------------------------------------------------------------------- | 1044 //------------------------------------------------------------------------- |
963 // Compile wrappers to imported functions. | 1045 // Compile wrappers to imported functions. |
964 //------------------------------------------------------------------------- | 1046 //------------------------------------------------------------------------- |
965 std::vector<Handle<Code>> import_code; | 1047 std::vector<Handle<Code>> import_code; |
966 MaybeHandle<FixedArray> maybe_import_data = | 1048 MaybeHandle<FixedArray> maybe_import_data = |
967 compiled_module->GetValue<FixedArray>(isolate, kImportData); | 1049 compiled_module->GetValue<FixedArray>(isolate, kImportData); |
968 Handle<FixedArray> import_data; | 1050 Handle<FixedArray> import_data; |
969 if (maybe_import_data.ToHandle(&import_data)) { | 1051 if (maybe_import_data.ToHandle(&import_data)) { |
970 if (!CompileWrappersToImportedFunctions(isolate, ffi, import_code, | 1052 if (!CompileWrappersToImportedFunctions(isolate, ffi, import_code, |
971 import_data, thrower)) { | 1053 import_data, thrower)) { |
972 return false; | 1054 return false; |
973 } | 1055 } |
974 } | 1056 } |
975 | 1057 |
976 RecordStats(isolate, import_code); | 1058 RecordStats(isolate, import_code); |
977 | |
978 if (import_code.empty()) return true; | 1059 if (import_code.empty()) return true; |
979 | 1060 |
980 { | 1061 Handle<FixedArray> new_imports = |
981 DisallowHeapAllocation no_gc; | 1062 isolate->factory()->NewFixedArray(static_cast<int>(import_code.size())); |
982 std::map<Code*, int> import_to_index; | 1063 for (int i = 0; i < new_imports->length(); ++i) { |
983 Handle<FixedArray> mapping = | 1064 new_imports->set(i, *import_code[i]); |
984 compiled_module->GetValueChecked<FixedArray>(isolate, kImportMap); | |
985 for (int i = 0; i < mapping->length(); ++i) { | |
986 import_to_index.insert(std::make_pair(Code::cast(mapping->get(i)), i)); | |
987 } | |
988 | |
989 Handle<FixedArray> code_table = Handle<FixedArray>( | |
990 FixedArray::cast(instance->GetInternalField(kWasmModuleCodeTable))); | |
991 | |
992 int mode_mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET); | |
993 AllowDeferredHandleDereference embedding_raw_address; | |
994 for (int i = 0; i < code_table->length(); ++i) { | |
995 Handle<Code> wasm_function = | |
996 code_table->GetValueChecked<Code>(isolate, i); | |
997 for (RelocIterator it(*wasm_function, mode_mask); !it.done(); it.next()) { | |
998 Code* target = | |
999 Code::GetCodeFromTargetAddress(it.rinfo()->target_address()); | |
1000 if (target->kind() == Code::WASM_TO_JS_FUNCTION) { | |
1001 auto found_index = import_to_index.find(target); | |
1002 CHECK(found_index != import_to_index.end()); | |
1003 int index = found_index->second; | |
1004 CHECK(index < static_cast<int>(import_code.size())); | |
1005 Handle<Code> new_target = import_code[index]; | |
1006 it.rinfo()->set_target_address(new_target->instruction_start(), | |
1007 UPDATE_WRITE_BARRIER, | |
1008 SKIP_ICACHE_FLUSH); | |
1009 } | |
1010 } | |
1011 } | |
1012 } | 1065 } |
1013 Handle<FixedArray> new_mapping = | 1066 compiled_module->set(kImportMap, *new_imports); |
1014 isolate->factory()->NewFixedArray(static_cast<int>(import_code.size())); | |
1015 for (int i = 0; i < new_mapping->length(); ++i) { | |
1016 new_mapping->set(i, *import_code[i]); | |
1017 } | |
1018 compiled_module->set(kImportMap, *new_mapping); | |
1019 | |
1020 return true; | 1067 return true; |
1021 } | 1068 } |
1022 | 1069 |
1023 bool SetupExportsObject(Handle<FixedArray> compiled_module, Isolate* isolate, | 1070 bool SetupExportsObject(Handle<FixedArray> compiled_module, Isolate* isolate, |
1024 Handle<JSObject> instance, ErrorThrower* thrower) { | 1071 Handle<JSObject> instance, ErrorThrower* thrower) { |
1025 Factory* factory = isolate->factory(); | 1072 Factory* factory = isolate->factory(); |
1026 bool mem_export = | 1073 bool mem_export = |
1027 static_cast<bool>(Smi::cast(compiled_module->get(kExportMem))->value()); | 1074 static_cast<bool>(Smi::cast(compiled_module->get(kExportMem))->value()); |
1028 ModuleOrigin origin = static_cast<ModuleOrigin>( | 1075 ModuleOrigin origin = static_cast<ModuleOrigin>( |
1029 Smi::cast(compiled_module->get(kOrigin))->value()); | 1076 Smi::cast(compiled_module->get(kOrigin))->value()); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1074 // Export the memory as a named property. | 1121 // Export the memory as a named property. |
1075 Handle<String> name = factory->InternalizeUtf8String("memory"); | 1122 Handle<String> name = factory->InternalizeUtf8String("memory"); |
1076 Handle<JSArrayBuffer> memory = Handle<JSArrayBuffer>( | 1123 Handle<JSArrayBuffer> memory = Handle<JSArrayBuffer>( |
1077 JSArrayBuffer::cast(instance->GetInternalField(kWasmMemArrayBuffer))); | 1124 JSArrayBuffer::cast(instance->GetInternalField(kWasmMemArrayBuffer))); |
1078 JSObject::AddProperty(exports_object, name, memory, READ_ONLY); | 1125 JSObject::AddProperty(exports_object, name, memory, READ_ONLY); |
1079 } | 1126 } |
1080 } | 1127 } |
1081 return true; | 1128 return true; |
1082 } | 1129 } |
1083 | 1130 |
1131 #define GET_COMPILED_MODULE_WEAK_RELATION_OR_NULL(Field) \ | |
1132 WeakCell* Get##Field(const FixedArray* compiled_module) { \ | |
1133 Object* obj = compiled_module->get(k##Field); \ | |
1134 DCHECK_NOT_NULL(obj); \ | |
1135 if (obj->IsWeakCell()) { \ | |
1136 return WeakCell::cast(obj); \ | |
1137 } else { \ | |
1138 return nullptr; \ | |
1139 } \ | |
1140 } | |
1141 | |
1142 GET_COMPILED_MODULE_WEAK_RELATION_OR_NULL(NextInstance) | |
1143 GET_COMPILED_MODULE_WEAK_RELATION_OR_NULL(PrevInstance) | |
1144 GET_COMPILED_MODULE_WEAK_RELATION_OR_NULL(OwningInstance) | |
1145 GET_COMPILED_MODULE_WEAK_RELATION_OR_NULL(ModuleObject) | |
1146 | |
1147 static void ResetCompiledModule(Isolate* isolate, JSObject* owner, | |
1148 FixedArray* compiled_module) { | |
1149 Object* undefined = *isolate->factory()->undefined_value(); | |
1150 Object* mem_size_obj = compiled_module->get(kMemSize); | |
1151 DCHECK(mem_size_obj->IsNumber()); | |
1152 uint32_t old_mem_size = | |
1153 static_cast<uint32_t>(HeapNumber::cast(mem_size_obj)->value()); | |
1154 Object* mem_start = compiled_module->get(kMemStart); | |
1155 Address old_mem_address = nullptr; | |
1156 Address globals_start = | |
1157 GetGlobalStartAddressFromCodeTemplate(undefined, owner); | |
1158 | |
1159 if (old_mem_size > 0) { | |
1160 CHECK_NE(mem_start, undefined); | |
1161 old_mem_address = | |
1162 static_cast<Address>(JSArrayBuffer::cast(mem_start)->backing_store()); | |
1163 } | |
1164 int mode_mask = RelocInfo::ModeMask(RelocInfo::WASM_MEMORY_REFERENCE) | | |
1165 RelocInfo::ModeMask(RelocInfo::WASM_MEMORY_SIZE_REFERENCE) | | |
1166 RelocInfo::ModeMask(RelocInfo::WASM_GLOBAL_REFERENCE); | |
1167 | |
1168 Object* fct_obj = compiled_module->get(kFunctions); | |
1169 if (fct_obj != nullptr && fct_obj != undefined && | |
1170 (old_mem_size > 0 || globals_start != nullptr)) { | |
1171 FixedArray* functions = FixedArray::cast(fct_obj); | |
1172 for (int i = 0; i < functions->length(); ++i) { | |
1173 Code* code = Code::cast(functions->get(i)); | |
1174 bool changed = false; | |
1175 for (RelocIterator it(code, mode_mask); !it.done(); it.next()) { | |
1176 RelocInfo::Mode mode = it.rinfo()->rmode(); | |
1177 if (RelocInfo::IsWasmMemoryReference(mode) || | |
1178 RelocInfo::IsWasmMemorySizeReference(mode)) { | |
1179 it.rinfo()->update_wasm_memory_reference(old_mem_address, nullptr, | |
1180 old_mem_size, old_mem_size); | |
1181 changed = true; | |
1182 } else { | |
1183 CHECK(RelocInfo::IsWasmGlobalReference(mode)); | |
1184 it.rinfo()->update_wasm_global_reference(globals_start, nullptr); | |
1185 changed = true; | |
1186 } | |
1187 } | |
1188 if (changed) { | |
1189 Assembler::FlushICache(isolate, code->instruction_start(), | |
1190 code->instruction_size()); | |
1191 } | |
1192 } | |
1193 } | |
1194 compiled_module->set(kOwningInstance, undefined); | |
1195 compiled_module->set(kMemStart, undefined); | |
1196 } | |
1197 | |
1198 static void InstanceFinalizer(const v8::WeakCallbackInfo<void>& data) { | |
1199 JSObject** p = reinterpret_cast<JSObject**>(data.GetParameter()); | |
1200 JSObject* owner = *p; | |
1201 FixedArray* compiled_module = | |
1202 FixedArray::cast(owner->GetInternalField(kWasmCompiledModule)); | |
1203 Isolate* isolate = reinterpret_cast<Isolate*>(data.GetIsolate()); | |
1204 Object* undefined = *isolate->factory()->undefined_value(); | |
1205 WeakCell* weak_module_obj = GetModuleObject(compiled_module); | |
1206 DCHECK_NOT_NULL(weak_module_obj); | |
1207 if (!weak_module_obj->cleared()) { | |
bradnelson
2016/09/02 16:57:00
Why?
Mircea Trofin
2016/09/02 20:55:30
It may be cleared when this happens:
var m = new W
| |
1208 JSObject* module_obj = JSObject::cast(weak_module_obj->value()); | |
1209 FixedArray* current_template = | |
1210 FixedArray::cast(module_obj->GetInternalField(0)); | |
1211 DCHECK_NULL(GetPrevInstance(current_template)); | |
bradnelson
2016/09/02 16:57:00
Separate out the remove from chain operation?
Or c
Mircea Trofin
2016/09/02 20:55:30
There nothing else than the delete - we're called
| |
1212 WeakCell* next = GetNextInstance(compiled_module); | |
1213 WeakCell* prev = GetPrevInstance(compiled_module); | |
1214 | |
1215 if (current_template == compiled_module) { | |
1216 if (next == nullptr) { | |
1217 ResetCompiledModule(isolate, owner, compiled_module); | |
1218 } else { | |
1219 DCHECK(next->value()->IsFixedArray()); | |
1220 module_obj->SetInternalField(0, next->value()); | |
1221 DCHECK_NULL(prev); | |
1222 FixedArray::cast(next->value())->set(kPrevInstance, undefined); | |
1223 } | |
1224 } else { | |
1225 DCHECK(!(prev == nullptr && next == nullptr)); | |
1226 // the only reason prev or next would be cleared is if the | |
1227 // respective objects got collected, but if that happened, | |
1228 // we would have relinked the list. | |
1229 if (prev != nullptr) { | |
1230 DCHECK(!prev->cleared()); | |
1231 FixedArray::cast(prev->value()) | |
1232 ->set(kNextInstance, next == nullptr ? undefined : next); | |
1233 } | |
1234 if (next != nullptr) { | |
1235 DCHECK(!next->cleared()); | |
1236 FixedArray::cast(next->value()) | |
1237 ->set(kPrevInstance, prev == nullptr ? undefined : prev); | |
1238 } | |
1239 } | |
1240 } | |
1241 GlobalHandles::Destroy(reinterpret_cast<Object**>(p)); | |
1242 } | |
1243 | |
1084 } // namespace | 1244 } // namespace |
1085 | 1245 |
1086 MaybeHandle<FixedArray> WasmModule::CompileFunctions( | 1246 MaybeHandle<FixedArray> WasmModule::CompileFunctions( |
1087 Isolate* isolate, ErrorThrower* thrower) const { | 1247 Isolate* isolate, ErrorThrower* thrower) const { |
1088 Factory* factory = isolate->factory(); | 1248 Factory* factory = isolate->factory(); |
1089 | 1249 |
1090 MaybeHandle<FixedArray> nothing; | 1250 MaybeHandle<FixedArray> nothing; |
1091 | 1251 |
1092 WasmModuleInstance temp_instance_for_compilation(this); | 1252 WasmModuleInstance temp_instance_for_compilation(this); |
1093 temp_instance_for_compilation.context = isolate->native_context(); | 1253 temp_instance_for_compilation.context = isolate->native_context(); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1149 } | 1309 } |
1150 if (thrower->error()) return nothing; | 1310 if (thrower->error()) return nothing; |
1151 | 1311 |
1152 // At this point, compilation has completed. Update the code table. | 1312 // At this point, compilation has completed. Update the code table. |
1153 for (size_t i = FLAG_skip_compiling_wasm_funcs; | 1313 for (size_t i = FLAG_skip_compiling_wasm_funcs; |
1154 i < temp_instance_for_compilation.function_code.size(); ++i) { | 1314 i < temp_instance_for_compilation.function_code.size(); ++i) { |
1155 Code* code = *temp_instance_for_compilation.function_code[i]; | 1315 Code* code = *temp_instance_for_compilation.function_code[i]; |
1156 compiled_functions->set(static_cast<int>(i), code); | 1316 compiled_functions->set(static_cast<int>(i), code); |
1157 } | 1317 } |
1158 | 1318 |
1319 LinkModuleFunctions(isolate, compiled_functions); | |
1320 | |
1321 // TODO(mtrofin): do we need to flush the cache here? | |
1322 FlushAssemblyCache(isolate, compiled_functions); | |
bradnelson
2016/09/02 16:56:59
Because the code has never run? Probably not.
Mircea Trofin
2016/09/02 20:55:30
Acknowledged.
| |
1323 | |
1159 // Create the compiled module object, and populate with compiled functions | 1324 // Create the compiled module object, and populate with compiled functions |
1160 // and information needed at instantiation time. This object needs to be | 1325 // and information needed at instantiation time. This object needs to be |
1161 // serializable. Instantiation may occur off a deserialized version of this | 1326 // serializable. Instantiation may occur off a deserialized version of this |
1162 // object. | 1327 // object. |
1163 Handle<FixedArray> ret = | 1328 Handle<FixedArray> ret = |
1164 factory->NewFixedArray(kCompiledWasmObjectTableSize, TENURED); | 1329 factory->NewFixedArray(kCompiledWasmObjectTableSize, TENURED); |
1165 ret->set(kFunctions, *compiled_functions); | 1330 ret->set(kFunctions, *compiled_functions); |
1166 if (!indirect_table.is_null()) { | 1331 if (!indirect_table.is_null()) { |
1167 ret->set(kTableOfIndirectFunctionTables, *indirect_table.ToHandleChecked()); | 1332 ret->set(kTableOfIndirectFunctionTables, *indirect_table.ToHandleChecked()); |
1168 } | 1333 } |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1244 } | 1409 } |
1245 | 1410 |
1246 Handle<ByteArray> function_name_table = | 1411 Handle<ByteArray> function_name_table = |
1247 BuildFunctionNamesTable(isolate, module_env.module); | 1412 BuildFunctionNamesTable(isolate, module_env.module); |
1248 ret->set(kFunctionNameTable, *function_name_table); | 1413 ret->set(kFunctionNameTable, *function_name_table); |
1249 ret->set(kMinRequiredMemory, Smi::FromInt(min_mem_pages)); | 1414 ret->set(kMinRequiredMemory, Smi::FromInt(min_mem_pages)); |
1250 if (data_segments.size() > 0) SaveDataSegmentInfo(factory, this, ret); | 1415 if (data_segments.size() > 0) SaveDataSegmentInfo(factory, this, ret); |
1251 ret->set(kGlobalsSize, Smi::FromInt(globals_size)); | 1416 ret->set(kGlobalsSize, Smi::FromInt(globals_size)); |
1252 ret->set(kExportMem, Smi::FromInt(mem_export)); | 1417 ret->set(kExportMem, Smi::FromInt(mem_export)); |
1253 ret->set(kOrigin, Smi::FromInt(origin)); | 1418 ret->set(kOrigin, Smi::FromInt(origin)); |
1419 ret->set(kMemSize, | |
1420 *factory->NewHeapNumber( | |
1421 static_cast<double>(temp_instance_for_compilation.mem_size), | |
1422 MUTABLE, TENURED)); | |
1254 return ret; | 1423 return ret; |
1255 } | 1424 } |
1256 | 1425 |
1257 void PatchJSWrapper(Isolate* isolate, Handle<Code> wrapper, | 1426 void PatchJSWrapper(Isolate* isolate, Handle<Code> wrapper, |
1258 Handle<Code> new_target) { | 1427 Handle<Code> new_target) { |
1259 AllowDeferredHandleDereference embedding_raw_address; | 1428 AllowDeferredHandleDereference embedding_raw_address; |
1260 bool seen = false; | 1429 bool seen = false; |
1261 for (RelocIterator it(*wrapper, 1 << RelocInfo::CODE_TARGET); !it.done(); | 1430 for (RelocIterator it(*wrapper, 1 << RelocInfo::CODE_TARGET); !it.done(); |
1262 it.next()) { | 1431 it.next()) { |
1263 Code* target = Code::GetCodeFromTargetAddress(it.rinfo()->target_address()); | 1432 Code* target = Code::GetCodeFromTargetAddress(it.rinfo()->target_address()); |
1264 if (target->kind() == Code::WASM_FUNCTION) { | 1433 if (target->kind() == Code::WASM_FUNCTION) { |
1265 DCHECK(!seen); | 1434 DCHECK(!seen); |
1266 seen = true; | 1435 seen = true; |
1267 it.rinfo()->set_target_address(new_target->instruction_start(), | 1436 it.rinfo()->set_target_address(new_target->instruction_start(), |
1268 UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH); | 1437 UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH); |
1269 } | 1438 } |
1270 } | 1439 } |
1271 CHECK(seen); | 1440 CHECK(seen); |
1272 Assembler::FlushICache(isolate, wrapper->instruction_start(), | 1441 Assembler::FlushICache(isolate, wrapper->instruction_start(), |
1273 wrapper->instruction_size()); | 1442 wrapper->instruction_size()); |
1274 } | 1443 } |
1275 | 1444 |
1276 Handle<FixedArray> SetupIndirectFunctionTable( | 1445 Handle<FixedArray> SetupIndirectFunctionTable( |
1277 Isolate* isolate, Handle<FixedArray> wasm_functions, | 1446 Isolate* isolate, Handle<FixedArray> wasm_functions, |
1278 Handle<FixedArray> indirect_table_template) { | 1447 Handle<FixedArray> indirect_table_template, |
1448 Handle<FixedArray> tables_to_replace) { | |
1279 Factory* factory = isolate->factory(); | 1449 Factory* factory = isolate->factory(); |
1280 Handle<FixedArray> cloned_indirect_tables = | 1450 Handle<FixedArray> cloned_indirect_tables = |
1281 factory->CopyFixedArray(indirect_table_template); | 1451 factory->CopyFixedArray(indirect_table_template); |
1282 for (int i = 0; i < cloned_indirect_tables->length(); ++i) { | 1452 for (int i = 0; i < cloned_indirect_tables->length(); ++i) { |
1283 Handle<FixedArray> orig_metadata = | 1453 Handle<FixedArray> orig_metadata = |
1284 cloned_indirect_tables->GetValueChecked<FixedArray>(isolate, i); | 1454 cloned_indirect_tables->GetValueChecked<FixedArray>(isolate, i); |
1285 Handle<FixedArray> cloned_metadata = factory->CopyFixedArray(orig_metadata); | 1455 Handle<FixedArray> cloned_metadata = factory->CopyFixedArray(orig_metadata); |
1286 cloned_indirect_tables->set(i, *cloned_metadata); | 1456 cloned_indirect_tables->set(i, *cloned_metadata); |
1287 | 1457 |
1288 Handle<FixedArray> orig_table = | 1458 Handle<FixedArray> orig_table = |
1289 cloned_metadata->GetValueChecked<FixedArray>(isolate, kTable); | 1459 cloned_metadata->GetValueChecked<FixedArray>(isolate, kTable); |
1290 Handle<FixedArray> cloned_table = factory->CopyFixedArray(orig_table); | 1460 Handle<FixedArray> cloned_table = factory->CopyFixedArray(orig_table); |
1291 cloned_metadata->set(kTable, *cloned_table); | 1461 cloned_metadata->set(kTable, *cloned_table); |
1292 // Patch the cloned code to refer to the cloned kTable. | 1462 // Patch the cloned code to refer to the cloned kTable. |
1293 for (int i = 0; i < wasm_functions->length(); ++i) { | 1463 Handle<FixedArray> table_to_replace = |
1464 tables_to_replace->GetValueChecked<FixedArray>(isolate, i) | |
1465 ->GetValueChecked<FixedArray>(isolate, kTable); | |
1466 for (int fct_index = 0; fct_index < wasm_functions->length(); ++fct_index) { | |
1294 Handle<Code> wasm_function = | 1467 Handle<Code> wasm_function = |
1295 wasm_functions->GetValueChecked<Code>(isolate, i); | 1468 wasm_functions->GetValueChecked<Code>(isolate, fct_index); |
1296 PatchFunctionTable(wasm_function, orig_table, cloned_table); | 1469 PatchFunctionTable(wasm_function, table_to_replace, cloned_table); |
1297 } | 1470 } |
1298 } | 1471 } |
1299 return cloned_indirect_tables; | 1472 return cloned_indirect_tables; |
1300 } | 1473 } |
1301 | 1474 |
1302 Handle<FixedArray> CloneModuleForInstance(Isolate* isolate, | 1475 Handle<FixedArray> CloneModuleForInstance(Isolate* isolate, |
1303 Handle<FixedArray> original) { | 1476 Handle<FixedArray> original) { |
1304 Factory* factory = isolate->factory(); | 1477 Factory* factory = isolate->factory(); |
1478 bool is_first = | |
1479 original->GetValue<WeakCell>(isolate, kOwningInstance).is_null(); | |
1480 | |
1481 if (is_first) { | |
1482 return original; | |
1483 } | |
1484 | |
1485 // We insert the latest clone in front. | |
1305 Handle<FixedArray> clone = factory->CopyFixedArray(original); | 1486 Handle<FixedArray> clone = factory->CopyFixedArray(original); |
1487 Handle<WeakCell> weak_link_to_wasm_obj = | |
1488 original->GetValueChecked<WeakCell>(isolate, kModuleObject); | |
1489 | |
1490 clone->set(kModuleObject, *weak_link_to_wasm_obj); | |
1491 clone->set(kNextInstance, *factory->NewWeakCell(original)); | |
1492 original->set(kPrevInstance, *factory->NewWeakCell(clone)); | |
1493 JSObject::cast(weak_link_to_wasm_obj->value())->SetInternalField(0, *clone); | |
1306 | 1494 |
1307 // Clone each wasm code object. | 1495 // Clone each wasm code object. |
1308 Handle<FixedArray> orig_wasm_functions = | 1496 Handle<FixedArray> orig_wasm_functions = |
1309 original->GetValueChecked<FixedArray>(isolate, kFunctions); | 1497 original->GetValueChecked<FixedArray>(isolate, kFunctions); |
1310 Handle<FixedArray> clone_wasm_functions = | 1498 Handle<FixedArray> clone_wasm_functions = |
1311 factory->CopyFixedArray(orig_wasm_functions); | 1499 factory->CopyFixedArray(orig_wasm_functions); |
1312 clone->set(kFunctions, *clone_wasm_functions); | 1500 clone->set(kFunctions, *clone_wasm_functions); |
1313 for (int i = 0; i < clone_wasm_functions->length(); ++i) { | 1501 for (int i = 0; i < clone_wasm_functions->length(); ++i) { |
1314 Handle<Code> orig_code = | 1502 Handle<Code> orig_code = |
1315 clone_wasm_functions->GetValueChecked<Code>(isolate, i); | 1503 clone_wasm_functions->GetValueChecked<Code>(isolate, i); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1356 clone->set(kStartupFunction, *startup_metadata); | 1544 clone->set(kStartupFunction, *startup_metadata); |
1357 // TODO(wasm): see todo above about int vs size_t indexing in FixedArray. | 1545 // TODO(wasm): see todo above about int vs size_t indexing in FixedArray. |
1358 int startup_fct_index = | 1546 int startup_fct_index = |
1359 Smi::cast(startup_metadata->get(kExportedFunctionIndex))->value(); | 1547 Smi::cast(startup_metadata->get(kExportedFunctionIndex))->value(); |
1360 CHECK_GE(startup_fct_index, 0); | 1548 CHECK_GE(startup_fct_index, 0); |
1361 CHECK_LT(startup_fct_index, clone_wasm_functions->length()); | 1549 CHECK_LT(startup_fct_index, clone_wasm_functions->length()); |
1362 Handle<Code> new_target = | 1550 Handle<Code> new_target = |
1363 clone_wasm_functions->GetValueChecked<Code>(isolate, startup_fct_index); | 1551 clone_wasm_functions->GetValueChecked<Code>(isolate, startup_fct_index); |
1364 PatchJSWrapper(isolate, startup_fct_clone, new_target); | 1552 PatchJSWrapper(isolate, startup_fct_clone, new_target); |
1365 } | 1553 } |
1554 clone->set(kImportMap, *isolate->factory()->undefined_value()); | |
1366 return clone; | 1555 return clone; |
1367 } | 1556 } |
1368 | 1557 |
1369 // Instantiates a wasm module as a JSObject. | 1558 // Instantiates a wasm module as a JSObject. |
1370 // * allocates a backing store of {mem_size} bytes. | 1559 // * allocates a backing store of {mem_size} bytes. |
1371 // * installs a named property "memory" for that buffer if exported | 1560 // * installs a named property "memory" for that buffer if exported |
1372 // * installs named properties on the object for exported functions | 1561 // * installs named properties on the object for exported functions |
1373 // * compiles wasm code to machine code | 1562 // * compiles wasm code to machine code |
1374 MaybeHandle<JSObject> WasmModule::Instantiate( | 1563 MaybeHandle<JSObject> WasmModule::Instantiate( |
1375 Isolate* isolate, Handle<FixedArray> compiled_module, | 1564 Isolate* isolate, Handle<FixedArray> compiled_module_template, |
1376 Handle<JSReceiver> ffi, Handle<JSArrayBuffer> memory) { | 1565 Handle<JSReceiver> ffi, Handle<JSArrayBuffer> memory) { |
1377 HistogramTimerScope wasm_instantiate_module_time_scope( | 1566 HistogramTimerScope wasm_instantiate_module_time_scope( |
1378 isolate->counters()->wasm_instantiate_module_time()); | 1567 isolate->counters()->wasm_instantiate_module_time()); |
1379 ErrorThrower thrower(isolate, "WasmModule::Instantiate()"); | 1568 ErrorThrower thrower(isolate, "WasmModule::Instantiate()"); |
1380 Factory* factory = isolate->factory(); | 1569 Factory* factory = isolate->factory(); |
1381 | 1570 |
1382 compiled_module = CloneModuleForInstance(isolate, compiled_module); | 1571 Handle<FixedArray> compiled_module = |
1572 CloneModuleForInstance(isolate, compiled_module_template); | |
1383 | 1573 |
1574 bool template_is_owned = | |
1575 GetOwningInstance(*compiled_module_template) != nullptr; | |
1576 | |
1577 MaybeHandle<JSObject> template_owner; | |
1578 if (template_is_owned) { | |
1579 Handle<WeakCell> weak_owner = | |
1580 compiled_module_template->GetValueChecked<WeakCell>(isolate, | |
1581 kOwningInstance); | |
1582 template_owner = handle(JSObject::cast(weak_owner->value())); | |
1583 } | |
1384 // These fields are compulsory. | 1584 // These fields are compulsory. |
1385 Handle<FixedArray> code_table = | 1585 Handle<FixedArray> code_table = |
1386 compiled_module->GetValueChecked<FixedArray>(isolate, kFunctions); | 1586 compiled_module->GetValueChecked<FixedArray>(isolate, kFunctions); |
1387 | 1587 |
1388 std::vector<Handle<Code>> functions( | |
1389 static_cast<size_t>(code_table->length())); | |
1390 for (int i = 0; i < code_table->length(); ++i) { | |
1391 functions[static_cast<size_t>(i)] = | |
1392 code_table->GetValueChecked<Code>(isolate, i); | |
1393 } | |
1394 LinkModuleFunctions(isolate, functions); | |
1395 | |
1396 RecordStats(isolate, code_table); | 1588 RecordStats(isolate, code_table); |
1397 | 1589 |
1398 MaybeHandle<JSObject> nothing; | 1590 MaybeHandle<JSObject> nothing; |
1399 | 1591 |
1400 Handle<Map> map = factory->NewMap( | 1592 Handle<Map> map = factory->NewMap( |
1401 JS_OBJECT_TYPE, | 1593 JS_OBJECT_TYPE, |
1402 JSObject::kHeaderSize + kWasmModuleInternalFieldCount * kPointerSize); | 1594 JSObject::kHeaderSize + kWasmModuleInternalFieldCount * kPointerSize); |
1403 Handle<JSObject> js_object = factory->NewJSObjectFromMap(map, TENURED); | 1595 Handle<JSObject> js_object = factory->NewJSObjectFromMap(map, TENURED); |
1404 js_object->SetInternalField(kWasmModuleCodeTable, *code_table); | 1596 js_object->SetInternalField(kWasmModuleCodeTable, *code_table); |
1405 | 1597 |
1598 // Remember the old imports, for the case when we are at the first instance - | |
1599 // they will be | |
1600 // replaced with the instance's actual imports in SetupImports. | |
bradnelson
2016/09/02 16:57:00
reflow comment
Mircea Trofin
2016/09/02 20:55:30
Done.
| |
1601 MaybeHandle<FixedArray> old_imports = | |
1602 compiled_module_template->GetValue<FixedArray>(isolate, kImportMap); | |
1406 if (!(SetupInstanceHeap(isolate, compiled_module, js_object, memory, | 1603 if (!(SetupInstanceHeap(isolate, compiled_module, js_object, memory, |
1407 &thrower) && | 1604 &thrower) && |
1408 SetupGlobals(isolate, compiled_module, js_object, &thrower) && | 1605 SetupGlobals(isolate, template_owner, compiled_module, js_object, |
1606 &thrower) && | |
1409 SetupImports(isolate, compiled_module, js_object, &thrower, ffi) && | 1607 SetupImports(isolate, compiled_module, js_object, &thrower, ffi) && |
1410 SetupExportsObject(compiled_module, isolate, js_object, &thrower))) { | 1608 SetupExportsObject(compiled_module, isolate, js_object, &thrower))) { |
1411 return nothing; | 1609 return nothing; |
1412 } | 1610 } |
1413 | 1611 |
1612 FixupFunctionsAndImports( | |
1613 compiled_module_template->GetValueChecked<FixedArray>(isolate, | |
1614 kFunctions), | |
1615 code_table, old_imports, | |
1616 compiled_module->GetValue<FixedArray>(isolate, kImportMap)); | |
1617 | |
1414 SetDebugSupport(factory, compiled_module, js_object); | 1618 SetDebugSupport(factory, compiled_module, js_object); |
1415 SetRuntimeSupport(isolate, js_object); | 1619 SetRuntimeSupport(isolate, js_object); |
1416 | 1620 |
1417 FlushAssemblyCache(isolate, code_table); | 1621 FlushAssemblyCache(isolate, code_table); |
1418 | 1622 |
1419 MaybeHandle<FixedArray> maybe_indirect_tables = | 1623 { |
1420 compiled_module->GetValue<FixedArray>(isolate, | 1624 std::vector<Handle<Code>> functions( |
1421 kTableOfIndirectFunctionTables); | 1625 static_cast<size_t>(code_table->length())); |
1422 Handle<FixedArray> indirect_tables_template; | 1626 for (int i = 0; i < code_table->length(); ++i) { |
1423 if (maybe_indirect_tables.ToHandle(&indirect_tables_template)) { | 1627 functions[static_cast<size_t>(i)] = |
1424 Handle<FixedArray> indirect_tables = SetupIndirectFunctionTable( | 1628 code_table->GetValueChecked<Code>(isolate, i); |
1425 isolate, code_table, indirect_tables_template); | |
1426 for (int i = 0; i < indirect_tables->length(); ++i) { | |
1427 Handle<FixedArray> metadata = | |
1428 indirect_tables->GetValueChecked<FixedArray>(isolate, i); | |
1429 uint32_t size = Smi::cast(metadata->get(kSize))->value(); | |
1430 Handle<FixedArray> table = | |
1431 metadata->GetValueChecked<FixedArray>(isolate, kTable); | |
1432 wasm::PopulateFunctionTable(table, size, &functions); | |
1433 } | 1629 } |
1434 js_object->SetInternalField(kWasmModuleFunctionTable, *indirect_tables); | 1630 |
1631 MaybeHandle<FixedArray> maybe_indirect_tables = | |
1632 compiled_module->GetValue<FixedArray>(isolate, | |
1633 kTableOfIndirectFunctionTables); | |
1634 Handle<FixedArray> indirect_tables_template; | |
1635 if (maybe_indirect_tables.ToHandle(&indirect_tables_template)) { | |
1636 Handle<FixedArray> to_replace = | |
1637 template_owner.is_null() | |
1638 ? indirect_tables_template | |
1639 : handle(FixedArray::cast( | |
1640 template_owner.ToHandleChecked()->GetInternalField( | |
1641 kWasmModuleFunctionTable))); | |
1642 Handle<FixedArray> indirect_tables = SetupIndirectFunctionTable( | |
1643 isolate, code_table, indirect_tables_template, to_replace); | |
1644 for (int i = 0; i < indirect_tables->length(); ++i) { | |
1645 Handle<FixedArray> metadata = | |
1646 indirect_tables->GetValueChecked<FixedArray>(isolate, i); | |
1647 uint32_t size = Smi::cast(metadata->get(kSize))->value(); | |
1648 Handle<FixedArray> table = | |
1649 metadata->GetValueChecked<FixedArray>(isolate, kTable); | |
1650 wasm::PopulateFunctionTable(table, size, &functions); | |
1651 } | |
1652 js_object->SetInternalField(kWasmModuleFunctionTable, *indirect_tables); | |
1653 } | |
1435 } | 1654 } |
1436 | 1655 |
1437 // Run the start function if one was specified. | 1656 // Run the start function if one was specified. |
1438 MaybeHandle<FixedArray> maybe_startup_fct = | 1657 MaybeHandle<FixedArray> maybe_startup_fct = |
1439 compiled_module->GetValue<FixedArray>(isolate, kStartupFunction); | 1658 compiled_module->GetValue<FixedArray>(isolate, kStartupFunction); |
1440 Handle<FixedArray> metadata; | 1659 Handle<FixedArray> metadata; |
1441 if (maybe_startup_fct.ToHandle(&metadata)) { | 1660 if (maybe_startup_fct.ToHandle(&metadata)) { |
1442 HandleScope scope(isolate); | 1661 HandleScope scope(isolate); |
1443 Handle<Code> startup_code = | 1662 Handle<Code> startup_code = |
1444 metadata->GetValueChecked<Code>(isolate, kExportCode); | 1663 metadata->GetValueChecked<Code>(isolate, kExportCode); |
1445 int arity = Smi::cast(metadata->get(kExportArity))->value(); | 1664 int arity = Smi::cast(metadata->get(kExportArity))->value(); |
1446 MaybeHandle<ByteArray> startup_signature = | 1665 MaybeHandle<ByteArray> startup_signature = |
1447 metadata->GetValue<ByteArray>(isolate, kExportedSignature); | 1666 metadata->GetValue<ByteArray>(isolate, kExportedSignature); |
1448 Handle<JSFunction> startup_fct = WrapExportCodeAsJSFunction( | 1667 Handle<JSFunction> startup_fct = WrapExportCodeAsJSFunction( |
1449 isolate, startup_code, factory->InternalizeUtf8String("start"), arity, | 1668 isolate, startup_code, factory->InternalizeUtf8String("start"), arity, |
1450 startup_signature, js_object); | 1669 startup_signature, js_object); |
1451 RecordStats(isolate, *startup_code); | 1670 RecordStats(isolate, *startup_code); |
1452 // Call the JS function. | 1671 // Call the JS function. |
1453 Handle<Object> undefined = isolate->factory()->undefined_value(); | 1672 Handle<Object> undefined = isolate->factory()->undefined_value(); |
1454 MaybeHandle<Object> retval = | 1673 MaybeHandle<Object> retval = |
1455 Execution::Call(isolate, startup_fct, undefined, 0, nullptr); | 1674 Execution::Call(isolate, startup_fct, undefined, 0, nullptr); |
1456 | 1675 |
1457 if (retval.is_null()) { | 1676 if (retval.is_null()) { |
1458 thrower.Error("WASM.instantiateModule(): start function failed"); | 1677 thrower.Error("WASM.instantiateModule(): start function failed"); |
1459 return nothing; | 1678 return nothing; |
1460 } | 1679 } |
1461 } | 1680 } |
1462 | 1681 |
1463 DCHECK(wasm::IsWasmObject(*js_object)); | 1682 DCHECK(wasm::IsWasmObject(*js_object)); |
1683 | |
1684 if (!compiled_module->GetValue<WeakCell>(isolate, kModuleObject).is_null()) { | |
1685 js_object->SetInternalField(kWasmCompiledModule, *compiled_module); | |
1686 compiled_module->set(kOwningInstance, *factory->NewWeakCell(js_object)); | |
1687 | |
1688 Handle<Object> global_handle = | |
1689 isolate->global_handles()->Create(*js_object); | |
1690 GlobalHandles::MakeWeak(global_handle.location(), global_handle.location(), | |
1691 &InstanceFinalizer, | |
1692 v8::WeakCallbackType::kFinalizer); | |
1693 } | |
1694 | |
1464 return js_object; | 1695 return js_object; |
1465 } | 1696 } |
1466 | 1697 |
1467 // TODO(mtrofin): remove this once we move to WASM_DIRECT_CALL | 1698 // TODO(mtrofin): remove this once we move to WASM_DIRECT_CALL |
1468 Handle<Code> ModuleEnv::GetCodeOrPlaceholder(uint32_t index) const { | 1699 Handle<Code> ModuleEnv::GetCodeOrPlaceholder(uint32_t index) const { |
1469 DCHECK(IsValidFunction(index)); | 1700 DCHECK(IsValidFunction(index)); |
1470 if (!placeholders.empty()) return placeholders[index]; | 1701 if (!placeholders.empty()) return placeholders[index]; |
1471 DCHECK_NOT_NULL(instance); | 1702 DCHECK_NOT_NULL(instance); |
1472 return instance->function_code[index]; | 1703 return instance->function_code[index]; |
1473 } | 1704 } |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1641 DCHECK(origin == ModuleOrigin::kAsmJsOrigin); | 1872 DCHECK(origin == ModuleOrigin::kAsmJsOrigin); |
1642 Handle<Map> map = isolate->factory()->NewMap( | 1873 Handle<Map> map = isolate->factory()->NewMap( |
1643 JS_OBJECT_TYPE, JSObject::kHeaderSize + kPointerSize); | 1874 JS_OBJECT_TYPE, JSObject::kHeaderSize + kPointerSize); |
1644 module_obj = isolate->factory()->NewJSObjectFromMap(map, TENURED); | 1875 module_obj = isolate->factory()->NewJSObjectFromMap(map, TENURED); |
1645 } | 1876 } |
1646 module_obj->SetInternalField(0, *compiled_module); | 1877 module_obj->SetInternalField(0, *compiled_module); |
1647 if (origin == ModuleOrigin::kWasmOrigin) { | 1878 if (origin == ModuleOrigin::kWasmOrigin) { |
1648 Handle<Symbol> module_sym(isolate->native_context()->wasm_module_sym()); | 1879 Handle<Symbol> module_sym(isolate->native_context()->wasm_module_sym()); |
1649 Object::SetProperty(module_obj, module_sym, module_obj, STRICT).Check(); | 1880 Object::SetProperty(module_obj, module_sym, module_obj, STRICT).Check(); |
1650 } | 1881 } |
1882 compiled_module->set(kModuleObject, | |
1883 *isolate->factory()->NewWeakCell(module_obj)); | |
1651 return module_obj; | 1884 return module_obj; |
1652 } | 1885 } |
1653 | 1886 |
1654 MaybeHandle<JSObject> CreateModuleObjectFromBytes(Isolate* isolate, | 1887 MaybeHandle<JSObject> CreateModuleObjectFromBytes(Isolate* isolate, |
1655 const byte* start, | 1888 const byte* start, |
1656 const byte* end, | 1889 const byte* end, |
1657 ErrorThrower* thrower, | 1890 ErrorThrower* thrower, |
1658 ModuleOrigin origin) { | 1891 ModuleOrigin origin) { |
1659 MaybeHandle<JSObject> nothing; | 1892 MaybeHandle<JSObject> nothing; |
1660 Zone zone(isolate->allocator()); | 1893 Zone zone(isolate->allocator()); |
1661 ModuleResult result = | 1894 ModuleResult result = |
1662 DecodeWasmModule(isolate, &zone, start, end, false, origin); | 1895 DecodeWasmModule(isolate, &zone, start, end, false, origin); |
1663 std::unique_ptr<const WasmModule> decoded_module(result.val); | 1896 std::unique_ptr<const WasmModule> decoded_module(result.val); |
1664 if (result.failed()) { | 1897 if (result.failed()) { |
1665 thrower->Failed("Wasm decoding failed", result); | 1898 thrower->Failed("Wasm decoding failed", result); |
1666 return nothing; | 1899 return nothing; |
1667 } | 1900 } |
1668 MaybeHandle<FixedArray> compiled_module = | 1901 MaybeHandle<FixedArray> compiled_module = |
1669 decoded_module->CompileFunctions(isolate, thrower); | 1902 decoded_module->CompileFunctions(isolate, thrower); |
1670 if (compiled_module.is_null()) return nothing; | 1903 if (compiled_module.is_null()) return nothing; |
1671 | 1904 |
1672 return CreateCompiledModuleObject(isolate, compiled_module.ToHandleChecked(), | 1905 return CreateCompiledModuleObject(isolate, compiled_module.ToHandleChecked(), |
1673 origin); | 1906 origin); |
1674 } | 1907 } |
1675 | 1908 |
1909 MaybeHandle<JSArrayBuffer> GetInstanceMemory(Isolate* isolate, | |
1910 Handle<JSObject> instance) { | |
1911 Object* mem = instance->GetInternalField(kWasmMemArrayBuffer); | |
1912 DCHECK(IsWasmObject(*instance)); | |
1913 if (mem->IsUndefined(isolate)) return MaybeHandle<JSArrayBuffer>(); | |
1914 return Handle<JSArrayBuffer>(JSArrayBuffer::cast(mem)); | |
1915 } | |
1916 | |
1917 void SetInstanceMemory(Handle<JSObject> instance, JSArrayBuffer* buffer) { | |
1918 DisallowHeapAllocation no_gc; | |
1919 DCHECK(IsWasmObject(*instance)); | |
1920 instance->SetInternalField(kWasmMemArrayBuffer, buffer); | |
1921 } | |
1922 | |
1676 namespace testing { | 1923 namespace testing { |
1677 | 1924 |
1678 int32_t CompileAndRunWasmModule(Isolate* isolate, const byte* module_start, | 1925 int32_t CompileAndRunWasmModule(Isolate* isolate, const byte* module_start, |
1679 const byte* module_end, bool asm_js) { | 1926 const byte* module_end, bool asm_js) { |
1680 HandleScope scope(isolate); | 1927 HandleScope scope(isolate); |
1681 Zone zone(isolate->allocator()); | 1928 Zone zone(isolate->allocator()); |
1682 ErrorThrower thrower(isolate, "CompileAndRunWasmModule"); | 1929 ErrorThrower thrower(isolate, "CompileAndRunWasmModule"); |
1683 | 1930 |
1684 // Decode the module, but don't verify function bodies, since we'll | 1931 // Decode the module, but don't verify function bodies, since we'll |
1685 // be compiling them anyway. | 1932 // be compiling them anyway. |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1750 if (result->IsSmi()) { | 1997 if (result->IsSmi()) { |
1751 return Smi::cast(*result)->value(); | 1998 return Smi::cast(*result)->value(); |
1752 } | 1999 } |
1753 if (result->IsHeapNumber()) { | 2000 if (result->IsHeapNumber()) { |
1754 return static_cast<int32_t>(HeapNumber::cast(*result)->value()); | 2001 return static_cast<int32_t>(HeapNumber::cast(*result)->value()); |
1755 } | 2002 } |
1756 thrower->Error("WASM.compileRun() failed: Return value should be number"); | 2003 thrower->Error("WASM.compileRun() failed: Return value should be number"); |
1757 return -1; | 2004 return -1; |
1758 } | 2005 } |
1759 | 2006 |
2007 void ValidateInstancesChain(Isolate* isolate, Handle<JSObject> module_obj, | |
2008 int instance_count) { | |
2009 CHECK_GE(instance_count, 0); | |
2010 DisallowHeapAllocation no_gc; | |
2011 FixedArray* compiled_module = | |
2012 FixedArray::cast(module_obj->GetInternalField(0)); | |
2013 CHECK_EQ(JSObject::cast(GetModuleObject(compiled_module)->value()), | |
2014 *module_obj); | |
2015 Object* prev = nullptr; | |
2016 int found_instances = GetOwningInstance(compiled_module) == nullptr ? 0 : 1; | |
2017 FixedArray* current_instance = compiled_module; | |
2018 while (GetNextInstance(current_instance) != nullptr) { | |
2019 CHECK((prev == nullptr && GetPrevInstance(current_instance) == nullptr) || | |
2020 GetPrevInstance(current_instance)->value() == prev); | |
2021 CHECK_EQ(GetModuleObject(current_instance)->value(), *module_obj); | |
2022 CHECK(IsWasmObject(GetOwningInstance(current_instance)->value())); | |
2023 prev = current_instance; | |
2024 current_instance = | |
2025 FixedArray::cast(GetNextInstance(current_instance)->value()); | |
2026 ++found_instances; | |
2027 CHECK_LE(found_instances, instance_count); | |
2028 } | |
2029 CHECK_EQ(found_instances, instance_count); | |
2030 } | |
2031 | |
2032 void ValidateModuleState(Isolate* isolate, Handle<JSObject> module_obj) { | |
2033 DisallowHeapAllocation no_gc; | |
2034 FixedArray* compiled_module = | |
2035 FixedArray::cast(module_obj->GetInternalField(0)); | |
2036 CHECK_NOT_NULL(GetModuleObject(compiled_module)); | |
2037 CHECK_EQ(GetModuleObject(compiled_module)->value(), *module_obj); | |
2038 CHECK_NULL(GetPrevInstance(compiled_module)); | |
2039 CHECK_NULL(GetNextInstance(compiled_module)); | |
2040 CHECK_NULL(GetOwningInstance(compiled_module)); | |
2041 } | |
2042 | |
2043 void ValidateOrphanedInstance(Isolate* isolate, Handle<JSObject> instance) { | |
2044 DisallowHeapAllocation no_gc; | |
2045 CHECK(IsWasmObject(*instance)); | |
2046 FixedArray* compiled_module = | |
2047 FixedArray::cast(instance->GetInternalField(kWasmCompiledModule)); | |
2048 CHECK_NOT_NULL(GetModuleObject(compiled_module)); | |
2049 CHECK(GetModuleObject(compiled_module)->cleared()); | |
2050 } | |
2051 | |
1760 } // namespace testing | 2052 } // namespace testing |
1761 } // namespace wasm | 2053 } // namespace wasm |
1762 } // namespace internal | 2054 } // namespace internal |
1763 } // namespace v8 | 2055 } // namespace v8 |
OLD | NEW |