LCOV - code coverage report
Current view: top level - src/wasm - wasm-objects.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 525 555 94.6 %
Date: 2017-04-26 Functions: 99 117 84.6 %

          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/wasm/module-decoder.h"
      14             : #include "src/wasm/wasm-code-specialization.h"
      15             : #include "src/wasm/wasm-module.h"
      16             : #include "src/wasm/wasm-text.h"
      17             : 
      18             : #define TRACE(...)                                      \
      19             :   do {                                                  \
      20             :     if (FLAG_trace_wasm_instances) PrintF(__VA_ARGS__); \
      21             :   } while (false)
      22             : 
      23             : #define TRACE_CHAIN(instance)        \
      24             :   do {                               \
      25             :     instance->PrintInstancesChain(); \
      26             :   } while (false)
      27             : 
      28             : using namespace v8::internal;
      29             : using namespace v8::internal::wasm;
      30             : 
      31             : #define DEFINE_GETTER0(getter, Container, name, field, type) \
      32             :   type* Container::name() { return type::cast(getter(field)); }
      33             : 
      34             : #define DEFINE_ACCESSORS0(getter, setter, Container, name, field, type) \
      35             :   DEFINE_GETTER0(getter, Container, name, field, type)                  \
      36             :   void Container::set_##name(type* value) { return setter(field, value); }
      37             : 
      38             : #define DEFINE_OPTIONAL_ACCESSORS0(getter, setter, Container, name, field, \
      39             :                                    type)                                   \
      40             :   DEFINE_ACCESSORS0(getter, setter, Container, name, field, type)          \
      41             :   bool Container::has_##name() {                                           \
      42             :     return !getter(field)->IsUndefined(GetIsolate());                      \
      43             :   }
      44             : 
      45             : #define DEFINE_OPTIONAL_GETTER0(getter, Container, name, field, type) \
      46             :   DEFINE_GETTER0(getter, Container, name, field, type)                \
      47             :   bool Container::has_##name() {                                      \
      48             :     return !getter(field)->IsUndefined(GetIsolate());                 \
      49             :   }
      50             : 
      51             : #define DEFINE_GETTER0(getter, Container, name, field, type) \
      52             :   type* Container::name() { return type::cast(getter(field)); }
      53             : 
      54             : #define DEFINE_OBJ_GETTER(Container, name, field, type) \
      55             :   DEFINE_GETTER0(GetEmbedderField, Container, name, field, type)
      56             : #define DEFINE_OBJ_ACCESSORS(Container, name, field, type)               \
      57             :   DEFINE_ACCESSORS0(GetEmbedderField, SetEmbedderField, Container, name, \
      58             :                     field, type)
      59             : #define DEFINE_OPTIONAL_OBJ_ACCESSORS(Container, name, field, type)         \
      60             :   DEFINE_OPTIONAL_ACCESSORS0(GetEmbedderField, SetEmbedderField, Container, \
      61             :                              name, field, type)
      62             : #define DEFINE_ARR_GETTER(Container, name, field, type) \
      63             :   DEFINE_GETTER0(get, Container, name, field, type)
      64             : #define DEFINE_ARR_ACCESSORS(Container, name, field, type) \
      65             :   DEFINE_ACCESSORS0(get, set, Container, name, field, type)
      66             : #define DEFINE_OPTIONAL_ARR_ACCESSORS(Container, name, field, type) \
      67             :   DEFINE_OPTIONAL_ACCESSORS0(get, set, Container, name, field, type)
      68             : #define DEFINE_OPTIONAL_ARR_GETTER(Container, name, field, type) \
      69             :   DEFINE_OPTIONAL_GETTER0(get, Container, name, field, type)
      70             : 
      71             : namespace {
      72             : 
      73             : // An iterator that returns first the module itself, then all modules linked via
      74             : // next, then all linked via prev.
      75             : class CompiledModulesIterator
      76             :     : public std::iterator<std::input_iterator_tag,
      77             :                            Handle<WasmCompiledModule>> {
      78             :  public:
      79             :   CompiledModulesIterator(Isolate* isolate,
      80             :                           Handle<WasmCompiledModule> start_module, bool at_end)
      81             :       : isolate_(isolate),
      82             :         start_module_(start_module),
      83         212 :         current_(at_end ? Handle<WasmCompiledModule>::null() : start_module) {}
      84             : 
      85             :   Handle<WasmCompiledModule> operator*() const {
      86             :     DCHECK(!current_.is_null());
      87             :     return current_;
      88             :   }
      89             : 
      90         106 :   void operator++() { Advance(); }
      91             : 
      92             :   bool operator!=(const CompiledModulesIterator& other) {
      93             :     DCHECK(start_module_.is_identical_to(other.start_module_));
      94             :     return !current_.is_identical_to(other.current_);
      95             :   }
      96             : 
      97             :  private:
      98         106 :   void Advance() {
      99             :     DCHECK(!current_.is_null());
     100         106 :     if (!is_backwards_) {
     101         106 :       if (current_->has_weak_next_instance()) {
     102             :         WeakCell* weak_next = current_->ptr_to_weak_next_instance();
     103           0 :         if (!weak_next->cleared()) {
     104             :           current_ =
     105           0 :               handle(WasmCompiledModule::cast(weak_next->value()), isolate_);
     106           0 :           return;
     107             :         }
     108             :       }
     109             :       // No more modules in next-links, now try the previous-links.
     110         106 :       is_backwards_ = true;
     111         106 :       current_ = start_module_;
     112             :     }
     113         106 :     if (current_->has_weak_prev_instance()) {
     114             :       WeakCell* weak_prev = current_->ptr_to_weak_prev_instance();
     115           0 :       if (!weak_prev->cleared()) {
     116             :         current_ =
     117           0 :             handle(WasmCompiledModule::cast(weak_prev->value()), isolate_);
     118           0 :         return;
     119             :       }
     120             :     }
     121         106 :     current_ = Handle<WasmCompiledModule>::null();
     122             :   }
     123             : 
     124             :   friend class CompiledModuleInstancesIterator;
     125             :   Isolate* isolate_;
     126             :   Handle<WasmCompiledModule> start_module_;
     127             :   Handle<WasmCompiledModule> current_;
     128             :   bool is_backwards_ = false;
     129             : };
     130             : 
     131             : // An iterator based on the CompiledModulesIterator, but it returns all live
     132             : // instances, not the WasmCompiledModules itself.
     133             : class CompiledModuleInstancesIterator
     134             :     : public std::iterator<std::input_iterator_tag,
     135             :                            Handle<WasmInstanceObject>> {
     136             :  public:
     137         212 :   CompiledModuleInstancesIterator(Isolate* isolate,
     138             :                                   Handle<WasmCompiledModule> start_module,
     139             :                                   bool at_end)
     140             :       : it(isolate, start_module, at_end) {
     141         268 :     while (NeedToAdvance()) ++it;
     142         212 :   }
     143             : 
     144          78 :   Handle<WasmInstanceObject> operator*() {
     145             :     return handle(
     146             :         WasmInstanceObject::cast((*it)->weak_owning_instance()->value()),
     147         234 :         it.isolate_);
     148             :   }
     149             : 
     150          78 :   void operator++() {
     151          78 :     do {
     152          78 :       ++it;
     153             :     } while (NeedToAdvance());
     154          78 :   }
     155             : 
     156             :   bool operator!=(const CompiledModuleInstancesIterator& other) {
     157             :     return it != other.it;
     158             :   }
     159             : 
     160             :  private:
     161         318 :   bool NeedToAdvance() {
     162         424 :     return !it.current_.is_null() &&
     163         184 :            (!it.current_->has_weak_owning_instance() ||
     164         318 :             it.current_->ptr_to_weak_owning_instance()->cleared());
     165             :   }
     166             :   CompiledModulesIterator it;
     167             : };
     168             : 
     169             : v8::base::iterator_range<CompiledModuleInstancesIterator>
     170         106 : iterate_compiled_module_instance_chain(
     171             :     Isolate* isolate, Handle<WasmCompiledModule> compiled_module) {
     172             :   return {CompiledModuleInstancesIterator(isolate, compiled_module, false),
     173         212 :           CompiledModuleInstancesIterator(isolate, compiled_module, true)};
     174             : }
     175             : 
     176             : #ifdef DEBUG
     177             : bool IsBreakablePosition(Handle<WasmCompiledModule> compiled_module,
     178             :                          int func_index, int offset_in_func) {
     179             :   DisallowHeapAllocation no_gc;
     180             :   AccountingAllocator alloc;
     181             :   Zone tmp(&alloc, ZONE_NAME);
     182             :   BodyLocalDecls locals(&tmp);
     183             :   const byte* module_start = compiled_module->module_bytes()->GetChars();
     184             :   WasmFunction& func = compiled_module->module()->functions[func_index];
     185             :   BytecodeIterator iterator(module_start + func.code_start_offset,
     186             :                             module_start + func.code_end_offset, &locals);
     187             :   DCHECK_LT(0, locals.encoded_size);
     188             :   for (uint32_t offset : iterator.offsets()) {
     189             :     if (offset > static_cast<uint32_t>(offset_in_func)) break;
     190             :     if (offset == static_cast<uint32_t>(offset_in_func)) return true;
     191             :   }
     192             :   return false;
     193             : }
     194             : #endif  // DEBUG
     195             : 
     196             : }  // namespace
     197             : 
     198       15955 : Handle<WasmModuleObject> WasmModuleObject::New(
     199             :     Isolate* isolate, Handle<WasmCompiledModule> compiled_module) {
     200       15955 :   WasmModule* module = compiled_module->module();
     201             :   Handle<JSObject> module_object;
     202       15955 :   if (module->is_wasm()) {
     203             :     Handle<JSFunction> module_cons(
     204       24678 :         isolate->native_context()->wasm_module_constructor());
     205       12339 :     module_object = isolate->factory()->NewJSObject(module_cons);
     206       24678 :     Handle<Symbol> module_sym(isolate->native_context()->wasm_module_sym());
     207             :     Object::SetProperty(module_object, module_sym, module_object, STRICT)
     208       24678 :         .Check();
     209             :   } else {
     210             :     DCHECK(module->is_asm_js());
     211             :     Handle<Map> map = isolate->factory()->NewMap(
     212             :         JS_OBJECT_TYPE,
     213        3616 :         JSObject::kHeaderSize + WasmModuleObject::kFieldCount * kPointerSize);
     214        3616 :     module_object = isolate->factory()->NewJSObjectFromMap(map, TENURED);
     215             :   }
     216             :   module_object->SetEmbedderField(WasmModuleObject::kCompiledModule,
     217       15955 :                                   *compiled_module);
     218             :   Handle<WeakCell> link_to_module =
     219       15955 :       isolate->factory()->NewWeakCell(module_object);
     220             :   compiled_module->set_weak_wasm_module(link_to_module);
     221       15955 :   return Handle<WasmModuleObject>::cast(module_object);
     222             : }
     223             : 
     224       87606 : WasmModuleObject* WasmModuleObject::cast(Object* object) {
     225             :   DCHECK(object->IsJSObject());
     226             :   // TODO(titzer): brand check for WasmModuleObject.
     227       87606 :   return reinterpret_cast<WasmModuleObject*>(object);
     228             : }
     229             : 
     230         210 : bool WasmModuleObject::IsWasmModuleObject(Object* object) {
     231         420 :   return object->IsJSObject() &&
     232         420 :          JSObject::cast(object)->GetEmbedderFieldCount() == kFieldCount;
     233             : }
     234             : 
     235      287524 : DEFINE_OBJ_GETTER(WasmModuleObject, compiled_module, kCompiledModule,
     236             :                   WasmCompiledModule)
     237             : 
     238        1147 : Handle<WasmTableObject> WasmTableObject::New(Isolate* isolate, uint32_t initial,
     239             :                                              int64_t maximum,
     240             :                                              Handle<FixedArray>* js_functions) {
     241             :   Handle<JSFunction> table_ctor(
     242        2294 :       isolate->native_context()->wasm_table_constructor());
     243        1147 :   Handle<JSObject> table_obj = isolate->factory()->NewJSObject(table_ctor);
     244             :   table_obj->SetEmbedderField(kWrapperTracerHeader, Smi::kZero);
     245             : 
     246        1147 :   *js_functions = isolate->factory()->NewFixedArray(initial);
     247        1147 :   Object* null = isolate->heap()->null_value();
     248        6711 :   for (int i = 0; i < static_cast<int>(initial); ++i) {
     249        5564 :     (*js_functions)->set(i, null);
     250             :   }
     251        1147 :   table_obj->SetEmbedderField(kFunctions, *(*js_functions));
     252        1147 :   Handle<Object> max = isolate->factory()->NewNumber(maximum);
     253        1147 :   table_obj->SetEmbedderField(kMaximum, *max);
     254             : 
     255        1147 :   Handle<FixedArray> dispatch_tables = isolate->factory()->NewFixedArray(0);
     256        1147 :   table_obj->SetEmbedderField(kDispatchTables, *dispatch_tables);
     257        2294 :   Handle<Symbol> table_sym(isolate->native_context()->wasm_table_sym());
     258        2294 :   Object::SetProperty(table_obj, table_sym, table_obj, STRICT).Check();
     259        1147 :   return Handle<WasmTableObject>::cast(table_obj);
     260             : }
     261             : 
     262        6960 : DEFINE_OBJ_GETTER(WasmTableObject, dispatch_tables, kDispatchTables, FixedArray)
     263             : 
     264        1934 : Handle<FixedArray> WasmTableObject::AddDispatchTable(
     265             :     Isolate* isolate, Handle<WasmTableObject> table_obj,
     266             :     Handle<WasmInstanceObject> instance, int table_index,
     267             :     Handle<FixedArray> function_table, Handle<FixedArray> signature_table) {
     268             :   Handle<FixedArray> dispatch_tables(
     269             :       FixedArray::cast(table_obj->GetEmbedderField(kDispatchTables)), isolate);
     270             :   DCHECK_EQ(0, dispatch_tables->length() % 4);
     271             : 
     272        1934 :   if (instance.is_null()) return dispatch_tables;
     273             :   // TODO(titzer): use weak cells here to avoid leaking instances.
     274             : 
     275             :   // Grow the dispatch table and add a new triple at the end.
     276             :   Handle<FixedArray> new_dispatch_tables =
     277         967 :       isolate->factory()->CopyFixedArrayAndGrow(dispatch_tables, 4);
     278             : 
     279         967 :   new_dispatch_tables->set(dispatch_tables->length() + 0, *instance);
     280             :   new_dispatch_tables->set(dispatch_tables->length() + 1,
     281             :                            Smi::FromInt(table_index));
     282        1934 :   new_dispatch_tables->set(dispatch_tables->length() + 2, *function_table);
     283        1934 :   new_dispatch_tables->set(dispatch_tables->length() + 3, *signature_table);
     284             : 
     285             :   table_obj->SetEmbedderField(WasmTableObject::kDispatchTables,
     286         967 :                               *new_dispatch_tables);
     287             : 
     288         967 :   return new_dispatch_tables;
     289             : }
     290             : 
     291       33540 : DEFINE_OBJ_ACCESSORS(WasmTableObject, functions, kFunctions, FixedArray)
     292             : 
     293        9390 : uint32_t WasmTableObject::current_length() { return functions()->length(); }
     294             : 
     295           0 : bool WasmTableObject::has_maximum_length() {
     296           0 :   return GetEmbedderField(kMaximum)->Number() >= 0;
     297             : }
     298             : 
     299        1155 : int64_t WasmTableObject::maximum_length() {
     300        1155 :   return static_cast<int64_t>(GetEmbedderField(kMaximum)->Number());
     301             : }
     302             : 
     303       21375 : WasmTableObject* WasmTableObject::cast(Object* object) {
     304             :   DCHECK(object && object->IsJSObject());
     305             :   // TODO(titzer): brand check for WasmTableObject.
     306       21375 :   return reinterpret_cast<WasmTableObject*>(object);
     307             : }
     308             : 
     309         255 : void WasmTableObject::Grow(Isolate* isolate, Handle<WasmTableObject> table,
     310             :                            uint32_t count) {
     311             :   Handle<FixedArray> dispatch_tables(table->dispatch_tables());
     312             :   wasm::GrowDispatchTables(isolate, dispatch_tables,
     313         255 :                            table->functions()->length(), count);
     314         255 : }
     315             : 
     316             : namespace {
     317             : 
     318        1631 : Handle<JSArrayBuffer> GrowMemoryBuffer(Isolate* isolate,
     319             :                                        Handle<JSArrayBuffer> old_buffer,
     320             :                                        uint32_t pages, uint32_t max_pages) {
     321             :   Address old_mem_start = nullptr;
     322             :   uint32_t old_size = 0;
     323        1631 :   if (!old_buffer.is_null()) {
     324             :     DCHECK(old_buffer->byte_length()->IsNumber());
     325             :     old_mem_start = static_cast<Address>(old_buffer->backing_store());
     326        1541 :     old_size = old_buffer->byte_length()->Number();
     327             :   }
     328             :   DCHECK_GE(std::numeric_limits<uint32_t>::max(),
     329             :             old_size + pages * WasmModule::kPageSize);
     330        1631 :   uint32_t new_size = old_size + pages * WasmModule::kPageSize;
     331        3187 :   if (new_size <= old_size || max_pages * WasmModule::kPageSize < new_size ||
     332        1556 :       FLAG_wasm_max_mem_pages * WasmModule::kPageSize < new_size) {
     333             :     return Handle<JSArrayBuffer>::null();
     334             :   }
     335             : 
     336             :   // TODO(gdeepti): Change the protection here instead of allocating a new
     337             :   // buffer before guard regions are turned on, see issue #5886.
     338             :   const bool enable_guard_regions =
     339        1630 :       (old_buffer.is_null() && EnableGuardRegions()) ||
     340        1450 :       (!old_buffer.is_null() && old_buffer->has_guard_region());
     341             :   Handle<JSArrayBuffer> new_buffer =
     342        1540 :       NewArrayBuffer(isolate, new_size, enable_guard_regions);
     343        1540 :   if (new_buffer.is_null()) return new_buffer;
     344             :   Address new_mem_start = static_cast<Address>(new_buffer->backing_store());
     345        1540 :   memcpy(new_mem_start, old_mem_start, old_size);
     346        1540 :   return new_buffer;
     347             : }
     348             : 
     349             : // May GC, because SetSpecializationMemInfoFrom may GC
     350        4773 : void SetInstanceMemory(Isolate* isolate, Handle<WasmInstanceObject> instance,
     351             :                        Handle<JSArrayBuffer> buffer) {
     352             :   instance->set_memory_buffer(*buffer);
     353             :   WasmCompiledModule::SetSpecializationMemInfoFrom(
     354        4773 :       isolate->factory(), handle(instance->compiled_module()), buffer);
     355        4773 :   if (instance->has_debug_info()) {
     356          30 :     instance->debug_info()->UpdateMemory(*buffer);
     357             :   }
     358        4773 : }
     359             : 
     360        9546 : void UncheckedUpdateInstanceMemory(Isolate* isolate,
     361             :                                    Handle<WasmInstanceObject> instance,
     362             :                                    Address old_mem_start, uint32_t old_size) {
     363             :   DCHECK(instance->has_memory_buffer());
     364             :   Handle<JSArrayBuffer> mem_buffer(instance->memory_buffer());
     365        4773 :   uint32_t new_size = mem_buffer->byte_length()->Number();
     366             :   Address new_mem_start = static_cast<Address>(mem_buffer->backing_store());
     367             :   DCHECK_NOT_NULL(new_mem_start);
     368        4773 :   Zone specialization_zone(isolate->allocator(), ZONE_NAME);
     369        9546 :   CodeSpecialization code_specialization(isolate, &specialization_zone);
     370             :   code_specialization.RelocateMemoryReferences(old_mem_start, old_size,
     371        4773 :                                                new_mem_start, new_size);
     372        9546 :   code_specialization.ApplyToWholeInstance(*instance);
     373        4773 : }
     374             : 
     375             : }  // namespace
     376             : 
     377        1569 : Handle<WasmMemoryObject> WasmMemoryObject::New(Isolate* isolate,
     378             :                                                Handle<JSArrayBuffer> buffer,
     379             :                                                int32_t maximum) {
     380             :   Handle<JSFunction> memory_ctor(
     381        3138 :       isolate->native_context()->wasm_memory_constructor());
     382             :   Handle<JSObject> memory_obj =
     383        1569 :       isolate->factory()->NewJSObject(memory_ctor, TENURED);
     384             :   memory_obj->SetEmbedderField(kWrapperTracerHeader, Smi::kZero);
     385             :   buffer.is_null() ? memory_obj->SetEmbedderField(
     386          30 :                          kArrayBuffer, isolate->heap()->undefined_value())
     387        3123 :                    : memory_obj->SetEmbedderField(kArrayBuffer, *buffer);
     388        1569 :   Handle<Object> max = isolate->factory()->NewNumber(maximum);
     389        1569 :   memory_obj->SetEmbedderField(kMaximum, *max);
     390        3138 :   Handle<Symbol> memory_sym(isolate->native_context()->wasm_memory_sym());
     391        3138 :   Object::SetProperty(memory_obj, memory_sym, memory_obj, STRICT).Check();
     392        1569 :   return Handle<WasmMemoryObject>::cast(memory_obj);
     393             : }
     394             : 
     395       11675 : DEFINE_OPTIONAL_OBJ_ACCESSORS(WasmMemoryObject, buffer, kArrayBuffer,
     396             :                               JSArrayBuffer)
     397        7281 : DEFINE_OPTIONAL_OBJ_ACCESSORS(WasmMemoryObject, instances_link, kInstancesLink,
     398             :                               WasmInstanceWrapper)
     399             : 
     400           0 : uint32_t WasmMemoryObject::current_pages() {
     401             :   uint32_t byte_length;
     402           0 :   CHECK(buffer()->byte_length()->ToUint32(&byte_length));
     403           0 :   return byte_length / wasm::WasmModule::kPageSize;
     404             : }
     405             : 
     406         997 : bool WasmMemoryObject::has_maximum_pages() {
     407         997 :   return GetEmbedderField(kMaximum)->Number() >= 0;
     408             : }
     409             : 
     410        2512 : int32_t WasmMemoryObject::maximum_pages() {
     411        2512 :   return static_cast<int32_t>(GetEmbedderField(kMaximum)->Number());
     412             : }
     413             : 
     414        4275 : WasmMemoryObject* WasmMemoryObject::cast(Object* object) {
     415             :   DCHECK(object && object->IsJSObject());
     416             :   // TODO(titzer): brand check for WasmMemoryObject.
     417        4275 :   return reinterpret_cast<WasmMemoryObject*>(object);
     418             : }
     419             : 
     420        1742 : void WasmMemoryObject::AddInstance(Isolate* isolate,
     421             :                                    Handle<WasmInstanceObject> instance) {
     422             :   Handle<WasmInstanceWrapper> instance_wrapper =
     423             :       handle(instance->instance_wrapper());
     424        1742 :   if (has_instances_link()) {
     425             :     Handle<WasmInstanceWrapper> current_wrapper(instances_link());
     426             :     DCHECK(WasmInstanceWrapper::IsWasmInstanceWrapper(*current_wrapper));
     427             :     DCHECK(!current_wrapper->has_previous());
     428             :     instance_wrapper->set_next_wrapper(*current_wrapper);
     429             :     current_wrapper->set_previous_wrapper(*instance_wrapper);
     430             :   }
     431             :   set_instances_link(*instance_wrapper);
     432        1742 : }
     433             : 
     434        1024 : void WasmMemoryObject::ResetInstancesLink(Isolate* isolate) {
     435             :   Handle<Object> undefined = isolate->factory()->undefined_value();
     436        1024 :   SetEmbedderField(kInstancesLink, *undefined);
     437        1024 : }
     438             : 
     439             : // static
     440        1042 : int32_t WasmMemoryObject::Grow(Isolate* isolate,
     441             :                                Handle<WasmMemoryObject> memory_object,
     442             :                                uint32_t pages) {
     443             :   Handle<JSArrayBuffer> old_buffer;
     444             :   uint32_t old_size = 0;
     445             :   Address old_mem_start = nullptr;
     446        1042 :   if (memory_object->has_buffer()) {
     447             :     old_buffer = handle(memory_object->buffer());
     448        1027 :     old_size = old_buffer->byte_length()->Number();
     449             :     old_mem_start = static_cast<Address>(old_buffer->backing_store());
     450             :   }
     451             :   Handle<JSArrayBuffer> new_buffer;
     452             :   // Return current size if grow by 0.
     453        1042 :   if (pages == 0) {
     454             :     // Even for pages == 0, we need to attach a new JSArrayBuffer and neuter the
     455             :     // old one to be spec compliant.
     456          90 :     if (!old_buffer.is_null() && old_buffer->backing_store() != nullptr) {
     457             :       new_buffer = SetupArrayBuffer(isolate, old_buffer->backing_store(),
     458             :                                     old_size, old_buffer->is_external(),
     459         135 :                                     old_buffer->has_guard_region());
     460             :       memory_object->set_buffer(*new_buffer);
     461             :       old_buffer->set_is_neuterable(true);
     462          45 :       if (!old_buffer->has_guard_region()) {
     463             :         old_buffer->set_is_external(true);
     464          42 :         isolate->heap()->UnregisterArrayBuffer(*old_buffer);
     465             :       }
     466             :       // Neuter but don't free the memory because it is now being used by
     467             :       // new_buffer.
     468          45 :       old_buffer->Neuter();
     469             :     }
     470             :     DCHECK_EQ(0, old_size % WasmModule::kPageSize);
     471          45 :     return old_size / WasmModule::kPageSize;
     472             :   }
     473         997 :   if (!memory_object->has_instances_link()) {
     474             :     // Memory object does not have an instance associated with it, just grow
     475             :     uint32_t max_pages;
     476          52 :     if (memory_object->has_maximum_pages()) {
     477          52 :       max_pages = static_cast<uint32_t>(memory_object->maximum_pages());
     478          52 :       if (FLAG_wasm_max_mem_pages < max_pages) return -1;
     479             :     } else {
     480           0 :       max_pages = FLAG_wasm_max_mem_pages;
     481             :     }
     482          52 :     new_buffer = GrowMemoryBuffer(isolate, old_buffer, pages, max_pages);
     483          52 :     if (new_buffer.is_null()) return -1;
     484             :   } else {
     485             :     Handle<WasmInstanceWrapper> instance_wrapper(
     486             :         memory_object->instances_link());
     487             :     DCHECK(WasmInstanceWrapper::IsWasmInstanceWrapper(*instance_wrapper));
     488             :     DCHECK(instance_wrapper->has_instance());
     489         945 :     Handle<WasmInstanceObject> instance = instance_wrapper->instance_object();
     490             :     DCHECK(IsWasmInstance(*instance));
     491         945 :     uint32_t max_pages = instance->GetMaxMemoryPages();
     492             : 
     493             :     // Grow memory object buffer and update instances associated with it.
     494         945 :     new_buffer = GrowMemoryBuffer(isolate, old_buffer, pages, max_pages);
     495         945 :     if (new_buffer.is_null()) return -1;
     496             :     DCHECK(!instance_wrapper->has_previous());
     497         930 :     SetInstanceMemory(isolate, instance, new_buffer);
     498         930 :     UncheckedUpdateInstanceMemory(isolate, instance, old_mem_start, old_size);
     499        5145 :     while (instance_wrapper->has_next()) {
     500        3285 :       instance_wrapper = instance_wrapper->next_wrapper();
     501             :       DCHECK(WasmInstanceWrapper::IsWasmInstanceWrapper(*instance_wrapper));
     502        3285 :       Handle<WasmInstanceObject> instance = instance_wrapper->instance_object();
     503             :       DCHECK(IsWasmInstance(*instance));
     504        3285 :       SetInstanceMemory(isolate, instance, new_buffer);
     505        3285 :       UncheckedUpdateInstanceMemory(isolate, instance, old_mem_start, old_size);
     506             :     }
     507             :   }
     508             :   memory_object->set_buffer(*new_buffer);
     509             :   DCHECK_EQ(0, old_size % WasmModule::kPageSize);
     510         982 :   return old_size / WasmModule::kPageSize;
     511             : }
     512             : 
     513     1342558 : DEFINE_OBJ_ACCESSORS(WasmInstanceObject, compiled_module, kCompiledModule,
     514             :                      WasmCompiledModule)
     515        2860 : DEFINE_OPTIONAL_OBJ_ACCESSORS(WasmInstanceObject, globals_buffer,
     516             :                               kGlobalsArrayBuffer, JSArrayBuffer)
     517      106158 : DEFINE_OPTIONAL_OBJ_ACCESSORS(WasmInstanceObject, memory_buffer,
     518             :                               kMemoryArrayBuffer, JSArrayBuffer)
     519      142053 : DEFINE_OPTIONAL_OBJ_ACCESSORS(WasmInstanceObject, memory_object, kMemoryObject,
     520             :                               WasmMemoryObject)
     521      126213 : DEFINE_OPTIONAL_OBJ_ACCESSORS(WasmInstanceObject, debug_info, kDebugInfo,
     522             :                               WasmDebugInfo)
     523       34078 : DEFINE_OPTIONAL_OBJ_ACCESSORS(WasmInstanceObject, instance_wrapper,
     524             :                               kWasmMemInstanceWrapper, WasmInstanceWrapper)
     525             : 
     526           0 : WasmModuleObject* WasmInstanceObject::module_object() {
     527           0 :   return *compiled_module()->wasm_module();
     528             : }
     529             : 
     530       12432 : WasmModule* WasmInstanceObject::module() { return compiled_module()->module(); }
     531             : 
     532        1228 : Handle<WasmDebugInfo> WasmInstanceObject::GetOrCreateDebugInfo(
     533             :     Handle<WasmInstanceObject> instance) {
     534        1303 :   if (instance->has_debug_info()) return handle(instance->debug_info());
     535        1153 :   Handle<WasmDebugInfo> new_info = WasmDebugInfo::New(instance);
     536             :   instance->set_debug_info(*new_info);
     537        1153 :   return new_info;
     538             : }
     539             : 
     540      320512 : WasmInstanceObject* WasmInstanceObject::cast(Object* object) {
     541             :   DCHECK(IsWasmInstanceObject(object));
     542      320512 :   return reinterpret_cast<WasmInstanceObject*>(object);
     543             : }
     544             : 
     545       51980 : bool WasmInstanceObject::IsWasmInstanceObject(Object* object) {
     546       51980 :   if (!object->IsJSObject()) return false;
     547             : 
     548             :   JSObject* obj = JSObject::cast(object);
     549             :   Isolate* isolate = obj->GetIsolate();
     550       51980 :   if (obj->GetEmbedderFieldCount() != kFieldCount) {
     551             :     return false;
     552             :   }
     553             : 
     554             :   Object* mem = obj->GetEmbedderField(kMemoryArrayBuffer);
     555      104230 :   if (!(mem->IsUndefined(isolate) || mem->IsJSArrayBuffer()) ||
     556             :       !WasmCompiledModule::IsWasmCompiledModule(
     557       51980 :           obj->GetEmbedderField(kCompiledModule))) {
     558             :     return false;
     559             :   }
     560             : 
     561             :   // All checks passed.
     562       51980 :   return true;
     563             : }
     564             : 
     565       87727 : Handle<WasmInstanceObject> WasmInstanceObject::New(
     566             :     Isolate* isolate, Handle<WasmCompiledModule> compiled_module) {
     567             :   Handle<JSFunction> instance_cons(
     568      175454 :       isolate->native_context()->wasm_instance_constructor());
     569             :   Handle<JSObject> instance_object =
     570       87727 :       isolate->factory()->NewJSObject(instance_cons, TENURED);
     571             :   instance_object->SetEmbedderField(kWrapperTracerHeader, Smi::kZero);
     572             : 
     573      175454 :   Handle<Symbol> instance_sym(isolate->native_context()->wasm_instance_sym());
     574             :   Object::SetProperty(instance_object, instance_sym, instance_object, STRICT)
     575      175454 :       .Check();
     576             :   Handle<WasmInstanceObject> instance(
     577             :       reinterpret_cast<WasmInstanceObject*>(*instance_object), isolate);
     578             : 
     579       87727 :   instance->SetEmbedderField(kCompiledModule, *compiled_module);
     580      175454 :   instance->SetEmbedderField(kMemoryObject, isolate->heap()->undefined_value());
     581             :   Handle<WasmInstanceWrapper> instance_wrapper =
     582       87727 :       WasmInstanceWrapper::New(isolate, instance);
     583       87727 :   instance->SetEmbedderField(kWasmMemInstanceWrapper, *instance_wrapper);
     584       87727 :   return instance;
     585             : }
     586             : 
     587        4653 : int32_t WasmInstanceObject::GetMemorySize() {
     588        4653 :   if (!has_memory_buffer()) return 0;
     589        4638 :   uint32_t bytes = memory_buffer()->byte_length()->Number();
     590             :   DCHECK_EQ(0, bytes % WasmModule::kPageSize);
     591        4638 :   return bytes / WasmModule::kPageSize;
     592             : }
     593             : 
     594        1318 : int32_t WasmInstanceObject::GrowMemory(Isolate* isolate,
     595             :                                        Handle<WasmInstanceObject> instance,
     596             :                                        uint32_t pages) {
     597        1387 :   if (pages == 0) return instance->GetMemorySize();
     598        1249 :   if (instance->has_memory_object()) {
     599             :     return WasmMemoryObject::Grow(
     600         615 :         isolate, handle(instance->memory_object(), isolate), pages);
     601             :   }
     602             : 
     603             :   // No other instances to grow, grow just the one.
     604             :   uint32_t old_size = 0;
     605             :   Address old_mem_start = nullptr;
     606             :   Handle<JSArrayBuffer> old_buffer;
     607         634 :   if (instance->has_memory_buffer()) {
     608             :     old_buffer = handle(instance->memory_buffer(), isolate);
     609         559 :     old_size = old_buffer->byte_length()->Number();
     610             :     old_mem_start = static_cast<Address>(old_buffer->backing_store());
     611             :   }
     612         634 :   uint32_t max_pages = instance->GetMaxMemoryPages();
     613             :   Handle<JSArrayBuffer> buffer =
     614         634 :       GrowMemoryBuffer(isolate, old_buffer, pages, max_pages);
     615         634 :   if (buffer.is_null()) return -1;
     616         558 :   SetInstanceMemory(isolate, instance, buffer);
     617         558 :   UncheckedUpdateInstanceMemory(isolate, instance, old_mem_start, old_size);
     618             :   DCHECK_EQ(0, old_size % WasmModule::kPageSize);
     619         558 :   return old_size / WasmModule::kPageSize;
     620             : }
     621             : 
     622        1579 : uint32_t WasmInstanceObject::GetMaxMemoryPages() {
     623        1579 :   if (has_memory_object()) {
     624         945 :     if (memory_object()->has_maximum_pages()) {
     625             :       uint32_t maximum =
     626         885 :           static_cast<uint32_t>(memory_object()->maximum_pages());
     627         885 :       if (maximum < FLAG_wasm_max_mem_pages) return maximum;
     628             :     }
     629             :   }
     630         709 :   uint32_t compiled_max_pages = compiled_module()->module()->max_mem_pages;
     631         709 :   Isolate* isolate = GetIsolate();
     632         709 :   auto* histogram = (compiled_module()->module()->is_wasm()
     633             :                          ? isolate->counters()->wasm_wasm_max_mem_pages_count()
     634        1418 :                          : isolate->counters()->wasm_asm_max_mem_pages_count());
     635         709 :   histogram->AddSample(compiled_max_pages);
     636         709 :   if (compiled_max_pages != 0) return compiled_max_pages;
     637           0 :   return FLAG_wasm_max_mem_pages;
     638             : }
     639             : 
     640        3171 : WasmInstanceObject* WasmExportedFunction::instance() {
     641        3171 :   return WasmInstanceObject::cast(GetEmbedderField(kInstance));
     642             : }
     643             : 
     644        3171 : int WasmExportedFunction::function_index() {
     645             :   int32_t func_index;
     646        3171 :   CHECK(GetEmbedderField(kIndex)->ToInt32(&func_index));
     647        3171 :   return func_index;
     648             : }
     649             : 
     650        3171 : WasmExportedFunction* WasmExportedFunction::cast(Object* object) {
     651             :   DCHECK(object && object->IsJSFunction());
     652             :   DCHECK_EQ(Code::JS_TO_WASM_FUNCTION,
     653             :             JSFunction::cast(object)->code()->kind());
     654             :   // TODO(titzer): brand check for WasmExportedFunction.
     655        3171 :   return reinterpret_cast<WasmExportedFunction*>(object);
     656             : }
     657             : 
     658       90249 : Handle<WasmExportedFunction> WasmExportedFunction::New(
     659             :     Isolate* isolate, Handle<WasmInstanceObject> instance,
     660             :     MaybeHandle<String> maybe_name, int func_index, int arity,
     661             :     Handle<Code> export_wrapper) {
     662             :   Handle<String> name;
     663       90249 :   if (maybe_name.is_null()) {
     664             :     EmbeddedVector<char, 16> buffer;
     665       72767 :     int length = SNPrintF(buffer, "%d", func_index);
     666             :     name = isolate->factory()
     667             :                ->NewStringFromOneByte(
     668             :                    Vector<uint8_t>::cast(buffer.SubVector(0, length)))
     669      145534 :                .ToHandleChecked();
     670             :   } else {
     671       17482 :     name = maybe_name.ToHandleChecked();
     672             :   }
     673             :   DCHECK_EQ(Code::JS_TO_WASM_FUNCTION, export_wrapper->kind());
     674             :   Handle<SharedFunctionInfo> shared =
     675       90249 :       isolate->factory()->NewSharedFunctionInfo(name, export_wrapper, false);
     676             :   shared->set_length(arity);
     677             :   shared->set_internal_formal_parameter_count(arity);
     678             :   Handle<JSFunction> function = isolate->factory()->NewFunction(
     679       90249 :       isolate->wasm_function_map(), name, export_wrapper);
     680             :   function->SetEmbedderField(kWrapperTracerHeader, Smi::kZero);
     681             : 
     682       90249 :   function->set_shared(*shared);
     683             : 
     684       90249 :   function->SetEmbedderField(kInstance, *instance);
     685             :   function->SetEmbedderField(kIndex, Smi::FromInt(func_index));
     686       90249 :   return Handle<WasmExportedFunction>::cast(function);
     687             : }
     688             : 
     689       51980 : bool WasmSharedModuleData::IsWasmSharedModuleData(Object* object) {
     690       51980 :   if (!object->IsFixedArray()) return false;
     691             :   FixedArray* arr = FixedArray::cast(object);
     692       51980 :   if (arr->length() != kFieldCount) return false;
     693             :   Isolate* isolate = arr->GetIsolate();
     694       51980 :   if (!arr->get(kModuleWrapper)->IsForeign()) return false;
     695      103960 :   if (!arr->get(kModuleBytes)->IsUndefined(isolate) &&
     696             :       !arr->get(kModuleBytes)->IsSeqOneByteString())
     697             :     return false;
     698       51980 :   if (!arr->get(kScript)->IsScript()) return false;
     699       51980 :   if (!arr->get(kAsmJsOffsetTable)->IsUndefined(isolate) &&
     700             :       !arr->get(kAsmJsOffsetTable)->IsByteArray())
     701             :     return false;
     702       52026 :   if (!arr->get(kBreakPointInfos)->IsUndefined(isolate) &&
     703             :       !arr->get(kBreakPointInfos)->IsFixedArray())
     704             :     return false;
     705       51980 :   return true;
     706             : }
     707             : 
     708      878556 : WasmSharedModuleData* WasmSharedModuleData::cast(Object* object) {
     709             :   DCHECK(IsWasmSharedModuleData(object));
     710      878556 :   return reinterpret_cast<WasmSharedModuleData*>(object);
     711             : }
     712             : 
     713      231191 : wasm::WasmModule* WasmSharedModuleData::module() {
     714             :   // We populate the kModuleWrapper field with a Foreign holding the
     715             :   // address to the address of a WasmModule. This is because we can
     716             :   // handle both cases when the WasmModule's lifetime is managed through
     717             :   // a Managed<WasmModule> object, as well as cases when it's managed
     718             :   // by the embedder. CcTests fall into the latter case.
     719             :   return *(reinterpret_cast<wasm::WasmModule**>(
     720      549807 :       Foreign::cast(get(kModuleWrapper))->foreign_address()));
     721             : }
     722             : 
     723      389957 : DEFINE_OPTIONAL_ARR_ACCESSORS(WasmSharedModuleData, module_bytes, kModuleBytes,
     724             :                               SeqOneByteString);
     725       78990 : DEFINE_ARR_GETTER(WasmSharedModuleData, script, kScript, Script);
     726          78 : DEFINE_OPTIONAL_ARR_ACCESSORS(WasmSharedModuleData, asm_js_offset_table,
     727             :                               kAsmJsOffsetTable, ByteArray);
     728       95494 : DEFINE_OPTIONAL_ARR_GETTER(WasmSharedModuleData, breakpoint_infos,
     729             :                            kBreakPointInfos, FixedArray);
     730        7232 : DEFINE_OPTIONAL_ARR_GETTER(WasmSharedModuleData, lazy_compilation_orchestrator,
     731             :                            kLazyCompilationOrchestrator, Foreign);
     732             : 
     733       55551 : Handle<WasmSharedModuleData> WasmSharedModuleData::New(
     734             :     Isolate* isolate, Handle<Foreign> module_wrapper,
     735             :     Handle<SeqOneByteString> module_bytes, Handle<Script> script,
     736             :     Handle<ByteArray> asm_js_offset_table) {
     737             :   Handle<FixedArray> arr =
     738       55551 :       isolate->factory()->NewFixedArray(kFieldCount, TENURED);
     739             :   arr->set(kWrapperTracerHeader, Smi::kZero);
     740       55551 :   arr->set(kModuleWrapper, *module_wrapper);
     741       55551 :   if (!module_bytes.is_null()) {
     742       55551 :     arr->set(kModuleBytes, *module_bytes);
     743             :   }
     744       55551 :   if (!script.is_null()) {
     745       55551 :     arr->set(kScript, *script);
     746             :   }
     747       55551 :   if (!asm_js_offset_table.is_null()) {
     748        3616 :     arr->set(kAsmJsOffsetTable, *asm_js_offset_table);
     749             :   }
     750             : 
     751             :   DCHECK(WasmSharedModuleData::IsWasmSharedModuleData(*arr));
     752       55551 :   return Handle<WasmSharedModuleData>::cast(arr);
     753             : }
     754             : 
     755       74553 : bool WasmSharedModuleData::is_asm_js() {
     756       74553 :   bool asm_js = module()->is_asm_js();
     757             :   DCHECK_EQ(asm_js, script()->IsUserJavaScript());
     758             :   DCHECK_EQ(asm_js, has_asm_js_offset_table());
     759       74553 :   return asm_js;
     760             : }
     761             : 
     762         112 : void WasmSharedModuleData::ReinitializeAfterDeserialization(
     763             :     Isolate* isolate, Handle<WasmSharedModuleData> shared) {
     764             :   DCHECK(shared->get(kModuleWrapper)->IsUndefined(isolate));
     765             : #ifdef DEBUG
     766             :   // No BreakpointInfo objects should survive deserialization.
     767             :   if (shared->has_breakpoint_infos()) {
     768             :     for (int i = 0, e = shared->breakpoint_infos()->length(); i < e; ++i) {
     769             :       DCHECK(shared->breakpoint_infos()->get(i)->IsUndefined(isolate));
     770             :     }
     771             :   }
     772             : #endif
     773             : 
     774         224 :   shared->set(kBreakPointInfos, isolate->heap()->undefined_value());
     775             : 
     776             :   WasmModule* module = nullptr;
     777             :   {
     778             :     // We parse the module again directly from the module bytes, so
     779             :     // the underlying storage must not be moved meanwhile.
     780             :     DisallowHeapAllocation no_allocation;
     781             :     SeqOneByteString* module_bytes = shared->module_bytes();
     782             :     const byte* start =
     783         112 :         reinterpret_cast<const byte*>(module_bytes->GetCharsAddress());
     784         112 :     const byte* end = start + module_bytes->length();
     785             :     // TODO(titzer): remember the module origin in the compiled_module
     786             :     // For now, we assume serialized modules did not originate from asm.js.
     787             :     ModuleResult result =
     788         224 :         DecodeWasmModule(isolate, start, end, false, kWasmOrigin);
     789         112 :     CHECK(result.ok());
     790         112 :     CHECK_NOT_NULL(result.val);
     791             :     module = const_cast<WasmModule*>(result.val);
     792             :   }
     793             : 
     794             :   Handle<WasmModuleWrapper> module_wrapper =
     795         112 :       WasmModuleWrapper::New(isolate, module);
     796             : 
     797         112 :   shared->set(kModuleWrapper, *module_wrapper);
     798             :   DCHECK(WasmSharedModuleData::IsWasmSharedModuleData(*shared));
     799         112 : }
     800             : 
     801             : namespace {
     802             : 
     803        1657 : int GetBreakpointPos(Isolate* isolate, Object* break_point_info_or_undef) {
     804        1657 :   if (break_point_info_or_undef->IsUndefined(isolate)) return kMaxInt;
     805         745 :   return BreakPointInfo::cast(break_point_info_or_undef)->source_position();
     806             : }
     807             : 
     808         461 : int FindBreakpointInfoInsertPos(Isolate* isolate,
     809             :                                 Handle<FixedArray> breakpoint_infos,
     810             :                                 int position) {
     811             :   // Find insert location via binary search, taking care of undefined values on
     812             :   // the right. Position is always greater than zero.
     813             :   DCHECK_LT(0, position);
     814             : 
     815             :   int left = 0;                            // inclusive
     816             :   int right = breakpoint_infos->length();  // exclusive
     817        2024 :   while (right - left > 1) {
     818        1102 :     int mid = left + (right - left) / 2;
     819             :     Object* mid_obj = breakpoint_infos->get(mid);
     820        1102 :     if (GetBreakpointPos(isolate, mid_obj) <= position) {
     821             :       left = mid;
     822             :     } else {
     823             :       right = mid;
     824             :     }
     825             :   }
     826             : 
     827         461 :   int left_pos = GetBreakpointPos(isolate, breakpoint_infos->get(left));
     828         461 :   return left_pos < position ? left + 1 : left;
     829             : }
     830             : 
     831             : }  // namespace
     832             : 
     833         106 : void WasmSharedModuleData::AddBreakpoint(Handle<WasmSharedModuleData> shared,
     834             :                                          int position,
     835             :                                          Handle<Object> break_point_object) {
     836             :   Isolate* isolate = shared->GetIsolate();
     837             :   Handle<FixedArray> breakpoint_infos;
     838         106 :   if (shared->has_breakpoint_infos()) {
     839             :     breakpoint_infos = handle(shared->breakpoint_infos(), isolate);
     840             :   } else {
     841          46 :     breakpoint_infos = isolate->factory()->NewFixedArray(4, TENURED);
     842          46 :     shared->set(kBreakPointInfos, *breakpoint_infos);
     843             :   }
     844             : 
     845             :   int insert_pos =
     846         106 :       FindBreakpointInfoInsertPos(isolate, breakpoint_infos, position);
     847             : 
     848             :   // If a BreakPointInfo object already exists for this position, add the new
     849             :   // breakpoint object and return.
     850         200 :   if (insert_pos < breakpoint_infos->length() &&
     851          94 :       GetBreakpointPos(isolate, breakpoint_infos->get(insert_pos)) ==
     852             :           position) {
     853             :     Handle<BreakPointInfo> old_info(
     854             :         BreakPointInfo::cast(breakpoint_infos->get(insert_pos)), isolate);
     855           0 :     BreakPointInfo::SetBreakPoint(old_info, break_point_object);
     856         106 :     return;
     857             :   }
     858             : 
     859             :   // Enlarge break positions array if necessary.
     860             :   bool need_realloc = !breakpoint_infos->get(breakpoint_infos->length() - 1)
     861         106 :                            ->IsUndefined(isolate);
     862             :   Handle<FixedArray> new_breakpoint_infos = breakpoint_infos;
     863         106 :   if (need_realloc) {
     864             :     new_breakpoint_infos = isolate->factory()->NewFixedArray(
     865          12 :         2 * breakpoint_infos->length(), TENURED);
     866          12 :     shared->set(kBreakPointInfos, *new_breakpoint_infos);
     867             :     // Copy over the entries [0, insert_pos).
     868          84 :     for (int i = 0; i < insert_pos; ++i)
     869          72 :       new_breakpoint_infos->set(i, breakpoint_infos->get(i));
     870             :   }
     871             : 
     872             :   // Move elements [insert_pos+1, ...] up by one.
     873         212 :   for (int i = insert_pos + 1; i < breakpoint_infos->length(); ++i) {
     874             :     Object* entry = breakpoint_infos->get(i);
     875          82 :     if (entry->IsUndefined(isolate)) break;
     876           0 :     new_breakpoint_infos->set(i + 1, entry);
     877             :   }
     878             : 
     879             :   // Generate new BreakpointInfo.
     880             :   Handle<BreakPointInfo> breakpoint_info =
     881         106 :       isolate->factory()->NewBreakPointInfo(position);
     882         106 :   BreakPointInfo::SetBreakPoint(breakpoint_info, break_point_object);
     883             : 
     884             :   // Now insert new position at insert_pos.
     885         106 :   new_breakpoint_infos->set(insert_pos, *breakpoint_info);
     886             : }
     887             : 
     888       47286 : void WasmSharedModuleData::SetBreakpointsOnNewInstance(
     889             :     Handle<WasmSharedModuleData> shared, Handle<WasmInstanceObject> instance) {
     890       94572 :   if (!shared->has_breakpoint_infos()) return;
     891             :   Isolate* isolate = shared->GetIsolate();
     892             :   Handle<WasmCompiledModule> compiled_module(instance->compiled_module(),
     893             :                                              isolate);
     894             :   Handle<WasmDebugInfo> debug_info =
     895           0 :       WasmInstanceObject::GetOrCreateDebugInfo(instance);
     896             : 
     897             :   Handle<FixedArray> breakpoint_infos(shared->breakpoint_infos(), isolate);
     898             :   // If the array exists, it should not be empty.
     899             :   DCHECK_LT(0, breakpoint_infos->length());
     900             : 
     901           0 :   for (int i = 0, e = breakpoint_infos->length(); i < e; ++i) {
     902             :     Handle<Object> obj(breakpoint_infos->get(i), isolate);
     903           0 :     if (obj->IsUndefined(isolate)) {
     904             :       for (; i < e; ++i) {
     905             :         DCHECK(breakpoint_infos->get(i)->IsUndefined(isolate));
     906             :       }
     907             :       break;
     908             :     }
     909             :     Handle<BreakPointInfo> breakpoint_info = Handle<BreakPointInfo>::cast(obj);
     910             :     int position = breakpoint_info->source_position();
     911             : 
     912             :     // Find the function for this breakpoint, and set the breakpoint.
     913           0 :     int func_index = compiled_module->GetContainingFunction(position);
     914             :     DCHECK_LE(0, func_index);
     915           0 :     WasmFunction& func = compiled_module->module()->functions[func_index];
     916           0 :     int offset_in_func = position - func.code_start_offset;
     917           0 :     WasmDebugInfo::SetBreakpoint(debug_info, func_index, offset_in_func);
     918             :   }
     919             : }
     920             : 
     921        3616 : void WasmSharedModuleData::PrepareForLazyCompilation(
     922             :     Handle<WasmSharedModuleData> shared) {
     923        3616 :   if (shared->has_lazy_compilation_orchestrator()) return;
     924             :   Isolate* isolate = shared->GetIsolate();
     925        3616 :   LazyCompilationOrchestrator* orch = new LazyCompilationOrchestrator();
     926             :   Handle<Managed<LazyCompilationOrchestrator>> orch_handle =
     927        3616 :       Managed<LazyCompilationOrchestrator>::New(isolate, orch);
     928        3616 :   shared->set(WasmSharedModuleData::kLazyCompilationOrchestrator, *orch_handle);
     929             : }
     930             : 
     931       55551 : Handle<WasmCompiledModule> WasmCompiledModule::New(
     932             :     Isolate* isolate, Handle<WasmSharedModuleData> shared,
     933             :     Handle<FixedArray> code_table,
     934             :     MaybeHandle<FixedArray> maybe_empty_function_tables,
     935             :     MaybeHandle<FixedArray> maybe_signature_tables) {
     936             :   Handle<FixedArray> ret =
     937       55551 :       isolate->factory()->NewFixedArray(PropertyIndices::Count, TENURED);
     938             :   // WasmCompiledModule::cast would fail since fields are not set yet.
     939             :   Handle<WasmCompiledModule> compiled_module(
     940             :       reinterpret_cast<WasmCompiledModule*>(*ret), isolate);
     941             :   compiled_module->InitId();
     942             :   compiled_module->set_shared(shared);
     943       55551 :   compiled_module->set_native_context(isolate->native_context());
     944             :   compiled_module->set_code_table(code_table);
     945             :   int function_table_count =
     946      111102 :       static_cast<int>(shared->module()->function_tables.size());
     947       55551 :   if (function_table_count > 0) {
     948             :     compiled_module->set_signature_tables(
     949             :         maybe_signature_tables.ToHandleChecked());
     950             :     compiled_module->set_empty_function_tables(
     951             :         maybe_empty_function_tables.ToHandleChecked());
     952             :     compiled_module->set_function_tables(
     953             :         maybe_empty_function_tables.ToHandleChecked());
     954             :   }
     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       55551 :   compiled_module->set_min_mem_pages(shared->module()->min_mem_pages);
     960             :   compiled_module->set_num_imported_functions(
     961       55551 :       shared->module()->num_imported_functions);
     962       55551 :   return compiled_module;
     963             : }
     964             : 
     965       32147 : Handle<WasmCompiledModule> WasmCompiledModule::Clone(
     966             :     Isolate* isolate, Handle<WasmCompiledModule> module) {
     967             :   Handle<FixedArray> code_copy =
     968       32147 :       isolate->factory()->CopyFixedArray(module->code_table());
     969             :   Handle<WasmCompiledModule> ret = Handle<WasmCompiledModule>::cast(
     970       32147 :       isolate->factory()->CopyFixedArray(module));
     971             :   ret->InitId();
     972             :   ret->set_code_table(code_copy);
     973             :   ret->reset_weak_owning_instance();
     974             :   ret->reset_weak_next_instance();
     975             :   ret->reset_weak_prev_instance();
     976             :   ret->reset_weak_exported_functions();
     977       32147 :   if (ret->has_embedded_mem_start()) {
     978             :     WasmCompiledModule::recreate_embedded_mem_start(ret, isolate->factory(),
     979        2852 :                                                     ret->embedded_mem_start());
     980             :   }
     981       32147 :   if (ret->has_globals_start()) {
     982             :     WasmCompiledModule::recreate_globals_start(ret, isolate->factory(),
     983        1361 :                                                ret->globals_start());
     984             :   }
     985       32147 :   if (ret->has_embedded_mem_size()) {
     986             :     WasmCompiledModule::recreate_embedded_mem_size(ret, isolate->factory(),
     987        2852 :                                                    ret->embedded_mem_size());
     988             :   }
     989       32147 :   return ret;
     990             : }
     991             : 
     992        3510 : void WasmCompiledModule::Reset(Isolate* isolate,
     993             :                                WasmCompiledModule* compiled_module) {
     994             :   DisallowHeapAllocation no_gc;
     995             :   TRACE("Resetting %d\n", compiled_module->instance_id());
     996             :   Object* undefined = *isolate->factory()->undefined_value();
     997             :   Object* fct_obj = compiled_module->ptr_to_code_table();
     998        1755 :   if (fct_obj != nullptr && fct_obj != undefined) {
     999        1755 :     uint32_t old_mem_size = compiled_module->mem_size();
    1000             :     uint32_t default_mem_size = compiled_module->default_mem_size();
    1001        1755 :     Address old_mem_start = compiled_module->GetEmbeddedMemStartOrNull();
    1002             : 
    1003             :     // Patch code to update memory references, global references, and function
    1004             :     // table references.
    1005        1755 :     Zone specialization_zone(isolate->allocator(), ZONE_NAME);
    1006        3510 :     CodeSpecialization code_specialization(isolate, &specialization_zone);
    1007             : 
    1008        1755 :     if (old_mem_size > 0 && old_mem_start != nullptr) {
    1009             :       code_specialization.RelocateMemoryReferences(old_mem_start, old_mem_size,
    1010        1663 :                                                    nullptr, default_mem_size);
    1011             :     }
    1012             : 
    1013        1755 :     if (compiled_module->has_globals_start()) {
    1014             :       Address globals_start =
    1015          85 :           reinterpret_cast<Address>(compiled_module->globals_start());
    1016          85 :       code_specialization.RelocateGlobals(globals_start, nullptr);
    1017             :       compiled_module->set_globals_start(0);
    1018             :     }
    1019             : 
    1020             :     // Reset function tables.
    1021        1755 :     if (compiled_module->has_function_tables()) {
    1022             :       FixedArray* function_tables = compiled_module->ptr_to_function_tables();
    1023             :       FixedArray* empty_function_tables =
    1024             :           compiled_module->ptr_to_empty_function_tables();
    1025          81 :       if (function_tables != empty_function_tables) {
    1026             :         DCHECK_EQ(function_tables->length(), empty_function_tables->length());
    1027         162 :         for (int i = 0, e = function_tables->length(); i < e; ++i) {
    1028             :           code_specialization.RelocateObject(
    1029             :               handle(function_tables->get(i), isolate),
    1030          81 :               handle(empty_function_tables->get(i), isolate));
    1031             :         }
    1032             :         compiled_module->set_ptr_to_function_tables(empty_function_tables);
    1033             :       }
    1034             :     }
    1035             : 
    1036             :     FixedArray* functions = FixedArray::cast(fct_obj);
    1037        9670 :     for (int i = compiled_module->num_imported_functions(),
    1038             :              end = functions->length();
    1039             :          i < end; ++i) {
    1040             :       Code* code = Code::cast(functions->get(i));
    1041             :       // Skip lazy compile stubs.
    1042        7910 :       if (code->builtin_index() == Builtins::kWasmCompileLazy) continue;
    1043        7137 :       if (code->kind() != Code::WASM_FUNCTION) {
    1044             :         // From here on, there should only be wrappers for exported functions.
    1045             :         for (; i < end; ++i) {
    1046             :           DCHECK_EQ(Code::JS_TO_WASM_FUNCTION,
    1047             :                     Code::cast(functions->get(i))->kind());
    1048             :         }
    1049             :         break;
    1050             :       }
    1051             :       bool changed =
    1052        5387 :           code_specialization.ApplyToWasmCode(code, SKIP_ICACHE_FLUSH);
    1053             :       // TODO(wasm): Check if this is faster than passing FLUSH_ICACHE_IF_NEEDED
    1054             :       // above.
    1055        5387 :       if (changed) {
    1056         951 :         Assembler::FlushICache(isolate, code->instruction_start(),
    1057        1902 :                                code->instruction_size());
    1058             :       }
    1059        1755 :     }
    1060             :   }
    1061        1755 :   compiled_module->ResetSpecializationMemInfoIfNeeded();
    1062        1755 : }
    1063             : 
    1064           0 : void WasmCompiledModule::InitId() {
    1065             : #if DEBUG
    1066             :   static uint32_t instance_id_counter = 0;
    1067             :   set(kID_instance_id, Smi::FromInt(instance_id_counter++));
    1068             :   TRACE("New compiled module id: %d\n", instance_id());
    1069             : #endif
    1070           0 : }
    1071             : 
    1072        1755 : void WasmCompiledModule::ResetSpecializationMemInfoIfNeeded() {
    1073             :   DisallowHeapAllocation no_gc;
    1074        1755 :   if (has_embedded_mem_start()) {
    1075             :     set_embedded_mem_size(0);
    1076             :     set_embedded_mem_start(0);
    1077             :   }
    1078        1755 : }
    1079             : 
    1080       14467 : void WasmCompiledModule::SetSpecializationMemInfoFrom(
    1081             :     Factory* factory, Handle<WasmCompiledModule> compiled_module,
    1082             :     Handle<JSArrayBuffer> buffer) {
    1083             :   DCHECK(!buffer.is_null());
    1084       14467 :   size_t start_address = reinterpret_cast<size_t>(buffer->backing_store());
    1085       14467 :   uint32_t size = static_cast<uint32_t>(buffer->byte_length()->Number());
    1086       14467 :   if (!compiled_module->has_embedded_mem_start()) {
    1087             :     DCHECK(!compiled_module->has_embedded_mem_size());
    1088             :     WasmCompiledModule::recreate_embedded_mem_start(compiled_module, factory,
    1089        5755 :                                                     start_address);
    1090             :     WasmCompiledModule::recreate_embedded_mem_size(compiled_module, factory,
    1091        5755 :                                                    size);
    1092             :   } else {
    1093             :     compiled_module->set_embedded_mem_start(start_address);
    1094             :     compiled_module->set_embedded_mem_size(size);
    1095             :   }
    1096       14467 : }
    1097             : 
    1098        2860 : void WasmCompiledModule::SetGlobalsStartAddressFrom(
    1099             :     Factory* factory, Handle<WasmCompiledModule> compiled_module,
    1100             :     Handle<JSArrayBuffer> buffer) {
    1101             :   DCHECK(!buffer.is_null());
    1102        2860 :   size_t start_address = reinterpret_cast<size_t>(buffer->backing_store());
    1103        2860 :   if (!compiled_module->has_globals_start()) {
    1104             :     WasmCompiledModule::recreate_globals_start(compiled_module, factory,
    1105        1432 :                                                start_address);
    1106             :   } else {
    1107             :     compiled_module->set_globals_start(start_address);
    1108             :   }
    1109        2860 : }
    1110             : 
    1111      182051 : MaybeHandle<String> WasmCompiledModule::ExtractUtf8StringFromModuleBytes(
    1112             :     Isolate* isolate, Handle<WasmCompiledModule> compiled_module,
    1113             :     uint32_t offset, uint32_t size) {
    1114             :   // TODO(wasm): cache strings from modules if it's a performance win.
    1115             :   Handle<SeqOneByteString> module_bytes(compiled_module->module_bytes(),
    1116      182051 :                                         isolate);
    1117             :   DCHECK_GE(module_bytes->length(), offset);
    1118             :   DCHECK_GE(module_bytes->length() - offset, size);
    1119             :   // UTF8 validation happens at decode time.
    1120             :   DCHECK(unibrow::Utf8::Validate(
    1121             :       reinterpret_cast<const byte*>(module_bytes->GetCharsAddress() + offset),
    1122             :       size));
    1123             :   DCHECK_GE(kMaxInt, offset);
    1124             :   DCHECK_GE(kMaxInt, size);
    1125             :   return isolate->factory()->NewStringFromUtf8SubString(
    1126      182051 :       module_bytes, static_cast<int>(offset), static_cast<int>(size));
    1127             : }
    1128             : 
    1129       51980 : bool WasmCompiledModule::IsWasmCompiledModule(Object* obj) {
    1130       51980 :   if (!obj->IsFixedArray()) return false;
    1131             :   FixedArray* arr = FixedArray::cast(obj);
    1132       51980 :   if (arr->length() != PropertyIndices::Count) return false;
    1133             :   Isolate* isolate = arr->GetIsolate();
    1134             : #define WCM_CHECK_TYPE(NAME, TYPE_CHECK) \
    1135             :   do {                                   \
    1136             :     Object* obj = arr->get(kID_##NAME);  \
    1137             :     if (!(TYPE_CHECK)) return false;     \
    1138             :   } while (false);
    1139             : // We're OK with undefined, generally, because maybe we don't
    1140             : // have a value for that item. For example, we may not have a
    1141             : // memory, or globals.
    1142             : // We're not OK with the const numbers being undefined. They are
    1143             : // expected to be initialized at construction.
    1144             : #define WCM_CHECK_OBJECT(TYPE, NAME) \
    1145             :   WCM_CHECK_TYPE(NAME, obj->IsUndefined(isolate) || obj->Is##TYPE())
    1146             : #define WCM_CHECK_CONST_OBJECT(TYPE, NAME) \
    1147             :   WCM_CHECK_TYPE(NAME, obj->IsUndefined(isolate) || obj->Is##TYPE())
    1148             : #define WCM_CHECK_WASM_OBJECT(TYPE, NAME) \
    1149             :   WCM_CHECK_TYPE(NAME, TYPE::Is##TYPE(obj))
    1150             : #define WCM_CHECK_WEAK_LINK(TYPE, NAME) WCM_CHECK_OBJECT(WeakCell, NAME)
    1151             : #define WCM_CHECK_SMALL_NUMBER(TYPE, NAME) \
    1152             :   WCM_CHECK_TYPE(NAME, obj->IsUndefined(isolate) || obj->IsSmi())
    1153             : #define WCM_CHECK(KIND, TYPE, NAME) WCM_CHECK_##KIND(TYPE, NAME)
    1154             : #define WCM_CHECK_SMALL_CONST_NUMBER(TYPE, NAME) \
    1155             :   WCM_CHECK_TYPE(NAME, obj->IsSmi())
    1156             : #define WCM_CHECK_LARGE_NUMBER(TYPE, NAME) \
    1157             :   WCM_CHECK_TYPE(NAME, obj->IsUndefined(isolate) || obj->IsMutableHeapNumber())
    1158     1017476 :   WCM_PROPERTY_TABLE(WCM_CHECK)
    1159             : #undef WCM_CHECK
    1160             : 
    1161             :   // All checks passed.
    1162       51980 :   return true;
    1163             : }
    1164             : 
    1165       52742 : void WasmCompiledModule::PrintInstancesChain() {
    1166             : #if DEBUG
    1167             :   if (!FLAG_trace_wasm_instances) return;
    1168             :   for (WasmCompiledModule* current = this; current != nullptr;) {
    1169             :     PrintF("->%d", current->instance_id());
    1170             :     if (!current->has_weak_next_instance()) break;
    1171             :     CHECK(!current->ptr_to_weak_next_instance()->cleared());
    1172             :     current =
    1173             :         WasmCompiledModule::cast(current->ptr_to_weak_next_instance()->value());
    1174             :   }
    1175             :   PrintF("\n");
    1176             : #endif
    1177       52742 : }
    1178             : 
    1179         112 : void WasmCompiledModule::ReinitializeAfterDeserialization(
    1180             :     Isolate* isolate, Handle<WasmCompiledModule> compiled_module) {
    1181             :   // This method must only be called immediately after deserialization.
    1182             :   // At this point, no module wrapper exists, so the shared module data is
    1183             :   // incomplete.
    1184             :   Handle<WasmSharedModuleData> shared(
    1185             :       static_cast<WasmSharedModuleData*>(compiled_module->get(kID_shared)),
    1186             :       isolate);
    1187             :   DCHECK(!WasmSharedModuleData::IsWasmSharedModuleData(*shared));
    1188         112 :   WasmSharedModuleData::ReinitializeAfterDeserialization(isolate, shared);
    1189         112 :   WasmCompiledModule::Reset(isolate, *compiled_module);
    1190             :   DCHECK(WasmSharedModuleData::IsWasmSharedModuleData(*shared));
    1191         112 : }
    1192             : 
    1193       11449 : uint32_t WasmCompiledModule::mem_size() const {
    1194             :   DCHECK(has_embedded_mem_size() == has_embedded_mem_start());
    1195       22898 :   return has_embedded_mem_start() ? embedded_mem_size() : default_mem_size();
    1196             : }
    1197             : 
    1198           0 : uint32_t WasmCompiledModule::default_mem_size() const {
    1199        7511 :   return min_mem_pages() * WasmModule::kPageSize;
    1200             : }
    1201             : 
    1202        2370 : MaybeHandle<String> WasmCompiledModule::GetFunctionNameOrNull(
    1203             :     Isolate* isolate, Handle<WasmCompiledModule> compiled_module,
    1204             :     uint32_t func_index) {
    1205             :   DCHECK_LT(func_index, compiled_module->module()->functions.size());
    1206        4740 :   WasmFunction& function = compiled_module->module()->functions[func_index];
    1207             :   DCHECK_IMPLIES(function.name_offset == 0, function.name_length == 0);
    1208        2370 :   if (!function.name_offset) return {};
    1209             :   return WasmCompiledModule::ExtractUtf8StringFromModuleBytes(
    1210        2310 :       isolate, compiled_module, function.name_offset, function.name_length);
    1211             : }
    1212             : 
    1213         609 : Handle<String> WasmCompiledModule::GetFunctionName(
    1214             :     Isolate* isolate, Handle<WasmCompiledModule> compiled_module,
    1215             :     uint32_t func_index) {
    1216             :   MaybeHandle<String> name =
    1217         609 :       GetFunctionNameOrNull(isolate, compiled_module, func_index);
    1218         609 :   if (!name.is_null()) return name.ToHandleChecked();
    1219           0 :   return isolate->factory()->NewStringFromStaticChars("<WASM UNNAMED>");
    1220             : }
    1221             : 
    1222       12496 : Vector<const uint8_t> WasmCompiledModule::GetRawFunctionName(
    1223             :     uint32_t func_index) {
    1224             :   DCHECK_GT(module()->functions.size(), func_index);
    1225       12496 :   WasmFunction& function = module()->functions[func_index];
    1226       12496 :   SeqOneByteString* bytes = module_bytes();
    1227             :   DCHECK_GE(bytes->length(), function.name_offset);
    1228             :   DCHECK_GE(bytes->length() - function.name_offset, function.name_length);
    1229       12496 :   return Vector<const uint8_t>(bytes->GetCharsAddress() + function.name_offset,
    1230       24992 :                                function.name_length);
    1231             : }
    1232             : 
    1233       37528 : int WasmCompiledModule::GetFunctionOffset(uint32_t func_index) {
    1234       75056 :   std::vector<WasmFunction>& functions = module()->functions;
    1235       75056 :   if (static_cast<uint32_t>(func_index) >= functions.size()) return -1;
    1236             :   DCHECK_GE(kMaxInt, functions[func_index].code_start_offset);
    1237       37528 :   return static_cast<int>(functions[func_index].code_start_offset);
    1238             : }
    1239             : 
    1240         624 : int WasmCompiledModule::GetContainingFunction(uint32_t byte_offset) {
    1241         624 :   std::vector<WasmFunction>& functions = module()->functions;
    1242             : 
    1243             :   // Binary search for a function containing the given position.
    1244             :   int left = 0;                                    // inclusive
    1245         624 :   int right = static_cast<int>(functions.size());  // exclusive
    1246         624 :   if (right == 0) return false;
    1247        1283 :   while (right - left > 1) {
    1248         659 :     int mid = left + (right - left) / 2;
    1249        1318 :     if (functions[mid].code_start_offset <= byte_offset) {
    1250             :       left = mid;
    1251             :     } else {
    1252             :       right = mid;
    1253             :     }
    1254             :   }
    1255             :   // If the found function does not contains the given position, return -1.
    1256         624 :   WasmFunction& func = functions[left];
    1257        1248 :   if (byte_offset < func.code_start_offset ||
    1258         624 :       byte_offset >= func.code_end_offset) {
    1259             :     return -1;
    1260             :   }
    1261             : 
    1262         624 :   return left;
    1263             : }
    1264             : 
    1265         518 : bool WasmCompiledModule::GetPositionInfo(uint32_t position,
    1266             :                                          Script::PositionInfo* info) {
    1267         518 :   int func_index = GetContainingFunction(position);
    1268         518 :   if (func_index < 0) return false;
    1269             : 
    1270         518 :   WasmFunction& function = module()->functions[func_index];
    1271             : 
    1272         518 :   info->line = func_index;
    1273         518 :   info->column = position - function.code_start_offset;
    1274         518 :   info->line_start = function.code_start_offset;
    1275         518 :   info->line_end = function.code_end_offset;
    1276         518 :   return true;
    1277             : }
    1278             : 
    1279             : namespace {
    1280             : 
    1281             : enum AsmJsOffsetTableEntryLayout {
    1282             :   kOTEByteOffset,
    1283             :   kOTECallPosition,
    1284             :   kOTENumberConvPosition,
    1285             :   kOTESize
    1286             : };
    1287             : 
    1288        1371 : Handle<ByteArray> GetDecodedAsmJsOffsetTable(
    1289             :     Handle<WasmCompiledModule> compiled_module, Isolate* isolate) {
    1290             :   DCHECK(compiled_module->is_asm_js());
    1291             :   Handle<ByteArray> offset_table(
    1292        2742 :       compiled_module->shared()->asm_js_offset_table(), isolate);
    1293             : 
    1294             :   // The last byte in the asm_js_offset_tables ByteArray tells whether it is
    1295             :   // still encoded (0) or decoded (1).
    1296             :   enum AsmJsTableType : int { Encoded = 0, Decoded = 1 };
    1297        1371 :   int table_type = offset_table->get(offset_table->length() - 1);
    1298             :   DCHECK(table_type == Encoded || table_type == Decoded);
    1299        1371 :   if (table_type == Decoded) return offset_table;
    1300             : 
    1301             :   AsmJsOffsetsResult asm_offsets;
    1302             :   {
    1303             :     DisallowHeapAllocation no_gc;
    1304          78 :     const byte* bytes_start = offset_table->GetDataStartAddress();
    1305          78 :     const byte* bytes_end = bytes_start + offset_table->length() - 1;
    1306          78 :     asm_offsets = wasm::DecodeAsmJsOffsets(bytes_start, bytes_end);
    1307             :   }
    1308             :   // Wasm bytes must be valid and must contain asm.js offset table.
    1309             :   DCHECK(asm_offsets.ok());
    1310             :   DCHECK_GE(kMaxInt, asm_offsets.val.size());
    1311         156 :   int num_functions = static_cast<int>(asm_offsets.val.size());
    1312             :   int num_imported_functions =
    1313          78 :       static_cast<int>(compiled_module->module()->num_imported_functions);
    1314             :   DCHECK_EQ(compiled_module->module()->functions.size(),
    1315             :             static_cast<size_t>(num_functions) + num_imported_functions);
    1316             :   int num_entries = 0;
    1317         334 :   for (int func = 0; func < num_functions; ++func) {
    1318         512 :     size_t new_size = asm_offsets.val[func].size();
    1319             :     DCHECK_LE(new_size, static_cast<size_t>(kMaxInt) - num_entries);
    1320         256 :     num_entries += static_cast<int>(new_size);
    1321             :   }
    1322             :   // One byte to encode that this is a decoded table.
    1323             :   DCHECK_GE(kMaxInt,
    1324             :             1 + static_cast<uint64_t>(num_entries) * kOTESize * kIntSize);
    1325          78 :   int total_size = 1 + num_entries * kOTESize * kIntSize;
    1326             :   Handle<ByteArray> decoded_table =
    1327          78 :       isolate->factory()->NewByteArray(total_size, TENURED);
    1328             :   decoded_table->set(total_size - 1, AsmJsTableType::Decoded);
    1329         156 :   compiled_module->shared()->set_asm_js_offset_table(*decoded_table);
    1330             : 
    1331             :   int idx = 0;
    1332         256 :   std::vector<WasmFunction>& wasm_funs = compiled_module->module()->functions;
    1333         334 :   for (int func = 0; func < num_functions; ++func) {
    1334         256 :     std::vector<AsmJsOffsetEntry>& func_asm_offsets = asm_offsets.val[func];
    1335         256 :     if (func_asm_offsets.empty()) continue;
    1336             :     int func_offset =
    1337         356 :         wasm_funs[num_imported_functions + func].code_start_offset;
    1338         673 :     for (AsmJsOffsetEntry& e : func_asm_offsets) {
    1339             :       // Byte offsets must be strictly monotonously increasing:
    1340             :       DCHECK_IMPLIES(idx > 0, func_offset + e.byte_offset >
    1341             :                                   decoded_table->get_int(idx - kOTESize));
    1342         317 :       decoded_table->set_int(idx + kOTEByteOffset, func_offset + e.byte_offset);
    1343         317 :       decoded_table->set_int(idx + kOTECallPosition, e.source_position_call);
    1344             :       decoded_table->set_int(idx + kOTENumberConvPosition,
    1345         317 :                              e.source_position_number_conversion);
    1346         317 :       idx += kOTESize;
    1347             :     }
    1348             :   }
    1349             :   DCHECK_EQ(total_size, idx * kIntSize + 1);
    1350          78 :   return decoded_table;
    1351             : }
    1352             : 
    1353             : }  // namespace
    1354             : 
    1355        1371 : int WasmCompiledModule::GetAsmJsSourcePosition(
    1356             :     Handle<WasmCompiledModule> compiled_module, uint32_t func_index,
    1357             :     uint32_t byte_offset, bool is_at_number_conversion) {
    1358             :   Isolate* isolate = compiled_module->GetIsolate();
    1359             :   Handle<ByteArray> offset_table =
    1360        1371 :       GetDecodedAsmJsOffsetTable(compiled_module, isolate);
    1361             : 
    1362             :   DCHECK_LT(func_index, compiled_module->module()->functions.size());
    1363             :   uint32_t func_code_offset =
    1364        4113 :       compiled_module->module()->functions[func_index].code_start_offset;
    1365        1371 :   uint32_t total_offset = func_code_offset + byte_offset;
    1366             : 
    1367             :   // Binary search for the total byte offset.
    1368             :   int left = 0;                                              // inclusive
    1369        1371 :   int right = offset_table->length() / kIntSize / kOTESize;  // exclusive
    1370             :   DCHECK_LT(left, right);
    1371        6200 :   while (right - left > 1) {
    1372        3458 :     int mid = left + (right - left) / 2;
    1373        3458 :     int mid_entry = offset_table->get_int(kOTESize * mid);
    1374             :     DCHECK_GE(kMaxInt, mid_entry);
    1375        3458 :     if (static_cast<uint32_t>(mid_entry) <= total_offset) {
    1376             :       left = mid;
    1377             :     } else {
    1378             :       right = mid;
    1379             :     }
    1380             :   }
    1381             :   // There should be an entry for each position that could show up on the stack
    1382             :   // trace:
    1383             :   DCHECK_EQ(total_offset, offset_table->get_int(kOTESize * left));
    1384        1371 :   int idx = is_at_number_conversion ? kOTENumberConvPosition : kOTECallPosition;
    1385        2742 :   return offset_table->get_int(kOTESize * left + idx);
    1386             : }
    1387             : 
    1388         100 : v8::debug::WasmDisassembly WasmCompiledModule::DisassembleFunction(
    1389             :     int func_index) {
    1390             :   DisallowHeapAllocation no_gc;
    1391             : 
    1392         200 :   if (func_index < 0 ||
    1393         100 :       static_cast<uint32_t>(func_index) >= module()->functions.size())
    1394             :     return {};
    1395             : 
    1396         100 :   SeqOneByteString* module_bytes_str = module_bytes();
    1397         100 :   Vector<const byte> module_bytes(module_bytes_str->GetChars(),
    1398             :                                   module_bytes_str->length());
    1399             : 
    1400         100 :   std::ostringstream disassembly_os;
    1401             :   v8::debug::WasmDisassembly::OffsetTable offset_table;
    1402             : 
    1403         100 :   PrintWasmText(module(), module_bytes, static_cast<uint32_t>(func_index),
    1404         200 :                 disassembly_os, &offset_table);
    1405             : 
    1406         200 :   return {disassembly_os.str(), std::move(offset_table)};
    1407             : }
    1408             : 
    1409          85 : bool WasmCompiledModule::GetPossibleBreakpoints(
    1410             :     const v8::debug::Location& start, const v8::debug::Location& end,
    1411             :     std::vector<v8::debug::BreakLocation>* locations) {
    1412             :   DisallowHeapAllocation no_gc;
    1413             : 
    1414         449 :   std::vector<WasmFunction>& functions = module()->functions;
    1415         255 :   if (start.GetLineNumber() < 0 || start.GetColumnNumber() < 0 ||
    1416         170 :       (!end.IsEmpty() &&
    1417         170 :        (end.GetLineNumber() < 0 || end.GetColumnNumber() < 0)))
    1418             :     return false;
    1419             : 
    1420             :   // start_func_index, start_offset and end_func_index is inclusive.
    1421             :   // end_offset is exclusive.
    1422             :   // start_offset and end_offset are module-relative byte offsets.
    1423          85 :   uint32_t start_func_index = start.GetLineNumber();
    1424         170 :   if (start_func_index >= functions.size()) return false;
    1425          85 :   int start_func_len = functions[start_func_index].code_end_offset -
    1426          85 :                        functions[start_func_index].code_start_offset;
    1427          85 :   if (start.GetColumnNumber() > start_func_len) return false;
    1428             :   uint32_t start_offset =
    1429          78 :       functions[start_func_index].code_start_offset + start.GetColumnNumber();
    1430             :   uint32_t end_func_index;
    1431             :   uint32_t end_offset;
    1432          78 :   if (end.IsEmpty()) {
    1433             :     // Default: everything till the end of the Script.
    1434           0 :     end_func_index = static_cast<uint32_t>(functions.size() - 1);
    1435           0 :     end_offset = functions[end_func_index].code_end_offset;
    1436             :   } else {
    1437             :     // If end is specified: Use it and check for valid input.
    1438          78 :     end_func_index = static_cast<uint32_t>(end.GetLineNumber());
    1439             : 
    1440             :     // Special case: Stop before the start of the next function. Change to: Stop
    1441             :     // at the end of the function before, such that we don't disassemble the
    1442             :     // next function also.
    1443          78 :     if (end.GetColumnNumber() == 0 && end_func_index > 0) {
    1444          33 :       --end_func_index;
    1445          66 :       end_offset = functions[end_func_index].code_end_offset;
    1446             :     } else {
    1447          90 :       if (end_func_index >= functions.size()) return false;
    1448             :       end_offset =
    1449          45 :           functions[end_func_index].code_start_offset + end.GetColumnNumber();
    1450          45 :       if (end_offset > functions[end_func_index].code_end_offset) return false;
    1451             :     }
    1452             :   }
    1453             : 
    1454          78 :   AccountingAllocator alloc;
    1455         156 :   Zone tmp(&alloc, ZONE_NAME);
    1456          78 :   const byte* module_start = module_bytes()->GetChars();
    1457             : 
    1458         156 :   for (uint32_t func_idx = start_func_index; func_idx <= end_func_index;
    1459             :        ++func_idx) {
    1460          78 :     WasmFunction& func = functions[func_idx];
    1461          78 :     if (func.code_start_offset == func.code_end_offset) continue;
    1462             : 
    1463             :     BodyLocalDecls locals(&tmp);
    1464             :     BytecodeIterator iterator(module_start + func.code_start_offset,
    1465          78 :                               module_start + func.code_end_offset, &locals);
    1466             :     DCHECK_LT(0u, locals.encoded_size);
    1467         736 :     for (uint32_t offset : iterator.offsets()) {
    1468         345 :       uint32_t total_offset = func.code_start_offset + offset;
    1469         345 :       if (total_offset >= end_offset) {
    1470             :         DCHECK_EQ(end_func_index, func_idx);
    1471             :         break;
    1472             :       }
    1473         313 :       if (total_offset < start_offset) continue;
    1474         178 :       locations->emplace_back(func_idx, offset, debug::kCommonBreakLocation);
    1475             :     }
    1476             :   }
    1477          78 :   return true;
    1478             : }
    1479             : 
    1480         106 : bool WasmCompiledModule::SetBreakPoint(
    1481             :     Handle<WasmCompiledModule> compiled_module, int* position,
    1482             :     Handle<Object> break_point_object) {
    1483             :   Isolate* isolate = compiled_module->GetIsolate();
    1484             : 
    1485             :   // Find the function for this breakpoint.
    1486         106 :   int func_index = compiled_module->GetContainingFunction(*position);
    1487         106 :   if (func_index < 0) return false;
    1488         212 :   WasmFunction& func = compiled_module->module()->functions[func_index];
    1489         106 :   int offset_in_func = *position - func.code_start_offset;
    1490             : 
    1491             :   // According to the current design, we should only be called with valid
    1492             :   // breakable positions.
    1493             :   DCHECK(IsBreakablePosition(compiled_module, func_index, offset_in_func));
    1494             : 
    1495             :   // Insert new break point into break_positions of shared module data.
    1496             :   WasmSharedModuleData::AddBreakpoint(compiled_module->shared(), *position,
    1497         106 :                                       break_point_object);
    1498             : 
    1499             :   // Iterate over all instances of this module and tell them to set this new
    1500             :   // breakpoint.
    1501         184 :   for (Handle<WasmInstanceObject> instance :
    1502         262 :        iterate_compiled_module_instance_chain(isolate, compiled_module)) {
    1503             :     Handle<WasmDebugInfo> debug_info =
    1504          78 :         WasmInstanceObject::GetOrCreateDebugInfo(instance);
    1505          78 :     WasmDebugInfo::SetBreakpoint(debug_info, func_index, offset_in_func);
    1506             :   }
    1507             : 
    1508         106 :   return true;
    1509             : }
    1510             : 
    1511         355 : MaybeHandle<FixedArray> WasmCompiledModule::CheckBreakPoints(int position) {
    1512         124 :   Isolate* isolate = GetIsolate();
    1513         710 :   if (!shared()->has_breakpoint_infos()) return {};
    1514             : 
    1515         710 :   Handle<FixedArray> breakpoint_infos(shared()->breakpoint_infos(), isolate);
    1516             :   int insert_pos =
    1517         355 :       FindBreakpointInfoInsertPos(isolate, breakpoint_infos, position);
    1518         355 :   if (insert_pos >= breakpoint_infos->length()) return {};
    1519             : 
    1520             :   Handle<Object> maybe_breakpoint_info(breakpoint_infos->get(insert_pos),
    1521             :                                        isolate);
    1522         355 :   if (maybe_breakpoint_info->IsUndefined(isolate)) return {};
    1523             :   Handle<BreakPointInfo> breakpoint_info =
    1524             :       Handle<BreakPointInfo>::cast(maybe_breakpoint_info);
    1525         209 :   if (breakpoint_info->source_position() != position) return {};
    1526             : 
    1527             :   Handle<Object> breakpoint_objects(breakpoint_info->break_point_objects(),
    1528             :                                     isolate);
    1529         124 :   return isolate->debug()->GetHitBreakPointObjects(breakpoint_objects);
    1530             : }
    1531             : 
    1532       12699 : MaybeHandle<Code> WasmCompiledModule::CompileLazy(
    1533             :     Isolate* isolate, Handle<WasmInstanceObject> instance, Handle<Code> caller,
    1534             :     int offset, int func_index, bool patch_caller) {
    1535       25398 :   isolate->set_context(*instance->compiled_module()->native_context());
    1536             :   Object* orch_obj =
    1537       25398 :       instance->compiled_module()->shared()->lazy_compilation_orchestrator();
    1538             :   LazyCompilationOrchestrator* orch =
    1539             :       Managed<LazyCompilationOrchestrator>::cast(orch_obj)->get();
    1540             :   return orch->CompileLazy(isolate, instance, caller, offset, func_index,
    1541       12699 :                            patch_caller);
    1542             : }
    1543             : 
    1544       87727 : Handle<WasmInstanceWrapper> WasmInstanceWrapper::New(
    1545             :     Isolate* isolate, Handle<WasmInstanceObject> instance) {
    1546             :   Handle<FixedArray> array =
    1547       87727 :       isolate->factory()->NewFixedArray(kWrapperPropertyCount, TENURED);
    1548             :   Handle<WasmInstanceWrapper> instance_wrapper(
    1549             :       reinterpret_cast<WasmInstanceWrapper*>(*array), isolate);
    1550       87727 :   Handle<WeakCell> cell = isolate->factory()->NewWeakCell(instance);
    1551       87727 :   instance_wrapper->set(kWrapperInstanceObject, *cell);
    1552       87727 :   return instance_wrapper;
    1553             : }
    1554             : 
    1555        6497 : bool WasmInstanceWrapper::IsWasmInstanceWrapper(Object* obj) {
    1556        6497 :   if (!obj->IsFixedArray()) return false;
    1557             :   Handle<FixedArray> array = handle(FixedArray::cast(obj));
    1558        3677 :   if (array->length() != kWrapperPropertyCount) return false;
    1559        3677 :   if (!array->get(kWrapperInstanceObject)->IsWeakCell()) return false;
    1560             :   Isolate* isolate = array->GetIsolate();
    1561        6573 :   if (!array->get(kNextInstanceWrapper)->IsUndefined(isolate) &&
    1562             :       !array->get(kNextInstanceWrapper)->IsFixedArray())
    1563             :     return false;
    1564        7272 :   if (!array->get(kPreviousInstanceWrapper)->IsUndefined(isolate) &&
    1565             :       !array->get(kPreviousInstanceWrapper)->IsFixedArray())
    1566             :     return false;
    1567        3677 :   return true;
    1568             : }

Generated by: LCOV version 1.10