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 537 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
548 } | 548 } |
549 if (changed) { | 549 if (changed) { |
550 Assembler::FlushICache(isolate, code->instruction_start(), | 550 Assembler::FlushICache(isolate, code->instruction_start(), |
551 code->instruction_size()); | 551 code->instruction_size()); |
552 } | 552 } |
553 } | 553 } |
554 } | 554 } |
555 compiled_module->reset_memory(); | 555 compiled_module->reset_memory(); |
556 } | 556 } |
557 | 557 |
558 static void MemoryInstanceFinalizer(Isolate* isolate, | |
559 WasmInstanceObject* instance) { | |
560 // If the memory object is destroyed, nothing needs to be done here. | |
561 if (!instance->has_memory_object()) return; | |
562 Handle<WasmInstanceWrapper> instance_wrapper = | |
563 handle(instance->get_instance_wrapper()); | |
564 DCHECK(WasmInstanceWrapper::IsWasmInstanceWrapper(*instance_wrapper)); | |
565 DCHECK(instance_wrapper->has_instance()); | |
566 bool has_prev = instance_wrapper->has_previous(); | |
567 bool has_next = instance_wrapper->has_next(); | |
568 Handle<WasmMemoryObject> memory_object(instance->get_memory_object()); | |
569 | |
570 if (!has_prev && !has_next) { | |
571 memory_object->ResetInstancesLink(isolate); | |
572 return; | |
573 } else { | |
574 Handle<WasmInstanceWrapper> next_wrapper, prev_wrapper; | |
575 if (!has_prev) { | |
576 Handle<WasmInstanceWrapper> next_wrapper = | |
577 instance_wrapper->next_wrapper(); | |
578 next_wrapper->reset_previous_wrapper(); | |
579 // As this is the first link in the memory object, destroying | |
580 // without updating memory object would corrupt the instance chain in | |
581 // the memory object. | |
582 memory_object->set_instances_link(*next_wrapper); | |
583 } else if (!has_next) { | |
584 instance_wrapper->previous_wrapper()->reset_next_wrapper(); | |
585 } else { | |
586 DCHECK(has_next && has_prev); | |
587 Handle<WasmInstanceWrapper> prev_wrapper = | |
588 instance_wrapper->previous_wrapper(); | |
589 Handle<WasmInstanceWrapper> next_wrapper = | |
590 instance_wrapper->next_wrapper(); | |
591 prev_wrapper->set_next_wrapper(*next_wrapper); | |
592 next_wrapper->set_previous_wrapper(*prev_wrapper); | |
593 } | |
594 // Reset to avoid dangling pointers | |
595 instance_wrapper->reset(); | |
596 } | |
597 } | |
598 | |
599 static void InstanceFinalizer(const v8::WeakCallbackInfo<void>& data) { | 558 static void InstanceFinalizer(const v8::WeakCallbackInfo<void>& data) { |
600 JSObject** p = reinterpret_cast<JSObject**>(data.GetParameter()); | 559 JSObject** p = reinterpret_cast<JSObject**>(data.GetParameter()); |
601 WasmInstanceObject* owner = reinterpret_cast<WasmInstanceObject*>(*p); | 560 WasmInstanceObject* owner = reinterpret_cast<WasmInstanceObject*>(*p); |
602 Isolate* isolate = reinterpret_cast<Isolate*>(data.GetIsolate()); | |
603 // Is a link to shared memory instances exists, update the list of memory | |
604 // instances before the instance is destroyed. | |
605 if (owner->has_instance_wrapper()) MemoryInstanceFinalizer(isolate, owner); | |
606 WasmCompiledModule* compiled_module = owner->get_compiled_module(); | 561 WasmCompiledModule* compiled_module = owner->get_compiled_module(); |
607 TRACE("Finalizing %d {\n", compiled_module->instance_id()); | 562 TRACE("Finalizing %d {\n", compiled_module->instance_id()); |
| 563 Isolate* isolate = reinterpret_cast<Isolate*>(data.GetIsolate()); |
608 DCHECK(compiled_module->has_weak_wasm_module()); | 564 DCHECK(compiled_module->has_weak_wasm_module()); |
609 WeakCell* weak_wasm_module = compiled_module->ptr_to_weak_wasm_module(); | 565 WeakCell* weak_wasm_module = compiled_module->ptr_to_weak_wasm_module(); |
610 | 566 |
611 // weak_wasm_module may have been cleared, meaning the module object | 567 // weak_wasm_module may have been cleared, meaning the module object |
612 // was GC-ed. In that case, there won't be any new instances created, | 568 // was GC-ed. In that case, there won't be any new instances created, |
613 // and we don't need to maintain the links between instances. | 569 // and we don't need to maintain the links between instances. |
614 if (!weak_wasm_module->cleared()) { | 570 if (!weak_wasm_module->cleared()) { |
615 JSObject* wasm_module = JSObject::cast(weak_wasm_module->value()); | 571 JSObject* wasm_module = JSObject::cast(weak_wasm_module->value()); |
616 WasmCompiledModule* current_template = | 572 WasmCompiledModule* current_template = |
617 WasmCompiledModule::cast(wasm_module->GetInternalField(0)); | 573 WasmCompiledModule::cast(wasm_module->GetInternalField(0)); |
(...skipping 639 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1257 ? static_cast<Address>( | 1213 ? static_cast<Address>( |
1258 compiled_module_->memory()->backing_store()) | 1214 compiled_module_->memory()->backing_store()) |
1259 : nullptr; | 1215 : nullptr; |
1260 RelocateMemoryReferencesInCode(code_table, old_mem_start, mem_start, | 1216 RelocateMemoryReferencesInCode(code_table, old_mem_start, mem_start, |
1261 old_mem_size, mem_size); | 1217 old_mem_size, mem_size); |
1262 compiled_module_->set_memory(memory_); | 1218 compiled_module_->set_memory(memory_); |
1263 } else { | 1219 } else { |
1264 LoadDataSegments(nullptr, 0); | 1220 LoadDataSegments(nullptr, 0); |
1265 } | 1221 } |
1266 | 1222 |
1267 if (instance->has_memory_object()) { | |
1268 instance->get_memory_object()->AddInstance(isolate_, instance); | |
1269 } | |
1270 | |
1271 //-------------------------------------------------------------------------- | 1223 //-------------------------------------------------------------------------- |
1272 // Set up the runtime support for the new instance. | 1224 // Set up the runtime support for the new instance. |
1273 //-------------------------------------------------------------------------- | 1225 //-------------------------------------------------------------------------- |
1274 Handle<WeakCell> weak_link = factory->NewWeakCell(instance); | 1226 Handle<WeakCell> weak_link = factory->NewWeakCell(instance); |
1275 | 1227 |
1276 for (int i = num_imported_functions + FLAG_skip_compiling_wasm_funcs; | 1228 for (int i = num_imported_functions + FLAG_skip_compiling_wasm_funcs; |
1277 i < code_table->length(); ++i) { | 1229 i < code_table->length(); ++i) { |
1278 Handle<Code> code = code_table->GetValueChecked<Code>(isolate_, i); | 1230 Handle<Code> code = code_table->GetValueChecked<Code>(isolate_, i); |
1279 if (code->kind() == Code::WASM_FUNCTION) { | 1231 if (code->kind() == Code::WASM_FUNCTION) { |
1280 Handle<FixedArray> deopt_data = factory->NewFixedArray(2, TENURED); | 1232 Handle<FixedArray> deopt_data = factory->NewFixedArray(2, TENURED); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1331 compiled_module_->set_weak_wasm_module( | 1283 compiled_module_->set_weak_wasm_module( |
1332 original.ToHandleChecked()->weak_wasm_module()); | 1284 original.ToHandleChecked()->weak_wasm_module()); |
1333 } | 1285 } |
1334 module_object_->SetInternalField(0, *compiled_module_); | 1286 module_object_->SetInternalField(0, *compiled_module_); |
1335 compiled_module_->set_weak_owning_instance(link_to_owning_instance); | 1287 compiled_module_->set_weak_owning_instance(link_to_owning_instance); |
1336 GlobalHandles::MakeWeak(global_handle.location(), | 1288 GlobalHandles::MakeWeak(global_handle.location(), |
1337 global_handle.location(), &InstanceFinalizer, | 1289 global_handle.location(), &InstanceFinalizer, |
1338 v8::WeakCallbackType::kFinalizer); | 1290 v8::WeakCallbackType::kFinalizer); |
1339 } | 1291 } |
1340 } | 1292 } |
| 1293 |
| 1294 DCHECK(wasm::IsWasmInstance(*instance)); |
| 1295 if (instance->has_memory_object()) { |
| 1296 instance->get_memory_object()->AddInstance(*instance); |
| 1297 } |
| 1298 |
1341 //-------------------------------------------------------------------------- | 1299 //-------------------------------------------------------------------------- |
1342 // Run the start function if one was specified. | 1300 // Run the start function if one was specified. |
1343 //-------------------------------------------------------------------------- | 1301 //-------------------------------------------------------------------------- |
1344 if (module_->start_function_index >= 0) { | 1302 if (module_->start_function_index >= 0) { |
1345 HandleScope scope(isolate_); | 1303 HandleScope scope(isolate_); |
1346 ModuleEnv module_env; | 1304 ModuleEnv module_env; |
1347 module_env.module = module_; | 1305 module_env.module = module_; |
1348 module_env.instance = nullptr; | 1306 module_env.instance = nullptr; |
1349 module_env.origin = module_->origin; | 1307 module_env.origin = module_->origin; |
1350 int start_index = module_->start_function_index; | 1308 int start_index = module_->start_function_index; |
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1625 break; | 1583 break; |
1626 } | 1584 } |
1627 case kExternalMemory: { | 1585 case kExternalMemory: { |
1628 Handle<Object> object = result.ToHandleChecked(); | 1586 Handle<Object> object = result.ToHandleChecked(); |
1629 if (!WasmJs::IsWasmMemoryObject(isolate_, object)) { | 1587 if (!WasmJs::IsWasmMemoryObject(isolate_, object)) { |
1630 ReportFFIError("memory import must be a WebAssembly.Memory object", | 1588 ReportFFIError("memory import must be a WebAssembly.Memory object", |
1631 index, module_name, function_name); | 1589 index, module_name, function_name); |
1632 return -1; | 1590 return -1; |
1633 } | 1591 } |
1634 auto memory = Handle<WasmMemoryObject>::cast(object); | 1592 auto memory = Handle<WasmMemoryObject>::cast(object); |
1635 DCHECK(WasmJs::IsWasmMemoryObject(isolate_, memory)); | |
1636 instance->set_memory_object(*memory); | 1593 instance->set_memory_object(*memory); |
1637 memory_ = Handle<JSArrayBuffer>(memory->get_buffer(), isolate_); | 1594 memory_ = Handle<JSArrayBuffer>(memory->get_buffer(), isolate_); |
1638 break; | 1595 break; |
1639 } | 1596 } |
1640 case kExternalGlobal: { | 1597 case kExternalGlobal: { |
1641 // Global imports are converted to numbers and written into the | 1598 // Global imports are converted to numbers and written into the |
1642 // {globals_} array buffer. | 1599 // {globals_} array buffer. |
1643 Handle<Object> object = result.ToHandleChecked(); | 1600 Handle<Object> object = result.ToHandleChecked(); |
1644 MaybeHandle<Object> number = Object::ToNumber(object); | 1601 MaybeHandle<Object> number = Object::ToNumber(object); |
1645 if (number.is_null()) { | 1602 if (number.is_null()) { |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1807 // If there was no imported WebAssembly.Memory object, create one. | 1764 // If there was no imported WebAssembly.Memory object, create one. |
1808 Handle<JSArrayBuffer> buffer(instance->get_memory_buffer(), | 1765 Handle<JSArrayBuffer> buffer(instance->get_memory_buffer(), |
1809 isolate_); | 1766 isolate_); |
1810 memory_object = WasmMemoryObject::New( | 1767 memory_object = WasmMemoryObject::New( |
1811 isolate_, buffer, | 1768 isolate_, buffer, |
1812 (module_->max_mem_pages != 0) ? module_->max_mem_pages : -1); | 1769 (module_->max_mem_pages != 0) ? module_->max_mem_pages : -1); |
1813 instance->set_memory_object(*memory_object); | 1770 instance->set_memory_object(*memory_object); |
1814 } else { | 1771 } else { |
1815 memory_object = Handle<WasmMemoryObject>( | 1772 memory_object = Handle<WasmMemoryObject>( |
1816 instance->get_memory_object(), isolate_); | 1773 instance->get_memory_object(), isolate_); |
1817 DCHECK(WasmJs::IsWasmMemoryObject(isolate_, memory_object)); | |
1818 memory_object->ResetInstancesLink(isolate_); | |
1819 } | 1774 } |
1820 | 1775 |
1821 desc.set_value(memory_object); | 1776 desc.set_value(memory_object); |
1822 break; | 1777 break; |
1823 } | 1778 } |
1824 case kExternalGlobal: { | 1779 case kExternalGlobal: { |
1825 // Export the value of the global variable as a number. | 1780 // Export the value of the global variable as a number. |
1826 WasmGlobal& global = module_->globals[exp.index]; | 1781 WasmGlobal& global = module_->globals[exp.index]; |
1827 double num = 0; | 1782 double num = 0; |
1828 switch (global.type) { | 1783 switch (global.type) { |
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2145 ModuleOrigin origin) { | 2100 ModuleOrigin origin) { |
2146 ModuleResult result = DecodeWasmModule(isolate, start, end, true, origin); | 2101 ModuleResult result = DecodeWasmModule(isolate, start, end, true, origin); |
2147 if (result.val) { | 2102 if (result.val) { |
2148 delete result.val; | 2103 delete result.val; |
2149 } else { | 2104 } else { |
2150 DCHECK(!result.ok()); | 2105 DCHECK(!result.ok()); |
2151 } | 2106 } |
2152 return result.ok(); | 2107 return result.ok(); |
2153 } | 2108 } |
2154 | 2109 |
2155 MaybeHandle<JSArrayBuffer> wasm::GetInstanceMemory(Isolate* isolate, | 2110 MaybeHandle<JSArrayBuffer> wasm::GetInstanceMemory( |
2156 Handle<JSObject> object) { | 2111 Isolate* isolate, Handle<WasmInstanceObject> instance) { |
2157 auto instance = Handle<WasmInstanceObject>::cast(object); | |
2158 if (instance->has_memory_buffer()) { | 2112 if (instance->has_memory_buffer()) { |
2159 return Handle<JSArrayBuffer>(instance->get_memory_buffer(), isolate); | 2113 return Handle<JSArrayBuffer>(instance->get_memory_buffer(), isolate); |
2160 } | 2114 } |
2161 return MaybeHandle<JSArrayBuffer>(); | 2115 return MaybeHandle<JSArrayBuffer>(); |
2162 } | 2116 } |
2163 | 2117 |
2164 void SetInstanceMemory(Handle<WasmInstanceObject> instance, | 2118 void SetInstanceMemory(Handle<WasmInstanceObject> instance, |
2165 JSArrayBuffer* buffer) { | 2119 JSArrayBuffer* buffer) { |
2166 DisallowHeapAllocation no_gc; | 2120 DisallowHeapAllocation no_gc; |
2167 instance->set_memory_buffer(buffer); | 2121 instance->set_memory_buffer(buffer); |
2168 instance->get_compiled_module()->set_ptr_to_memory(buffer); | 2122 instance->get_compiled_module()->set_ptr_to_memory(buffer); |
2169 } | 2123 } |
2170 | 2124 |
2171 int32_t wasm::GetInstanceMemorySize(Isolate* isolate, | 2125 int32_t wasm::GetInstanceMemorySize(Isolate* isolate, |
2172 Handle<WasmInstanceObject> instance) { | 2126 Handle<WasmInstanceObject> instance) { |
2173 DCHECK(IsWasmInstance(*instance)); | |
2174 MaybeHandle<JSArrayBuffer> maybe_mem_buffer = | 2127 MaybeHandle<JSArrayBuffer> maybe_mem_buffer = |
2175 GetInstanceMemory(isolate, instance); | 2128 GetInstanceMemory(isolate, instance); |
2176 Handle<JSArrayBuffer> buffer; | 2129 Handle<JSArrayBuffer> buffer; |
2177 if (!maybe_mem_buffer.ToHandle(&buffer)) { | 2130 if (!maybe_mem_buffer.ToHandle(&buffer)) { |
2178 return 0; | 2131 return 0; |
2179 } else { | 2132 } else { |
2180 return buffer->byte_length()->Number() / WasmModule::kPageSize; | 2133 return buffer->byte_length()->Number() / WasmModule::kPageSize; |
2181 } | 2134 } |
2182 } | 2135 } |
2183 | 2136 |
2184 uint32_t GetMaxInstanceMemorySize(Isolate* isolate, | 2137 uint32_t GetMaxInstanceMemorySize(Isolate* isolate, |
2185 Handle<WasmInstanceObject> instance) { | 2138 Handle<WasmInstanceObject> instance) { |
2186 if (instance->has_memory_object()) { | 2139 if (instance->has_memory_object()) { |
2187 Handle<WasmMemoryObject> memory_object(instance->get_memory_object(), | 2140 Handle<WasmMemoryObject> memory_object(instance->get_memory_object(), |
2188 isolate); | 2141 isolate); |
2189 | 2142 |
2190 int maximum = memory_object->maximum_pages(); | 2143 int maximum = memory_object->maximum_pages(); |
2191 if (maximum > 0) return static_cast<uint32_t>(maximum); | 2144 if (maximum > 0) return static_cast<uint32_t>(maximum); |
2192 } | 2145 } |
2193 uint32_t compiled_max_pages = | 2146 uint32_t compiled_max_pages = |
2194 instance->get_compiled_module()->max_mem_pages(); | 2147 instance->get_compiled_module()->max_mem_pages(); |
2195 isolate->counters()->wasm_max_mem_pages_count()->AddSample( | 2148 isolate->counters()->wasm_max_mem_pages_count()->AddSample( |
2196 compiled_max_pages); | 2149 compiled_max_pages); |
2197 if (compiled_max_pages != 0) return compiled_max_pages; | 2150 if (compiled_max_pages != 0) return compiled_max_pages; |
2198 return WasmModule::kV8MaxPages; | 2151 return WasmModule::kV8MaxPages; |
2199 } | 2152 } |
2200 | 2153 |
2201 Handle<JSArrayBuffer> GrowMemoryBuffer(Isolate* isolate, | 2154 int32_t wasm::GrowInstanceMemory(Isolate* isolate, |
2202 MaybeHandle<JSArrayBuffer> buffer, | 2155 Handle<WasmInstanceObject> instance, |
2203 uint32_t pages, uint32_t max_pages) { | 2156 uint32_t pages) { |
| 2157 if (pages == 0) return GetInstanceMemorySize(isolate, instance); |
| 2158 uint32_t max_pages = GetMaxInstanceMemorySize(isolate, instance); |
| 2159 |
| 2160 Address old_mem_start = nullptr; |
| 2161 uint32_t old_size = 0, new_size = 0; |
| 2162 |
| 2163 MaybeHandle<JSArrayBuffer> maybe_mem_buffer = |
| 2164 GetInstanceMemory(isolate, instance); |
2204 Handle<JSArrayBuffer> old_buffer; | 2165 Handle<JSArrayBuffer> old_buffer; |
2205 Address old_mem_start = nullptr; | 2166 if (!maybe_mem_buffer.ToHandle(&old_buffer) || |
2206 uint32_t old_size = 0; | 2167 old_buffer->backing_store() == nullptr) { |
2207 if (buffer.ToHandle(&old_buffer) && old_buffer->backing_store() != nullptr) { | 2168 // If module object does not have linear memory associated with it, |
| 2169 // Allocate new array buffer of given size. |
| 2170 new_size = pages * WasmModule::kPageSize; |
| 2171 if (max_pages < pages) return -1; |
| 2172 } else { |
2208 old_mem_start = static_cast<Address>(old_buffer->backing_store()); | 2173 old_mem_start = static_cast<Address>(old_buffer->backing_store()); |
| 2174 old_size = old_buffer->byte_length()->Number(); |
| 2175 // If the old memory was zero-sized, we should have been in the |
| 2176 // "undefined" case above. |
2209 DCHECK_NOT_NULL(old_mem_start); | 2177 DCHECK_NOT_NULL(old_mem_start); |
2210 old_size = old_buffer->byte_length()->Number(); | 2178 DCHECK(old_size + pages * WasmModule::kPageSize <= |
| 2179 std::numeric_limits<uint32_t>::max()); |
| 2180 new_size = old_size + pages * WasmModule::kPageSize; |
2211 } | 2181 } |
2212 DCHECK(old_size + pages * WasmModule::kPageSize <= | 2182 |
2213 std::numeric_limits<uint32_t>::max()); | |
2214 uint32_t new_size = old_size + pages * WasmModule::kPageSize; | |
2215 if (new_size <= old_size || max_pages * WasmModule::kPageSize < new_size || | 2183 if (new_size <= old_size || max_pages * WasmModule::kPageSize < new_size || |
2216 WasmModule::kV8MaxPages * WasmModule::kPageSize < new_size) { | 2184 WasmModule::kV8MaxPages * WasmModule::kPageSize < new_size) { |
2217 return Handle<JSArrayBuffer>::null(); | 2185 return -1; |
2218 } | 2186 } |
2219 | 2187 |
2220 Handle<JSArrayBuffer> new_buffer; | 2188 Handle<JSArrayBuffer> buffer; |
| 2189 |
2221 if (!old_buffer.is_null() && old_buffer->has_guard_region()) { | 2190 if (!old_buffer.is_null() && old_buffer->has_guard_region()) { |
2222 // We don't move the backing store, we simply change the protection to make | 2191 // We don't move the backing store, we simply change the protection to make |
2223 // more of it accessible. | 2192 // more of it accessible. |
2224 base::OS::Unprotect(old_buffer->backing_store(), new_size); | 2193 base::OS::Unprotect(old_buffer->backing_store(), new_size); |
2225 reinterpret_cast<v8::Isolate*>(isolate) | 2194 reinterpret_cast<v8::Isolate*>(isolate) |
2226 ->AdjustAmountOfExternalAllocatedMemory(pages * WasmModule::kPageSize); | 2195 ->AdjustAmountOfExternalAllocatedMemory(pages * WasmModule::kPageSize); |
2227 Handle<Object> new_size_object = | 2196 Handle<Object> new_size_object = |
2228 isolate->factory()->NewNumberFromSize(new_size); | 2197 isolate->factory()->NewNumberFromSize(new_size); |
2229 old_buffer->set_byte_length(*new_size_object); | 2198 old_buffer->set_byte_length(*new_size_object); |
2230 new_buffer = old_buffer; | 2199 |
| 2200 SetInstanceMemory(instance, *old_buffer); |
| 2201 Handle<FixedArray> code_table = |
| 2202 instance->get_compiled_module()->code_table(); |
| 2203 RelocateMemoryReferencesInCode(code_table, old_mem_start, old_mem_start, |
| 2204 old_size, new_size); |
| 2205 buffer = old_buffer; |
2231 } else { | 2206 } else { |
2232 const bool enable_guard_regions = false; | 2207 const bool enable_guard_regions = false; |
2233 new_buffer = NewArrayBuffer(isolate, new_size, enable_guard_regions); | 2208 buffer = NewArrayBuffer(isolate, new_size, enable_guard_regions); |
2234 if (new_buffer.is_null()) return new_buffer; | 2209 if (buffer.is_null()) return -1; |
2235 Address new_mem_start = static_cast<Address>(new_buffer->backing_store()); | 2210 Address new_mem_start = static_cast<Address>(buffer->backing_store()); |
2236 if (old_size != 0) { | 2211 if (old_size != 0) { |
2237 memcpy(new_mem_start, old_mem_start, old_size); | 2212 memcpy(new_mem_start, old_mem_start, old_size); |
2238 } | 2213 } |
| 2214 SetInstanceMemory(instance, *buffer); |
| 2215 Handle<FixedArray> code_table = |
| 2216 instance->get_compiled_module()->code_table(); |
| 2217 RelocateMemoryReferencesInCode(code_table, old_mem_start, new_mem_start, |
| 2218 old_size, new_size); |
2239 } | 2219 } |
2240 return new_buffer; | |
2241 } | |
2242 | 2220 |
2243 void UncheckedUpdateInstanceMemory(Isolate* isolate, | 2221 SetInstanceMemory(instance, *buffer); |
2244 Handle<WasmInstanceObject> instance, | 2222 if (instance->has_memory_object()) { |
2245 Address old_mem_start, uint32_t old_size) { | 2223 instance->get_memory_object()->set_buffer(*buffer); |
2246 DCHECK(instance->has_memory_buffer()); | 2224 } |
2247 Handle<JSArrayBuffer> new_buffer(instance->get_memory_buffer()); | |
2248 uint32_t new_size = new_buffer->byte_length()->Number(); | |
2249 DCHECK(new_size <= std::numeric_limits<uint32_t>::max()); | |
2250 Address new_mem_start = static_cast<Address>(new_buffer->backing_store()); | |
2251 DCHECK_NOT_NULL(new_mem_start); | |
2252 Handle<FixedArray> code_table = instance->get_compiled_module()->code_table(); | |
2253 RelocateMemoryReferencesInCode(code_table, old_mem_start, new_mem_start, | |
2254 old_size, new_size); | |
2255 } | |
2256 | 2225 |
2257 int32_t wasm::GrowWebAssemblyMemory(Isolate* isolate, Handle<Object> receiver, | |
2258 uint32_t pages) { | |
2259 DCHECK(WasmJs::IsWasmMemoryObject(isolate, receiver)); | |
2260 Handle<WasmMemoryObject> memory_object(WasmMemoryObject::cast(*receiver)); | |
2261 Handle<WasmInstanceWrapper> instance_wrapper( | |
2262 memory_object->get_instances_link()); | |
2263 DCHECK(WasmInstanceWrapper::IsWasmInstanceWrapper(*instance_wrapper)); | |
2264 DCHECK(instance_wrapper->has_instance()); | |
2265 Handle<WasmInstanceObject> instance = instance_wrapper->instance_object(); | |
2266 DCHECK(IsWasmInstance(*instance)); | |
2267 if (pages == 0) return GetInstanceMemorySize(isolate, instance); | |
2268 uint32_t max_pages = GetMaxInstanceMemorySize(isolate, instance); | |
2269 | |
2270 // Grow memory object buffer and update instances associated with it. | |
2271 MaybeHandle<JSArrayBuffer> memory_buffer = | |
2272 handle(memory_object->get_buffer()); | |
2273 Handle<JSArrayBuffer> old_buffer; | |
2274 uint32_t old_size = 0; | |
2275 Address old_mem_start = nullptr; | |
2276 if (memory_buffer.ToHandle(&old_buffer) && | |
2277 old_buffer->backing_store() != nullptr) { | |
2278 old_size = old_buffer->byte_length()->Number(); | |
2279 old_mem_start = static_cast<Address>(old_buffer->backing_store()); | |
2280 } | |
2281 Handle<JSArrayBuffer> new_buffer = | |
2282 GrowMemoryBuffer(isolate, memory_buffer, pages, max_pages); | |
2283 if (new_buffer.is_null()) return -1; | |
2284 DCHECK(!instance_wrapper->has_previous()); | |
2285 SetInstanceMemory(instance, *new_buffer); | |
2286 UncheckedUpdateInstanceMemory(isolate, instance, old_mem_start, old_size); | |
2287 while (instance_wrapper->has_next()) { | |
2288 instance_wrapper = instance_wrapper->next_wrapper(); | |
2289 DCHECK(WasmInstanceWrapper::IsWasmInstanceWrapper(*instance_wrapper)); | |
2290 Handle<WasmInstanceObject> instance = instance_wrapper->instance_object(); | |
2291 DCHECK(IsWasmInstance(*instance)); | |
2292 SetInstanceMemory(instance, *new_buffer); | |
2293 UncheckedUpdateInstanceMemory(isolate, instance, old_mem_start, old_size); | |
2294 } | |
2295 memory_object->set_buffer(*new_buffer); | |
2296 DCHECK(old_size % WasmModule::kPageSize == 0); | 2226 DCHECK(old_size % WasmModule::kPageSize == 0); |
2297 return (old_size / WasmModule::kPageSize); | 2227 return (old_size / WasmModule::kPageSize); |
2298 } | 2228 } |
2299 | 2229 |
2300 int32_t wasm::GrowMemory(Isolate* isolate, Handle<WasmInstanceObject> instance, | |
2301 uint32_t pages) { | |
2302 if (!IsWasmInstance(*instance)) return -1; | |
2303 if (pages == 0) return GetInstanceMemorySize(isolate, instance); | |
2304 Handle<WasmInstanceObject> instance_obj(WasmInstanceObject::cast(*instance)); | |
2305 if (!instance_obj->has_memory_object()) { | |
2306 // No other instances to grow, grow just the one. | |
2307 MaybeHandle<JSArrayBuffer> instance_buffer = | |
2308 GetInstanceMemory(isolate, instance); | |
2309 Handle<JSArrayBuffer> old_buffer; | |
2310 uint32_t old_size = 0; | |
2311 Address old_mem_start = nullptr; | |
2312 if (instance_buffer.ToHandle(&old_buffer) && | |
2313 old_buffer->backing_store() != nullptr) { | |
2314 old_size = old_buffer->byte_length()->Number(); | |
2315 old_mem_start = static_cast<Address>(old_buffer->backing_store()); | |
2316 } | |
2317 uint32_t max_pages = GetMaxInstanceMemorySize(isolate, instance_obj); | |
2318 Handle<JSArrayBuffer> buffer = | |
2319 GrowMemoryBuffer(isolate, instance_buffer, pages, max_pages); | |
2320 if (buffer.is_null()) return -1; | |
2321 SetInstanceMemory(instance, *buffer); | |
2322 UncheckedUpdateInstanceMemory(isolate, instance, old_mem_start, old_size); | |
2323 DCHECK(old_size % WasmModule::kPageSize == 0); | |
2324 return (old_size / WasmModule::kPageSize); | |
2325 } else { | |
2326 return GrowWebAssemblyMemory( | |
2327 isolate, handle(instance_obj->get_memory_object()), pages); | |
2328 } | |
2329 } | |
2330 | |
2331 void testing::ValidateInstancesChain(Isolate* isolate, | 2230 void testing::ValidateInstancesChain(Isolate* isolate, |
2332 Handle<WasmModuleObject> module_obj, | 2231 Handle<WasmModuleObject> module_obj, |
2333 int instance_count) { | 2232 int instance_count) { |
2334 CHECK_GE(instance_count, 0); | 2233 CHECK_GE(instance_count, 0); |
2335 DisallowHeapAllocation no_gc; | 2234 DisallowHeapAllocation no_gc; |
2336 WasmCompiledModule* compiled_module = module_obj->get_compiled_module(); | 2235 WasmCompiledModule* compiled_module = module_obj->get_compiled_module(); |
2337 CHECK_EQ(JSObject::cast(compiled_module->ptr_to_weak_wasm_module()->value()), | 2236 CHECK_EQ(JSObject::cast(compiled_module->ptr_to_weak_wasm_module()->value()), |
2338 *module_obj); | 2237 *module_obj); |
2339 Object* prev = nullptr; | 2238 Object* prev = nullptr; |
2340 int found_instances = compiled_module->has_weak_owning_instance() ? 1 : 0; | 2239 int found_instances = compiled_module->has_weak_owning_instance() ? 1 : 0; |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2406 MaybeHandle<String> WasmCompiledModule::GetFunctionName( | 2305 MaybeHandle<String> WasmCompiledModule::GetFunctionName( |
2407 Handle<WasmCompiledModule> compiled_module, uint32_t func_index) { | 2306 Handle<WasmCompiledModule> compiled_module, uint32_t func_index) { |
2408 DCHECK_LT(func_index, compiled_module->module()->functions.size()); | 2307 DCHECK_LT(func_index, compiled_module->module()->functions.size()); |
2409 WasmFunction& function = compiled_module->module()->functions[func_index]; | 2308 WasmFunction& function = compiled_module->module()->functions[func_index]; |
2410 Isolate* isolate = compiled_module->GetIsolate(); | 2309 Isolate* isolate = compiled_module->GetIsolate(); |
2411 MaybeHandle<String> string = ExtractStringFromModuleBytes( | 2310 MaybeHandle<String> string = ExtractStringFromModuleBytes( |
2412 isolate, compiled_module, function.name_offset, function.name_length); | 2311 isolate, compiled_module, function.name_offset, function.name_length); |
2413 if (!string.is_null()) return string.ToHandleChecked(); | 2312 if (!string.is_null()) return string.ToHandleChecked(); |
2414 return {}; | 2313 return {}; |
2415 } | 2314 } |
OLD | NEW |