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 "src/wasm/wasm-objects.h" | 5 #include "src/wasm/wasm-objects.h" |
6 #include "src/utils.h" | 6 #include "src/utils.h" |
7 | 7 |
8 #include "src/assembler-inl.h" | 8 #include "src/assembler-inl.h" |
9 #include "src/base/iterator.h" | 9 #include "src/base/iterator.h" |
10 #include "src/compiler/wasm-compiler.h" | 10 #include "src/compiler/wasm-compiler.h" |
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
316 isolate->native_context()->wasm_memory_constructor()); | 316 isolate->native_context()->wasm_memory_constructor()); |
317 auto memory_obj = Handle<WasmMemoryObject>::cast( | 317 auto memory_obj = Handle<WasmMemoryObject>::cast( |
318 isolate->factory()->NewJSObject(memory_ctor, TENURED)); | 318 isolate->factory()->NewJSObject(memory_ctor, TENURED)); |
319 if (buffer.is_null()) { | 319 if (buffer.is_null()) { |
320 const bool enable_guard_regions = EnableGuardRegions(); | 320 const bool enable_guard_regions = EnableGuardRegions(); |
321 buffer = SetupArrayBuffer(isolate, nullptr, 0, nullptr, 0, false, | 321 buffer = SetupArrayBuffer(isolate, nullptr, 0, nullptr, 0, false, |
322 enable_guard_regions); | 322 enable_guard_regions); |
323 } | 323 } |
324 memory_obj->set_array_buffer(*buffer); | 324 memory_obj->set_array_buffer(*buffer); |
325 memory_obj->set_maximum_pages(maximum); | 325 memory_obj->set_maximum_pages(maximum); |
326 return Handle<WasmMemoryObject>::cast(memory_obj); | 326 return memory_obj; |
327 } | 327 } |
328 | 328 |
329 uint32_t WasmMemoryObject::current_pages() { | 329 uint32_t WasmMemoryObject::current_pages() { |
330 uint32_t byte_length; | 330 uint32_t byte_length; |
331 CHECK(array_buffer()->byte_length()->ToUint32(&byte_length)); | 331 CHECK(array_buffer()->byte_length()->ToUint32(&byte_length)); |
332 return byte_length / wasm::WasmModule::kPageSize; | 332 return byte_length / wasm::WasmModule::kPageSize; |
333 } | 333 } |
334 | 334 |
335 void WasmMemoryObject::AddInstance(Isolate* isolate, | 335 void WasmMemoryObject::AddInstance(Isolate* isolate, |
| 336 Handle<WasmMemoryObject> memory, |
336 Handle<WasmInstanceObject> instance) { | 337 Handle<WasmInstanceObject> instance) { |
337 Handle<WasmInstanceWrapper> instance_wrapper = | 338 Handle<WeakFixedArray> old_instances = |
338 handle(instance->instance_wrapper()); | 339 memory->has_instances() |
339 if (has_instances_link()) { | 340 ? Handle<WeakFixedArray>(memory->instances(), isolate) |
340 Handle<WasmInstanceWrapper> current_wrapper(instances_link()); | 341 : Handle<WeakFixedArray>::null(); |
341 DCHECK(WasmInstanceWrapper::IsWasmInstanceWrapper(*current_wrapper)); | 342 Handle<WeakFixedArray> new_instances = |
342 DCHECK(!current_wrapper->has_previous()); | 343 WeakFixedArray::Add(old_instances, instance); |
343 instance_wrapper->set_next_wrapper(*current_wrapper); | 344 memory->set_instances(*new_instances); |
344 current_wrapper->set_previous_wrapper(*instance_wrapper); | 345 } |
| 346 |
| 347 void WasmMemoryObject::RemoveInstance(Isolate* isolate, |
| 348 Handle<WasmMemoryObject> memory, |
| 349 Handle<WasmInstanceObject> instance) { |
| 350 if (memory->has_instances()) { |
| 351 memory->instances()->Remove(instance); |
345 } | 352 } |
346 set_instances_link(*instance_wrapper); | |
347 } | 353 } |
348 | 354 |
349 // static | 355 // static |
350 int32_t WasmMemoryObject::Grow(Isolate* isolate, | 356 int32_t WasmMemoryObject::Grow(Isolate* isolate, |
351 Handle<WasmMemoryObject> memory_object, | 357 Handle<WasmMemoryObject> memory_object, |
352 uint32_t pages) { | 358 uint32_t pages) { |
353 Handle<JSArrayBuffer> old_buffer(memory_object->array_buffer()); | 359 Handle<JSArrayBuffer> old_buffer(memory_object->array_buffer()); |
354 uint32_t old_size = 0; | 360 uint32_t old_size = 0; |
355 CHECK(old_buffer->byte_length()->ToUint32(&old_size)); | 361 CHECK(old_buffer->byte_length()->ToUint32(&old_size)); |
356 Handle<JSArrayBuffer> new_buffer; | 362 Handle<JSArrayBuffer> new_buffer; |
357 // Return current size if grow by 0. | 363 // Return current size if grow by 0. |
358 if (pages == 0) { | 364 if (pages == 0) { |
359 // Even for pages == 0, we need to attach a new JSArrayBuffer with the same | 365 // Even for pages == 0, we need to attach a new JSArrayBuffer with the same |
360 // backing store and neuter the old one to be spec compliant. | 366 // backing store and neuter the old one to be spec compliant. |
361 if (old_size != 0) { | 367 if (old_size != 0) { |
362 new_buffer = SetupArrayBuffer( | 368 new_buffer = SetupArrayBuffer( |
363 isolate, old_buffer->allocation_base(), | 369 isolate, old_buffer->allocation_base(), |
364 old_buffer->allocation_length(), old_buffer->backing_store(), | 370 old_buffer->allocation_length(), old_buffer->backing_store(), |
365 old_size, old_buffer->is_external(), old_buffer->has_guard_region()); | 371 old_size, old_buffer->is_external(), old_buffer->has_guard_region()); |
366 memory_object->set_array_buffer(*new_buffer); | 372 memory_object->set_array_buffer(*new_buffer); |
367 } | 373 } |
368 DCHECK_EQ(0, old_size % WasmModule::kPageSize); | 374 DCHECK_EQ(0, old_size % WasmModule::kPageSize); |
369 return old_size / WasmModule::kPageSize; | 375 return old_size / WasmModule::kPageSize; |
370 } | 376 } |
371 if (!memory_object->has_instances_link()) { | 377 |
372 // Memory object does not have an instance associated with it, just grow | 378 uint32_t max_pages; |
373 uint32_t max_pages; | 379 if (memory_object->has_maximum_pages()) { |
374 if (memory_object->has_maximum_pages()) { | 380 max_pages = static_cast<uint32_t>(memory_object->maximum_pages()); |
375 max_pages = static_cast<uint32_t>(memory_object->maximum_pages()); | 381 if (FLAG_wasm_max_mem_pages < max_pages) return -1; |
376 if (FLAG_wasm_max_mem_pages < max_pages) return -1; | |
377 } else { | |
378 max_pages = FLAG_wasm_max_mem_pages; | |
379 } | |
380 new_buffer = GrowMemoryBuffer(isolate, old_buffer, pages, max_pages); | |
381 if (new_buffer.is_null()) return -1; | |
382 } else { | 382 } else { |
383 Handle<WasmInstanceWrapper> instance_wrapper( | 383 max_pages = FLAG_wasm_max_mem_pages; |
384 memory_object->instances_link()); | 384 } |
385 DCHECK(WasmInstanceWrapper::IsWasmInstanceWrapper(*instance_wrapper)); | 385 new_buffer = GrowMemoryBuffer(isolate, old_buffer, pages, max_pages); |
386 DCHECK(instance_wrapper->has_instance()); | 386 if (new_buffer.is_null()) return -1; |
387 Handle<WasmInstanceObject> instance = instance_wrapper->instance_object(); | |
388 DCHECK(instance->IsWasmInstanceObject()); | |
389 uint32_t max_pages = instance->GetMaxMemoryPages(); | |
390 | 387 |
391 // Grow memory object buffer and update instances associated with it. | 388 if (memory_object->has_instances()) { |
392 new_buffer = GrowMemoryBuffer(isolate, old_buffer, pages, max_pages); | |
393 if (new_buffer.is_null()) return -1; | |
394 DCHECK(!instance_wrapper->has_previous()); | |
395 SetInstanceMemory(isolate, instance, new_buffer); | |
396 Address old_mem_start = static_cast<Address>(old_buffer->backing_store()); | 389 Address old_mem_start = static_cast<Address>(old_buffer->backing_store()); |
397 UncheckedUpdateInstanceMemory(isolate, instance, old_mem_start, old_size); | 390 Handle<WeakFixedArray> instances(memory_object->instances(), isolate); |
398 while (instance_wrapper->has_next()) { | 391 for (int i = 0; i < instances->Length(); i++) { |
399 instance_wrapper = instance_wrapper->next_wrapper(); | 392 Object* elem = instances->Get(i); |
400 DCHECK(WasmInstanceWrapper::IsWasmInstanceWrapper(*instance_wrapper)); | 393 if (!elem->IsWasmInstanceObject()) continue; |
401 Handle<WasmInstanceObject> instance = instance_wrapper->instance_object(); | 394 Handle<WasmInstanceObject> instance(WasmInstanceObject::cast(elem), |
402 DCHECK(instance->IsWasmInstanceObject()); | 395 isolate); |
403 SetInstanceMemory(isolate, instance, new_buffer); | 396 SetInstanceMemory(isolate, instance, new_buffer); |
404 UncheckedUpdateInstanceMemory(isolate, instance, old_mem_start, old_size); | 397 UncheckedUpdateInstanceMemory(isolate, instance, old_mem_start, old_size); |
405 } | 398 } |
406 } | 399 } |
| 400 |
407 memory_object->set_array_buffer(*new_buffer); | 401 memory_object->set_array_buffer(*new_buffer); |
408 DCHECK_EQ(0, old_size % WasmModule::kPageSize); | 402 DCHECK_EQ(0, old_size % WasmModule::kPageSize); |
409 return old_size / WasmModule::kPageSize; | 403 return old_size / WasmModule::kPageSize; |
410 } | 404 } |
411 | 405 |
412 WasmModuleObject* WasmInstanceObject::module_object() { | 406 WasmModuleObject* WasmInstanceObject::module_object() { |
413 return *compiled_module()->wasm_module(); | 407 return *compiled_module()->wasm_module(); |
414 } | 408 } |
415 | 409 |
416 WasmModule* WasmInstanceObject::module() { return compiled_module()->module(); } | 410 WasmModule* WasmInstanceObject::module() { return compiled_module()->module(); } |
(...skipping 10 matching lines...) Expand all Loading... |
427 Isolate* isolate, Handle<WasmCompiledModule> compiled_module) { | 421 Isolate* isolate, Handle<WasmCompiledModule> compiled_module) { |
428 Handle<JSFunction> instance_cons( | 422 Handle<JSFunction> instance_cons( |
429 isolate->native_context()->wasm_instance_constructor()); | 423 isolate->native_context()->wasm_instance_constructor()); |
430 Handle<JSObject> instance_object = | 424 Handle<JSObject> instance_object = |
431 isolate->factory()->NewJSObject(instance_cons, TENURED); | 425 isolate->factory()->NewJSObject(instance_cons, TENURED); |
432 | 426 |
433 Handle<WasmInstanceObject> instance( | 427 Handle<WasmInstanceObject> instance( |
434 reinterpret_cast<WasmInstanceObject*>(*instance_object), isolate); | 428 reinterpret_cast<WasmInstanceObject*>(*instance_object), isolate); |
435 | 429 |
436 instance->set_compiled_module(*compiled_module); | 430 instance->set_compiled_module(*compiled_module); |
437 Handle<WasmInstanceWrapper> instance_wrapper = | |
438 WasmInstanceWrapper::New(isolate, instance); | |
439 instance->set_instance_wrapper(*instance_wrapper); | |
440 return instance; | 431 return instance; |
441 } | 432 } |
442 | 433 |
443 int32_t WasmInstanceObject::GetMemorySize() { | 434 int32_t WasmInstanceObject::GetMemorySize() { |
444 if (!has_memory_buffer()) return 0; | 435 if (!has_memory_buffer()) return 0; |
445 uint32_t bytes = memory_buffer()->byte_length()->Number(); | 436 uint32_t bytes = memory_buffer()->byte_length()->Number(); |
446 DCHECK_EQ(0, bytes % WasmModule::kPageSize); | 437 DCHECK_EQ(0, bytes % WasmModule::kPageSize); |
447 return bytes / WasmModule::kPageSize; | 438 return bytes / WasmModule::kPageSize; |
448 } | 439 } |
449 | 440 |
(...skipping 935 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1385 Isolate* isolate, Handle<WasmInstanceObject> instance, Handle<Code> caller, | 1376 Isolate* isolate, Handle<WasmInstanceObject> instance, Handle<Code> caller, |
1386 int offset, int func_index, bool patch_caller) { | 1377 int offset, int func_index, bool patch_caller) { |
1387 isolate->set_context(*instance->compiled_module()->native_context()); | 1378 isolate->set_context(*instance->compiled_module()->native_context()); |
1388 Object* orch_obj = | 1379 Object* orch_obj = |
1389 instance->compiled_module()->shared()->lazy_compilation_orchestrator(); | 1380 instance->compiled_module()->shared()->lazy_compilation_orchestrator(); |
1390 LazyCompilationOrchestrator* orch = | 1381 LazyCompilationOrchestrator* orch = |
1391 Managed<LazyCompilationOrchestrator>::cast(orch_obj)->get(); | 1382 Managed<LazyCompilationOrchestrator>::cast(orch_obj)->get(); |
1392 return orch->CompileLazy(isolate, instance, caller, offset, func_index, | 1383 return orch->CompileLazy(isolate, instance, caller, offset, func_index, |
1393 patch_caller); | 1384 patch_caller); |
1394 } | 1385 } |
1395 | |
1396 Handle<WasmInstanceWrapper> WasmInstanceWrapper::New( | |
1397 Isolate* isolate, Handle<WasmInstanceObject> instance) { | |
1398 Handle<FixedArray> array = | |
1399 isolate->factory()->NewFixedArray(kFieldCount, TENURED); | |
1400 Handle<WasmInstanceWrapper> instance_wrapper( | |
1401 reinterpret_cast<WasmInstanceWrapper*>(*array), isolate); | |
1402 Handle<WeakCell> cell = isolate->factory()->NewWeakCell(instance); | |
1403 instance_wrapper->set(kWrapperInstanceObjectIndex, *cell); | |
1404 return instance_wrapper; | |
1405 } | |
1406 | |
1407 bool WasmInstanceWrapper::IsWasmInstanceWrapper(Object* obj) { | |
1408 if (!obj->IsFixedArray()) return false; | |
1409 Handle<FixedArray> array = handle(FixedArray::cast(obj)); | |
1410 if (array->length() != kFieldCount) return false; | |
1411 if (!array->get(kWrapperInstanceObjectIndex)->IsWeakCell()) return false; | |
1412 Isolate* isolate = array->GetIsolate(); | |
1413 if (!array->get(kNextInstanceWrapperIndex)->IsUndefined(isolate) && | |
1414 !array->get(kNextInstanceWrapperIndex)->IsFixedArray()) | |
1415 return false; | |
1416 if (!array->get(kPreviousInstanceWrapperIndex)->IsUndefined(isolate) && | |
1417 !array->get(kPreviousInstanceWrapperIndex)->IsFixedArray()) | |
1418 return false; | |
1419 return true; | |
1420 } | |
OLD | NEW |