LCOV - code coverage report
Current view: top level - src/wasm - wasm-objects.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 668 699 95.6 %
Date: 2019-04-17 Functions: 82 85 96.5 %

          Line data    Source code
       1             : // Copyright 2015 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/wasm/wasm-objects.h"
       6             : #include "src/utils.h"
       7             : 
       8             : #include "src/assembler-inl.h"
       9             : #include "src/base/iterator.h"
      10             : #include "src/code-factory.h"
      11             : #include "src/compiler/wasm-compiler.h"
      12             : #include "src/counters.h"
      13             : #include "src/debug/debug-interface.h"
      14             : #include "src/objects-inl.h"
      15             : #include "src/objects/debug-objects-inl.h"
      16             : #include "src/objects/shared-function-info.h"
      17             : #include "src/objects/struct-inl.h"
      18             : #include "src/trap-handler/trap-handler.h"
      19             : #include "src/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     1231090 :   WasmInstanceNativeAllocations(Handle<WasmInstanceObject> instance,
      71             :                                 size_t num_imported_functions,
      72             :                                 size_t num_imported_mutable_globals,
      73             :                                 size_t num_data_segments,
      74     1231090 :                                 size_t num_elem_segments) {
      75     1231090 :     SET(instance, imported_function_targets,
      76             :         reinterpret_cast<Address*>(
      77             :             calloc(num_imported_functions, sizeof(Address))));
      78     1231090 :     SET(instance, imported_mutable_globals,
      79             :         reinterpret_cast<Address*>(
      80             :             calloc(num_imported_mutable_globals, sizeof(Address))));
      81     1231090 :     SET(instance, data_segment_starts,
      82             :         reinterpret_cast<Address*>(calloc(num_data_segments, sizeof(Address))));
      83     1231090 :     SET(instance, data_segment_sizes,
      84             :         reinterpret_cast<uint32_t*>(
      85             :             calloc(num_data_segments, sizeof(uint32_t))));
      86     1231090 :     SET(instance, dropped_data_segments,
      87             :         reinterpret_cast<uint8_t*>(calloc(num_data_segments, sizeof(uint8_t))));
      88     1231090 :     SET(instance, dropped_elem_segments,
      89             :         reinterpret_cast<uint8_t*>(calloc(num_elem_segments, sizeof(uint8_t))));
      90     1231090 :   }
      91     2462180 :   ~WasmInstanceNativeAllocations() {
      92     1231090 :     ::free(indirect_function_table_sig_ids_);
      93     1231090 :     indirect_function_table_sig_ids_ = nullptr;
      94     1231090 :     ::free(indirect_function_table_targets_);
      95     1231090 :     indirect_function_table_targets_ = nullptr;
      96     1231090 :     ::free(imported_function_targets_);
      97     1231090 :     imported_function_targets_ = nullptr;
      98     1231090 :     ::free(imported_mutable_globals_);
      99     1231090 :     imported_mutable_globals_ = nullptr;
     100     1231090 :     ::free(data_segment_starts_);
     101     1231090 :     data_segment_starts_ = nullptr;
     102     1231090 :     ::free(data_segment_sizes_);
     103     1231090 :     data_segment_sizes_ = nullptr;
     104     1231090 :     ::free(dropped_data_segments_);
     105     1231090 :     dropped_data_segments_ = nullptr;
     106     1231090 :     ::free(dropped_elem_segments_);
     107     1231090 :     dropped_elem_segments_ = nullptr;
     108     1231090 :   }
     109             :   // Resizes the indirect function table.
     110        3273 :   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        3273 :     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        2385 :       new_sig_ids = malloc(new_size * sizeof(uint32_t));
     130        2385 :       new_targets = malloc(new_size * sizeof(Address));
     131        2385 :       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        3273 :     SET(instance, indirect_function_table_sig_ids,
     136             :         reinterpret_cast<uint32_t*>(new_sig_ids));
     137        3273 :     SET(instance, indirect_function_table_targets,
     138             :         reinterpret_cast<Address*>(new_targets));
     139             : 
     140        3273 :     instance->set_indirect_function_table_refs(*new_refs);
     141    40447627 :     for (uint32_t j = old_size; j < new_size; j++) {
     142    40444354 :       IndirectFunctionTableEntry(instance, static_cast<int>(j)).clear();
     143             :     }
     144        3273 :   }
     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     1231090 :       sizeof(WasmInstanceNativeAllocations) +
     159     2462180 :       (1 * kSystemPointerSize * module->num_imported_mutable_globals) +
     160     1231090 :       (2 * kSystemPointerSize * module->num_imported_functions) +
     161     1231090 :       ((kSystemPointerSize + sizeof(uint32_t) + sizeof(uint8_t)) *
     162     1231090 :        module->num_declared_data_segments);
     163     1233983 :   for (auto& table : module->tables) {
     164        2893 :     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     1096831 : 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     1096831 :   int export_wrapper_size = static_cast<int>(module->num_exported_functions);
     236             :   Handle<FixedArray> export_wrappers = isolate->factory()->NewFixedArray(
     237     1096831 :       export_wrapper_size, AllocationType::kOld);
     238             :   return New(isolate, std::move(native_module), script, export_wrappers,
     239     2193662 :              code_size_estimate);
     240             : }
     241             : 
     242             : // static
     243     1237207 : 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     1237207 :       wasm::WasmCodeManager::EstimateNativeModuleNonCodeSize(module);
     254             :   Handle<Managed<wasm::NativeModule>> managed_native_module =
     255             :       Managed<wasm::NativeModule>::FromSharedPtr(isolate, memory_estimate,
     256     1237207 :                                                  std::move(native_module));
     257             : 
     258             :   Handle<WasmModuleObject> module_object = Handle<WasmModuleObject>::cast(
     259     1237207 :       isolate->factory()->NewJSObject(isolate->wasm_module_constructor()));
     260     1237207 :   module_object->set_export_wrappers(*export_wrappers);
     261     1237207 :   if (script->type() == Script::TYPE_WASM) {
     262     1232189 :     script->set_wasm_module_object(*module_object);
     263             :   }
     264     1237207 :   module_object->set_script(*script);
     265     2474414 :   module_object->set_weak_instance_list(
     266     1237207 :       ReadOnlyRoots(isolate).empty_weak_array_list());
     267     1237207 :   module_object->set_managed_native_module(*managed_native_module);
     268     1237207 :   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      134655 : void WasmModuleObject::SetBreakpointsOnNewInstance(
     398             :     Handle<WasmModuleObject> module_object,
     399             :     Handle<WasmInstanceObject> instance) {
     400      269310 :   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      152004 : 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      304008 :   const WasmModule* module = module_object->module();
     511             : 
     512      152004 :   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      151220 :     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      242038 : 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      484077 :       module_object->native_module()->wire_bytes();
     672      242039 :   return ExtractUtf8StringFromModuleBytes(isolate, wire_bytes, ref);
     673             : }
     674             : 
     675      257132 : MaybeHandle<String> WasmModuleObject::ExtractUtf8StringFromModuleBytes(
     676             :     Isolate* isolate, Vector<const uint8_t> wire_bytes,
     677             :     wasm::WireBytesRef ref) {
     678      499171 :   Vector<const uint8_t> name_vec = wire_bytes + ref.offset();
     679      257132 :   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      499171 :       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      151876 : int WasmModuleObject::GetFunctionOffset(uint32_t func_index) {
     728             :   const std::vector<WasmFunction>& functions = module()->functions;
     729      303752 :   if (static_cast<uint32_t>(func_index) >= functions.size()) return -1;
     730             :   DCHECK_GE(kMaxInt, functions[func_index].code.offset());
     731      151876 :   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        4725 : 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             :   Handle<JSFunction> table_ctor(
     787       14175 :       isolate->native_context()->wasm_table_constructor(), isolate);
     788             :   auto table_obj = Handle<WasmTableObject>::cast(
     789        4725 :       isolate->factory()->NewJSObject(table_ctor));
     790             : 
     791        4725 :   Handle<FixedArray> backing_store = isolate->factory()->NewFixedArray(initial);
     792        4725 :   Object null = ReadOnlyRoots(isolate).null_value();
     793       88215 :   for (int i = 0; i < static_cast<int>(initial); ++i) {
     794       41745 :     backing_store->set(i, null);
     795             :   }
     796             : 
     797             :   table_obj->set_raw_type(static_cast<int>(type));
     798        4725 :   table_obj->set_elements(*backing_store);
     799             :   Handle<Object> max;
     800        4725 :   if (has_maximum) {
     801        3373 :     max = isolate->factory()->NewNumberFromUint(maximum);
     802             :   } else {
     803             :     max = isolate->factory()->undefined_value();
     804             :   }
     805        4725 :   table_obj->set_maximum_length(*max);
     806             : 
     807        4725 :   table_obj->set_dispatch_tables(ReadOnlyRoots(isolate).empty_fixed_array());
     808        4725 :   if (elements != nullptr) {
     809        1708 :     *elements = backing_store;
     810             :   }
     811        4725 :   return Handle<WasmTableObject>::cast(table_obj);
     812             : }
     813             : 
     814        4073 : 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        4073 :   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        4073 :                                                 kDispatchTableNumElements);
     829             : 
     830       12219 :   new_dispatch_tables->set(old_length + kDispatchTableInstanceOffset,
     831        4073 :                            *instance);
     832             :   new_dispatch_tables->set(old_length + kDispatchTableIndexOffset,
     833             :                            Smi::FromInt(table_index));
     834             : 
     835        4073 :   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       13912 : bool WasmTableObject::IsInBounds(Isolate* isolate,
     863             :                                  Handle<WasmTableObject> table,
     864             :                                  uint32_t entry_index) {
     865             :   return (entry_index <
     866       27816 :               static_cast<uint32_t>(std::numeric_limits<int>::max()) &&
     867       27816 :           static_cast<int>(entry_index) < table->elements()->length());
     868             : }
     869             : 
     870        3336 : bool WasmTableObject::IsValidElement(Isolate* isolate,
     871             :                                      Handle<WasmTableObject> table,
     872             :                                      Handle<Object> element) {
     873             :   // Anyref tables take everything.
     874        3336 :   if (table->type() == wasm::kWasmAnyRef) return true;
     875             :   // Anyfunc tables can store {null} or {WasmExportedFunction} objects.
     876        3288 :   if (element->IsNull(isolate)) return true;
     877        2136 :   return WasmExportedFunction::IsWasmExportedFunction(*element);
     878             : }
     879             : 
     880        3112 : 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        3112 :   int entry_index = static_cast<int>(index);
     889        3112 :   if (table->type() == wasm::kWasmAnyRef) {
     890          48 :     elements->set(entry_index, *element);
     891          48 :     return;
     892             :   }
     893             : 
     894        3064 :   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        3824 :                                              isolate);
     904        1912 :   int func_index = exported_function->function_index();
     905        1912 :   auto* wasm_function = &target_instance->module()->functions[func_index];
     906             :   DCHECK_NOT_NULL(wasm_function);
     907             :   DCHECK_NOT_NULL(wasm_function->sig);
     908        5736 :   UpdateDispatchTables(isolate, table, entry_index, wasm_function->sig,
     909             :                        handle(exported_function->instance(), isolate),
     910        1912 :                        func_index);
     911        1912 :   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       12053 : 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       23189 :   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       12053 : }
    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     2109768 : 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     2109768 :   *is_valid = true;
    1040             :   Handle<Object> element(table->elements()->get(entry_index), isolate);
    1041             : 
    1042     2109768 :   *is_null = element->IsNull(isolate);
    1043     2109768 :   if (*is_null) return;
    1044             : 
    1045        2924 :   if (WasmExportedFunction::IsWasmExportedFunction(*element)) {
    1046             :     auto target_func = Handle<WasmExportedFunction>::cast(element);
    1047        2176 :     *instance = handle(target_func->instance(), isolate);
    1048        1088 :     *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        2200 : bool AdjustBufferPermissions(Isolate* isolate, Handle<JSArrayBuffer> old_buffer,
    1061             :                              size_t new_size) {
    1062        2200 :   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        2200 :   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        1724 :     if (!i::SetPermissions(GetPlatformPageAllocator(), old_mem_start, new_size,
    1071             :                            PageAllocator::kReadWrite)) {
    1072             :       return false;
    1073             :     }
    1074             :     reinterpret_cast<v8::Isolate*>(isolate)
    1075        1724 :         ->AdjustAmountOfExternalAllocatedMemory(new_size - old_size);
    1076             :   }
    1077             :   return true;
    1078             : }
    1079             : 
    1080        2100 : MaybeHandle<JSArrayBuffer> MemoryGrowBuffer(Isolate* isolate,
    1081             :                                             Handle<JSArrayBuffer> old_buffer,
    1082             :                                             size_t new_size) {
    1083        4200 :   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        2100 :   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             :     wasm::WasmMemoryTracker* const memory_tracker =
    1096             :         isolate->wasm_engine()->memory_tracker();
    1097             :     // If the old buffer had full guard regions, we can only safely use the new
    1098             :     // buffer if it also has full guard regions. Otherwise, we'd have to
    1099             :     // recompile all the instances using this memory to insert bounds checks.
    1100             :     void* old_mem_start = old_buffer->backing_store();
    1101          16 :     if (memory_tracker->HasFullGuardRegions(old_mem_start) &&
    1102           8 :         !memory_tracker->HasFullGuardRegions(new_buffer->backing_store())) {
    1103           0 :       return {};
    1104             :     }
    1105             :     size_t old_size = old_buffer->byte_length();
    1106           8 :     if (old_size == 0) return new_buffer;
    1107             :     memcpy(new_buffer->backing_store(), old_mem_start, old_size);
    1108             :     DCHECK(old_buffer.is_null() || !old_buffer->is_shared());
    1109             :     constexpr bool free_memory = true;
    1110           8 :     i::wasm::DetachMemoryBuffer(isolate, old_buffer, free_memory);
    1111           8 :     return new_buffer;
    1112             :   } else {
    1113        2092 :     if (!AdjustBufferPermissions(isolate, old_buffer, new_size)) return {};
    1114             :     // NOTE: We must allocate a new array buffer here because the spec
    1115             :     // assumes that ArrayBuffers do not change size.
    1116             :     void* backing_store = old_buffer->backing_store();
    1117             :     bool is_external = old_buffer->is_external();
    1118             :     // Disconnect buffer early so GC won't free it.
    1119        2092 :     i::wasm::DetachMemoryBuffer(isolate, old_buffer, false);
    1120             :     Handle<JSArrayBuffer> new_buffer =
    1121        2092 :         wasm::SetupArrayBuffer(isolate, backing_store, new_size, is_external);
    1122        2092 :     return new_buffer;
    1123             :   }
    1124             : }
    1125             : 
    1126             : // May GC, because SetSpecializationMemInfoFrom may GC
    1127       59055 : void SetInstanceMemory(Handle<WasmInstanceObject> instance,
    1128             :                        Handle<JSArrayBuffer> buffer) {
    1129      118110 :   instance->SetRawMemory(reinterpret_cast<byte*>(buffer->backing_store()),
    1130       59055 :                          buffer->byte_length());
    1131             : #if DEBUG
    1132             :   if (!FLAG_mock_arraybuffer_allocator) {
    1133             :     // To flush out bugs earlier, in DEBUG mode, check that all pages of the
    1134             :     // memory are accessible by reading and writing one byte on each page.
    1135             :     // Don't do this if the mock ArrayBuffer allocator is enabled.
    1136             :     byte* mem_start = instance->memory_start();
    1137             :     size_t mem_size = instance->memory_size();
    1138             :     for (size_t offset = 0; offset < mem_size; offset += wasm::kWasmPageSize) {
    1139             :       byte val = mem_start[offset];
    1140             :       USE(val);
    1141             :       mem_start[offset] = val;
    1142             :     }
    1143             :   }
    1144             : #endif
    1145       59055 : }
    1146             : 
    1147             : }  // namespace
    1148             : 
    1149       55243 : Handle<WasmMemoryObject> WasmMemoryObject::New(
    1150             :     Isolate* isolate, MaybeHandle<JSArrayBuffer> maybe_buffer,
    1151             :     uint32_t maximum) {
    1152             :   // TODO(kschimpf): Do we need to add an argument that defines the
    1153             :   // style of memory the user prefers (with/without trap handling), so
    1154             :   // that the memory will match the style of the compiled wasm module.
    1155             :   // See issue v8:7143
    1156             :   Handle<JSFunction> memory_ctor(
    1157      165728 :       isolate->native_context()->wasm_memory_constructor(), isolate);
    1158             :   auto memory_obj = Handle<WasmMemoryObject>::cast(
    1159       55242 :       isolate->factory()->NewJSObject(memory_ctor, AllocationType::kOld));
    1160             : 
    1161             :   Handle<JSArrayBuffer> buffer;
    1162       55243 :   if (!maybe_buffer.ToHandle(&buffer)) {
    1163             :     // If no buffer was provided, create a 0-length one.
    1164          12 :     buffer = wasm::SetupArrayBuffer(isolate, nullptr, 0, false);
    1165             :   }
    1166       55243 :   memory_obj->set_array_buffer(*buffer);
    1167       55243 :   memory_obj->set_maximum_pages(maximum);
    1168             : 
    1169       55243 :   return memory_obj;
    1170             : }
    1171             : 
    1172        4371 : MaybeHandle<WasmMemoryObject> WasmMemoryObject::New(Isolate* isolate,
    1173             :                                                     uint32_t initial,
    1174             :                                                     uint32_t maximum,
    1175             :                                                     bool is_shared_memory) {
    1176             :   Handle<JSArrayBuffer> buffer;
    1177        4371 :   size_t size = static_cast<size_t>(i::wasm::kWasmPageSize) *
    1178        4371 :                 static_cast<size_t>(initial);
    1179        4371 :   if (is_shared_memory) {
    1180         249 :     size_t max_size = static_cast<size_t>(i::wasm::kWasmPageSize) *
    1181         249 :                       static_cast<size_t>(maximum);
    1182         498 :     if (!i::wasm::NewSharedArrayBuffer(isolate, size, max_size)
    1183             :              .ToHandle(&buffer)) {
    1184           0 :       return {};
    1185             :     }
    1186             :   } else {
    1187        8244 :     if (!i::wasm::NewArrayBuffer(isolate, size).ToHandle(&buffer)) {
    1188           8 :       return {};
    1189             :     }
    1190             :   }
    1191        4363 :   return New(isolate, buffer, maximum);
    1192             : }
    1193             : 
    1194        1206 : bool WasmMemoryObject::has_full_guard_region(Isolate* isolate) {
    1195             :   const wasm::WasmMemoryTracker::AllocationData* allocation =
    1196             :       isolate->wasm_engine()->memory_tracker()->FindAllocationData(
    1197        1206 :           array_buffer()->backing_store());
    1198        1206 :   CHECK_NOT_NULL(allocation);
    1199             : 
    1200             :   Address allocation_base =
    1201        1206 :       reinterpret_cast<Address>(allocation->allocation_base);
    1202        1206 :   Address buffer_start = reinterpret_cast<Address>(allocation->buffer_start);
    1203             : 
    1204             :   // Return whether the allocation covers every possible Wasm heap index.
    1205             :   //
    1206             :   // We always have the following relationship:
    1207             :   // allocation_base <= buffer_start <= buffer_start + memory_size <=
    1208             :   // allocation_base + allocation_length
    1209             :   // (in other words, the buffer fits within the allocation)
    1210             :   //
    1211             :   // The space between buffer_start + memory_size and allocation_base +
    1212             :   // allocation_length is the guard region. Here we make sure the guard region
    1213             :   // is large enough for any Wasm heap offset.
    1214        1206 :   return buffer_start + wasm::kWasmMaxHeapOffset <=
    1215        1206 :          allocation_base + allocation->allocation_length;
    1216             : }
    1217             : 
    1218       54984 : void WasmMemoryObject::AddInstance(Isolate* isolate,
    1219             :                                    Handle<WasmMemoryObject> memory,
    1220             :                                    Handle<WasmInstanceObject> instance) {
    1221             :   Handle<WeakArrayList> old_instances =
    1222             :       memory->has_instances()
    1223             :           ? Handle<WeakArrayList>(memory->instances(), isolate)
    1224             :           : handle(ReadOnlyRoots(isolate->heap()).empty_weak_array_list(),
    1225      107243 :                    isolate);
    1226             :   Handle<WeakArrayList> new_instances = WeakArrayList::AddToEnd(
    1227       54984 :       isolate, old_instances, MaybeObjectHandle::Weak(instance));
    1228       54985 :   memory->set_instances(*new_instances);
    1229             :   Handle<JSArrayBuffer> buffer(memory->array_buffer(), isolate);
    1230       54986 :   SetInstanceMemory(instance, buffer);
    1231       54987 : }
    1232             : 
    1233        2316 : void WasmMemoryObject::update_instances(Isolate* isolate,
    1234             :                                         Handle<JSArrayBuffer> buffer) {
    1235        2316 :   if (has_instances()) {
    1236             :     Handle<WeakArrayList> instances(this->instances(), isolate);
    1237       10532 :     for (int i = 0; i < instances->length(); i++) {
    1238             :       MaybeObject elem = instances->Get(i);
    1239             :       HeapObject heap_object;
    1240        4244 :       if (elem->GetHeapObjectIfWeak(&heap_object)) {
    1241             :         Handle<WasmInstanceObject> instance(
    1242             :             WasmInstanceObject::cast(heap_object), isolate);
    1243        4068 :         SetInstanceMemory(instance, buffer);
    1244             :       } else {
    1245             :         DCHECK(elem->IsCleared());
    1246             :       }
    1247             :     }
    1248             :   }
    1249        2316 :   set_array_buffer(*buffer);
    1250        2316 : }
    1251             : 
    1252             : // static
    1253        2432 : int32_t WasmMemoryObject::Grow(Isolate* isolate,
    1254             :                                Handle<WasmMemoryObject> memory_object,
    1255             :                                uint32_t pages) {
    1256        7296 :   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.wasm"), "GrowMemory");
    1257             :   Handle<JSArrayBuffer> old_buffer(memory_object->array_buffer(), isolate);
    1258        2432 :   if (old_buffer->is_shared() && !FLAG_wasm_grow_shared_memory) return -1;
    1259             :   auto* memory_tracker = isolate->wasm_engine()->memory_tracker();
    1260        2432 :   if (!memory_tracker->IsWasmMemoryGrowable(old_buffer)) return -1;
    1261             : 
    1262             :   // Checks for maximum memory size, compute new size.
    1263        2424 :   uint32_t maximum_pages = wasm::max_mem_pages();
    1264        2424 :   if (memory_object->has_maximum_pages()) {
    1265             :     maximum_pages = std::min(
    1266        4560 :         maximum_pages, static_cast<uint32_t>(memory_object->maximum_pages()));
    1267             :   }
    1268        2424 :   CHECK_GE(wasm::max_mem_pages(), maximum_pages);
    1269             :   size_t old_size = old_buffer->byte_length();
    1270        4848 :   CHECK_EQ(0, old_size % wasm::kWasmPageSize);
    1271        2424 :   size_t old_pages = old_size / wasm::kWasmPageSize;
    1272        4848 :   CHECK_GE(wasm::max_mem_pages(), old_pages);
    1273        4632 :   if ((pages > maximum_pages - old_pages) ||          // exceeds remaining
    1274        2208 :       (pages > wasm::max_mem_pages() - old_pages)) {  // exceeds limit
    1275             :     return -1;
    1276             :   }
    1277             :   size_t new_size =
    1278        2208 :       static_cast<size_t>(old_pages + pages) * wasm::kWasmPageSize;
    1279             : 
    1280             :   // Memory is grown, but the memory objects and instances are not yet updated.
    1281             :   // Handle this in the interrupt handler so that it's safe for all the isolates
    1282             :   // that share this buffer to be updated safely.
    1283             :   Handle<JSArrayBuffer> new_buffer;
    1284        2208 :   if (old_buffer->is_shared()) {
    1285             :     // Adjust protections for the buffer.
    1286         108 :     if (!AdjustBufferPermissions(isolate, old_buffer, new_size)) {
    1287             :       return -1;
    1288             :     }
    1289             :     void* backing_store = old_buffer->backing_store();
    1290         108 :     if (memory_tracker->IsWasmSharedMemory(backing_store)) {
    1291             :       // This memory is shared between different isolates.
    1292             :       DCHECK(old_buffer->is_shared());
    1293             :       // Update pending grow state, and trigger a grow interrupt on all the
    1294             :       // isolates that share this buffer.
    1295         100 :       memory_tracker->SetPendingUpdateOnGrow(old_buffer, new_size);
    1296             :       // Handle interrupts for this isolate so that the instances with this
    1297             :       // isolate are updated.
    1298         100 :       isolate->stack_guard()->HandleInterrupts();
    1299             :       // Failure to allocate, or adjust pemissions already handled here, and
    1300             :       // updates to instances handled in the interrupt handler safe to return.
    1301         100 :       return static_cast<uint32_t>(old_size / wasm::kWasmPageSize);
    1302             :     }
    1303             :     // SharedArrayBuffer, but not shared across isolates. Setup a new buffer
    1304             :     // with updated permissions and update the instances.
    1305             :     new_buffer =
    1306             :         wasm::SetupArrayBuffer(isolate, backing_store, new_size,
    1307           8 :                                old_buffer->is_external(), SharedFlag::kShared);
    1308           8 :     memory_object->update_instances(isolate, new_buffer);
    1309             :   } else {
    1310        4200 :     if (!MemoryGrowBuffer(isolate, old_buffer, new_size)
    1311             :              .ToHandle(&new_buffer)) {
    1312             :       return -1;
    1313             :     }
    1314             :   }
    1315             :   // Update instances if any.
    1316        2108 :   memory_object->update_instances(isolate, new_buffer);
    1317        2108 :   return static_cast<uint32_t>(old_size / wasm::kWasmPageSize);
    1318             : }
    1319             : 
    1320             : // static
    1321        8164 : MaybeHandle<WasmGlobalObject> WasmGlobalObject::New(
    1322             :     Isolate* isolate, MaybeHandle<JSArrayBuffer> maybe_untagged_buffer,
    1323             :     MaybeHandle<FixedArray> maybe_tagged_buffer, wasm::ValueType type,
    1324             :     int32_t offset, bool is_mutable) {
    1325             :   Handle<JSFunction> global_ctor(
    1326       24492 :       isolate->native_context()->wasm_global_constructor(), isolate);
    1327             :   auto global_obj = Handle<WasmGlobalObject>::cast(
    1328        8164 :       isolate->factory()->NewJSObject(global_ctor));
    1329             : 
    1330        8164 :   if (wasm::ValueTypes::IsReferenceType(type)) {
    1331             :     DCHECK(maybe_untagged_buffer.is_null());
    1332             :     Handle<FixedArray> tagged_buffer;
    1333         656 :     if (!maybe_tagged_buffer.ToHandle(&tagged_buffer)) {
    1334             :       // If no buffer was provided, create one.
    1335             :       tagged_buffer =
    1336         352 :           isolate->factory()->NewFixedArray(1, AllocationType::kOld);
    1337         352 :       CHECK_EQ(offset, 0);
    1338             :     }
    1339         656 :     global_obj->set_tagged_buffer(*tagged_buffer);
    1340             :   } else {
    1341             :     DCHECK(maybe_tagged_buffer.is_null());
    1342             :     Handle<JSArrayBuffer> untagged_buffer;
    1343        7508 :     uint32_t type_size = wasm::ValueTypes::ElementSizeInBytes(type);
    1344        7508 :     if (!maybe_untagged_buffer.ToHandle(&untagged_buffer)) {
    1345             :       // If no buffer was provided, create one long enough for the given type.
    1346             :       untagged_buffer = isolate->factory()->NewJSArrayBuffer(
    1347        6976 :           SharedFlag::kNotShared, AllocationType::kOld);
    1348             : 
    1349             :       const bool initialize = true;
    1350        6976 :       if (!JSArrayBuffer::SetupAllocatingData(untagged_buffer, isolate,
    1351             :                                               type_size, initialize)) {
    1352           0 :         return {};
    1353             :       }
    1354             :     }
    1355             : 
    1356             :     // Check that the offset is in bounds.
    1357       15016 :     CHECK_LE(offset + type_size, untagged_buffer->byte_length());
    1358             : 
    1359        7508 :     global_obj->set_untagged_buffer(*untagged_buffer);
    1360             :   }
    1361             :   global_obj->set_flags(0);
    1362       16328 :   global_obj->set_type(type);
    1363             :   global_obj->set_offset(offset);
    1364       16328 :   global_obj->set_is_mutable(is_mutable);
    1365             : 
    1366        8164 :   return global_obj;
    1367             : }
    1368             : 
    1369    20223057 : void IndirectFunctionTableEntry::clear() {
    1370    20223057 :   instance_->indirect_function_table_sig_ids()[index_] = -1;
    1371    20223057 :   instance_->indirect_function_table_targets()[index_] = 0;
    1372    40446114 :   instance_->indirect_function_table_refs()->set(
    1373    60669171 :       index_, ReadOnlyRoots(instance_->GetIsolate()).undefined_value());
    1374    20223057 : }
    1375             : 
    1376       18693 : void IndirectFunctionTableEntry::Set(int sig_id,
    1377             :                                      Handle<WasmInstanceObject> target_instance,
    1378             :                                      int target_func_index) {
    1379             :   TRACE_IFT(
    1380             :       "IFT entry %p[%d] = {sig_id=%d, target_instance=%p, "
    1381             :       "target_func_index=%d}\n",
    1382             :       reinterpret_cast<void*>(instance_->ptr()), index_, sig_id,
    1383             :       reinterpret_cast<void*>(target_instance->ptr()), target_func_index);
    1384             : 
    1385             :   Object ref;
    1386             :   Address call_target = 0;
    1387       18693 :   if (target_func_index <
    1388       18693 :       static_cast<int>(target_instance->module()->num_imported_functions)) {
    1389             :     // The function in the target instance was imported. Use its imports table,
    1390             :     // which contains a tuple needed by the import wrapper.
    1391             :     ImportedFunctionEntry entry(target_instance, target_func_index);
    1392        1032 :     ref = entry.object_ref();
    1393             :     call_target = entry.target();
    1394             :   } else {
    1395             :     // The function in the target instance was not imported.
    1396       17661 :     ref = *target_instance;
    1397       17661 :     call_target = target_instance->GetCallTarget(target_func_index);
    1398             :   }
    1399             : 
    1400             :   // Set the signature id, the target, and the receiver ref.
    1401       18693 :   instance_->indirect_function_table_sig_ids()[index_] = sig_id;
    1402       18693 :   instance_->indirect_function_table_targets()[index_] = call_target;
    1403       37386 :   instance_->indirect_function_table_refs()->set(index_, ref);
    1404       18693 : }
    1405             : 
    1406       40576 : Object IndirectFunctionTableEntry::object_ref() {
    1407       81152 :   return instance_->indirect_function_table_refs()->get(index_);
    1408             : }
    1409             : 
    1410       40696 : int IndirectFunctionTableEntry::sig_id() {
    1411       40696 :   return instance_->indirect_function_table_sig_ids()[index_];
    1412             : }
    1413             : 
    1414       40576 : Address IndirectFunctionTableEntry::target() {
    1415       40576 :   return instance_->indirect_function_table_targets()[index_];
    1416             : }
    1417             : 
    1418         596 : void IndirectFunctionTableEntry::CopyFrom(
    1419             :     const IndirectFunctionTableEntry& that) {
    1420         596 :   instance_->indirect_function_table_sig_ids()[index_] =
    1421         596 :       that.instance_->indirect_function_table_sig_ids()[that.index_];
    1422         596 :   instance_->indirect_function_table_targets()[index_] =
    1423         596 :       that.instance_->indirect_function_table_targets()[that.index_];
    1424        1192 :   instance_->indirect_function_table_refs()->set(
    1425        1788 :       index_, that.instance_->indirect_function_table_refs()->get(that.index_));
    1426         596 : }
    1427             : 
    1428       12625 : void ImportedFunctionEntry::SetWasmToJs(
    1429             :     Isolate* isolate, Handle<JSReceiver> callable,
    1430             :     const wasm::WasmCode* wasm_to_js_wrapper) {
    1431             :   TRACE_IFT("Import callable %p[%d] = {callable=%p, target=%p}\n",
    1432             :             reinterpret_cast<void*>(instance_->ptr()), index_,
    1433             :             reinterpret_cast<void*>(callable->ptr()),
    1434             :             wasm_to_js_wrapper->instructions().start());
    1435             :   DCHECK_EQ(wasm::WasmCode::kWasmToJsWrapper, wasm_to_js_wrapper->kind());
    1436             :   Handle<Tuple2> tuple =
    1437       12625 :       isolate->factory()->NewTuple2(instance_, callable, AllocationType::kOld);
    1438       25250 :   instance_->imported_function_refs()->set(index_, *tuple);
    1439       12625 :   instance_->imported_function_targets()[index_] =
    1440       12625 :       wasm_to_js_wrapper->instruction_start();
    1441       12625 : }
    1442             : 
    1443      107288 : void ImportedFunctionEntry::SetWasmToWasm(WasmInstanceObject instance,
    1444             :                                           Address call_target) {
    1445             :   TRACE_IFT("Import WASM %p[%d] = {instance=%p, target=%" PRIuPTR "}\n",
    1446             :             reinterpret_cast<void*>(instance_->ptr()), index_,
    1447             :             reinterpret_cast<void*>(instance->ptr()), call_target);
    1448      214576 :   instance_->imported_function_refs()->set(index_, instance);
    1449      107288 :   instance_->imported_function_targets()[index_] = call_target;
    1450      107288 : }
    1451             : 
    1452           0 : WasmInstanceObject ImportedFunctionEntry::instance() {
    1453             :   // The imported reference entry is either a target instance or a tuple
    1454             :   // of this instance and the target callable.
    1455           0 :   Object value = instance_->imported_function_refs()->get(index_);
    1456           0 :   if (value->IsWasmInstanceObject()) {
    1457             :     return WasmInstanceObject::cast(value);
    1458             :   }
    1459             :   Tuple2 tuple = Tuple2::cast(value);
    1460             :   return WasmInstanceObject::cast(tuple->value1());
    1461             : }
    1462             : 
    1463           0 : JSReceiver ImportedFunctionEntry::callable() {
    1464           0 :   return JSReceiver::cast(Tuple2::cast(object_ref())->value2());
    1465             : }
    1466             : 
    1467        9221 : Object ImportedFunctionEntry::object_ref() {
    1468       18442 :   return instance_->imported_function_refs()->get(index_);
    1469             : }
    1470             : 
    1471        8189 : Address ImportedFunctionEntry::target() {
    1472        9221 :   return instance_->imported_function_targets()[index_];
    1473             : }
    1474             : 
    1475             : // static
    1476             : constexpr uint16_t WasmInstanceObject::kTaggedFieldOffsets[];
    1477             : 
    1478             : // static
    1479        4909 : bool WasmInstanceObject::EnsureIndirectFunctionTableWithMinimumSize(
    1480             :     Handle<WasmInstanceObject> instance, uint32_t minimum_size) {
    1481             :   uint32_t old_size = instance->indirect_function_table_size();
    1482        4909 :   if (old_size >= minimum_size) return false;  // Nothing to do.
    1483             : 
    1484             :   Isolate* isolate = instance->GetIsolate();
    1485             :   HandleScope scope(isolate);
    1486             :   auto native_allocations = GetNativeAllocations(*instance);
    1487             :   native_allocations->resize_indirect_function_table(isolate, instance,
    1488        3273 :                                                      minimum_size);
    1489             :   return true;
    1490             : }
    1491             : 
    1492     1331625 : void WasmInstanceObject::SetRawMemory(byte* mem_start, size_t mem_size) {
    1493     1331625 :   CHECK_LE(mem_size, wasm::max_mem_bytes());
    1494             : #if V8_HOST_ARCH_64_BIT
    1495     1331625 :   uint64_t mem_mask64 = base::bits::RoundUpToPowerOfTwo64(mem_size) - 1;
    1496             :   set_memory_start(mem_start);
    1497             :   set_memory_size(mem_size);
    1498             :   set_memory_mask(mem_mask64);
    1499             : #else
    1500             :   // Must handle memory > 2GiB specially.
    1501             :   CHECK_LE(mem_size, size_t{kMaxUInt32});
    1502             :   uint32_t mem_mask32 =
    1503             :       (mem_size > 2 * size_t{GB})
    1504             :           ? 0xFFFFFFFFu
    1505             :           : base::bits::RoundUpToPowerOfTwo32(static_cast<uint32_t>(mem_size)) -
    1506             :                 1;
    1507             :   set_memory_start(mem_start);
    1508             :   set_memory_size(mem_size);
    1509             :   set_memory_mask(mem_mask32);
    1510             : #endif
    1511     1331625 : }
    1512             : 
    1513      149017 : const WasmModule* WasmInstanceObject::module() {
    1514     1085692 :   return module_object()->module();
    1515             : }
    1516             : 
    1517       37681 : Handle<WasmDebugInfo> WasmInstanceObject::GetOrCreateDebugInfo(
    1518             :     Handle<WasmInstanceObject> instance) {
    1519       37681 :   if (instance->has_debug_info()) {
    1520             :     return handle(instance->debug_info(), instance->GetIsolate());
    1521             :   }
    1522        1719 :   Handle<WasmDebugInfo> new_info = WasmDebugInfo::New(instance);
    1523             :   DCHECK(instance->has_debug_info());
    1524        1719 :   return new_info;
    1525             : }
    1526             : 
    1527     1231090 : Handle<WasmInstanceObject> WasmInstanceObject::New(
    1528             :     Isolate* isolate, Handle<WasmModuleObject> module_object) {
    1529             :   Handle<JSFunction> instance_cons(
    1530     3693270 :       isolate->native_context()->wasm_instance_constructor(), isolate);
    1531             :   Handle<JSObject> instance_object =
    1532     1231090 :       isolate->factory()->NewJSObject(instance_cons, AllocationType::kOld);
    1533             : 
    1534             :   Handle<WasmInstanceObject> instance(
    1535             :       WasmInstanceObject::cast(*instance_object), isolate);
    1536             :   instance->clear_padding();
    1537             : 
    1538             :   // Initialize the imported function arrays.
    1539     2462180 :   auto module = module_object->module();
    1540     1231090 :   auto num_imported_functions = module->num_imported_functions;
    1541     1231090 :   auto num_imported_mutable_globals = module->num_imported_mutable_globals;
    1542     1231090 :   auto num_data_segments = module->num_declared_data_segments;
    1543             :   size_t native_allocations_size = EstimateNativeAllocationsSize(module);
    1544             :   auto native_allocations = Managed<WasmInstanceNativeAllocations>::Allocate(
    1545             :       isolate, native_allocations_size, instance, num_imported_functions,
    1546             :       num_imported_mutable_globals, num_data_segments,
    1547     1231090 :       module->elem_segments.size());
    1548     2462178 :   instance->set_managed_native_allocations(*native_allocations);
    1549             : 
    1550             :   Handle<FixedArray> imported_function_refs =
    1551     1231090 :       isolate->factory()->NewFixedArray(num_imported_functions);
    1552     1231090 :   instance->set_imported_function_refs(*imported_function_refs);
    1553             : 
    1554     1231088 :   Handle<Code> centry_stub = CodeFactory::CEntry(isolate);
    1555     1231090 :   instance->set_centry_stub(*centry_stub);
    1556             : 
    1557     1231090 :   instance->SetRawMemory(nullptr, 0);
    1558             :   instance->set_isolate_root(isolate->isolate_root());
    1559             :   instance->set_stack_limit_address(
    1560             :       isolate->stack_guard()->address_of_jslimit());
    1561             :   instance->set_real_stack_limit_address(
    1562             :       isolate->stack_guard()->address_of_real_jslimit());
    1563             :   instance->set_globals_start(nullptr);
    1564             :   instance->set_indirect_function_table_size(0);
    1565             :   instance->set_indirect_function_table_sig_ids(nullptr);
    1566             :   instance->set_indirect_function_table_targets(nullptr);
    1567     3693270 :   instance->set_native_context(*isolate->native_context());
    1568     1231090 :   instance->set_module_object(*module_object);
    1569     1231088 :   instance->set_undefined_value(ReadOnlyRoots(isolate).undefined_value());
    1570     1231088 :   instance->set_null_value(ReadOnlyRoots(isolate).null_value());
    1571     2462180 :   instance->set_jump_table_start(
    1572             :       module_object->native_module()->jump_table_start());
    1573             : 
    1574             :   // Insert the new instance into the modules weak list of instances.
    1575             :   // TODO(mstarzinger): Allow to reuse holes in the {WeakArrayList} below.
    1576             :   Handle<WeakArrayList> weak_instance_list(module_object->weak_instance_list(),
    1577             :                                            isolate);
    1578             :   weak_instance_list = WeakArrayList::AddToEnd(
    1579     1231090 :       isolate, weak_instance_list, MaybeObjectHandle::Weak(instance));
    1580     1231090 :   module_object->set_weak_instance_list(*weak_instance_list);
    1581             : 
    1582     1231090 :   InitDataSegmentArrays(instance, module_object);
    1583     1231090 :   InitElemSegmentArrays(instance, module_object);
    1584             : 
    1585     1231089 :   return instance;
    1586             : }
    1587             : 
    1588             : // static
    1589     1231088 : void WasmInstanceObject::InitDataSegmentArrays(
    1590             :     Handle<WasmInstanceObject> instance,
    1591             :     Handle<WasmModuleObject> module_object) {
    1592     2462177 :   auto module = module_object->module();
    1593     2462179 :   auto wire_bytes = module_object->native_module()->wire_bytes();
    1594     1231090 :   auto num_data_segments = module->num_declared_data_segments;
    1595             :   // The number of declared data segments will be zero if there is no DataCount
    1596             :   // section. These arrays will not be allocated nor initialized in that case,
    1597             :   // since they cannot be used (since the validator checks that number of
    1598             :   // declared data segments when validating the memory.init and memory.drop
    1599             :   // instructions).
    1600             :   DCHECK(num_data_segments == 0 ||
    1601             :          num_data_segments == module->data_segments.size());
    1602     1231234 :   for (size_t i = 0; i < num_data_segments; ++i) {
    1603             :     const wasm::WasmDataSegment& segment = module->data_segments[i];
    1604             :     // Set the active segments to being already dropped, since memory.init on
    1605             :     // a dropped passive segment and an active segment have the same
    1606             :     // behavior.
    1607          72 :     instance->dropped_data_segments()[i] = segment.active ? 1 : 0;
    1608             : 
    1609             :     // Initialize the pointer and size of passive segments.
    1610             :     auto source_bytes = wire_bytes.SubVector(segment.source.offset(),
    1611          72 :                                              segment.source.end_offset());
    1612          72 :     instance->data_segment_starts()[i] =
    1613          72 :         reinterpret_cast<Address>(source_bytes.start());
    1614          72 :     instance->data_segment_sizes()[i] = source_bytes.length();
    1615             :   }
    1616     1231090 : }
    1617             : 
    1618     1231090 : void WasmInstanceObject::InitElemSegmentArrays(
    1619             :     Handle<WasmInstanceObject> instance,
    1620             :     Handle<WasmModuleObject> module_object) {
    1621     2462180 :   auto module = module_object->module();
    1622             :   auto num_elem_segments = module->elem_segments.size();
    1623     1235372 :   for (size_t i = 0; i < num_elem_segments; ++i) {
    1624             :     const wasm::WasmElemSegment& segment = module->elem_segments[i];
    1625             :     // Set the active segments to being already dropped, since table.init on
    1626             :     // a dropped passive segment and an active segment have the same
    1627             :     // behavior.
    1628        2141 :     instance->dropped_elem_segments()[i] = segment.active ? 1 : 0;
    1629             :   }
    1630     1231090 : }
    1631             : 
    1632      124837 : Address WasmInstanceObject::GetCallTarget(uint32_t func_index) {
    1633      124837 :   wasm::NativeModule* native_module = module_object()->native_module();
    1634      124837 :   if (func_index < native_module->num_imported_functions()) {
    1635           0 :     return imported_function_targets()[func_index];
    1636             :   }
    1637      124837 :   return native_module->GetCallTargetForFunction(func_index);
    1638             : }
    1639             : 
    1640             : namespace {
    1641         276 : void CopyTableEntriesImpl(Handle<WasmInstanceObject> instance, uint32_t dst,
    1642             :                           uint32_t src, uint32_t count, bool copy_backward) {
    1643             :   DCHECK(IsInBounds(dst, count, instance->indirect_function_table_size()));
    1644         276 :   if (copy_backward) {
    1645         252 :     for (uint32_t i = count; i > 0; i--) {
    1646         108 :       auto to_entry = IndirectFunctionTableEntry(instance, dst + i - 1);
    1647         108 :       auto from_entry = IndirectFunctionTableEntry(instance, src + i - 1);
    1648         108 :       to_entry.CopyFrom(from_entry);
    1649             :     }
    1650             :   } else {
    1651        1216 :     for (uint32_t i = 0; i < count; i++) {
    1652         488 :       auto to_entry = IndirectFunctionTableEntry(instance, dst + i);
    1653         488 :       auto from_entry = IndirectFunctionTableEntry(instance, src + i);
    1654         488 :       to_entry.CopyFrom(from_entry);
    1655             :     }
    1656             :   }
    1657         276 : }
    1658             : }  // namespace
    1659             : 
    1660             : // static
    1661        2328 : bool WasmInstanceObject::CopyTableEntries(Isolate* isolate,
    1662             :                                           Handle<WasmInstanceObject> instance,
    1663             :                                           uint32_t table_src_index,
    1664             :                                           uint32_t table_dst_index,
    1665             :                                           uint32_t dst, uint32_t src,
    1666             :                                           uint32_t count) {
    1667        2328 :   if (static_cast<int>(table_dst_index) >= instance->tables()->length()) {
    1668             :     return false;
    1669             :   }
    1670        2328 :   if (static_cast<int>(table_src_index) >= instance->tables()->length()) {
    1671             :     return false;
    1672             :   }
    1673             : 
    1674             :   // TODO(titzer): multiple tables in TableCopy
    1675        2328 :   CHECK_EQ(0, table_src_index);
    1676        2328 :   CHECK_EQ(0, table_dst_index);
    1677             :   auto max = instance->indirect_function_table_size();
    1678        2328 :   bool copy_backward = src < dst && dst - src < count;
    1679             :   bool ok = ClampToBounds(dst, &count, max);
    1680             :   // Use & instead of && so the clamp is not short-circuited.
    1681             :   ok &= ClampToBounds(src, &count, max);
    1682             : 
    1683             :   // If performing a partial copy when copying backward, then the first access
    1684             :   // will be out-of-bounds, so no entries should be copied.
    1685        2328 :   if (copy_backward && !ok) return ok;
    1686             : 
    1687        2304 :   if (dst == src || count == 0) return ok;  // no-op
    1688             : 
    1689             :   // TODO(titzer): multiple tables in TableCopy
    1690             :   auto table = handle(
    1691             :       WasmTableObject::cast(instance->tables()->get(table_src_index)), isolate);
    1692             :   // Broadcast table copy operation to all instances that import this table.
    1693             :   Handle<FixedArray> dispatch_tables(table->dispatch_tables(), isolate);
    1694         804 :   for (int i = 0; i < dispatch_tables->length();
    1695             :        i += kDispatchTableNumElements) {
    1696             :     Handle<WasmInstanceObject> target_instance(
    1697             :         WasmInstanceObject::cast(
    1698             :             dispatch_tables->get(i + kDispatchTableInstanceOffset)),
    1699             :         isolate);
    1700         276 :     CopyTableEntriesImpl(target_instance, dst, src, count, copy_backward);
    1701             :   }
    1702             : 
    1703             :   // Copy the function entries.
    1704             :   auto dst_table = handle(
    1705             :       WasmTableObject::cast(instance->tables()->get(table_dst_index)), isolate);
    1706             :   auto src_table = handle(
    1707             :       WasmTableObject::cast(instance->tables()->get(table_src_index)), isolate);
    1708         252 :   if (copy_backward) {
    1709         252 :     for (uint32_t i = count; i > 0; i--) {
    1710         432 :       dst_table->elements()->set(dst + i - 1,
    1711         216 :                                  src_table->elements()->get(src + i - 1));
    1712             :     }
    1713             :   } else {
    1714        1112 :     for (uint32_t i = 0; i < count; i++) {
    1715        1344 :       dst_table->elements()->set(dst + i, src_table->elements()->get(src + i));
    1716             :     }
    1717             :   }
    1718             :   return ok;
    1719             : }
    1720             : 
    1721             : // static
    1722         336 : bool WasmInstanceObject::InitTableEntries(Isolate* isolate,
    1723             :                                           Handle<WasmInstanceObject> instance,
    1724             :                                           uint32_t table_index,
    1725             :                                           uint32_t segment_index, uint32_t dst,
    1726             :                                           uint32_t src, uint32_t count) {
    1727             :   // Note that this implementation just calls through to module instantiation.
    1728             :   // This is intentional, so that the runtime only depends on the object
    1729             :   // methods, and not the module instantiation logic.
    1730             :   return wasm::LoadElemSegment(isolate, instance, table_index, segment_index,
    1731         336 :                                dst, src, count);
    1732             : }
    1733             : 
    1734      238153 : MaybeHandle<WasmExportedFunction> WasmInstanceObject::GetWasmExportedFunction(
    1735             :     Isolate* isolate, Handle<WasmInstanceObject> instance, int index) {
    1736             :   MaybeHandle<WasmExportedFunction> result;
    1737      238153 :   if (instance->has_wasm_exported_functions()) {
    1738             :     Object val = instance->wasm_exported_functions()->get(index);
    1739      212897 :     if (!val->IsUndefined(isolate)) {
    1740             :       result = Handle<WasmExportedFunction>(WasmExportedFunction::cast(val),
    1741             :                                             isolate);
    1742             :     }
    1743             :   }
    1744      238153 :   return result;
    1745             : }
    1746             : 
    1747      334717 : void WasmInstanceObject::SetWasmExportedFunction(
    1748             :     Isolate* isolate, Handle<WasmInstanceObject> instance, int index,
    1749             :     Handle<WasmExportedFunction> val) {
    1750             :   Handle<FixedArray> functions;
    1751      334717 :   if (!instance->has_wasm_exported_functions()) {
    1752             :     // lazily-allocate the wasm exported functions.
    1753             :     functions = isolate->factory()->NewFixedArray(
    1754      130564 :         static_cast<int>(instance->module()->functions.size()));
    1755      130564 :     instance->set_wasm_exported_functions(*functions);
    1756             :   } else {
    1757             :     functions =
    1758             :         Handle<FixedArray>(instance->wasm_exported_functions(), isolate);
    1759             :   }
    1760      669432 :   functions->set(index, *val);
    1761      334716 : }
    1762             : 
    1763             : // static
    1764          96 : Handle<WasmExceptionObject> WasmExceptionObject::New(
    1765             :     Isolate* isolate, const wasm::FunctionSig* sig,
    1766             :     Handle<HeapObject> exception_tag) {
    1767             :   Handle<JSFunction> exception_cons(
    1768         288 :       isolate->native_context()->wasm_exception_constructor(), isolate);
    1769             :   Handle<JSObject> exception_object =
    1770          96 :       isolate->factory()->NewJSObject(exception_cons, AllocationType::kOld);
    1771             :   Handle<WasmExceptionObject> exception =
    1772             :       Handle<WasmExceptionObject>::cast(exception_object);
    1773             : 
    1774             :   // Serialize the signature.
    1775             :   DCHECK_EQ(0, sig->return_count());
    1776             :   DCHECK_LE(sig->parameter_count(), std::numeric_limits<int>::max());
    1777          96 :   int sig_size = static_cast<int>(sig->parameter_count());
    1778             :   Handle<PodArray<wasm::ValueType>> serialized_sig =
    1779             :       PodArray<wasm::ValueType>::New(isolate, sig_size, AllocationType::kOld);
    1780             :   int index = 0;  // Index into the {PodArray} above.
    1781         112 :   for (wasm::ValueType param : sig->parameters()) {
    1782           8 :     serialized_sig->set(index++, param);
    1783             :   }
    1784          96 :   exception->set_serialized_signature(*serialized_sig);
    1785          96 :   exception->set_exception_tag(*exception_tag);
    1786             : 
    1787          96 :   return exception;
    1788             : }
    1789             : 
    1790          56 : bool WasmExceptionObject::IsSignatureEqual(const wasm::FunctionSig* sig) {
    1791             :   DCHECK_EQ(0, sig->return_count());
    1792             :   DCHECK_LE(sig->parameter_count(), std::numeric_limits<int>::max());
    1793          56 :   int sig_size = static_cast<int>(sig->parameter_count());
    1794          56 :   if (sig_size != serialized_signature()->length()) return false;
    1795          48 :   for (int index = 0; index < sig_size; ++index) {
    1796           0 :     if (sig->GetParam(index) != serialized_signature()->get(index)) {
    1797             :       return false;
    1798             :     }
    1799             :   }
    1800             :   return true;
    1801             : }
    1802             : 
    1803             : // static
    1804         604 : Handle<JSReceiver> WasmExceptionPackage::New(
    1805             :     Isolate* isolate, Handle<WasmExceptionTag> exception_tag, int size) {
    1806             :   Handle<Object> exception = isolate->factory()->NewWasmRuntimeError(
    1807         604 :       MessageTemplate::kWasmExceptionError);
    1808        1208 :   CHECK(!Object::SetProperty(isolate, exception,
    1809             :                              isolate->factory()->wasm_exception_tag_symbol(),
    1810             :                              exception_tag, StoreOrigin::kMaybeKeyed,
    1811             :                              Just(ShouldThrow::kThrowOnError))
    1812             :              .is_null());
    1813         604 :   Handle<FixedArray> values = isolate->factory()->NewFixedArray(size);
    1814        1208 :   CHECK(!Object::SetProperty(isolate, exception,
    1815             :                              isolate->factory()->wasm_exception_values_symbol(),
    1816             :                              values, StoreOrigin::kMaybeKeyed,
    1817             :                              Just(ShouldThrow::kThrowOnError))
    1818             :              .is_null());
    1819         604 :   return Handle<JSReceiver>::cast(exception);
    1820             : }
    1821             : 
    1822             : // static
    1823        1312 : Handle<Object> WasmExceptionPackage::GetExceptionTag(
    1824             :     Isolate* isolate, Handle<Object> exception_object) {
    1825        1312 :   if (exception_object->IsJSReceiver()) {
    1826        1216 :     Handle<JSReceiver> exception = Handle<JSReceiver>::cast(exception_object);
    1827             :     Handle<Object> tag;
    1828        3648 :     if (JSReceiver::GetProperty(isolate, exception,
    1829        1216 :                                 isolate->factory()->wasm_exception_tag_symbol())
    1830             :             .ToHandle(&tag)) {
    1831        1216 :       return tag;
    1832             :     }
    1833             :   }
    1834          96 :   return ReadOnlyRoots(isolate).undefined_value_handle();
    1835             : }
    1836             : 
    1837             : // static
    1838        2372 : Handle<Object> WasmExceptionPackage::GetExceptionValues(
    1839             :     Isolate* isolate, Handle<Object> exception_object) {
    1840        2372 :   if (exception_object->IsJSReceiver()) {
    1841        2372 :     Handle<JSReceiver> exception = Handle<JSReceiver>::cast(exception_object);
    1842             :     Handle<Object> values;
    1843        7116 :     if (JSReceiver::GetProperty(
    1844             :             isolate, exception,
    1845        2372 :             isolate->factory()->wasm_exception_values_symbol())
    1846             :             .ToHandle(&values)) {
    1847             :       DCHECK(values->IsFixedArray());
    1848        2372 :       return values;
    1849             :     }
    1850             :   }
    1851           0 :   return ReadOnlyRoots(isolate).undefined_value_handle();
    1852             : }
    1853             : 
    1854             : #ifdef DEBUG
    1855             : 
    1856             : namespace {
    1857             : 
    1858             : constexpr uint32_t kBytesPerExceptionValuesArrayElement = 2;
    1859             : 
    1860             : size_t ComputeEncodedElementSize(wasm::ValueType type) {
    1861             :   size_t byte_size =
    1862             :       static_cast<size_t>(wasm::ValueTypes::ElementSizeInBytes(type));
    1863             :   DCHECK_EQ(byte_size % kBytesPerExceptionValuesArrayElement, 0);
    1864             :   DCHECK_LE(1, byte_size / kBytesPerExceptionValuesArrayElement);
    1865             :   return byte_size / kBytesPerExceptionValuesArrayElement;
    1866             : }
    1867             : 
    1868             : }  // namespace
    1869             : 
    1870             : #endif  // DEBUG
    1871             : 
    1872             : // static
    1873        1155 : uint32_t WasmExceptionPackage::GetEncodedSize(
    1874             :     const wasm::WasmException* exception) {
    1875        1155 :   const wasm::WasmExceptionSig* sig = exception->sig;
    1876             :   uint32_t encoded_size = 0;
    1877        2583 :   for (size_t i = 0; i < sig->parameter_count(); ++i) {
    1878         714 :     switch (sig->GetParam(i)) {
    1879             :       case wasm::kWasmI32:
    1880             :       case wasm::kWasmF32:
    1881             :         DCHECK_EQ(2, ComputeEncodedElementSize(sig->GetParam(i)));
    1882         440 :         encoded_size += 2;
    1883         440 :         break;
    1884             :       case wasm::kWasmI64:
    1885             :       case wasm::kWasmF64:
    1886             :         DCHECK_EQ(4, ComputeEncodedElementSize(sig->GetParam(i)));
    1887         116 :         encoded_size += 4;
    1888         116 :         break;
    1889             :       case wasm::kWasmS128:
    1890             :         DCHECK_EQ(8, ComputeEncodedElementSize(sig->GetParam(i)));
    1891          36 :         encoded_size += 8;
    1892          36 :         break;
    1893             :       case wasm::kWasmAnyRef:
    1894         122 :         encoded_size += 1;
    1895         122 :         break;
    1896             :       default:
    1897           0 :         UNREACHABLE();
    1898             :     }
    1899             :   }
    1900        1155 :   return encoded_size;
    1901             : }
    1902             : 
    1903      253682 : bool WasmExportedFunction::IsWasmExportedFunction(Object object) {
    1904      253682 :   if (!object->IsJSFunction()) return false;
    1905             :   JSFunction js_function = JSFunction::cast(object);
    1906      242558 :   if (Code::JS_TO_WASM_FUNCTION != js_function->code()->kind()) return false;
    1907             :   DCHECK(js_function->shared()->HasWasmExportedFunctionData());
    1908      222568 :   return true;
    1909             : }
    1910             : 
    1911      326432 : WasmInstanceObject WasmExportedFunction::instance() {
    1912      652864 :   return shared()->wasm_exported_function_data()->instance();
    1913             : }
    1914             : 
    1915      217457 : int WasmExportedFunction::function_index() {
    1916      434914 :   return shared()->wasm_exported_function_data()->function_index();
    1917             : }
    1918             : 
    1919      237115 : Handle<WasmExportedFunction> WasmExportedFunction::New(
    1920             :     Isolate* isolate, Handle<WasmInstanceObject> instance,
    1921             :     MaybeHandle<String> maybe_name, int func_index, int arity,
    1922             :     Handle<Code> export_wrapper) {
    1923             :   DCHECK_EQ(Code::JS_TO_WASM_FUNCTION, export_wrapper->kind());
    1924      237116 :   int num_imported_functions = instance->module()->num_imported_functions;
    1925             :   int jump_table_offset = -1;
    1926      237116 :   if (func_index >= num_imported_functions) {
    1927             :     ptrdiff_t jump_table_diff =
    1928      710229 :         instance->module_object()->native_module()->jump_table_offset(
    1929             :             func_index);
    1930             :     DCHECK(jump_table_diff >= 0 && jump_table_diff <= INT_MAX);
    1931      236741 :     jump_table_offset = static_cast<int>(jump_table_diff);
    1932             :   }
    1933             :   Handle<WasmExportedFunctionData> function_data =
    1934             :       Handle<WasmExportedFunctionData>::cast(isolate->factory()->NewStruct(
    1935      237113 :           WASM_EXPORTED_FUNCTION_DATA_TYPE, AllocationType::kOld));
    1936      237116 :   function_data->set_wrapper_code(*export_wrapper);
    1937      237116 :   function_data->set_instance(*instance);
    1938             :   function_data->set_jump_table_offset(jump_table_offset);
    1939             :   function_data->set_function_index(func_index);
    1940             :   Handle<String> name;
    1941      237116 :   if (!maybe_name.ToHandle(&name)) {
    1942             :     EmbeddedVector<char, 16> buffer;
    1943      227994 :     int length = SNPrintF(buffer, "%d", func_index);
    1944             :     name = isolate->factory()
    1945      455988 :                ->NewStringFromOneByte(
    1946      227994 :                    Vector<uint8_t>::cast(buffer.SubVector(0, length)))
    1947      227994 :                .ToHandleChecked();
    1948             :   }
    1949             :   NewFunctionArgs args = NewFunctionArgs::ForWasm(
    1950      237116 :       name, function_data, isolate->sloppy_function_without_prototype_map());
    1951      237115 :   Handle<JSFunction> js_function = isolate->factory()->NewFunction(args);
    1952             :   // According to the spec, exported functions should not have a [[Construct]]
    1953             :   // method.
    1954             :   DCHECK(!js_function->IsConstructor());
    1955             :   js_function->shared()->set_length(arity);
    1956             :   js_function->shared()->set_internal_formal_parameter_count(arity);
    1957      237114 :   return Handle<WasmExportedFunction>::cast(js_function);
    1958             : }
    1959             : 
    1960      107064 : Address WasmExportedFunction::GetWasmCallTarget() {
    1961      107064 :   return instance()->GetCallTarget(function_index());
    1962             : }
    1963             : 
    1964           0 : wasm::FunctionSig* WasmExportedFunction::sig() {
    1965           0 :   return instance()->module()->functions[function_index()].sig;
    1966             : }
    1967             : 
    1968         692 : Handle<WasmExceptionTag> WasmExceptionTag::New(Isolate* isolate, int index) {
    1969             :   Handle<WasmExceptionTag> result =
    1970             :       Handle<WasmExceptionTag>::cast(isolate->factory()->NewStruct(
    1971         692 :           WASM_EXCEPTION_TAG_TYPE, AllocationType::kOld));
    1972             :   result->set_index(index);
    1973         692 :   return result;
    1974             : }
    1975             : 
    1976        2469 : Handle<AsmWasmData> AsmWasmData::New(
    1977             :     Isolate* isolate, std::shared_ptr<wasm::NativeModule> native_module,
    1978             :     Handle<FixedArray> export_wrappers, Handle<ByteArray> asm_js_offset_table,
    1979             :     Handle<HeapNumber> uses_bitset) {
    1980             :   const WasmModule* module = native_module->module();
    1981             :   size_t memory_estimate =
    1982        2469 :       wasm::WasmCodeManager::EstimateNativeModuleCodeSize(module) +
    1983        2469 :       wasm::WasmCodeManager::EstimateNativeModuleNonCodeSize(module);
    1984             :   Handle<Managed<wasm::NativeModule>> managed_native_module =
    1985             :       Managed<wasm::NativeModule>::FromSharedPtr(isolate, memory_estimate,
    1986        2469 :                                                  std::move(native_module));
    1987             :   Handle<AsmWasmData> result = Handle<AsmWasmData>::cast(
    1988        2469 :       isolate->factory()->NewStruct(ASM_WASM_DATA_TYPE, AllocationType::kOld));
    1989        2469 :   result->set_managed_native_module(*managed_native_module);
    1990        2469 :   result->set_export_wrappers(*export_wrappers);
    1991        2469 :   result->set_asm_js_offset_table(*asm_js_offset_table);
    1992        2469 :   result->set_uses_bitset(*uses_bitset);
    1993        2469 :   return result;
    1994             : }
    1995             : 
    1996             : #undef TRACE
    1997             : #undef TRACE_IFT
    1998             : }  // namespace internal
    1999      122004 : }  // namespace v8

Generated by: LCOV version 1.10