| 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 818 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 829 } | 829 } |
| 830 | 830 |
| 831 // Create the compiled module object, and populate with compiled functions | 831 // Create the compiled module object, and populate with compiled functions |
| 832 // and information needed at instantiation time. This object needs to be | 832 // and information needed at instantiation time. This object needs to be |
| 833 // serializable. Instantiation may occur off a deserialized version of this | 833 // serializable. Instantiation may occur off a deserialized version of this |
| 834 // object. | 834 // object. |
| 835 Handle<WasmCompiledModule> ret = | 835 Handle<WasmCompiledModule> ret = |
| 836 WasmCompiledModule::New(isolate, module_wrapper); | 836 WasmCompiledModule::New(isolate, module_wrapper); |
| 837 ret->set_code_table(code_table); | 837 ret->set_code_table(code_table); |
| 838 ret->set_min_mem_pages(min_mem_pages); | 838 ret->set_min_mem_pages(min_mem_pages); |
| 839 ret->set_max_mem_pages(max_mem_pages); |
| 839 if (function_table_count > 0) { | 840 if (function_table_count > 0) { |
| 840 ret->set_function_tables(function_tables); | 841 ret->set_function_tables(function_tables); |
| 841 ret->set_empty_function_tables(function_tables); | 842 ret->set_empty_function_tables(function_tables); |
| 842 } | 843 } |
| 843 | 844 |
| 844 // Compile JS->WASM wrappers for exported functions. | 845 // Compile JS->WASM wrappers for exported functions. |
| 845 int func_index = 0; | 846 int func_index = 0; |
| 846 for (auto exp : export_table) { | 847 for (auto exp : export_table) { |
| 847 if (exp.kind != kExternalFunction) continue; | 848 if (exp.kind != kExternalFunction) continue; |
| 848 Handle<Code> wasm_code = | 849 Handle<Code> wasm_code = |
| (...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1116 //-------------------------------------------------------------------------- | 1117 //-------------------------------------------------------------------------- |
| 1117 InitGlobals(); | 1118 InitGlobals(); |
| 1118 | 1119 |
| 1119 //-------------------------------------------------------------------------- | 1120 //-------------------------------------------------------------------------- |
| 1120 // Set up the memory for the new instance. | 1121 // Set up the memory for the new instance. |
| 1121 //-------------------------------------------------------------------------- | 1122 //-------------------------------------------------------------------------- |
| 1122 MaybeHandle<JSArrayBuffer> old_memory; | 1123 MaybeHandle<JSArrayBuffer> old_memory; |
| 1123 | 1124 |
| 1124 uint32_t min_mem_pages = module_->min_mem_pages; | 1125 uint32_t min_mem_pages = module_->min_mem_pages; |
| 1125 isolate_->counters()->wasm_min_mem_pages_count()->AddSample(min_mem_pages); | 1126 isolate_->counters()->wasm_min_mem_pages_count()->AddSample(min_mem_pages); |
| 1126 // TODO(wasm): re-enable counter for max_mem_pages when we use that field. | |
| 1127 | 1127 |
| 1128 if (!memory_.is_null()) { | 1128 if (!memory_.is_null()) { |
| 1129 // Set externally passed ArrayBuffer non neuterable. | 1129 // Set externally passed ArrayBuffer non neuterable. |
| 1130 memory_->set_is_neuterable(false); | 1130 memory_->set_is_neuterable(false); |
| 1131 } else if (min_mem_pages > 0) { | 1131 } else if (min_mem_pages > 0) { |
| 1132 memory_ = AllocateMemory(min_mem_pages); | 1132 memory_ = AllocateMemory(min_mem_pages); |
| 1133 if (memory_.is_null()) return nothing; // failed to allocate memory | 1133 if (memory_.is_null()) return nothing; // failed to allocate memory |
| 1134 } | 1134 } |
| 1135 | 1135 |
| 1136 if (!memory_.is_null()) { | 1136 if (!memory_.is_null()) { |
| (...skipping 532 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1669 case kExternalMemory: { | 1669 case kExternalMemory: { |
| 1670 // Export the memory as a WebAssembly.Memory object. | 1670 // Export the memory as a WebAssembly.Memory object. |
| 1671 Handle<Object> memory_object( | 1671 Handle<Object> memory_object( |
| 1672 instance->GetInternalField(kWasmMemObject), isolate_); | 1672 instance->GetInternalField(kWasmMemObject), isolate_); |
| 1673 if (memory_object->IsUndefined(isolate_)) { | 1673 if (memory_object->IsUndefined(isolate_)) { |
| 1674 // If there was no imported WebAssembly.Memory object, create one. | 1674 // If there was no imported WebAssembly.Memory object, create one. |
| 1675 Handle<JSArrayBuffer> buffer( | 1675 Handle<JSArrayBuffer> buffer( |
| 1676 JSArrayBuffer::cast( | 1676 JSArrayBuffer::cast( |
| 1677 instance->GetInternalField(kWasmMemArrayBuffer)), | 1677 instance->GetInternalField(kWasmMemArrayBuffer)), |
| 1678 isolate_); | 1678 isolate_); |
| 1679 memory_object = | 1679 memory_object = WasmJs::CreateWasmMemoryObject( |
| 1680 WasmJs::CreateWasmMemoryObject(isolate_, buffer, false, 0); | 1680 isolate_, buffer, (module_->max_mem_pages != 0), |
| 1681 module_->max_mem_pages); |
| 1681 instance->SetInternalField(kWasmMemObject, *memory_object); | 1682 instance->SetInternalField(kWasmMemObject, *memory_object); |
| 1682 } | 1683 } |
| 1683 | 1684 |
| 1684 desc.set_value(memory_object); | 1685 desc.set_value(memory_object); |
| 1685 break; | 1686 break; |
| 1686 } | 1687 } |
| 1687 case kExternalGlobal: { | 1688 case kExternalGlobal: { |
| 1688 // Export the value of the global variable as a number. | 1689 // Export the value of the global variable as a number. |
| 1689 WasmGlobal& global = module_->globals[exp.index]; | 1690 WasmGlobal& global = module_->globals[exp.index]; |
| 1690 double num = 0; | 1691 double num = 0; |
| (...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2094 GetInstanceMemory(isolate, instance); | 2095 GetInstanceMemory(isolate, instance); |
| 2095 Handle<JSArrayBuffer> buffer; | 2096 Handle<JSArrayBuffer> buffer; |
| 2096 if (!maybe_mem_buffer.ToHandle(&buffer)) { | 2097 if (!maybe_mem_buffer.ToHandle(&buffer)) { |
| 2097 return 0; | 2098 return 0; |
| 2098 } else { | 2099 } else { |
| 2099 return buffer->byte_length()->Number() / WasmModule::kPageSize; | 2100 return buffer->byte_length()->Number() / WasmModule::kPageSize; |
| 2100 } | 2101 } |
| 2101 } | 2102 } |
| 2102 | 2103 |
| 2103 uint32_t GetMaxInstanceMemorySize(Isolate* isolate, Handle<JSObject> instance) { | 2104 uint32_t GetMaxInstanceMemorySize(Isolate* isolate, Handle<JSObject> instance) { |
| 2104 uint32_t max_pages = WasmModule::kV8MaxPages; | |
| 2105 Handle<Object> memory_object(instance->GetInternalField(kWasmMemObject), | 2105 Handle<Object> memory_object(instance->GetInternalField(kWasmMemObject), |
| 2106 isolate); | 2106 isolate); |
| 2107 if (memory_object->IsUndefined(isolate)) return max_pages; | 2107 if (!memory_object->IsUndefined(isolate)) { |
| 2108 return WasmJs::GetWasmMemoryMaximumSize(isolate, memory_object); | 2108 uint32_t mem_obj_max = |
| 2109 WasmJs::GetWasmMemoryMaximumSize(isolate, memory_object); |
| 2110 if (mem_obj_max != 0) return mem_obj_max; |
| 2111 } |
| 2112 uint32_t compiled_max_pages = GetCompiledModule(*instance)->max_mem_pages(); |
| 2113 isolate->counters()->wasm_max_mem_pages_count()->AddSample( |
| 2114 compiled_max_pages); |
| 2115 if (compiled_max_pages != 0) return compiled_max_pages; |
| 2116 return WasmModule::kV8MaxPages; |
| 2109 } | 2117 } |
| 2110 | 2118 |
| 2111 int32_t wasm::GrowInstanceMemory(Isolate* isolate, Handle<JSObject> instance, | 2119 int32_t wasm::GrowInstanceMemory(Isolate* isolate, Handle<JSObject> instance, |
| 2112 uint32_t pages) { | 2120 uint32_t pages) { |
| 2113 if (!IsWasmInstance(*instance)) return -1; | 2121 if (!IsWasmInstance(*instance)) return -1; |
| 2114 if (pages == 0) return GetInstanceMemorySize(isolate, instance); | 2122 if (pages == 0) return GetInstanceMemorySize(isolate, instance); |
| 2115 uint32_t max_pages = GetMaxInstanceMemorySize(isolate, instance); | 2123 uint32_t max_pages = GetMaxInstanceMemorySize(isolate, instance); |
| 2116 if (WasmModule::kV8MaxPages < max_pages) return -1; | |
| 2117 | 2124 |
| 2118 Address old_mem_start = nullptr; | 2125 Address old_mem_start = nullptr; |
| 2119 uint32_t old_size = 0, new_size = 0; | 2126 uint32_t old_size = 0, new_size = 0; |
| 2120 | 2127 |
| 2121 MaybeHandle<JSArrayBuffer> maybe_mem_buffer = | 2128 MaybeHandle<JSArrayBuffer> maybe_mem_buffer = |
| 2122 GetInstanceMemory(isolate, instance); | 2129 GetInstanceMemory(isolate, instance); |
| 2123 Handle<JSArrayBuffer> old_buffer; | 2130 Handle<JSArrayBuffer> old_buffer; |
| 2124 if (!maybe_mem_buffer.ToHandle(&old_buffer) || | 2131 if (!maybe_mem_buffer.ToHandle(&old_buffer) || |
| 2125 old_buffer->backing_store() == nullptr) { | 2132 old_buffer->backing_store() == nullptr) { |
| 2126 // If module object does not have linear memory associated with it, | 2133 // If module object does not have linear memory associated with it, |
| 2127 // Allocate new array buffer of given size. | 2134 // Allocate new array buffer of given size. |
| 2128 new_size = pages * WasmModule::kPageSize; | 2135 new_size = pages * WasmModule::kPageSize; |
| 2129 if (max_pages < pages) return -1; | 2136 if (max_pages < pages) return -1; |
| 2130 } else { | 2137 } else { |
| 2131 old_mem_start = static_cast<Address>(old_buffer->backing_store()); | 2138 old_mem_start = static_cast<Address>(old_buffer->backing_store()); |
| 2132 old_size = old_buffer->byte_length()->Number(); | 2139 old_size = old_buffer->byte_length()->Number(); |
| 2133 // If the old memory was zero-sized, we should have been in the | 2140 // If the old memory was zero-sized, we should have been in the |
| 2134 // "undefined" case above. | 2141 // "undefined" case above. |
| 2135 DCHECK_NOT_NULL(old_mem_start); | 2142 DCHECK_NOT_NULL(old_mem_start); |
| 2136 DCHECK(old_size + pages * WasmModule::kPageSize <= | 2143 DCHECK(old_size + pages * WasmModule::kPageSize <= |
| 2137 std::numeric_limits<uint32_t>::max()); | 2144 std::numeric_limits<uint32_t>::max()); |
| 2138 new_size = old_size + pages * WasmModule::kPageSize; | 2145 new_size = old_size + pages * WasmModule::kPageSize; |
| 2139 } | 2146 } |
| 2140 | 2147 |
| 2141 if (new_size <= old_size || max_pages * WasmModule::kPageSize < new_size) { | 2148 if (new_size <= old_size || max_pages * WasmModule::kPageSize < new_size || |
| 2149 WasmModule::kV8MaxPages * WasmModule::kPageSize < new_size) { |
| 2142 return -1; | 2150 return -1; |
| 2143 } | 2151 } |
| 2144 Handle<JSArrayBuffer> buffer = NewArrayBuffer(isolate, new_size); | 2152 Handle<JSArrayBuffer> buffer = NewArrayBuffer(isolate, new_size); |
| 2145 if (buffer.is_null()) return -1; | 2153 if (buffer.is_null()) return -1; |
| 2146 Address new_mem_start = static_cast<Address>(buffer->backing_store()); | 2154 Address new_mem_start = static_cast<Address>(buffer->backing_store()); |
| 2147 if (old_size != 0) { | 2155 if (old_size != 0) { |
| 2148 memcpy(new_mem_start, old_mem_start, old_size); | 2156 memcpy(new_mem_start, old_mem_start, old_size); |
| 2149 } | 2157 } |
| 2150 SetInstanceMemory(instance, *buffer); | 2158 SetInstanceMemory(instance, *buffer); |
| 2151 Handle<FixedArray> code_table = GetCompiledModule(*instance)->code_table(); | 2159 Handle<FixedArray> code_table = GetCompiledModule(*instance)->code_table(); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2232 CHECK_NOT_NULL(result.val); | 2240 CHECK_NOT_NULL(result.val); |
| 2233 module = const_cast<WasmModule*>(result.val); | 2241 module = const_cast<WasmModule*>(result.val); |
| 2234 } | 2242 } |
| 2235 | 2243 |
| 2236 Handle<WasmModuleWrapper> module_wrapper = | 2244 Handle<WasmModuleWrapper> module_wrapper = |
| 2237 WasmModuleWrapper::New(isolate, module); | 2245 WasmModuleWrapper::New(isolate, module); |
| 2238 | 2246 |
| 2239 compiled_module->set_module_wrapper(module_wrapper); | 2247 compiled_module->set_module_wrapper(module_wrapper); |
| 2240 DCHECK(WasmCompiledModule::IsWasmCompiledModule(*compiled_module)); | 2248 DCHECK(WasmCompiledModule::IsWasmCompiledModule(*compiled_module)); |
| 2241 } | 2249 } |
| OLD | NEW |