summaryrefslogtreecommitdiff
path: root/deps/v8/src/wasm/wasm-module.h
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/wasm/wasm-module.h')
-rw-r--r--deps/v8/src/wasm/wasm-module.h221
1 files changed, 147 insertions, 74 deletions
diff --git a/deps/v8/src/wasm/wasm-module.h b/deps/v8/src/wasm/wasm-module.h
index 235d9de4d1..bc96893274 100644
--- a/deps/v8/src/wasm/wasm-module.h
+++ b/deps/v8/src/wasm/wasm-module.h
@@ -24,6 +24,7 @@
#include "src/wasm/wasm-constants.h"
#include "src/wasm/wasm-init-expr.h"
#include "src/wasm/wasm-limits.h"
+#include "src/wasm/well-known-imports.h"
namespace v8::internal {
class WasmModuleObject;
@@ -35,6 +36,7 @@ using WasmName = base::Vector<const char>;
struct AsmJsOffsets;
class ErrorThrower;
+class WellKnownImportsList;
// Reference to a string in the wire bytes.
class WireBytesRef {
@@ -90,10 +92,12 @@ using WasmTagSig = FunctionSig;
// Static representation of a wasm tag type.
struct WasmTag {
- explicit WasmTag(const WasmTagSig* sig) : sig(sig) {}
+ explicit WasmTag(const WasmTagSig* sig, uint32_t sig_index)
+ : sig(sig), sig_index(sig_index) {}
const FunctionSig* ToFunctionSig() const { return sig; }
const WasmTagSig* sig; // type signature of the tag.
+ uint32_t sig_index;
};
// Static representation of a wasm literal stringref.
@@ -127,17 +131,26 @@ struct WasmElemSegment {
// Construct an active segment.
WasmElemSegment(ValueType type, uint32_t table_index,
- ConstantExpression offset, ElementType element_type)
+ ConstantExpression offset, ElementType element_type,
+ uint32_t element_count, uint32_t elements_wire_bytes_offset)
: status(kStatusActive),
type(type),
table_index(table_index),
offset(std::move(offset)),
- element_type(element_type) {}
+ element_type(element_type),
+ element_count(element_count),
+ elements_wire_bytes_offset(elements_wire_bytes_offset) {}
// Construct a passive or declarative segment, which has no table index or
// offset.
- WasmElemSegment(ValueType type, Status status, ElementType element_type)
- : status(status), type(type), table_index(0), element_type(element_type) {
+ WasmElemSegment(ValueType type, Status status, ElementType element_type,
+ uint32_t element_count, uint32_t elements_wire_bytes_offset)
+ : status(status),
+ type(type),
+ table_index(0),
+ element_type(element_type),
+ element_count(element_count),
+ elements_wire_bytes_offset(elements_wire_bytes_offset) {
DCHECK_NE(status, kStatusActive);
}
@@ -146,7 +159,9 @@ struct WasmElemSegment {
: status(kStatusActive),
type(kWasmBottom),
table_index(0),
- element_type(kFunctionIndexElements) {}
+ element_type(kFunctionIndexElements),
+ element_count(0),
+ elements_wire_bytes_offset(0) {}
WasmElemSegment(const WasmElemSegment&) = delete;
WasmElemSegment(WasmElemSegment&&) V8_NOEXCEPT = default;
@@ -158,7 +173,8 @@ struct WasmElemSegment {
uint32_t table_index;
ConstantExpression offset;
ElementType element_type;
- std::vector<ConstantExpression> entries;
+ uint32_t element_count;
+ uint32_t elements_wire_bytes_offset;
};
// Static representation of a wasm import.
@@ -286,7 +302,7 @@ struct ModuleWireBytes;
class V8_EXPORT_PRIVATE LazilyGeneratedNames {
public:
- WireBytesRef LookupFunctionName(const ModuleWireBytes& wire_bytes,
+ WireBytesRef LookupFunctionName(ModuleWireBytes wire_bytes,
uint32_t function_index);
void AddForTesting(int function_index, WireBytesRef name);
@@ -334,23 +350,30 @@ constexpr uint32_t kNoSuperType = std::numeric_limits<uint32_t>::max();
struct TypeDefinition {
enum Kind { kFunction, kStruct, kArray };
- TypeDefinition(const FunctionSig* sig, uint32_t supertype)
- : function_sig(sig), supertype(supertype), kind(kFunction) {}
- TypeDefinition(const StructType* type, uint32_t supertype)
- : struct_type(type), supertype(supertype), kind(kStruct) {}
- TypeDefinition(const ArrayType* type, uint32_t supertype)
- : array_type(type), supertype(supertype), kind(kArray) {}
+ TypeDefinition(const FunctionSig* sig, uint32_t supertype, bool is_final)
+ : function_sig(sig),
+ supertype(supertype),
+ kind(kFunction),
+ is_final(is_final) {}
+ TypeDefinition(const StructType* type, uint32_t supertype, bool is_final)
+ : struct_type(type),
+ supertype(supertype),
+ kind(kStruct),
+ is_final(is_final) {}
+ TypeDefinition(const ArrayType* type, uint32_t supertype, bool is_final)
+ : array_type(type),
+ supertype(supertype),
+ kind(kArray),
+ is_final(is_final) {}
TypeDefinition()
- : function_sig(nullptr), supertype(kNoSuperType), kind(kFunction) {}
-
- union {
- const FunctionSig* function_sig;
- const StructType* struct_type;
- const ArrayType* array_type;
- };
+ : function_sig(nullptr),
+ supertype(kNoSuperType),
+ kind(kFunction),
+ is_final(false) {}
bool operator==(const TypeDefinition& other) const {
- if (supertype != other.supertype || kind != other.kind) {
+ if (supertype != other.supertype || kind != other.kind ||
+ is_final != other.is_final) {
return false;
}
switch (kind) {
@@ -367,8 +390,14 @@ struct TypeDefinition {
return !(*this == other);
}
+ union {
+ const FunctionSig* function_sig;
+ const StructType* struct_type;
+ const ArrayType* array_type;
+ };
uint32_t supertype;
Kind kind;
+ bool is_final;
};
struct V8_EXPORT_PRIVATE WasmDebugSymbols {
@@ -473,16 +502,32 @@ struct FunctionTypeFeedback {
struct TypeFeedbackStorage {
std::unordered_map<uint32_t, FunctionTypeFeedback> feedback_for_function;
// Accesses to {feedback_for_function} are guarded by this mutex.
- mutable base::Mutex mutex;
+ // Multiple reads are allowed (shared lock), but only exclusive writes.
+ // Currently known users of the mutex are:
+ // - LiftoffCompiler: writes {call_targets}.
+ // - TransitiveTypeFeedbackProcessor: reads {call_targets},
+ // writes {feedback_vector}, reads {feedback_vector.size()}.
+ // - TriggerTierUp: increments {tierup_priority}.
+ // - WasmGraphBuilder: reads {feedback_vector}.
+ // - Feedback vector allocation: reads {call_targets.size()}.
+ // - PGO ProfileGenerator: reads everything.
+ // - PGO deserializer: writes everything, currently not locked, relies on
+ // being called before multi-threading enters the picture.
+ mutable base::SharedMutex mutex;
+
+ WellKnownImportsList well_known_imports;
};
struct WasmTable;
// Static representation of a module.
struct V8_EXPORT_PRIVATE WasmModule {
- std::unique_ptr<Zone> signature_zone;
+ // ================ Fields ===================================================
+ Zone signature_zone;
uint32_t initial_pages = 0; // initial size of the memory in 64k pages
uint32_t maximum_pages = 0; // maximum size of the memory in 64k pages
+ uintptr_t min_memory_size = 0; // smallest size of any memory in bytes
+ uintptr_t max_memory_size = 0; // largest size of any memory in bytes
bool has_shared_memory = false; // true if memory is a SharedArrayBuffer
bool has_maximum_pages = false; // true if there is a maximum memory size
bool is_memory64 = false; // true if the memory is 64 bit
@@ -510,8 +555,49 @@ struct V8_EXPORT_PRIVATE WasmModule {
// ID and length).
WireBytesRef name_section = {0, 0};
- AccountingAllocator* allocator() const { return signature_zone->allocator(); }
+ std::vector<TypeDefinition> types; // by type index
+ // Maps each type index to its global (cross-module) canonical index as per
+ // isorecursive type canonicalization.
+ std::vector<uint32_t> isorecursive_canonical_type_ids;
+ std::vector<WasmFunction> functions;
+ std::vector<WasmGlobal> globals;
+ std::vector<WasmDataSegment> data_segments;
+ std::vector<WasmTable> tables;
+ std::vector<WasmImport> import_table;
+ std::vector<WasmExport> export_table;
+ std::vector<WasmTag> tags;
+ std::vector<WasmStringRefLiteral> stringref_literals;
+ std::vector<WasmElemSegment> elem_segments;
+ std::vector<WasmCompilationHint> compilation_hints;
+ BranchHintInfo branch_hints;
+ // Pairs of module offsets and mark id.
+ std::vector<std::pair<uint32_t, uint32_t>> inst_traces;
+
+ // This is the only member of {WasmModule} where we store dynamic information
+ // that's not a decoded representation of the wire bytes.
+ // TODO(jkummerow): Rename.
+ mutable TypeFeedbackStorage type_feedback;
+
+ const ModuleOrigin origin;
+ mutable LazilyGeneratedNames lazily_generated_names;
+ WasmDebugSymbols debug_symbols;
+
+ // Asm.js source position information. Only available for modules compiled
+ // from asm.js.
+ std::unique_ptr<AsmJsOffsetInformation> asm_js_offset_information;
+ // {validated_functions} is atomically updated when functions get validated
+ // (during compilation, streaming decoding, or via explicit validation).
+ static_assert(sizeof(std::atomic<uint8_t>) == 1);
+ static_assert(alignof(std::atomic<uint8_t>) == 1);
+ mutable std::unique_ptr<std::atomic<uint8_t>[]> validated_functions;
+
+ // ================ Constructors =============================================
+ explicit WasmModule(ModuleOrigin = kWasmOrigin);
+ WasmModule(const WasmModule&) = delete;
+ WasmModule& operator=(const WasmModule&) = delete;
+
+ // ================ Accessors ================================================
void add_type(TypeDefinition type) {
types.push_back(type);
// Isorecursive canonical type will be computed later.
@@ -520,9 +606,10 @@ struct V8_EXPORT_PRIVATE WasmModule {
bool has_type(uint32_t index) const { return index < types.size(); }
- void add_signature(const FunctionSig* sig, uint32_t supertype) {
+ void add_signature(const FunctionSig* sig, uint32_t supertype,
+ bool is_final) {
DCHECK_NOT_NULL(sig);
- add_type(TypeDefinition(sig, supertype));
+ add_type(TypeDefinition(sig, supertype, is_final));
}
bool has_signature(uint32_t index) const {
return index < types.size() &&
@@ -530,35 +617,44 @@ struct V8_EXPORT_PRIVATE WasmModule {
}
const FunctionSig* signature(uint32_t index) const {
DCHECK(has_signature(index));
+ size_t num_types = types.size();
+ V8_ASSUME(index < num_types);
return types[index].function_sig;
}
- void add_struct_type(const StructType* type, uint32_t supertype) {
+ void add_struct_type(const StructType* type, uint32_t supertype,
+ bool is_final) {
DCHECK_NOT_NULL(type);
- add_type(TypeDefinition(type, supertype));
+ add_type(TypeDefinition(type, supertype, is_final));
}
bool has_struct(uint32_t index) const {
return index < types.size() && types[index].kind == TypeDefinition::kStruct;
}
const StructType* struct_type(uint32_t index) const {
DCHECK(has_struct(index));
+ size_t num_types = types.size();
+ V8_ASSUME(index < num_types);
return types[index].struct_type;
}
- void add_array_type(const ArrayType* type, uint32_t supertype) {
+ void add_array_type(const ArrayType* type, uint32_t supertype,
+ bool is_final) {
DCHECK_NOT_NULL(type);
- add_type(TypeDefinition(type, supertype));
+ add_type(TypeDefinition(type, supertype, is_final));
}
bool has_array(uint32_t index) const {
return index < types.size() && types[index].kind == TypeDefinition::kArray;
}
const ArrayType* array_type(uint32_t index) const {
DCHECK(has_array(index));
+ size_t num_types = types.size();
+ V8_ASSUME(index < num_types);
return types[index].array_type;
}
uint32_t supertype(uint32_t index) const {
- DCHECK(index < types.size());
+ size_t num_types = types.size();
+ V8_ASSUME(index < num_types);
return types[index].supertype;
}
bool has_supertype(uint32_t index) const {
@@ -580,10 +676,12 @@ struct V8_EXPORT_PRIVATE WasmModule {
DCHECK_LE(pos, num_declared_functions);
uint8_t byte =
validated_functions[pos >> 3].load(std::memory_order_relaxed);
+ DCHECK_IMPLIES(origin != kWasmOrigin, byte == 0xff);
return byte & (1 << (pos & 7));
}
void set_function_validated(int func_index) const {
+ DCHECK_EQ(kWasmOrigin, origin);
DCHECK_NOT_NULL(validated_functions);
DCHECK_LE(num_imported_functions, func_index);
int pos = func_index - num_imported_functions;
@@ -598,46 +696,19 @@ struct V8_EXPORT_PRIVATE WasmModule {
}
}
+ void set_all_functions_validated() const {
+ DCHECK_EQ(kWasmOrigin, origin);
+ if (num_declared_functions == 0) return;
+ DCHECK_NOT_NULL(validated_functions);
+ size_t num_words = (num_declared_functions + 7) / 8;
+ for (size_t i = 0; i < num_words; ++i) {
+ validated_functions[i].store(0xff, std::memory_order_relaxed);
+ }
+ }
+
base::Vector<const WasmFunction> declared_functions() const {
return base::VectorOf(functions) + num_imported_functions;
}
-
- std::vector<TypeDefinition> types; // by type index
- // Maps each type index to its global (cross-module) canonical index as per
- // isorecursive type canonicalization.
- std::vector<uint32_t> isorecursive_canonical_type_ids;
- std::vector<WasmFunction> functions;
- std::vector<WasmGlobal> globals;
- std::vector<WasmDataSegment> data_segments;
- std::vector<WasmTable> tables;
- std::vector<WasmImport> import_table;
- std::vector<WasmExport> export_table;
- std::vector<WasmTag> tags;
- std::vector<WasmStringRefLiteral> stringref_literals;
- std::vector<WasmElemSegment> elem_segments;
- std::vector<WasmCompilationHint> compilation_hints;
- BranchHintInfo branch_hints;
- // Pairs of module offsets and mark id.
- std::vector<std::pair<uint32_t, uint32_t>> inst_traces;
- mutable TypeFeedbackStorage type_feedback;
-
- ModuleOrigin origin = kWasmOrigin; // origin of the module
- mutable LazilyGeneratedNames lazily_generated_names;
- WasmDebugSymbols debug_symbols;
-
- // Asm.js source position information. Only available for modules compiled
- // from asm.js.
- std::unique_ptr<AsmJsOffsetInformation> asm_js_offset_information;
-
- // {validated_functions} is atomically updated when functions get validated
- // (during compilation, streaming decoding, or via explicit validation).
- static_assert(sizeof(std::atomic<uint8_t>) == 1);
- static_assert(alignof(std::atomic<uint8_t>) == 1);
- mutable std::unique_ptr<std::atomic<uint8_t>[]> validated_functions;
-
- explicit WasmModule(std::unique_ptr<Zone> signature_zone = nullptr);
- WasmModule(const WasmModule&) = delete;
- WasmModule& operator=(const WasmModule&) = delete;
};
// Static representation of a wasm indirect call table.
@@ -689,6 +760,8 @@ V8_EXPORT_PRIVATE int GetSubtypingDepth(const WasmModule* module,
// It is illegal for anyone receiving a ModuleWireBytes to store pointers based
// on module_bytes, as this storage is only guaranteed to be alive as long as
// this struct is alive.
+// As {ModuleWireBytes} is just a wrapper around a {base::Vector<const byte>},
+// it should generally be passed by value.
struct V8_EXPORT_PRIVATE ModuleWireBytes {
explicit ModuleWireBytes(base::Vector<const byte> module_bytes)
: module_bytes_(module_bytes) {}
@@ -701,8 +774,7 @@ struct V8_EXPORT_PRIVATE ModuleWireBytes {
WasmName GetNameOrNull(WireBytesRef ref) const;
// Get a string stored in the module bytes representing a function name.
- WasmName GetNameOrNull(const WasmFunction* function,
- const WasmModule* module) const;
+ WasmName GetNameOrNull(int func_index, const WasmModule* module) const;
// Checks the given reference is contained within the module bytes.
bool BoundsCheck(WireBytesRef ref) const {
@@ -724,13 +796,14 @@ struct V8_EXPORT_PRIVATE ModuleWireBytes {
private:
base::Vector<const byte> module_bytes_;
};
+ASSERT_TRIVIALLY_COPYABLE(ModuleWireBytes);
// A helper for printing out the names of functions.
struct WasmFunctionName {
- WasmFunctionName(const WasmFunction* function, WasmName name)
- : function_(function), name_(name) {}
+ WasmFunctionName(int func_index, WasmName name)
+ : func_index_(func_index), name_(name) {}
- const WasmFunction* function_;
+ const int func_index_;
const WasmName name_;
};