LCOV - code coverage report
Current view: top level - src/wasm - wasm-objects.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 495 547 90.5 %
Date: 2017-10-20 Functions: 66 74 89.2 %

          Line data    Source code
       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
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/wasm/wasm-objects.h"
       6             : #include "src/utils.h"
       7             : 
       8             : #include "src/assembler-inl.h"
       9             : #include "src/base/iterator.h"
      10             : #include "src/compiler/wasm-compiler.h"
      11             : #include "src/debug/debug-interface.h"
      12             : #include "src/objects-inl.h"
      13             : #include "src/objects/debug-objects-inl.h"
      14             : #include "src/wasm/module-compiler.h"
      15             : #include "src/wasm/module-decoder.h"
      16             : #include "src/wasm/wasm-code-specialization.h"
      17             : #include "src/wasm/wasm-memory.h"
      18             : #include "src/wasm/wasm-module.h"
      19             : #include "src/wasm/wasm-objects-inl.h"
      20             : #include "src/wasm/wasm-text.h"
      21             : 
      22             : #define TRACE(...)                                      \
      23             :   do {                                                  \
      24             :     if (FLAG_trace_wasm_instances) PrintF(__VA_ARGS__); \
      25             :   } while (false)
      26             : 
      27             : namespace v8 {
      28             : namespace internal {
      29             : 
      30             : // Import a few often used types from the wasm namespace.
      31             : using GlobalHandleAddress = wasm::GlobalHandleAddress;
      32             : using WasmFunction = wasm::WasmFunction;
      33             : using WasmModule = wasm::WasmModule;
      34             : 
      35             : namespace {
      36             : 
      37             : // An iterator that returns first the module itself, then all modules linked via
      38             : // next, then all linked via prev.
      39             : class CompiledModulesIterator
      40             :     : public v8::base::iterator<std::input_iterator_tag,
      41             :                                 Handle<WasmCompiledModule>> {
      42             :  public:
      43             :   CompiledModulesIterator(Isolate* isolate,
      44             :                           Handle<WasmCompiledModule> start_module, bool at_end)
      45             :       : isolate_(isolate),
      46             :         start_module_(start_module),
      47         188 :         current_(at_end ? Handle<WasmCompiledModule>::null() : start_module) {}
      48             : 
      49             :   Handle<WasmCompiledModule> operator*() const {
      50             :     DCHECK(!current_.is_null());
      51             :     return current_;
      52             :   }
      53             : 
      54          94 :   void operator++() { Advance(); }
      55             : 
      56             :   bool operator!=(const CompiledModulesIterator& other) {
      57             :     DCHECK(start_module_.is_identical_to(other.start_module_));
      58             :     return !current_.is_identical_to(other.current_);
      59             :   }
      60             : 
      61             :  private:
      62          94 :   void Advance() {
      63             :     DCHECK(!current_.is_null());
      64          94 :     if (!is_backwards_) {
      65          94 :       if (current_->has_weak_next_instance()) {
      66             :         WeakCell* weak_next = current_->ptr_to_weak_next_instance();
      67           0 :         if (!weak_next->cleared()) {
      68             :           current_ =
      69           0 :               handle(WasmCompiledModule::cast(weak_next->value()), isolate_);
      70           0 :           return;
      71             :         }
      72             :       }
      73             :       // No more modules in next-links, now try the previous-links.
      74          94 :       is_backwards_ = true;
      75          94 :       current_ = start_module_;
      76             :     }
      77          94 :     if (current_->has_weak_prev_instance()) {
      78             :       WeakCell* weak_prev = current_->ptr_to_weak_prev_instance();
      79           0 :       if (!weak_prev->cleared()) {
      80             :         current_ =
      81           0 :             handle(WasmCompiledModule::cast(weak_prev->value()), isolate_);
      82           0 :         return;
      83             :       }
      84             :     }
      85          94 :     current_ = Handle<WasmCompiledModule>::null();
      86             :   }
      87             : 
      88             :   friend class CompiledModuleInstancesIterator;
      89             :   Isolate* isolate_;
      90             :   Handle<WasmCompiledModule> start_module_;
      91             :   Handle<WasmCompiledModule> current_;
      92             :   bool is_backwards_ = false;
      93             : };
      94             : 
      95             : // An iterator based on the CompiledModulesIterator, but it returns all live
      96             : // instances, not the WasmCompiledModules itself.
      97             : class CompiledModuleInstancesIterator
      98             :     : public v8::base::iterator<std::input_iterator_tag,
      99             :                                 Handle<WasmInstanceObject>> {
     100             :  public:
     101         188 :   CompiledModuleInstancesIterator(Isolate* isolate,
     102             :                                   Handle<WasmCompiledModule> start_module,
     103             :                                   bool at_end)
     104             :       : it(isolate, start_module, at_end) {
     105         236 :     while (NeedToAdvance()) ++it;
     106         188 :   }
     107             : 
     108          70 :   Handle<WasmInstanceObject> operator*() {
     109             :     return handle(
     110             :         WasmInstanceObject::cast((*it)->weak_owning_instance()->value()),
     111         210 :         it.isolate_);
     112             :   }
     113             : 
     114          70 :   void operator++() {
     115          70 :     do {
     116          70 :       ++it;
     117             :     } while (NeedToAdvance());
     118          70 :   }
     119             : 
     120             :   bool operator!=(const CompiledModuleInstancesIterator& other) {
     121             :     return it != other.it;
     122             :   }
     123             : 
     124             :  private:
     125         282 :   bool NeedToAdvance() {
     126         376 :     return !it.current_.is_null() &&
     127         164 :            (!it.current_->has_weak_owning_instance() ||
     128         282 :             it.current_->ptr_to_weak_owning_instance()->cleared());
     129             :   }
     130             :   CompiledModulesIterator it;
     131             : };
     132             : 
     133             : v8::base::iterator_range<CompiledModuleInstancesIterator>
     134          94 : iterate_compiled_module_instance_chain(
     135             :     Isolate* isolate, Handle<WasmCompiledModule> compiled_module) {
     136             :   return {CompiledModuleInstancesIterator(isolate, compiled_module, false),
     137         188 :           CompiledModuleInstancesIterator(isolate, compiled_module, true)};
     138             : }
     139             : 
     140             : #ifdef DEBUG
     141             : bool IsBreakablePosition(Handle<WasmCompiledModule> compiled_module,
     142             :                          int func_index, int offset_in_func) {
     143             :   DisallowHeapAllocation no_gc;
     144             :   AccountingAllocator alloc;
     145             :   Zone tmp(&alloc, ZONE_NAME);
     146             :   wasm::BodyLocalDecls locals(&tmp);
     147             :   const byte* module_start = compiled_module->module_bytes()->GetChars();
     148             :   WasmFunction& func = compiled_module->module()->functions[func_index];
     149             :   wasm::BytecodeIterator iterator(module_start + func.code.offset(),
     150             :                                   module_start + func.code.end_offset(),
     151             :                                   &locals);
     152             :   DCHECK_LT(0, locals.encoded_size);
     153             :   for (uint32_t offset : iterator.offsets()) {
     154             :     if (offset > static_cast<uint32_t>(offset_in_func)) break;
     155             :     if (offset == static_cast<uint32_t>(offset_in_func)) return true;
     156             :   }
     157             :   return false;
     158             : }
     159             : #endif  // DEBUG
     160             : 
     161             : }  // namespace
     162             : 
     163      148074 : Handle<WasmModuleObject> WasmModuleObject::New(
     164             :     Isolate* isolate, Handle<WasmCompiledModule> compiled_module) {
     165             :   Handle<JSFunction> module_cons(
     166      296148 :       isolate->native_context()->wasm_module_constructor());
     167             :   auto module_object = Handle<WasmModuleObject>::cast(
     168      148074 :       isolate->factory()->NewJSObject(module_cons));
     169      148074 :   module_object->set_compiled_module(*compiled_module);
     170             :   Handle<WeakCell> link_to_module =
     171      148074 :       isolate->factory()->NewWeakCell(module_object);
     172             :   compiled_module->set_weak_wasm_module(link_to_module);
     173      148074 :   return module_object;
     174             : }
     175             : 
     176          20 : void WasmModuleObject::ValidateStateForTesting(
     177             :     Isolate* isolate, Handle<WasmModuleObject> module_obj) {
     178             :   DisallowHeapAllocation no_gc;
     179             :   WasmCompiledModule* compiled_module = module_obj->compiled_module();
     180          20 :   CHECK(compiled_module->has_weak_wasm_module());
     181          20 :   CHECK_EQ(compiled_module->ptr_to_weak_wasm_module()->value(), *module_obj);
     182          20 :   CHECK(!compiled_module->has_weak_prev_instance());
     183          20 :   CHECK(!compiled_module->has_weak_next_instance());
     184          20 :   CHECK(!compiled_module->has_weak_owning_instance());
     185          20 : }
     186             : 
     187        1770 : Handle<WasmTableObject> WasmTableObject::New(Isolate* isolate, uint32_t initial,
     188             :                                              int64_t maximum,
     189             :                                              Handle<FixedArray>* js_functions) {
     190             :   Handle<JSFunction> table_ctor(
     191        3540 :       isolate->native_context()->wasm_table_constructor());
     192             :   auto table_obj = Handle<WasmTableObject>::cast(
     193        1770 :       isolate->factory()->NewJSObject(table_ctor));
     194             : 
     195        1770 :   *js_functions = isolate->factory()->NewFixedArray(initial);
     196        1770 :   Object* null = isolate->heap()->null_value();
     197       12690 :   for (int i = 0; i < static_cast<int>(initial); ++i) {
     198       10920 :     (*js_functions)->set(i, null);
     199             :   }
     200        1770 :   table_obj->set_functions(**js_functions);
     201             :   DCHECK_EQ(maximum, static_cast<int>(maximum));
     202        1770 :   Handle<Object> max = isolate->factory()->NewNumber(maximum);
     203        1770 :   table_obj->set_maximum_length(*max);
     204             : 
     205        1770 :   Handle<FixedArray> dispatch_tables = isolate->factory()->NewFixedArray(0);
     206        1770 :   table_obj->set_dispatch_tables(*dispatch_tables);
     207        1770 :   return Handle<WasmTableObject>::cast(table_obj);
     208             : }
     209             : 
     210        1290 : Handle<FixedArray> WasmTableObject::AddDispatchTable(
     211             :     Isolate* isolate, Handle<WasmTableObject> table_obj,
     212             :     Handle<WasmInstanceObject> instance, int table_index,
     213             :     Handle<FixedArray> function_table, Handle<FixedArray> signature_table) {
     214             :   Handle<FixedArray> dispatch_tables(table_obj->dispatch_tables());
     215             :   DCHECK_EQ(0, dispatch_tables->length() % 4);
     216             : 
     217        1290 :   if (instance.is_null()) return dispatch_tables;
     218             :   // TODO(titzer): use weak cells here to avoid leaking instances.
     219             : 
     220             :   // Grow the dispatch table and add a new entry at the end.
     221             :   Handle<FixedArray> new_dispatch_tables =
     222        1290 :       isolate->factory()->CopyFixedArrayAndGrow(dispatch_tables, 4);
     223             : 
     224        1290 :   new_dispatch_tables->set(dispatch_tables->length() + 0, *instance);
     225             :   new_dispatch_tables->set(dispatch_tables->length() + 1,
     226             :                            Smi::FromInt(table_index));
     227        2580 :   new_dispatch_tables->set(dispatch_tables->length() + 2, *function_table);
     228        2580 :   new_dispatch_tables->set(dispatch_tables->length() + 3, *signature_table);
     229             : 
     230        1290 :   table_obj->set_dispatch_tables(*new_dispatch_tables);
     231             : 
     232        1290 :   return new_dispatch_tables;
     233             : }
     234             : 
     235        3300 : void WasmTableObject::Grow(Isolate* isolate, uint32_t count) {
     236             :   Handle<FixedArray> dispatch_tables(this->dispatch_tables());
     237             :   DCHECK_EQ(0, dispatch_tables->length() % 4);
     238         530 :   uint32_t old_size = functions()->length();
     239             : 
     240         530 :   Zone specialization_zone(isolate->allocator(), ZONE_NAME);
     241        3300 :   for (int i = 0; i < dispatch_tables->length(); i += 4) {
     242             :     Handle<FixedArray> old_function_table(
     243        1120 :         FixedArray::cast(dispatch_tables->get(i + 2)));
     244             :     Handle<FixedArray> old_signature_table(
     245        1120 :         FixedArray::cast(dispatch_tables->get(i + 3)));
     246             :     Handle<FixedArray> new_function_table = isolate->global_handles()->Create(
     247        2240 :         *isolate->factory()->CopyFixedArrayAndGrow(old_function_table, count));
     248             :     Handle<FixedArray> new_signature_table = isolate->global_handles()->Create(
     249        2240 :         *isolate->factory()->CopyFixedArrayAndGrow(old_signature_table, count));
     250             : 
     251             :     GlobalHandleAddress new_function_table_addr = new_function_table.address();
     252             :     GlobalHandleAddress new_signature_table_addr =
     253             :         new_signature_table.address();
     254             : 
     255        1120 :     int table_index = Smi::cast(dispatch_tables->get(i + 1))->value();
     256             :     // Update dispatch tables with new function/signature tables
     257        1120 :     dispatch_tables->set(i + 2, *new_function_table);
     258        1120 :     dispatch_tables->set(i + 3, *new_signature_table);
     259             : 
     260             :     // Patch the code of the respective instance.
     261             :     {
     262             :       DisallowHeapAllocation no_gc;
     263             :       wasm::CodeSpecialization code_specialization(isolate,
     264        1120 :                                                    &specialization_zone);
     265             :       WasmInstanceObject* instance =
     266             :           WasmInstanceObject::cast(dispatch_tables->get(i));
     267             :       WasmCompiledModule* compiled_module = instance->compiled_module();
     268             :       GlobalHandleAddress old_function_table_addr =
     269             :           WasmCompiledModule::GetTableValue(
     270             :               compiled_module->ptr_to_function_tables(), table_index);
     271             :       GlobalHandleAddress old_signature_table_addr =
     272             :           WasmCompiledModule::GetTableValue(
     273             :               compiled_module->ptr_to_signature_tables(), table_index);
     274        1120 :       code_specialization.PatchTableSize(old_size, old_size + count);
     275             :       code_specialization.RelocatePointer(old_function_table_addr,
     276        1120 :                                           new_function_table_addr);
     277             :       code_specialization.RelocatePointer(old_signature_table_addr,
     278        1120 :                                           new_signature_table_addr);
     279        1120 :       code_specialization.ApplyToWholeInstance(instance);
     280             :       WasmCompiledModule::UpdateTableValue(
     281             :           compiled_module->ptr_to_function_tables(), table_index,
     282             :           new_function_table_addr);
     283             :       WasmCompiledModule::UpdateTableValue(
     284             :           compiled_module->ptr_to_signature_tables(), table_index,
     285        1120 :           new_signature_table_addr);
     286             :     }
     287         530 :   }
     288         530 : }
     289             : 
     290        3750 : void WasmTableObject::Set(Isolate* isolate, Handle<WasmTableObject> table,
     291             :                           int32_t index, Handle<JSFunction> function) {
     292             :   Handle<FixedArray> array(table->functions(), isolate);
     293             : 
     294             :   Handle<FixedArray> dispatch_tables(table->dispatch_tables(), isolate);
     295             : 
     296             :   WasmFunction* wasm_function = nullptr;
     297        3750 :   Handle<Code> code = Handle<Code>::null();
     298             :   Handle<Object> value = isolate->factory()->null_value();
     299             : 
     300        3750 :   if (!function.is_null()) {
     301             :     auto exported_function = Handle<WasmExportedFunction>::cast(function);
     302        2230 :     wasm_function = wasm::GetWasmFunctionForExport(isolate, function);
     303             :     // The verification that {function} is an export was done
     304             :     // by the caller.
     305             :     DCHECK_NOT_NULL(wasm_function);
     306             :     value = function;
     307             :     // TODO(titzer): Make JSToWasm wrappers just call the WASM to WASM wrapper,
     308             :     // and then we can just reuse the WASM to WASM wrapper.
     309             :     Address new_context_address = reinterpret_cast<Address>(
     310        2230 :         exported_function->instance()->wasm_context()->get());
     311             :     code = compiler::CompileWasmToWasmWrapper(
     312             :         isolate, exported_function->GetWasmCode(), wasm_function->sig,
     313        4460 :         exported_function->function_index(), new_context_address);
     314             :   }
     315             : 
     316        3750 :   UpdateDispatchTables(isolate, dispatch_tables, index, wasm_function, code);
     317        3750 :   array->set(index, *value);
     318        3750 : }
     319             : 
     320             : namespace {
     321             : 
     322        2132 : Handle<JSArrayBuffer> GrowMemoryBuffer(Isolate* isolate,
     323             :                                        Handle<JSArrayBuffer> old_buffer,
     324             :                                        uint32_t pages, uint32_t maximum_pages) {
     325             :   Address old_mem_start = nullptr;
     326        1962 :   uint32_t old_size = 0;
     327        1962 :   if (!old_buffer.is_null()) {
     328             :     old_mem_start = static_cast<Address>(old_buffer->backing_store());
     329        1962 :     CHECK(old_buffer->byte_length()->ToUint32(&old_size));
     330             :   }
     331             :   DCHECK_EQ(0, old_size % WasmModule::kPageSize);
     332        1962 :   uint32_t old_pages = old_size / WasmModule::kPageSize;
     333             :   DCHECK_GE(std::numeric_limits<uint32_t>::max(),
     334             :             old_size + pages * WasmModule::kPageSize);
     335        1962 :   if (old_pages > maximum_pages || pages > maximum_pages - old_pages) {
     336             :     return Handle<JSArrayBuffer>::null();
     337             :   }
     338             :   const bool enable_guard_regions = old_buffer.is_null()
     339             :                                         ? trap_handler::UseTrapHandler()
     340        1740 :                                         : old_buffer->has_guard_region();
     341             :   size_t new_size =
     342        1740 :       static_cast<size_t>(old_pages + pages) * WasmModule::kPageSize;
     343        1740 :   if (enable_guard_regions && old_size != 0) {
     344             :     DCHECK_NOT_NULL(old_buffer->backing_store());
     345         170 :     if (new_size > FLAG_wasm_max_mem_pages * WasmModule::kPageSize ||
     346             :         new_size > kMaxInt) {
     347             :       return Handle<JSArrayBuffer>::null();
     348             :     }
     349             :     isolate->array_buffer_allocator()->SetProtection(
     350             :         old_mem_start, new_size,
     351         170 :         v8::ArrayBuffer::Allocator::Protection::kReadWrite);
     352             :     reinterpret_cast<v8::Isolate*>(isolate)
     353         170 :         ->AdjustAmountOfExternalAllocatedMemory(pages * WasmModule::kPageSize);
     354         170 :     Handle<Object> length_obj = isolate->factory()->NewNumberFromSize(new_size);
     355         170 :     old_buffer->set_byte_length(*length_obj);
     356         170 :     return old_buffer;
     357             :   } else {
     358             :     Handle<JSArrayBuffer> new_buffer;
     359        1570 :     new_buffer = wasm::NewArrayBuffer(isolate, new_size, enable_guard_regions);
     360        1570 :     if (new_buffer.is_null() || old_size == 0) return new_buffer;
     361             :     Address new_mem_start = static_cast<Address>(new_buffer->backing_store());
     362        1450 :     memcpy(new_mem_start, old_mem_start, old_size);
     363        1450 :     return new_buffer;
     364             :   }
     365             : }
     366             : 
     367             : // May GC, because SetSpecializationMemInfoFrom may GC
     368       19929 : void SetInstanceMemory(Isolate* isolate, Handle<WasmInstanceObject> instance,
     369             :                        Handle<JSArrayBuffer> buffer) {
     370       19929 :   instance->set_memory_buffer(*buffer);
     371             :   auto wasm_context = instance->wasm_context()->get();
     372       19929 :   wasm_context->mem_start = reinterpret_cast<byte*>(buffer->backing_store());
     373       19929 :   wasm_context->mem_size = buffer->byte_length()->Number();
     374             : #if DEBUG
     375             :   // To flush out bugs earlier, in DEBUG mode, check that all pages of the
     376             :   // memory are accessible by reading and writing one byte on each page.
     377             :   for (uint32_t offset = 0; offset < wasm_context->mem_size;
     378             :        offset += WasmModule::kPageSize) {
     379             :     byte val = wasm_context->mem_start[offset];
     380             :     wasm_context->mem_start[offset] = val;
     381             :   }
     382             : #endif
     383       19929 : }
     384             : 
     385             : }  // namespace
     386             : 
     387       16084 : Handle<WasmMemoryObject> WasmMemoryObject::New(Isolate* isolate,
     388             :                                                Handle<JSArrayBuffer> buffer,
     389             :                                                int32_t maximum) {
     390             :   Handle<JSFunction> memory_ctor(
     391       32168 :       isolate->native_context()->wasm_memory_constructor());
     392             :   auto memory_obj = Handle<WasmMemoryObject>::cast(
     393       16084 :       isolate->factory()->NewJSObject(memory_ctor, TENURED));
     394             : 
     395       16084 :   if (buffer.is_null()) {
     396             :     // If no buffer was provided, create a 0-length one.
     397             :     buffer = wasm::SetupArrayBuffer(isolate, nullptr, 0, nullptr, 0, false,
     398        5120 :                                     trap_handler::UseTrapHandler());
     399             :   } else {
     400             :     // Paranoid check that the buffer size makes sense.
     401       10964 :     uint32_t mem_size = 0;
     402       10964 :     CHECK(buffer->byte_length()->ToUint32(&mem_size));
     403             :   }
     404       16084 :   memory_obj->set_array_buffer(*buffer);
     405             :   memory_obj->set_maximum_pages(maximum);
     406             : 
     407       16084 :   return memory_obj;
     408             : }
     409             : 
     410           0 : uint32_t WasmMemoryObject::current_pages() {
     411             :   uint32_t byte_length;
     412           0 :   CHECK(array_buffer()->byte_length()->ToUint32(&byte_length));
     413           0 :   return byte_length / WasmModule::kPageSize;
     414             : }
     415             : 
     416       15776 : void WasmMemoryObject::AddInstance(Isolate* isolate,
     417             :                                    Handle<WasmMemoryObject> memory,
     418             :                                    Handle<WasmInstanceObject> instance) {
     419             :   Handle<WeakFixedArray> old_instances =
     420             :       memory->has_instances()
     421             :           ? Handle<WeakFixedArray>(memory->instances(), isolate)
     422       15776 :           : Handle<WeakFixedArray>::null();
     423             :   Handle<WeakFixedArray> new_instances =
     424       15776 :       WeakFixedArray::Add(old_instances, instance);
     425       15776 :   memory->set_instances(*new_instances);
     426             :   Handle<JSArrayBuffer> buffer(memory->array_buffer(), isolate);
     427       15776 :   SetInstanceMemory(isolate, instance, buffer);
     428       15776 : }
     429             : 
     430        3143 : void WasmMemoryObject::RemoveInstance(Isolate* isolate,
     431             :                                       Handle<WasmMemoryObject> memory,
     432             :                                       Handle<WasmInstanceObject> instance) {
     433        3143 :   if (memory->has_instances()) {
     434        3143 :     memory->instances()->Remove(instance);
     435             :   }
     436        3143 : }
     437             : 
     438          96 : void WasmMemoryObject::SetupNewBufferWithSameBackingStore(
     439             :     Isolate* isolate, Handle<WasmMemoryObject> memory_object, uint32_t size) {
     440             :   // In case of Memory.Grow(0), or Memory.Grow(delta) with guard pages enabled,
     441             :   // Setup a new buffer, update memory object, and instances associated with the
     442             :   // memory object, as the current buffer will be detached.
     443             :   Handle<JSArrayBuffer> old_buffer(memory_object->array_buffer());
     444             :   Handle<JSArrayBuffer> new_buffer;
     445             : 
     446             :   constexpr bool is_external = false;
     447             :   new_buffer = wasm::SetupArrayBuffer(
     448             :       isolate, old_buffer->allocation_base(), old_buffer->allocation_length(),
     449          96 :       old_buffer->backing_store(), size * WasmModule::kPageSize, is_external,
     450         288 :       old_buffer->has_guard_region());
     451          96 :   if (memory_object->has_instances()) {
     452             :     Handle<WeakFixedArray> instances(memory_object->instances(), isolate);
     453         252 :     for (int i = 0; i < instances->Length(); i++) {
     454         104 :       Object* elem = instances->Get(i);
     455         135 :       if (!elem->IsWasmInstanceObject()) continue;
     456             :       Handle<WasmInstanceObject> instance(WasmInstanceObject::cast(elem),
     457             :                                           isolate);
     458          73 :       SetInstanceMemory(isolate, instance, new_buffer);
     459             :     }
     460             :   }
     461          96 :   memory_object->set_array_buffer(*new_buffer);
     462          96 : }
     463             : 
     464             : // static
     465        2038 : int32_t WasmMemoryObject::Grow(Isolate* isolate,
     466             :                                Handle<WasmMemoryObject> memory_object,
     467             :                                uint32_t pages) {
     468             :   Handle<JSArrayBuffer> old_buffer(memory_object->array_buffer());
     469        2038 :   uint32_t old_size = 0;
     470        2038 :   CHECK(old_buffer->byte_length()->ToUint32(&old_size));
     471             :   DCHECK_EQ(0, old_size % WasmModule::kPageSize);
     472             :   Handle<JSArrayBuffer> new_buffer;
     473             :   // Return current size if grow by 0.
     474        2038 :   if (pages == 0) return old_size / WasmModule::kPageSize;
     475             : 
     476        1962 :   uint32_t maximum_pages = FLAG_wasm_max_mem_pages;
     477        1962 :   if (memory_object->has_maximum_pages()) {
     478             :     maximum_pages = Min(FLAG_wasm_max_mem_pages,
     479        1900 :                         static_cast<uint32_t>(memory_object->maximum_pages()));
     480             :   }
     481        1962 :   new_buffer = GrowMemoryBuffer(isolate, old_buffer, pages, maximum_pages);
     482        1962 :   if (new_buffer.is_null()) return -1;
     483             : 
     484        1740 :   if (memory_object->has_instances()) {
     485             :     Handle<WeakFixedArray> instances(memory_object->instances(), isolate);
     486       13640 :     for (int i = 0; i < instances->Length(); i++) {
     487        5120 :       Object* elem = instances->Get(i);
     488        6160 :       if (!elem->IsWasmInstanceObject()) continue;
     489             :       Handle<WasmInstanceObject> instance(WasmInstanceObject::cast(elem),
     490             :                                           isolate);
     491        4080 :       SetInstanceMemory(isolate, instance, new_buffer);
     492             :     }
     493             :   }
     494        1740 :   memory_object->set_array_buffer(*new_buffer);
     495        1740 :   return old_size / WasmModule::kPageSize;
     496             : }
     497             : 
     498           0 : WasmModuleObject* WasmInstanceObject::module_object() {
     499           0 :   return *compiled_module()->wasm_module();
     500             : }
     501             : 
     502      282524 : WasmModule* WasmInstanceObject::module() { return compiled_module()->module(); }
     503             : 
     504        1042 : Handle<WasmDebugInfo> WasmInstanceObject::GetOrCreateDebugInfo(
     505             :     Handle<WasmInstanceObject> instance) {
     506        1042 :   if (instance->has_debug_info()) return handle(instance->debug_info());
     507         982 :   Handle<WasmDebugInfo> new_info = WasmDebugInfo::New(instance);
     508             :   DCHECK(instance->has_debug_info());
     509         982 :   return new_info;
     510             : }
     511             : 
     512      191035 : Handle<WasmInstanceObject> WasmInstanceObject::New(
     513             :     Isolate* isolate, Handle<WasmCompiledModule> compiled_module) {
     514             :   Handle<JSFunction> instance_cons(
     515      382070 :       isolate->native_context()->wasm_instance_constructor());
     516             :   Handle<JSObject> instance_object =
     517      191035 :       isolate->factory()->NewJSObject(instance_cons, TENURED);
     518             : 
     519             :   Handle<WasmInstanceObject> instance(
     520             :       reinterpret_cast<WasmInstanceObject*>(*instance_object), isolate);
     521             : 
     522      191035 :   auto wasm_context = Managed<WasmContext>::Allocate(isolate);
     523      191035 :   wasm_context->get()->mem_start = nullptr;
     524      191035 :   wasm_context->get()->mem_size = 0;
     525      191035 :   wasm_context->get()->globals_start = nullptr;
     526      191035 :   instance->set_wasm_context(*wasm_context);
     527             : 
     528      191035 :   instance->set_compiled_module(*compiled_module);
     529      191035 :   return instance;
     530             : }
     531             : 
     532         156 : int32_t WasmInstanceObject::GetMemorySize() {
     533         156 :   if (!has_memory_buffer()) return 0;
     534         156 :   uint32_t bytes = memory_buffer()->byte_length()->Number();
     535             :   DCHECK_EQ(0, bytes % WasmModule::kPageSize);
     536         156 :   return bytes / WasmModule::kPageSize;
     537             : }
     538             : 
     539        1852 : int32_t WasmInstanceObject::GrowMemory(Isolate* isolate,
     540             :                                        Handle<WasmInstanceObject> instance,
     541             :                                        uint32_t pages) {
     542        2008 :   if (pages == 0) return instance->GetMemorySize();
     543             :   DCHECK(instance->has_memory_object());
     544             :   return WasmMemoryObject::Grow(
     545        1696 :       isolate, handle(instance->memory_object(), isolate), pages);
     546             : }
     547             : 
     548           0 : uint32_t WasmInstanceObject::GetMaxMemoryPages() {
     549           0 :   if (has_memory_object()) {
     550           0 :     if (memory_object()->has_maximum_pages()) {
     551             :       uint32_t maximum =
     552           0 :           static_cast<uint32_t>(memory_object()->maximum_pages());
     553           0 :       if (maximum < FLAG_wasm_max_mem_pages) return maximum;
     554             :     }
     555             :   }
     556           0 :   uint32_t compiled_maximum_pages = compiled_module()->module()->maximum_pages;
     557             :   Isolate* isolate = GetIsolate();
     558             :   assert(compiled_module()->module()->is_wasm());
     559             :   isolate->counters()->wasm_wasm_max_mem_pages_count()->AddSample(
     560           0 :       compiled_maximum_pages);
     561           0 :   if (compiled_maximum_pages != 0) return compiled_maximum_pages;
     562           0 :   return FLAG_wasm_max_mem_pages;
     563             : }
     564             : 
     565      133277 : WasmInstanceObject* WasmInstanceObject::GetOwningInstance(Code* code) {
     566             :   DisallowHeapAllocation no_gc;
     567             :   DCHECK(code->kind() == Code::WASM_FUNCTION ||
     568             :          code->kind() == Code::WASM_INTERPRETER_ENTRY);
     569             :   FixedArray* deopt_data = code->deoptimization_data();
     570             :   DCHECK_EQ(code->kind() == Code::WASM_INTERPRETER_ENTRY ? 1 : 2,
     571             :             deopt_data->length());
     572             :   Object* weak_link = deopt_data->get(0);
     573             :   DCHECK(weak_link->IsWeakCell());
     574             :   WeakCell* cell = WeakCell::cast(weak_link);
     575      133277 :   if (cell->cleared()) return nullptr;
     576      133277 :   return WasmInstanceObject::cast(cell->value());
     577             : }
     578             : 
     579          60 : void WasmInstanceObject::ValidateInstancesChainForTesting(
     580             :     Isolate* isolate, Handle<WasmModuleObject> module_obj, int instance_count) {
     581          60 :   CHECK_GE(instance_count, 0);
     582             :   DisallowHeapAllocation no_gc;
     583             :   WasmCompiledModule* compiled_module = module_obj->compiled_module();
     584          60 :   CHECK_EQ(JSObject::cast(compiled_module->ptr_to_weak_wasm_module()->value()),
     585             :            *module_obj);
     586             :   Object* prev = nullptr;
     587          60 :   int found_instances = compiled_module->has_weak_owning_instance() ? 1 : 0;
     588             :   WasmCompiledModule* current_instance = compiled_module;
     589         160 :   while (current_instance->has_weak_next_instance()) {
     590          50 :     CHECK((prev == nullptr && !current_instance->has_weak_prev_instance()) ||
     591             :           current_instance->ptr_to_weak_prev_instance()->value() == prev);
     592          40 :     CHECK_EQ(current_instance->ptr_to_weak_wasm_module()->value(), *module_obj);
     593          40 :     CHECK(current_instance->ptr_to_weak_owning_instance()
     594             :               ->value()
     595             :               ->IsWasmInstanceObject());
     596             :     prev = current_instance;
     597             :     current_instance = WasmCompiledModule::cast(
     598             :         current_instance->ptr_to_weak_next_instance()->value());
     599          40 :     ++found_instances;
     600          40 :     CHECK_LE(found_instances, instance_count);
     601             :   }
     602          60 :   CHECK_EQ(found_instances, instance_count);
     603          60 : }
     604             : 
     605          10 : void WasmInstanceObject::ValidateOrphanedInstanceForTesting(
     606             :     Isolate* isolate, Handle<WasmInstanceObject> instance) {
     607             :   DisallowHeapAllocation no_gc;
     608             :   WasmCompiledModule* compiled_module = instance->compiled_module();
     609          10 :   CHECK(compiled_module->has_weak_wasm_module());
     610          10 :   CHECK(compiled_module->ptr_to_weak_wasm_module()->cleared());
     611          10 : }
     612             : 
     613      145415 : bool WasmExportedFunction::IsWasmExportedFunction(Object* object) {
     614      145415 :   if (!object->IsJSFunction()) return false;
     615             :   Handle<JSFunction> js_function(JSFunction::cast(object));
     616      143465 :   if (Code::JS_TO_WASM_FUNCTION != js_function->code()->kind()) return false;
     617             : 
     618             :   Handle<Symbol> symbol(
     619             :       js_function->GetIsolate()->factory()->wasm_instance_symbol());
     620             :   MaybeHandle<Object> maybe_result =
     621      133885 :       JSObject::GetPropertyOrElement(js_function, symbol);
     622             :   Handle<Object> result;
     623      133885 :   if (!maybe_result.ToHandle(&result)) return false;
     624      133885 :   return result->IsWasmInstanceObject();
     625             : }
     626             : 
     627      136489 : WasmExportedFunction* WasmExportedFunction::cast(Object* object) {
     628             :   DCHECK(IsWasmExportedFunction(object));
     629      136489 :   return reinterpret_cast<WasmExportedFunction*>(object);
     630             : }
     631             : 
     632      138345 : WasmInstanceObject* WasmExportedFunction::instance() {
     633             :   DisallowHeapAllocation no_allocation;
     634             :   Handle<Symbol> symbol(GetIsolate()->factory()->wasm_instance_symbol());
     635             :   MaybeHandle<Object> result =
     636      138345 :       JSObject::GetPropertyOrElement(handle(this), symbol);
     637      138345 :   return WasmInstanceObject::cast(*(result.ToHandleChecked()));
     638             : }
     639             : 
     640      405676 : int WasmExportedFunction::function_index() {
     641             :   DisallowHeapAllocation no_allocation;
     642             :   Handle<Symbol> symbol = GetIsolate()->factory()->wasm_function_index_symbol();
     643             :   MaybeHandle<Object> result =
     644      405676 :       JSObject::GetPropertyOrElement(handle(this), symbol);
     645      405676 :   return result.ToHandleChecked()->Number();
     646             : }
     647             : 
     648      198486 : Handle<WasmExportedFunction> WasmExportedFunction::New(
     649             :     Isolate* isolate, Handle<WasmInstanceObject> instance,
     650             :     MaybeHandle<String> maybe_name, int func_index, int arity,
     651             :     Handle<Code> export_wrapper) {
     652             :   DCHECK_EQ(Code::JS_TO_WASM_FUNCTION, export_wrapper->kind());
     653             :   Handle<String> name;
     654      198486 :   if (!maybe_name.ToHandle(&name)) {
     655             :     EmbeddedVector<char, 16> buffer;
     656      188150 :     int length = SNPrintF(buffer, "%d", func_index);
     657             :     name = isolate->factory()
     658             :                ->NewStringFromOneByte(
     659      188150 :                    Vector<uint8_t>::cast(buffer.SubVector(0, length)))
     660      376300 :                .ToHandleChecked();
     661             :   }
     662             :   Handle<SharedFunctionInfo> shared =
     663      198486 :       isolate->factory()->NewSharedFunctionInfo(name, export_wrapper, false);
     664             :   shared->set_length(arity);
     665             :   shared->set_internal_formal_parameter_count(arity);
     666             :   Handle<JSFunction> js_function = isolate->factory()->NewFunction(
     667      198486 :       isolate->sloppy_function_map(), name, export_wrapper);
     668             : 
     669      198486 :   js_function->set_shared(*shared);
     670             :   Handle<Symbol> instance_symbol(isolate->factory()->wasm_instance_symbol());
     671      198486 :   JSObject::AddProperty(js_function, instance_symbol, instance, DONT_ENUM);
     672             : 
     673             :   Handle<Symbol> function_index_symbol(
     674             :       isolate->factory()->wasm_function_index_symbol());
     675             :   JSObject::AddProperty(js_function, function_index_symbol,
     676      396972 :                         isolate->factory()->NewNumber(func_index), DONT_ENUM);
     677             : 
     678      198486 :   return Handle<WasmExportedFunction>::cast(js_function);
     679             : }
     680             : 
     681      136115 : Handle<Code> WasmExportedFunction::GetWasmCode() {
     682             :   DisallowHeapAllocation no_gc;
     683             :   Handle<Code> export_wrapper_code = handle(this->code());
     684             :   DCHECK_EQ(export_wrapper_code->kind(), Code::JS_TO_WASM_FUNCTION);
     685             :   int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET);
     686      382295 :   for (RelocIterator it(*export_wrapper_code, mask);; it.next()) {
     687             :     DCHECK(!it.done());
     688      764590 :     Code* target = Code::GetCodeFromTargetAddress(it.rinfo()->target_address());
     689      629520 :     if (target->kind() != Code::WASM_FUNCTION &&
     690      628510 :         target->kind() != Code::WASM_TO_JS_FUNCTION &&
     691             :         target->kind() != Code::WASM_INTERPRETER_ENTRY)
     692             :       continue;
     693             : // There should only be this one call to wasm code.
     694             : #ifdef DEBUG
     695             :     for (it.next(); !it.done(); it.next()) {
     696             :       Code* code = Code::GetCodeFromTargetAddress(it.rinfo()->target_address());
     697             :       DCHECK(code->kind() != Code::WASM_FUNCTION &&
     698             :              code->kind() != Code::WASM_TO_JS_FUNCTION &&
     699             :              code->kind() != Code::WASM_INTERPRETER_ENTRY);
     700             :     }
     701             : #endif
     702      136115 :     return handle(target);
     703      246180 :   }
     704             :   UNREACHABLE();
     705             : }
     706             : 
     707           0 : bool WasmSharedModuleData::IsWasmSharedModuleData(Object* object) {
     708           0 :   if (!object->IsFixedArray()) return false;
     709             :   FixedArray* arr = FixedArray::cast(object);
     710           0 :   if (arr->length() != kFieldCount) return false;
     711             :   Isolate* isolate = arr->GetIsolate();
     712           0 :   if (!arr->get(kModuleWrapperIndex)->IsForeign()) return false;
     713           0 :   if (!arr->get(kModuleBytesIndex)->IsUndefined(isolate) &&
     714             :       !arr->get(kModuleBytesIndex)->IsSeqOneByteString())
     715             :     return false;
     716           0 :   if (!arr->get(kScriptIndex)->IsScript()) return false;
     717           0 :   if (!arr->get(kAsmJsOffsetTableIndex)->IsUndefined(isolate) &&
     718             :       !arr->get(kAsmJsOffsetTableIndex)->IsByteArray())
     719             :     return false;
     720           0 :   if (!arr->get(kBreakPointInfosIndex)->IsUndefined(isolate) &&
     721             :       !arr->get(kBreakPointInfosIndex)->IsFixedArray())
     722             :     return false;
     723           0 :   return true;
     724             : }
     725             : 
     726     1462486 : WasmSharedModuleData* WasmSharedModuleData::cast(Object* object) {
     727             :   DCHECK(IsWasmSharedModuleData(object));
     728     1462486 :   return reinterpret_cast<WasmSharedModuleData*>(object);
     729             : }
     730             : 
     731      645440 : WasmModule* WasmSharedModuleData::module() {
     732             :   // We populate the kModuleWrapper field with a Foreign holding the
     733             :   // address to the address of a WasmModule. This is because we can
     734             :   // handle both cases when the WasmModule's lifetime is managed through
     735             :   // a Managed<WasmModule> object, as well as cases when it's managed
     736             :   // by the embedder. CcTests fall into the latter case.
     737             :   return *(reinterpret_cast<WasmModule**>(
     738     1298051 :       Foreign::cast(get(kModuleWrapperIndex))->foreign_address()));
     739             : }
     740             : 
     741      185130 : Handle<WasmSharedModuleData> WasmSharedModuleData::New(
     742             :     Isolate* isolate, Handle<Foreign> module_wrapper,
     743             :     Handle<SeqOneByteString> module_bytes, Handle<Script> script,
     744             :     Handle<ByteArray> asm_js_offset_table) {
     745             :   Handle<FixedArray> arr =
     746      185130 :       isolate->factory()->NewFixedArray(kFieldCount, TENURED);
     747      185130 :   arr->set(kModuleWrapperIndex, *module_wrapper);
     748      185130 :   if (!module_bytes.is_null()) {
     749      185130 :     arr->set(kModuleBytesIndex, *module_bytes);
     750             :   }
     751      185130 :   if (!script.is_null()) {
     752      185130 :     arr->set(kScriptIndex, *script);
     753             :   }
     754      185130 :   if (!asm_js_offset_table.is_null()) {
     755        3547 :     arr->set(kAsmJsOffsetTableIndex, *asm_js_offset_table);
     756             :   }
     757             : 
     758             :   DCHECK(WasmSharedModuleData::IsWasmSharedModuleData(*arr));
     759      185130 :   return Handle<WasmSharedModuleData>::cast(arr);
     760             : }
     761             : 
     762       43759 : bool WasmSharedModuleData::is_asm_js() {
     763       43759 :   bool asm_js = module()->is_asm_js();
     764             :   DCHECK_EQ(asm_js, script()->IsUserJavaScript());
     765             :   DCHECK_EQ(asm_js, has_asm_js_offset_table());
     766       43759 :   return asm_js;
     767             : }
     768             : 
     769          80 : void WasmSharedModuleData::ReinitializeAfterDeserialization(
     770             :     Isolate* isolate, Handle<WasmSharedModuleData> shared) {
     771             :   DCHECK(shared->get(kModuleWrapperIndex)->IsUndefined(isolate));
     772             : #ifdef DEBUG
     773             :   // No BreakpointInfo objects should survive deserialization.
     774             :   if (shared->has_breakpoint_infos()) {
     775             :     for (int i = 0, e = shared->breakpoint_infos()->length(); i < e; ++i) {
     776             :       DCHECK(shared->breakpoint_infos()->get(i)->IsUndefined(isolate));
     777             :     }
     778             :   }
     779             : #endif
     780             : 
     781         160 :   shared->set(kBreakPointInfosIndex, isolate->heap()->undefined_value());
     782             : 
     783             :   WasmModule* module = nullptr;
     784             :   {
     785             :     // We parse the module again directly from the module bytes, so
     786             :     // the underlying storage must not be moved meanwhile.
     787             :     DisallowHeapAllocation no_allocation;
     788             :     SeqOneByteString* module_bytes = shared->module_bytes();
     789             :     const byte* start =
     790          80 :         reinterpret_cast<const byte*>(module_bytes->GetCharsAddress());
     791          80 :     const byte* end = start + module_bytes->length();
     792             :     // TODO(titzer): remember the module origin in the compiled_module
     793             :     // For now, we assume serialized modules did not originate from asm.js.
     794             :     wasm::ModuleResult result =
     795         160 :         SyncDecodeWasmModule(isolate, start, end, false, wasm::kWasmOrigin);
     796          80 :     CHECK(result.ok());
     797          80 :     CHECK_NOT_NULL(result.val);
     798             :     // Take ownership of the WasmModule and immediately transfer it to the
     799             :     // WasmModuleWrapper below.
     800          80 :     module = result.val.release();
     801             :   }
     802             : 
     803             :   Handle<wasm::WasmModuleWrapper> module_wrapper =
     804          80 :       wasm::WasmModuleWrapper::From(isolate, module);
     805             : 
     806          80 :   shared->set(kModuleWrapperIndex, *module_wrapper);
     807             :   DCHECK(WasmSharedModuleData::IsWasmSharedModuleData(*shared));
     808          80 : }
     809             : 
     810             : namespace {
     811             : 
     812        1578 : int GetBreakpointPos(Isolate* isolate, Object* break_point_info_or_undef) {
     813        1578 :   if (break_point_info_or_undef->IsUndefined(isolate)) return kMaxInt;
     814         679 :   return BreakPointInfo::cast(break_point_info_or_undef)->source_position();
     815             : }
     816             : 
     817         448 : int FindBreakpointInfoInsertPos(Isolate* isolate,
     818             :                                 Handle<FixedArray> breakpoint_infos,
     819             :                                 int position) {
     820             :   // Find insert location via binary search, taking care of undefined values on
     821             :   // the right. Position is always greater than zero.
     822             :   DCHECK_LT(0, position);
     823             : 
     824             :   int left = 0;                            // inclusive
     825             :   int right = breakpoint_infos->length();  // exclusive
     826        1942 :   while (right - left > 1) {
     827        1046 :     int mid = left + (right - left) / 2;
     828             :     Object* mid_obj = breakpoint_infos->get(mid);
     829        1046 :     if (GetBreakpointPos(isolate, mid_obj) <= position) {
     830             :       left = mid;
     831             :     } else {
     832             :       right = mid;
     833             :     }
     834             :   }
     835             : 
     836         448 :   int left_pos = GetBreakpointPos(isolate, breakpoint_infos->get(left));
     837         448 :   return left_pos < position ? left + 1 : left;
     838             : }
     839             : 
     840             : }  // namespace
     841             : 
     842          94 : void WasmSharedModuleData::AddBreakpoint(Handle<WasmSharedModuleData> shared,
     843             :                                          int position,
     844             :                                          Handle<Object> break_point_object) {
     845             :   Isolate* isolate = shared->GetIsolate();
     846             :   Handle<FixedArray> breakpoint_infos;
     847          94 :   if (shared->has_breakpoint_infos()) {
     848             :     breakpoint_infos = handle(shared->breakpoint_infos(), isolate);
     849             :   } else {
     850          44 :     breakpoint_infos = isolate->factory()->NewFixedArray(4, TENURED);
     851          44 :     shared->set(kBreakPointInfosIndex, *breakpoint_infos);
     852             :   }
     853             : 
     854             :   int insert_pos =
     855          94 :       FindBreakpointInfoInsertPos(isolate, breakpoint_infos, position);
     856             : 
     857             :   // If a BreakPointInfo object already exists for this position, add the new
     858             :   // breakpoint object and return.
     859         178 :   if (insert_pos < breakpoint_infos->length() &&
     860          84 :       GetBreakpointPos(isolate, breakpoint_infos->get(insert_pos)) ==
     861             :           position) {
     862             :     Handle<BreakPointInfo> old_info(
     863             :         BreakPointInfo::cast(breakpoint_infos->get(insert_pos)), isolate);
     864           0 :     BreakPointInfo::SetBreakPoint(old_info, break_point_object);
     865          94 :     return;
     866             :   }
     867             : 
     868             :   // Enlarge break positions array if necessary.
     869             :   bool need_realloc = !breakpoint_infos->get(breakpoint_infos->length() - 1)
     870          94 :                            ->IsUndefined(isolate);
     871             :   Handle<FixedArray> new_breakpoint_infos = breakpoint_infos;
     872          94 :   if (need_realloc) {
     873             :     new_breakpoint_infos = isolate->factory()->NewFixedArray(
     874          10 :         2 * breakpoint_infos->length(), TENURED);
     875          10 :     shared->set(kBreakPointInfosIndex, *new_breakpoint_infos);
     876             :     // Copy over the entries [0, insert_pos).
     877          70 :     for (int i = 0; i < insert_pos; ++i)
     878          60 :       new_breakpoint_infos->set(i, breakpoint_infos->get(i));
     879             :   }
     880             : 
     881             :   // Move elements [insert_pos+1, ...] up by one.
     882         188 :   for (int i = insert_pos + 1; i < breakpoint_infos->length(); ++i) {
     883             :     Object* entry = breakpoint_infos->get(i);
     884          74 :     if (entry->IsUndefined(isolate)) break;
     885           0 :     new_breakpoint_infos->set(i + 1, entry);
     886             :   }
     887             : 
     888             :   // Generate new BreakpointInfo.
     889             :   Handle<BreakPointInfo> breakpoint_info =
     890          94 :       isolate->factory()->NewBreakPointInfo(position);
     891          94 :   BreakPointInfo::SetBreakPoint(breakpoint_info, break_point_object);
     892             : 
     893             :   // Now insert new position at insert_pos.
     894          94 :   new_breakpoint_infos->set(insert_pos, *breakpoint_info);
     895             : }
     896             : 
     897      152662 : void WasmSharedModuleData::SetBreakpointsOnNewInstance(
     898             :     Handle<WasmSharedModuleData> shared, Handle<WasmInstanceObject> instance) {
     899      305324 :   if (!shared->has_breakpoint_infos()) return;
     900             :   Isolate* isolate = shared->GetIsolate();
     901             :   Handle<WasmCompiledModule> compiled_module(instance->compiled_module(),
     902             :                                              isolate);
     903             :   Handle<WasmDebugInfo> debug_info =
     904           0 :       WasmInstanceObject::GetOrCreateDebugInfo(instance);
     905             : 
     906             :   Handle<FixedArray> breakpoint_infos(shared->breakpoint_infos(), isolate);
     907             :   // If the array exists, it should not be empty.
     908             :   DCHECK_LT(0, breakpoint_infos->length());
     909             : 
     910           0 :   for (int i = 0, e = breakpoint_infos->length(); i < e; ++i) {
     911             :     Handle<Object> obj(breakpoint_infos->get(i), isolate);
     912           0 :     if (obj->IsUndefined(isolate)) {
     913             :       for (; i < e; ++i) {
     914             :         DCHECK(breakpoint_infos->get(i)->IsUndefined(isolate));
     915             :       }
     916             :       break;
     917             :     }
     918             :     Handle<BreakPointInfo> breakpoint_info = Handle<BreakPointInfo>::cast(obj);
     919             :     int position = breakpoint_info->source_position();
     920             : 
     921             :     // Find the function for this breakpoint, and set the breakpoint.
     922           0 :     int func_index = compiled_module->GetContainingFunction(position);
     923             :     DCHECK_LE(0, func_index);
     924           0 :     WasmFunction& func = compiled_module->module()->functions[func_index];
     925           0 :     int offset_in_func = position - func.code.offset();
     926           0 :     WasmDebugInfo::SetBreakpoint(debug_info, func_index, offset_in_func);
     927             :   }
     928             : }
     929             : 
     930        3571 : void WasmSharedModuleData::PrepareForLazyCompilation(
     931             :     Handle<WasmSharedModuleData> shared) {
     932        3571 :   if (shared->has_lazy_compilation_orchestrator()) return;
     933             :   Isolate* isolate = shared->GetIsolate();
     934             :   auto orch_handle =
     935        3571 :       Managed<wasm::LazyCompilationOrchestrator>::Allocate(isolate);
     936        3571 :   shared->set_lazy_compilation_orchestrator(*orch_handle);
     937             : }
     938             : 
     939      185130 : Handle<WasmCompiledModule> WasmCompiledModule::New(
     940             :     Isolate* isolate, Handle<WasmSharedModuleData> shared,
     941             :     Handle<FixedArray> code_table, Handle<FixedArray> export_wrappers,
     942      186710 :     const std::vector<GlobalHandleAddress>& function_tables,
     943        1580 :     const std::vector<GlobalHandleAddress>& signature_tables) {
     944             :   DCHECK_EQ(function_tables.size(), signature_tables.size());
     945             :   Handle<FixedArray> ret =
     946      185130 :       isolate->factory()->NewFixedArray(PropertyIndices::Count, TENURED);
     947             :   // WasmCompiledModule::cast would fail since fields are not set yet.
     948             :   Handle<WasmCompiledModule> compiled_module(
     949             :       reinterpret_cast<WasmCompiledModule*>(*ret), isolate);
     950             :   compiled_module->InitId();
     951             :   compiled_module->set_shared(shared);
     952      185130 :   compiled_module->set_native_context(isolate->native_context());
     953             :   compiled_module->set_code_table(code_table);
     954             :   compiled_module->set_export_wrappers(export_wrappers);
     955             :   // TODO(mtrofin): we copy these because the order of finalization isn't
     956             :   // reliable, and we need these at Reset (which is called at
     957             :   // finalization). If the order were reliable, and top-down, we could instead
     958             :   // just get them from shared().
     959      185130 :   compiled_module->set_initial_pages(shared->module()->initial_pages);
     960             :   compiled_module->set_num_imported_functions(
     961      185130 :       shared->module()->num_imported_functions);
     962             : 
     963      185130 :   int num_function_tables = static_cast<int>(function_tables.size());
     964      185130 :   if (num_function_tables > 0) {
     965             :     Handle<FixedArray> st =
     966        1580 :         isolate->factory()->NewFixedArray(num_function_tables, TENURED);
     967             :     Handle<FixedArray> ft =
     968        1580 :         isolate->factory()->NewFixedArray(num_function_tables, TENURED);
     969        3160 :     for (int i = 0; i < num_function_tables; ++i) {
     970        1580 :       size_t index = static_cast<size_t>(i);
     971        1580 :       SetTableValue(isolate, ft, i, function_tables[index]);
     972        1580 :       SetTableValue(isolate, st, i, signature_tables[index]);
     973             :     }
     974             :     // TODO(wasm): setting the empty tables here this way is OK under the
     975             :     // assumption that we compile and then instantiate. It needs rework if we do
     976             :     // direct instantiation. The empty tables are used as a default when
     977             :     // resetting the compiled module.
     978             :     compiled_module->set_signature_tables(st);
     979             :     compiled_module->set_empty_signature_tables(st);
     980             :     compiled_module->set_function_tables(ft);
     981             :     compiled_module->set_empty_function_tables(ft);
     982             :   }
     983             : 
     984             :   // TODO(mtrofin): copy the rest of the specialization parameters over.
     985             :   // We're currently OK because we're only using defaults.
     986      185130 :   return compiled_module;
     987             : }
     988             : 
     989        6625 : Handle<WasmCompiledModule> WasmCompiledModule::Clone(
     990             :     Isolate* isolate, Handle<WasmCompiledModule> module) {
     991             :   Handle<FixedArray> code_copy =
     992        6625 :       isolate->factory()->CopyFixedArray(module->code_table());
     993             :   Handle<WasmCompiledModule> ret = Handle<WasmCompiledModule>::cast(
     994        6625 :       isolate->factory()->CopyFixedArray(module));
     995             :   ret->InitId();
     996             :   ret->set_code_table(code_copy);
     997             :   ret->reset_weak_owning_instance();
     998             :   ret->reset_weak_next_instance();
     999             :   ret->reset_weak_prev_instance();
    1000             :   ret->reset_weak_exported_functions();
    1001        6625 :   return ret;
    1002             : }
    1003             : 
    1004        7000 : void WasmCompiledModule::SetTableValue(Isolate* isolate,
    1005             :                                        Handle<FixedArray> table, int index,
    1006             :                                        Address value) {
    1007             :   Handle<HeapNumber> number = isolate->factory()->NewHeapNumber(
    1008        7000 :       static_cast<double>(reinterpret_cast<size_t>(value)), MUTABLE, TENURED);
    1009        7000 :   table->set(index, *number);
    1010        7000 : }
    1011             : 
    1012           0 : void WasmCompiledModule::UpdateTableValue(FixedArray* table, int index,
    1013             :                                           Address value) {
    1014             :   DisallowHeapAllocation no_gc;
    1015             :   HeapNumber::cast(table->get(index))
    1016        2240 :       ->set_value(static_cast<double>(reinterpret_cast<size_t>(value)));
    1017           0 : }
    1018             : 
    1019       11120 : Address WasmCompiledModule::GetTableValue(FixedArray* table, int index) {
    1020             :   DisallowHeapAllocation no_gc;
    1021             :   double value = HeapNumber::cast(table->get(index))->value();
    1022       13536 :   return reinterpret_cast<Address>(static_cast<size_t>(value));
    1023             : }
    1024             : 
    1025        1080 : void WasmCompiledModule::Reset(Isolate* isolate,
    1026             :                                WasmCompiledModule* compiled_module) {
    1027             :   DisallowHeapAllocation no_gc;
    1028             :   TRACE("Resetting %d\n", compiled_module->instance_id());
    1029             :   Object* undefined = *isolate->factory()->undefined_value();
    1030             :   Object* fct_obj = compiled_module->ptr_to_code_table();
    1031         540 :   if (fct_obj != nullptr && fct_obj != undefined) {
    1032             :     // Patch code to update memory references, global references, and function
    1033             :     // table references.
    1034         540 :     Zone specialization_zone(isolate->allocator(), ZONE_NAME);
    1035        1080 :     wasm::CodeSpecialization code_specialization(isolate, &specialization_zone);
    1036             : 
    1037             :     // Reset function tables.
    1038         540 :     if (compiled_module->has_function_tables()) {
    1039             :       FixedArray* function_tables = compiled_module->ptr_to_function_tables();
    1040             :       FixedArray* signature_tables = compiled_module->ptr_to_signature_tables();
    1041             :       FixedArray* empty_function_tables =
    1042             :           compiled_module->ptr_to_empty_function_tables();
    1043             :       FixedArray* empty_signature_tables =
    1044             :           compiled_module->ptr_to_empty_signature_tables();
    1045          44 :       if (function_tables != empty_function_tables) {
    1046             :         DCHECK_EQ(function_tables->length(), empty_function_tables->length());
    1047          88 :         for (int i = 0, e = function_tables->length(); i < e; ++i) {
    1048             :           GlobalHandleAddress func_addr =
    1049             :               WasmCompiledModule::GetTableValue(function_tables, i);
    1050             :           GlobalHandleAddress sig_addr =
    1051             :               WasmCompiledModule::GetTableValue(signature_tables, i);
    1052             :           code_specialization.RelocatePointer(
    1053             :               func_addr,
    1054          44 :               WasmCompiledModule::GetTableValue(empty_function_tables, i));
    1055             :           code_specialization.RelocatePointer(
    1056             :               sig_addr,
    1057          44 :               WasmCompiledModule::GetTableValue(empty_signature_tables, i));
    1058             :         }
    1059             :         compiled_module->set_ptr_to_function_tables(empty_function_tables);
    1060             :         compiled_module->set_ptr_to_signature_tables(empty_signature_tables);
    1061             :       }
    1062             :     }
    1063             : 
    1064             :     FixedArray* functions = FixedArray::cast(fct_obj);
    1065        3207 :     for (int i = compiled_module->num_imported_functions(),
    1066             :              end = functions->length();
    1067             :          i < end; ++i) {
    1068             :       Code* code = Code::cast(functions->get(i));
    1069             :       // Skip lazy compile stubs.
    1070        2127 :       if (code->builtin_index() == Builtins::kWasmCompileLazy) continue;
    1071        1359 :       if (code->kind() != Code::WASM_FUNCTION) {
    1072             :         // From here on, there should only be wrappers for exported functions.
    1073             :         for (; i < end; ++i) {
    1074             :           DCHECK_EQ(Code::JS_TO_WASM_FUNCTION,
    1075             :                     Code::cast(functions->get(i))->kind());
    1076             :         }
    1077             :         break;
    1078             :       }
    1079             :       bool changed =
    1080        1359 :           code_specialization.ApplyToWasmCode(code, SKIP_ICACHE_FLUSH);
    1081             :       // TODO(wasm): Check if this is faster than passing FLUSH_ICACHE_IF_NEEDED
    1082             :       // above.
    1083        1359 :       if (changed) {
    1084          56 :         Assembler::FlushICache(isolate, code->instruction_start(),
    1085         112 :                                code->instruction_size());
    1086             :       }
    1087         540 :     }
    1088             :   }
    1089         540 : }
    1090             : 
    1091           0 : void WasmCompiledModule::InitId() {
    1092             : #if DEBUG
    1093             :   static uint32_t instance_id_counter = 0;
    1094             :   set(kID_instance_id, Smi::FromInt(instance_id_counter++));
    1095             :   TRACE("New compiled module id: %d\n", instance_id());
    1096             : #endif
    1097           0 : }
    1098             : 
    1099      201684 : MaybeHandle<String> WasmCompiledModule::ExtractUtf8StringFromModuleBytes(
    1100             :     Isolate* isolate, Handle<WasmCompiledModule> compiled_module,
    1101             :     wasm::WireBytesRef ref) {
    1102             :   // TODO(wasm): cache strings from modules if it's a performance win.
    1103             :   Handle<SeqOneByteString> module_bytes(compiled_module->module_bytes(),
    1104             :                                         isolate);
    1105             :   return WasmCompiledModule::ExtractUtf8StringFromModuleBytes(
    1106      201684 :       isolate, module_bytes, ref);
    1107             : }
    1108             : 
    1109      296490 : MaybeHandle<String> WasmCompiledModule::ExtractUtf8StringFromModuleBytes(
    1110             :     Isolate* isolate, Handle<SeqOneByteString> module_bytes,
    1111             :     wasm::WireBytesRef ref) {
    1112             :   DCHECK_GE(module_bytes->length(), ref.end_offset());
    1113             :   // UTF8 validation happens at decode time.
    1114             :   DCHECK(unibrow::Utf8::ValidateEncoding(
    1115             :       reinterpret_cast<const byte*>(module_bytes->GetCharsAddress() +
    1116             :                                     ref.offset()),
    1117             :       ref.length()));
    1118             :   DCHECK_GE(kMaxInt, ref.offset());
    1119             :   DCHECK_GE(kMaxInt, ref.length());
    1120             :   return isolate->factory()->NewStringFromUtf8SubString(
    1121      296490 :       module_bytes, static_cast<int>(ref.offset()),
    1122      794664 :       static_cast<int>(ref.length()));
    1123             : }
    1124             : 
    1125           0 : bool WasmCompiledModule::IsWasmCompiledModule(Object* obj) {
    1126           0 :   if (!obj->IsFixedArray()) return false;
    1127             :   FixedArray* arr = FixedArray::cast(obj);
    1128           0 :   if (arr->length() != PropertyIndices::Count) return false;
    1129             : #define WCM_CHECK_TYPE(NAME, TYPE_CHECK) \
    1130             :   do {                                   \
    1131             :     Object* obj = arr->get(kID_##NAME);  \
    1132             :     if (!(TYPE_CHECK)) return false;     \
    1133             :   } while (false);
    1134             : // We're OK with undefined, generally, because maybe we don't
    1135             : // have a value for that item. For example, we may not have a
    1136             : // memory, or globals.
    1137             : // We're not OK with the const numbers being undefined. They are
    1138             : // expected to be initialized at construction.
    1139             : #define WCM_CHECK_OBJECT(TYPE, NAME) \
    1140             :   WCM_CHECK_TYPE(NAME, obj->IsUndefined(isolate) || obj->Is##TYPE())
    1141             : #define WCM_CHECK_CONST_OBJECT(TYPE, NAME) \
    1142             :   WCM_CHECK_TYPE(NAME, obj->IsUndefined(isolate) || obj->Is##TYPE())
    1143             : #define WCM_CHECK_WASM_OBJECT(TYPE, NAME) \
    1144             :   WCM_CHECK_TYPE(NAME, TYPE::Is##TYPE(obj))
    1145             : #define WCM_CHECK_WEAK_LINK(TYPE, NAME) WCM_CHECK_OBJECT(WeakCell, NAME)
    1146             : #define WCM_CHECK_SMALL_NUMBER(TYPE, NAME) \
    1147             :   WCM_CHECK_TYPE(NAME, obj->IsUndefined(isolate) || obj->IsSmi())
    1148             : #define WCM_CHECK(KIND, TYPE, NAME) WCM_CHECK_##KIND(TYPE, NAME)
    1149             : #define WCM_CHECK_SMALL_CONST_NUMBER(TYPE, NAME) \
    1150             :   WCM_CHECK_TYPE(NAME, obj->IsSmi())
    1151             : #undef WCM_CHECK_TYPE
    1152             : #undef WCM_CHECK_OBJECT
    1153             : #undef WCM_CHECK_CONST_OBJECT
    1154             : #undef WCM_CHECK_WASM_OBJECT
    1155             : #undef WCM_CHECK_WEAK_LINK
    1156             : #undef WCM_CHECK_SMALL_NUMBER
    1157             : #undef WCM_CHECK
    1158             : #undef WCM_CHECK_SMALL_CONST_NUMBER
    1159             : 
    1160             :   // All checks passed.
    1161           0 :   return true;
    1162             : }
    1163             : 
    1164      154832 : void WasmCompiledModule::PrintInstancesChain() {
    1165             : #if DEBUG
    1166             :   if (!FLAG_trace_wasm_instances) return;
    1167             :   for (WasmCompiledModule* current = this; current != nullptr;) {
    1168             :     PrintF("->%d", current->instance_id());
    1169             :     if (!current->has_weak_next_instance()) break;
    1170             :     DCHECK(!current->ptr_to_weak_next_instance()->cleared());
    1171             :     current =
    1172             :         WasmCompiledModule::cast(current->ptr_to_weak_next_instance()->value());
    1173             :   }
    1174             :   PrintF("\n");
    1175             : #endif
    1176      154832 : }
    1177             : 
    1178          80 : void WasmCompiledModule::ReinitializeAfterDeserialization(
    1179          40 :     Isolate* isolate, Handle<WasmCompiledModule> compiled_module) {
    1180             :   // This method must only be called immediately after deserialization.
    1181             :   // At this point, no module wrapper exists, so the shared module data is
    1182             :   // incomplete.
    1183             :   Handle<WasmSharedModuleData> shared(
    1184             :       static_cast<WasmSharedModuleData*>(compiled_module->get(kID_shared)),
    1185             :       isolate);
    1186             :   DCHECK(!WasmSharedModuleData::IsWasmSharedModuleData(*shared));
    1187          80 :   WasmSharedModuleData::ReinitializeAfterDeserialization(isolate, shared);
    1188             :   int function_table_count =
    1189         160 :       static_cast<int>(compiled_module->module()->function_tables.size());
    1190          80 :   if (function_table_count > 0) {
    1191             :     // The tables are of the right size, but contain bogus global handle
    1192             :     // addresses. Produce new global handles for the empty tables, then reset,
    1193             :     // which will relocate the code. We end up with a WasmCompiledModule as-if
    1194             :     // it were just compiled.
    1195             :     DCHECK(compiled_module->has_function_tables());
    1196             :     DCHECK(compiled_module->has_signature_tables());
    1197             :     DCHECK(compiled_module->has_empty_signature_tables());
    1198             :     DCHECK(compiled_module->has_empty_function_tables());
    1199             : 
    1200          20 :     for (int i = 0; i < function_table_count; ++i) {
    1201             :       Handle<Object> global_func_table_handle =
    1202          20 :           isolate->global_handles()->Create(isolate->heap()->undefined_value());
    1203             :       Handle<Object> global_sig_table_handle =
    1204          20 :           isolate->global_handles()->Create(isolate->heap()->undefined_value());
    1205             :       GlobalHandleAddress new_func_table = global_func_table_handle.address();
    1206             :       GlobalHandleAddress new_sig_table = global_sig_table_handle.address();
    1207             :       SetTableValue(isolate, compiled_module->empty_function_tables(), i,
    1208          20 :                     new_func_table);
    1209             :       SetTableValue(isolate, compiled_module->empty_signature_tables(), i,
    1210          20 :                     new_sig_table);
    1211             :     }
    1212             :   }
    1213             : 
    1214             :   // Reset, but don't delete any global handles, because their owning instance
    1215             :   // may still be active.
    1216          80 :   WasmCompiledModule::Reset(isolate, *compiled_module);
    1217             :   DCHECK(WasmSharedModuleData::IsWasmSharedModuleData(*shared));
    1218          80 : }
    1219             : 
    1220           0 : uint32_t WasmCompiledModule::default_mem_size() const {
    1221           0 :   return initial_pages() * WasmModule::kPageSize;
    1222             : }
    1223             : 
    1224         680 : MaybeHandle<String> WasmCompiledModule::GetModuleNameOrNull(
    1225             :     Isolate* isolate, Handle<WasmCompiledModule> compiled_module) {
    1226         680 :   WasmModule* module = compiled_module->module();
    1227         680 :   if (!module->name.is_set()) return {};
    1228             :   return WasmCompiledModule::ExtractUtf8StringFromModuleBytes(
    1229           0 :       isolate, compiled_module, module->name);
    1230             : }
    1231             : 
    1232        2015 : MaybeHandle<String> WasmCompiledModule::GetFunctionNameOrNull(
    1233             :     Isolate* isolate, Handle<WasmCompiledModule> compiled_module,
    1234             :     uint32_t func_index) {
    1235             :   DCHECK_LT(func_index, compiled_module->module()->functions.size());
    1236        4030 :   WasmFunction& function = compiled_module->module()->functions[func_index];
    1237        2015 :   if (!function.name.is_set()) return {};
    1238             :   return WasmCompiledModule::ExtractUtf8StringFromModuleBytes(
    1239        1975 :       isolate, compiled_module, function.name);
    1240             : }
    1241             : 
    1242         755 : Handle<String> WasmCompiledModule::GetFunctionName(
    1243             :     Isolate* isolate, Handle<WasmCompiledModule> compiled_module,
    1244             :     uint32_t func_index) {
    1245             :   MaybeHandle<String> name =
    1246         755 :       GetFunctionNameOrNull(isolate, compiled_module, func_index);
    1247         755 :   if (!name.is_null()) return name.ToHandleChecked();
    1248           0 :   return isolate->factory()->NewStringFromStaticChars("<WASM UNNAMED>");
    1249             : }
    1250             : 
    1251       11259 : Vector<const uint8_t> WasmCompiledModule::GetRawFunctionName(
    1252             :     uint32_t func_index) {
    1253             :   DCHECK_GT(module()->functions.size(), func_index);
    1254       11259 :   WasmFunction& function = module()->functions[func_index];
    1255             :   SeqOneByteString* bytes = module_bytes();
    1256             :   DCHECK_GE(bytes->length(), function.name.end_offset());
    1257             :   return Vector<const uint8_t>(
    1258       11259 :       bytes->GetCharsAddress() + function.name.offset(),
    1259       22518 :       function.name.length());
    1260             : }
    1261             : 
    1262       40600 : int WasmCompiledModule::GetFunctionOffset(uint32_t func_index) {
    1263       81200 :   std::vector<WasmFunction>& functions = module()->functions;
    1264       81200 :   if (static_cast<uint32_t>(func_index) >= functions.size()) return -1;
    1265             :   DCHECK_GE(kMaxInt, functions[func_index].code.offset());
    1266       40600 :   return static_cast<int>(functions[func_index].code.offset());
    1267             : }
    1268             : 
    1269         582 : int WasmCompiledModule::GetContainingFunction(uint32_t byte_offset) {
    1270         582 :   std::vector<WasmFunction>& functions = module()->functions;
    1271             : 
    1272             :   // Binary search for a function containing the given position.
    1273             :   int left = 0;                                    // inclusive
    1274         582 :   int right = static_cast<int>(functions.size());  // exclusive
    1275         582 :   if (right == 0) return false;
    1276        1122 :   while (right - left > 1) {
    1277         540 :     int mid = left + (right - left) / 2;
    1278        1080 :     if (functions[mid].code.offset() <= byte_offset) {
    1279             :       left = mid;
    1280             :     } else {
    1281             :       right = mid;
    1282             :     }
    1283             :   }
    1284             :   // If the found function does not contains the given position, return -1.
    1285         582 :   WasmFunction& func = functions[left];
    1286        1164 :   if (byte_offset < func.code.offset() ||
    1287             :       byte_offset >= func.code.end_offset()) {
    1288             :     return -1;
    1289             :   }
    1290             : 
    1291         582 :   return left;
    1292             : }
    1293             : 
    1294         488 : bool WasmCompiledModule::GetPositionInfo(uint32_t position,
    1295             :                                          Script::PositionInfo* info) {
    1296         488 :   int func_index = GetContainingFunction(position);
    1297         488 :   if (func_index < 0) return false;
    1298             : 
    1299         488 :   WasmFunction& function = module()->functions[func_index];
    1300             : 
    1301         488 :   info->line = func_index;
    1302         488 :   info->column = position - function.code.offset();
    1303         488 :   info->line_start = function.code.offset();
    1304         488 :   info->line_end = function.code.end_offset();
    1305         488 :   return true;
    1306             : }
    1307             : 
    1308             : namespace {
    1309             : 
    1310             : enum AsmJsOffsetTableEntryLayout {
    1311             :   kOTEByteOffset,
    1312             :   kOTECallPosition,
    1313             :   kOTENumberConvPosition,
    1314             :   kOTESize
    1315             : };
    1316             : 
    1317         968 : Handle<ByteArray> GetDecodedAsmJsOffsetTable(
    1318             :     Handle<WasmCompiledModule> compiled_module, Isolate* isolate) {
    1319             :   DCHECK(compiled_module->is_asm_js());
    1320             :   Handle<ByteArray> offset_table(
    1321        1936 :       compiled_module->shared()->asm_js_offset_table(), isolate);
    1322             : 
    1323             :   // The last byte in the asm_js_offset_tables ByteArray tells whether it is
    1324             :   // still encoded (0) or decoded (1).
    1325             :   enum AsmJsTableType : int { Encoded = 0, Decoded = 1 };
    1326         968 :   int table_type = offset_table->get(offset_table->length() - 1);
    1327             :   DCHECK(table_type == Encoded || table_type == Decoded);
    1328         968 :   if (table_type == Decoded) return offset_table;
    1329             : 
    1330             :   wasm::AsmJsOffsetsResult asm_offsets;
    1331             :   {
    1332             :     DisallowHeapAllocation no_gc;
    1333          78 :     const byte* bytes_start = offset_table->GetDataStartAddress();
    1334          78 :     const byte* bytes_end = bytes_start + offset_table->length() - 1;
    1335          78 :     asm_offsets = wasm::DecodeAsmJsOffsets(bytes_start, bytes_end);
    1336             :   }
    1337             :   // Wasm bytes must be valid and must contain asm.js offset table.
    1338             :   DCHECK(asm_offsets.ok());
    1339             :   DCHECK_GE(kMaxInt, asm_offsets.val.size());
    1340         156 :   int num_functions = static_cast<int>(asm_offsets.val.size());
    1341             :   int num_imported_functions =
    1342          78 :       static_cast<int>(compiled_module->module()->num_imported_functions);
    1343             :   DCHECK_EQ(compiled_module->module()->functions.size(),
    1344             :             static_cast<size_t>(num_functions) + num_imported_functions);
    1345             :   int num_entries = 0;
    1346         270 :   for (int func = 0; func < num_functions; ++func) {
    1347         384 :     size_t new_size = asm_offsets.val[func].size();
    1348             :     DCHECK_LE(new_size, static_cast<size_t>(kMaxInt) - num_entries);
    1349         192 :     num_entries += static_cast<int>(new_size);
    1350             :   }
    1351             :   // One byte to encode that this is a decoded table.
    1352             :   DCHECK_GE(kMaxInt,
    1353             :             1 + static_cast<uint64_t>(num_entries) * kOTESize * kIntSize);
    1354          78 :   int total_size = 1 + num_entries * kOTESize * kIntSize;
    1355             :   Handle<ByteArray> decoded_table =
    1356          78 :       isolate->factory()->NewByteArray(total_size, TENURED);
    1357             :   decoded_table->set(total_size - 1, AsmJsTableType::Decoded);
    1358         156 :   compiled_module->shared()->set_asm_js_offset_table(*decoded_table);
    1359             : 
    1360             :   int idx = 0;
    1361         192 :   std::vector<WasmFunction>& wasm_funs = compiled_module->module()->functions;
    1362         270 :   for (int func = 0; func < num_functions; ++func) {
    1363             :     std::vector<wasm::AsmJsOffsetEntry>& func_asm_offsets =
    1364         192 :         asm_offsets.val[func];
    1365         192 :     if (func_asm_offsets.empty()) continue;
    1366         228 :     int func_offset = wasm_funs[num_imported_functions + func].code.offset();
    1367         480 :     for (wasm::AsmJsOffsetEntry& e : func_asm_offsets) {
    1368             :       // Byte offsets must be strictly monotonously increasing:
    1369             :       DCHECK_IMPLIES(idx > 0, func_offset + e.byte_offset >
    1370             :                                   decoded_table->get_int(idx - kOTESize));
    1371         252 :       decoded_table->set_int(idx + kOTEByteOffset, func_offset + e.byte_offset);
    1372         252 :       decoded_table->set_int(idx + kOTECallPosition, e.source_position_call);
    1373             :       decoded_table->set_int(idx + kOTENumberConvPosition,
    1374         252 :                              e.source_position_number_conversion);
    1375         252 :       idx += kOTESize;
    1376             :     }
    1377             :   }
    1378             :   DCHECK_EQ(total_size, idx * kIntSize + 1);
    1379          78 :   return decoded_table;
    1380             : }
    1381             : 
    1382             : }  // namespace
    1383             : 
    1384       41126 : int WasmCompiledModule::GetSourcePosition(
    1385             :     Handle<WasmCompiledModule> compiled_module, uint32_t func_index,
    1386             :     uint32_t byte_offset, bool is_at_number_conversion) {
    1387             :   Isolate* isolate = compiled_module->GetIsolate();
    1388       41126 :   const WasmModule* module = compiled_module->module();
    1389             : 
    1390       41126 :   if (!module->is_asm_js()) {
    1391             :     // for non-asm.js modules, we just add the function's start offset
    1392             :     // to make a module-relative position.
    1393       40158 :     return byte_offset + compiled_module->GetFunctionOffset(func_index);
    1394             :   }
    1395             : 
    1396             :   // asm.js modules have an additional offset table that must be searched.
    1397             :   Handle<ByteArray> offset_table =
    1398         968 :       GetDecodedAsmJsOffsetTable(compiled_module, isolate);
    1399             : 
    1400             :   DCHECK_LT(func_index, module->functions.size());
    1401        1936 :   uint32_t func_code_offset = module->functions[func_index].code.offset();
    1402         968 :   uint32_t total_offset = func_code_offset + byte_offset;
    1403             : 
    1404             :   // Binary search for the total byte offset.
    1405             :   int left = 0;                                              // inclusive
    1406         968 :   int right = offset_table->length() / kIntSize / kOTESize;  // exclusive
    1407             :   DCHECK_LT(left, right);
    1408        3772 :   while (right - left > 1) {
    1409        1836 :     int mid = left + (right - left) / 2;
    1410        1836 :     int mid_entry = offset_table->get_int(kOTESize * mid);
    1411             :     DCHECK_GE(kMaxInt, mid_entry);
    1412        1836 :     if (static_cast<uint32_t>(mid_entry) <= total_offset) {
    1413             :       left = mid;
    1414             :     } else {
    1415             :       right = mid;
    1416             :     }
    1417             :   }
    1418             :   // There should be an entry for each position that could show up on the stack
    1419             :   // trace:
    1420             :   DCHECK_EQ(total_offset, offset_table->get_int(kOTESize * left));
    1421         968 :   int idx = is_at_number_conversion ? kOTENumberConvPosition : kOTECallPosition;
    1422        1936 :   return offset_table->get_int(kOTESize * left + idx);
    1423             : }
    1424             : 
    1425          89 : v8::debug::WasmDisassembly WasmCompiledModule::DisassembleFunction(
    1426             :     int func_index) {
    1427             :   DisallowHeapAllocation no_gc;
    1428             : 
    1429         178 :   if (func_index < 0 ||
    1430          89 :       static_cast<uint32_t>(func_index) >= module()->functions.size())
    1431             :     return {};
    1432             : 
    1433             :   SeqOneByteString* module_bytes_str = module_bytes();
    1434          89 :   Vector<const byte> module_bytes(module_bytes_str->GetChars(),
    1435          89 :                                   module_bytes_str->length());
    1436             : 
    1437          89 :   std::ostringstream disassembly_os;
    1438             :   v8::debug::WasmDisassembly::OffsetTable offset_table;
    1439             : 
    1440          89 :   PrintWasmText(module(), module_bytes, static_cast<uint32_t>(func_index),
    1441         178 :                 disassembly_os, &offset_table);
    1442             : 
    1443         178 :   return {disassembly_os.str(), std::move(offset_table)};
    1444             : }
    1445             : 
    1446          72 : bool WasmCompiledModule::GetPossibleBreakpoints(
    1447             :     const v8::debug::Location& start, const v8::debug::Location& end,
    1448             :     std::vector<v8::debug::BreakLocation>* locations) {
    1449             :   DisallowHeapAllocation no_gc;
    1450             : 
    1451         380 :   std::vector<WasmFunction>& functions = module()->functions;
    1452         216 :   if (start.GetLineNumber() < 0 || start.GetColumnNumber() < 0 ||
    1453         144 :       (!end.IsEmpty() &&
    1454         144 :        (end.GetLineNumber() < 0 || end.GetColumnNumber() < 0)))
    1455             :     return false;
    1456             : 
    1457             :   // start_func_index, start_offset and end_func_index is inclusive.
    1458             :   // end_offset is exclusive.
    1459             :   // start_offset and end_offset are module-relative byte offsets.
    1460          72 :   uint32_t start_func_index = start.GetLineNumber();
    1461         144 :   if (start_func_index >= functions.size()) return false;
    1462          72 :   int start_func_len = functions[start_func_index].code.length();
    1463          72 :   if (start.GetColumnNumber() > start_func_len) return false;
    1464             :   uint32_t start_offset =
    1465          66 :       functions[start_func_index].code.offset() + start.GetColumnNumber();
    1466             :   uint32_t end_func_index;
    1467             :   uint32_t end_offset;
    1468          66 :   if (end.IsEmpty()) {
    1469             :     // Default: everything till the end of the Script.
    1470           0 :     end_func_index = static_cast<uint32_t>(functions.size() - 1);
    1471           0 :     end_offset = functions[end_func_index].code.end_offset();
    1472             :   } else {
    1473             :     // If end is specified: Use it and check for valid input.
    1474          66 :     end_func_index = static_cast<uint32_t>(end.GetLineNumber());
    1475             : 
    1476             :     // Special case: Stop before the start of the next function. Change to: Stop
    1477             :     // at the end of the function before, such that we don't disassemble the
    1478             :     // next function also.
    1479          66 :     if (end.GetColumnNumber() == 0 && end_func_index > 0) {
    1480          28 :       --end_func_index;
    1481          28 :       end_offset = functions[end_func_index].code.end_offset();
    1482             :     } else {
    1483          76 :       if (end_func_index >= functions.size()) return false;
    1484             :       end_offset =
    1485          38 :           functions[end_func_index].code.offset() + end.GetColumnNumber();
    1486          38 :       if (end_offset > functions[end_func_index].code.end_offset())
    1487             :         return false;
    1488             :     }
    1489             :   }
    1490             : 
    1491          66 :   AccountingAllocator alloc;
    1492         132 :   Zone tmp(&alloc, ZONE_NAME);
    1493          66 :   const byte* module_start = module_bytes()->GetChars();
    1494             : 
    1495         132 :   for (uint32_t func_idx = start_func_index; func_idx <= end_func_index;
    1496             :        ++func_idx) {
    1497          66 :     WasmFunction& func = functions[func_idx];
    1498         358 :     if (func.code.length() == 0) continue;
    1499             : 
    1500             :     wasm::BodyLocalDecls locals(&tmp);
    1501             :     wasm::BytecodeIterator iterator(module_start + func.code.offset(),
    1502             :                                     module_start + func.code.end_offset(),
    1503          66 :                                     &locals);
    1504             :     DCHECK_LT(0u, locals.encoded_size);
    1505         623 :     for (uint32_t offset : iterator.offsets()) {
    1506         292 :       uint32_t total_offset = func.code.offset() + offset;
    1507         292 :       if (total_offset >= end_offset) {
    1508             :         DCHECK_EQ(end_func_index, func_idx);
    1509             :         break;
    1510             :       }
    1511         265 :       if (total_offset < start_offset) continue;
    1512         150 :       locations->emplace_back(func_idx, offset, debug::kCommonBreakLocation);
    1513             :     }
    1514             :   }
    1515          66 :   return true;
    1516             : }
    1517             : 
    1518          94 : bool WasmCompiledModule::SetBreakPoint(
    1519             :     Handle<WasmCompiledModule> compiled_module, int* position,
    1520             :     Handle<Object> break_point_object) {
    1521             :   Isolate* isolate = compiled_module->GetIsolate();
    1522             : 
    1523             :   // Find the function for this breakpoint.
    1524          94 :   int func_index = compiled_module->GetContainingFunction(*position);
    1525          94 :   if (func_index < 0) return false;
    1526         188 :   WasmFunction& func = compiled_module->module()->functions[func_index];
    1527          94 :   int offset_in_func = *position - func.code.offset();
    1528             : 
    1529             :   // According to the current design, we should only be called with valid
    1530             :   // breakable positions.
    1531             :   DCHECK(IsBreakablePosition(compiled_module, func_index, offset_in_func));
    1532             : 
    1533             :   // Insert new break point into break_positions of shared module data.
    1534             :   WasmSharedModuleData::AddBreakpoint(compiled_module->shared(), *position,
    1535          94 :                                       break_point_object);
    1536             : 
    1537             :   // Iterate over all instances of this module and tell them to set this new
    1538             :   // breakpoint.
    1539         164 :   for (Handle<WasmInstanceObject> instance :
    1540         234 :        iterate_compiled_module_instance_chain(isolate, compiled_module)) {
    1541             :     Handle<WasmDebugInfo> debug_info =
    1542          70 :         WasmInstanceObject::GetOrCreateDebugInfo(instance);
    1543          70 :     WasmDebugInfo::SetBreakpoint(debug_info, func_index, offset_in_func);
    1544             :   }
    1545             : 
    1546          94 :   return true;
    1547             : }
    1548             : 
    1549         354 : MaybeHandle<FixedArray> WasmCompiledModule::CheckBreakPoints(int position) {
    1550         109 :   Isolate* isolate = GetIsolate();
    1551         708 :   if (!shared()->has_breakpoint_infos()) return {};
    1552             : 
    1553         708 :   Handle<FixedArray> breakpoint_infos(shared()->breakpoint_infos(), isolate);
    1554             :   int insert_pos =
    1555         354 :       FindBreakpointInfoInsertPos(isolate, breakpoint_infos, position);
    1556         354 :   if (insert_pos >= breakpoint_infos->length()) return {};
    1557             : 
    1558             :   Handle<Object> maybe_breakpoint_info(breakpoint_infos->get(insert_pos),
    1559             :                                        isolate);
    1560         354 :   if (maybe_breakpoint_info->IsUndefined(isolate)) return {};
    1561             :   Handle<BreakPointInfo> breakpoint_info =
    1562             :       Handle<BreakPointInfo>::cast(maybe_breakpoint_info);
    1563         180 :   if (breakpoint_info->source_position() != position) return {};
    1564             : 
    1565             :   Handle<Object> breakpoint_objects(breakpoint_info->break_point_objects(),
    1566             :                                     isolate);
    1567         109 :   return isolate->debug()->GetHitBreakPointObjects(breakpoint_objects);
    1568             : }
    1569             : 
    1570       11477 : Handle<Code> WasmCompiledModule::CompileLazy(
    1571             :     Isolate* isolate, Handle<WasmInstanceObject> instance, Handle<Code> caller,
    1572             :     int offset, int func_index, bool patch_caller) {
    1573       22954 :   isolate->set_context(*instance->compiled_module()->native_context());
    1574             :   Object* orch_obj =
    1575       22954 :       instance->compiled_module()->shared()->lazy_compilation_orchestrator();
    1576             :   auto* orch =
    1577             :       Managed<wasm::LazyCompilationOrchestrator>::cast(orch_obj)->get();
    1578             :   return orch->CompileLazy(isolate, instance, caller, offset, func_index,
    1579       11477 :                            patch_caller);
    1580             : }
    1581             : 
    1582             : #undef TRACE
    1583             : 
    1584             : }  // namespace internal
    1585             : }  // namespace v8

Generated by: LCOV version 1.10