LCOV - code coverage report
Current view: top level - src/wasm - wasm-objects.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 659 689 95.6 %
Date: 2019-04-17 Functions: 81 84 96.4 %

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

Generated by: LCOV version 1.10