5 #include "src/wasm/wasm-objects.h" 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/trap-handler/trap-handler.h" 18 #include "src/wasm/jump-table-assembler.h" 19 #include "src/wasm/module-compiler.h" 20 #include "src/wasm/module-decoder.h" 21 #include "src/wasm/wasm-code-manager.h" 22 #include "src/wasm/wasm-engine.h" 23 #include "src/wasm/wasm-limits.h" 24 #include "src/wasm/wasm-memory.h" 25 #include "src/wasm/wasm-module.h" 26 #include "src/wasm/wasm-objects-inl.h" 27 #include "src/wasm/wasm-text.h" 31 if (FLAG_trace_wasm_instances) PrintF(__VA_ARGS__); \ 34 #define TRACE_IFT(...) \ 36 if (false) PrintF(__VA_ARGS__); \ 43 using WasmFunction = wasm::WasmFunction;
44 using WasmModule = wasm::WasmModule;
54 class WasmInstanceNativeAllocations {
58 #define SET(instance, field, value) \ 62 instance->set_##field(v); \ 66 WasmInstanceNativeAllocations(Handle<WasmInstanceObject> instance,
67 size_t num_imported_functions,
68 size_t num_imported_mutable_globals) {
69 SET(instance, imported_function_targets,
70 reinterpret_cast<Address*>(
71 calloc(num_imported_functions,
sizeof(Address))));
72 SET(instance, imported_mutable_globals,
73 reinterpret_cast<Address*>(
74 calloc(num_imported_mutable_globals,
sizeof(Address))));
76 ~WasmInstanceNativeAllocations() {
77 ::free(indirect_function_table_sig_ids_);
78 indirect_function_table_sig_ids_ =
nullptr;
79 ::free(indirect_function_table_targets_);
80 indirect_function_table_targets_ =
nullptr;
81 ::free(imported_function_targets_);
82 imported_function_targets_ =
nullptr;
83 ::free(imported_mutable_globals_);
84 imported_mutable_globals_ =
nullptr;
87 void resize_indirect_function_table(Isolate* isolate,
88 Handle<WasmInstanceObject> instance,
90 uint32_t old_size = instance->indirect_function_table_size();
91 void* new_sig_ids =
nullptr;
92 void* new_targets =
nullptr;
93 Handle<FixedArray> new_refs;
94 if (indirect_function_table_sig_ids_) {
96 new_sig_ids = realloc(indirect_function_table_sig_ids_,
99 realloc(indirect_function_table_targets_, new_size *
sizeof(Address));
101 Handle<FixedArray> old(instance->indirect_function_table_refs(), isolate);
102 new_refs = isolate->factory()->CopyFixedArrayAndGrow(
103 old, static_cast<int>(new_size - old_size));
106 new_sig_ids = malloc(new_size *
sizeof(
uint32_t));
107 new_targets = malloc(new_size *
sizeof(Address));
108 new_refs = isolate->factory()->NewFixedArray(static_cast<int>(new_size));
111 instance->set_indirect_function_table_size(new_size);
112 SET(instance, indirect_function_table_sig_ids,
113 reinterpret_cast<uint32_t*>(new_sig_ids));
114 SET(instance, indirect_function_table_targets,
115 reinterpret_cast<Address*>(new_targets));
117 instance->set_indirect_function_table_refs(*new_refs);
118 for (
uint32_t j = old_size; j < new_size; j++) {
119 IndirectFunctionTableEntry(instance, static_cast<int>(j)).clear();
122 uint32_t* indirect_function_table_sig_ids_ =
nullptr;
123 Address* indirect_function_table_targets_ =
nullptr;
124 Address* imported_function_targets_ =
nullptr;
125 Address* imported_mutable_globals_ =
nullptr;
129 size_t EstimateNativeAllocationsSize(
const WasmModule* module) {
130 size_t estimate =
sizeof(WasmInstanceNativeAllocations) +
131 (1 * kPointerSize * module->num_imported_mutable_globals) +
132 (2 * kPointerSize * module->num_imported_functions);
133 for (
auto& table : module->tables) {
134 estimate += 3 * kPointerSize * table.initial_size;
139 WasmInstanceNativeAllocations* GetNativeAllocations(
140 WasmInstanceObject* instance) {
141 return reinterpret_cast<Managed<WasmInstanceNativeAllocations>*
>(
142 instance->managed_native_allocations())
147 bool IsBreakablePosition(wasm::NativeModule* native_module,
int func_index,
148 int offset_in_func) {
149 AccountingAllocator alloc;
150 Zone tmp(&alloc, ZONE_NAME);
151 wasm::BodyLocalDecls locals(&tmp);
152 const byte* module_start = native_module->wire_bytes().start();
153 const WasmFunction& func = native_module->module()->functions[func_index];
154 wasm::BytecodeIterator iterator(module_start + func.code.offset(),
155 module_start + func.code.end_offset(),
157 DCHECK_LT(0, locals.encoded_size);
158 for (
uint32_t offset : iterator.offsets()) {
159 if (offset > static_cast<uint32_t>(offset_in_func))
break;
160 if (offset == static_cast<uint32_t>(offset_in_func))
return true;
166 enum DispatchTableElements :
int {
167 kDispatchTableInstanceOffset,
168 kDispatchTableIndexOffset,
169 kDispatchTableFunctionTableOffset,
171 kDispatchTableNumElements
177 Handle<WasmModuleObject> WasmModuleObject::New(
178 Isolate* isolate,
const wasm::WasmFeatures& enabled,
179 std::shared_ptr<const wasm::WasmModule> shared_module,
180 OwnedVector<const uint8_t> wire_bytes, Handle<Script> script,
181 Handle<ByteArray> asm_js_offset_table) {
183 size_t code_size_estimate =
184 wasm::WasmCodeManager::EstimateNativeModuleCodeSize(shared_module.get());
185 auto native_module = isolate->wasm_engine()->code_manager()->NewNativeModule(
186 isolate, enabled, code_size_estimate,
187 wasm::NativeModule::kCanAllocateMoreMemory, std::move(shared_module));
188 native_module->SetWireBytes(std::move(wire_bytes));
189 native_module->SetRuntimeStubs(isolate);
192 Handle<WasmModuleObject> module_object =
193 New(isolate, std::move(native_module), script, code_size_estimate);
194 if (!asm_js_offset_table.is_null()) {
195 module_object->set_asm_js_offset_table(*asm_js_offset_table);
197 return module_object;
201 Handle<WasmModuleObject> WasmModuleObject::New(
202 Isolate* isolate, std::shared_ptr<wasm::NativeModule> native_module,
203 Handle<Script> script,
size_t code_size_estimate) {
204 const WasmModule* module = native_module->module();
205 int export_wrapper_size =
static_cast<int>(module->num_exported_functions);
206 Handle<FixedArray> export_wrappers =
207 isolate->factory()->NewFixedArray(export_wrapper_size, TENURED);
208 return New(isolate, std::move(native_module), script, export_wrappers,
213 Handle<WasmModuleObject> WasmModuleObject::New(
214 Isolate* isolate, std::shared_ptr<wasm::NativeModule> native_module,
215 Handle<Script> script, Handle<FixedArray> export_wrappers,
216 size_t code_size_estimate) {
217 const WasmModule* module = native_module->module();
221 size_t memory_estimate =
223 wasm::WasmCodeManager::EstimateNativeModuleNonCodeSize(module);
224 Handle<Managed<wasm::NativeModule>> managed_native_module =
225 Managed<wasm::NativeModule>::FromSharedPtr(isolate, memory_estimate,
226 std::move(native_module));
228 Handle<WasmModuleObject> module_object = Handle<WasmModuleObject>::cast(
229 isolate->factory()->NewJSObject(isolate->wasm_module_constructor()));
230 module_object->set_export_wrappers(*export_wrappers);
231 if (script->type() == Script::TYPE_WASM) {
232 script->set_wasm_module_object(*module_object);
234 module_object->set_script(*script);
235 module_object->set_weak_instance_list(
236 ReadOnlyRoots(isolate).empty_weak_array_list());
237 module_object->set_managed_native_module(*managed_native_module);
238 return module_object;
241 bool WasmModuleObject::SetBreakPoint(Handle<WasmModuleObject> module_object,
243 Handle<BreakPoint> break_point) {
244 Isolate* isolate = module_object->GetIsolate();
247 int func_index = module_object->GetContainingFunction(*position);
248 if (func_index < 0)
return false;
249 const WasmFunction& func = module_object->module()->functions[func_index];
250 int offset_in_func = *position - func.code.offset();
254 DCHECK(IsBreakablePosition(module_object->native_module(), func_index,
258 WasmModuleObject::AddBreakpoint(module_object, *position, break_point);
262 Handle<WeakArrayList> weak_instance_list(module_object->weak_instance_list(),
264 for (
int i = 0;
i < weak_instance_list->length(); ++
i) {
265 MaybeObject maybe_instance = weak_instance_list->Get(
i);
266 if (maybe_instance->IsWeak()) {
267 Handle<WasmInstanceObject> instance(
268 WasmInstanceObject::cast(maybe_instance->GetHeapObjectAssumeWeak()),
270 Handle<WasmDebugInfo> debug_info =
271 WasmInstanceObject::GetOrCreateDebugInfo(instance);
272 WasmDebugInfo::SetBreakpoint(debug_info, func_index, offset_in_func);
281 int GetBreakpointPos(Isolate* isolate, Object* break_point_info_or_undef) {
282 if (break_point_info_or_undef->IsUndefined(isolate))
return kMaxInt;
283 return BreakPointInfo::cast(break_point_info_or_undef)->source_position();
286 int FindBreakpointInfoInsertPos(Isolate* isolate,
287 Handle<FixedArray> breakpoint_infos,
291 DCHECK_LT(0, position);
294 int right = breakpoint_infos->length();
295 while (right - left > 1) {
296 int mid = left + (right - left) / 2;
297 Object* mid_obj = breakpoint_infos->get(mid);
298 if (GetBreakpointPos(isolate, mid_obj) <= position) {
305 int left_pos = GetBreakpointPos(isolate, breakpoint_infos->get(left));
306 return left_pos < position ? left + 1 : left;
311 void WasmModuleObject::AddBreakpoint(Handle<WasmModuleObject> module_object,
313 Handle<BreakPoint> break_point) {
314 Isolate* isolate = module_object->GetIsolate();
315 Handle<FixedArray> breakpoint_infos;
316 if (module_object->has_breakpoint_infos()) {
317 breakpoint_infos = handle(module_object->breakpoint_infos(), isolate);
319 breakpoint_infos = isolate->factory()->NewFixedArray(4, TENURED);
320 module_object->set_breakpoint_infos(*breakpoint_infos);
324 FindBreakpointInfoInsertPos(isolate, breakpoint_infos, position);
328 if (insert_pos < breakpoint_infos->length() &&
329 GetBreakpointPos(isolate, breakpoint_infos->get(insert_pos)) ==
331 Handle<BreakPointInfo> old_info(
332 BreakPointInfo::cast(breakpoint_infos->get(insert_pos)), isolate);
333 BreakPointInfo::SetBreakPoint(isolate, old_info, break_point);
338 bool need_realloc = !breakpoint_infos->get(breakpoint_infos->length() - 1)
339 ->IsUndefined(isolate);
340 Handle<FixedArray> new_breakpoint_infos = breakpoint_infos;
342 new_breakpoint_infos = isolate->factory()->NewFixedArray(
343 2 * breakpoint_infos->length(), TENURED);
344 module_object->set_breakpoint_infos(*new_breakpoint_infos);
346 for (
int i = 0;
i < insert_pos; ++
i)
347 new_breakpoint_infos->set(
i, breakpoint_infos->get(
i));
351 for (
int i = breakpoint_infos->length() - 1;
i >= insert_pos; --
i) {
352 Object* entry = breakpoint_infos->get(
i);
353 if (entry->IsUndefined(isolate))
continue;
354 new_breakpoint_infos->set(
i + 1, entry);
358 Handle<BreakPointInfo> breakpoint_info =
359 isolate->factory()->NewBreakPointInfo(position);
360 BreakPointInfo::SetBreakPoint(isolate, breakpoint_info, break_point);
363 new_breakpoint_infos->set(insert_pos, *breakpoint_info);
366 void WasmModuleObject::SetBreakpointsOnNewInstance(
367 Handle<WasmModuleObject> module_object,
368 Handle<WasmInstanceObject> instance) {
369 if (!module_object->has_breakpoint_infos())
return;
370 Isolate* isolate = module_object->GetIsolate();
371 Handle<WasmDebugInfo> debug_info =
372 WasmInstanceObject::GetOrCreateDebugInfo(instance);
374 Handle<FixedArray> breakpoint_infos(module_object->breakpoint_infos(),
377 DCHECK_LT(0, breakpoint_infos->length());
379 for (
int i = 0, e = breakpoint_infos->length();
i < e; ++
i) {
380 Handle<Object> obj(breakpoint_infos->get(
i), isolate);
381 if (obj->IsUndefined(isolate)) {
383 DCHECK(breakpoint_infos->get(
i)->IsUndefined(isolate));
387 Handle<BreakPointInfo> breakpoint_info = Handle<BreakPointInfo>::cast(obj);
388 int position = breakpoint_info->source_position();
391 int func_index = module_object->GetContainingFunction(position);
392 DCHECK_LE(0, func_index);
393 const WasmFunction& func = module_object->module()->functions[func_index];
394 int offset_in_func = position - func.code.offset();
395 WasmDebugInfo::SetBreakpoint(debug_info, func_index, offset_in_func);
401 enum AsmJsOffsetTableEntryLayout {
404 kOTENumberConvPosition,
408 Handle<ByteArray> GetDecodedAsmJsOffsetTable(
409 Handle<WasmModuleObject> module_object, Isolate* isolate) {
410 DCHECK(module_object->is_asm_js());
411 Handle<ByteArray> offset_table(module_object->asm_js_offset_table(), isolate);
415 enum AsmJsTableType :
int { Encoded = 0, Decoded = 1 };
416 int table_type = offset_table->get(offset_table->length() - 1);
417 DCHECK(table_type == Encoded || table_type == Decoded);
418 if (table_type == Decoded)
return offset_table;
420 wasm::AsmJsOffsets asm_offsets;
422 DisallowHeapAllocation no_gc;
423 byte* bytes_start = offset_table->GetDataStartAddress();
424 byte* bytes_end =
reinterpret_cast<byte*
>(
425 reinterpret_cast<Address
>(bytes_start) + offset_table->length() - 1);
426 asm_offsets = wasm::DecodeAsmJsOffsets(bytes_start, bytes_end).value();
429 DCHECK_GE(kMaxInt, asm_offsets.size());
430 int num_functions =
static_cast<int>(asm_offsets.size());
431 int num_imported_functions =
432 static_cast<int>(module_object->module()->num_imported_functions);
433 DCHECK_EQ(module_object->module()->functions.size(),
434 static_cast<size_t>(num_functions) + num_imported_functions);
436 for (
int func = 0; func < num_functions; ++func) {
437 size_t new_size = asm_offsets[func].size();
438 DCHECK_LE(new_size, static_cast<size_t>(kMaxInt) - num_entries);
439 num_entries +=
static_cast<int>(new_size);
443 1 + static_cast<uint64_t>(num_entries) * kOTESize * kIntSize);
444 int total_size = 1 + num_entries * kOTESize * kIntSize;
445 Handle<ByteArray> decoded_table =
446 isolate->factory()->NewByteArray(total_size, TENURED);
447 decoded_table->set(total_size - 1, AsmJsTableType::Decoded);
448 module_object->set_asm_js_offset_table(*decoded_table);
451 const std::vector<WasmFunction>& wasm_funs =
452 module_object->module()->functions;
453 for (
int func = 0; func < num_functions; ++func) {
454 std::vector<wasm::AsmJsOffsetEntry>& func_asm_offsets = asm_offsets[func];
455 if (func_asm_offsets.empty())
continue;
456 int func_offset = wasm_funs[num_imported_functions + func].code.offset();
457 for (wasm::AsmJsOffsetEntry& e : func_asm_offsets) {
459 DCHECK_IMPLIES(idx > 0, func_offset + e.byte_offset >
460 decoded_table->get_int(idx - kOTESize));
461 decoded_table->set_int(idx + kOTEByteOffset, func_offset + e.byte_offset);
462 decoded_table->set_int(idx + kOTECallPosition, e.source_position_call);
463 decoded_table->set_int(idx + kOTENumberConvPosition,
464 e.source_position_number_conversion);
468 DCHECK_EQ(total_size, idx * kIntSize + 1);
469 return decoded_table;
474 int WasmModuleObject::GetSourcePosition(Handle<WasmModuleObject> module_object,
477 bool is_at_number_conversion) {
478 Isolate* isolate = module_object->GetIsolate();
479 const WasmModule* module = module_object->module();
481 if (module->origin != wasm::kAsmJsOrigin) {
484 return byte_offset + module_object->GetFunctionOffset(func_index);
488 Handle<ByteArray> offset_table =
489 GetDecodedAsmJsOffsetTable(module_object, isolate);
491 DCHECK_LT(func_index, module->functions.size());
492 uint32_t func_code_offset = module->functions[func_index].code.offset();
493 uint32_t total_offset = func_code_offset + byte_offset;
497 int right = offset_table->length() / kIntSize / kOTESize;
498 DCHECK_LT(left, right);
499 while (right - left > 1) {
500 int mid = left + (right - left) / 2;
501 int mid_entry = offset_table->get_int(kOTESize * mid);
502 DCHECK_GE(kMaxInt, mid_entry);
503 if (static_cast<uint32_t>(mid_entry) <= total_offset) {
511 DCHECK_EQ(total_offset, offset_table->get_int(kOTESize * left));
512 int idx = is_at_number_conversion ? kOTENumberConvPosition : kOTECallPosition;
513 return offset_table->get_int(kOTESize * left + idx);
518 DisallowHeapAllocation no_gc;
520 if (func_index < 0 ||
521 static_cast<uint32_t>(func_index) >= module()->functions.size())
524 Vector<const byte> wire_bytes = native_module()->wire_bytes();
526 std::ostringstream disassembly_os;
527 v8::debug::WasmDisassembly::OffsetTable offset_table;
529 PrintWasmText(module(), wire_bytes, static_cast<uint32_t>(func_index),
530 disassembly_os, &offset_table);
532 return {disassembly_os.str(), std::move(offset_table)};
535 bool WasmModuleObject::GetPossibleBreakpoints(
537 std::vector<v8::debug::BreakLocation>* locations) {
538 DisallowHeapAllocation no_gc;
540 const std::vector<WasmFunction>& functions = module()->functions;
541 if (start.GetLineNumber() < 0 || start.GetColumnNumber() < 0 ||
543 (end.GetLineNumber() < 0 || end.GetColumnNumber() < 0)))
549 uint32_t start_func_index = start.GetLineNumber();
550 if (start_func_index >= functions.size())
return false;
551 int start_func_len = functions[start_func_index].code.length();
552 if (start.GetColumnNumber() > start_func_len)
return false;
554 functions[start_func_index].code.offset() + start.GetColumnNumber();
559 end_func_index =
static_cast<uint32_t>(functions.size() - 1);
560 end_offset = functions[end_func_index].code.end_offset();
563 end_func_index =
static_cast<uint32_t>(end.GetLineNumber());
568 if (end.GetColumnNumber() == 0 && end_func_index > 0) {
570 end_offset = functions[end_func_index].code.end_offset();
572 if (end_func_index >= functions.size())
return false;
574 functions[end_func_index].code.offset() + end.GetColumnNumber();
575 if (end_offset > functions[end_func_index].code.end_offset())
580 AccountingAllocator alloc;
581 Zone tmp(&alloc, ZONE_NAME);
582 const byte* module_start = native_module()->wire_bytes().start();
584 for (
uint32_t func_idx = start_func_index; func_idx <= end_func_index;
586 const WasmFunction& func = functions[func_idx];
587 if (func.code.length() == 0)
continue;
589 wasm::BodyLocalDecls locals(&tmp);
590 wasm::BytecodeIterator iterator(module_start + func.code.offset(),
591 module_start + func.code.end_offset(),
593 DCHECK_LT(0u, locals.encoded_size);
594 for (
uint32_t offset : iterator.offsets()) {
595 uint32_t total_offset = func.code.offset() + offset;
596 if (total_offset >= end_offset) {
597 DCHECK_EQ(end_func_index, func_idx);
600 if (total_offset < start_offset)
continue;
601 locations->emplace_back(func_idx, offset, debug::kCommonBreakLocation);
607 MaybeHandle<FixedArray> WasmModuleObject::CheckBreakPoints(
608 Isolate* isolate, Handle<WasmModuleObject> module_object,
int position) {
609 if (!module_object->has_breakpoint_infos())
return {};
611 Handle<FixedArray> breakpoint_infos(module_object->breakpoint_infos(),
614 FindBreakpointInfoInsertPos(isolate, breakpoint_infos, position);
615 if (insert_pos >= breakpoint_infos->length())
return {};
617 Handle<Object> maybe_breakpoint_info(breakpoint_infos->get(insert_pos),
619 if (maybe_breakpoint_info->IsUndefined(isolate))
return {};
620 Handle<BreakPointInfo> breakpoint_info =
621 Handle<BreakPointInfo>::cast(maybe_breakpoint_info);
622 if (breakpoint_info->source_position() != position)
return {};
626 Handle<Object> break_points(breakpoint_info->break_points(), isolate);
627 if (break_points->IsFixedArray()) {
628 return Handle<FixedArray>::cast(break_points);
630 Handle<FixedArray> break_points_hit = isolate->factory()->NewFixedArray(1);
631 break_points_hit->set(0, *break_points);
632 return break_points_hit;
635 MaybeHandle<String> WasmModuleObject::ExtractUtf8StringFromModuleBytes(
636 Isolate* isolate, Handle<WasmModuleObject> module_object,
637 wasm::WireBytesRef ref) {
639 Vector<const uint8_t> wire_bytes =
640 module_object->native_module()->wire_bytes();
641 return ExtractUtf8StringFromModuleBytes(isolate, wire_bytes, ref);
644 MaybeHandle<String> WasmModuleObject::ExtractUtf8StringFromModuleBytes(
645 Isolate* isolate, Vector<const uint8_t> wire_bytes,
646 wasm::WireBytesRef ref) {
647 Vector<const uint8_t> name_vec = wire_bytes + ref.offset();
648 name_vec.Truncate(ref.length());
650 DCHECK(unibrow::Utf8::ValidateEncoding(name_vec.start(), name_vec.length()));
651 return isolate->factory()->NewStringFromUtf8(
652 Vector<const char>::cast(name_vec));
655 MaybeHandle<String> WasmModuleObject::GetModuleNameOrNull(
656 Isolate* isolate, Handle<WasmModuleObject> module_object) {
657 const WasmModule* module = module_object->module();
658 if (!module->name.is_set())
return {};
659 return ExtractUtf8StringFromModuleBytes(isolate, module_object, module->name);
662 MaybeHandle<String> WasmModuleObject::GetFunctionNameOrNull(
663 Isolate* isolate, Handle<WasmModuleObject> module_object,
665 DCHECK_LT(func_index, module_object->module()->functions.size());
666 wasm::WireBytesRef name = module_object->module()->LookupFunctionName(
667 wasm::ModuleWireBytes(module_object->native_module()->wire_bytes()),
669 if (!name.is_set())
return {};
670 return ExtractUtf8StringFromModuleBytes(isolate, module_object, name);
673 Handle<String> WasmModuleObject::GetFunctionName(
674 Isolate* isolate, Handle<WasmModuleObject> module_object,
676 MaybeHandle<String> name =
677 GetFunctionNameOrNull(isolate, module_object, func_index);
678 if (!name.is_null())
return name.ToHandleChecked();
679 EmbeddedVector<char, 32> buffer;
680 int length = SNPrintF(buffer,
"wasm-function[%u]", func_index);
681 return isolate->factory()
682 ->NewStringFromOneByte(Vector<uint8_t>::cast(buffer.SubVector(0, length)))
686 Vector<const uint8_t> WasmModuleObject::GetRawFunctionName(
688 DCHECK_GT(module()->functions.size(), func_index);
689 wasm::ModuleWireBytes wire_bytes(native_module()->wire_bytes());
690 wasm::WireBytesRef name_ref =
691 module()->LookupFunctionName(wire_bytes, func_index);
692 wasm::WasmName name = wire_bytes.GetNameOrNull(name_ref);
693 return Vector<const uint8_t>::cast(name);
696 int WasmModuleObject::GetFunctionOffset(
uint32_t func_index) {
697 const std::vector<WasmFunction>& functions = module()->functions;
698 if (static_cast<uint32_t>(func_index) >= functions.size())
return -1;
699 DCHECK_GE(kMaxInt, functions[func_index].code.offset());
700 return static_cast<int>(functions[func_index].code.offset());
703 int WasmModuleObject::GetContainingFunction(
uint32_t byte_offset) {
704 const std::vector<WasmFunction>& functions = module()->functions;
708 int right =
static_cast<int>(functions.size());
709 if (right == 0)
return false;
710 while (right - left > 1) {
711 int mid = left + (right - left) / 2;
712 if (functions[mid].code.offset() <= byte_offset) {
719 const WasmFunction& func = functions[left];
720 if (byte_offset < func.code.offset() ||
721 byte_offset >= func.code.end_offset()) {
728 bool WasmModuleObject::GetPositionInfo(
uint32_t position,
729 Script::PositionInfo* info) {
730 if (script()->source_mapping_url()->IsString()) {
731 if (module()->functions.size() == 0)
return false;
733 info->column = position;
734 info->line_start = module()->functions[0].code.offset();
735 info->line_end = module()->functions.back().code.end_offset();
738 int func_index = GetContainingFunction(position);
739 if (func_index < 0)
return false;
741 const WasmFunction&
function = module()->functions[func_index];
743 info->line = func_index;
744 info->column = position -
function.code.offset();
745 info->line_start =
function.code.offset();
746 info->line_end =
function.code.end_offset();
750 Handle<WasmTableObject> WasmTableObject::New(Isolate* isolate,
uint32_t initial,
752 Handle<FixedArray>* js_functions) {
753 Handle<JSFunction> table_ctor(
754 isolate->native_context()->wasm_table_constructor(), isolate);
755 auto table_obj = Handle<WasmTableObject>::cast(
756 isolate->factory()->NewJSObject(table_ctor));
758 *js_functions = isolate->factory()->NewFixedArray(initial);
759 Object* null = ReadOnlyRoots(isolate).null_value();
760 for (
int i = 0; i < static_cast<int>(initial); ++
i) {
761 (*js_functions)->set(
i, null);
763 table_obj->set_functions(**js_functions);
764 DCHECK_EQ(maximum, static_cast<int>(maximum));
765 Handle<Object> max = isolate->factory()->NewNumber(maximum);
766 table_obj->set_maximum_length(*max);
768 table_obj->set_dispatch_tables(ReadOnlyRoots(isolate).empty_fixed_array());
769 return Handle<WasmTableObject>::cast(table_obj);
772 void WasmTableObject::AddDispatchTable(Isolate* isolate,
773 Handle<WasmTableObject> table_obj,
774 Handle<WasmInstanceObject> instance,
776 Handle<FixedArray> dispatch_tables(table_obj->dispatch_tables(), isolate);
777 int old_length = dispatch_tables->length();
778 DCHECK_EQ(0, old_length % kDispatchTableNumElements);
780 if (instance.is_null())
return;
784 Handle<FixedArray> new_dispatch_tables =
785 isolate->factory()->CopyFixedArrayAndGrow(dispatch_tables,
786 kDispatchTableNumElements);
788 new_dispatch_tables->set(old_length + kDispatchTableInstanceOffset,
790 new_dispatch_tables->set(old_length + kDispatchTableIndexOffset,
791 Smi::FromInt(table_index));
793 table_obj->set_dispatch_tables(*new_dispatch_tables);
796 void WasmTableObject::Grow(Isolate* isolate,
uint32_t count) {
797 if (count == 0)
return;
799 Handle<FixedArray> dispatch_tables(this->dispatch_tables(), isolate);
800 DCHECK_EQ(0, dispatch_tables->length() % kDispatchTableNumElements);
801 uint32_t old_size = functions()->length();
809 for (
int i = 0;
i < dispatch_tables->length();
810 i += kDispatchTableNumElements) {
811 Handle<WasmInstanceObject> instance(
812 WasmInstanceObject::cast(dispatch_tables->get(
i)), isolate);
813 DCHECK_EQ(old_size, instance->indirect_function_table_size());
814 uint32_t new_size = old_size + count;
815 WasmInstanceObject::EnsureIndirectFunctionTableWithMinimumSize(instance,
820 void WasmTableObject::Set(Isolate* isolate, Handle<WasmTableObject> table,
821 int32_t table_index, Handle<JSFunction>
function) {
822 Handle<FixedArray> array(table->functions(), isolate);
823 if (
function.is_null()) {
824 ClearDispatchTables(isolate, table, table_index);
825 array->set(table_index, ReadOnlyRoots(isolate).null_value());
830 DCHECK(WasmExportedFunction::IsWasmExportedFunction(*
function));
831 auto exported_function = Handle<WasmExportedFunction>::cast(
function);
832 Handle<WasmInstanceObject> target_instance(exported_function->instance(),
834 int func_index = exported_function->function_index();
835 auto* wasm_function = &target_instance->module()->functions[func_index];
836 DCHECK_NOT_NULL(wasm_function);
837 DCHECK_NOT_NULL(wasm_function->sig);
838 UpdateDispatchTables(isolate, table, table_index, wasm_function->sig,
839 handle(exported_function->instance(), isolate),
841 array->set(table_index, *
function);
844 void WasmTableObject::UpdateDispatchTables(
845 Isolate* isolate, Handle<WasmTableObject> table,
int table_index,
846 wasm::FunctionSig* sig, Handle<WasmInstanceObject> target_instance,
847 int target_func_index) {
850 Handle<FixedArray> dispatch_tables(table->dispatch_tables(), isolate);
851 DCHECK_EQ(0, dispatch_tables->length() % kDispatchTableNumElements);
853 for (
int i = 0;
i < dispatch_tables->length();
854 i += kDispatchTableNumElements) {
855 Handle<WasmInstanceObject> instance(
856 WasmInstanceObject::cast(
857 dispatch_tables->get(
i + kDispatchTableInstanceOffset)),
861 auto sig_id = instance->module()->signature_map.Find(*sig);
862 IndirectFunctionTableEntry(instance, table_index)
863 .Set(sig_id, target_instance, target_func_index);
867 void WasmTableObject::ClearDispatchTables(Isolate* isolate,
868 Handle<WasmTableObject> table,
870 Handle<FixedArray> dispatch_tables(table->dispatch_tables(), isolate);
871 DCHECK_EQ(0, dispatch_tables->length() % kDispatchTableNumElements);
872 for (
int i = 0;
i < dispatch_tables->length();
873 i += kDispatchTableNumElements) {
874 Handle<WasmInstanceObject> target_instance(
875 WasmInstanceObject::cast(
876 dispatch_tables->get(
i + kDispatchTableInstanceOffset)),
878 DCHECK_LT(index, target_instance->indirect_function_table_size());
879 IndirectFunctionTableEntry(target_instance, index).clear();
884 MaybeHandle<JSArrayBuffer> MemoryGrowBuffer(Isolate* isolate,
885 Handle<JSArrayBuffer> old_buffer,
888 CHECK_GE(wasm::max_mem_pages(), maximum_pages);
889 if (!old_buffer->is_growable())
return {};
890 void* old_mem_start = old_buffer->backing_store();
891 size_t old_size = old_buffer->byte_length();
892 CHECK_EQ(0, old_size % wasm::kWasmPageSize);
893 size_t old_pages = old_size / wasm::kWasmPageSize;
894 CHECK_GE(wasm::max_mem_pages(), old_pages);
896 if ((pages > maximum_pages - old_pages) ||
897 (pages > wasm::max_mem_pages() - old_pages)) {
901 static_cast<size_t>(old_pages + pages) * wasm::kWasmPageSize;
907 if (!old_buffer->is_external() &&
908 ((new_size < old_buffer->allocation_length()) || old_size == new_size)) {
909 if (old_size != new_size) {
910 DCHECK_NOT_NULL(old_buffer->backing_store());
913 if (!i::SetPermissions(GetPlatformPageAllocator(), old_mem_start,
914 new_size, PageAllocator::kReadWrite)) {
917 reinterpret_cast<v8::Isolate*
>(isolate)
918 ->AdjustAmountOfExternalAllocatedMemory(pages * wasm::kWasmPageSize);
922 void* backing_store = old_buffer->backing_store();
923 bool is_external = old_buffer->is_external();
925 i::wasm::DetachMemoryBuffer(isolate, old_buffer,
false);
926 Handle<JSArrayBuffer> new_buffer =
927 wasm::SetupArrayBuffer(isolate, backing_store, new_size, is_external);
932 Handle<JSArrayBuffer> new_buffer;
933 if (!wasm::NewArrayBuffer(isolate, new_size).ToHandle(&new_buffer)) {
936 wasm::WasmMemoryTracker*
const memory_tracker =
937 isolate->wasm_engine()->memory_tracker();
941 if (memory_tracker->HasFullGuardRegions(old_mem_start) &&
942 !memory_tracker->HasFullGuardRegions(new_buffer->backing_store())) {
945 if (old_size == 0)
return new_buffer;
946 memcpy(new_buffer->backing_store(), old_mem_start, old_size);
947 DCHECK(old_buffer.is_null() || !old_buffer->is_shared());
948 constexpr
bool free_memory =
true;
949 i::wasm::DetachMemoryBuffer(isolate, old_buffer, free_memory);
955 void SetInstanceMemory(Handle<WasmInstanceObject> instance,
956 Handle<JSArrayBuffer> buffer) {
957 instance->SetRawMemory(reinterpret_cast<byte*>(buffer->backing_store()),
958 buffer->byte_length());
960 if (!FLAG_mock_arraybuffer_allocator) {
964 byte* mem_start = instance->memory_start();
965 size_t mem_size = instance->memory_size();
966 for (
size_t offset = 0; offset < mem_size; offset += wasm::kWasmPageSize) {
967 byte val = mem_start[offset];
969 mem_start[offset] = val;
977 Handle<WasmMemoryObject> WasmMemoryObject::New(
978 Isolate* isolate, MaybeHandle<JSArrayBuffer> maybe_buffer,
984 Handle<JSFunction> memory_ctor(
985 isolate->native_context()->wasm_memory_constructor(), isolate);
986 auto memory_obj = Handle<WasmMemoryObject>::cast(
987 isolate->factory()->NewJSObject(memory_ctor, TENURED));
989 Handle<JSArrayBuffer> buffer;
990 if (!maybe_buffer.ToHandle(&buffer)) {
992 buffer = wasm::SetupArrayBuffer(isolate,
nullptr, 0,
false);
994 memory_obj->set_array_buffer(*buffer);
995 memory_obj->set_maximum_pages(maximum);
1000 uint32_t WasmMemoryObject::current_pages() {
1001 return static_cast<uint32_t>(array_buffer()->byte_length() /
1002 wasm::kWasmPageSize);
1005 bool WasmMemoryObject::has_full_guard_region(Isolate* isolate) {
1006 const wasm::WasmMemoryTracker::AllocationData* allocation =
1007 isolate->wasm_engine()->memory_tracker()->FindAllocationData(
1008 array_buffer()->backing_store());
1009 CHECK_NOT_NULL(allocation);
1011 Address allocation_base =
1012 reinterpret_cast<Address
>(allocation->allocation_base);
1013 Address buffer_start =
reinterpret_cast<Address
>(allocation->buffer_start);
1025 return buffer_start + wasm::kWasmMaxHeapOffset <=
1026 allocation_base + allocation->allocation_length;
1029 void WasmMemoryObject::AddInstance(Isolate* isolate,
1030 Handle<WasmMemoryObject> memory,
1031 Handle<WasmInstanceObject> instance) {
1032 Handle<WeakArrayList> old_instances =
1033 memory->has_instances()
1034 ? Handle<WeakArrayList>(memory->instances(), isolate)
1035 : handle(ReadOnlyRoots(isolate->heap()).empty_weak_array_list(),
1037 Handle<WeakArrayList> new_instances = WeakArrayList::AddToEnd(
1038 isolate, old_instances, MaybeObjectHandle::Weak(instance));
1039 memory->set_instances(*new_instances);
1040 Handle<JSArrayBuffer> buffer(memory->array_buffer(), isolate);
1041 SetInstanceMemory(instance, buffer);
1044 void WasmMemoryObject::RemoveInstance(Handle<WasmMemoryObject> memory,
1045 Handle<WasmInstanceObject> instance) {
1046 if (memory->has_instances()) {
1047 memory->instances()->RemoveOne(MaybeObjectHandle::Weak(instance));
1052 int32_t WasmMemoryObject::Grow(Isolate* isolate,
1053 Handle<WasmMemoryObject> memory_object,
1055 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT(
"v8.wasm"),
"GrowMemory");
1056 Handle<JSArrayBuffer> old_buffer(memory_object->array_buffer(), isolate);
1057 if (!old_buffer->is_growable())
return -1;
1058 size_t old_size = old_buffer->byte_length();
1059 DCHECK_EQ(0, old_size % wasm::kWasmPageSize);
1060 Handle<JSArrayBuffer> new_buffer;
1062 uint32_t maximum_pages = wasm::max_mem_pages();
1063 if (memory_object->has_maximum_pages()) {
1064 maximum_pages = std::min(
1065 maximum_pages, static_cast<uint32_t>(memory_object->maximum_pages()));
1067 if (!MemoryGrowBuffer(isolate, old_buffer, pages, maximum_pages)
1068 .ToHandle(&new_buffer)) {
1072 if (memory_object->has_instances()) {
1073 Handle<WeakArrayList> instances(memory_object->instances(), isolate);
1074 for (
int i = 0;
i < instances->length();
i++) {
1075 MaybeObject elem = instances->Get(
i);
1076 HeapObject* heap_object;
1077 if (elem->GetHeapObjectIfWeak(&heap_object)) {
1078 Handle<WasmInstanceObject> instance(
1079 WasmInstanceObject::cast(heap_object), isolate);
1080 SetInstanceMemory(instance, new_buffer);
1082 DCHECK(elem->IsCleared());
1086 memory_object->set_array_buffer(*new_buffer);
1087 return static_cast<uint32_t>(old_size / wasm::kWasmPageSize);
1091 MaybeHandle<WasmGlobalObject> WasmGlobalObject::New(
1092 Isolate* isolate, MaybeHandle<JSArrayBuffer> maybe_buffer,
1093 wasm::ValueType type, int32_t offset,
bool is_mutable) {
1094 Handle<JSFunction> global_ctor(
1095 isolate->native_context()->wasm_global_constructor(), isolate);
1096 auto global_obj = Handle<WasmGlobalObject>::cast(
1097 isolate->factory()->NewJSObject(global_ctor));
1099 uint32_t type_size = wasm::ValueTypes::ElementSizeInBytes(type);
1101 Handle<JSArrayBuffer> buffer;
1102 if (!maybe_buffer.ToHandle(&buffer)) {
1105 isolate->factory()->NewJSArrayBuffer(SharedFlag::kNotShared, TENURED);
1107 const bool initialize =
true;
1108 if (!JSArrayBuffer::SetupAllocatingData(buffer, isolate, type_size,
1115 CHECK_LE(offset + type_size, buffer->byte_length());
1117 global_obj->set_array_buffer(*buffer);
1118 global_obj->set_flags(0);
1119 global_obj->set_type(type);
1120 global_obj->set_offset(offset);
1121 global_obj->set_is_mutable(is_mutable);
1126 void IndirectFunctionTableEntry::clear() {
1127 instance_->indirect_function_table_sig_ids()[index_] = -1;
1128 instance_->indirect_function_table_targets()[index_] = 0;
1129 instance_->indirect_function_table_refs()->set(
1130 index_, ReadOnlyRoots(instance_->GetIsolate()).undefined_value());
1133 void IndirectFunctionTableEntry::Set(
int sig_id,
1134 Handle<WasmInstanceObject> target_instance,
1135 int target_func_index) {
1137 "IFT entry %p[%d] = {sig_id=%d, target_instance=%p, " 1138 "target_func_index=%d}\n",
1139 *instance_, index_, sig_id, *target_instance, target_func_index);
1141 Object* ref =
nullptr;
1142 Address call_target = 0;
1143 if (target_func_index <
1144 static_cast<int>(target_instance->module()->num_imported_functions)) {
1147 ImportedFunctionEntry entry(target_instance, target_func_index);
1148 ref = entry.object_ref();
1149 call_target = entry.target();
1152 ref = *target_instance;
1153 call_target = target_instance->GetCallTarget(target_func_index);
1157 instance_->indirect_function_table_sig_ids()[index_] = sig_id;
1158 instance_->indirect_function_table_targets()[index_] = call_target;
1159 instance_->indirect_function_table_refs()->set(index_, ref);
1162 Object* IndirectFunctionTableEntry::object_ref() {
1163 return instance_->indirect_function_table_refs()->get(index_);
1166 int IndirectFunctionTableEntry::sig_id() {
1167 return instance_->indirect_function_table_sig_ids()[index_];
1170 Address IndirectFunctionTableEntry::target() {
1171 return instance_->indirect_function_table_targets()[index_];
1174 void ImportedFunctionEntry::SetWasmToJs(
1175 Isolate* isolate, Handle<JSReceiver> callable,
1176 const wasm::WasmCode* wasm_to_js_wrapper) {
1177 TRACE_IFT(
"Import callable %p[%d] = {callable=%p, target=%p}\n", *instance_,
1178 index_, *callable, wasm_to_js_wrapper->instructions().start());
1179 DCHECK_EQ(wasm::WasmCode::kWasmToJsWrapper, wasm_to_js_wrapper->kind());
1180 Handle<Tuple2> tuple =
1181 isolate->factory()->NewTuple2(instance_, callable, TENURED);
1182 instance_->imported_function_refs()->set(index_, *tuple);
1183 instance_->imported_function_targets()[index_] =
1184 wasm_to_js_wrapper->instruction_start();
1187 void ImportedFunctionEntry::SetWasmToWasm(WasmInstanceObject* instance,
1188 Address call_target) {
1189 TRACE_IFT(
"Import WASM %p[%d] = {instance=%p, target=%" PRIuPTR
"}\n",
1190 *instance_, index_, instance, call_target);
1191 instance_->imported_function_refs()->set(index_, instance);
1192 instance_->imported_function_targets()[index_] = call_target;
1195 WasmInstanceObject* ImportedFunctionEntry::instance() {
1198 Object* value = instance_->imported_function_refs()->get(index_);
1199 if (value->IsWasmInstanceObject()) {
1200 return WasmInstanceObject::cast(value);
1202 Tuple2* tuple = Tuple2::cast(value);
1203 return WasmInstanceObject::cast(tuple->value1());
1206 JSReceiver* ImportedFunctionEntry::callable() {
1207 return JSReceiver::cast(Tuple2::cast(object_ref())->value2());
1210 Object* ImportedFunctionEntry::object_ref() {
1211 return instance_->imported_function_refs()->get(index_);
1214 Address ImportedFunctionEntry::target() {
1215 return instance_->imported_function_targets()[index_];
1218 bool WasmInstanceObject::EnsureIndirectFunctionTableWithMinimumSize(
1219 Handle<WasmInstanceObject> instance,
uint32_t minimum_size) {
1220 uint32_t old_size = instance->indirect_function_table_size();
1221 if (old_size >= minimum_size)
return false;
1223 Isolate* isolate = instance->GetIsolate();
1224 HandleScope scope(isolate);
1225 auto native_allocations = GetNativeAllocations(*instance);
1226 native_allocations->resize_indirect_function_table(isolate, instance,
1231 void WasmInstanceObject::SetRawMemory(byte* mem_start,
size_t mem_size) {
1232 CHECK_LE(mem_size, wasm::max_mem_bytes());
1233 #if V8_HOST_ARCH_64_BIT 1234 uint64_t mem_mask64 = base::bits::RoundUpToPowerOfTwo64(mem_size) - 1;
1235 set_memory_start(mem_start);
1236 set_memory_size(mem_size);
1237 set_memory_mask(mem_mask64);
1240 CHECK_LE(mem_size,
size_t{kMaxUInt32});
1242 (mem_size > 2 *
size_t{GB})
1244 : base::bits::RoundUpToPowerOfTwo32(static_cast<uint32_t>(mem_size)) -
1246 set_memory_start(mem_start);
1247 set_memory_size(mem_size);
1248 set_memory_mask(mem_mask32);
1252 const WasmModule* WasmInstanceObject::module() {
1253 return module_object()->module();
1256 Handle<WasmDebugInfo> WasmInstanceObject::GetOrCreateDebugInfo(
1257 Handle<WasmInstanceObject> instance) {
1258 if (instance->has_debug_info()) {
1259 return handle(instance->debug_info(), instance->GetIsolate());
1261 Handle<WasmDebugInfo> new_info = WasmDebugInfo::New(instance);
1262 DCHECK(instance->has_debug_info());
1266 Handle<WasmInstanceObject> WasmInstanceObject::New(
1267 Isolate* isolate, Handle<WasmModuleObject> module_object) {
1268 Handle<JSFunction> instance_cons(
1269 isolate->native_context()->wasm_instance_constructor(), isolate);
1270 Handle<JSObject> instance_object =
1271 isolate->factory()->NewJSObject(instance_cons, TENURED);
1273 Handle<WasmInstanceObject> instance(
1274 reinterpret_cast<WasmInstanceObject*>(*instance_object), isolate);
1277 auto module = module_object->module();
1278 auto num_imported_functions = module->num_imported_functions;
1279 auto num_imported_mutable_globals = module->num_imported_mutable_globals;
1280 size_t native_allocations_size = EstimateNativeAllocationsSize(module);
1281 auto native_allocations = Managed<WasmInstanceNativeAllocations>::Allocate(
1282 isolate, native_allocations_size, instance, num_imported_functions,
1283 num_imported_mutable_globals);
1284 instance->set_managed_native_allocations(*native_allocations);
1286 Handle<FixedArray> imported_function_refs =
1287 isolate->factory()->NewFixedArray(num_imported_functions);
1288 instance->set_imported_function_refs(*imported_function_refs);
1290 Handle<Code> centry_stub = CodeFactory::CEntry(isolate);
1291 instance->set_centry_stub(*centry_stub);
1293 instance->SetRawMemory(
nullptr, 0);
1294 instance->set_isolate_root(isolate->isolate_root());
1295 instance->set_stack_limit_address(
1296 isolate->stack_guard()->address_of_jslimit());
1297 instance->set_real_stack_limit_address(
1298 isolate->stack_guard()->address_of_real_jslimit());
1299 instance->set_globals_start(
nullptr);
1300 instance->set_indirect_function_table_size(0);
1301 instance->set_indirect_function_table_sig_ids(
nullptr);
1302 instance->set_indirect_function_table_targets(
nullptr);
1303 instance->set_native_context(*isolate->native_context());
1304 instance->set_module_object(*module_object);
1305 instance->set_undefined_value(ReadOnlyRoots(isolate).undefined_value());
1306 instance->set_null_value(ReadOnlyRoots(isolate).null_value());
1307 instance->set_jump_table_start(
1308 module_object->native_module()->jump_table_start());
1312 Handle<WeakArrayList> weak_instance_list(module_object->weak_instance_list(),
1314 weak_instance_list = WeakArrayList::AddToEnd(
1315 isolate, weak_instance_list, MaybeObjectHandle::Weak(instance));
1316 module_object->set_weak_instance_list(*weak_instance_list);
1321 Address WasmInstanceObject::GetCallTarget(
uint32_t func_index) {
1322 wasm::NativeModule* native_module = module_object()->native_module();
1323 if (func_index < native_module->num_imported_functions()) {
1324 return imported_function_targets()[func_index];
1326 return native_module->GetCallTargetForFunction(func_index);
1330 Handle<WasmExceptionObject> WasmExceptionObject::New(
1331 Isolate* isolate,
const wasm::FunctionSig* sig,
1332 Handle<HeapObject> exception_tag) {
1333 Handle<JSFunction> exception_cons(
1334 isolate->native_context()->wasm_exception_constructor(), isolate);
1335 Handle<JSObject> exception_object =
1336 isolate->factory()->NewJSObject(exception_cons, TENURED);
1337 Handle<WasmExceptionObject> exception =
1338 Handle<WasmExceptionObject>::cast(exception_object);
1341 DCHECK_EQ(0, sig->return_count());
1342 DCHECK_LE(sig->parameter_count(), std::numeric_limits<int>::max());
1343 int sig_size =
static_cast<int>(sig->parameter_count());
1344 Handle<PodArray<wasm::ValueType>> serialized_sig =
1345 PodArray<wasm::ValueType>::New(isolate, sig_size, TENURED);
1347 for (wasm::ValueType param : sig->parameters()) {
1348 serialized_sig->set(index++, param);
1350 exception->set_serialized_signature(*serialized_sig);
1351 exception->set_exception_tag(*exception_tag);
1356 bool WasmExceptionObject::IsSignatureEqual(
const wasm::FunctionSig* sig) {
1357 DCHECK_EQ(0, sig->return_count());
1358 DCHECK_LE(sig->parameter_count(), std::numeric_limits<int>::max());
1359 int sig_size =
static_cast<int>(sig->parameter_count());
1360 if (sig_size != serialized_signature()->length())
return false;
1361 for (
int index = 0; index < sig_size; ++index) {
1362 if (sig->GetParam(index) != serialized_signature()->get(index)) {
1369 bool WasmExportedFunction::IsWasmExportedFunction(Object*
object) {
1370 if (!object->IsJSFunction())
return false;
1371 JSFunction* js_function = JSFunction::cast(
object);
1372 if (Code::JS_TO_WASM_FUNCTION != js_function->code()->kind())
return false;
1373 DCHECK(js_function->shared()->HasWasmExportedFunctionData());
1377 WasmExportedFunction* WasmExportedFunction::cast(Object*
object) {
1378 DCHECK(IsWasmExportedFunction(
object));
1379 return reinterpret_cast<WasmExportedFunction*
>(object);
1382 WasmInstanceObject* WasmExportedFunction::instance() {
1383 return shared()->wasm_exported_function_data()->instance();
1386 int WasmExportedFunction::function_index() {
1387 return shared()->wasm_exported_function_data()->function_index();
1390 Handle<WasmExportedFunction> WasmExportedFunction::New(
1391 Isolate* isolate, Handle<WasmInstanceObject> instance,
1392 MaybeHandle<String> maybe_name,
int func_index,
int arity,
1393 Handle<Code> export_wrapper) {
1394 DCHECK_EQ(Code::JS_TO_WASM_FUNCTION, export_wrapper->kind());
1395 int num_imported_functions = instance->module()->num_imported_functions;
1396 int jump_table_offset = -1;
1397 if (func_index >= num_imported_functions) {
1398 ptrdiff_t jump_table_diff =
1399 instance->module_object()->native_module()->jump_table_offset(
1401 DCHECK(jump_table_diff >= 0 && jump_table_diff <= INT_MAX);
1402 jump_table_offset =
static_cast<int>(jump_table_diff);
1404 Handle<WasmExportedFunctionData> function_data =
1405 Handle<WasmExportedFunctionData>::cast(isolate->factory()->NewStruct(
1406 WASM_EXPORTED_FUNCTION_DATA_TYPE, TENURED));
1407 function_data->set_wrapper_code(*export_wrapper);
1408 function_data->set_instance(*instance);
1409 function_data->set_jump_table_offset(jump_table_offset);
1410 function_data->set_function_index(func_index);
1411 Handle<String> name;
1412 if (!maybe_name.ToHandle(&name)) {
1413 EmbeddedVector<char, 16> buffer;
1414 int length = SNPrintF(buffer,
"%d", func_index);
1415 name = isolate->factory()
1416 ->NewStringFromOneByte(
1417 Vector<uint8_t>::cast(buffer.SubVector(0, length)))
1420 NewFunctionArgs args = NewFunctionArgs::ForWasm(
1421 name, function_data, isolate->sloppy_function_without_prototype_map());
1422 Handle<JSFunction> js_function = isolate->factory()->NewFunction(args);
1425 DCHECK(!js_function->IsConstructor());
1426 js_function->shared()->set_length(arity);
1427 js_function->shared()->set_internal_formal_parameter_count(arity);
1428 return Handle<WasmExportedFunction>::cast(js_function);
1431 Address WasmExportedFunction::GetWasmCallTarget() {
1432 return instance()->GetCallTarget(function_index());
1435 wasm::FunctionSig* WasmExportedFunction::sig() {
1436 return instance()->module()->functions[function_index()].sig;
1439 Handle<AsmWasmData> AsmWasmData::New(
1440 Isolate* isolate, std::shared_ptr<wasm::NativeModule> native_module,
1441 Handle<FixedArray> export_wrappers, Handle<ByteArray> asm_js_offset_table,
1442 Handle<HeapNumber> uses_bitset) {
1443 const WasmModule* module = native_module->module();
1444 size_t memory_estimate =
1445 wasm::WasmCodeManager::EstimateNativeModuleCodeSize(module) +
1446 wasm::WasmCodeManager::EstimateNativeModuleNonCodeSize(module);
1447 Handle<Managed<wasm::NativeModule>> managed_native_module =
1448 Managed<wasm::NativeModule>::FromSharedPtr(isolate, memory_estimate,
1449 std::move(native_module));
1450 Handle<AsmWasmData> result = Handle<AsmWasmData>::cast(
1451 isolate->factory()->NewStruct(ASM_WASM_DATA_TYPE, TENURED));
1452 result->set_managed_native_module(*managed_native_module);
1453 result->set_export_wrappers(*export_wrappers);
1454 result->set_asm_js_offset_table(*asm_js_offset_table);
1455 result->set_uses_bitset(*uses_bitset);