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 |