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

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

Issue 2305903002: [wasm] reuse the first compiled module (Closed)
Patch Set: feedback 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
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <memory> 5 #include <memory>
6 6
7 #include "src/base/atomic-utils.h" 7 #include "src/base/atomic-utils.h"
8 #include "src/code-stubs.h" 8 #include "src/code-stubs.h"
9 9
10 #include "src/macro-assembler.h" 10 #include "src/macro-assembler.h"
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 = 0,
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
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
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 ||
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
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
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
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->IsMutableHeapNumber());
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 // weak_module_obj may have been cleared, meaning the module object
1208 // was GC-ed. In that case, there won't be any new instances created,
1209 // and we don't need to maintain the links between instances.
1210 if (!weak_module_obj->cleared()) {
1211 JSObject* module_obj = JSObject::cast(weak_module_obj->value());
1212 FixedArray* current_template =
1213 FixedArray::cast(module_obj->GetInternalField(0));
1214 DCHECK_NULL(GetPrevInstance(current_template));
1215 WeakCell* next = GetNextInstance(compiled_module);
1216 WeakCell* prev = GetPrevInstance(compiled_module);
1217
1218 if (current_template == compiled_module) {
1219 if (next == nullptr) {
1220 ResetCompiledModule(isolate, owner, compiled_module);
1221 } else {
1222 DCHECK(next->value()->IsFixedArray());
1223 module_obj->SetInternalField(0, next->value());
1224 DCHECK_NULL(prev);
1225 FixedArray::cast(next->value())->set(kPrevInstance, undefined);
1226 }
1227 } else {
1228 DCHECK(!(prev == nullptr && next == nullptr));
1229 // the only reason prev or next would be cleared is if the
1230 // respective objects got collected, but if that happened,
1231 // we would have relinked the list.
1232 if (prev != nullptr) {
1233 DCHECK(!prev->cleared());
1234 FixedArray::cast(prev->value())
1235 ->set(kNextInstance, next == nullptr ? undefined : next);
1236 }
1237 if (next != nullptr) {
1238 DCHECK(!next->cleared());
1239 FixedArray::cast(next->value())
1240 ->set(kPrevInstance, prev == nullptr ? undefined : prev);
1241 }
1242 }
1243 }
1244 GlobalHandles::Destroy(reinterpret_cast<Object**>(p));
1245 }
1246
1084 } // namespace 1247 } // namespace
1085 1248
1086 MaybeHandle<FixedArray> WasmModule::CompileFunctions( 1249 MaybeHandle<FixedArray> WasmModule::CompileFunctions(
1087 Isolate* isolate, ErrorThrower* thrower) const { 1250 Isolate* isolate, ErrorThrower* thrower) const {
1088 Factory* factory = isolate->factory(); 1251 Factory* factory = isolate->factory();
1089 1252
1090 MaybeHandle<FixedArray> nothing; 1253 MaybeHandle<FixedArray> nothing;
1091 1254
1092 WasmModuleInstance temp_instance_for_compilation(this); 1255 WasmModuleInstance temp_instance_for_compilation(this);
1093 temp_instance_for_compilation.context = isolate->native_context(); 1256 temp_instance_for_compilation.context = isolate->native_context();
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
1149 } 1312 }
1150 if (thrower->error()) return nothing; 1313 if (thrower->error()) return nothing;
1151 1314
1152 // At this point, compilation has completed. Update the code table. 1315 // At this point, compilation has completed. Update the code table.
1153 for (size_t i = FLAG_skip_compiling_wasm_funcs; 1316 for (size_t i = FLAG_skip_compiling_wasm_funcs;
1154 i < temp_instance_for_compilation.function_code.size(); ++i) { 1317 i < temp_instance_for_compilation.function_code.size(); ++i) {
1155 Code* code = *temp_instance_for_compilation.function_code[i]; 1318 Code* code = *temp_instance_for_compilation.function_code[i];
1156 compiled_functions->set(static_cast<int>(i), code); 1319 compiled_functions->set(static_cast<int>(i), code);
1157 } 1320 }
1158 1321
1322 LinkModuleFunctions(isolate, compiled_functions);
1323
1324 // TODO(mtrofin): do we need to flush the cache here?
1325 FlushAssemblyCache(isolate, compiled_functions);
1326
1159 // Create the compiled module object, and populate with compiled functions 1327 // Create the compiled module object, and populate with compiled functions
1160 // and information needed at instantiation time. This object needs to be 1328 // and information needed at instantiation time. This object needs to be
1161 // serializable. Instantiation may occur off a deserialized version of this 1329 // serializable. Instantiation may occur off a deserialized version of this
1162 // object. 1330 // object.
1163 Handle<FixedArray> ret = 1331 Handle<FixedArray> ret =
1164 factory->NewFixedArray(kCompiledWasmObjectTableSize, TENURED); 1332 factory->NewFixedArray(kCompiledWasmObjectTableSize, TENURED);
1165 ret->set(kFunctions, *compiled_functions); 1333 ret->set(kFunctions, *compiled_functions);
1166 if (!indirect_table.is_null()) { 1334 if (!indirect_table.is_null()) {
1167 ret->set(kTableOfIndirectFunctionTables, *indirect_table.ToHandleChecked()); 1335 ret->set(kTableOfIndirectFunctionTables, *indirect_table.ToHandleChecked());
1168 } 1336 }
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
1244 } 1412 }
1245 1413
1246 Handle<ByteArray> function_name_table = 1414 Handle<ByteArray> function_name_table =
1247 BuildFunctionNamesTable(isolate, module_env.module); 1415 BuildFunctionNamesTable(isolate, module_env.module);
1248 ret->set(kFunctionNameTable, *function_name_table); 1416 ret->set(kFunctionNameTable, *function_name_table);
1249 ret->set(kMinRequiredMemory, Smi::FromInt(min_mem_pages)); 1417 ret->set(kMinRequiredMemory, Smi::FromInt(min_mem_pages));
1250 if (data_segments.size() > 0) SaveDataSegmentInfo(factory, this, ret); 1418 if (data_segments.size() > 0) SaveDataSegmentInfo(factory, this, ret);
1251 ret->set(kGlobalsSize, Smi::FromInt(globals_size)); 1419 ret->set(kGlobalsSize, Smi::FromInt(globals_size));
1252 ret->set(kExportMem, Smi::FromInt(mem_export)); 1420 ret->set(kExportMem, Smi::FromInt(mem_export));
1253 ret->set(kOrigin, Smi::FromInt(origin)); 1421 ret->set(kOrigin, Smi::FromInt(origin));
1422 Handle<HeapNumber> size_as_object = factory->NewHeapNumber(
1423 static_cast<double>(temp_instance_for_compilation.mem_size), MUTABLE,
1424 TENURED);
1425 ret->set(kMemSize, *size_as_object);
1254 return ret; 1426 return ret;
1255 } 1427 }
1256 1428
1257 void PatchJSWrapper(Isolate* isolate, Handle<Code> wrapper, 1429 void PatchJSWrapper(Isolate* isolate, Handle<Code> wrapper,
1258 Handle<Code> new_target) { 1430 Handle<Code> new_target) {
1259 AllowDeferredHandleDereference embedding_raw_address; 1431 AllowDeferredHandleDereference embedding_raw_address;
1260 bool seen = false; 1432 bool seen = false;
1261 for (RelocIterator it(*wrapper, 1 << RelocInfo::CODE_TARGET); !it.done(); 1433 for (RelocIterator it(*wrapper, 1 << RelocInfo::CODE_TARGET); !it.done();
1262 it.next()) { 1434 it.next()) {
1263 Code* target = Code::GetCodeFromTargetAddress(it.rinfo()->target_address()); 1435 Code* target = Code::GetCodeFromTargetAddress(it.rinfo()->target_address());
1264 if (target->kind() == Code::WASM_FUNCTION) { 1436 if (target->kind() == Code::WASM_FUNCTION) {
1265 DCHECK(!seen); 1437 DCHECK(!seen);
1266 seen = true; 1438 seen = true;
1267 it.rinfo()->set_target_address(new_target->instruction_start(), 1439 it.rinfo()->set_target_address(new_target->instruction_start(),
1268 UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH); 1440 UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
1269 } 1441 }
1270 } 1442 }
1271 CHECK(seen); 1443 CHECK(seen);
1272 Assembler::FlushICache(isolate, wrapper->instruction_start(), 1444 Assembler::FlushICache(isolate, wrapper->instruction_start(),
1273 wrapper->instruction_size()); 1445 wrapper->instruction_size());
1274 } 1446 }
1275 1447
1276 Handle<FixedArray> SetupIndirectFunctionTable( 1448 Handle<FixedArray> SetupIndirectFunctionTable(
1277 Isolate* isolate, Handle<FixedArray> wasm_functions, 1449 Isolate* isolate, Handle<FixedArray> wasm_functions,
1278 Handle<FixedArray> indirect_table_template) { 1450 Handle<FixedArray> indirect_table_template,
1451 Handle<FixedArray> tables_to_replace) {
1279 Factory* factory = isolate->factory(); 1452 Factory* factory = isolate->factory();
1280 Handle<FixedArray> cloned_indirect_tables = 1453 Handle<FixedArray> cloned_indirect_tables =
1281 factory->CopyFixedArray(indirect_table_template); 1454 factory->CopyFixedArray(indirect_table_template);
1282 for (int i = 0; i < cloned_indirect_tables->length(); ++i) { 1455 for (int i = 0; i < cloned_indirect_tables->length(); ++i) {
1283 Handle<FixedArray> orig_metadata = 1456 Handle<FixedArray> orig_metadata =
1284 cloned_indirect_tables->GetValueChecked<FixedArray>(isolate, i); 1457 cloned_indirect_tables->GetValueChecked<FixedArray>(isolate, i);
1285 Handle<FixedArray> cloned_metadata = factory->CopyFixedArray(orig_metadata); 1458 Handle<FixedArray> cloned_metadata = factory->CopyFixedArray(orig_metadata);
1286 cloned_indirect_tables->set(i, *cloned_metadata); 1459 cloned_indirect_tables->set(i, *cloned_metadata);
1287 1460
1288 Handle<FixedArray> orig_table = 1461 Handle<FixedArray> orig_table =
1289 cloned_metadata->GetValueChecked<FixedArray>(isolate, kTable); 1462 cloned_metadata->GetValueChecked<FixedArray>(isolate, kTable);
1290 Handle<FixedArray> cloned_table = factory->CopyFixedArray(orig_table); 1463 Handle<FixedArray> cloned_table = factory->CopyFixedArray(orig_table);
1291 cloned_metadata->set(kTable, *cloned_table); 1464 cloned_metadata->set(kTable, *cloned_table);
1292 // Patch the cloned code to refer to the cloned kTable. 1465 // Patch the cloned code to refer to the cloned kTable.
1293 for (int i = 0; i < wasm_functions->length(); ++i) { 1466 Handle<FixedArray> table_to_replace =
1467 tables_to_replace->GetValueChecked<FixedArray>(isolate, i)
1468 ->GetValueChecked<FixedArray>(isolate, kTable);
1469 for (int fct_index = 0; fct_index < wasm_functions->length(); ++fct_index) {
1294 Handle<Code> wasm_function = 1470 Handle<Code> wasm_function =
1295 wasm_functions->GetValueChecked<Code>(isolate, i); 1471 wasm_functions->GetValueChecked<Code>(isolate, fct_index);
1296 PatchFunctionTable(wasm_function, orig_table, cloned_table); 1472 PatchFunctionTable(wasm_function, table_to_replace, cloned_table);
1297 } 1473 }
1298 } 1474 }
1299 return cloned_indirect_tables; 1475 return cloned_indirect_tables;
1300 } 1476 }
1301 1477
1302 Handle<FixedArray> CloneModuleForInstance(Isolate* isolate, 1478 Handle<FixedArray> CloneModuleForInstance(Isolate* isolate,
1303 Handle<FixedArray> original) { 1479 Handle<FixedArray> original) {
1304 Factory* factory = isolate->factory(); 1480 Factory* factory = isolate->factory();
1481 bool is_first =
1482 original->GetValue<WeakCell>(isolate, kOwningInstance).is_null();
1483
1484 if (is_first) {
1485 return original;
1486 }
1487
1488 // We insert the latest clone in front.
1305 Handle<FixedArray> clone = factory->CopyFixedArray(original); 1489 Handle<FixedArray> clone = factory->CopyFixedArray(original);
1490 Handle<WeakCell> weak_link_to_wasm_obj =
1491 original->GetValueChecked<WeakCell>(isolate, kModuleObject);
1492
1493 clone->set(kModuleObject, *weak_link_to_wasm_obj);
1494 Handle<WeakCell> link_to_original = factory->NewWeakCell(original);
1495 clone->set(kNextInstance, *link_to_original);
1496 Handle<WeakCell> link_to_clone = factory->NewWeakCell(clone);
1497 original->set(kPrevInstance, *link_to_clone);
1498 JSObject::cast(weak_link_to_wasm_obj->value())->SetInternalField(0, *clone);
1306 1499
1307 // Clone each wasm code object. 1500 // Clone each wasm code object.
1308 Handle<FixedArray> orig_wasm_functions = 1501 Handle<FixedArray> orig_wasm_functions =
1309 original->GetValueChecked<FixedArray>(isolate, kFunctions); 1502 original->GetValueChecked<FixedArray>(isolate, kFunctions);
1310 Handle<FixedArray> clone_wasm_functions = 1503 Handle<FixedArray> clone_wasm_functions =
1311 factory->CopyFixedArray(orig_wasm_functions); 1504 factory->CopyFixedArray(orig_wasm_functions);
1312 clone->set(kFunctions, *clone_wasm_functions); 1505 clone->set(kFunctions, *clone_wasm_functions);
1313 for (int i = 0; i < clone_wasm_functions->length(); ++i) { 1506 for (int i = 0; i < clone_wasm_functions->length(); ++i) {
1314 Handle<Code> orig_code = 1507 Handle<Code> orig_code =
1315 clone_wasm_functions->GetValueChecked<Code>(isolate, i); 1508 clone_wasm_functions->GetValueChecked<Code>(isolate, i);
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1356 clone->set(kStartupFunction, *startup_metadata); 1549 clone->set(kStartupFunction, *startup_metadata);
1357 // TODO(wasm): see todo above about int vs size_t indexing in FixedArray. 1550 // TODO(wasm): see todo above about int vs size_t indexing in FixedArray.
1358 int startup_fct_index = 1551 int startup_fct_index =
1359 Smi::cast(startup_metadata->get(kExportedFunctionIndex))->value(); 1552 Smi::cast(startup_metadata->get(kExportedFunctionIndex))->value();
1360 CHECK_GE(startup_fct_index, 0); 1553 CHECK_GE(startup_fct_index, 0);
1361 CHECK_LT(startup_fct_index, clone_wasm_functions->length()); 1554 CHECK_LT(startup_fct_index, clone_wasm_functions->length());
1362 Handle<Code> new_target = 1555 Handle<Code> new_target =
1363 clone_wasm_functions->GetValueChecked<Code>(isolate, startup_fct_index); 1556 clone_wasm_functions->GetValueChecked<Code>(isolate, startup_fct_index);
1364 PatchJSWrapper(isolate, startup_fct_clone, new_target); 1557 PatchJSWrapper(isolate, startup_fct_clone, new_target);
1365 } 1558 }
1559 clone->set(kImportMap, *isolate->factory()->undefined_value());
1366 return clone; 1560 return clone;
1367 } 1561 }
1368 1562
1369 // Instantiates a wasm module as a JSObject. 1563 // Instantiates a wasm module as a JSObject.
1370 // * allocates a backing store of {mem_size} bytes. 1564 // * allocates a backing store of {mem_size} bytes.
1371 // * installs a named property "memory" for that buffer if exported 1565 // * installs a named property "memory" for that buffer if exported
1372 // * installs named properties on the object for exported functions 1566 // * installs named properties on the object for exported functions
1373 // * compiles wasm code to machine code 1567 // * compiles wasm code to machine code
1374 MaybeHandle<JSObject> WasmModule::Instantiate( 1568 MaybeHandle<JSObject> WasmModule::Instantiate(
1375 Isolate* isolate, Handle<FixedArray> compiled_module, 1569 Isolate* isolate, Handle<FixedArray> compiled_module_template,
1376 Handle<JSReceiver> ffi, Handle<JSArrayBuffer> memory) { 1570 Handle<JSReceiver> ffi, Handle<JSArrayBuffer> memory) {
1377 HistogramTimerScope wasm_instantiate_module_time_scope( 1571 HistogramTimerScope wasm_instantiate_module_time_scope(
1378 isolate->counters()->wasm_instantiate_module_time()); 1572 isolate->counters()->wasm_instantiate_module_time());
1379 ErrorThrower thrower(isolate, "WasmModule::Instantiate()"); 1573 ErrorThrower thrower(isolate, "WasmModule::Instantiate()");
1380 Factory* factory = isolate->factory(); 1574 Factory* factory = isolate->factory();
1381 1575
1382 compiled_module = CloneModuleForInstance(isolate, compiled_module); 1576 Handle<FixedArray> compiled_module =
1577 CloneModuleForInstance(isolate, compiled_module_template);
1383 1578
1579 bool template_is_owned =
1580 GetOwningInstance(*compiled_module_template) != nullptr;
1581
1582 MaybeHandle<JSObject> template_owner;
1583 if (template_is_owned) {
1584 Handle<WeakCell> weak_owner =
1585 compiled_module_template->GetValueChecked<WeakCell>(isolate,
1586 kOwningInstance);
1587 template_owner = handle(JSObject::cast(weak_owner->value()));
1588 }
1384 // These fields are compulsory. 1589 // These fields are compulsory.
1385 Handle<FixedArray> code_table = 1590 Handle<FixedArray> code_table =
1386 compiled_module->GetValueChecked<FixedArray>(isolate, kFunctions); 1591 compiled_module->GetValueChecked<FixedArray>(isolate, kFunctions);
1387 1592
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); 1593 RecordStats(isolate, code_table);
1397 1594
1398 MaybeHandle<JSObject> nothing; 1595 MaybeHandle<JSObject> nothing;
1399 1596
1400 Handle<Map> map = factory->NewMap( 1597 Handle<Map> map = factory->NewMap(
1401 JS_OBJECT_TYPE, 1598 JS_OBJECT_TYPE,
1402 JSObject::kHeaderSize + kWasmModuleInternalFieldCount * kPointerSize); 1599 JSObject::kHeaderSize + kWasmModuleInternalFieldCount * kPointerSize);
1403 Handle<JSObject> js_object = factory->NewJSObjectFromMap(map, TENURED); 1600 Handle<JSObject> js_object = factory->NewJSObjectFromMap(map, TENURED);
1404 js_object->SetInternalField(kWasmModuleCodeTable, *code_table); 1601 js_object->SetInternalField(kWasmModuleCodeTable, *code_table);
1405 1602
1603 // Remember the old imports, for the case when we are at the first instance -
1604 // they will be replaced with the instance's actual imports in SetupImports.
1605 MaybeHandle<FixedArray> old_imports =
1606 compiled_module_template->GetValue<FixedArray>(isolate, kImportMap);
1406 if (!(SetupInstanceHeap(isolate, compiled_module, js_object, memory, 1607 if (!(SetupInstanceHeap(isolate, compiled_module, js_object, memory,
1407 &thrower) && 1608 &thrower) &&
1408 SetupGlobals(isolate, compiled_module, js_object, &thrower) && 1609 SetupGlobals(isolate, template_owner, compiled_module, js_object,
1610 &thrower) &&
1409 SetupImports(isolate, compiled_module, js_object, &thrower, ffi) && 1611 SetupImports(isolate, compiled_module, js_object, &thrower, ffi) &&
1410 SetupExportsObject(compiled_module, isolate, js_object, &thrower))) { 1612 SetupExportsObject(compiled_module, isolate, js_object, &thrower))) {
1411 return nothing; 1613 return nothing;
1412 } 1614 }
1413 1615
1616 FixupFunctionsAndImports(
1617 compiled_module_template->GetValueChecked<FixedArray>(isolate,
1618 kFunctions),
1619 code_table, old_imports,
1620 compiled_module->GetValue<FixedArray>(isolate, kImportMap));
1621
1414 SetDebugSupport(factory, compiled_module, js_object); 1622 SetDebugSupport(factory, compiled_module, js_object);
1415 SetRuntimeSupport(isolate, js_object); 1623 SetRuntimeSupport(isolate, js_object);
1416 1624
1417 FlushAssemblyCache(isolate, code_table); 1625 FlushAssemblyCache(isolate, code_table);
1418 1626
1419 MaybeHandle<FixedArray> maybe_indirect_tables = 1627 {
1420 compiled_module->GetValue<FixedArray>(isolate, 1628 std::vector<Handle<Code>> functions(
1421 kTableOfIndirectFunctionTables); 1629 static_cast<size_t>(code_table->length()));
1422 Handle<FixedArray> indirect_tables_template; 1630 for (int i = 0; i < code_table->length(); ++i) {
1423 if (maybe_indirect_tables.ToHandle(&indirect_tables_template)) { 1631 functions[static_cast<size_t>(i)] =
1424 Handle<FixedArray> indirect_tables = SetupIndirectFunctionTable( 1632 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 } 1633 }
1434 js_object->SetInternalField(kWasmModuleFunctionTable, *indirect_tables); 1634
1635 MaybeHandle<FixedArray> maybe_indirect_tables =
1636 compiled_module->GetValue<FixedArray>(isolate,
1637 kTableOfIndirectFunctionTables);
1638 Handle<FixedArray> indirect_tables_template;
1639 if (maybe_indirect_tables.ToHandle(&indirect_tables_template)) {
1640 Handle<FixedArray> to_replace =
1641 template_owner.is_null()
1642 ? indirect_tables_template
1643 : handle(FixedArray::cast(
1644 template_owner.ToHandleChecked()->GetInternalField(
1645 kWasmModuleFunctionTable)));
1646 Handle<FixedArray> indirect_tables = SetupIndirectFunctionTable(
1647 isolate, code_table, indirect_tables_template, to_replace);
1648 for (int i = 0; i < indirect_tables->length(); ++i) {
1649 Handle<FixedArray> metadata =
1650 indirect_tables->GetValueChecked<FixedArray>(isolate, i);
1651 uint32_t size = Smi::cast(metadata->get(kSize))->value();
1652 Handle<FixedArray> table =
1653 metadata->GetValueChecked<FixedArray>(isolate, kTable);
1654 wasm::PopulateFunctionTable(table, size, &functions);
1655 }
1656 js_object->SetInternalField(kWasmModuleFunctionTable, *indirect_tables);
1657 }
1435 } 1658 }
1436 1659
1437 // Run the start function if one was specified. 1660 // Run the start function if one was specified.
1438 MaybeHandle<FixedArray> maybe_startup_fct = 1661 MaybeHandle<FixedArray> maybe_startup_fct =
1439 compiled_module->GetValue<FixedArray>(isolate, kStartupFunction); 1662 compiled_module->GetValue<FixedArray>(isolate, kStartupFunction);
1440 Handle<FixedArray> metadata; 1663 Handle<FixedArray> metadata;
1441 if (maybe_startup_fct.ToHandle(&metadata)) { 1664 if (maybe_startup_fct.ToHandle(&metadata)) {
1442 HandleScope scope(isolate); 1665 HandleScope scope(isolate);
1443 Handle<Code> startup_code = 1666 Handle<Code> startup_code =
1444 metadata->GetValueChecked<Code>(isolate, kExportCode); 1667 metadata->GetValueChecked<Code>(isolate, kExportCode);
1445 int arity = Smi::cast(metadata->get(kExportArity))->value(); 1668 int arity = Smi::cast(metadata->get(kExportArity))->value();
1446 MaybeHandle<ByteArray> startup_signature = 1669 MaybeHandle<ByteArray> startup_signature =
1447 metadata->GetValue<ByteArray>(isolate, kExportedSignature); 1670 metadata->GetValue<ByteArray>(isolate, kExportedSignature);
1448 Handle<JSFunction> startup_fct = WrapExportCodeAsJSFunction( 1671 Handle<JSFunction> startup_fct = WrapExportCodeAsJSFunction(
1449 isolate, startup_code, factory->InternalizeUtf8String("start"), arity, 1672 isolate, startup_code, factory->InternalizeUtf8String("start"), arity,
1450 startup_signature, js_object); 1673 startup_signature, js_object);
1451 RecordStats(isolate, *startup_code); 1674 RecordStats(isolate, *startup_code);
1452 // Call the JS function. 1675 // Call the JS function.
1453 Handle<Object> undefined = isolate->factory()->undefined_value(); 1676 Handle<Object> undefined = isolate->factory()->undefined_value();
1454 MaybeHandle<Object> retval = 1677 MaybeHandle<Object> retval =
1455 Execution::Call(isolate, startup_fct, undefined, 0, nullptr); 1678 Execution::Call(isolate, startup_fct, undefined, 0, nullptr);
1456 1679
1457 if (retval.is_null()) { 1680 if (retval.is_null()) {
1458 thrower.Error("WASM.instantiateModule(): start function failed"); 1681 thrower.Error("WASM.instantiateModule(): start function failed");
1459 return nothing; 1682 return nothing;
1460 } 1683 }
1461 } 1684 }
1462 1685
1463 DCHECK(wasm::IsWasmObject(*js_object)); 1686 DCHECK(wasm::IsWasmObject(*js_object));
1687
1688 if (!compiled_module->GetValue<WeakCell>(isolate, kModuleObject).is_null()) {
1689 js_object->SetInternalField(kWasmCompiledModule, *compiled_module);
1690 Handle<WeakCell> link_to_owner = factory->NewWeakCell(js_object);
1691 compiled_module->set(kOwningInstance, *link_to_owner);
1692
1693 Handle<Object> global_handle =
1694 isolate->global_handles()->Create(*js_object);
1695 GlobalHandles::MakeWeak(global_handle.location(), global_handle.location(),
1696 &InstanceFinalizer,
1697 v8::WeakCallbackType::kFinalizer);
1698 }
1699
1464 return js_object; 1700 return js_object;
1465 } 1701 }
1466 1702
1467 // TODO(mtrofin): remove this once we move to WASM_DIRECT_CALL 1703 // TODO(mtrofin): remove this once we move to WASM_DIRECT_CALL
1468 Handle<Code> ModuleEnv::GetCodeOrPlaceholder(uint32_t index) const { 1704 Handle<Code> ModuleEnv::GetCodeOrPlaceholder(uint32_t index) const {
1469 DCHECK(IsValidFunction(index)); 1705 DCHECK(IsValidFunction(index));
1470 if (!placeholders.empty()) return placeholders[index]; 1706 if (!placeholders.empty()) return placeholders[index];
1471 DCHECK_NOT_NULL(instance); 1707 DCHECK_NOT_NULL(instance);
1472 return instance->function_code[index]; 1708 return instance->function_code[index];
1473 } 1709 }
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
1641 DCHECK(origin == ModuleOrigin::kAsmJsOrigin); 1877 DCHECK(origin == ModuleOrigin::kAsmJsOrigin);
1642 Handle<Map> map = isolate->factory()->NewMap( 1878 Handle<Map> map = isolate->factory()->NewMap(
1643 JS_OBJECT_TYPE, JSObject::kHeaderSize + kPointerSize); 1879 JS_OBJECT_TYPE, JSObject::kHeaderSize + kPointerSize);
1644 module_obj = isolate->factory()->NewJSObjectFromMap(map, TENURED); 1880 module_obj = isolate->factory()->NewJSObjectFromMap(map, TENURED);
1645 } 1881 }
1646 module_obj->SetInternalField(0, *compiled_module); 1882 module_obj->SetInternalField(0, *compiled_module);
1647 if (origin == ModuleOrigin::kWasmOrigin) { 1883 if (origin == ModuleOrigin::kWasmOrigin) {
1648 Handle<Symbol> module_sym(isolate->native_context()->wasm_module_sym()); 1884 Handle<Symbol> module_sym(isolate->native_context()->wasm_module_sym());
1649 Object::SetProperty(module_obj, module_sym, module_obj, STRICT).Check(); 1885 Object::SetProperty(module_obj, module_sym, module_obj, STRICT).Check();
1650 } 1886 }
1887 Handle<WeakCell> link_to_module = isolate->factory()->NewWeakCell(module_obj);
1888 compiled_module->set(kModuleObject, *link_to_module);
1651 return module_obj; 1889 return module_obj;
1652 } 1890 }
1653 1891
1654 MaybeHandle<JSObject> CreateModuleObjectFromBytes(Isolate* isolate, 1892 MaybeHandle<JSObject> CreateModuleObjectFromBytes(Isolate* isolate,
1655 const byte* start, 1893 const byte* start,
1656 const byte* end, 1894 const byte* end,
1657 ErrorThrower* thrower, 1895 ErrorThrower* thrower,
1658 ModuleOrigin origin) { 1896 ModuleOrigin origin) {
1659 MaybeHandle<JSObject> nothing; 1897 MaybeHandle<JSObject> nothing;
1660 Zone zone(isolate->allocator()); 1898 Zone zone(isolate->allocator());
1661 ModuleResult result = 1899 ModuleResult result =
1662 DecodeWasmModule(isolate, &zone, start, end, false, origin); 1900 DecodeWasmModule(isolate, &zone, start, end, false, origin);
1663 std::unique_ptr<const WasmModule> decoded_module(result.val); 1901 std::unique_ptr<const WasmModule> decoded_module(result.val);
1664 if (result.failed()) { 1902 if (result.failed()) {
1665 thrower->Failed("Wasm decoding failed", result); 1903 thrower->Failed("Wasm decoding failed", result);
1666 return nothing; 1904 return nothing;
1667 } 1905 }
1668 MaybeHandle<FixedArray> compiled_module = 1906 MaybeHandle<FixedArray> compiled_module =
1669 decoded_module->CompileFunctions(isolate, thrower); 1907 decoded_module->CompileFunctions(isolate, thrower);
1670 if (compiled_module.is_null()) return nothing; 1908 if (compiled_module.is_null()) return nothing;
1671 1909
1672 return CreateCompiledModuleObject(isolate, compiled_module.ToHandleChecked(), 1910 return CreateCompiledModuleObject(isolate, compiled_module.ToHandleChecked(),
1673 origin); 1911 origin);
1674 } 1912 }
1675 1913
1914 MaybeHandle<JSArrayBuffer> GetInstanceMemory(Isolate* isolate,
1915 Handle<JSObject> instance) {
1916 Object* mem = instance->GetInternalField(kWasmMemArrayBuffer);
1917 DCHECK(IsWasmObject(*instance));
1918 if (mem->IsUndefined(isolate)) return MaybeHandle<JSArrayBuffer>();
1919 return Handle<JSArrayBuffer>(JSArrayBuffer::cast(mem));
1920 }
1921
1922 void SetInstanceMemory(Handle<JSObject> instance, JSArrayBuffer* buffer) {
1923 DisallowHeapAllocation no_gc;
1924 DCHECK(IsWasmObject(*instance));
1925 instance->SetInternalField(kWasmMemArrayBuffer, buffer);
1926 Object* module = instance->GetInternalField(kWasmCompiledModule);
1927 if (module->IsFixedArray()) {
1928 HeapNumber::cast(FixedArray::cast(module)->get(kMemSize))
1929 ->set_value(buffer->byte_length()->Number());
1930 }
1931 }
1932
1676 namespace testing { 1933 namespace testing {
1677 1934
1678 int32_t CompileAndRunWasmModule(Isolate* isolate, const byte* module_start, 1935 int32_t CompileAndRunWasmModule(Isolate* isolate, const byte* module_start,
1679 const byte* module_end, bool asm_js) { 1936 const byte* module_end, bool asm_js) {
1680 HandleScope scope(isolate); 1937 HandleScope scope(isolate);
1681 Zone zone(isolate->allocator()); 1938 Zone zone(isolate->allocator());
1682 ErrorThrower thrower(isolate, "CompileAndRunWasmModule"); 1939 ErrorThrower thrower(isolate, "CompileAndRunWasmModule");
1683 1940
1684 // Decode the module, but don't verify function bodies, since we'll 1941 // Decode the module, but don't verify function bodies, since we'll
1685 // be compiling them anyway. 1942 // be compiling them anyway.
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
1750 if (result->IsSmi()) { 2007 if (result->IsSmi()) {
1751 return Smi::cast(*result)->value(); 2008 return Smi::cast(*result)->value();
1752 } 2009 }
1753 if (result->IsHeapNumber()) { 2010 if (result->IsHeapNumber()) {
1754 return static_cast<int32_t>(HeapNumber::cast(*result)->value()); 2011 return static_cast<int32_t>(HeapNumber::cast(*result)->value());
1755 } 2012 }
1756 thrower->Error("WASM.compileRun() failed: Return value should be number"); 2013 thrower->Error("WASM.compileRun() failed: Return value should be number");
1757 return -1; 2014 return -1;
1758 } 2015 }
1759 2016
2017 void ValidateInstancesChain(Isolate* isolate, Handle<JSObject> module_obj,
2018 int instance_count) {
2019 CHECK_GE(instance_count, 0);
2020 DisallowHeapAllocation no_gc;
2021 FixedArray* compiled_module =
2022 FixedArray::cast(module_obj->GetInternalField(0));
2023 CHECK_EQ(JSObject::cast(GetModuleObject(compiled_module)->value()),
2024 *module_obj);
2025 Object* prev = nullptr;
2026 int found_instances = GetOwningInstance(compiled_module) == nullptr ? 0 : 1;
2027 FixedArray* current_instance = compiled_module;
2028 while (GetNextInstance(current_instance) != nullptr) {
2029 CHECK((prev == nullptr && GetPrevInstance(current_instance) == nullptr) ||
2030 GetPrevInstance(current_instance)->value() == prev);
2031 CHECK_EQ(GetModuleObject(current_instance)->value(), *module_obj);
2032 CHECK(IsWasmObject(GetOwningInstance(current_instance)->value()));
2033 prev = current_instance;
2034 current_instance =
2035 FixedArray::cast(GetNextInstance(current_instance)->value());
2036 ++found_instances;
2037 CHECK_LE(found_instances, instance_count);
2038 }
2039 CHECK_EQ(found_instances, instance_count);
2040 }
2041
2042 void ValidateModuleState(Isolate* isolate, Handle<JSObject> module_obj) {
2043 DisallowHeapAllocation no_gc;
2044 FixedArray* compiled_module =
2045 FixedArray::cast(module_obj->GetInternalField(0));
2046 CHECK_NOT_NULL(GetModuleObject(compiled_module));
2047 CHECK_EQ(GetModuleObject(compiled_module)->value(), *module_obj);
2048 CHECK_NULL(GetPrevInstance(compiled_module));
2049 CHECK_NULL(GetNextInstance(compiled_module));
2050 CHECK_NULL(GetOwningInstance(compiled_module));
2051 }
2052
2053 void ValidateOrphanedInstance(Isolate* isolate, Handle<JSObject> instance) {
2054 DisallowHeapAllocation no_gc;
2055 CHECK(IsWasmObject(*instance));
2056 FixedArray* compiled_module =
2057 FixedArray::cast(instance->GetInternalField(kWasmCompiledModule));
2058 CHECK_NOT_NULL(GetModuleObject(compiled_module));
2059 CHECK(GetModuleObject(compiled_module)->cleared());
2060 }
2061
1760 } // namespace testing 2062 } // namespace testing
1761 } // namespace wasm 2063 } // namespace wasm
1762 } // namespace internal 2064 } // namespace internal
1763 } // namespace v8 2065 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698