Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(218)

Side by Side Diff: src/wasm/wasm-module.cc

Issue 2471883003: [wasm] WebAssembly.Memory object can be referenced by multiple Instance objects. (Closed)
Patch Set: Rebase, add Dcheck Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698