Chromium Code Reviews| 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 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 74 kInternalFunctionIndex | 74 kInternalFunctionIndex |
| 75 }; | 75 }; |
| 76 | 76 |
| 77 // Internal constants for the layout of the module object. | 77 // Internal constants for the layout of the module object. |
| 78 enum WasmInstanceObjectFields { | 78 enum WasmInstanceObjectFields { |
| 79 kWasmCompiledModule = 0, | 79 kWasmCompiledModule = 0, |
| 80 kWasmMemObject, | 80 kWasmMemObject, |
| 81 kWasmMemArrayBuffer, | 81 kWasmMemArrayBuffer, |
| 82 kWasmGlobalsArrayBuffer, | 82 kWasmGlobalsArrayBuffer, |
| 83 kWasmDebugInfo, | 83 kWasmDebugInfo, |
| 84 kWasmMemInstanceWrapper, | |
| 84 kWasmInstanceInternalFieldCount | 85 kWasmInstanceInternalFieldCount |
| 85 }; | 86 }; |
| 86 | 87 |
| 87 byte* raw_buffer_ptr(MaybeHandle<JSArrayBuffer> buffer, int offset) { | 88 byte* raw_buffer_ptr(MaybeHandle<JSArrayBuffer> buffer, int offset) { |
| 88 return static_cast<byte*>(buffer.ToHandleChecked()->backing_store()) + offset; | 89 return static_cast<byte*>(buffer.ToHandleChecked()->backing_store()) + offset; |
| 89 } | 90 } |
| 90 | 91 |
| 91 uint32_t GetMinModuleMemSize(const WasmModule* module) { | 92 uint32_t GetMinModuleMemSize(const WasmModule* module) { |
| 92 return WasmModule::kPageSize * module->min_mem_pages; | 93 return WasmModule::kPageSize * module->min_mem_pages; |
| 93 } | 94 } |
| (...skipping 1007 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1101 table_instances_.reserve(module_->function_tables.size()); | 1102 table_instances_.reserve(module_->function_tables.size()); |
| 1102 for (int index = 0; index < function_table_count; ++index) { | 1103 for (int index = 0; index < function_table_count; ++index) { |
| 1103 table_instances_.push_back({Handle<JSObject>::null(), | 1104 table_instances_.push_back({Handle<JSObject>::null(), |
| 1104 Handle<FixedArray>::null(), | 1105 Handle<FixedArray>::null(), |
| 1105 Handle<FixedArray>::null()}); | 1106 Handle<FixedArray>::null()}); |
| 1106 } | 1107 } |
| 1107 | 1108 |
| 1108 //-------------------------------------------------------------------------- | 1109 //-------------------------------------------------------------------------- |
| 1109 // Process the imports for the module. | 1110 // Process the imports for the module. |
| 1110 //-------------------------------------------------------------------------- | 1111 //-------------------------------------------------------------------------- |
| 1111 int num_imported_functions = ProcessImports(code_table, instance); | 1112 int num_imported_functions = ProcessImports(code_table, instance); |
|
Mircea Trofin
2016/11/09 18:57:09
the call to ProcessImports may setup a memory inst
gdeepti
2016/11/16 05:34:10
Maybe I'm misunderstanding your point here, but se
| |
| 1112 if (num_imported_functions < 0) return nothing; | 1113 if (num_imported_functions < 0) return nothing; |
| 1113 | 1114 |
| 1114 //-------------------------------------------------------------------------- | 1115 //-------------------------------------------------------------------------- |
| 1115 // Process the initialization for the module's globals. | 1116 // Process the initialization for the module's globals. |
| 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 //-------------------------------------------------------------------------- |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1216 } | 1217 } |
| 1217 module_object_->SetInternalField(0, *compiled_module_); | 1218 module_object_->SetInternalField(0, *compiled_module_); |
| 1218 instance->SetInternalField(kWasmCompiledModule, *compiled_module_); | 1219 instance->SetInternalField(kWasmCompiledModule, *compiled_module_); |
| 1219 compiled_module_->set_weak_owning_instance(link_to_owning_instance); | 1220 compiled_module_->set_weak_owning_instance(link_to_owning_instance); |
| 1220 GlobalHandles::MakeWeak(global_handle.location(), | 1221 GlobalHandles::MakeWeak(global_handle.location(), |
| 1221 global_handle.location(), &InstanceFinalizer, | 1222 global_handle.location(), &InstanceFinalizer, |
| 1222 v8::WeakCallbackType::kFinalizer); | 1223 v8::WeakCallbackType::kFinalizer); |
| 1223 } | 1224 } |
| 1224 } | 1225 } |
| 1225 | 1226 |
| 1226 DCHECK(wasm::IsWasmInstance(*instance)); | |
| 1227 Handle<Object> memory_object(instance->GetInternalField(kWasmMemObject), | |
| 1228 isolate_); | |
| 1229 WasmJs::SetWasmMemoryInstance(isolate_, memory_object, instance); | |
| 1230 | |
| 1231 //-------------------------------------------------------------------------- | 1227 //-------------------------------------------------------------------------- |
| 1232 // Run the start function if one was specified. | 1228 // Run the start function if one was specified. |
| 1233 //-------------------------------------------------------------------------- | 1229 //-------------------------------------------------------------------------- |
| 1234 if (module_->start_function_index >= 0) { | 1230 if (module_->start_function_index >= 0) { |
| 1235 HandleScope scope(isolate_); | 1231 HandleScope scope(isolate_); |
| 1236 int start_index = module_->start_function_index; | 1232 int start_index = module_->start_function_index; |
| 1237 Handle<Code> startup_code = | 1233 Handle<Code> startup_code = |
| 1238 code_table->GetValueChecked<Code>(isolate_, start_index); | 1234 code_table->GetValueChecked<Code>(isolate_, start_index); |
| 1239 FunctionSig* sig = module_->functions[start_index].sig; | 1235 FunctionSig* sig = module_->functions[start_index].sig; |
| 1240 Handle<JSFunction> startup_fct = WrapExportCodeAsJSFunction( | 1236 Handle<JSFunction> startup_fct = WrapExportCodeAsJSFunction( |
| (...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1497 } | 1493 } |
| 1498 case kExternalMemory: { | 1494 case kExternalMemory: { |
| 1499 Handle<Object> object = result.ToHandleChecked(); | 1495 Handle<Object> object = result.ToHandleChecked(); |
| 1500 if (!WasmJs::IsWasmMemoryObject(isolate_, object)) { | 1496 if (!WasmJs::IsWasmMemoryObject(isolate_, object)) { |
| 1501 ReportFFIError("memory import must be a WebAssembly.Memory object", | 1497 ReportFFIError("memory import must be a WebAssembly.Memory object", |
| 1502 index, module_name, function_name); | 1498 index, module_name, function_name); |
| 1503 return -1; | 1499 return -1; |
| 1504 } | 1500 } |
| 1505 instance->SetInternalField(kWasmMemObject, *object); | 1501 instance->SetInternalField(kWasmMemObject, *object); |
| 1506 memory_ = WasmJs::GetWasmMemoryArrayBuffer(isolate_, object); | 1502 memory_ = WasmJs::GetWasmMemoryArrayBuffer(isolate_, object); |
| 1503 WasmJs::SetWasmMemoryInstance(isolate_, object, instance); | |
| 1507 break; | 1504 break; |
| 1508 } | 1505 } |
| 1509 case kExternalGlobal: { | 1506 case kExternalGlobal: { |
| 1510 // Global imports are converted to numbers and written into the | 1507 // Global imports are converted to numbers and written into the |
| 1511 // {globals_} array buffer. | 1508 // {globals_} array buffer. |
| 1512 Handle<Object> object = result.ToHandleChecked(); | 1509 Handle<Object> object = result.ToHandleChecked(); |
| 1513 MaybeHandle<Object> number = Object::ToNumber(object); | 1510 MaybeHandle<Object> number = Object::ToNumber(object); |
| 1514 if (number.is_null()) { | 1511 if (number.is_null()) { |
| 1515 ReportFFIError("global import could not be converted to number", | 1512 ReportFFIError("global import could not be converted to number", |
| 1516 index, module_name, function_name); | 1513 index, module_name, function_name); |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1672 instance->GetInternalField(kWasmMemObject), isolate_); | 1669 instance->GetInternalField(kWasmMemObject), isolate_); |
| 1673 if (memory_object->IsUndefined(isolate_)) { | 1670 if (memory_object->IsUndefined(isolate_)) { |
| 1674 // If there was no imported WebAssembly.Memory object, create one. | 1671 // If there was no imported WebAssembly.Memory object, create one. |
| 1675 Handle<JSArrayBuffer> buffer( | 1672 Handle<JSArrayBuffer> buffer( |
| 1676 JSArrayBuffer::cast( | 1673 JSArrayBuffer::cast( |
| 1677 instance->GetInternalField(kWasmMemArrayBuffer)), | 1674 instance->GetInternalField(kWasmMemArrayBuffer)), |
| 1678 isolate_); | 1675 isolate_); |
| 1679 memory_object = | 1676 memory_object = |
| 1680 WasmJs::CreateWasmMemoryObject(isolate_, buffer, false, 0); | 1677 WasmJs::CreateWasmMemoryObject(isolate_, buffer, false, 0); |
| 1681 instance->SetInternalField(kWasmMemObject, *memory_object); | 1678 instance->SetInternalField(kWasmMemObject, *memory_object); |
| 1679 } else { | |
| 1680 DCHECK(WasmJs::IsWasmMemoryObject(isolate_, memory_object)); | |
| 1681 WasmJs::ResetWasmMemoryInstance(isolate_, memory_object); | |
| 1682 } | 1682 } |
| 1683 | 1683 |
| 1684 desc.set_value(memory_object); | 1684 desc.set_value(memory_object); |
| 1685 break; | 1685 break; |
| 1686 } | 1686 } |
| 1687 case kExternalGlobal: { | 1687 case kExternalGlobal: { |
| 1688 // Export the value of the global variable as a number. | 1688 // Export the value of the global variable as a number. |
| 1689 WasmGlobal& global = module_->globals[exp.index]; | 1689 WasmGlobal& global = module_->globals[exp.index]; |
| 1690 double num = 0; | 1690 double num = 0; |
| 1691 switch (global.type) { | 1691 switch (global.type) { |
| (...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2065 ModuleOrigin origin) { | 2065 ModuleOrigin origin) { |
| 2066 ModuleResult result = DecodeWasmModule(isolate, start, end, false, origin); | 2066 ModuleResult result = DecodeWasmModule(isolate, start, end, false, origin); |
| 2067 if (result.ok()) { | 2067 if (result.ok()) { |
| 2068 DCHECK_NOT_NULL(result.val); | 2068 DCHECK_NOT_NULL(result.val); |
| 2069 delete result.val; | 2069 delete result.val; |
| 2070 return true; | 2070 return true; |
| 2071 } | 2071 } |
| 2072 return false; | 2072 return false; |
| 2073 } | 2073 } |
| 2074 | 2074 |
| 2075 void wasm::SetInstanceMemoryObject(Handle<JSObject> instance, | |
| 2076 Handle<Object> mem_object) { | |
| 2077 DCHECK(IsWasmInstance(*instance)); | |
| 2078 instance->SetInternalField(kWasmMemObject, *mem_object); | |
| 2079 } | |
| 2080 | |
| 2075 MaybeHandle<JSArrayBuffer> wasm::GetInstanceMemory(Isolate* isolate, | 2081 MaybeHandle<JSArrayBuffer> wasm::GetInstanceMemory(Isolate* isolate, |
| 2076 Handle<JSObject> instance) { | 2082 Handle<JSObject> instance) { |
| 2077 Object* mem = instance->GetInternalField(kWasmMemArrayBuffer); | 2083 Object* mem = instance->GetInternalField(kWasmMemArrayBuffer); |
| 2078 DCHECK(IsWasmInstance(*instance)); | 2084 DCHECK(IsWasmInstance(*instance)); |
| 2079 if (mem->IsUndefined(isolate)) return MaybeHandle<JSArrayBuffer>(); | 2085 if (mem->IsUndefined(isolate)) return MaybeHandle<JSArrayBuffer>(); |
| 2080 return Handle<JSArrayBuffer>(JSArrayBuffer::cast(mem)); | 2086 return Handle<JSArrayBuffer>(JSArrayBuffer::cast(mem)); |
| 2081 } | 2087 } |
| 2082 | 2088 |
| 2083 void SetInstanceMemory(Handle<JSObject> instance, JSArrayBuffer* buffer) { | 2089 void SetInstanceMemory(Handle<JSObject> instance, JSArrayBuffer* buffer) { |
| 2084 DisallowHeapAllocation no_gc; | 2090 DisallowHeapAllocation no_gc; |
| 2085 DCHECK(IsWasmInstance(*instance)); | 2091 DCHECK(IsWasmInstance(*instance)); |
| 2086 instance->SetInternalField(kWasmMemArrayBuffer, buffer); | 2092 instance->SetInternalField(kWasmMemArrayBuffer, buffer); |
| 2087 WasmCompiledModule* compiled_module = GetCompiledModule(*instance); | 2093 WasmCompiledModule* compiled_module = GetCompiledModule(*instance); |
| 2088 compiled_module->set_ptr_to_memory(buffer); | 2094 compiled_module->set_ptr_to_memory(buffer); |
| 2089 } | 2095 } |
| 2090 | 2096 |
| 2091 int32_t wasm::GetInstanceMemorySize(Isolate* isolate, | 2097 int32_t wasm::GetInstanceMemorySize(Isolate* isolate, |
| 2092 Handle<JSObject> instance) { | 2098 Handle<JSObject> instance) { |
| 2099 DCHECK(IsWasmInstance(*instance)); | |
| 2093 MaybeHandle<JSArrayBuffer> maybe_mem_buffer = | 2100 MaybeHandle<JSArrayBuffer> maybe_mem_buffer = |
| 2094 GetInstanceMemory(isolate, instance); | 2101 GetInstanceMemory(isolate, instance); |
| 2095 Handle<JSArrayBuffer> buffer; | 2102 Handle<JSArrayBuffer> buffer; |
| 2096 if (!maybe_mem_buffer.ToHandle(&buffer)) { | 2103 if (!maybe_mem_buffer.ToHandle(&buffer)) { |
| 2097 return 0; | 2104 return 0; |
| 2098 } else { | 2105 } else { |
| 2099 return buffer->byte_length()->Number() / WasmModule::kPageSize; | 2106 return buffer->byte_length()->Number() / WasmModule::kPageSize; |
| 2100 } | 2107 } |
| 2101 } | 2108 } |
| 2102 | 2109 |
| 2103 uint32_t GetMaxInstanceMemorySize(Isolate* isolate, Handle<JSObject> instance) { | 2110 uint32_t GetMaxInstanceMemorySize(Isolate* isolate, Handle<JSObject> instance) { |
| 2104 uint32_t max_pages = WasmModule::kV8MaxPages; | 2111 uint32_t max_pages = WasmModule::kV8MaxPages; |
| 2105 Handle<Object> memory_object(instance->GetInternalField(kWasmMemObject), | 2112 Handle<Object> memory_object(instance->GetInternalField(kWasmMemObject), |
| 2106 isolate); | 2113 isolate); |
| 2107 if (memory_object->IsUndefined(isolate)) return max_pages; | 2114 if (memory_object->IsUndefined(isolate)) return max_pages; |
| 2108 return WasmJs::GetWasmMemoryMaximumSize(isolate, memory_object); | 2115 return WasmJs::GetWasmMemoryMaximumSize(isolate, memory_object); |
| 2109 } | 2116 } |
| 2110 | 2117 |
| 2111 int32_t wasm::GrowInstanceMemory(Isolate* isolate, Handle<JSObject> instance, | 2118 Handle<JSArrayBuffer> GrowMemoryBuffer(Isolate* isolate, |
| 2112 uint32_t pages) { | 2119 MaybeHandle<JSArrayBuffer> buffer, |
| 2113 if (!IsWasmInstance(*instance)) return -1; | 2120 uint32_t pages, uint32_t max_pages) { |
| 2114 if (pages == 0) return GetInstanceMemorySize(isolate, instance); | 2121 Handle<JSArrayBuffer> old_buffer; |
| 2115 uint32_t max_pages = GetMaxInstanceMemorySize(isolate, instance); | 2122 Address old_mem_start = nullptr; |
| 2116 if (WasmModule::kV8MaxPages < max_pages) return -1; | 2123 uint32_t old_size = 0; |
| 2124 if (buffer.ToHandle(&old_buffer) && old_buffer->backing_store() != nullptr) { | |
| 2125 old_mem_start = static_cast<Address>(old_buffer->backing_store()); | |
| 2126 DCHECK_NOT_NULL(old_mem_start); | |
| 2127 old_size = old_buffer->byte_length()->Number(); | |
| 2128 } | |
| 2129 DCHECK(old_size + pages * WasmModule::kPageSize <= | |
| 2130 std::numeric_limits<uint32_t>::max()); | |
| 2131 uint32_t new_size = old_size + pages * WasmModule::kPageSize; | |
| 2132 if (new_size <= old_size || max_pages * WasmModule::kPageSize < new_size) { | |
| 2133 return Handle<JSArrayBuffer>::null(); | |
| 2134 } | |
| 2135 Handle<JSArrayBuffer> new_buffer = NewArrayBuffer(isolate, new_size); | |
| 2136 Address new_mem_start = static_cast<Address>(new_buffer->backing_store()); | |
| 2137 if (new_buffer.is_null() || new_mem_start == nullptr) { | |
| 2138 return Handle<JSArrayBuffer>::null(); | |
| 2139 } | |
| 2140 if (old_size != 0) memcpy(new_mem_start, old_mem_start, old_size); | |
| 2141 return new_buffer; | |
| 2142 } | |
| 2117 | 2143 |
| 2118 Address old_mem_start = nullptr; | 2144 int32_t UncheckedUpdateInstanceMemory(Isolate* isolate, |
| 2119 uint32_t old_size = 0, new_size = 0; | 2145 Handle<JSObject> instance, |
| 2120 | 2146 Handle<JSArrayBuffer> buffer) { |
| 2121 MaybeHandle<JSArrayBuffer> maybe_mem_buffer = | 2147 MaybeHandle<JSArrayBuffer> maybe_mem_buffer = |
| 2122 GetInstanceMemory(isolate, instance); | 2148 GetInstanceMemory(isolate, instance); |
| 2123 Handle<JSArrayBuffer> old_buffer; | 2149 Handle<JSArrayBuffer> old_buffer; |
| 2124 if (!maybe_mem_buffer.ToHandle(&old_buffer) || | 2150 Address old_mem_start = nullptr; |
| 2125 old_buffer->backing_store() == nullptr) { | 2151 uint32_t old_size = 0; |
| 2126 // If module object does not have linear memory associated with it, | 2152 if (maybe_mem_buffer.ToHandle(&old_buffer) && |
| 2127 // Allocate new array buffer of given size. | 2153 old_buffer->backing_store() != nullptr) { |
| 2128 new_size = pages * WasmModule::kPageSize; | |
| 2129 if (max_pages < pages) return -1; | |
| 2130 } else { | |
| 2131 old_mem_start = static_cast<Address>(old_buffer->backing_store()); | 2154 old_mem_start = static_cast<Address>(old_buffer->backing_store()); |
| 2155 DCHECK_NOT_NULL(old_mem_start); | |
| 2132 old_size = old_buffer->byte_length()->Number(); | 2156 old_size = old_buffer->byte_length()->Number(); |
| 2133 // If the old memory was zero-sized, we should have been in the | |
| 2134 // "undefined" case above. | |
| 2135 DCHECK_NOT_NULL(old_mem_start); | |
| 2136 DCHECK(old_size + pages * WasmModule::kPageSize <= | |
| 2137 std::numeric_limits<uint32_t>::max()); | |
| 2138 new_size = old_size + pages * WasmModule::kPageSize; | |
| 2139 } | 2157 } |
| 2140 | 2158 uint32_t new_size = buffer->byte_length()->Number(); |
| 2141 if (new_size <= old_size || max_pages * WasmModule::kPageSize < new_size) { | 2159 DCHECK(new_size <= std::numeric_limits<uint32_t>::max()); |
| 2142 return -1; | |
| 2143 } | |
| 2144 Handle<JSArrayBuffer> buffer = NewArrayBuffer(isolate, new_size); | |
| 2145 if (buffer.is_null()) return -1; | |
| 2146 Address new_mem_start = static_cast<Address>(buffer->backing_store()); | 2160 Address new_mem_start = static_cast<Address>(buffer->backing_store()); |
| 2147 if (old_size != 0) { | 2161 DCHECK_NOT_NULL(new_mem_start); |
| 2148 memcpy(new_mem_start, old_mem_start, old_size); | |
| 2149 } | |
| 2150 SetInstanceMemory(instance, *buffer); | 2162 SetInstanceMemory(instance, *buffer); |
| 2151 Handle<FixedArray> code_table = GetCompiledModule(*instance)->code_table(); | 2163 Handle<FixedArray> code_table = GetCompiledModule(*instance)->code_table(); |
| 2152 RelocateMemoryReferencesInCode(code_table, old_mem_start, new_mem_start, | 2164 RelocateMemoryReferencesInCode(code_table, old_mem_start, new_mem_start, |
| 2153 old_size, new_size); | 2165 old_size, new_size); |
| 2154 Handle<Object> memory_object(instance->GetInternalField(kWasmMemObject), | |
| 2155 isolate); | |
| 2156 if (!memory_object->IsUndefined(isolate)) { | |
| 2157 WasmJs::SetWasmMemoryArrayBuffer(isolate, memory_object, buffer); | |
| 2158 } | |
| 2159 | |
| 2160 DCHECK(old_size % WasmModule::kPageSize == 0); | 2166 DCHECK(old_size % WasmModule::kPageSize == 0); |
| 2161 return (old_size / WasmModule::kPageSize); | 2167 return (old_size / WasmModule::kPageSize); |
| 2162 } | 2168 } |
| 2163 | 2169 |
| 2170 int32_t wasm::GrowWebAssemblyMemory(Isolate* isolate, | |
|
Mircea Trofin
2016/11/09 18:57:10
please add comment explaining what the return is.
gdeepti
2016/11/16 05:34:10
This is as per Spec for GrowMemory - Return the pr
| |
| 2171 Handle<Object> memory_object, | |
| 2172 uint32_t pages) { | |
| 2173 DCHECK(WasmJs::IsWasmMemoryObject(isolate, memory_object)); | |
| 2174 uint32_t max_pages = WasmJs::GetWasmMemoryMaximumSize(isolate, memory_object); | |
| 2175 if (WasmModule::kV8MaxPages < max_pages) return -1; | |
|
Mircea Trofin
2016/11/09 18:57:10
Should this be a DCHECK rather, and have the calle
gdeepti
2016/11/16 05:34:10
As per the spec, grow_memory should return -1 for
| |
| 2176 Handle<WasmInstanceWrapper> instance_wrapper = | |
| 2177 Handle<WasmInstanceWrapper>::cast( | |
| 2178 WasmJs::GetWasmMemoryInstanceWrapper(isolate, memory_object)); | |
| 2179 DCHECK(WasmInstanceWrapper::IsWasmInstanceWrapper(*instance_wrapper)); | |
| 2180 DCHECK(instance_wrapper->has_instance()); | |
| 2181 Handle<JSObject> instance = instance_wrapper->instance_object(); | |
| 2182 DCHECK(IsWasmInstance(*instance)); | |
| 2183 if (pages == 0) return GetInstanceMemorySize(isolate, instance); | |
|
Mircea Trofin
2016/11/09 18:57:09
why support pages == 0? Should this be an early DC
gdeepti
2016/11/16 05:34:10
The Spec says - "Return the previous memory size i
| |
| 2184 | |
| 2185 // Grow memory object buffer and update instances associated with it. | |
| 2186 MaybeHandle<JSArrayBuffer> old_buffer = | |
| 2187 WasmJs::GetWasmMemoryArrayBuffer(isolate, memory_object); | |
| 2188 Handle<JSArrayBuffer> new_buffer = | |
| 2189 GrowMemoryBuffer(isolate, old_buffer, pages, max_pages); | |
| 2190 if (new_buffer.is_null()) return -1; | |
| 2191 DCHECK(!instance_wrapper->has_previous()); | |
| 2192 int32_t ret = UncheckedUpdateInstanceMemory(isolate, instance, new_buffer); | |
| 2193 while (instance_wrapper->has_next()) { | |
|
Mircea Trofin
2016/11/09 18:57:09
nit: perhaps paranoia, but you could do this in a
gdeepti
2016/11/16 05:34:10
I would prefer to leave this as is, as this seems
| |
| 2194 instance_wrapper = instance_wrapper->next_wrapper(); | |
| 2195 DCHECK(WasmInstanceWrapper::IsWasmInstanceWrapper(*instance_wrapper)); | |
| 2196 Handle<JSObject> instance = instance_wrapper->instance_object(); | |
| 2197 DCHECK(IsWasmInstance(*instance)); | |
| 2198 CHECK_EQ(ret, UncheckedUpdateInstanceMemory(isolate, instance, new_buffer)); | |
| 2199 } | |
| 2200 WasmJs::SetWasmMemoryArrayBuffer(isolate, memory_object, new_buffer); | |
| 2201 return ret; | |
| 2202 } | |
| 2203 | |
| 2204 int32_t wasm::GrowMemory(Isolate* isolate, Handle<JSObject> instance, | |
| 2205 uint32_t pages) { | |
| 2206 if (!IsWasmInstance(*instance)) return -1; | |
| 2207 if (pages == 0) return GetInstanceMemorySize(isolate, instance); | |
| 2208 Handle<Object> obj(instance->GetInternalField(kWasmMemObject), isolate); | |
| 2209 if (obj->IsUndefined(isolate)) { | |
| 2210 // No other instances to grow, grow just the one. | |
| 2211 MaybeHandle<JSArrayBuffer> old_buffer = | |
| 2212 GetInstanceMemory(isolate, instance); | |
| 2213 Handle<JSArrayBuffer> buffer = | |
| 2214 GrowMemoryBuffer(isolate, old_buffer, pages, WasmModule::kV8MaxPages); | |
| 2215 if (buffer.is_null()) return -1; | |
| 2216 return UncheckedUpdateInstanceMemory(isolate, instance, buffer); | |
| 2217 } else { | |
| 2218 return GrowWebAssemblyMemory(isolate, obj, pages); | |
| 2219 } | |
| 2220 } | |
| 2221 | |
| 2164 void testing::ValidateInstancesChain(Isolate* isolate, | 2222 void testing::ValidateInstancesChain(Isolate* isolate, |
| 2165 Handle<JSObject> wasm_module, | 2223 Handle<JSObject> wasm_module, |
| 2166 int instance_count) { | 2224 int instance_count) { |
| 2167 CHECK_GE(instance_count, 0); | 2225 CHECK_GE(instance_count, 0); |
| 2168 DisallowHeapAllocation no_gc; | 2226 DisallowHeapAllocation no_gc; |
| 2169 WasmCompiledModule* compiled_module = | 2227 WasmCompiledModule* compiled_module = |
| 2170 WasmCompiledModule::cast(wasm_module->GetInternalField(0)); | 2228 WasmCompiledModule::cast(wasm_module->GetInternalField(0)); |
| 2171 CHECK_EQ(JSObject::cast(compiled_module->ptr_to_weak_wasm_module()->value()), | 2229 CHECK_EQ(JSObject::cast(compiled_module->ptr_to_weak_wasm_module()->value()), |
| 2172 *wasm_module); | 2230 *wasm_module); |
| 2173 Object* prev = nullptr; | 2231 Object* prev = nullptr; |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2232 CHECK_NOT_NULL(result.val); | 2290 CHECK_NOT_NULL(result.val); |
| 2233 module = const_cast<WasmModule*>(result.val); | 2291 module = const_cast<WasmModule*>(result.val); |
| 2234 } | 2292 } |
| 2235 | 2293 |
| 2236 Handle<WasmModuleWrapper> module_wrapper = | 2294 Handle<WasmModuleWrapper> module_wrapper = |
| 2237 WasmModuleWrapper::New(isolate, module); | 2295 WasmModuleWrapper::New(isolate, module); |
| 2238 | 2296 |
| 2239 compiled_module->set_module_wrapper(module_wrapper); | 2297 compiled_module->set_module_wrapper(module_wrapper); |
| 2240 DCHECK(WasmCompiledModule::IsWasmCompiledModule(*compiled_module)); | 2298 DCHECK(WasmCompiledModule::IsWasmCompiledModule(*compiled_module)); |
| 2241 } | 2299 } |
| 2300 | |
| 2301 static void MemoryInstanceFinalizer(const v8::WeakCallbackInfo<void>& data) { | |
|
Mircea Trofin
2016/11/09 18:57:10
I'd piggy-back on the existing finalizer registrat
gdeepti
2016/11/16 05:34:10
The MemoryInstanceFinalizer is optional, i.e, only
| |
| 2302 JSObject** p = reinterpret_cast<JSObject**>(data.GetParameter()); | |
| 2303 JSObject* instance = *p; | |
| 2304 Isolate* isolate = reinterpret_cast<Isolate*>(data.GetIsolate()); | |
| 2305 Handle<WasmInstanceWrapper> instance_wrapper = | |
| 2306 handle(WasmInstanceWrapper::cast( | |
| 2307 instance->GetInternalField(kWasmMemInstanceWrapper))); | |
| 2308 | |
| 2309 DCHECK(WasmInstanceWrapper::IsWasmInstanceWrapper(*instance_wrapper)); | |
| 2310 DCHECK(instance_wrapper->has_instance()); | |
| 2311 bool has_prev = instance_wrapper->has_previous(); | |
| 2312 bool has_next = instance_wrapper->has_next(); | |
| 2313 Handle<Object> memory_object(instance->GetInternalField(kWasmMemObject), | |
| 2314 isolate); | |
| 2315 | |
| 2316 if (!has_prev && !has_next) { | |
| 2317 if (!memory_object->IsUndefined(isolate)) { | |
| 2318 WasmJs::ResetWasmMemoryInstance(isolate, memory_object); | |
| 2319 } | |
| 2320 GlobalHandles::Destroy(reinterpret_cast<Object**>(p)); | |
| 2321 return; | |
| 2322 } else { | |
| 2323 Handle<WasmInstanceWrapper> next_wrapper, prev_wrapper; | |
| 2324 if (!has_prev) { | |
| 2325 Handle<WasmInstanceWrapper> next_wrapper = | |
| 2326 instance_wrapper->next_wrapper(); | |
| 2327 next_wrapper->reset_previous_wrapper(); | |
| 2328 // As this is the first link in the memory object, destroying | |
| 2329 // without updating memory object would corrupt the instance chain in | |
| 2330 // the memory object. | |
|
Mircea Trofin
2016/11/09 18:57:10
This comment makes me believe even moreso that we
gdeepti
2016/11/16 05:34:10
Agreed, Done.
| |
| 2331 const int kWasmMemObjectInstancesLink = 2; | |
|
Mircea Trofin
2016/11/09 18:57:10
please see my earlier comment about fragility. Ple
gdeepti
2016/11/16 05:34:10
Done.
| |
| 2332 JSObject::cast(*memory_object) | |
| 2333 ->SetInternalField(kWasmMemObjectInstancesLink, *next_wrapper); | |
| 2334 } else if (!has_next) { | |
| 2335 instance_wrapper->previous_wrapper()->reset_next_wrapper(); | |
| 2336 } else { | |
| 2337 DCHECK(has_next && has_prev); | |
| 2338 Handle<WasmInstanceWrapper> prev_wrapper = | |
| 2339 instance_wrapper->previous_wrapper(); | |
| 2340 Handle<WasmInstanceWrapper> next_wrapper = | |
| 2341 instance_wrapper->next_wrapper(); | |
| 2342 prev_wrapper->set_next_wrapper(*next_wrapper); | |
| 2343 next_wrapper->set_previous_wrapper(*prev_wrapper); | |
| 2344 } | |
| 2345 // Reset to avoid dangling pointers | |
| 2346 instance_wrapper->reset(); | |
| 2347 GlobalHandles::Destroy(reinterpret_cast<Object**>(p)); | |
| 2348 } | |
| 2349 } | |
| 2350 | |
| 2351 Handle<WasmInstanceWrapper> WasmInstanceWrapper::New( | |
| 2352 Isolate* isolate, Handle<JSObject> instance) { | |
| 2353 Handle<FixedArray> array = | |
| 2354 isolate->factory()->NewFixedArray(kWrapperPropertyCount, TENURED); | |
| 2355 Handle<WasmInstanceWrapper> instance_wrapper( | |
| 2356 reinterpret_cast<WasmInstanceWrapper*>(*array), isolate); | |
| 2357 instance_wrapper->set_instance_object(instance, isolate); | |
| 2358 return instance_wrapper; | |
| 2359 } | |
| 2360 | |
| 2361 bool WasmInstanceWrapper::IsWasmInstanceWrapper(Object* obj) { | |
| 2362 if (!obj->IsFixedArray()) return false; | |
| 2363 FixedArray* array = FixedArray::cast(obj); | |
| 2364 if (array->length() != kWrapperPropertyCount) return false; | |
| 2365 if (!array->get(kWrapperInstanceObject)->IsWeakCell()) return false; | |
| 2366 Isolate* isolate = array->GetIsolate(); | |
| 2367 if (!array->get(kNextInstanceWrapper)->IsUndefined(isolate) && | |
| 2368 !array->get(kNextInstanceWrapper)->IsFixedArray()) | |
| 2369 return false; | |
| 2370 if (!array->get(kPreviousInstanceWrapper)->IsUndefined(isolate) && | |
| 2371 !array->get(kPreviousInstanceWrapper)->IsFixedArray()) | |
| 2372 return false; | |
| 2373 return true; | |
| 2374 } | |
| 2375 | |
| 2376 void WasmInstanceWrapper::set_instance_object(Handle<JSObject> instance, | |
| 2377 Isolate* isolate) { | |
| 2378 Handle<Object> global_handle = isolate->global_handles()->Create(*instance); | |
| 2379 Handle<WeakCell> cell = isolate->factory()->NewWeakCell(instance); | |
| 2380 set(kWrapperInstanceObject, *cell); | |
| 2381 GlobalHandles::MakeWeak(global_handle.location(), global_handle.location(), | |
| 2382 &MemoryInstanceFinalizer, | |
|
bradnelson
2016/11/09 01:40:11
You should be able to piggy-back this on the exist
gdeepti
2016/11/16 05:34:10
Done.
| |
| 2383 v8::WeakCallbackType::kFinalizer); | |
| 2384 } | |
| OLD | NEW |