LCOV - code coverage report
Current view: top level - src/wasm - wasm-objects.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 602 634 95.0 %
Date: 2019-01-20 Functions: 72 74 97.3 %

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

Generated by: LCOV version 1.10