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 <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 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
65 Handle<Object> new_ref) { | 65 Handle<Object> new_ref) { |
66 for (RelocIterator it(*code, 1 << RelocInfo::EMBEDDED_OBJECT); !it.done(); | 66 for (RelocIterator it(*code, 1 << RelocInfo::EMBEDDED_OBJECT); !it.done(); |
67 it.next()) { | 67 it.next()) { |
68 if (it.rinfo()->target_object() == *old_ref) { | 68 if (it.rinfo()->target_object() == *old_ref) { |
69 it.rinfo()->set_target_object(*new_ref); | 69 it.rinfo()->set_target_object(*new_ref); |
70 } | 70 } |
71 } | 71 } |
72 } | 72 } |
73 | 73 |
74 static void MemoryFinalizer(const v8::WeakCallbackInfo<void>& data) { | 74 static void MemoryFinalizer(const v8::WeakCallbackInfo<void>& data) { |
| 75 DisallowHeapAllocation no_gc; |
75 JSArrayBuffer** p = reinterpret_cast<JSArrayBuffer**>(data.GetParameter()); | 76 JSArrayBuffer** p = reinterpret_cast<JSArrayBuffer**>(data.GetParameter()); |
76 JSArrayBuffer* buffer = *p; | 77 JSArrayBuffer* buffer = *p; |
77 | 78 |
78 void* memory = buffer->backing_store(); | 79 void* memory = buffer->backing_store(); |
79 base::OS::Free(memory, | 80 base::OS::Free(memory, |
80 RoundUp(kWasmMaxHeapOffset, base::OS::CommitPageSize())); | 81 RoundUp(kWasmMaxHeapOffset, base::OS::CommitPageSize())); |
81 | 82 |
82 data.GetIsolate()->AdjustAmountOfExternalAllocatedMemory( | 83 data.GetIsolate()->AdjustAmountOfExternalAllocatedMemory( |
83 -buffer->byte_length()->Number()); | 84 -buffer->byte_length()->Number()); |
84 | 85 |
(...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
549 } | 550 } |
550 if (changed) { | 551 if (changed) { |
551 Assembler::FlushICache(isolate, code->instruction_start(), | 552 Assembler::FlushICache(isolate, code->instruction_start(), |
552 code->instruction_size()); | 553 code->instruction_size()); |
553 } | 554 } |
554 } | 555 } |
555 } | 556 } |
556 compiled_module->reset_memory(); | 557 compiled_module->reset_memory(); |
557 } | 558 } |
558 | 559 |
| 560 static void MemoryInstanceFinalizer(Isolate* isolate, |
| 561 WasmInstanceObject* instance) { |
| 562 DisallowHeapAllocation no_gc; |
| 563 // If the memory object is destroyed, nothing needs to be done here. |
| 564 if (!instance->has_memory_object()) return; |
| 565 Handle<WasmInstanceWrapper> instance_wrapper = |
| 566 handle(instance->get_instance_wrapper()); |
| 567 DCHECK(WasmInstanceWrapper::IsWasmInstanceWrapper(*instance_wrapper)); |
| 568 DCHECK(instance_wrapper->has_instance()); |
| 569 bool has_prev = instance_wrapper->has_previous(); |
| 570 bool has_next = instance_wrapper->has_next(); |
| 571 Handle<WasmMemoryObject> memory_object(instance->get_memory_object()); |
| 572 |
| 573 if (!has_prev && !has_next) { |
| 574 memory_object->ResetInstancesLink(isolate); |
| 575 return; |
| 576 } else { |
| 577 Handle<WasmInstanceWrapper> next_wrapper, prev_wrapper; |
| 578 if (!has_prev) { |
| 579 Handle<WasmInstanceWrapper> next_wrapper = |
| 580 instance_wrapper->next_wrapper(); |
| 581 next_wrapper->reset_previous_wrapper(); |
| 582 // As this is the first link in the memory object, destroying |
| 583 // without updating memory object would corrupt the instance chain in |
| 584 // the memory object. |
| 585 memory_object->set_instances_link(*next_wrapper); |
| 586 } else if (!has_next) { |
| 587 instance_wrapper->previous_wrapper()->reset_next_wrapper(); |
| 588 } else { |
| 589 DCHECK(has_next && has_prev); |
| 590 Handle<WasmInstanceWrapper> prev_wrapper = |
| 591 instance_wrapper->previous_wrapper(); |
| 592 Handle<WasmInstanceWrapper> next_wrapper = |
| 593 instance_wrapper->next_wrapper(); |
| 594 prev_wrapper->set_next_wrapper(*next_wrapper); |
| 595 next_wrapper->set_previous_wrapper(*prev_wrapper); |
| 596 } |
| 597 // Reset to avoid dangling pointers |
| 598 instance_wrapper->reset(); |
| 599 } |
| 600 } |
| 601 |
559 static void InstanceFinalizer(const v8::WeakCallbackInfo<void>& data) { | 602 static void InstanceFinalizer(const v8::WeakCallbackInfo<void>& data) { |
| 603 DisallowHeapAllocation no_gc; |
560 JSObject** p = reinterpret_cast<JSObject**>(data.GetParameter()); | 604 JSObject** p = reinterpret_cast<JSObject**>(data.GetParameter()); |
561 WasmInstanceObject* owner = reinterpret_cast<WasmInstanceObject*>(*p); | 605 WasmInstanceObject* owner = reinterpret_cast<WasmInstanceObject*>(*p); |
| 606 Isolate* isolate = reinterpret_cast<Isolate*>(data.GetIsolate()); |
| 607 // Is a link to shared memory instances exists, update the list of memory |
| 608 // instances before the instance is destroyed. |
| 609 if (owner->has_instance_wrapper()) MemoryInstanceFinalizer(isolate, owner); |
562 WasmCompiledModule* compiled_module = owner->get_compiled_module(); | 610 WasmCompiledModule* compiled_module = owner->get_compiled_module(); |
563 TRACE("Finalizing %d {\n", compiled_module->instance_id()); | 611 TRACE("Finalizing %d {\n", compiled_module->instance_id()); |
564 Isolate* isolate = reinterpret_cast<Isolate*>(data.GetIsolate()); | |
565 DCHECK(compiled_module->has_weak_wasm_module()); | 612 DCHECK(compiled_module->has_weak_wasm_module()); |
566 WeakCell* weak_wasm_module = compiled_module->ptr_to_weak_wasm_module(); | 613 WeakCell* weak_wasm_module = compiled_module->ptr_to_weak_wasm_module(); |
567 | 614 |
568 // weak_wasm_module may have been cleared, meaning the module object | 615 // weak_wasm_module may have been cleared, meaning the module object |
569 // was GC-ed. In that case, there won't be any new instances created, | 616 // was GC-ed. In that case, there won't be any new instances created, |
570 // and we don't need to maintain the links between instances. | 617 // and we don't need to maintain the links between instances. |
571 if (!weak_wasm_module->cleared()) { | 618 if (!weak_wasm_module->cleared()) { |
572 JSObject* wasm_module = JSObject::cast(weak_wasm_module->value()); | 619 JSObject* wasm_module = JSObject::cast(weak_wasm_module->value()); |
573 WasmCompiledModule* current_template = | 620 WasmCompiledModule* current_template = |
574 WasmCompiledModule::cast(wasm_module->GetInternalField(0)); | 621 WasmCompiledModule::cast(wasm_module->GetInternalField(0)); |
(...skipping 601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1176 ? static_cast<Address>( | 1223 ? static_cast<Address>( |
1177 compiled_module_->memory()->backing_store()) | 1224 compiled_module_->memory()->backing_store()) |
1178 : nullptr; | 1225 : nullptr; |
1179 RelocateMemoryReferencesInCode(code_table, old_mem_start, mem_start, | 1226 RelocateMemoryReferencesInCode(code_table, old_mem_start, mem_start, |
1180 old_mem_size, mem_size); | 1227 old_mem_size, mem_size); |
1181 compiled_module_->set_memory(memory_); | 1228 compiled_module_->set_memory(memory_); |
1182 } else { | 1229 } else { |
1183 LoadDataSegments(nullptr, 0); | 1230 LoadDataSegments(nullptr, 0); |
1184 } | 1231 } |
1185 | 1232 |
| 1233 DCHECK(wasm::IsWasmInstance(*instance)); |
| 1234 if (instance->has_memory_object()) { |
| 1235 instance->get_memory_object()->AddInstance(isolate_, instance); |
| 1236 } |
| 1237 |
1186 //-------------------------------------------------------------------------- | 1238 //-------------------------------------------------------------------------- |
1187 // Set up the runtime support for the new instance. | 1239 // Set up the runtime support for the new instance. |
1188 //-------------------------------------------------------------------------- | 1240 //-------------------------------------------------------------------------- |
1189 Handle<WeakCell> weak_link = factory->NewWeakCell(instance); | 1241 Handle<WeakCell> weak_link = factory->NewWeakCell(instance); |
1190 | 1242 |
1191 for (int i = num_imported_functions + FLAG_skip_compiling_wasm_funcs; | 1243 for (int i = num_imported_functions + FLAG_skip_compiling_wasm_funcs; |
1192 i < code_table->length(); ++i) { | 1244 i < code_table->length(); ++i) { |
1193 Handle<Code> code = code_table->GetValueChecked<Code>(isolate_, i); | 1245 Handle<Code> code = code_table->GetValueChecked<Code>(isolate_, i); |
1194 if (code->kind() == Code::WASM_FUNCTION) { | 1246 if (code->kind() == Code::WASM_FUNCTION) { |
1195 Handle<FixedArray> deopt_data = factory->NewFixedArray(2, TENURED); | 1247 Handle<FixedArray> deopt_data = factory->NewFixedArray(2, TENURED); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1246 compiled_module_->set_weak_wasm_module( | 1298 compiled_module_->set_weak_wasm_module( |
1247 original.ToHandleChecked()->weak_wasm_module()); | 1299 original.ToHandleChecked()->weak_wasm_module()); |
1248 } | 1300 } |
1249 module_object_->SetInternalField(0, *compiled_module_); | 1301 module_object_->SetInternalField(0, *compiled_module_); |
1250 compiled_module_->set_weak_owning_instance(link_to_owning_instance); | 1302 compiled_module_->set_weak_owning_instance(link_to_owning_instance); |
1251 GlobalHandles::MakeWeak(global_handle.location(), | 1303 GlobalHandles::MakeWeak(global_handle.location(), |
1252 global_handle.location(), &InstanceFinalizer, | 1304 global_handle.location(), &InstanceFinalizer, |
1253 v8::WeakCallbackType::kFinalizer); | 1305 v8::WeakCallbackType::kFinalizer); |
1254 } | 1306 } |
1255 } | 1307 } |
1256 | |
1257 DCHECK(wasm::IsWasmInstance(*instance)); | |
1258 if (instance->has_memory_object()) { | |
1259 instance->get_memory_object()->AddInstance(*instance); | |
1260 } | |
1261 | |
1262 //-------------------------------------------------------------------------- | 1308 //-------------------------------------------------------------------------- |
1263 // Run the start function if one was specified. | 1309 // Run the start function if one was specified. |
1264 //-------------------------------------------------------------------------- | 1310 //-------------------------------------------------------------------------- |
1265 if (module_->start_function_index >= 0) { | 1311 if (module_->start_function_index >= 0) { |
1266 HandleScope scope(isolate_); | 1312 HandleScope scope(isolate_); |
1267 ModuleEnv module_env; | 1313 ModuleEnv module_env; |
1268 module_env.module = module_; | 1314 module_env.module = module_; |
1269 module_env.instance = nullptr; | 1315 module_env.instance = nullptr; |
1270 module_env.origin = module_->origin; | 1316 module_env.origin = module_->origin; |
1271 int start_index = module_->start_function_index; | 1317 int start_index = module_->start_function_index; |
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1546 break; | 1592 break; |
1547 } | 1593 } |
1548 case kExternalMemory: { | 1594 case kExternalMemory: { |
1549 Handle<Object> object = result.ToHandleChecked(); | 1595 Handle<Object> object = result.ToHandleChecked(); |
1550 if (!WasmJs::IsWasmMemoryObject(isolate_, object)) { | 1596 if (!WasmJs::IsWasmMemoryObject(isolate_, object)) { |
1551 ReportFFIError("memory import must be a WebAssembly.Memory object", | 1597 ReportFFIError("memory import must be a WebAssembly.Memory object", |
1552 index, module_name, function_name); | 1598 index, module_name, function_name); |
1553 return -1; | 1599 return -1; |
1554 } | 1600 } |
1555 auto memory = Handle<WasmMemoryObject>::cast(object); | 1601 auto memory = Handle<WasmMemoryObject>::cast(object); |
| 1602 DCHECK(WasmJs::IsWasmMemoryObject(isolate_, memory)); |
1556 instance->set_memory_object(*memory); | 1603 instance->set_memory_object(*memory); |
1557 memory_ = Handle<JSArrayBuffer>(memory->get_buffer(), isolate_); | 1604 memory_ = Handle<JSArrayBuffer>(memory->get_buffer(), isolate_); |
1558 break; | 1605 break; |
1559 } | 1606 } |
1560 case kExternalGlobal: { | 1607 case kExternalGlobal: { |
1561 // Global imports are converted to numbers and written into the | 1608 // Global imports are converted to numbers and written into the |
1562 // {globals_} array buffer. | 1609 // {globals_} array buffer. |
1563 Handle<Object> object = result.ToHandleChecked(); | 1610 Handle<Object> object = result.ToHandleChecked(); |
1564 MaybeHandle<Object> number = Object::ToNumber(object); | 1611 MaybeHandle<Object> number = Object::ToNumber(object); |
1565 if (number.is_null()) { | 1612 if (number.is_null()) { |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1727 // If there was no imported WebAssembly.Memory object, create one. | 1774 // If there was no imported WebAssembly.Memory object, create one. |
1728 Handle<JSArrayBuffer> buffer(instance->get_memory_buffer(), | 1775 Handle<JSArrayBuffer> buffer(instance->get_memory_buffer(), |
1729 isolate_); | 1776 isolate_); |
1730 memory_object = WasmMemoryObject::New( | 1777 memory_object = WasmMemoryObject::New( |
1731 isolate_, buffer, | 1778 isolate_, buffer, |
1732 (module_->max_mem_pages != 0) ? module_->max_mem_pages : -1); | 1779 (module_->max_mem_pages != 0) ? module_->max_mem_pages : -1); |
1733 instance->set_memory_object(*memory_object); | 1780 instance->set_memory_object(*memory_object); |
1734 } else { | 1781 } else { |
1735 memory_object = Handle<WasmMemoryObject>( | 1782 memory_object = Handle<WasmMemoryObject>( |
1736 instance->get_memory_object(), isolate_); | 1783 instance->get_memory_object(), isolate_); |
| 1784 DCHECK(WasmJs::IsWasmMemoryObject(isolate_, memory_object)); |
| 1785 memory_object->ResetInstancesLink(isolate_); |
1737 } | 1786 } |
1738 | 1787 |
1739 desc.set_value(memory_object); | 1788 desc.set_value(memory_object); |
1740 break; | 1789 break; |
1741 } | 1790 } |
1742 case kExternalGlobal: { | 1791 case kExternalGlobal: { |
1743 // Export the value of the global variable as a number. | 1792 // Export the value of the global variable as a number. |
1744 WasmGlobal& global = module_->globals[exp.index]; | 1793 WasmGlobal& global = module_->globals[exp.index]; |
1745 double num = 0; | 1794 double num = 0; |
1746 switch (global.type) { | 1795 switch (global.type) { |
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2062 ModuleResult result = DecodeWasmModule(isolate, start, end, true, origin); | 2111 ModuleResult result = DecodeWasmModule(isolate, start, end, true, origin); |
2063 if (result.val) { | 2112 if (result.val) { |
2064 delete result.val; | 2113 delete result.val; |
2065 } else { | 2114 } else { |
2066 DCHECK(!result.ok()); | 2115 DCHECK(!result.ok()); |
2067 } | 2116 } |
2068 return result.ok(); | 2117 return result.ok(); |
2069 } | 2118 } |
2070 | 2119 |
2071 MaybeHandle<JSArrayBuffer> wasm::GetInstanceMemory( | 2120 MaybeHandle<JSArrayBuffer> wasm::GetInstanceMemory( |
2072 Isolate* isolate, Handle<WasmInstanceObject> instance) { | 2121 Isolate* isolate, Handle<WasmInstanceObject> object) { |
| 2122 auto instance = Handle<WasmInstanceObject>::cast(object); |
2073 if (instance->has_memory_buffer()) { | 2123 if (instance->has_memory_buffer()) { |
2074 return Handle<JSArrayBuffer>(instance->get_memory_buffer(), isolate); | 2124 return Handle<JSArrayBuffer>(instance->get_memory_buffer(), isolate); |
2075 } | 2125 } |
2076 return MaybeHandle<JSArrayBuffer>(); | 2126 return MaybeHandle<JSArrayBuffer>(); |
2077 } | 2127 } |
2078 | 2128 |
2079 void SetInstanceMemory(Handle<WasmInstanceObject> instance, | 2129 void SetInstanceMemory(Handle<WasmInstanceObject> instance, |
2080 JSArrayBuffer* buffer) { | 2130 JSArrayBuffer* buffer) { |
2081 DisallowHeapAllocation no_gc; | 2131 DisallowHeapAllocation no_gc; |
2082 instance->set_memory_buffer(buffer); | 2132 instance->set_memory_buffer(buffer); |
2083 instance->get_compiled_module()->set_ptr_to_memory(buffer); | 2133 instance->get_compiled_module()->set_ptr_to_memory(buffer); |
2084 } | 2134 } |
2085 | 2135 |
2086 int32_t wasm::GetInstanceMemorySize(Isolate* isolate, | 2136 int32_t wasm::GetInstanceMemorySize(Isolate* isolate, |
2087 Handle<WasmInstanceObject> instance) { | 2137 Handle<WasmInstanceObject> instance) { |
| 2138 DCHECK(IsWasmInstance(*instance)); |
2088 MaybeHandle<JSArrayBuffer> maybe_mem_buffer = | 2139 MaybeHandle<JSArrayBuffer> maybe_mem_buffer = |
2089 GetInstanceMemory(isolate, instance); | 2140 GetInstanceMemory(isolate, instance); |
2090 Handle<JSArrayBuffer> buffer; | 2141 Handle<JSArrayBuffer> buffer; |
2091 if (!maybe_mem_buffer.ToHandle(&buffer)) { | 2142 if (!maybe_mem_buffer.ToHandle(&buffer)) { |
2092 return 0; | 2143 return 0; |
2093 } else { | 2144 } else { |
2094 return buffer->byte_length()->Number() / WasmModule::kPageSize; | 2145 return buffer->byte_length()->Number() / WasmModule::kPageSize; |
2095 } | 2146 } |
2096 } | 2147 } |
2097 | 2148 |
2098 uint32_t GetMaxInstanceMemorySize(Isolate* isolate, | 2149 uint32_t GetMaxInstanceMemorySize(Isolate* isolate, |
2099 Handle<WasmInstanceObject> instance) { | 2150 Handle<WasmInstanceObject> instance) { |
2100 if (instance->has_memory_object()) { | 2151 if (instance->has_memory_object()) { |
2101 Handle<WasmMemoryObject> memory_object(instance->get_memory_object(), | 2152 Handle<WasmMemoryObject> memory_object(instance->get_memory_object(), |
2102 isolate); | 2153 isolate); |
2103 | 2154 |
2104 int maximum = memory_object->maximum_pages(); | 2155 int maximum = memory_object->maximum_pages(); |
2105 if (maximum > 0) return static_cast<uint32_t>(maximum); | 2156 if (maximum > 0) return static_cast<uint32_t>(maximum); |
2106 } | 2157 } |
2107 uint32_t compiled_max_pages = | 2158 uint32_t compiled_max_pages = |
2108 instance->get_compiled_module()->max_mem_pages(); | 2159 instance->get_compiled_module()->max_mem_pages(); |
2109 isolate->counters()->wasm_max_mem_pages_count()->AddSample( | 2160 isolate->counters()->wasm_max_mem_pages_count()->AddSample( |
2110 compiled_max_pages); | 2161 compiled_max_pages); |
2111 if (compiled_max_pages != 0) return compiled_max_pages; | 2162 if (compiled_max_pages != 0) return compiled_max_pages; |
2112 return WasmModule::kV8MaxPages; | 2163 return WasmModule::kV8MaxPages; |
2113 } | 2164 } |
2114 | 2165 |
2115 int32_t wasm::GrowInstanceMemory(Isolate* isolate, | 2166 Handle<JSArrayBuffer> GrowMemoryBuffer(Isolate* isolate, |
2116 Handle<WasmInstanceObject> instance, | 2167 MaybeHandle<JSArrayBuffer> buffer, |
2117 uint32_t pages) { | 2168 uint32_t pages, uint32_t max_pages) { |
2118 if (pages == 0) return GetInstanceMemorySize(isolate, instance); | 2169 Handle<JSArrayBuffer> old_buffer; |
2119 uint32_t max_pages = GetMaxInstanceMemorySize(isolate, instance); | |
2120 | |
2121 Address old_mem_start = nullptr; | 2170 Address old_mem_start = nullptr; |
2122 uint32_t old_size = 0, new_size = 0; | 2171 uint32_t old_size = 0; |
2123 | 2172 if (buffer.ToHandle(&old_buffer) && old_buffer->backing_store() != nullptr) { |
2124 MaybeHandle<JSArrayBuffer> maybe_mem_buffer = | |
2125 GetInstanceMemory(isolate, instance); | |
2126 Handle<JSArrayBuffer> old_buffer; | |
2127 if (!maybe_mem_buffer.ToHandle(&old_buffer) || | |
2128 old_buffer->backing_store() == nullptr) { | |
2129 // If module object does not have linear memory associated with it, | |
2130 // Allocate new array buffer of given size. | |
2131 new_size = pages * WasmModule::kPageSize; | |
2132 if (max_pages < pages) return -1; | |
2133 } else { | |
2134 old_mem_start = static_cast<Address>(old_buffer->backing_store()); | 2173 old_mem_start = static_cast<Address>(old_buffer->backing_store()); |
| 2174 DCHECK_NOT_NULL(old_mem_start); |
2135 old_size = old_buffer->byte_length()->Number(); | 2175 old_size = old_buffer->byte_length()->Number(); |
2136 // If the old memory was zero-sized, we should have been in the | 2176 } |
2137 // "undefined" case above. | 2177 DCHECK(old_size + pages * WasmModule::kPageSize <= |
2138 DCHECK_NOT_NULL(old_mem_start); | 2178 std::numeric_limits<uint32_t>::max()); |
2139 DCHECK(old_size + pages * WasmModule::kPageSize <= | 2179 uint32_t new_size = old_size + pages * WasmModule::kPageSize; |
2140 std::numeric_limits<uint32_t>::max()); | 2180 if (new_size <= old_size || max_pages * WasmModule::kPageSize < new_size || |
2141 new_size = old_size + pages * WasmModule::kPageSize; | 2181 WasmModule::kV8MaxPages * WasmModule::kPageSize < new_size) { |
| 2182 return Handle<JSArrayBuffer>::null(); |
2142 } | 2183 } |
2143 | 2184 |
2144 if (new_size <= old_size || max_pages * WasmModule::kPageSize < new_size || | 2185 Handle<JSArrayBuffer> new_buffer; |
2145 WasmModule::kV8MaxPages * WasmModule::kPageSize < new_size) { | |
2146 return -1; | |
2147 } | |
2148 | |
2149 Handle<JSArrayBuffer> buffer; | |
2150 | |
2151 if (!old_buffer.is_null() && old_buffer->has_guard_region()) { | 2186 if (!old_buffer.is_null() && old_buffer->has_guard_region()) { |
2152 // We don't move the backing store, we simply change the protection to make | 2187 // We don't move the backing store, we simply change the protection to make |
2153 // more of it accessible. | 2188 // more of it accessible. |
2154 base::OS::Unprotect(old_buffer->backing_store(), new_size); | 2189 base::OS::Unprotect(old_buffer->backing_store(), new_size); |
2155 reinterpret_cast<v8::Isolate*>(isolate) | 2190 reinterpret_cast<v8::Isolate*>(isolate) |
2156 ->AdjustAmountOfExternalAllocatedMemory(pages * WasmModule::kPageSize); | 2191 ->AdjustAmountOfExternalAllocatedMemory(pages * WasmModule::kPageSize); |
2157 Handle<Object> new_size_object = | 2192 Handle<Object> new_size_object = |
2158 isolate->factory()->NewNumberFromSize(new_size); | 2193 isolate->factory()->NewNumberFromSize(new_size); |
2159 old_buffer->set_byte_length(*new_size_object); | 2194 old_buffer->set_byte_length(*new_size_object); |
2160 | 2195 new_buffer = old_buffer; |
2161 SetInstanceMemory(instance, *old_buffer); | |
2162 Handle<FixedArray> code_table = | |
2163 instance->get_compiled_module()->code_table(); | |
2164 RelocateMemoryReferencesInCode(code_table, old_mem_start, old_mem_start, | |
2165 old_size, new_size); | |
2166 buffer = old_buffer; | |
2167 } else { | 2196 } else { |
2168 const bool enable_guard_regions = false; | 2197 const bool enable_guard_regions = false; |
2169 buffer = NewArrayBuffer(isolate, new_size, enable_guard_regions); | 2198 new_buffer = NewArrayBuffer(isolate, new_size, enable_guard_regions); |
2170 if (buffer.is_null()) return -1; | 2199 if (new_buffer.is_null()) return new_buffer; |
2171 Address new_mem_start = static_cast<Address>(buffer->backing_store()); | 2200 Address new_mem_start = static_cast<Address>(new_buffer->backing_store()); |
2172 if (old_size != 0) { | 2201 if (old_size != 0) { |
2173 memcpy(new_mem_start, old_mem_start, old_size); | 2202 memcpy(new_mem_start, old_mem_start, old_size); |
2174 } | 2203 } |
2175 SetInstanceMemory(instance, *buffer); | |
2176 Handle<FixedArray> code_table = | |
2177 instance->get_compiled_module()->code_table(); | |
2178 RelocateMemoryReferencesInCode(code_table, old_mem_start, new_mem_start, | |
2179 old_size, new_size); | |
2180 } | 2204 } |
| 2205 return new_buffer; |
| 2206 } |
2181 | 2207 |
2182 SetInstanceMemory(instance, *buffer); | 2208 void UncheckedUpdateInstanceMemory(Isolate* isolate, |
2183 if (instance->has_memory_object()) { | 2209 Handle<WasmInstanceObject> instance, |
2184 instance->get_memory_object()->set_buffer(*buffer); | 2210 Address old_mem_start, uint32_t old_size) { |
| 2211 DCHECK(instance->has_memory_buffer()); |
| 2212 Handle<JSArrayBuffer> new_buffer(instance->get_memory_buffer()); |
| 2213 uint32_t new_size = new_buffer->byte_length()->Number(); |
| 2214 DCHECK(new_size <= std::numeric_limits<uint32_t>::max()); |
| 2215 Address new_mem_start = static_cast<Address>(new_buffer->backing_store()); |
| 2216 DCHECK_NOT_NULL(new_mem_start); |
| 2217 Handle<FixedArray> code_table = instance->get_compiled_module()->code_table(); |
| 2218 RelocateMemoryReferencesInCode(code_table, old_mem_start, new_mem_start, |
| 2219 old_size, new_size); |
| 2220 } |
| 2221 |
| 2222 int32_t wasm::GrowWebAssemblyMemory(Isolate* isolate, Handle<Object> receiver, |
| 2223 uint32_t pages) { |
| 2224 DCHECK(WasmJs::IsWasmMemoryObject(isolate, receiver)); |
| 2225 Handle<WasmMemoryObject> memory_object = |
| 2226 handle(WasmMemoryObject::cast(*receiver)); |
| 2227 Handle<WasmInstanceWrapper> instance_wrapper( |
| 2228 memory_object->get_instances_link()); |
| 2229 DCHECK(WasmInstanceWrapper::IsWasmInstanceWrapper(*instance_wrapper)); |
| 2230 DCHECK(instance_wrapper->has_instance()); |
| 2231 Handle<WasmInstanceObject> instance = instance_wrapper->instance_object(); |
| 2232 DCHECK(IsWasmInstance(*instance)); |
| 2233 if (pages == 0) return GetInstanceMemorySize(isolate, instance); |
| 2234 uint32_t max_pages = GetMaxInstanceMemorySize(isolate, instance); |
| 2235 |
| 2236 // Grow memory object buffer and update instances associated with it. |
| 2237 MaybeHandle<JSArrayBuffer> memory_buffer = |
| 2238 handle(memory_object->get_buffer()); |
| 2239 Handle<JSArrayBuffer> old_buffer; |
| 2240 uint32_t old_size = 0; |
| 2241 Address old_mem_start = nullptr; |
| 2242 if (memory_buffer.ToHandle(&old_buffer) && |
| 2243 old_buffer->backing_store() != nullptr) { |
| 2244 old_size = old_buffer->byte_length()->Number(); |
| 2245 old_mem_start = static_cast<Address>(old_buffer->backing_store()); |
2185 } | 2246 } |
2186 | 2247 Handle<JSArrayBuffer> new_buffer = |
| 2248 GrowMemoryBuffer(isolate, memory_buffer, pages, max_pages); |
| 2249 if (new_buffer.is_null()) return -1; |
| 2250 DCHECK(!instance_wrapper->has_previous()); |
| 2251 SetInstanceMemory(instance, *new_buffer); |
| 2252 UncheckedUpdateInstanceMemory(isolate, instance, old_mem_start, old_size); |
| 2253 while (instance_wrapper->has_next()) { |
| 2254 instance_wrapper = instance_wrapper->next_wrapper(); |
| 2255 DCHECK(WasmInstanceWrapper::IsWasmInstanceWrapper(*instance_wrapper)); |
| 2256 Handle<WasmInstanceObject> instance = instance_wrapper->instance_object(); |
| 2257 DCHECK(IsWasmInstance(*instance)); |
| 2258 SetInstanceMemory(instance, *new_buffer); |
| 2259 UncheckedUpdateInstanceMemory(isolate, instance, old_mem_start, old_size); |
| 2260 } |
| 2261 memory_object->set_buffer(*new_buffer); |
2187 DCHECK(old_size % WasmModule::kPageSize == 0); | 2262 DCHECK(old_size % WasmModule::kPageSize == 0); |
2188 return (old_size / WasmModule::kPageSize); | 2263 return (old_size / WasmModule::kPageSize); |
2189 } | 2264 } |
2190 | 2265 |
| 2266 int32_t wasm::GrowMemory(Isolate* isolate, Handle<WasmInstanceObject> instance, |
| 2267 uint32_t pages) { |
| 2268 if (!IsWasmInstance(*instance)) return -1; |
| 2269 if (pages == 0) return GetInstanceMemorySize(isolate, instance); |
| 2270 Handle<WasmInstanceObject> instance_obj(WasmInstanceObject::cast(*instance)); |
| 2271 if (!instance_obj->has_memory_object()) { |
| 2272 // No other instances to grow, grow just the one. |
| 2273 MaybeHandle<JSArrayBuffer> instance_buffer = |
| 2274 GetInstanceMemory(isolate, instance); |
| 2275 Handle<JSArrayBuffer> old_buffer; |
| 2276 uint32_t old_size = 0; |
| 2277 Address old_mem_start = nullptr; |
| 2278 if (instance_buffer.ToHandle(&old_buffer) && |
| 2279 old_buffer->backing_store() != nullptr) { |
| 2280 old_size = old_buffer->byte_length()->Number(); |
| 2281 old_mem_start = static_cast<Address>(old_buffer->backing_store()); |
| 2282 } |
| 2283 uint32_t max_pages = GetMaxInstanceMemorySize(isolate, instance_obj); |
| 2284 Handle<JSArrayBuffer> buffer = |
| 2285 GrowMemoryBuffer(isolate, instance_buffer, pages, max_pages); |
| 2286 if (buffer.is_null()) return -1; |
| 2287 SetInstanceMemory(instance, *buffer); |
| 2288 UncheckedUpdateInstanceMemory(isolate, instance, old_mem_start, old_size); |
| 2289 DCHECK(old_size % WasmModule::kPageSize == 0); |
| 2290 return (old_size / WasmModule::kPageSize); |
| 2291 } else { |
| 2292 return GrowWebAssemblyMemory( |
| 2293 isolate, handle(instance_obj->get_memory_object()), pages); |
| 2294 } |
| 2295 } |
| 2296 |
2191 void testing::ValidateInstancesChain(Isolate* isolate, | 2297 void testing::ValidateInstancesChain(Isolate* isolate, |
2192 Handle<WasmModuleObject> module_obj, | 2298 Handle<WasmModuleObject> module_obj, |
2193 int instance_count) { | 2299 int instance_count) { |
2194 CHECK_GE(instance_count, 0); | 2300 CHECK_GE(instance_count, 0); |
2195 DisallowHeapAllocation no_gc; | 2301 DisallowHeapAllocation no_gc; |
2196 WasmCompiledModule* compiled_module = module_obj->get_compiled_module(); | 2302 WasmCompiledModule* compiled_module = module_obj->get_compiled_module(); |
2197 CHECK_EQ(JSObject::cast(compiled_module->ptr_to_weak_wasm_module()->value()), | 2303 CHECK_EQ(JSObject::cast(compiled_module->ptr_to_weak_wasm_module()->value()), |
2198 *module_obj); | 2304 *module_obj); |
2199 Object* prev = nullptr; | 2305 Object* prev = nullptr; |
2200 int found_instances = compiled_module->has_weak_owning_instance() ? 1 : 0; | 2306 int found_instances = compiled_module->has_weak_owning_instance() ? 1 : 0; |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2266 MaybeHandle<String> WasmCompiledModule::GetFunctionName( | 2372 MaybeHandle<String> WasmCompiledModule::GetFunctionName( |
2267 Handle<WasmCompiledModule> compiled_module, uint32_t func_index) { | 2373 Handle<WasmCompiledModule> compiled_module, uint32_t func_index) { |
2268 DCHECK_LT(func_index, compiled_module->module()->functions.size()); | 2374 DCHECK_LT(func_index, compiled_module->module()->functions.size()); |
2269 WasmFunction& function = compiled_module->module()->functions[func_index]; | 2375 WasmFunction& function = compiled_module->module()->functions[func_index]; |
2270 Isolate* isolate = compiled_module->GetIsolate(); | 2376 Isolate* isolate = compiled_module->GetIsolate(); |
2271 MaybeHandle<String> string = ExtractStringFromModuleBytes( | 2377 MaybeHandle<String> string = ExtractStringFromModuleBytes( |
2272 isolate, compiled_module, function.name_offset, function.name_length); | 2378 isolate, compiled_module, function.name_offset, function.name_length); |
2273 if (!string.is_null()) return string.ToHandleChecked(); | 2379 if (!string.is_null()) return string.ToHandleChecked(); |
2274 return {}; | 2380 return {}; |
2275 } | 2381 } |
OLD | NEW |