LCOV - code coverage report
Current view: top level - src/wasm - wasm-objects.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 650 682 95.3 %
Date: 2019-02-19 Functions: 79 81 97.5 %

          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/code-factory.h"
      11             : #include "src/compiler/wasm-compiler.h"
      12             : #include "src/counters.h"
      13             : #include "src/debug/debug-interface.h"
      14             : #include "src/objects-inl.h"
      15             : #include "src/objects/debug-objects-inl.h"
      16             : #include "src/objects/shared-function-info.h"
      17             : #include "src/objects/struct-inl.h"
      18             : #include "src/trap-handler/trap-handler.h"
      19             : #include "src/wasm/jump-table-assembler.h"
      20             : #include "src/wasm/module-compiler.h"
      21             : #include "src/wasm/module-decoder.h"
      22             : #include "src/wasm/module-instantiate.h"
      23             : #include "src/wasm/wasm-code-manager.h"
      24             : #include "src/wasm/wasm-engine.h"
      25             : #include "src/wasm/wasm-limits.h"
      26             : #include "src/wasm/wasm-memory.h"
      27             : #include "src/wasm/wasm-module.h"
      28             : #include "src/wasm/wasm-objects-inl.h"
      29             : #include "src/wasm/wasm-text.h"
      30             : 
      31             : #define TRACE(...)                                      \
      32             :   do {                                                  \
      33             :     if (FLAG_trace_wasm_instances) PrintF(__VA_ARGS__); \
      34             :   } while (false)
      35             : 
      36             : #define TRACE_IFT(...)              \
      37             :   do {                              \
      38             :     if (false) PrintF(__VA_ARGS__); \
      39             :   } while (false)
      40             : 
      41             : namespace v8 {
      42             : namespace internal {
      43             : 
      44             : // Import a few often used types from the wasm namespace.
      45             : using WasmFunction = wasm::WasmFunction;
      46             : using WasmModule = wasm::WasmModule;
      47             : 
      48             : namespace {
      49             : 
      50             : // Manages the natively-allocated memory for a WasmInstanceObject. Since
      51             : // an instance finalizer is not guaranteed to run upon isolate shutdown,
      52             : // we must use a Managed<WasmInstanceNativeAllocations> to guarantee
      53             : // it is freed.
      54             : // Native allocations are the signature ids and targets for indirect call
      55             : // targets, as well as the call targets for imported functions.
      56             : class WasmInstanceNativeAllocations {
      57             :  public:
      58             : // Helper macro to set an internal field and the corresponding field
      59             : // on an instance.
      60             : #define SET(instance, field, value) \
      61             :   {                                 \
      62             :     auto v = value;                 \
      63             :     this->field##_ = v;             \
      64             :     instance->set_##field(v);       \
      65             :   }
      66             : 
      67             :   // Allocates initial native storage for a given instance.
      68     1229053 :   WasmInstanceNativeAllocations(Handle<WasmInstanceObject> instance,
      69             :                                 size_t num_imported_functions,
      70             :                                 size_t num_imported_mutable_globals,
      71             :                                 size_t num_data_segments,
      72     1229053 :                                 size_t num_elem_segments) {
      73     1229053 :     SET(instance, imported_function_targets,
      74             :         reinterpret_cast<Address*>(
      75             :             calloc(num_imported_functions, sizeof(Address))));
      76     1229053 :     SET(instance, imported_mutable_globals,
      77             :         reinterpret_cast<Address*>(
      78             :             calloc(num_imported_mutable_globals, sizeof(Address))));
      79     1229053 :     SET(instance, data_segment_starts,
      80             :         reinterpret_cast<Address*>(calloc(num_data_segments, sizeof(Address))));
      81     1229053 :     SET(instance, data_segment_sizes,
      82             :         reinterpret_cast<uint32_t*>(
      83             :             calloc(num_data_segments, sizeof(uint32_t))));
      84     1229053 :     SET(instance, dropped_data_segments,
      85             :         reinterpret_cast<uint8_t*>(calloc(num_data_segments, sizeof(uint8_t))));
      86     1229053 :     SET(instance, dropped_elem_segments,
      87             :         reinterpret_cast<uint8_t*>(calloc(num_elem_segments, sizeof(uint8_t))));
      88     1229053 :   }
      89     1229052 :   ~WasmInstanceNativeAllocations() {
      90     1229052 :     ::free(indirect_function_table_sig_ids_);
      91     1229052 :     indirect_function_table_sig_ids_ = nullptr;
      92     1229052 :     ::free(indirect_function_table_targets_);
      93     1229052 :     indirect_function_table_targets_ = nullptr;
      94     1229052 :     ::free(imported_function_targets_);
      95     1229052 :     imported_function_targets_ = nullptr;
      96     1229052 :     ::free(imported_mutable_globals_);
      97     1229052 :     imported_mutable_globals_ = nullptr;
      98     1229052 :     ::free(data_segment_starts_);
      99     1229052 :     data_segment_starts_ = nullptr;
     100     1229052 :     ::free(data_segment_sizes_);
     101     1229052 :     data_segment_sizes_ = nullptr;
     102     1229052 :     ::free(dropped_data_segments_);
     103     1229052 :     dropped_data_segments_ = nullptr;
     104     1229052 :     ::free(dropped_elem_segments_);
     105     1229052 :     dropped_elem_segments_ = nullptr;
     106     1229052 :   }
     107             :   // Resizes the indirect function table.
     108        3049 :   void resize_indirect_function_table(Isolate* isolate,
     109             :                                       Handle<WasmInstanceObject> instance,
     110             :                                       uint32_t new_size) {
     111             :     uint32_t old_size = instance->indirect_function_table_size();
     112             :     void* new_sig_ids = nullptr;
     113             :     void* new_targets = nullptr;
     114             :     Handle<FixedArray> new_refs;
     115        3049 :     if (indirect_function_table_sig_ids_) {
     116             :       // Reallocate the old storage.
     117             :       new_sig_ids = realloc(indirect_function_table_sig_ids_,
     118         888 :                             new_size * sizeof(uint32_t));
     119             :       new_targets =
     120         888 :           realloc(indirect_function_table_targets_, new_size * sizeof(Address));
     121             : 
     122        1776 :       Handle<FixedArray> old(instance->indirect_function_table_refs(), isolate);
     123             :       new_refs = isolate->factory()->CopyFixedArrayAndGrow(
     124         888 :           old, static_cast<int>(new_size - old_size));
     125             :     } else {
     126             :       // Allocate new storage.
     127        2161 :       new_sig_ids = malloc(new_size * sizeof(uint32_t));
     128        2161 :       new_targets = malloc(new_size * sizeof(Address));
     129        2161 :       new_refs = isolate->factory()->NewFixedArray(static_cast<int>(new_size));
     130             :     }
     131             :     // Initialize new entries.
     132             :     instance->set_indirect_function_table_size(new_size);
     133        3049 :     SET(instance, indirect_function_table_sig_ids,
     134             :         reinterpret_cast<uint32_t*>(new_sig_ids));
     135        3049 :     SET(instance, indirect_function_table_targets,
     136             :         reinterpret_cast<Address*>(new_targets));
     137             : 
     138        3049 :     instance->set_indirect_function_table_refs(*new_refs);
     139    20220233 :     for (uint32_t j = old_size; j < new_size; j++) {
     140    40440466 :       IndirectFunctionTableEntry(instance, static_cast<int>(j)).clear();
     141             :     }
     142        3049 :   }
     143             :   uint32_t* indirect_function_table_sig_ids_ = nullptr;
     144             :   Address* indirect_function_table_targets_ = nullptr;
     145             :   Address* imported_function_targets_ = nullptr;
     146             :   Address* imported_mutable_globals_ = nullptr;
     147             :   Address* data_segment_starts_ = nullptr;
     148             :   uint32_t* data_segment_sizes_ = nullptr;
     149             :   uint8_t* dropped_data_segments_ = nullptr;
     150             :   uint8_t* dropped_elem_segments_ = nullptr;
     151             : #undef SET
     152             : };
     153             : 
     154     1229053 : size_t EstimateNativeAllocationsSize(const WasmModule* module) {
     155             :   size_t estimate =
     156     1229053 :       sizeof(WasmInstanceNativeAllocations) +
     157     2458106 :       (1 * kSystemPointerSize * module->num_imported_mutable_globals) +
     158     1229053 :       (2 * kSystemPointerSize * module->num_imported_functions) +
     159     1229053 :       ((kSystemPointerSize + sizeof(uint32_t) + sizeof(uint8_t)) *
     160     1229053 :        module->num_declared_data_segments);
     161     2460851 :   for (auto& table : module->tables) {
     162        2745 :     estimate += 3 * kSystemPointerSize * table.initial_size;
     163             :   }
     164     1229053 :   return estimate;
     165             : }
     166             : 
     167        3049 : WasmInstanceNativeAllocations* GetNativeAllocations(
     168             :     WasmInstanceObject instance) {
     169             :   return Managed<WasmInstanceNativeAllocations>::cast(
     170        6098 :              instance->managed_native_allocations())
     171        9147 :       ->raw();
     172             : }
     173             : 
     174             : #ifdef DEBUG
     175             : bool IsBreakablePosition(wasm::NativeModule* native_module, int func_index,
     176             :                          int offset_in_func) {
     177             :   AccountingAllocator alloc;
     178             :   Zone tmp(&alloc, ZONE_NAME);
     179             :   wasm::BodyLocalDecls locals(&tmp);
     180             :   const byte* module_start = native_module->wire_bytes().start();
     181             :   const WasmFunction& func = native_module->module()->functions[func_index];
     182             :   wasm::BytecodeIterator iterator(module_start + func.code.offset(),
     183             :                                   module_start + func.code.end_offset(),
     184             :                                   &locals);
     185             :   DCHECK_LT(0, locals.encoded_size);
     186             :   for (uint32_t offset : iterator.offsets()) {
     187             :     if (offset > static_cast<uint32_t>(offset_in_func)) break;
     188             :     if (offset == static_cast<uint32_t>(offset_in_func)) return true;
     189             :   }
     190             :   return false;
     191             : }
     192             : #endif  // DEBUG
     193             : 
     194             : enum DispatchTableElements : int {
     195             :   kDispatchTableInstanceOffset,
     196             :   kDispatchTableIndexOffset,
     197             :   kDispatchTableFunctionTableOffset,
     198             :   // Marker:
     199             :   kDispatchTableNumElements
     200             : };
     201             : 
     202             : }  // namespace
     203             : 
     204             : // static
     205     1093792 : Handle<WasmModuleObject> WasmModuleObject::New(
     206             :     Isolate* isolate, const wasm::WasmFeatures& enabled,
     207             :     std::shared_ptr<const wasm::WasmModule> shared_module,
     208             :     OwnedVector<const uint8_t> wire_bytes, Handle<Script> script,
     209             :     Handle<ByteArray> asm_js_offset_table) {
     210             :   // Create a new {NativeModule} first.
     211             :   size_t code_size_estimate =
     212     1093792 :       wasm::WasmCodeManager::EstimateNativeModuleCodeSize(shared_module.get());
     213             :   auto native_module = isolate->wasm_engine()->NewNativeModule(
     214             :       isolate, enabled, code_size_estimate,
     215     2187584 :       wasm::NativeModule::kCanAllocateMoreMemory, std::move(shared_module));
     216     2187584 :   native_module->SetWireBytes(std::move(wire_bytes));
     217     1093792 :   native_module->SetRuntimeStubs(isolate);
     218             : 
     219             :   // Delegate to the shared {WasmModuleObject::New} allocator.
     220             :   Handle<WasmModuleObject> module_object =
     221     2187584 :       New(isolate, std::move(native_module), script, code_size_estimate);
     222     1093792 :   if (!asm_js_offset_table.is_null()) {
     223           0 :     module_object->set_asm_js_offset_table(*asm_js_offset_table);
     224             :   }
     225     2187584 :   return module_object;
     226             : }
     227             : 
     228             : // static
     229     1096120 : Handle<WasmModuleObject> WasmModuleObject::New(
     230             :     Isolate* isolate, std::shared_ptr<wasm::NativeModule> native_module,
     231             :     Handle<Script> script, size_t code_size_estimate) {
     232     1096120 :   const WasmModule* module = native_module->module();
     233     1096120 :   int export_wrapper_size = static_cast<int>(module->num_exported_functions);
     234             :   Handle<FixedArray> export_wrappers =
     235     1096120 :       isolate->factory()->NewFixedArray(export_wrapper_size, TENURED);
     236             :   return New(isolate, std::move(native_module), script, export_wrappers,
     237     2192240 :              code_size_estimate);
     238             : }
     239             : 
     240             : // static
     241     1235170 : Handle<WasmModuleObject> WasmModuleObject::New(
     242             :     Isolate* isolate, std::shared_ptr<wasm::NativeModule> native_module,
     243             :     Handle<Script> script, Handle<FixedArray> export_wrappers,
     244             :     size_t code_size_estimate) {
     245     1235170 :   const WasmModule* module = native_module->module();
     246             : 
     247             :   // Use the given shared {NativeModule}, but increase its reference count by
     248             :   // allocating a new {Managed<T>} that the {WasmModuleObject} references.
     249             :   size_t memory_estimate =
     250             :       code_size_estimate +
     251     1235170 :       wasm::WasmCodeManager::EstimateNativeModuleNonCodeSize(module);
     252             :   Handle<Managed<wasm::NativeModule>> managed_native_module =
     253             :       Managed<wasm::NativeModule>::FromSharedPtr(isolate, memory_estimate,
     254     2470342 :                                                  std::move(native_module));
     255             : 
     256             :   Handle<WasmModuleObject> module_object = Handle<WasmModuleObject>::cast(
     257     1235171 :       isolate->factory()->NewJSObject(isolate->wasm_module_constructor()));
     258     1235171 :   module_object->set_export_wrappers(*export_wrappers);
     259     1235171 :   if (script->type() == Script::TYPE_WASM) {
     260     2460418 :     script->set_wasm_module_object(*module_object);
     261             :   }
     262     1235170 :   module_object->set_script(*script);
     263             :   module_object->set_weak_instance_list(
     264     1235171 :       ReadOnlyRoots(isolate).empty_weak_array_list());
     265     1235171 :   module_object->set_managed_native_module(*managed_native_module);
     266     1235171 :   return module_object;
     267             : }
     268             : 
     269         112 : bool WasmModuleObject::SetBreakPoint(Handle<WasmModuleObject> module_object,
     270             :                                      int* position,
     271             :                                      Handle<BreakPoint> break_point) {
     272             :   Isolate* isolate = module_object->GetIsolate();
     273             : 
     274             :   // Find the function for this breakpoint.
     275         224 :   int func_index = module_object->GetContainingFunction(*position);
     276         112 :   if (func_index < 0) return false;
     277         448 :   const WasmFunction& func = module_object->module()->functions[func_index];
     278         112 :   int offset_in_func = *position - func.code.offset();
     279             : 
     280             :   // According to the current design, we should only be called with valid
     281             :   // breakable positions.
     282             :   DCHECK(IsBreakablePosition(module_object->native_module(), func_index,
     283             :                              offset_in_func));
     284             : 
     285             :   // Insert new break point into break_positions of module object.
     286         112 :   WasmModuleObject::AddBreakpoint(module_object, *position, break_point);
     287             : 
     288             :   // Iterate over all instances of this module and tell them to set this new
     289             :   // breakpoint. We do this using the weak list of all instances.
     290             :   Handle<WeakArrayList> weak_instance_list(module_object->weak_instance_list(),
     291         224 :                                            isolate);
     292         448 :   for (int i = 0; i < weak_instance_list->length(); ++i) {
     293         112 :     MaybeObject maybe_instance = weak_instance_list->Get(i);
     294         112 :     if (maybe_instance->IsWeak()) {
     295             :       Handle<WasmInstanceObject> instance(
     296             :           WasmInstanceObject::cast(maybe_instance->GetHeapObjectAssumeWeak()),
     297             :           isolate);
     298             :       Handle<WasmDebugInfo> debug_info =
     299         112 :           WasmInstanceObject::GetOrCreateDebugInfo(instance);
     300         112 :       WasmDebugInfo::SetBreakpoint(debug_info, func_index, offset_in_func);
     301             :     }
     302             :   }
     303             : 
     304             :   return true;
     305             : }
     306             : 
     307             : namespace {
     308             : 
     309        2332 : int GetBreakpointPos(Isolate* isolate, Object break_point_info_or_undef) {
     310        2332 :   if (break_point_info_or_undef->IsUndefined(isolate)) return kMaxInt;
     311             :   return BreakPointInfo::cast(break_point_info_or_undef)->source_position();
     312             : }
     313             : 
     314         668 : int FindBreakpointInfoInsertPos(Isolate* isolate,
     315             :                                 Handle<FixedArray> breakpoint_infos,
     316             :                                 int position) {
     317             :   // Find insert location via binary search, taking care of undefined values on
     318             :   // the right. Position is always greater than zero.
     319             :   DCHECK_LT(0, position);
     320             : 
     321             :   int left = 0;                            // inclusive
     322             :   int right = breakpoint_infos->length();  // exclusive
     323        2896 :   while (right - left > 1) {
     324        1560 :     int mid = left + (right - left) / 2;
     325        1560 :     Object mid_obj = breakpoint_infos->get(mid);
     326        1560 :     if (GetBreakpointPos(isolate, mid_obj) <= position) {
     327             :       left = mid;
     328             :     } else {
     329             :       right = mid;
     330             :     }
     331             :   }
     332             : 
     333         668 :   int left_pos = GetBreakpointPos(isolate, breakpoint_infos->get(left));
     334         668 :   return left_pos < position ? left + 1 : left;
     335             : }
     336             : 
     337             : }  // namespace
     338             : 
     339         112 : void WasmModuleObject::AddBreakpoint(Handle<WasmModuleObject> module_object,
     340             :                                      int position,
     341             :                                      Handle<BreakPoint> break_point) {
     342             :   Isolate* isolate = module_object->GetIsolate();
     343             :   Handle<FixedArray> breakpoint_infos;
     344         224 :   if (module_object->has_breakpoint_infos()) {
     345         120 :     breakpoint_infos = handle(module_object->breakpoint_infos(), isolate);
     346             :   } else {
     347          52 :     breakpoint_infos = isolate->factory()->NewFixedArray(4, TENURED);
     348          52 :     module_object->set_breakpoint_infos(*breakpoint_infos);
     349             :   }
     350             : 
     351             :   int insert_pos =
     352         112 :       FindBreakpointInfoInsertPos(isolate, breakpoint_infos, position);
     353             : 
     354             :   // If a BreakPointInfo object already exists for this position, add the new
     355             :   // breakpoint object and return.
     356         216 :   if (insert_pos < breakpoint_infos->length() &&
     357         104 :       GetBreakpointPos(isolate, breakpoint_infos->get(insert_pos)) ==
     358             :           position) {
     359             :     Handle<BreakPointInfo> old_info(
     360             :         BreakPointInfo::cast(breakpoint_infos->get(insert_pos)), isolate);
     361           0 :     BreakPointInfo::SetBreakPoint(isolate, old_info, break_point);
     362         112 :     return;
     363             :   }
     364             : 
     365             :   // Enlarge break positions array if necessary.
     366         112 :   bool need_realloc = !breakpoint_infos->get(breakpoint_infos->length() - 1)
     367         224 :                            ->IsUndefined(isolate);
     368             :   Handle<FixedArray> new_breakpoint_infos = breakpoint_infos;
     369         112 :   if (need_realloc) {
     370             :     new_breakpoint_infos = isolate->factory()->NewFixedArray(
     371          12 :         2 * breakpoint_infos->length(), TENURED);
     372          12 :     module_object->set_breakpoint_infos(*new_breakpoint_infos);
     373             :     // Copy over the entries [0, insert_pos).
     374          60 :     for (int i = 0; i < insert_pos; ++i)
     375          48 :       new_breakpoint_infos->set(i, breakpoint_infos->get(i));
     376             :   }
     377             : 
     378             :   // Move elements [insert_pos, ...] up by one.
     379         512 :   for (int i = breakpoint_infos->length() - 1; i >= insert_pos; --i) {
     380         400 :     Object entry = breakpoint_infos->get(i);
     381         744 :     if (entry->IsUndefined(isolate)) continue;
     382         112 :     new_breakpoint_infos->set(i + 1, entry);
     383             :   }
     384             : 
     385             :   // Generate new BreakpointInfo.
     386             :   Handle<BreakPointInfo> breakpoint_info =
     387         112 :       isolate->factory()->NewBreakPointInfo(position);
     388         112 :   BreakPointInfo::SetBreakPoint(isolate, breakpoint_info, break_point);
     389             : 
     390             :   // Now insert new position at insert_pos.
     391         224 :   new_breakpoint_infos->set(insert_pos, *breakpoint_info);
     392             : }
     393             : 
     394      133201 : void WasmModuleObject::SetBreakpointsOnNewInstance(
     395             :     Handle<WasmModuleObject> module_object,
     396             :     Handle<WasmInstanceObject> instance) {
     397      399603 :   if (!module_object->has_breakpoint_infos()) return;
     398             :   Isolate* isolate = module_object->GetIsolate();
     399             :   Handle<WasmDebugInfo> debug_info =
     400           0 :       WasmInstanceObject::GetOrCreateDebugInfo(instance);
     401             : 
     402             :   Handle<FixedArray> breakpoint_infos(module_object->breakpoint_infos(),
     403           0 :                                       isolate);
     404             :   // If the array exists, it should not be empty.
     405             :   DCHECK_LT(0, breakpoint_infos->length());
     406             : 
     407           0 :   for (int i = 0, e = breakpoint_infos->length(); i < e; ++i) {
     408             :     Handle<Object> obj(breakpoint_infos->get(i), isolate);
     409           0 :     if (obj->IsUndefined(isolate)) {
     410             :       for (; i < e; ++i) {
     411             :         DCHECK(breakpoint_infos->get(i)->IsUndefined(isolate));
     412             :       }
     413           0 :       break;
     414             :     }
     415           0 :     Handle<BreakPointInfo> breakpoint_info = Handle<BreakPointInfo>::cast(obj);
     416             :     int position = breakpoint_info->source_position();
     417             : 
     418             :     // Find the function for this breakpoint, and set the breakpoint.
     419           0 :     int func_index = module_object->GetContainingFunction(position);
     420             :     DCHECK_LE(0, func_index);
     421           0 :     const WasmFunction& func = module_object->module()->functions[func_index];
     422           0 :     int offset_in_func = position - func.code.offset();
     423           0 :     WasmDebugInfo::SetBreakpoint(debug_info, func_index, offset_in_func);
     424             :   }
     425             : }
     426             : 
     427             : namespace {
     428             : 
     429             : enum AsmJsOffsetTableEntryLayout {
     430             :   kOTEByteOffset,
     431             :   kOTECallPosition,
     432             :   kOTENumberConvPosition,
     433             :   kOTESize
     434             : };
     435             : 
     436         784 : Handle<ByteArray> GetDecodedAsmJsOffsetTable(
     437             :     Handle<WasmModuleObject> module_object, Isolate* isolate) {
     438             :   DCHECK(module_object->is_asm_js());
     439        1568 :   Handle<ByteArray> offset_table(module_object->asm_js_offset_table(), isolate);
     440             : 
     441             :   // The last byte in the asm_js_offset_tables ByteArray tells whether it is
     442             :   // still encoded (0) or decoded (1).
     443             :   enum AsmJsTableType : int { Encoded = 0, Decoded = 1 };
     444         784 :   int table_type = offset_table->get(offset_table->length() - 1);
     445             :   DCHECK(table_type == Encoded || table_type == Decoded);
     446         784 :   if (table_type == Decoded) return offset_table;
     447             : 
     448             :   wasm::AsmJsOffsets asm_offsets;
     449             :   {
     450             :     DisallowHeapAllocation no_gc;
     451             :     byte* bytes_start = offset_table->GetDataStartAddress();
     452             :     byte* bytes_end = reinterpret_cast<byte*>(
     453         140 :         reinterpret_cast<Address>(bytes_start) + offset_table->length() - 1);
     454         280 :     asm_offsets = wasm::DecodeAsmJsOffsets(bytes_start, bytes_end).value();
     455             :   }
     456             :   // Wasm bytes must be valid and must contain asm.js offset table.
     457             :   DCHECK_GE(kMaxInt, asm_offsets.size());
     458         280 :   int num_functions = static_cast<int>(asm_offsets.size());
     459             :   int num_imported_functions =
     460         280 :       static_cast<int>(module_object->module()->num_imported_functions);
     461             :   DCHECK_EQ(module_object->module()->functions.size(),
     462             :             static_cast<size_t>(num_functions) + num_imported_functions);
     463             :   int num_entries = 0;
     464         472 :   for (int func = 0; func < num_functions; ++func) {
     465         664 :     size_t new_size = asm_offsets[func].size();
     466             :     DCHECK_LE(new_size, static_cast<size_t>(kMaxInt) - num_entries);
     467         332 :     num_entries += static_cast<int>(new_size);
     468             :   }
     469             :   // One byte to encode that this is a decoded table.
     470             :   DCHECK_GE(kMaxInt,
     471             :             1 + static_cast<uint64_t>(num_entries) * kOTESize * kIntSize);
     472         140 :   int total_size = 1 + num_entries * kOTESize * kIntSize;
     473             :   Handle<ByteArray> decoded_table =
     474         140 :       isolate->factory()->NewByteArray(total_size, TENURED);
     475             :   decoded_table->set(total_size - 1, AsmJsTableType::Decoded);
     476         140 :   module_object->set_asm_js_offset_table(*decoded_table);
     477             : 
     478             :   int idx = 0;
     479         192 :   const std::vector<WasmFunction>& wasm_funs =
     480         280 :       module_object->module()->functions;
     481         472 :   for (int func = 0; func < num_functions; ++func) {
     482         332 :     std::vector<wasm::AsmJsOffsetEntry>& func_asm_offsets = asm_offsets[func];
     483         332 :     if (func_asm_offsets.empty()) continue;
     484         384 :     int func_offset = wasm_funs[num_imported_functions + func].code.offset();
     485         832 :     for (wasm::AsmJsOffsetEntry& e : func_asm_offsets) {
     486             :       // Byte offsets must be strictly monotonously increasing:
     487             :       DCHECK_IMPLIES(idx > 0, func_offset + e.byte_offset >
     488             :                                   decoded_table->get_int(idx - kOTESize));
     489         448 :       decoded_table->set_int(idx + kOTEByteOffset, func_offset + e.byte_offset);
     490         448 :       decoded_table->set_int(idx + kOTECallPosition, e.source_position_call);
     491             :       decoded_table->set_int(idx + kOTENumberConvPosition,
     492         448 :                              e.source_position_number_conversion);
     493         448 :       idx += kOTESize;
     494             :     }
     495             :   }
     496             :   DCHECK_EQ(total_size, idx * kIntSize + 1);
     497         140 :   return decoded_table;
     498             : }
     499             : 
     500             : }  // namespace
     501             : 
     502      152715 : int WasmModuleObject::GetSourcePosition(Handle<WasmModuleObject> module_object,
     503             :                                         uint32_t func_index,
     504             :                                         uint32_t byte_offset,
     505             :                                         bool is_at_number_conversion) {
     506             :   Isolate* isolate = module_object->GetIsolate();
     507      305430 :   const WasmModule* module = module_object->module();
     508             : 
     509      152715 :   if (module->origin != wasm::kAsmJsOrigin) {
     510             :     // for non-asm.js modules, we just add the function's start offset
     511             :     // to make a module-relative position.
     512      151931 :     return byte_offset + module_object->GetFunctionOffset(func_index);
     513             :   }
     514             : 
     515             :   // asm.js modules have an additional offset table that must be searched.
     516             :   Handle<ByteArray> offset_table =
     517         784 :       GetDecodedAsmJsOffsetTable(module_object, isolate);
     518             : 
     519             :   DCHECK_LT(func_index, module->functions.size());
     520        1568 :   uint32_t func_code_offset = module->functions[func_index].code.offset();
     521         784 :   uint32_t total_offset = func_code_offset + byte_offset;
     522             : 
     523             :   // Binary search for the total byte offset.
     524             :   int left = 0;                                              // inclusive
     525         784 :   int right = offset_table->length() / kIntSize / kOTESize;  // exclusive
     526             :   DCHECK_LT(left, right);
     527        3048 :   while (right - left > 1) {
     528        1480 :     int mid = left + (right - left) / 2;
     529        1480 :     int mid_entry = offset_table->get_int(kOTESize * mid);
     530             :     DCHECK_GE(kMaxInt, mid_entry);
     531        1480 :     if (static_cast<uint32_t>(mid_entry) <= total_offset) {
     532             :       left = mid;
     533             :     } else {
     534             :       right = mid;
     535             :     }
     536             :   }
     537             :   // There should be an entry for each position that could show up on the stack
     538             :   // trace:
     539             :   DCHECK_EQ(total_offset, offset_table->get_int(kOTESize * left));
     540         784 :   int idx = is_at_number_conversion ? kOTENumberConvPosition : kOTECallPosition;
     541         784 :   return offset_table->get_int(kOTESize * left + idx);
     542             : }
     543             : 
     544          80 : v8::debug::WasmDisassembly WasmModuleObject::DisassembleFunction(
     545             :     int func_index) {
     546             :   DisallowHeapAllocation no_gc;
     547             : 
     548         160 :   if (func_index < 0 ||
     549         160 :       static_cast<uint32_t>(func_index) >= module()->functions.size())
     550           0 :     return {};
     551             : 
     552          80 :   wasm::ModuleWireBytes wire_bytes(native_module()->wire_bytes());
     553             : 
     554          80 :   std::ostringstream disassembly_os;
     555             :   v8::debug::WasmDisassembly::OffsetTable offset_table;
     556             : 
     557             :   PrintWasmText(module(), wire_bytes, static_cast<uint32_t>(func_index),
     558         160 :                 disassembly_os, &offset_table);
     559             : 
     560         160 :   return {disassembly_os.str(), std::move(offset_table)};
     561             : }
     562             : 
     563          80 : bool WasmModuleObject::GetPossibleBreakpoints(
     564             :     const v8::debug::Location& start, const v8::debug::Location& end,
     565             :     std::vector<v8::debug::BreakLocation>* locations) {
     566             :   DisallowHeapAllocation no_gc;
     567             : 
     568         336 :   const std::vector<WasmFunction>& functions = module()->functions;
     569         240 :   if (start.GetLineNumber() < 0 || start.GetColumnNumber() < 0 ||
     570         160 :       (!end.IsEmpty() &&
     571         160 :        (end.GetLineNumber() < 0 || end.GetColumnNumber() < 0)))
     572             :     return false;
     573             : 
     574             :   // start_func_index, start_offset and end_func_index is inclusive.
     575             :   // end_offset is exclusive.
     576             :   // start_offset and end_offset are module-relative byte offsets.
     577          80 :   uint32_t start_func_index = start.GetLineNumber();
     578         160 :   if (start_func_index >= functions.size()) return false;
     579          80 :   int start_func_len = functions[start_func_index].code.length();
     580          80 :   if (start.GetColumnNumber() > start_func_len) return false;
     581             :   uint32_t start_offset =
     582          72 :       functions[start_func_index].code.offset() + start.GetColumnNumber();
     583             :   uint32_t end_func_index;
     584             :   uint32_t end_offset;
     585          72 :   if (end.IsEmpty()) {
     586             :     // Default: everything till the end of the Script.
     587           0 :     end_func_index = static_cast<uint32_t>(functions.size() - 1);
     588           0 :     end_offset = functions[end_func_index].code.end_offset();
     589             :   } else {
     590             :     // If end is specified: Use it and check for valid input.
     591          72 :     end_func_index = static_cast<uint32_t>(end.GetLineNumber());
     592             : 
     593             :     // Special case: Stop before the start of the next function. Change to: Stop
     594             :     // at the end of the function before, such that we don't disassemble the
     595             :     // next function also.
     596          72 :     if (end.GetColumnNumber() == 0 && end_func_index > 0) {
     597          32 :       --end_func_index;
     598          32 :       end_offset = functions[end_func_index].code.end_offset();
     599             :     } else {
     600          80 :       if (end_func_index >= functions.size()) return false;
     601             :       end_offset =
     602          40 :           functions[end_func_index].code.offset() + end.GetColumnNumber();
     603          40 :       if (end_offset > functions[end_func_index].code.end_offset())
     604             :         return false;
     605             :     }
     606             :   }
     607             : 
     608          72 :   AccountingAllocator alloc;
     609         144 :   Zone tmp(&alloc, ZONE_NAME);
     610          72 :   const byte* module_start = native_module()->wire_bytes().start();
     611             : 
     612         144 :   for (uint32_t func_idx = start_func_index; func_idx <= end_func_index;
     613             :        ++func_idx) {
     614          72 :     const WasmFunction& func = functions[func_idx];
     615         392 :     if (func.code.length() == 0) continue;
     616             : 
     617             :     wasm::BodyLocalDecls locals(&tmp);
     618             :     wasm::BytecodeIterator iterator(module_start + func.code.offset(),
     619             :                                     module_start + func.code.end_offset(),
     620          72 :                                     &locals);
     621             :     DCHECK_LT(0u, locals.encoded_size);
     622         684 :     for (uint32_t offset : iterator.offsets()) {
     623         320 :       uint32_t total_offset = func.code.offset() + offset;
     624         320 :       if (total_offset >= end_offset) {
     625             :         DCHECK_EQ(end_func_index, func_idx);
     626             :         break;
     627             :       }
     628         292 :       if (total_offset < start_offset) continue;
     629         152 :       locations->emplace_back(func_idx, offset, debug::kCommonBreakLocation);
     630             :     }
     631             :   }
     632          72 :   return true;
     633             : }
     634             : 
     635         556 : MaybeHandle<FixedArray> WasmModuleObject::CheckBreakPoints(
     636             :     Isolate* isolate, Handle<WasmModuleObject> module_object, int position) {
     637        1112 :   if (!module_object->has_breakpoint_infos()) return {};
     638             : 
     639             :   Handle<FixedArray> breakpoint_infos(module_object->breakpoint_infos(),
     640        1112 :                                       isolate);
     641             :   int insert_pos =
     642         556 :       FindBreakpointInfoInsertPos(isolate, breakpoint_infos, position);
     643         556 :   if (insert_pos >= breakpoint_infos->length()) return {};
     644             : 
     645             :   Handle<Object> maybe_breakpoint_info(breakpoint_infos->get(insert_pos),
     646             :                                        isolate);
     647        1112 :   if (maybe_breakpoint_info->IsUndefined(isolate)) return {};
     648             :   Handle<BreakPointInfo> breakpoint_info =
     649         324 :       Handle<BreakPointInfo>::cast(maybe_breakpoint_info);
     650         324 :   if (breakpoint_info->source_position() != position) return {};
     651             : 
     652             :   // There is no support for conditional break points. Just assume that every
     653             :   // break point always hits.
     654             :   Handle<Object> break_points(breakpoint_info->break_points(), isolate);
     655         424 :   if (break_points->IsFixedArray()) {
     656           0 :     return Handle<FixedArray>::cast(break_points);
     657             :   }
     658         212 :   Handle<FixedArray> break_points_hit = isolate->factory()->NewFixedArray(1);
     659         212 :   break_points_hit->set(0, *break_points);
     660         212 :   return break_points_hit;
     661             : }
     662             : 
     663      239330 : MaybeHandle<String> WasmModuleObject::ExtractUtf8StringFromModuleBytes(
     664             :     Isolate* isolate, Handle<WasmModuleObject> module_object,
     665             :     wasm::WireBytesRef ref) {
     666             :   // TODO(wasm): cache strings from modules if it's a performance win.
     667             :   Vector<const uint8_t> wire_bytes =
     668      478660 :       module_object->native_module()->wire_bytes();
     669      239330 :   return ExtractUtf8StringFromModuleBytes(isolate, wire_bytes, ref);
     670             : }
     671             : 
     672      255183 : MaybeHandle<String> WasmModuleObject::ExtractUtf8StringFromModuleBytes(
     673             :     Isolate* isolate, Vector<const uint8_t> wire_bytes,
     674             :     wasm::WireBytesRef ref) {
     675      494513 :   Vector<const uint8_t> name_vec = wire_bytes + ref.offset();
     676      255183 :   name_vec.Truncate(ref.length());
     677             :   // UTF8 validation happens at decode time.
     678             :   DCHECK(unibrow::Utf8::ValidateEncoding(name_vec.start(), name_vec.length()));
     679             :   return isolate->factory()->NewStringFromUtf8(
     680      494513 :       Vector<const char>::cast(name_vec));
     681             : }
     682             : 
     683         596 : MaybeHandle<String> WasmModuleObject::GetModuleNameOrNull(
     684             :     Isolate* isolate, Handle<WasmModuleObject> module_object) {
     685        1192 :   const WasmModule* module = module_object->module();
     686         596 :   if (!module->name.is_set()) return {};
     687          24 :   return ExtractUtf8StringFromModuleBytes(isolate, module_object, module->name);
     688             : }
     689             : 
     690        2336 : MaybeHandle<String> WasmModuleObject::GetFunctionNameOrNull(
     691             :     Isolate* isolate, Handle<WasmModuleObject> module_object,
     692             :     uint32_t func_index) {
     693             :   DCHECK_LT(func_index, module_object->module()->functions.size());
     694             :   wasm::WireBytesRef name = module_object->module()->LookupFunctionName(
     695             :       wasm::ModuleWireBytes(module_object->native_module()->wire_bytes()),
     696        7008 :       func_index);
     697        2336 :   if (!name.is_set()) return {};
     698        2280 :   return ExtractUtf8StringFromModuleBytes(isolate, module_object, name);
     699             : }
     700             : 
     701         832 : Handle<String> WasmModuleObject::GetFunctionName(
     702             :     Isolate* isolate, Handle<WasmModuleObject> module_object,
     703             :     uint32_t func_index) {
     704             :   MaybeHandle<String> name =
     705         832 :       GetFunctionNameOrNull(isolate, module_object, func_index);
     706         832 :   if (!name.is_null()) return name.ToHandleChecked();
     707             :   EmbeddedVector<char, 32> buffer;
     708           0 :   int length = SNPrintF(buffer, "wasm-function[%u]", func_index);
     709             :   return isolate->factory()
     710           0 :       ->NewStringFromOneByte(Vector<uint8_t>::cast(buffer.SubVector(0, length)))
     711           0 :       .ToHandleChecked();
     712             : }
     713             : 
     714          16 : Vector<const uint8_t> WasmModuleObject::GetRawFunctionName(
     715             :     uint32_t func_index) {
     716             :   DCHECK_GT(module()->functions.size(), func_index);
     717          16 :   wasm::ModuleWireBytes wire_bytes(native_module()->wire_bytes());
     718             :   wasm::WireBytesRef name_ref =
     719          16 :       module()->LookupFunctionName(wire_bytes, func_index);
     720          16 :   wasm::WasmName name = wire_bytes.GetNameOrNull(name_ref);
     721          16 :   return Vector<const uint8_t>::cast(name);
     722             : }
     723             : 
     724      152579 : int WasmModuleObject::GetFunctionOffset(uint32_t func_index) {
     725      152579 :   const std::vector<WasmFunction>& functions = module()->functions;
     726      305158 :   if (static_cast<uint32_t>(func_index) >= functions.size()) return -1;
     727             :   DCHECK_GE(kMaxInt, functions[func_index].code.offset());
     728      152579 :   return static_cast<int>(functions[func_index].code.offset());
     729             : }
     730             : 
     731         728 : int WasmModuleObject::GetContainingFunction(uint32_t byte_offset) {
     732         728 :   const std::vector<WasmFunction>& functions = module()->functions;
     733             : 
     734             :   // Binary search for a function containing the given position.
     735             :   int left = 0;                                    // inclusive
     736         728 :   int right = static_cast<int>(functions.size());  // exclusive
     737         728 :   if (right == 0) return false;
     738        1356 :   while (right - left > 1) {
     739         628 :     int mid = left + (right - left) / 2;
     740        1256 :     if (functions[mid].code.offset() <= byte_offset) {
     741             :       left = mid;
     742             :     } else {
     743             :       right = mid;
     744             :     }
     745             :   }
     746             :   // If the found function does not contains the given position, return -1.
     747         728 :   const WasmFunction& func = functions[left];
     748        1456 :   if (byte_offset < func.code.offset() ||
     749             :       byte_offset >= func.code.end_offset()) {
     750             :     return -1;
     751             :   }
     752             : 
     753         728 :   return left;
     754             : }
     755             : 
     756         740 : bool WasmModuleObject::GetPositionInfo(uint32_t position,
     757             :                                        Script::PositionInfo* info) {
     758        2220 :   if (script()->source_mapping_url()->IsString()) {
     759         248 :     if (module()->functions.size() == 0) return false;
     760         124 :     info->line = 0;
     761         124 :     info->column = position;
     762         124 :     info->line_start = module()->functions[0].code.offset();
     763         124 :     info->line_end = module()->functions.back().code.end_offset();
     764         124 :     return true;
     765             :   }
     766         616 :   int func_index = GetContainingFunction(position);
     767         616 :   if (func_index < 0) return false;
     768             : 
     769        1232 :   const WasmFunction& function = module()->functions[func_index];
     770             : 
     771         616 :   info->line = func_index;
     772         616 :   info->column = position - function.code.offset();
     773         616 :   info->line_start = function.code.offset();
     774         616 :   info->line_end = function.code.end_offset();
     775         616 :   return true;
     776             : }
     777             : 
     778        3281 : Handle<WasmTableObject> WasmTableObject::New(Isolate* isolate, uint32_t initial,
     779             :                                              uint32_t maximum,
     780             :                                              Handle<FixedArray>* js_functions) {
     781             :   Handle<JSFunction> table_ctor(
     782        9843 :       isolate->native_context()->wasm_table_constructor(), isolate);
     783             :   auto table_obj = Handle<WasmTableObject>::cast(
     784        3281 :       isolate->factory()->NewJSObject(table_ctor));
     785             : 
     786        3281 :   Handle<FixedArray> backing_store = isolate->factory()->NewFixedArray(initial);
     787        3281 :   Object null = ReadOnlyRoots(isolate).null_value();
     788       43770 :   for (int i = 0; i < static_cast<int>(initial); ++i) {
     789       40489 :     backing_store->set(i, null);
     790             :   }
     791        3281 :   table_obj->set_elements(*backing_store);
     792        3281 :   Handle<Object> max = isolate->factory()->NewNumberFromUint(maximum);
     793        3281 :   table_obj->set_maximum_length(*max);
     794             : 
     795        3281 :   table_obj->set_dispatch_tables(ReadOnlyRoots(isolate).empty_fixed_array());
     796        3281 :   if (js_functions != nullptr) {
     797        2024 :     *js_functions = backing_store;
     798             :   }
     799        3281 :   return Handle<WasmTableObject>::cast(table_obj);
     800             : }
     801             : 
     802        1392 : void WasmTableObject::AddDispatchTable(Isolate* isolate,
     803             :                                        Handle<WasmTableObject> table_obj,
     804             :                                        Handle<WasmInstanceObject> instance,
     805             :                                        int table_index) {
     806        2784 :   Handle<FixedArray> dispatch_tables(table_obj->dispatch_tables(), isolate);
     807             :   int old_length = dispatch_tables->length();
     808             :   DCHECK_EQ(0, old_length % kDispatchTableNumElements);
     809             : 
     810        2784 :   if (instance.is_null()) return;
     811             :   // TODO(titzer): use weak cells here to avoid leaking instances.
     812             : 
     813             :   // Grow the dispatch table and add a new entry at the end.
     814             :   Handle<FixedArray> new_dispatch_tables =
     815             :       isolate->factory()->CopyFixedArrayAndGrow(dispatch_tables,
     816        1392 :                                                 kDispatchTableNumElements);
     817             : 
     818             :   new_dispatch_tables->set(old_length + kDispatchTableInstanceOffset,
     819        2784 :                            *instance);
     820             :   new_dispatch_tables->set(old_length + kDispatchTableIndexOffset,
     821             :                            Smi::FromInt(table_index));
     822             : 
     823        1392 :   table_obj->set_dispatch_tables(*new_dispatch_tables);
     824             : }
     825             : 
     826         400 : void WasmTableObject::Grow(Isolate* isolate, uint32_t count) {
     827         800 :   if (count == 0) return;  // Degenerate case: nothing to do.
     828             : 
     829         400 :   Handle<FixedArray> dispatch_tables(this->dispatch_tables(), isolate);
     830             :   DCHECK_EQ(0, dispatch_tables->length() % kDispatchTableNumElements);
     831         800 :   uint32_t old_size = elements()->length();
     832             : 
     833             :   // Tables are stored in the instance object, no code patching is
     834             :   // necessary. We simply have to grow the raw tables in each instance
     835             :   // that has imported this table.
     836             : 
     837             :   // TODO(titzer): replace the dispatch table with a weak list of all
     838             :   // the instances that import a given table.
     839        2592 :   for (int i = 0; i < dispatch_tables->length();
     840             :        i += kDispatchTableNumElements) {
     841             :     Handle<WasmInstanceObject> instance(
     842             :         WasmInstanceObject::cast(dispatch_tables->get(i)), isolate);
     843             :     DCHECK_EQ(old_size, instance->indirect_function_table_size());
     844         896 :     uint32_t new_size = old_size + count;
     845             :     WasmInstanceObject::EnsureIndirectFunctionTableWithMinimumSize(instance,
     846         896 :                                                                    new_size);
     847             :   }
     848             : }
     849             : 
     850        3040 : void WasmTableObject::Set(Isolate* isolate, Handle<WasmTableObject> table,
     851             :                           uint32_t table_index, Handle<JSFunction> function) {
     852        6080 :   Handle<FixedArray> array(table->elements(), isolate);
     853        3040 :   if (function.is_null()) {
     854        1152 :     ClearDispatchTables(isolate, table, table_index);  // Degenerate case.
     855        2304 :     array->set(table_index, ReadOnlyRoots(isolate).null_value());
     856        3040 :     return;
     857             :   }
     858             : 
     859        1888 :   auto exported_function = Handle<WasmExportedFunction>::cast(function);
     860             :   Handle<WasmInstanceObject> target_instance(exported_function->instance(),
     861        3776 :                                              isolate);
     862        1888 :   int func_index = exported_function->function_index();
     863        5664 :   auto* wasm_function = &target_instance->module()->functions[func_index];
     864             :   DCHECK_NOT_NULL(wasm_function);
     865             :   DCHECK_NOT_NULL(wasm_function->sig);
     866             :   UpdateDispatchTables(isolate, table, table_index, wasm_function->sig,
     867             :                        handle(exported_function->instance(), isolate),
     868        3776 :                        func_index);
     869        3776 :   array->set(table_index, *function);
     870             : }
     871             : 
     872        3720 : void WasmTableObject::UpdateDispatchTables(
     873             :     Isolate* isolate, Handle<WasmTableObject> table, int table_index,
     874             :     wasm::FunctionSig* sig, Handle<WasmInstanceObject> target_instance,
     875             :     int target_func_index) {
     876             :   // We simply need to update the IFTs for each instance that imports
     877             :   // this table.
     878        7440 :   Handle<FixedArray> dispatch_tables(table->dispatch_tables(), isolate);
     879             :   DCHECK_EQ(0, dispatch_tables->length() % kDispatchTableNumElements);
     880             : 
     881       17424 :   for (int i = 0; i < dispatch_tables->length();
     882             :        i += kDispatchTableNumElements) {
     883             :     Handle<WasmInstanceObject> instance(
     884             :         WasmInstanceObject::cast(
     885             :             dispatch_tables->get(i + kDispatchTableInstanceOffset)),
     886             :         isolate);
     887             :     // Note that {SignatureMap::Find} may return {-1} if the signature is
     888             :     // not found; it will simply never match any check.
     889        4992 :     auto sig_id = instance->module()->signature_map.Find(*sig);
     890             :     IndirectFunctionTableEntry(instance, table_index)
     891        4992 :         .Set(sig_id, target_instance, target_func_index);
     892             :   }
     893        3720 : }
     894             : 
     895        1152 : void WasmTableObject::ClearDispatchTables(Isolate* isolate,
     896             :                                           Handle<WasmTableObject> table,
     897             :                                           int index) {
     898        2304 :   Handle<FixedArray> dispatch_tables(table->dispatch_tables(), isolate);
     899             :   DCHECK_EQ(0, dispatch_tables->length() % kDispatchTableNumElements);
     900        4064 :   for (int i = 0; i < dispatch_tables->length();
     901             :        i += kDispatchTableNumElements) {
     902             :     Handle<WasmInstanceObject> target_instance(
     903             :         WasmInstanceObject::cast(
     904             :             dispatch_tables->get(i + kDispatchTableInstanceOffset)),
     905             :         isolate);
     906             :     DCHECK_LT(index, target_instance->indirect_function_table_size());
     907         880 :     IndirectFunctionTableEntry(target_instance, index).clear();
     908             :   }
     909        1152 : }
     910             : 
     911             : namespace {
     912        2156 : MaybeHandle<JSArrayBuffer> MemoryGrowBuffer(Isolate* isolate,
     913             :                                             Handle<JSArrayBuffer> old_buffer,
     914             :                                             size_t new_size) {
     915        4312 :   CHECK_EQ(0, new_size % wasm::kWasmPageSize);
     916             :   size_t old_size = old_buffer->byte_length();
     917             :   void* old_mem_start = old_buffer->backing_store();
     918             :   // Reusing the backing store from externalized buffers causes problems with
     919             :   // Blink's array buffers. The connection between the two is lost, which can
     920             :   // lead to Blink not knowing about the other reference to the buffer and
     921             :   // freeing it too early.
     922        4304 :   if (old_buffer->is_external() || new_size > old_buffer->allocation_length()) {
     923             :     // We couldn't reuse the old backing store, so create a new one and copy the
     924             :     // old contents in.
     925             :     Handle<JSArrayBuffer> new_buffer;
     926          16 :     if (!wasm::NewArrayBuffer(isolate, new_size).ToHandle(&new_buffer)) {
     927           0 :       return {};
     928             :     }
     929             :     wasm::WasmMemoryTracker* const memory_tracker =
     930           8 :         isolate->wasm_engine()->memory_tracker();
     931             :     // If the old buffer had full guard regions, we can only safely use the new
     932             :     // buffer if it also has full guard regions. Otherwise, we'd have to
     933             :     // recompile all the instances using this memory to insert bounds checks.
     934          16 :     if (memory_tracker->HasFullGuardRegions(old_mem_start) &&
     935           8 :         !memory_tracker->HasFullGuardRegions(new_buffer->backing_store())) {
     936           0 :       return {};
     937             :     }
     938           8 :     if (old_size == 0) return new_buffer;
     939             :     memcpy(new_buffer->backing_store(), old_mem_start, old_size);
     940             :     DCHECK(old_buffer.is_null() || !old_buffer->is_shared());
     941             :     constexpr bool free_memory = true;
     942           8 :     i::wasm::DetachMemoryBuffer(isolate, old_buffer, free_memory);
     943           8 :     return new_buffer;
     944             :   } else {
     945        2148 :     if (old_size != new_size) {
     946             :       DCHECK_NOT_NULL(old_buffer->backing_store());
     947             :       // If adjusting permissions fails, propagate error back to return
     948             :       // failure to grow.
     949        1640 :       if (!i::SetPermissions(GetPlatformPageAllocator(), old_mem_start,
     950        1640 :                              new_size, PageAllocator::kReadWrite)) {
     951           0 :         return {};
     952             :       }
     953             :       DCHECK_GE(new_size, old_size);
     954             :       reinterpret_cast<v8::Isolate*>(isolate)
     955        1640 :           ->AdjustAmountOfExternalAllocatedMemory(new_size - old_size);
     956             :     }
     957             :     // NOTE: We must allocate a new array buffer here because the spec
     958             :     // assumes that ArrayBuffers do not change size.
     959             :     void* backing_store = old_buffer->backing_store();
     960             :     bool is_external = old_buffer->is_external();
     961             :     // Disconnect buffer early so GC won't free it.
     962        2148 :     i::wasm::DetachMemoryBuffer(isolate, old_buffer, false);
     963             :     Handle<JSArrayBuffer> new_buffer =
     964        2148 :         wasm::SetupArrayBuffer(isolate, backing_store, new_size, is_external);
     965        2148 :     return new_buffer;
     966             :   }
     967             : }
     968             : 
     969             : // May GC, because SetSpecializationMemInfoFrom may GC
     970       58768 : void SetInstanceMemory(Handle<WasmInstanceObject> instance,
     971             :                        Handle<JSArrayBuffer> buffer) {
     972             :   instance->SetRawMemory(reinterpret_cast<byte*>(buffer->backing_store()),
     973       58769 :                          buffer->byte_length());
     974             : #if DEBUG
     975             :   if (!FLAG_mock_arraybuffer_allocator) {
     976             :     // To flush out bugs earlier, in DEBUG mode, check that all pages of the
     977             :     // memory are accessible by reading and writing one byte on each page.
     978             :     // Don't do this if the mock ArrayBuffer allocator is enabled.
     979             :     byte* mem_start = instance->memory_start();
     980             :     size_t mem_size = instance->memory_size();
     981             :     for (size_t offset = 0; offset < mem_size; offset += wasm::kWasmPageSize) {
     982             :       byte val = mem_start[offset];
     983             :       USE(val);
     984             :       mem_start[offset] = val;
     985             :     }
     986             :   }
     987             : #endif
     988       58769 : }
     989             : 
     990             : }  // namespace
     991             : 
     992       54845 : Handle<WasmMemoryObject> WasmMemoryObject::New(
     993             :     Isolate* isolate, MaybeHandle<JSArrayBuffer> maybe_buffer,
     994             :     uint32_t maximum) {
     995             :   // TODO(kschimpf): Do we need to add an argument that defines the
     996             :   // style of memory the user prefers (with/without trap handling), so
     997             :   // that the memory will match the style of the compiled wasm module.
     998             :   // See issue v8:7143
     999             :   Handle<JSFunction> memory_ctor(
    1000      164535 :       isolate->native_context()->wasm_memory_constructor(), isolate);
    1001             :   auto memory_obj = Handle<WasmMemoryObject>::cast(
    1002       54845 :       isolate->factory()->NewJSObject(memory_ctor, TENURED));
    1003             : 
    1004             :   Handle<JSArrayBuffer> buffer;
    1005       54845 :   if (!maybe_buffer.ToHandle(&buffer)) {
    1006             :     // If no buffer was provided, create a 0-length one.
    1007          12 :     buffer = wasm::SetupArrayBuffer(isolate, nullptr, 0, false);
    1008             :   }
    1009       54845 :   memory_obj->set_array_buffer(*buffer);
    1010       54845 :   memory_obj->set_maximum_pages(maximum);
    1011             : 
    1012       54845 :   return memory_obj;
    1013             : }
    1014             : 
    1015        1206 : bool WasmMemoryObject::has_full_guard_region(Isolate* isolate) {
    1016             :   const wasm::WasmMemoryTracker::AllocationData* allocation =
    1017             :       isolate->wasm_engine()->memory_tracker()->FindAllocationData(
    1018        2412 :           array_buffer()->backing_store());
    1019        1206 :   CHECK_NOT_NULL(allocation);
    1020             : 
    1021             :   Address allocation_base =
    1022        1206 :       reinterpret_cast<Address>(allocation->allocation_base);
    1023        1206 :   Address buffer_start = reinterpret_cast<Address>(allocation->buffer_start);
    1024             : 
    1025             :   // Return whether the allocation covers every possible Wasm heap index.
    1026             :   //
    1027             :   // We always have the following relationship:
    1028             :   // allocation_base <= buffer_start <= buffer_start + memory_size <=
    1029             :   // allocation_base + allocation_length
    1030             :   // (in other words, the buffer fits within the allocation)
    1031             :   //
    1032             :   // The space between buffer_start + memory_size and allocation_base +
    1033             :   // allocation_length is the guard region. Here we make sure the guard region
    1034             :   // is large enough for any Wasm heap offset.
    1035        1206 :   return buffer_start + wasm::kWasmMaxHeapOffset <=
    1036        1206 :          allocation_base + allocation->allocation_length;
    1037             : }
    1038             : 
    1039       54540 : void WasmMemoryObject::AddInstance(Isolate* isolate,
    1040             :                                    Handle<WasmMemoryObject> memory,
    1041             :                                    Handle<WasmInstanceObject> instance) {
    1042             :   Handle<WeakArrayList> old_instances =
    1043      109081 :       memory->has_instances()
    1044             :           ? Handle<WeakArrayList>(memory->instances(), isolate)
    1045             :           : handle(ReadOnlyRoots(isolate->heap()).empty_weak_array_list(),
    1046      161046 :                    isolate);
    1047             :   Handle<WeakArrayList> new_instances = WeakArrayList::AddToEnd(
    1048       54541 :       isolate, old_instances, MaybeObjectHandle::Weak(instance));
    1049       54541 :   memory->set_instances(*new_instances);
    1050      109080 :   Handle<JSArrayBuffer> buffer(memory->array_buffer(), isolate);
    1051       54540 :   SetInstanceMemory(instance, buffer);
    1052       54541 : }
    1053             : 
    1054             : // static
    1055        2380 : int32_t WasmMemoryObject::Grow(Isolate* isolate,
    1056             :                                Handle<WasmMemoryObject> memory_object,
    1057             :                                uint32_t pages) {
    1058        4760 :   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.wasm"), "GrowMemory");
    1059        4760 :   Handle<JSArrayBuffer> old_buffer(memory_object->array_buffer(), isolate);
    1060             :   // TODO(gdeepti): Remove check for is_shared when Growing Shared memory
    1061             :   // is supported.
    1062        4760 :   if (!old_buffer->is_growable() || old_buffer->is_shared()) return -1;
    1063             : 
    1064             :   // Checks for maximum memory size, compute new size.
    1065        2380 :   uint32_t maximum_pages = wasm::max_mem_pages();
    1066        2380 :   if (memory_object->has_maximum_pages()) {
    1067             :     maximum_pages = std::min(
    1068        4456 :         maximum_pages, static_cast<uint32_t>(memory_object->maximum_pages()));
    1069             :   }
    1070        2380 :   CHECK_GE(wasm::max_mem_pages(), maximum_pages);
    1071             :   size_t old_size = old_buffer->byte_length();
    1072        4760 :   CHECK_EQ(0, old_size % wasm::kWasmPageSize);
    1073        2380 :   size_t old_pages = old_size / wasm::kWasmPageSize;
    1074        4760 :   CHECK_GE(wasm::max_mem_pages(), old_pages);
    1075        4536 :   if ((pages > maximum_pages - old_pages) ||          // exceeds remaining
    1076        2156 :       (pages > wasm::max_mem_pages() - old_pages)) {  // exceeds limit
    1077             :     return -1;
    1078             :   }
    1079             :   size_t new_size =
    1080        2156 :       static_cast<size_t>(old_pages + pages) * wasm::kWasmPageSize;
    1081             : 
    1082             :   // Grow the buffer.
    1083             :   Handle<JSArrayBuffer> new_buffer;
    1084        4312 :   if (!MemoryGrowBuffer(isolate, old_buffer, new_size).ToHandle(&new_buffer)) {
    1085             :     return -1;
    1086             :   }
    1087             : 
    1088             :   // Update instances if any.
    1089        4312 :   if (memory_object->has_instances()) {
    1090        3960 :     Handle<WeakArrayList> instances(memory_object->instances(), isolate);
    1091       12768 :     for (int i = 0; i < instances->length(); i++) {
    1092        4404 :       MaybeObject elem = instances->Get(i);
    1093        4404 :       HeapObject heap_object;
    1094        4404 :       if (elem->GetHeapObjectIfWeak(&heap_object)) {
    1095             :         Handle<WasmInstanceObject> instance(
    1096             :             WasmInstanceObject::cast(heap_object), isolate);
    1097        4228 :         SetInstanceMemory(instance, new_buffer);
    1098             :       } else {
    1099             :         DCHECK(elem->IsCleared());
    1100             :       }
    1101             :     }
    1102             :   }
    1103        2156 :   memory_object->set_array_buffer(*new_buffer);
    1104        2156 :   return static_cast<uint32_t>(old_size / wasm::kWasmPageSize);
    1105             : }
    1106             : 
    1107             : // static
    1108        7624 : MaybeHandle<WasmGlobalObject> WasmGlobalObject::New(
    1109             :     Isolate* isolate, MaybeHandle<JSArrayBuffer> maybe_untagged_buffer,
    1110             :     MaybeHandle<FixedArray> maybe_tagged_buffer, wasm::ValueType type,
    1111             :     int32_t offset, bool is_mutable) {
    1112             :   Handle<JSFunction> global_ctor(
    1113       22872 :       isolate->native_context()->wasm_global_constructor(), isolate);
    1114             :   auto global_obj = Handle<WasmGlobalObject>::cast(
    1115        7624 :       isolate->factory()->NewJSObject(global_ctor));
    1116             : 
    1117        7624 :   if (type == wasm::kWasmAnyRef) {
    1118             :     DCHECK(maybe_untagged_buffer.is_null());
    1119             :     Handle<FixedArray> tagged_buffer;
    1120         176 :     if (!maybe_tagged_buffer.ToHandle(&tagged_buffer)) {
    1121             :       // If no buffer was provided, create one.
    1122         112 :       tagged_buffer = isolate->factory()->NewFixedArray(1, TENURED);
    1123         112 :       CHECK_EQ(offset, 0);
    1124             :     }
    1125         176 :     global_obj->set_tagged_buffer(*tagged_buffer);
    1126             :   } else {
    1127             :     DCHECK(maybe_tagged_buffer.is_null());
    1128             :     Handle<JSArrayBuffer> untagged_buffer;
    1129        7448 :     uint32_t type_size = wasm::ValueTypes::ElementSizeInBytes(type);
    1130        7448 :     if (!maybe_untagged_buffer.ToHandle(&untagged_buffer)) {
    1131             :       // If no buffer was provided, create one long enough for the given type.
    1132             :       untagged_buffer =
    1133        6936 :           isolate->factory()->NewJSArrayBuffer(SharedFlag::kNotShared, TENURED);
    1134             : 
    1135             :       const bool initialize = true;
    1136        6936 :       if (!JSArrayBuffer::SetupAllocatingData(untagged_buffer, isolate,
    1137        6936 :                                               type_size, initialize)) {
    1138           0 :         return {};
    1139             :       }
    1140             :     }
    1141             : 
    1142             :     // Check that the offset is in bounds.
    1143       14896 :     CHECK_LE(offset + type_size, untagged_buffer->byte_length());
    1144             : 
    1145        7448 :     global_obj->set_untagged_buffer(*untagged_buffer);
    1146             :   }
    1147             :   global_obj->set_flags(0);
    1148       15248 :   global_obj->set_type(type);
    1149             :   global_obj->set_offset(offset);
    1150       15248 :   global_obj->set_is_mutable(is_mutable);
    1151             : 
    1152        7624 :   return global_obj;
    1153             : }
    1154             : 
    1155    20221113 : void IndirectFunctionTableEntry::clear() {
    1156    20221113 :   instance_->indirect_function_table_sig_ids()[index_] = -1;
    1157    20221113 :   instance_->indirect_function_table_targets()[index_] = 0;
    1158    40442226 :   instance_->indirect_function_table_refs()->set(
    1159    60663339 :       index_, ReadOnlyRoots(instance_->GetIsolate()).undefined_value());
    1160    20221113 : }
    1161             : 
    1162       17209 : void IndirectFunctionTableEntry::Set(int sig_id,
    1163             :                                      Handle<WasmInstanceObject> target_instance,
    1164             :                                      int target_func_index) {
    1165             :   TRACE_IFT(
    1166             :       "IFT entry %p[%d] = {sig_id=%d, target_instance=%p, "
    1167             :       "target_func_index=%d}\n",
    1168             :       reinterpret_cast<void*>(instance_->ptr()), index_, sig_id,
    1169             :       reinterpret_cast<void*>(target_instance->ptr()), target_func_index);
    1170             : 
    1171             :   Object ref;
    1172             :   Address call_target = 0;
    1173       34418 :   if (target_func_index <
    1174       34418 :       static_cast<int>(target_instance->module()->num_imported_functions)) {
    1175             :     // The function in the target instance was imported. Use its imports table,
    1176             :     // which contains a tuple needed by the import wrapper.
    1177             :     ImportedFunctionEntry entry(target_instance, target_func_index);
    1178         992 :     ref = entry.object_ref();
    1179         992 :     call_target = entry.target();
    1180             :   } else {
    1181             :     // The function in the target instance was not imported.
    1182       16217 :     ref = *target_instance;
    1183       32434 :     call_target = target_instance->GetCallTarget(target_func_index);
    1184             :   }
    1185             : 
    1186             :   // Set the signature id, the target, and the receiver ref.
    1187       17209 :   instance_->indirect_function_table_sig_ids()[index_] = sig_id;
    1188       17209 :   instance_->indirect_function_table_targets()[index_] = call_target;
    1189       34418 :   instance_->indirect_function_table_refs()->set(index_, ref);
    1190       17209 : }
    1191             : 
    1192          64 : Object IndirectFunctionTableEntry::object_ref() {
    1193         192 :   return instance_->indirect_function_table_refs()->get(index_);
    1194             : }
    1195             : 
    1196          88 : int IndirectFunctionTableEntry::sig_id() {
    1197          88 :   return instance_->indirect_function_table_sig_ids()[index_];
    1198             : }
    1199             : 
    1200          64 : Address IndirectFunctionTableEntry::target() {
    1201          64 :   return instance_->indirect_function_table_targets()[index_];
    1202             : }
    1203             : 
    1204         336 : void IndirectFunctionTableEntry::CopyFrom(
    1205             :     const IndirectFunctionTableEntry& that) {
    1206         336 :   instance_->indirect_function_table_sig_ids()[index_] =
    1207         336 :       that.instance_->indirect_function_table_sig_ids()[that.index_];
    1208         336 :   instance_->indirect_function_table_targets()[index_] =
    1209         336 :       that.instance_->indirect_function_table_targets()[that.index_];
    1210         672 :   instance_->indirect_function_table_refs()->set(
    1211        1680 :       index_, that.instance_->indirect_function_table_refs()->get(that.index_));
    1212         336 : }
    1213             : 
    1214       12065 : void ImportedFunctionEntry::SetWasmToJs(
    1215             :     Isolate* isolate, Handle<JSReceiver> callable,
    1216             :     const wasm::WasmCode* wasm_to_js_wrapper) {
    1217             :   TRACE_IFT("Import callable %p[%d] = {callable=%p, target=%p}\n",
    1218             :             reinterpret_cast<void*>(instance_->ptr()), index_,
    1219             :             reinterpret_cast<void*>(callable->ptr()),
    1220             :             wasm_to_js_wrapper->instructions().start());
    1221             :   DCHECK_EQ(wasm::WasmCode::kWasmToJsWrapper, wasm_to_js_wrapper->kind());
    1222             :   Handle<Tuple2> tuple =
    1223       12065 :       isolate->factory()->NewTuple2(instance_, callable, TENURED);
    1224       24130 :   instance_->imported_function_refs()->set(index_, *tuple);
    1225       12065 :   instance_->imported_function_targets()[index_] =
    1226       12065 :       wasm_to_js_wrapper->instruction_start();
    1227       12065 : }
    1228             : 
    1229      107352 : void ImportedFunctionEntry::SetWasmToWasm(WasmInstanceObject instance,
    1230             :                                           Address call_target) {
    1231             :   TRACE_IFT("Import WASM %p[%d] = {instance=%p, target=%" PRIuPTR "}\n",
    1232             :             reinterpret_cast<void*>(instance_->ptr()), index_,
    1233             :             reinterpret_cast<void*>(instance->ptr()), call_target);
    1234      214704 :   instance_->imported_function_refs()->set(index_, instance);
    1235      107352 :   instance_->imported_function_targets()[index_] = call_target;
    1236      107352 : }
    1237             : 
    1238           0 : WasmInstanceObject ImportedFunctionEntry::instance() {
    1239             :   // The imported reference entry is either a target instance or a tuple
    1240             :   // of this instance and the target callable.
    1241           0 :   Object value = instance_->imported_function_refs()->get(index_);
    1242           0 :   if (value->IsWasmInstanceObject()) {
    1243             :     return WasmInstanceObject::cast(value);
    1244             :   }
    1245             :   Tuple2 tuple = Tuple2::cast(value);
    1246             :   return WasmInstanceObject::cast(tuple->value1());
    1247             : }
    1248             : 
    1249           0 : JSReceiver ImportedFunctionEntry::callable() {
    1250           0 :   return JSReceiver::cast(Tuple2::cast(object_ref())->value2());
    1251             : }
    1252             : 
    1253        7624 : Object ImportedFunctionEntry::object_ref() {
    1254       22872 :   return instance_->imported_function_refs()->get(index_);
    1255             : }
    1256             : 
    1257        7624 : Address ImportedFunctionEntry::target() {
    1258        7624 :   return instance_->imported_function_targets()[index_];
    1259             : }
    1260             : 
    1261        4693 : bool WasmInstanceObject::EnsureIndirectFunctionTableWithMinimumSize(
    1262             :     Handle<WasmInstanceObject> instance, uint32_t minimum_size) {
    1263             :   uint32_t old_size = instance->indirect_function_table_size();
    1264        4693 :   if (old_size >= minimum_size) return false;  // Nothing to do.
    1265             : 
    1266             :   Isolate* isolate = instance->GetIsolate();
    1267             :   HandleScope scope(isolate);
    1268        3049 :   auto native_allocations = GetNativeAllocations(*instance);
    1269             :   native_allocations->resize_indirect_function_table(isolate, instance,
    1270        3049 :                                                      minimum_size);
    1271             :   return true;
    1272             : }
    1273             : 
    1274     1329053 : void WasmInstanceObject::SetRawMemory(byte* mem_start, size_t mem_size) {
    1275     1329053 :   CHECK_LE(mem_size, wasm::max_mem_bytes());
    1276             : #if V8_HOST_ARCH_64_BIT
    1277     1329053 :   uint64_t mem_mask64 = base::bits::RoundUpToPowerOfTwo64(mem_size) - 1;
    1278             :   set_memory_start(mem_start);
    1279             :   set_memory_size(mem_size);
    1280             :   set_memory_mask(mem_mask64);
    1281             : #else
    1282             :   // Must handle memory > 2GiB specially.
    1283             :   CHECK_LE(mem_size, size_t{kMaxUInt32});
    1284             :   uint32_t mem_mask32 =
    1285             :       (mem_size > 2 * size_t{GB})
    1286             :           ? 0xFFFFFFFFu
    1287             :           : base::bits::RoundUpToPowerOfTwo32(static_cast<uint32_t>(mem_size)) -
    1288             :                 1;
    1289             :   set_memory_start(mem_start);
    1290             :   set_memory_size(mem_size);
    1291             :   set_memory_mask(mem_mask32);
    1292             : #endif
    1293     1329054 : }
    1294             : 
    1295      503724 : const WasmModule* WasmInstanceObject::module() {
    1296     1007448 :   return module_object()->module();
    1297             : }
    1298             : 
    1299       34496 : Handle<WasmDebugInfo> WasmInstanceObject::GetOrCreateDebugInfo(
    1300             :     Handle<WasmInstanceObject> instance) {
    1301       68992 :   if (instance->has_debug_info()) {
    1302       67088 :     return handle(instance->debug_info(), instance->GetIsolate());
    1303             :   }
    1304         952 :   Handle<WasmDebugInfo> new_info = WasmDebugInfo::New(instance);
    1305             :   DCHECK(instance->has_debug_info());
    1306         952 :   return new_info;
    1307             : }
    1308             : 
    1309     1229053 : Handle<WasmInstanceObject> WasmInstanceObject::New(
    1310             :     Isolate* isolate, Handle<WasmModuleObject> module_object) {
    1311             :   Handle<JSFunction> instance_cons(
    1312     3687159 :       isolate->native_context()->wasm_instance_constructor(), isolate);
    1313             :   Handle<JSObject> instance_object =
    1314     1229053 :       isolate->factory()->NewJSObject(instance_cons, TENURED);
    1315             : 
    1316             :   Handle<WasmInstanceObject> instance(
    1317             :       WasmInstanceObject::cast(*instance_object), isolate);
    1318     2458106 :   instance->clear_padding();
    1319             : 
    1320             :   // Initialize the imported function arrays.
    1321     2458106 :   auto module = module_object->module();
    1322     1229053 :   auto num_imported_functions = module->num_imported_functions;
    1323     1229053 :   auto num_imported_mutable_globals = module->num_imported_mutable_globals;
    1324     1229053 :   auto num_data_segments = module->num_declared_data_segments;
    1325     1229053 :   size_t native_allocations_size = EstimateNativeAllocationsSize(module);
    1326             :   auto native_allocations = Managed<WasmInstanceNativeAllocations>::Allocate(
    1327             :       isolate, native_allocations_size, instance, num_imported_functions,
    1328             :       num_imported_mutable_globals, num_data_segments,
    1329     2458106 :       module->elem_segments.size());
    1330     2458106 :   instance->set_managed_native_allocations(*native_allocations);
    1331             : 
    1332             :   Handle<FixedArray> imported_function_refs =
    1333     1229053 :       isolate->factory()->NewFixedArray(num_imported_functions);
    1334     1229053 :   instance->set_imported_function_refs(*imported_function_refs);
    1335             : 
    1336     1229053 :   Handle<Code> centry_stub = CodeFactory::CEntry(isolate);
    1337     1229053 :   instance->set_centry_stub(*centry_stub);
    1338             : 
    1339     1229053 :   instance->SetRawMemory(nullptr, 0);
    1340             :   instance->set_isolate_root(isolate->isolate_root());
    1341             :   instance->set_stack_limit_address(
    1342             :       isolate->stack_guard()->address_of_jslimit());
    1343             :   instance->set_real_stack_limit_address(
    1344             :       isolate->stack_guard()->address_of_real_jslimit());
    1345             :   instance->set_globals_start(nullptr);
    1346             :   instance->set_indirect_function_table_size(0);
    1347             :   instance->set_indirect_function_table_sig_ids(nullptr);
    1348             :   instance->set_indirect_function_table_targets(nullptr);
    1349     3687159 :   instance->set_native_context(*isolate->native_context());
    1350     1229053 :   instance->set_module_object(*module_object);
    1351     1229053 :   instance->set_undefined_value(ReadOnlyRoots(isolate).undefined_value());
    1352     1229053 :   instance->set_null_value(ReadOnlyRoots(isolate).null_value());
    1353             :   instance->set_jump_table_start(
    1354     2458106 :       module_object->native_module()->jump_table_start());
    1355             : 
    1356             :   // Insert the new instance into the modules weak list of instances.
    1357             :   // TODO(mstarzinger): Allow to reuse holes in the {WeakArrayList} below.
    1358             :   Handle<WeakArrayList> weak_instance_list(module_object->weak_instance_list(),
    1359     2458106 :                                            isolate);
    1360             :   weak_instance_list = WeakArrayList::AddToEnd(
    1361     1229053 :       isolate, weak_instance_list, MaybeObjectHandle::Weak(instance));
    1362     1229053 :   module_object->set_weak_instance_list(*weak_instance_list);
    1363             : 
    1364     1229053 :   InitDataSegmentArrays(instance, module_object);
    1365     1229053 :   InitElemSegmentArrays(instance, module_object);
    1366             : 
    1367     1229052 :   return instance;
    1368             : }
    1369             : 
    1370             : // static
    1371     1229052 : void WasmInstanceObject::InitDataSegmentArrays(
    1372             :     Handle<WasmInstanceObject> instance,
    1373             :     Handle<WasmModuleObject> module_object) {
    1374     2458105 :   auto module = module_object->module();
    1375     2458106 :   auto wire_bytes = module_object->native_module()->wire_bytes();
    1376     1229053 :   auto num_data_segments = module->num_declared_data_segments;
    1377             :   // The number of declared data segments will be zero if there is no DataCount
    1378             :   // section. These arrays will not be allocated nor initialized in that case,
    1379             :   // since they cannot be used (since the validator checks that number of
    1380             :   // declared data segments when validating the memory.init and memory.drop
    1381             :   // instructions).
    1382             :   DCHECK(num_data_segments == 0 ||
    1383             :          num_data_segments == module->data_segments.size());
    1384     1229125 :   for (size_t i = 0; i < num_data_segments; ++i) {
    1385          72 :     const wasm::WasmDataSegment& segment = module->data_segments[i];
    1386             :     // Set the active segments to being already dropped, since memory.init on
    1387             :     // a dropped passive segment and an active segment have the same
    1388             :     // behavior.
    1389          72 :     instance->dropped_data_segments()[i] = segment.active ? 1 : 0;
    1390             : 
    1391             :     // Initialize the pointer and size of passive segments.
    1392          72 :     instance->data_segment_starts()[i] =
    1393         216 :         reinterpret_cast<Address>(&wire_bytes[segment.source.offset()]);
    1394         144 :     instance->data_segment_sizes()[i] = segment.source.length();
    1395             :   }
    1396     1229053 : }
    1397             : 
    1398     1229053 : void WasmInstanceObject::InitElemSegmentArrays(
    1399             :     Handle<WasmInstanceObject> instance,
    1400             :     Handle<WasmModuleObject> module_object) {
    1401     2458105 :   auto module = module_object->module();
    1402     1231053 :   auto num_elem_segments = module->elem_segments.size();
    1403     1231053 :   for (size_t i = 0; i < num_elem_segments; ++i) {
    1404             :     const wasm::WasmElemSegment& segment = module->elem_segments[i];
    1405             :     // Set the active segments to being already dropped, since table.init on
    1406             :     // a dropped passive segment and an active segment have the same
    1407             :     // behavior.
    1408        2001 :     instance->dropped_elem_segments()[i] = segment.active ? 1 : 0;
    1409             :   }
    1410     1229052 : }
    1411             : 
    1412      123345 : Address WasmInstanceObject::GetCallTarget(uint32_t func_index) {
    1413      123345 :   wasm::NativeModule* native_module = module_object()->native_module();
    1414      123345 :   if (func_index < native_module->num_imported_functions()) {
    1415          32 :     return imported_function_targets()[func_index];
    1416             :   }
    1417      123313 :   return native_module->GetCallTargetForFunction(func_index);
    1418             : }
    1419             : 
    1420             : namespace {
    1421         168 : void CopyTableEntriesImpl(Handle<WasmInstanceObject> instance, uint32_t dst,
    1422             :                           uint32_t src, uint32_t count) {
    1423             :   DCHECK(IsInBounds(dst, count, instance->indirect_function_table_size()));
    1424         168 :   if (src < dst) {
    1425         160 :     for (uint32_t i = count; i > 0; i--) {
    1426         160 :       auto to_entry = IndirectFunctionTableEntry(instance, dst + i - 1);
    1427         160 :       auto from_entry = IndirectFunctionTableEntry(instance, src + i - 1);
    1428         160 :       to_entry.CopyFrom(from_entry);
    1429             :     }
    1430             :   } else {
    1431         176 :     for (uint32_t i = 0; i < count; i++) {
    1432         176 :       auto to_entry = IndirectFunctionTableEntry(instance, dst + i);
    1433         176 :       auto from_entry = IndirectFunctionTableEntry(instance, src + i);
    1434         176 :       to_entry.CopyFrom(from_entry);
    1435             :     }
    1436             :   }
    1437         168 : }
    1438             : }  // namespace
    1439             : 
    1440             : // static
    1441        1504 : bool WasmInstanceObject::CopyTableEntries(Isolate* isolate,
    1442             :                                           Handle<WasmInstanceObject> instance,
    1443             :                                           uint32_t table_src_index,
    1444             :                                           uint32_t table_dst_index,
    1445             :                                           uint32_t dst, uint32_t src,
    1446             :                                           uint32_t count) {
    1447             :   // TODO(titzer): multiple tables in TableCopy
    1448        1504 :   CHECK_EQ(0, table_src_index);
    1449        1504 :   CHECK_EQ(0, table_dst_index);
    1450             :   auto max = instance->indirect_function_table_size();
    1451        3008 :   if (!IsInBounds(dst, count, max)) return false;
    1452        1296 :   if (!IsInBounds(src, count, max)) return false;
    1453         216 :   if (dst == src) return true;  // no-op
    1454             : 
    1455         288 :   if (!instance->has_table_object()) {
    1456             :     // No table object, only need to update this instance.
    1457          88 :     CopyTableEntriesImpl(instance, dst, src, count);
    1458          88 :     return true;
    1459             :   }
    1460             : 
    1461             :   Handle<WasmTableObject> table =
    1462         112 :       Handle<WasmTableObject>(instance->table_object(), isolate);
    1463             :   // Broadcast table copy operation to all instances that import this table.
    1464         112 :   Handle<FixedArray> dispatch_tables(table->dispatch_tables(), isolate);
    1465         272 :   for (int i = 0; i < dispatch_tables->length();
    1466             :        i += kDispatchTableNumElements) {
    1467             :     Handle<WasmInstanceObject> target_instance(
    1468             :         WasmInstanceObject::cast(
    1469             :             dispatch_tables->get(i + kDispatchTableInstanceOffset)),
    1470             :         isolate);
    1471          80 :     CopyTableEntriesImpl(target_instance, dst, src, count);
    1472             :   }
    1473             : 
    1474             :   // Copy the function entries.
    1475         112 :   Handle<FixedArray> functions(table->elements(), isolate);
    1476          56 :   if (src < dst) {
    1477          48 :     for (uint32_t i = count; i > 0; i--) {
    1478         144 :       functions->set(dst + i - 1, functions->get(src + i - 1));
    1479             :     }
    1480             :   } else {
    1481          48 :     for (uint32_t i = 0; i < count; i++) {
    1482         144 :       functions->set(dst + i, functions->get(src + i));
    1483             :     }
    1484             :   }
    1485             :   return true;
    1486             : }
    1487             : 
    1488             : // static
    1489         184 : bool WasmInstanceObject::InitTableEntries(Isolate* isolate,
    1490             :                                           Handle<WasmInstanceObject> instance,
    1491             :                                           uint32_t table_index,
    1492             :                                           uint32_t segment_index, uint32_t dst,
    1493             :                                           uint32_t src, uint32_t count) {
    1494             :   // Note that this implementation just calls through to module instantiation.
    1495             :   // This is intentional, so that the runtime only depends on the object
    1496             :   // methods, and not the module instantiation logic.
    1497             :   return wasm::LoadElemSegment(isolate, instance, table_index, segment_index,
    1498         184 :                                dst, src, count);
    1499             : }
    1500             : 
    1501      227319 : MaybeHandle<WasmExportedFunction> WasmInstanceObject::GetWasmExportedFunction(
    1502             :     Isolate* isolate, Handle<WasmInstanceObject> instance, int index) {
    1503             :   MaybeHandle<WasmExportedFunction> result;
    1504      454640 :   if (instance->has_wasm_exported_functions()) {
    1505      410008 :     Object val = instance->wasm_exported_functions()->get(index);
    1506      205004 :     if (!val->IsUndefined(isolate)) {
    1507             :       result = Handle<WasmExportedFunction>(WasmExportedFunction::cast(val),
    1508             :                                             isolate);
    1509             :     }
    1510             :   }
    1511      227320 :   return result;
    1512             : }
    1513             : 
    1514      333625 : void WasmInstanceObject::SetWasmExportedFunction(
    1515             :     Isolate* isolate, Handle<WasmInstanceObject> instance, int index,
    1516             :     Handle<WasmExportedFunction> val) {
    1517             :   Handle<FixedArray> functions;
    1518      667253 :   if (!instance->has_wasm_exported_functions()) {
    1519             :     // lazily-allocate the wasm exported functions.
    1520             :     functions = isolate->factory()->NewFixedArray(
    1521      258504 :         static_cast<int>(instance->module()->functions.size()));
    1522      129252 :     instance->set_wasm_exported_functions(*functions);
    1523             :   } else {
    1524             :     functions =
    1525      408752 :         Handle<FixedArray>(instance->wasm_exported_functions(), isolate);
    1526             :   }
    1527      667256 :   functions->set(index, *val);
    1528      333627 : }
    1529             : 
    1530             : // static
    1531          96 : Handle<WasmExceptionObject> WasmExceptionObject::New(
    1532          96 :     Isolate* isolate, const wasm::FunctionSig* sig,
    1533             :     Handle<HeapObject> exception_tag) {
    1534             :   Handle<JSFunction> exception_cons(
    1535         288 :       isolate->native_context()->wasm_exception_constructor(), isolate);
    1536             :   Handle<JSObject> exception_object =
    1537          96 :       isolate->factory()->NewJSObject(exception_cons, TENURED);
    1538             :   Handle<WasmExceptionObject> exception =
    1539          96 :       Handle<WasmExceptionObject>::cast(exception_object);
    1540             : 
    1541             :   // Serialize the signature.
    1542             :   DCHECK_EQ(0, sig->return_count());
    1543             :   DCHECK_LE(sig->parameter_count(), std::numeric_limits<int>::max());
    1544          96 :   int sig_size = static_cast<int>(sig->parameter_count());
    1545             :   Handle<PodArray<wasm::ValueType>> serialized_sig =
    1546             :       PodArray<wasm::ValueType>::New(isolate, sig_size, TENURED);
    1547             :   int index = 0;  // Index into the {PodArray} above.
    1548         104 :   for (wasm::ValueType param : sig->parameters()) {
    1549           8 :     serialized_sig->set(index++, param);
    1550             :   }
    1551          96 :   exception->set_serialized_signature(*serialized_sig);
    1552          96 :   exception->set_exception_tag(*exception_tag);
    1553             : 
    1554          96 :   return exception;
    1555             : }
    1556             : 
    1557          56 : bool WasmExceptionObject::IsSignatureEqual(const wasm::FunctionSig* sig) {
    1558             :   DCHECK_EQ(0, sig->return_count());
    1559             :   DCHECK_LE(sig->parameter_count(), std::numeric_limits<int>::max());
    1560          56 :   int sig_size = static_cast<int>(sig->parameter_count());
    1561         112 :   if (sig_size != serialized_signature()->length()) return false;
    1562           0 :   for (int index = 0; index < sig_size; ++index) {
    1563           0 :     if (sig->GetParam(index) != serialized_signature()->get(index)) {
    1564             :       return false;
    1565             :     }
    1566             :   }
    1567             :   return true;
    1568             : }
    1569             : 
    1570             : // static
    1571          12 : Handle<JSReceiver> WasmExceptionPackage::New(
    1572             :     Isolate* isolate, Handle<WasmExceptionTag> exception_tag, int size) {
    1573             :   Handle<Object> exception = isolate->factory()->NewWasmRuntimeError(
    1574          12 :       MessageTemplate::kWasmExceptionError);
    1575          24 :   CHECK(!Object::SetProperty(isolate, exception,
    1576             :                              isolate->factory()->wasm_exception_tag_symbol(),
    1577             :                              exception_tag, StoreOrigin::kMaybeKeyed,
    1578             :                              Just(ShouldThrow::kThrowOnError))
    1579             :              .is_null());
    1580          12 :   Handle<FixedArray> values = isolate->factory()->NewFixedArray(size);
    1581          24 :   CHECK(!Object::SetProperty(isolate, exception,
    1582             :                              isolate->factory()->wasm_exception_values_symbol(),
    1583             :                              values, StoreOrigin::kMaybeKeyed,
    1584             :                              Just(ShouldThrow::kThrowOnError))
    1585             :              .is_null());
    1586          12 :   return Handle<JSReceiver>::cast(exception);
    1587             : }
    1588             : 
    1589             : // static
    1590         680 : Handle<Object> WasmExceptionPackage::GetExceptionTag(
    1591             :     Isolate* isolate, Handle<Object> exception_object) {
    1592        1360 :   if (exception_object->IsJSReceiver()) {
    1593         632 :     Handle<JSReceiver> exception = Handle<JSReceiver>::cast(exception_object);
    1594             :     Handle<Object> tag;
    1595         632 :     if (JSReceiver::GetProperty(isolate, exception,
    1596         632 :                                 isolate->factory()->wasm_exception_tag_symbol())
    1597        1264 :             .ToHandle(&tag)) {
    1598         632 :       return tag;
    1599             :     }
    1600             :   }
    1601          48 :   return ReadOnlyRoots(isolate).undefined_value_handle();
    1602             : }
    1603             : 
    1604             : // static
    1605        1236 : Handle<Object> WasmExceptionPackage::GetExceptionValues(
    1606             :     Isolate* isolate, Handle<Object> exception_object) {
    1607        2472 :   if (exception_object->IsJSReceiver()) {
    1608        1236 :     Handle<JSReceiver> exception = Handle<JSReceiver>::cast(exception_object);
    1609             :     Handle<Object> values;
    1610        1236 :     if (JSReceiver::GetProperty(
    1611             :             isolate, exception,
    1612        1236 :             isolate->factory()->wasm_exception_values_symbol())
    1613        2472 :             .ToHandle(&values)) {
    1614             :       DCHECK(values->IsFixedArray());
    1615        1236 :       return values;
    1616             :     }
    1617             :   }
    1618           0 :   return ReadOnlyRoots(isolate).undefined_value_handle();
    1619             : }
    1620             : 
    1621             : #ifdef DEBUG
    1622             : 
    1623             : namespace {
    1624             : 
    1625             : constexpr uint32_t kBytesPerExceptionValuesArrayElement = 2;
    1626             : 
    1627             : size_t ComputeEncodedElementSize(wasm::ValueType type) {
    1628             :   size_t byte_size =
    1629             :       static_cast<size_t>(wasm::ValueTypes::ElementSizeInBytes(type));
    1630             :   DCHECK_EQ(byte_size % kBytesPerExceptionValuesArrayElement, 0);
    1631             :   DCHECK_LE(1, byte_size / kBytesPerExceptionValuesArrayElement);
    1632             :   return byte_size / kBytesPerExceptionValuesArrayElement;
    1633             : }
    1634             : 
    1635             : }  // namespace
    1636             : 
    1637             : #endif  // DEBUG
    1638             : 
    1639             : // static
    1640         515 : uint32_t WasmExceptionPackage::GetEncodedSize(
    1641             :     const wasm::WasmException* exception) {
    1642        1558 :   const wasm::WasmExceptionSig* sig = exception->sig;
    1643             :   uint32_t encoded_size = 0;
    1644        1558 :   for (size_t i = 0; i < sig->parameter_count(); ++i) {
    1645         264 :     switch (sig->GetParam(i)) {
    1646             :       case wasm::kWasmI32:
    1647             :       case wasm::kWasmF32:
    1648             :         DCHECK_EQ(2, ComputeEncodedElementSize(sig->GetParam(i)));
    1649         184 :         encoded_size += 2;
    1650         184 :         break;
    1651             :       case wasm::kWasmI64:
    1652             :       case wasm::kWasmF64:
    1653             :         DCHECK_EQ(4, ComputeEncodedElementSize(sig->GetParam(i)));
    1654          32 :         encoded_size += 4;
    1655          32 :         break;
    1656             :       case wasm::kWasmS128:
    1657             :         DCHECK_EQ(8, ComputeEncodedElementSize(sig->GetParam(i)));
    1658          16 :         encoded_size += 8;
    1659          16 :         break;
    1660             :       case wasm::kWasmAnyRef:
    1661          32 :         encoded_size += 1;
    1662          32 :         break;
    1663             :       default:
    1664           0 :         UNREACHABLE();
    1665             :     }
    1666             :   }
    1667         515 :   return encoded_size;
    1668             : }
    1669             : 
    1670      242074 : bool WasmExportedFunction::IsWasmExportedFunction(Object object) {
    1671      242074 :   if (!object->IsJSFunction()) return false;
    1672      238410 :   JSFunction js_function = JSFunction::cast(object);
    1673      476820 :   if (Code::JS_TO_WASM_FUNCTION != js_function->code()->kind()) return false;
    1674             :   DCHECK(js_function->shared()->HasWasmExportedFunctionData());
    1675      219400 :   return true;
    1676             : }
    1677             : 
    1678      331032 : WasmInstanceObject WasmExportedFunction::instance() {
    1679      331032 :   return shared()->wasm_exported_function_data()->instance();
    1680             : }
    1681             : 
    1682      222017 : int WasmExportedFunction::function_index() {
    1683      444034 :   return shared()->wasm_exported_function_data()->function_index();
    1684             : }
    1685             : 
    1686      235783 : Handle<WasmExportedFunction> WasmExportedFunction::New(
    1687             :     Isolate* isolate, Handle<WasmInstanceObject> instance,
    1688             :     MaybeHandle<String> maybe_name, int func_index, int arity,
    1689             :     Handle<Code> export_wrapper) {
    1690             :   DCHECK_EQ(Code::JS_TO_WASM_FUNCTION, export_wrapper->kind());
    1691      235783 :   int num_imported_functions = instance->module()->num_imported_functions;
    1692             :   int jump_table_offset = -1;
    1693      235783 :   if (func_index >= num_imported_functions) {
    1694             :     ptrdiff_t jump_table_diff =
    1695      470766 :         instance->module_object()->native_module()->jump_table_offset(
    1696      706149 :             func_index);
    1697             :     DCHECK(jump_table_diff >= 0 && jump_table_diff <= INT_MAX);
    1698      235383 :     jump_table_offset = static_cast<int>(jump_table_diff);
    1699             :   }
    1700             :   Handle<WasmExportedFunctionData> function_data =
    1701             :       Handle<WasmExportedFunctionData>::cast(isolate->factory()->NewStruct(
    1702      235783 :           WASM_EXPORTED_FUNCTION_DATA_TYPE, TENURED));
    1703      235782 :   function_data->set_wrapper_code(*export_wrapper);
    1704      235783 :   function_data->set_instance(*instance);
    1705             :   function_data->set_jump_table_offset(jump_table_offset);
    1706             :   function_data->set_function_index(func_index);
    1707             :   Handle<String> name;
    1708      235783 :   if (!maybe_name.ToHandle(&name)) {
    1709             :     EmbeddedVector<char, 16> buffer;
    1710      227613 :     int length = SNPrintF(buffer, "%d", func_index);
    1711             :     name = isolate->factory()
    1712             :                ->NewStringFromOneByte(
    1713      227613 :                    Vector<uint8_t>::cast(buffer.SubVector(0, length)))
    1714      455226 :                .ToHandleChecked();
    1715             :   }
    1716             :   NewFunctionArgs args = NewFunctionArgs::ForWasm(
    1717      235783 :       name, function_data, isolate->sloppy_function_without_prototype_map());
    1718      235783 :   Handle<JSFunction> js_function = isolate->factory()->NewFunction(args);
    1719             :   // According to the spec, exported functions should not have a [[Construct]]
    1720             :   // method.
    1721             :   DCHECK(!js_function->IsConstructor());
    1722      471562 :   js_function->shared()->set_length(arity);
    1723      471565 :   js_function->shared()->set_internal_formal_parameter_count(arity);
    1724      235783 :   return Handle<WasmExportedFunction>::cast(js_function);
    1725             : }
    1726             : 
    1727      107128 : Address WasmExportedFunction::GetWasmCallTarget() {
    1728      107128 :   return instance()->GetCallTarget(function_index());
    1729             : }
    1730             : 
    1731        2800 : wasm::FunctionSig* WasmExportedFunction::sig() {
    1732        5600 :   return instance()->module()->functions[function_index()].sig;
    1733             : }
    1734             : 
    1735         412 : Handle<WasmExceptionTag> WasmExceptionTag::New(Isolate* isolate, int index) {
    1736             :   Handle<WasmExceptionTag> result = Handle<WasmExceptionTag>::cast(
    1737         412 :       isolate->factory()->NewStruct(WASM_EXCEPTION_TAG_TYPE, TENURED));
    1738             :   result->set_index(index);
    1739         412 :   return result;
    1740             : }
    1741             : 
    1742        2439 : Handle<AsmWasmData> AsmWasmData::New(
    1743             :     Isolate* isolate, std::shared_ptr<wasm::NativeModule> native_module,
    1744             :     Handle<FixedArray> export_wrappers, Handle<ByteArray> asm_js_offset_table,
    1745             :     Handle<HeapNumber> uses_bitset) {
    1746        2439 :   const WasmModule* module = native_module->module();
    1747             :   size_t memory_estimate =
    1748        2439 :       wasm::WasmCodeManager::EstimateNativeModuleCodeSize(module) +
    1749        2439 :       wasm::WasmCodeManager::EstimateNativeModuleNonCodeSize(module);
    1750             :   Handle<Managed<wasm::NativeModule>> managed_native_module =
    1751             :       Managed<wasm::NativeModule>::FromSharedPtr(isolate, memory_estimate,
    1752        4878 :                                                  std::move(native_module));
    1753             :   Handle<AsmWasmData> result = Handle<AsmWasmData>::cast(
    1754        2439 :       isolate->factory()->NewStruct(ASM_WASM_DATA_TYPE, TENURED));
    1755        2439 :   result->set_managed_native_module(*managed_native_module);
    1756        2439 :   result->set_export_wrappers(*export_wrappers);
    1757        2439 :   result->set_asm_js_offset_table(*asm_js_offset_table);
    1758        2439 :   result->set_uses_bitset(*uses_bitset);
    1759        2439 :   return result;
    1760             : }
    1761             : 
    1762             : #undef TRACE
    1763             : #undef TRACE_IFT
    1764             : }  // namespace internal
    1765      178779 : }  // namespace v8

Generated by: LCOV version 1.10