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