| OLD | NEW |
| 1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 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/runtime/runtime-utils.h" | 5 #include "src/runtime/runtime-utils.h" |
| 6 | 6 |
| 7 #include "src/arguments.h" | 7 #include "src/arguments.h" |
| 8 #include "src/assembler.h" | 8 #include "src/assembler.h" |
| 9 #include "src/compiler/wasm-compiler.h" | 9 #include "src/compiler/wasm-compiler.h" |
| 10 #include "src/conversions.h" | 10 #include "src/conversions.h" |
| 11 #include "src/debug/debug.h" | 11 #include "src/debug/debug.h" |
| 12 #include "src/factory.h" | 12 #include "src/factory.h" |
| 13 #include "src/frames-inl.h" | 13 #include "src/frames-inl.h" |
| 14 #include "src/objects-inl.h" | 14 #include "src/objects-inl.h" |
| 15 #include "src/v8memory.h" | 15 #include "src/v8memory.h" |
| 16 #include "src/wasm/wasm-module.h" | 16 #include "src/wasm/wasm-module.h" |
| 17 | 17 |
| 18 namespace v8 { | 18 namespace v8 { |
| 19 namespace internal { | 19 namespace internal { |
| 20 | 20 |
| 21 namespace { | |
| 22 const int kWasmMemArrayBuffer = 2; | |
| 23 } | |
| 24 | |
| 25 RUNTIME_FUNCTION(Runtime_WasmGrowMemory) { | 21 RUNTIME_FUNCTION(Runtime_WasmGrowMemory) { |
| 26 HandleScope scope(isolate); | 22 HandleScope scope(isolate); |
| 27 DCHECK_EQ(1, args.length()); | 23 DCHECK_EQ(1, args.length()); |
| 28 uint32_t delta_pages = 0; | 24 uint32_t delta_pages = 0; |
| 29 CHECK(args[0]->ToUint32(&delta_pages)); | 25 CHECK(args[0]->ToUint32(&delta_pages)); |
| 30 Handle<JSObject> module_object; | 26 Handle<JSObject> module_instance; |
| 31 | 27 |
| 32 { | 28 { |
| 33 // Get the module JSObject | 29 // Get the module JSObject |
| 34 DisallowHeapAllocation no_allocation; | 30 DisallowHeapAllocation no_allocation; |
| 35 const Address entry = Isolate::c_entry_fp(isolate->thread_local_top()); | 31 const Address entry = Isolate::c_entry_fp(isolate->thread_local_top()); |
| 36 Address pc = | 32 Address pc = |
| 37 Memory::Address_at(entry + StandardFrameConstants::kCallerPCOffset); | 33 Memory::Address_at(entry + StandardFrameConstants::kCallerPCOffset); |
| 38 Code* code = | 34 Code* code = |
| 39 isolate->inner_pointer_to_code_cache()->GetCacheEntry(pc)->code; | 35 isolate->inner_pointer_to_code_cache()->GetCacheEntry(pc)->code; |
| 40 Object* undefined = *isolate->factory()->undefined_value(); | 36 Object* undefined = *isolate->factory()->undefined_value(); |
| 41 Object* owning_instance = wasm::GetOwningWasmInstance(undefined, code); | 37 Object* owning_instance = wasm::GetOwningWasmInstance(undefined, code); |
| 42 CHECK_NOT_NULL(owning_instance); | 38 CHECK_NOT_NULL(owning_instance); |
| 43 CHECK_NE(owning_instance, undefined); | 39 CHECK_NE(owning_instance, undefined); |
| 44 module_object = handle(JSObject::cast(owning_instance), isolate); | 40 module_instance = handle(JSObject::cast(owning_instance), isolate); |
| 45 } | 41 } |
| 46 | 42 |
| 47 Address old_mem_start, new_mem_start; | 43 Address old_mem_start, new_mem_start; |
| 48 uint32_t old_size, new_size; | 44 uint32_t old_size, new_size; |
| 49 | 45 |
| 50 // Get mem buffer associated with module object | 46 // Get mem buffer associated with module object |
| 51 Handle<Object> obj(module_object->GetInternalField(kWasmMemArrayBuffer), | 47 MaybeHandle<JSArrayBuffer> maybe_mem_buffer = |
| 52 isolate); | 48 wasm::GetInstanceMemory(isolate, module_instance); |
| 53 | 49 Handle<JSArrayBuffer> old_buffer; |
| 54 if (obj->IsUndefined(isolate)) { | 50 if (!maybe_mem_buffer.ToHandle(&old_buffer)) { |
| 55 // If module object does not have linear memory associated with it, | 51 // If module object does not have linear memory associated with it, |
| 56 // Allocate new array buffer of given size. | 52 // Allocate new array buffer of given size. |
| 57 old_mem_start = nullptr; | 53 old_mem_start = nullptr; |
| 58 old_size = 0; | 54 old_size = 0; |
| 59 // TODO(gdeepti): Fix bounds check to take into account size of memtype. | 55 // TODO(gdeepti): Fix bounds check to take into account size of memtype. |
| 60 new_size = delta_pages * wasm::WasmModule::kPageSize; | 56 new_size = delta_pages * wasm::WasmModule::kPageSize; |
| 61 // The code generated in the wasm compiler guarantees this precondition. | 57 // The code generated in the wasm compiler guarantees this precondition. |
| 62 DCHECK(delta_pages <= wasm::WasmModule::kMaxMemPages); | 58 DCHECK(delta_pages <= wasm::WasmModule::kMaxMemPages); |
| 63 new_mem_start = | 59 new_mem_start = |
| 64 static_cast<Address>(isolate->array_buffer_allocator()->Allocate( | 60 static_cast<Address>(isolate->array_buffer_allocator()->Allocate( |
| 65 static_cast<uint32_t>(new_size))); | 61 static_cast<uint32_t>(new_size))); |
| 66 if (new_mem_start == NULL) { | 62 if (new_mem_start == NULL) { |
| 67 return *isolate->factory()->NewNumberFromInt(-1); | 63 return *isolate->factory()->NewNumberFromInt(-1); |
| 68 } | 64 } |
| 69 #if DEBUG | 65 #if DEBUG |
| 70 // Double check the API allocator actually zero-initialized the memory. | 66 // Double check the API allocator actually zero-initialized the memory. |
| 71 for (size_t i = old_size; i < new_size; i++) { | 67 for (size_t i = old_size; i < new_size; i++) { |
| 72 DCHECK_EQ(0, new_mem_start[i]); | 68 DCHECK_EQ(0, new_mem_start[i]); |
| 73 } | 69 } |
| 74 #endif | 70 #endif |
| 75 } else { | 71 } else { |
| 76 Handle<JSArrayBuffer> old_buffer = Handle<JSArrayBuffer>::cast(obj); | |
| 77 old_mem_start = static_cast<Address>(old_buffer->backing_store()); | 72 old_mem_start = static_cast<Address>(old_buffer->backing_store()); |
| 78 old_size = old_buffer->byte_length()->Number(); | 73 old_size = old_buffer->byte_length()->Number(); |
| 79 // If the old memory was zero-sized, we should have been in the | 74 // If the old memory was zero-sized, we should have been in the |
| 80 // "undefined" case above. | 75 // "undefined" case above. |
| 81 DCHECK_NOT_NULL(old_mem_start); | 76 DCHECK_NOT_NULL(old_mem_start); |
| 82 DCHECK_NE(0, old_size); | 77 DCHECK_NE(0, old_size); |
| 83 | 78 |
| 84 new_size = old_size + delta_pages * wasm::WasmModule::kPageSize; | 79 new_size = old_size + delta_pages * wasm::WasmModule::kPageSize; |
| 85 if (new_size > | 80 if (new_size > |
| 86 wasm::WasmModule::kMaxMemPages * wasm::WasmModule::kPageSize) { | 81 wasm::WasmModule::kMaxMemPages * wasm::WasmModule::kPageSize) { |
| 87 return *isolate->factory()->NewNumberFromInt(-1); | 82 return *isolate->factory()->NewNumberFromInt(-1); |
| 88 } | 83 } |
| 89 new_mem_start = static_cast<Address>(realloc(old_mem_start, new_size)); | 84 new_mem_start = static_cast<Address>(realloc(old_mem_start, new_size)); |
| 90 if (new_mem_start == NULL) { | 85 if (new_mem_start == NULL) { |
| 91 return *isolate->factory()->NewNumberFromInt(-1); | 86 return *isolate->factory()->NewNumberFromInt(-1); |
| 92 } | 87 } |
| 93 old_buffer->set_is_external(true); | 88 old_buffer->set_is_external(true); |
| 94 isolate->heap()->UnregisterArrayBuffer(*old_buffer); | 89 isolate->heap()->UnregisterArrayBuffer(*old_buffer); |
| 95 // Zero initializing uninitialized memory from realloc | 90 // Zero initializing uninitialized memory from realloc |
| 96 memset(new_mem_start + old_size, 0, new_size - old_size); | 91 memset(new_mem_start + old_size, 0, new_size - old_size); |
| 97 } | 92 } |
| 98 | 93 |
| 99 Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer(); | 94 Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer(); |
| 100 JSArrayBuffer::Setup(buffer, isolate, false, new_mem_start, new_size); | 95 JSArrayBuffer::Setup(buffer, isolate, false, new_mem_start, new_size); |
| 101 buffer->set_is_neuterable(false); | 96 buffer->set_is_neuterable(false); |
| 102 | 97 |
| 103 // Set new buffer to be wasm memory | 98 // Set new buffer to be wasm memory |
| 104 module_object->SetInternalField(kWasmMemArrayBuffer, *buffer); | |
| 105 | 99 |
| 106 CHECK(wasm::UpdateWasmModuleMemory(module_object, old_mem_start, | 100 wasm::SetInstanceMemory(module_instance, *buffer); |
| 101 |
| 102 CHECK(wasm::UpdateWasmModuleMemory(module_instance, old_mem_start, |
| 107 new_mem_start, old_size, new_size)); | 103 new_mem_start, old_size, new_size)); |
| 108 | 104 |
| 109 return *isolate->factory()->NewNumberFromInt(old_size / | 105 return *isolate->factory()->NewNumberFromInt(old_size / |
| 110 wasm::WasmModule::kPageSize); | 106 wasm::WasmModule::kPageSize); |
| 111 } | 107 } |
| 112 | 108 |
| 113 RUNTIME_FUNCTION(Runtime_WasmThrowTypeError) { | 109 RUNTIME_FUNCTION(Runtime_WasmThrowTypeError) { |
| 114 HandleScope scope(isolate); | 110 HandleScope scope(isolate); |
| 115 DCHECK_EQ(0, args.length()); | 111 DCHECK_EQ(0, args.length()); |
| 116 THROW_NEW_ERROR_RETURN_FAILURE( | 112 THROW_NEW_ERROR_RETURN_FAILURE( |
| 117 isolate, NewTypeError(MessageTemplate::kWasmTrapTypeError)); | 113 isolate, NewTypeError(MessageTemplate::kWasmTrapTypeError)); |
| 118 } | 114 } |
| 119 } // namespace internal | 115 } // namespace internal |
| 120 } // namespace v8 | 116 } // namespace v8 |
| OLD | NEW |