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