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 |