v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
wasm-module.cc
Go to the documentation of this file.
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
6
7#include <functional>
8#include <memory>
9
10#include "src/api/api-inl.h"
13#include "src/objects/objects.h"
20#include "src/wasm/wasm-js.h"
21#include "src/wasm/wasm-module-builder.h" // For {ZoneBuffer}.
25
26namespace v8::internal::wasm {
27
28// Ensure that the max subtyping depth can be stored in the TypeDefinition.
29static_assert(
31 std::numeric_limits<decltype(TypeDefinition().subtyping_depth)>::max());
32
33template <class Value>
35 uint32_t count = 0;
36 uint32_t max = 0;
37 DCHECK_EQ(mode_, kInitializing);
38 for (const auto& entry : *map_) {
39 count++;
40 max = std::max(max, entry.first);
41 }
42 if (count >= (max + 1) / kLoadFactor) {
43 mode_ = kDense;
44 vector_.resize(max + 1);
45 for (auto& entry : *map_) {
46 vector_[entry.first] = std::move(entry.second);
47 }
48 map_.reset();
49 } else {
50 mode_ = kSparse;
51 }
52}
53template void NameMap::FinishInitialization();
55
57 ModuleWireBytes wire_bytes, uint32_t function_index) {
59 if (!has_functions_) {
60 has_functions_ = true;
62 }
63 const WireBytesRef* result = function_names_.Get(function_index);
64 if (!result) return WireBytesRef();
65 return *result;
66}
67
68bool LazilyGeneratedNames::Has(uint32_t function_index) {
71 return function_names_.Get(function_index) != nullptr;
72}
73
74// static
75int GetWasmFunctionOffset(const WasmModule* module, uint32_t func_index) {
76 const std::vector<WasmFunction>& functions = module->functions;
77 if (static_cast<uint32_t>(func_index) >= functions.size()) return -1;
78 DCHECK_GE(kMaxInt, functions[func_index].code.offset());
79 return static_cast<int>(functions[func_index].code.offset());
80}
81
82// static
83int GetNearestWasmFunction(const WasmModule* module, uint32_t byte_offset) {
84 const std::vector<WasmFunction>& functions = module->functions;
85
86 // Binary search for a function containing the given position.
87 int left = 0; // inclusive
88 int right = static_cast<int>(functions.size()); // exclusive
89 if (right == 0) return -1;
90 while (right - left > 1) {
91 int mid = left + (right - left) / 2;
92 if (functions[mid].code.offset() <= byte_offset) {
93 left = mid;
94 } else {
95 right = mid;
96 }
97 }
98
99 return left;
100}
101
102// static
103int GetContainingWasmFunction(const WasmModule* module, uint32_t byte_offset) {
104 int func_index = GetNearestWasmFunction(module, byte_offset);
105
106 if (func_index >= 0) {
107 // If the found function does not contain the given position, return -1.
108 const WasmFunction& func = module->functions[func_index];
109 if (byte_offset < func.code.offset() ||
110 byte_offset >= func.code.end_offset()) {
111 return -1;
112 }
113 }
114 return func_index;
115}
116
117int GetSubtypingDepth(const WasmModule* module, ModuleTypeIndex type_index) {
118 DCHECK_LT(type_index.index, module->types.size());
119 int depth = module->type(type_index).subtyping_depth;
121 return depth;
122}
123
125 WireBytesRef name) {
127 function_names_.Put(function_index, name);
128}
129
131 base::Vector<const uint8_t> encoded_offsets)
132 : encoded_offsets_(base::OwnedCopyOf(encoded_offsets)) {}
133
135
137 int byte_offset,
138 bool is_at_number_conversion) {
140
141 DCHECK_LE(0, declared_func_index);
142 DCHECK_GT(decoded_offsets_->functions.size(), declared_func_index);
143 std::vector<AsmJsOffsetEntry>& function_offsets =
144 decoded_offsets_->functions[declared_func_index].entries;
145
146 auto byte_offset_less = [](const AsmJsOffsetEntry& a,
147 const AsmJsOffsetEntry& b) {
148 return a.byte_offset < b.byte_offset;
149 };
150 SLOW_DCHECK(std::is_sorted(function_offsets.begin(), function_offsets.end(),
151 byte_offset_less));
152 // If there are no positions recorded, map offset 0 (for function entry) to
153 // position 0.
154 if (function_offsets.empty() && byte_offset == 0) return 0;
155 auto it =
156 std::lower_bound(function_offsets.begin(), function_offsets.end(),
157 AsmJsOffsetEntry{byte_offset, 0, 0}, byte_offset_less);
158 DCHECK_NE(function_offsets.end(), it);
159 DCHECK_EQ(byte_offset, it->byte_offset);
160 return is_at_number_conversion ? it->source_position_number_conversion
161 : it->source_position_call;
162}
163
165 int declared_func_index) {
167
168 DCHECK_LE(0, declared_func_index);
169 DCHECK_GT(decoded_offsets_->functions.size(), declared_func_index);
170 AsmJsOffsetFunctionEntries& function_info =
171 decoded_offsets_->functions[declared_func_index];
172
173 return {function_info.start_offset, function_info.end_offset};
174}
175
177 base::MutexGuard mutex_guard(&mutex_);
178 DCHECK_EQ(encoded_offsets_ == nullptr, decoded_offsets_ != nullptr);
179
180 if (decoded_offsets_) return;
183 decoded_offsets_ = std::make_unique<AsmJsOffsets>(std::move(result).value());
185}
186
187// Get a string stored in the module bytes representing a name.
189 if (!ref.is_set()) return {nullptr, 0}; // no name.
190 DCHECK(BoundsCheck(ref));
191 return WasmName::cast(
193}
194
195// Get a string stored in the module bytes representing a function name.
197 const WasmModule* module) const {
198 return GetNameOrNull(
199 module->lazily_generated_names.LookupFunctionName(*this, func_index));
200}
201
202std::ostream& operator<<(std::ostream& os, const WasmFunctionName& name) {
203 os << "#" << name.func_index_;
204 if (!name.name_.empty()) {
205 if (name.name_.begin()) {
206 os << ":";
207 os.write(name.name_.begin(), name.name_.length());
208 }
209 } else {
210 os << "?";
211 }
212 return os;
213}
214
216 : signature_zone(GetWasmEngine()->allocator(), "signature zone"),
217 origin(origin) {}
218
219uint64_t WasmModule::signature_hash(const TypeCanonicalizer* type_canonicalizer,
220 uint32_t function_index) const {
221 if (function_index >= functions.size()) {
223 }
224
226 canonical_sig_id(functions[function_index].sig_index);
227 return type_canonicalizer->LookupFunctionSignature(canonical_type_id)
228 ->signature_hash();
229}
230
233 // TODO(wasm): Once wasm has its own CSP policy, we should introduce a
234 // separate callback that includes information about the module about to be
235 // compiled. For the time being, pass an empty string as placeholder for the
236 // sources.
237 if (auto wasm_codegen_callback = isolate->allow_wasm_code_gen_callback()) {
238 return wasm_codegen_callback(
239 v8::Utils::ToLocal(context),
240 v8::Utils::ToLocal(isolate->factory()->empty_string()));
241 }
242 return true;
243}
244
246 DirectHandle<Context> context) {
247 DirectHandle<Object> error = context->ErrorMessageForWasmCodeGeneration();
248 DCHECK(!error.is_null());
249 return Object::NoSideEffectsToString(isolate, error);
250}
251
252namespace {
253
254// Converts the given {type} into a string representation that can be used in
255// reflective functions. Should be kept in sync with the {GetValueType} helper.
256DirectHandle<String> ToValueTypeString(Isolate* isolate, ValueType type) {
257 return isolate->factory()->InternalizeUtf8String(base::VectorOf(type.name()));
258}
259} // namespace
260
262 const FunctionSig* sig,
263 bool for_exception) {
264 Factory* factory = isolate->factory();
265
266 // Extract values for the {ValueType[]} arrays.
267 int param_index = 0;
268 int param_count = static_cast<int>(sig->parameter_count());
269 DirectHandle<FixedArray> param_values = factory->NewFixedArray(param_count);
270 for (ValueType type : sig->parameters()) {
271 DirectHandle<String> type_value = ToValueTypeString(isolate, type);
272 param_values->set(param_index++, *type_value);
273 }
274
275 // Create the resulting {FunctionType} object.
276 DirectHandle<JSFunction> object_function = isolate->object_function();
277 DirectHandle<JSObject> object = factory->NewJSObject(object_function);
278 DirectHandle<JSArray> params = factory->NewJSArrayWithElements(param_values);
279 DirectHandle<String> params_string =
280 factory->InternalizeUtf8String("parameters");
281 DirectHandle<String> results_string =
282 factory->InternalizeUtf8String("results");
283 JSObject::AddProperty(isolate, object, params_string, params, NONE);
284
285 // Now add the result types if needed.
286 if (for_exception) {
287 DCHECK_EQ(sig->returns().size(), 0);
288 } else {
289 int result_index = 0;
290 int result_count = static_cast<int>(sig->return_count());
291 DirectHandle<FixedArray> result_values =
292 factory->NewFixedArray(result_count);
293 for (ValueType type : sig->returns()) {
294 DirectHandle<String> type_value = ToValueTypeString(isolate, type);
295 result_values->set(result_index++, *type_value);
296 }
297 DirectHandle<JSArray> results =
298 factory->NewJSArrayWithElements(result_values);
299 JSObject::AddProperty(isolate, object, results_string, results, NONE);
300 }
301
302 return object;
303}
304
306 ValueType type) {
307 Factory* factory = isolate->factory();
308
309 DirectHandle<JSFunction> object_function = isolate->object_function();
310 DirectHandle<JSObject> object = factory->NewJSObject(object_function);
311 DirectHandle<String> mutable_string =
312 factory->InternalizeUtf8String("mutable");
313 DirectHandle<String> value_string = factory->value_string();
314 JSObject::AddProperty(isolate, object, mutable_string,
315 factory->ToBoolean(is_mutable), NONE);
316 JSObject::AddProperty(isolate, object, value_string,
317 ToValueTypeString(isolate, type), NONE);
318
319 return object;
320}
321
323 std::optional<uint64_t> max_size,
324 bool shared, AddressType address_type) {
325 Factory* factory = isolate->factory();
326
327 DirectHandle<JSFunction> object_function = isolate->object_function();
328 DirectHandle<JSObject> object = factory->NewJSObject(object_function);
329 DirectHandle<String> minimum_string =
330 factory->InternalizeUtf8String("minimum");
331 DirectHandle<String> maximum_string =
332 factory->InternalizeUtf8String("maximum");
333 DirectHandle<String> shared_string = factory->InternalizeUtf8String("shared");
334 DirectHandle<String> address_string =
335 factory->InternalizeUtf8String("address");
336 JSObject::AddProperty(isolate, object, minimum_string,
337 factory->NewNumberFromUint(min_size), NONE);
338 if (max_size.has_value()) {
340 if (address_type == AddressType::kI32) {
341 DCHECK_GE(kMaxUInt32, *max_size);
342 max = factory->NewNumberFromUint(static_cast<uint32_t>(*max_size));
343 } else {
344 max = BigInt::FromUint64(isolate, *max_size);
345 }
346 JSObject::AddProperty(isolate, object, maximum_string, max, NONE);
348 JSObject::AddProperty(isolate, object, shared_string,
349 factory->ToBoolean(shared), NONE);
350
352 isolate, object, address_string,
353 factory->InternalizeUtf8String(AddressTypeToStr(address_type)), NONE);
354
355 return object;
356}
357
359 uint32_t min_size,
360 std::optional<uint64_t> max_size,
361 AddressType address_type) {
362 Factory* factory = isolate->factory();
363
364 DirectHandle<String> element =
365 factory->InternalizeUtf8String(base::VectorOf(type.name()));
366
367 DirectHandle<JSFunction> object_function = isolate->object_function();
368 DirectHandle<JSObject> object = factory->NewJSObject(object_function);
369 DirectHandle<String> element_string = factory->element_string();
370 DirectHandle<String> minimum_string =
371 factory->InternalizeUtf8String("minimum");
372 DirectHandle<String> maximum_string =
373 factory->InternalizeUtf8String("maximum");
374 DirectHandle<String> address_string =
375 factory->InternalizeUtf8String("address");
376 JSObject::AddProperty(isolate, object, element_string, element, NONE);
377 JSObject::AddProperty(isolate, object, minimum_string,
378 factory->NewNumberFromUint(min_size), NONE);
379 if (max_size.has_value()) {
381 if (address_type == AddressType::kI32) {
382 DCHECK_GE(kMaxUInt32, *max_size);
383 max = factory->NewNumberFromUint(static_cast<uint32_t>(*max_size));
384 } else {
385 max = BigInt::FromUint64(isolate, *max_size);
386 }
387 JSObject::AddProperty(isolate, object, maximum_string, max, NONE);
388 }
390 isolate, object, address_string,
391 factory->InternalizeUtf8String(AddressTypeToStr(address_type)), NONE);
392
393 return object;
394}
395
397 DirectHandle<WasmModuleObject> module_object) {
398 auto enabled_features = i::wasm::WasmEnabledFeatures::FromIsolate(isolate);
399 Factory* factory = isolate->factory();
400
401 DirectHandle<String> module_string = factory->InternalizeUtf8String("module");
402 DirectHandle<String> name_string = factory->name_string();
403 DirectHandle<String> kind_string = factory->InternalizeUtf8String("kind");
404 DirectHandle<String> type_string = factory->InternalizeUtf8String("type");
405
406 DirectHandle<String> function_string = factory->function_string();
407 DirectHandle<String> table_string = factory->InternalizeUtf8String("table");
408 DirectHandle<String> memory_string = factory->InternalizeUtf8String("memory");
409 DirectHandle<String> global_string = factory->global_string();
410 DirectHandle<String> tag_string = factory->InternalizeUtf8String("tag");
411
412 // Create the result array.
413 NativeModule* native_module = module_object->native_module();
414 const WasmModule* module = native_module->module();
415 int num_imports = static_cast<int>(module->import_table.size());
416 DirectHandle<JSArray> array_object =
417 factory->NewJSArray(PACKED_ELEMENTS, 0, 0);
418 DirectHandle<FixedArray> storage = factory->NewFixedArray(num_imports);
419 JSArray::SetContent(array_object, storage);
420
422 isolate->native_context()->object_function(), isolate);
423
424 // Populate the result array.
425 const WellKnownImportsList& well_known_imports =
426 module->type_feedback.well_known_imports;
427 const std::string& magic_string_constants =
428 native_module->compile_imports().constants_module();
429 const bool has_magic_string_constants =
430 native_module->compile_imports().contains(
432
433 int cursor = 0;
434 for (int index = 0; index < num_imports; ++index) {
435 const WasmImport& import = module->import_table[index];
436
437 DirectHandle<JSObject> entry = factory->NewJSObject(object_function);
438
439 DirectHandle<String> import_kind;
440 DirectHandle<JSObject> type_value;
441 switch (import.kind) {
443 if (IsCompileTimeImport(well_known_imports.get(import.index))) {
444 continue;
445 }
446 if (enabled_features.has_type_reflection()) {
447 auto& func = module->functions[import.index];
448 type_value = GetTypeForFunction(isolate, func.sig);
449 }
450 import_kind = function_string;
451 break;
452 case kExternalTable:
453 if (enabled_features.has_type_reflection()) {
454 auto& table = module->tables[import.index];
455 std::optional<uint32_t> maximum_size;
456 if (table.has_maximum_size) maximum_size.emplace(table.maximum_size);
457 type_value = GetTypeForTable(isolate, table.type, table.initial_size,
458 maximum_size, table.address_type);
459 }
460 import_kind = table_string;
461 break;
462 case kExternalMemory:
463 if (enabled_features.has_type_reflection()) {
464 auto& memory = module->memories[import.index];
465 std::optional<uint32_t> maximum_size;
466 if (memory.has_maximum_pages) {
467 maximum_size.emplace(memory.maximum_pages);
468 }
469 type_value =
470 GetTypeForMemory(isolate, memory.initial_pages, maximum_size,
471 memory.is_shared, memory.address_type);
472 }
473 import_kind = memory_string;
474 break;
475 case kExternalGlobal:
476 if (has_magic_string_constants &&
477 import.module_name.length() == magic_string_constants.size() &&
478 std::equal(magic_string_constants.begin(),
479 magic_string_constants.end(),
480 module_object->native_module()->wire_bytes().begin() +
481 import.module_name.offset())) {
482 continue;
483 }
484 if (enabled_features.has_type_reflection()) {
485 auto& global = module->globals[import.index];
486 type_value =
487 GetTypeForGlobal(isolate, global.mutability, global.type);
488 }
489 import_kind = global_string;
490 break;
491 case kExternalTag:
492 import_kind = tag_string;
493 break;
494 }
495 DCHECK(!import_kind.is_null());
496
497 DirectHandle<String> import_module =
499 isolate, module_object, import.module_name, kInternalize);
500
501 DirectHandle<String> import_name =
503 isolate, module_object, import.field_name, kInternalize);
504
505 JSObject::AddProperty(isolate, entry, module_string, import_module, NONE);
506 JSObject::AddProperty(isolate, entry, name_string, import_name, NONE);
507 JSObject::AddProperty(isolate, entry, kind_string, import_kind, NONE);
508 if (!type_value.is_null()) {
509 JSObject::AddProperty(isolate, entry, type_string, type_value, NONE);
510 }
511
512 storage->set(cursor++, *entry);
513 }
514
515 array_object->set_length(Smi::FromInt(cursor));
516 return array_object;
517}
518
520 DirectHandle<WasmModuleObject> module_object) {
521 auto enabled_features = i::wasm::WasmEnabledFeatures::FromIsolate(isolate);
522 Factory* factory = isolate->factory();
523
524 DirectHandle<String> name_string = factory->name_string();
525 DirectHandle<String> kind_string = factory->InternalizeUtf8String("kind");
526 DirectHandle<String> type_string = factory->InternalizeUtf8String("type");
527
528 DirectHandle<String> function_string = factory->function_string();
529 DirectHandle<String> table_string = factory->InternalizeUtf8String("table");
530 DirectHandle<String> memory_string = factory->InternalizeUtf8String("memory");
531 DirectHandle<String> global_string = factory->global_string();
532 DirectHandle<String> tag_string = factory->InternalizeUtf8String("tag");
533
534 // Create the result array.
535 const WasmModule* module = module_object->module();
536 int num_exports = static_cast<int>(module->export_table.size());
537 DirectHandle<JSArray> array_object =
538 factory->NewJSArray(PACKED_ELEMENTS, 0, 0);
539 DirectHandle<FixedArray> storage = factory->NewFixedArray(num_exports);
540 JSArray::SetContent(array_object, storage);
541 array_object->set_length(Smi::FromInt(num_exports));
542
544 isolate->native_context()->object_function(), isolate);
545
546 // Populate the result array.
547 for (int index = 0; index < num_exports; ++index) {
548 const WasmExport& exp = module->export_table[index];
549
550 DirectHandle<String> export_kind;
551 DirectHandle<JSObject> type_value;
552 switch (exp.kind) {
554 if (enabled_features.has_type_reflection()) {
555 auto& func = module->functions[exp.index];
556 type_value = GetTypeForFunction(isolate, func.sig);
557 }
558 export_kind = function_string;
559 break;
560 case kExternalTable:
561 if (enabled_features.has_type_reflection()) {
562 auto& table = module->tables[exp.index];
563 std::optional<uint32_t> maximum_size;
564 if (table.has_maximum_size) maximum_size.emplace(table.maximum_size);
565 type_value = GetTypeForTable(isolate, table.type, table.initial_size,
566 maximum_size, table.address_type);
567 }
568 export_kind = table_string;
569 break;
570 case kExternalMemory:
571 if (enabled_features.has_type_reflection()) {
572 auto& memory = module->memories[exp.index];
573 std::optional<uint32_t> maximum_size;
574 if (memory.has_maximum_pages) {
575 maximum_size.emplace(memory.maximum_pages);
576 }
577 type_value =
578 GetTypeForMemory(isolate, memory.initial_pages, maximum_size,
579 memory.is_shared, memory.address_type);
580 }
581 export_kind = memory_string;
582 break;
583 case kExternalGlobal:
584 if (enabled_features.has_type_reflection()) {
585 auto& global = module->globals[exp.index];
586 type_value =
587 GetTypeForGlobal(isolate, global.mutability, global.type);
588 }
589 export_kind = global_string;
590 break;
591 case kExternalTag:
592 export_kind = tag_string;
593 break;
594 default:
595 UNREACHABLE();
596 }
597
598 DirectHandle<JSObject> entry = factory->NewJSObject(object_function);
599
600 DirectHandle<String> export_name =
602 isolate, module_object, exp.name, kNoInternalize);
603
604 JSObject::AddProperty(isolate, entry, name_string, export_name, NONE);
605 JSObject::AddProperty(isolate, entry, kind_string, export_kind, NONE);
606 if (!type_value.is_null()) {
607 JSObject::AddProperty(isolate, entry, type_string, type_value, NONE);
608 }
609
610 storage->set(index, *entry);
611 }
612
613 return array_object;
614}
615
617 Isolate* isolate, DirectHandle<WasmModuleObject> module_object,
618 DirectHandle<String> name, ErrorThrower* thrower) {
619 Factory* factory = isolate->factory();
620
621 base::Vector<const uint8_t> wire_bytes =
622 module_object->native_module()->wire_bytes();
623 std::vector<CustomSectionOffset> custom_sections =
624 DecodeCustomSections(wire_bytes);
625
626 DirectHandleVector<Object> matching_sections(isolate);
627
628 // Gather matching sections.
629 for (auto& section : custom_sections) {
630 DirectHandle<String> section_name =
632 isolate, module_object, section.name, kNoInternalize);
633
634 if (!name->Equals(*section_name)) continue;
635
636 // Make a copy of the payload data in the section.
637 size_t size = section.payload.length();
639 isolate->factory()->NewJSArrayBufferAndBackingStore(
641 DirectHandle<JSArrayBuffer> array_buffer;
642 if (!result.ToHandle(&array_buffer)) {
643 thrower->RangeError("out of memory allocating custom section data");
644 return DirectHandle<JSArray>();
645 }
646 memcpy(array_buffer->backing_store(),
647 wire_bytes.begin() + section.payload.offset(),
648 section.payload.length());
649
650 matching_sections.push_back(array_buffer);
651 }
652
653 int num_custom_sections = static_cast<int>(matching_sections.size());
654 DirectHandle<JSArray> array_object =
655 factory->NewJSArray(PACKED_ELEMENTS, 0, 0);
657 factory->NewFixedArray(num_custom_sections);
658 JSArray::SetContent(array_object, storage);
659 array_object->set_length(Smi::FromInt(num_custom_sections));
660
661 for (int i = 0; i < num_custom_sections; i++) {
662 storage->set(i, *matching_sections[i]);
663 }
664
665 return array_object;
666}
667
668// Get the source position from a given function index and wire bytes offset
669// (relative to the function entry), for either asm.js or pure Wasm modules.
670int GetSourcePosition(const WasmModule* module, uint32_t func_index,
671 uint32_t byte_offset, bool is_at_number_conversion) {
673 module->asm_js_offset_information != nullptr);
674 if (!is_asmjs_module(module)) {
675 // For non-asm.js modules, we just add the function's start offset
676 // to make a module-relative position.
677 return byte_offset + GetWasmFunctionOffset(module, func_index);
678 }
679
680 // asm.js modules have an additional offset table that must be searched.
681 return module->asm_js_offset_information->GetSourcePosition(
682 declared_function_index(module, func_index), byte_offset,
683 is_at_number_conversion);
684}
685
688#if V8_ENABLE_DRUMBRAKE
689 800
690#else // V8_ENABLE_DRUMBRAKE
691 768
692#endif // V8_ENABLE_DRUMBRAKE
693 );
694 return sizeof(WasmModule) + // --
696 ContentSize(types) + // --
698 ContentSize(functions) + // --
699 ContentSize(globals) + // --
701 ContentSize(tables) + // --
702 ContentSize(memories) + // --
705 ContentSize(tags) + // --
710 ContentSize(inst_traces) + // --
711 (num_declared_functions + 7) / 8; // validated_functions
712}
713
714template <class Value>
716 UNREACHABLE(); // Explicit implementations below.
717}
718
719template <>
721 size_t result = ContentSize(vector_);
722 if (map_) result += ContentSize(*map_);
723 return result;
724}
725
730
731template <>
733 size_t result = ContentSize(vector_);
734 for (const auto& inner_map : vector_) {
735 result += inner_map.EstimateCurrentMemoryConsumption();
736 }
737 if (map_) {
739 for (const auto& [outer_index, inner_map] : *map_) {
740 result += inner_map.EstimateCurrentMemoryConsumption();
741 }
742 }
743 return result;
744}
745
749 // Not including sizeof(TFS) because that's contained in sizeof(WasmModule).
750 base::MutexGuard guard(&mutex);
752 for (const auto& [func_idx, feedback] : feedback_for_function) {
753 result += ContentSize(feedback.feedback_vector);
754 result += feedback.call_targets.size() * sizeof(uint32_t);
755 }
757 // The size of {well_known_imports} can only be estimated at the WasmModule
758 // level.
759 if (v8_flags.trace_wasm_offheap_memory) {
760 PrintF("TypeFeedback: %zu\n", result);
761 }
762 return result;
763}
764
767#if V8_ENABLE_DRUMBRAKE
768 800
769#else // V8_ENABLE_DRUMBRAKE
770 768
771#endif // V8_ENABLE_DRUMBRAKE
772 );
773 size_t result = EstimateStoredSize();
774
776 // For type_feedback.well_known_imports:
778
780
781 if (v8_flags.trace_wasm_offheap_memory) {
782 PrintF("WasmModule: %zu\n", result);
783 }
784 return result;
785}
786
788 char delimiter) {
789 if (buffer.empty()) return 0;
790 size_t old_size = buffer.size();
791 auto append_char = [&buffer](char c) {
792 if (buffer.size() == 1) return; // Keep last character for '\0'.
793 buffer[0] = c;
794 buffer += 1;
795 };
796 for (CanonicalValueType t : sig->parameters()) {
797 append_char(t.short_name());
798 }
799 append_char(delimiter);
800 for (CanonicalValueType t : sig->returns()) {
801 append_char(t.short_name());
802 }
803 buffer[0] = '\0';
804 return old_size - buffer.size();
805}
806
807int JumpTableOffset(const WasmModule* module, int func_index) {
809 declared_function_index(module, func_index));
810}
811
814 reinterpret_cast<const char*>(wire_bytes.begin()), wire_bytes.length(),
816}
817
818int NumFeedbackSlots(const WasmModule* module, int func_index) {
819 base::MutexGuard mutex_guard{&module->type_feedback.mutex};
820 auto it = module->type_feedback.feedback_for_function.find(func_index);
821 if (it == module->type_feedback.feedback_for_function.end()) return 0;
822 // The number of call instructions is capped by max function size.
823 static_assert(kV8MaxWasmFunctionSize < std::numeric_limits<int>::max() / 2);
824 return static_cast<int>(2 * it->second.call_targets.size());
825}
826
827} // namespace v8::internal::wasm
Builtins::Kind kind
Definition builtins.cc:40
#define SLOW_DCHECK(condition)
Definition checks.h:21
std::unique_ptr< T[]> ReleaseData()
Definition vector.h:280
Vector< T > as_vector() const
Definition vector.h:276
int length() const
Definition vector.h:64
Vector< T > SubVector(size_t from, size_t to) const
Definition vector.h:41
constexpr bool empty() const
Definition vector.h:73
constexpr size_t size() const
Definition vector.h:70
constexpr T * begin() const
Definition vector.h:96
static Vector< const char > cast(Vector< S > input)
Definition vector.h:157
static V8_EXPORT_PRIVATE Handle< BigInt > FromUint64(Isolate *isolate, uint64_t n)
Definition bigint.cc:1355
void push_back(const DirectHandle< T > &x)
Definition handles.h:940
size_t size() const noexcept
Definition handles.h:900
V8_INLINE bool is_null() const
Definition handles.h:693
Handle< Boolean > ToBoolean(bool value)
Handle< Number > NewNumberFromUint(uint32_t value)
Handle< FixedArray > NewFixedArray(int length, AllocationType allocation=AllocationType::kYoung)
Handle< JSArray > NewJSArray(ElementsKind elements_kind, int length, int capacity, ArrayStorageAllocationMode mode=ArrayStorageAllocationMode::DONT_INITIALIZE_ARRAY_ELEMENTS, AllocationType allocation=AllocationType::kYoung)
Definition factory.cc:3211
Handle< JSObject > NewJSObject(DirectHandle< JSFunction > constructor, AllocationType allocation=AllocationType::kYoung, NewJSObjectType=NewJSObjectType::kNoAPIWrapper)
Definition factory.cc:2985
Handle< JSArray > NewJSArrayWithElements(DirectHandle< FixedArrayBase > elements, ElementsKind elements_kind, int length, AllocationType allocation=AllocationType::kYoung)
Definition factory.cc:3228
Handle< String > InternalizeUtf8String(base::Vector< const char > str)
Definition factory.cc:608
static void SetContent(DirectHandle< JSArray > array, DirectHandle< FixedArrayBase > storage)
static V8_EXPORT_PRIVATE void AddProperty(Isolate *isolate, DirectHandle< JSObject > object, DirectHandle< Name > name, DirectHandle< Object > value, PropertyAttributes attributes)
static V8_EXPORT_PRIVATE DirectHandle< String > NoSideEffectsToString(Isolate *isolate, DirectHandle< Object > input)
Definition objects.cc:687
static constexpr Tagged< Smi > FromInt(int value)
Definition smi.h:38
static uint32_t HashSequentialString(const char_t *chars, uint32_t length, uint64_t seed)
static DirectHandle< String > ExtractUtf8StringFromModuleBytes(Isolate *, DirectHandle< WasmModuleObject >, wasm::WireBytesRef, InternalizeString)
size_t allocation_size_for_tracing() const
Definition zone.h:197
void Put(uint32_t key, const Value &value)
size_t EstimateCurrentMemoryConsumption() const
const Value * Get(uint32_t key) const
std::unique_ptr< MapType > map_
std::vector< Value > vector_
std::pair< int, int > GetFunctionOffsets(int func_index)
base::OwnedVector< const uint8_t > encoded_offsets_
int GetSourcePosition(int func_index, int byte_offset, bool is_at_number_conversion)
AsmJsOffsetInformation(base::Vector< const uint8_t > encoded_offsets)
std::unique_ptr< AsmJsOffsets > decoded_offsets_
static uint32_t JumpSlotIndexToOffset(uint32_t slot_index)
WireBytesRef LookupFunctionName(ModuleWireBytes wire_bytes, uint32_t function_index)
bool Has(uint32_t function_index)
void AddForTesting(int function_index, WireBytesRef name)
const WasmModule * module() const
const CompileTimeImports & compile_imports() const
V8_EXPORT_PRIVATE const CanonicalSig * LookupFunctionSignature(CanonicalTypeIndex index) const
WellKnownImport get(int index) const
RecordWriteMode const mode_
const MapRef map_
std::vector< T > vector_
Definition sweeper.cc:212
std::optional< TNode< JSArray > > a
ZoneVector< RpoNumber > & result
constexpr Vector< T > VectorOf(T *start, size_t size)
Definition vector.h:360
bool IsCompileTimeImport(WellKnownImport wki)
DirectHandle< JSObject > GetTypeForTable(Isolate *isolate, ValueType type, uint32_t min_size, std::optional< uint64_t > max_size, AddressType address_type)
size_t PrintSignature(base::Vector< char > buffer, const CanonicalSig *sig, char delimiter)
int GetSubtypingDepth(const WasmModule *module, ModuleTypeIndex type_index)
DirectHandle< JSObject > GetTypeForMemory(Isolate *isolate, uint32_t min_size, std::optional< uint64_t > max_size, bool shared, AddressType address_type)
void DecodeFunctionNames(base::Vector< const uint8_t > wire_bytes, NameMap &names)
int GetWasmFunctionOffset(const WasmModule *module, uint32_t func_index)
int JumpTableOffset(const WasmModule *module, int func_index)
int GetContainingWasmFunction(const WasmModule *module, uint32_t byte_offset)
bool is_asmjs_module(const WasmModule *module)
size_t GetWireBytesHash(base::Vector< const uint8_t > wire_bytes)
DirectHandle< JSArray > GetImports(Isolate *isolate, DirectHandle< WasmModuleObject > module_object)
AsmJsOffsetsResult DecodeAsmJsOffsets(base::Vector< const uint8_t > encoded_offsets)
constexpr const char * AddressTypeToStr(AddressType address_type)
Definition wasm-module.h:48
int GetSourcePosition(const WasmModule *module, uint32_t func_index, uint32_t byte_offset, bool is_at_number_conversion)
int GetNearestWasmFunction(const WasmModule *module, uint32_t byte_offset)
size_t ContentSize(const std::vector< T > &vector)
constexpr uint32_t kV8MaxRttSubtypingDepth
Definition wasm-limits.h:65
WasmEngine * GetWasmEngine()
int declared_function_index(const WasmModule *module, int func_index)
DirectHandle< JSArray > GetExports(Isolate *isolate, DirectHandle< WasmModuleObject > module_object)
DirectHandle< JSArray > GetCustomSections(Isolate *isolate, DirectHandle< WasmModuleObject > module_object, DirectHandle< String > name, ErrorThrower *thrower)
std::ostream & operator<<(std::ostream &os, LiftoffVarState slot)
DirectHandle< JSObject > GetTypeForFunction(Isolate *isolate, const FunctionSig *sig, bool for_exception)
std::vector< CustomSectionOffset > DecodeCustomSections(base::Vector< const uint8_t > bytes)
DirectHandle< String > ErrorStringForCodegen(Isolate *isolate, DirectHandle< Context > context)
bool IsWasmCodegenAllowed(Isolate *isolate, DirectHandle< NativeContext > context)
int NumFeedbackSlots(const WasmModule *module, int func_index)
DirectHandle< JSObject > GetTypeForGlobal(Isolate *isolate, bool is_mutable, ValueType type)
void PrintF(const char *format,...)
Definition utils.cc:39
wasm::WasmModule WasmModule
kWasmInternalFunctionIndirectPointerTag kProtectedInstanceDataOffset sig
static const uint64_t kZeroHashSeed
Definition utils.h:267
V8_EXPORT_PRIVATE FlagValues v8_flags
return value
Definition map-inl.h:893
constexpr int kMaxInt
Definition globals.h:374
constexpr uint64_t kInvalidWasmSignatureHash
Definition globals.h:2896
constexpr uint32_t kMaxUInt32
Definition globals.h:387
#define DCHECK_LE(v1, v2)
Definition logging.h:490
#define DCHECK_NE(v1, v2)
Definition logging.h:486
#define DCHECK_GE(v1, v2)
Definition logging.h:488
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_LT(v1, v2)
Definition logging.h:489
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
#define DCHECK_GT(v1, v2)
Definition logging.h:487
#define UPDATE_WHEN_CLASS_CHANGES(classname, size)
bool BoundsCheck(WireBytesRef ref) const
base::Vector< const uint8_t > module_bytes_
WasmName GetNameOrNull(WireBytesRef ref) const
base::Vector< const uint8_t > module_bytes() const
std::unordered_map< uint32_t, FunctionTypeFeedback > feedback_for_function
std::unordered_map< uint32_t, uint32_t > deopt_count_for_function
LazilyGeneratedNames lazily_generated_names
std::vector< TypeDefinition > types
std::vector< CanonicalTypeIndex > isorecursive_canonical_type_ids
CanonicalTypeIndex canonical_type_id(ModuleTypeIndex index) const
std::vector< WasmMemory > memories
std::unique_ptr< AsmJsOffsetInformation > asm_js_offset_information
std::vector< WasmExport > export_table
std::vector< WasmElemSegment > elem_segments
std::vector< WasmImport > import_table
std::vector< WasmStringRefLiteral > stringref_literals
uint64_t signature_hash(const TypeCanonicalizer *, uint32_t function_index) const
CanonicalTypeIndex canonical_sig_id(ModuleTypeIndex index) const
size_t EstimateCurrentMemoryConsumption() const
std::vector< WasmCompilationHint > compilation_hints
std::vector< std::pair< uint32_t, uint32_t > > inst_traces
std::vector< WasmTag > tags
std::vector< WasmGlobal > globals
TypeFeedbackStorage type_feedback
std::vector< WasmDataSegment > data_segments
WasmModule(ModuleOrigin=kWasmOrigin)
std::vector< WasmTable > tables