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 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 107 void ReplaceReferenceInCode(Handle<Code> code, Handle<Object> old_ref, | 107 void ReplaceReferenceInCode(Handle<Code> code, Handle<Object> old_ref, | 
| 108 Handle<Object> new_ref) { | 108 Handle<Object> new_ref) { | 
| 109 for (RelocIterator it(*code, 1 << RelocInfo::EMBEDDED_OBJECT); !it.done(); | 109 for (RelocIterator it(*code, 1 << RelocInfo::EMBEDDED_OBJECT); !it.done(); | 
| 110 it.next()) { | 110 it.next()) { | 
| 111 if (it.rinfo()->target_object() == *old_ref) { | 111 if (it.rinfo()->target_object() == *old_ref) { | 
| 112 it.rinfo()->set_target_object(*new_ref); | 112 it.rinfo()->set_target_object(*new_ref); | 
| 113 } | 113 } | 
| 114 } | 114 } | 
| 115 } | 115 } | 
| 116 | 116 | 
| 117 Handle<JSArrayBuffer> NewArrayBuffer(Isolate* isolate, size_t size) { | 117 #if V8_HOST_ARCH_64_BIT | 
| 118 if (size > (WasmModule::kV8MaxPages * WasmModule::kPageSize)) { | 118 static void MemoryFinalizer(const v8::WeakCallbackInfo<void>& data) { | 
| 119 // TODO(titzer): lift restriction on maximum memory allocated here. | 119 JSArrayBuffer** p = reinterpret_cast<JSArrayBuffer**>(data.GetParameter()); | 
| 120 return Handle<JSArrayBuffer>::null(); | 120 JSArrayBuffer* buffer = *p; | 
| 121 } | |
| 122 void* memory = isolate->array_buffer_allocator()->Allocate(size); | |
| 123 if (memory == nullptr) { | |
| 124 return Handle<JSArrayBuffer>::null(); | |
| 125 } | |
| 126 | 121 | 
| 127 #if DEBUG | 122 void* memory = buffer->backing_store(); | 
| 128 // Double check the API allocator actually zero-initialized the memory. | 123 base::OS::Free(memory, | 
| 129 const byte* bytes = reinterpret_cast<const byte*>(memory); | 124 RoundUp(kWasmMaxHeapOffset, base::OS::CommitPageSize())); | 
| 130 for (size_t i = 0; i < size; ++i) { | 125 | 
| 131 DCHECK_EQ(0, bytes[i]); | 126 data.GetIsolate()->AdjustAmountOfExternalAllocatedMemory( | 
| 132 } | 127 -buffer->byte_length()->Number()); | 
| 128 | |
| 129 GlobalHandles::Destroy(reinterpret_cast<Object**>(p)); | |
| 130 } | |
| 133 #endif | 131 #endif | 
| 134 | 132 | 
| 135 Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer(); | 133 void* TryAllocateBackingStore(Isolate* isolate, size_t size, bool guard) { | 
| 136 JSArrayBuffer::Setup(buffer, isolate, false, memory, static_cast<int>(size)); | 134 if (guard) { | 
| 
 
titzer
2016/11/07 19:54:53
I think this needs to be TARGET_ARCH.
How about g
 
Eric Holk
2016/11/08 23:58:15
Done. I also updated the help text for --wasm_guar
 
 | |
| 137 buffer->set_is_neuterable(false); | 135 #if V8_HOST_ARCH_64_BIT | 
| 138 return buffer; | 136 void* memory; | 
| 137 // TODO(eholk): On Windows we want to make sure we don't commit the guard | |
| 138 // pages yet. | |
| 139 | |
| 140 // We always allocate the largest possible offset into the heap, so the | |
| 141 // addressable memory after the guard page can be made inaccessible. | |
| 142 const size_t alloc_size = | |
| 143 RoundUp(kWasmMaxHeapOffset, base::OS::CommitPageSize()); | |
| 144 DCHECK_EQ(0, size % base::OS::CommitPageSize()); | |
| 145 | |
| 146 size_t allocated_size = 0; | |
| 147 const bool is_executable = false; | |
| 148 memory = base::OS::Allocate(alloc_size, &allocated_size, is_executable); | |
| 149 if (allocated_size < alloc_size) { | |
| 150 base::OS::Free(memory, allocated_size); | |
| 151 return nullptr; | |
| 152 } | |
| 153 | |
| 154 if (memory == nullptr) { | |
| 155 return nullptr; | |
| 156 } | |
| 157 | |
| 158 byte* bytes = reinterpret_cast<byte*>(memory); | |
| 159 base::OS::Guard(bytes + size, alloc_size - size); | |
| 160 | |
| 161 reinterpret_cast<v8::Isolate*>(isolate) | |
| 162 ->AdjustAmountOfExternalAllocatedMemory(size); | |
| 163 | |
| 164 return memory; | |
| 165 #else | |
| 166 DCHECK(false && "Guard pages are not supported on 32-bit systems"); | |
| 167 return nullptr; | |
| 168 #endif | |
| 169 } else { | |
| 170 void* memory = isolate->array_buffer_allocator()->Allocate(size); | |
| 171 return memory; | |
| 172 } | |
| 139 } | 173 } | 
| 140 | 174 | 
| 141 void RelocateMemoryReferencesInCode(Handle<FixedArray> code_table, | 175 void RelocateMemoryReferencesInCode(Handle<FixedArray> code_table, | 
| 142 Address old_start, Address start, | 176 Address old_start, Address start, | 
| 143 uint32_t prev_size, uint32_t new_size) { | 177 uint32_t prev_size, uint32_t new_size) { | 
| 144 for (int i = 0; i < code_table->length(); ++i) { | 178 for (int i = 0; i < code_table->length(); ++i) { | 
| 145 DCHECK(code_table->get(i)->IsCode()); | 179 DCHECK(code_table->get(i)->IsCode()); | 
| 146 Handle<Code> code = Handle<Code>(Code::cast(code_table->get(i))); | 180 Handle<Code> code = Handle<Code>(Code::cast(code_table->get(i))); | 
| 147 AllowDeferredHandleDereference embedding_raw_address; | 181 AllowDeferredHandleDereference embedding_raw_address; | 
| 148 int mask = (1 << RelocInfo::WASM_MEMORY_REFERENCE) | | 182 int mask = (1 << RelocInfo::WASM_MEMORY_REFERENCE) | | 
| (...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 624 TRACE_CHAIN(WasmCompiledModule::cast(wasm_module->GetInternalField(0))); | 658 TRACE_CHAIN(WasmCompiledModule::cast(wasm_module->GetInternalField(0))); | 
| 625 TRACE("}\n"); | 659 TRACE("}\n"); | 
| 626 } | 660 } | 
| 627 compiled_module->reset_weak_owning_instance(); | 661 compiled_module->reset_weak_owning_instance(); | 
| 628 GlobalHandles::Destroy(reinterpret_cast<Object**>(p)); | 662 GlobalHandles::Destroy(reinterpret_cast<Object**>(p)); | 
| 629 TRACE("}\n"); | 663 TRACE("}\n"); | 
| 630 } | 664 } | 
| 631 | 665 | 
| 632 } // namespace | 666 } // namespace | 
| 633 | 667 | 
| 668 Handle<JSArrayBuffer> wasm::NewArrayBuffer(Isolate* isolate, size_t size, | |
| 669 bool enable_guard_regions) { | |
| 
 
titzer
2016/11/07 19:54:52
I like this name better. Can we make the header fi
 
Eric Holk
2016/11/08 23:58:15
Done.
 
 | |
| 670 if (size > (WasmModule::kV8MaxPages * WasmModule::kPageSize)) { | |
| 671 // TODO(titzer): lift restriction on maximum memory allocated here. | |
| 672 return Handle<JSArrayBuffer>::null(); | |
| 673 } | |
| 674 | |
| 675 void* memory = TryAllocateBackingStore(isolate, size, enable_guard_regions); | |
| 676 bool is_external = enable_guard_regions; | |
| 
 
titzer
2016/11/07 19:54:52
What about making is_external a return value from
 
Eric Holk
2016/11/08 23:58:15
Done, although it seems like V8_TARGET_ARCH_64_BIT
 
 | |
| 677 | |
| 678 if (memory == nullptr) { | |
| 679 return Handle<JSArrayBuffer>::null(); | |
| 680 } | |
| 681 | |
| 682 #if DEBUG | |
| 683 // Double check the API allocator actually zero-initialized the memory. | |
| 684 const byte* bytes = reinterpret_cast<const byte*>(memory); | |
| 685 for (size_t i = 0; i < size; ++i) { | |
| 686 DCHECK_EQ(0, bytes[i]); | |
| 687 } | |
| 688 #endif | |
| 689 | |
| 690 Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer(); | |
| 691 JSArrayBuffer::Setup(buffer, isolate, is_external, memory, | |
| 692 static_cast<int>(size)); | |
| 693 buffer->set_is_neuterable(false); | |
| 694 buffer->set_has_guard_region(enable_guard_regions); | |
| 695 | |
| 696 #if V8_HOST_ARCH_64_BIT | |
| 697 if (is_external) { | |
| 698 // We mark the buffer as external if we allocated it here with guard | |
| 699 // pages. That means we need to arrange for it to be freed. | |
| 700 | |
| 701 // TODO(eholk): Finalizers may not run when the main thread is shutting | |
| 702 // down, which means we may leak memory here. | |
| 703 Handle<Object> global_handle = isolate->global_handles()->Create(*buffer); | |
| 704 GlobalHandles::MakeWeak(global_handle.location(), global_handle.location(), | |
| 705 &MemoryFinalizer, v8::WeakCallbackType::kFinalizer); | |
| 706 } | |
| 707 #endif | |
| 708 | |
| 709 return buffer; | |
| 710 } | |
| 711 | |
| 634 const char* wasm::SectionName(WasmSectionCode code) { | 712 const char* wasm::SectionName(WasmSectionCode code) { | 
| 635 switch (code) { | 713 switch (code) { | 
| 636 case kUnknownSectionCode: | 714 case kUnknownSectionCode: | 
| 637 return "Unknown"; | 715 return "Unknown"; | 
| 638 case kTypeSectionCode: | 716 case kTypeSectionCode: | 
| 639 return "Type"; | 717 return "Type"; | 
| 640 case kImportSectionCode: | 718 case kImportSectionCode: | 
| 641 return "Import"; | 719 return "Import"; | 
| 642 case kFunctionSectionCode: | 720 case kFunctionSectionCode: | 
| 643 return "Function"; | 721 return "Function"; | 
| (...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1069 Handle<JSObject> instance = factory->NewJSObjectFromMap(map, TENURED); | 1147 Handle<JSObject> instance = factory->NewJSObjectFromMap(map, TENURED); | 
| 1070 instance->SetInternalField(kWasmMemObject, | 1148 instance->SetInternalField(kWasmMemObject, | 
| 1071 isolate_->heap()->undefined_value()); | 1149 isolate_->heap()->undefined_value()); | 
| 1072 | 1150 | 
| 1073 //-------------------------------------------------------------------------- | 1151 //-------------------------------------------------------------------------- | 
| 1074 // Set up the globals for the new instance. | 1152 // Set up the globals for the new instance. | 
| 1075 //-------------------------------------------------------------------------- | 1153 //-------------------------------------------------------------------------- | 
| 1076 MaybeHandle<JSArrayBuffer> old_globals; | 1154 MaybeHandle<JSArrayBuffer> old_globals; | 
| 1077 uint32_t globals_size = module_->globals_size; | 1155 uint32_t globals_size = module_->globals_size; | 
| 1078 if (globals_size > 0) { | 1156 if (globals_size > 0) { | 
| 1157 const bool enable_guard_regions = false; | |
| 1079 Handle<JSArrayBuffer> global_buffer = | 1158 Handle<JSArrayBuffer> global_buffer = | 
| 1080 NewArrayBuffer(isolate_, globals_size); | 1159 NewArrayBuffer(isolate_, globals_size, enable_guard_regions); | 
| 1081 globals_ = global_buffer; | 1160 globals_ = global_buffer; | 
| 1082 if (globals_.is_null()) { | 1161 if (globals_.is_null()) { | 
| 1083 thrower_->RangeError("Out of memory: wasm globals"); | 1162 thrower_->RangeError("Out of memory: wasm globals"); | 
| 1084 return nothing; | 1163 return nothing; | 
| 1085 } | 1164 } | 
| 1086 Address old_address = owner.is_null() | 1165 Address old_address = owner.is_null() | 
| 1087 ? nullptr | 1166 ? nullptr | 
| 1088 : GetGlobalStartAddressFromCodeTemplate( | 1167 : GetGlobalStartAddressFromCodeTemplate( | 
| 1089 isolate_->heap()->undefined_value(), | 1168 isolate_->heap()->undefined_value(), | 
| 1090 JSObject::cast(*owner.ToHandleChecked())); | 1169 JSObject::cast(*owner.ToHandleChecked())); | 
| (...skipping 30 matching lines...) Expand all Loading... | |
| 1121 //-------------------------------------------------------------------------- | 1200 //-------------------------------------------------------------------------- | 
| 1122 MaybeHandle<JSArrayBuffer> old_memory; | 1201 MaybeHandle<JSArrayBuffer> old_memory; | 
| 1123 | 1202 | 
| 1124 uint32_t min_mem_pages = module_->min_mem_pages; | 1203 uint32_t min_mem_pages = module_->min_mem_pages; | 
| 1125 isolate_->counters()->wasm_min_mem_pages_count()->AddSample(min_mem_pages); | 1204 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. | 1205 // TODO(wasm): re-enable counter for max_mem_pages when we use that field. | 
| 1127 | 1206 | 
| 1128 if (!memory_.is_null()) { | 1207 if (!memory_.is_null()) { | 
| 1129 // Set externally passed ArrayBuffer non neuterable. | 1208 // Set externally passed ArrayBuffer non neuterable. | 
| 1130 memory_->set_is_neuterable(false); | 1209 memory_->set_is_neuterable(false); | 
| 1210 | |
| 1211 DCHECK_IMPLIES(FLAG_wasm_guard_pages, module_->origin == kAsmJsOrigin || | |
| 1212 memory_->has_guard_region()); | |
| 1131 } else if (min_mem_pages > 0) { | 1213 } else if (min_mem_pages > 0) { | 
| 1132 memory_ = AllocateMemory(min_mem_pages); | 1214 memory_ = AllocateMemory(min_mem_pages); | 
| 1133 if (memory_.is_null()) return nothing; // failed to allocate memory | 1215 if (memory_.is_null()) return nothing; // failed to allocate memory | 
| 1134 } | 1216 } | 
| 1135 | 1217 | 
| 1136 if (!memory_.is_null()) { | 1218 if (!memory_.is_null()) { | 
| 1137 instance->SetInternalField(kWasmMemArrayBuffer, *memory_); | 1219 instance->SetInternalField(kWasmMemArrayBuffer, *memory_); | 
| 1138 Address mem_start = static_cast<Address>(memory_->backing_store()); | 1220 Address mem_start = static_cast<Address>(memory_->backing_store()); | 
| 1139 uint32_t mem_size = | 1221 uint32_t mem_size = | 
| 1140 static_cast<uint32_t>(memory_->byte_length()->Number()); | 1222 static_cast<uint32_t>(memory_->byte_length()->Number()); | 
| (...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1572 } | 1654 } | 
| 1573 } | 1655 } | 
| 1574 } | 1656 } | 
| 1575 | 1657 | 
| 1576 // Allocate memory for a module instance as a new JSArrayBuffer. | 1658 // Allocate memory for a module instance as a new JSArrayBuffer. | 
| 1577 Handle<JSArrayBuffer> AllocateMemory(uint32_t min_mem_pages) { | 1659 Handle<JSArrayBuffer> AllocateMemory(uint32_t min_mem_pages) { | 
| 1578 if (min_mem_pages > WasmModule::kV8MaxPages) { | 1660 if (min_mem_pages > WasmModule::kV8MaxPages) { | 
| 1579 thrower_->RangeError("Out of memory: wasm memory too large"); | 1661 thrower_->RangeError("Out of memory: wasm memory too large"); | 
| 1580 return Handle<JSArrayBuffer>::null(); | 1662 return Handle<JSArrayBuffer>::null(); | 
| 1581 } | 1663 } | 
| 1582 Handle<JSArrayBuffer> mem_buffer = | 1664 const bool enable_guard_regions = FLAG_wasm_guard_pages; | 
| 1583 NewArrayBuffer(isolate_, min_mem_pages * WasmModule::kPageSize); | 1665 Handle<JSArrayBuffer> mem_buffer = NewArrayBuffer( | 
| 1666 isolate_, min_mem_pages * WasmModule::kPageSize, enable_guard_regions); | |
| 1584 | 1667 | 
| 1585 if (mem_buffer.is_null()) { | 1668 if (mem_buffer.is_null()) { | 
| 1586 thrower_->RangeError("Out of memory: wasm memory"); | 1669 thrower_->RangeError("Out of memory: wasm memory"); | 
| 1587 } | 1670 } | 
| 1588 return mem_buffer; | 1671 return mem_buffer; | 
| 1589 } | 1672 } | 
| 1590 | 1673 | 
| 1591 // Process the exports, creating wrappers for functions, tables, memories, | 1674 // Process the exports, creating wrappers for functions, tables, memories, | 
| 1592 // and globals. | 1675 // and globals. | 
| 1593 void ProcessExports(Handle<FixedArray> code_table, | 1676 void ProcessExports(Handle<FixedArray> code_table, | 
| (...skipping 540 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2134 // "undefined" case above. | 2217 // "undefined" case above. | 
| 2135 DCHECK_NOT_NULL(old_mem_start); | 2218 DCHECK_NOT_NULL(old_mem_start); | 
| 2136 DCHECK(old_size + pages * WasmModule::kPageSize <= | 2219 DCHECK(old_size + pages * WasmModule::kPageSize <= | 
| 2137 std::numeric_limits<uint32_t>::max()); | 2220 std::numeric_limits<uint32_t>::max()); | 
| 2138 new_size = old_size + pages * WasmModule::kPageSize; | 2221 new_size = old_size + pages * WasmModule::kPageSize; | 
| 2139 } | 2222 } | 
| 2140 | 2223 | 
| 2141 if (new_size <= old_size || max_pages * WasmModule::kPageSize < new_size) { | 2224 if (new_size <= old_size || max_pages * WasmModule::kPageSize < new_size) { | 
| 2142 return -1; | 2225 return -1; | 
| 2143 } | 2226 } | 
| 2144 Handle<JSArrayBuffer> buffer = NewArrayBuffer(isolate, new_size); | 2227 | 
| 2145 if (buffer.is_null()) return -1; | 2228 Handle<JSArrayBuffer> buffer; | 
| 2146 Address new_mem_start = static_cast<Address>(buffer->backing_store()); | 2229 | 
| 2147 if (old_size != 0) { | 2230 if (FLAG_wasm_guard_pages && !old_buffer.is_null()) { | 
| 
 
titzer
2016/11/07 19:54:53
How about !old_buffer.is_null() and old_buffer.has
 
Eric Holk
2016/11/08 23:58:15
Done.
 
 | |
| 2148 memcpy(new_mem_start, old_mem_start, old_size); | 2231 base::OS::Unprotect(old_buffer->backing_store(), new_size); | 
| 
 
titzer
2016/11/07 19:54:53
Add a comment that we aren't moving the memory her
 
Eric Holk
2016/11/08 23:58:15
Done.
 
 | |
| 2232 reinterpret_cast<v8::Isolate*>(isolate) | |
| 2233 ->AdjustAmountOfExternalAllocatedMemory(pages * WasmModule::kPageSize); | |
| 2234 Handle<Object> new_size_object = | |
| 2235 isolate->factory()->NewNumberFromSize(new_size); | |
| 2236 old_buffer->set_byte_length(*new_size_object); | |
| 2237 | |
| 2238 SetInstanceMemory(instance, *old_buffer); | |
| 2239 Handle<FixedArray> code_table = GetCompiledModule(*instance)->code_table(); | |
| 2240 RelocateMemoryReferencesInCode(code_table, old_mem_start, old_mem_start, | |
| 2241 old_size, new_size); | |
| 2242 buffer = old_buffer; | |
| 2243 } else { | |
| 2244 const bool enable_guard_regions = FLAG_wasm_guard_pages; | |
| 2245 buffer = NewArrayBuffer(isolate, new_size, enable_guard_regions); | |
| 2246 if (buffer.is_null()) return -1; | |
| 2247 Address new_mem_start = static_cast<Address>(buffer->backing_store()); | |
| 2248 if (old_size != 0) { | |
| 2249 memcpy(new_mem_start, old_mem_start, old_size); | |
| 2250 } | |
| 2251 SetInstanceMemory(instance, *buffer); | |
| 2252 Handle<FixedArray> code_table = GetCompiledModule(*instance)->code_table(); | |
| 2253 RelocateMemoryReferencesInCode(code_table, old_mem_start, new_mem_start, | |
| 2254 old_size, new_size); | |
| 2149 } | 2255 } | 
| 2150 SetInstanceMemory(instance, *buffer); | 2256 | 
| 2151 Handle<FixedArray> code_table = GetCompiledModule(*instance)->code_table(); | |
| 2152 RelocateMemoryReferencesInCode(code_table, old_mem_start, new_mem_start, | |
| 2153 old_size, new_size); | |
| 2154 Handle<Object> memory_object(instance->GetInternalField(kWasmMemObject), | 2257 Handle<Object> memory_object(instance->GetInternalField(kWasmMemObject), | 
| 2155 isolate); | 2258 isolate); | 
| 2156 if (!memory_object->IsUndefined(isolate)) { | 2259 if (!memory_object->IsUndefined(isolate)) { | 
| 2157 WasmJs::SetWasmMemoryArrayBuffer(isolate, memory_object, buffer); | 2260 WasmJs::SetWasmMemoryArrayBuffer(isolate, memory_object, buffer); | 
| 2158 } | 2261 } | 
| 2159 | 2262 | 
| 2160 DCHECK(old_size % WasmModule::kPageSize == 0); | 2263 DCHECK(old_size % WasmModule::kPageSize == 0); | 
| 2161 return (old_size / WasmModule::kPageSize); | 2264 return (old_size / WasmModule::kPageSize); | 
| 2162 } | 2265 } | 
| 2163 | 2266 | 
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2232 CHECK_NOT_NULL(result.val); | 2335 CHECK_NOT_NULL(result.val); | 
| 2233 module = const_cast<WasmModule*>(result.val); | 2336 module = const_cast<WasmModule*>(result.val); | 
| 2234 } | 2337 } | 
| 2235 | 2338 | 
| 2236 Handle<WasmModuleWrapper> module_wrapper = | 2339 Handle<WasmModuleWrapper> module_wrapper = | 
| 2237 WasmModuleWrapper::New(isolate, module); | 2340 WasmModuleWrapper::New(isolate, module); | 
| 2238 | 2341 | 
| 2239 compiled_module->set_module_wrapper(module_wrapper); | 2342 compiled_module->set_module_wrapper(module_wrapper); | 
| 2240 DCHECK(WasmCompiledModule::IsWasmCompiledModule(*compiled_module)); | 2343 DCHECK(WasmCompiledModule::IsWasmCompiledModule(*compiled_module)); | 
| 2241 } | 2344 } | 
| OLD | NEW |