Commit cab9ad05 authored by Manos Koukoutos's avatar Manos Koukoutos Committed by V8 LUCI CQ

[wasm] Documentation and small cleanups

Change-Id: Ia3ef956926b54add138936e3e7d03a0faa457ff9
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3913127Reviewed-by: 's avatarSimon Zünd <szuend@chromium.org>
Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Cr-Commit-Position: refs/heads/main@{#83422}
parent 6eb99796
...@@ -17,9 +17,8 @@ namespace compiler { ...@@ -17,9 +17,8 @@ namespace compiler {
class MachineGraph; class MachineGraph;
// Eliminate allocated objects which are only assigned to. // Eliminate allocated objects with no uses other than as store targets.
// Current restrictions: Does not work for arrays (until they are also allocated // Future work: Also exclude phis and renamings from uses.
// with AllocateRaw). Does not work if the allocated object is passed to a phi.
class WasmEscapeAnalysis final : public AdvancedReducer { class WasmEscapeAnalysis final : public AdvancedReducer {
public: public:
WasmEscapeAnalysis(Editor* editor, MachineGraph* mcgraph) WasmEscapeAnalysis(Editor* editor, MachineGraph* mcgraph)
......
...@@ -117,6 +117,9 @@ wasm::TypeInModule WasmGCOperatorReducer::ObjectTypeFromContext(Node* object, ...@@ -117,6 +117,9 @@ wasm::TypeInModule WasmGCOperatorReducer::ObjectTypeFromContext(Node* object,
: type_from_node; : type_from_node;
} }
// If the condition of this node's branch is a type check or a null check,
// add the additional information about the type-checked node to the path
// state.
Reduction WasmGCOperatorReducer::ReduceIf(Node* node, bool condition) { Reduction WasmGCOperatorReducer::ReduceIf(Node* node, bool condition) {
DCHECK(node->opcode() == IrOpcode::kIfTrue || DCHECK(node->opcode() == IrOpcode::kIfTrue ||
node->opcode() == IrOpcode::kIfFalse); node->opcode() == IrOpcode::kIfFalse);
...@@ -184,7 +187,7 @@ Reduction WasmGCOperatorReducer::ReduceMerge(Node* node) { ...@@ -184,7 +187,7 @@ Reduction WasmGCOperatorReducer::ReduceMerge(Node* node) {
// Change the current type block list to a longest common prefix of this // Change the current type block list to a longest common prefix of this
// state list and the other list. (The common prefix should correspond to // state list and the other list. (The common prefix should correspond to
// the state of the common dominator.) // the state of the common dominator.)
// TODO(manoskouk): Consider computing intersections for some types. // TODO(manoskouk): Consider computing unions for some types.
types.ResetToCommonAncestor(GetState(*input_it)); types.ResetToCommonAncestor(GetState(*input_it));
} }
return UpdateStates(node, types); return UpdateStates(node, types);
......
...@@ -35,9 +35,11 @@ struct NodeWithType { ...@@ -35,9 +35,11 @@ struct NodeWithType {
wasm::TypeInModule type; wasm::TypeInModule type;
}; };
// This class optimizes away wasm-gc nodes based on the types of their // This class optimizes away wasm-gc type checks and casts. Two types of
// arguments. Although types have been assigned to nodes already, this class // information are used:
// also tracks additional type information along control paths. // - Types already marked on graph nodes.
// - Path-dependent type information that is inferred when a type check is used
// as a branch condition.
class WasmGCOperatorReducer final class WasmGCOperatorReducer final
: public AdvancedReducerWithControlPathState<NodeWithType, : public AdvancedReducerWithControlPathState<NodeWithType,
kMultipleInstances> { kMultipleInstances> {
...@@ -61,6 +63,8 @@ class WasmGCOperatorReducer final ...@@ -61,6 +63,8 @@ class WasmGCOperatorReducer final
Reduction ReduceStart(Node* node); Reduction ReduceStart(Node* node);
Node* SetType(Node* node, wasm::ValueType type); Node* SetType(Node* node, wasm::ValueType type);
// Returns the intersection of the type marked on {object} and the type
// information about object tracked on {control}'s control path (if present).
wasm::TypeInModule ObjectTypeFromContext(Node* object, Node* control); wasm::TypeInModule ObjectTypeFromContext(Node* object, Node* control);
Reduction UpdateNodeAndAliasesTypes(Node* state_owner, Reduction UpdateNodeAndAliasesTypes(Node* state_owner,
ControlPathTypes parent_state, Node* node, ControlPathTypes parent_state, Node* node,
......
...@@ -55,7 +55,12 @@ class WasmInliner final : public AdvancedReducer { ...@@ -55,7 +55,12 @@ class WasmInliner final : public AdvancedReducer {
const char* reducer_name() const override { return "WasmInliner"; } const char* reducer_name() const override { return "WasmInliner"; }
// Registers (tail) calls to possibly be inlined, prioritized by inlining
// heuristics provided by {LexicographicOrdering}.
// Only locally defined functions are inlinable, and a limited number of
// inlinings of a specific function is allowed.
Reduction Reduce(Node* node) final; Reduction Reduce(Node* node) final;
// Inlines calls registered by {Reduce}, until an inlining budget is exceeded.
void Finalize() final; void Finalize() final;
static bool graph_size_allows_inlining(size_t graph_size) { static bool graph_size_allows_inlining(size_t graph_size) {
......
...@@ -18,6 +18,11 @@ namespace compiler { ...@@ -18,6 +18,11 @@ namespace compiler {
class MachineGraph; class MachineGraph;
// Recomputes wasm-gc types along the graph to assign the narrowest possible
// type to each node.
// Specifically, struct field accesses, array element accesses, phis, type
// casts, and type guards are retyped.
// Types in loops are computed to a fixed point.
class WasmTyper final : public AdvancedReducer { class WasmTyper final : public AdvancedReducer {
public: public:
WasmTyper(Editor* editor, MachineGraph* mcgraph, uint32_t function_index); WasmTyper(Editor* editor, MachineGraph* mcgraph, uint32_t function_index);
......
...@@ -964,13 +964,7 @@ Handle<WasmValueObject> WasmValueObject::New( ...@@ -964,13 +964,7 @@ Handle<WasmValueObject> WasmValueObject::New(
} }
break; break;
} }
case wasm::kRtt: { case wasm::kRtt:
// TODO(7748): Expose RTTs to DevTools.
t = isolate->factory()->InternalizeString(base::StaticCharVector("rtt"));
v = isolate->factory()->InternalizeString(
base::StaticCharVector("(unimplemented)"));
break;
}
case wasm::kVoid: case wasm::kVoid:
case wasm::kBottom: case wasm::kBottom:
UNREACHABLE(); UNREACHABLE();
......
...@@ -1880,7 +1880,6 @@ void AsmWasmData::AsmWasmDataPrint(std::ostream& os) { ...@@ -1880,7 +1880,6 @@ void AsmWasmData::AsmWasmDataPrint(std::ostream& os) {
void WasmTypeInfo::WasmTypeInfoPrint(std::ostream& os) { void WasmTypeInfo::WasmTypeInfoPrint(std::ostream& os) {
PrintHeader(os, "WasmTypeInfo"); PrintHeader(os, "WasmTypeInfo");
os << "\n - type address: " << reinterpret_cast<void*>(native_type()); os << "\n - type address: " << reinterpret_cast<void*>(native_type());
// TODO(manoskouk): Print supertype info.
os << "\n - supertypes: "; os << "\n - supertypes: ";
for (int i = 0; i < supertypes_length(); i++) { for (int i = 0; i < supertypes_length(); i++) {
os << "\n - " << Brief(supertypes(i)); os << "\n - " << Brief(supertypes(i));
......
...@@ -1562,10 +1562,10 @@ void PushArgs(const i::wasm::FunctionSig* sig, const Val args[], ...@@ -1562,10 +1562,10 @@ void PushArgs(const i::wasm::FunctionSig* sig, const Val args[],
// TODO(7748): Make sure this works for all heap types. // TODO(7748): Make sure this works for all heap types.
packer->Push(WasmRefToV8(store->i_isolate(), args[i].ref())->ptr()); packer->Push(WasmRefToV8(store->i_isolate(), args[i].ref())->ptr());
break; break;
case i::wasm::kRtt:
case i::wasm::kS128: case i::wasm::kS128:
// TODO(7748): Implement. // TODO(7748): Implement.
UNIMPLEMENTED(); UNIMPLEMENTED();
case i::wasm::kRtt:
case i::wasm::kI8: case i::wasm::kI8:
case i::wasm::kI16: case i::wasm::kI16:
case i::wasm::kVoid: case i::wasm::kVoid:
...@@ -1601,10 +1601,10 @@ void PopArgs(const i::wasm::FunctionSig* sig, Val results[], ...@@ -1601,10 +1601,10 @@ void PopArgs(const i::wasm::FunctionSig* sig, Val results[],
results[i] = Val(V8RefValueToWasm(store, obj)); results[i] = Val(V8RefValueToWasm(store, obj));
break; break;
} }
case i::wasm::kRtt:
case i::wasm::kS128: case i::wasm::kS128:
// TODO(7748): Implement. // TODO(7748): Implement.
UNIMPLEMENTED(); UNIMPLEMENTED();
case i::wasm::kRtt:
case i::wasm::kI8: case i::wasm::kI8:
case i::wasm::kI16: case i::wasm::kI16:
case i::wasm::kVoid: case i::wasm::kVoid:
...@@ -1869,10 +1869,10 @@ auto Global::get() const -> Val { ...@@ -1869,10 +1869,10 @@ auto Global::get() const -> Val {
} }
return Val(V8RefValueToWasm(store, result)); return Val(V8RefValueToWasm(store, result));
} }
case i::wasm::kRtt:
case i::wasm::kS128: case i::wasm::kS128:
// TODO(7748): Implement these. // TODO(7748): Implement these.
UNIMPLEMENTED(); UNIMPLEMENTED();
case i::wasm::kRtt:
case i::wasm::kI8: case i::wasm::kI8:
case i::wasm::kI16: case i::wasm::kI16:
case i::wasm::kVoid: case i::wasm::kVoid:
......
...@@ -83,8 +83,6 @@ uint32_t TypeCanonicalizer::AddRecursiveGroup(const FunctionSig* sig) { ...@@ -83,8 +83,6 @@ uint32_t TypeCanonicalizer::AddRecursiveGroup(const FunctionSig* sig) {
return canonical_index; return canonical_index;
} }
// An index in a type gets mapped to a relative index if it is inside the new
// canonical group, or the canonical representative if it is not.
ValueType TypeCanonicalizer::CanonicalizeValueType( ValueType TypeCanonicalizer::CanonicalizeValueType(
const WasmModule* module, ValueType type, const WasmModule* module, ValueType type,
uint32_t recursive_group_start) const { uint32_t recursive_group_start) const {
...@@ -116,8 +114,6 @@ bool TypeCanonicalizer::IsCanonicalSubtype(uint32_t sub_index, ...@@ -116,8 +114,6 @@ bool TypeCanonicalizer::IsCanonicalSubtype(uint32_t sub_index,
return false; return false;
} }
// Map all type indices (including supertype) inside {type} to indices
// relative to {recursive_group_start}.
TypeCanonicalizer::CanonicalType TypeCanonicalizer::CanonicalizeTypeDef( TypeCanonicalizer::CanonicalType TypeCanonicalizer::CanonicalizeTypeDef(
const WasmModule* module, TypeDefinition type, const WasmModule* module, TypeDefinition type,
uint32_t recursive_group_start) { uint32_t recursive_group_start) {
......
...@@ -21,8 +21,8 @@ namespace wasm { ...@@ -21,8 +21,8 @@ namespace wasm {
// types. // types.
// A recursive group is a subsequence of types explicitly marked in the type // A recursive group is a subsequence of types explicitly marked in the type
// section of a wasm module. Identical recursive groups have to be canonicalized // section of a wasm module. Identical recursive groups have to be canonicalized
// to a single canonical group and are considered identical. Respective // to a single canonical group. Respective types in two identical groups are
// types in two identical groups are considered identical for all purposes. // considered identical for all purposes.
// Two groups are considered identical if they have the same shape, and all // Two groups are considered identical if they have the same shape, and all
// type indices referenced in the same position in both groups reference: // type indices referenced in the same position in both groups reference:
// - identical types, if those do not belong to the rec. group, // - identical types, if those do not belong to the rec. group,
...@@ -105,9 +105,15 @@ class TypeCanonicalizer { ...@@ -105,9 +105,15 @@ class TypeCanonicalizer {
int FindCanonicalGroup(CanonicalGroup&) const; int FindCanonicalGroup(CanonicalGroup&) const;
// Canonicalize all types present in {type} (including supertype) according to
// {CanonicalizeValueType}.
CanonicalType CanonicalizeTypeDef(const WasmModule* module, CanonicalType CanonicalizeTypeDef(const WasmModule* module,
TypeDefinition type, TypeDefinition type,
uint32_t recursive_group_start); uint32_t recursive_group_start);
// An indexed type gets mapped to a {ValueType::CanonicalWithRelativeIndex}
// if its index points inside the new canonical group; otherwise, the index
// gets mapped to its canonical representative.
ValueType CanonicalizeValueType(const WasmModule* module, ValueType type, ValueType CanonicalizeValueType(const WasmModule* module, ValueType type,
uint32_t recursive_group_start) const; uint32_t recursive_group_start) const;
......
...@@ -21,12 +21,13 @@ class JSArrayBuffer; ...@@ -21,12 +21,13 @@ class JSArrayBuffer;
namespace wasm { namespace wasm {
// An interface for WasmFullDecoder used to decode constant expressions. This // An interface for WasmFullDecoder used to decode constant expressions.
// interface has two modes: only validation (when {isolate_ == nullptr}), which // This interface has two modes: only validation (when {isolate_ == nullptr}),
// is used in module-decoder, and code-generation (when {isolate_ != nullptr}), // and code-generation (when {isolate_ != nullptr}). We merge two distinct
// which is used in module-instantiate. We merge two distinct functionalities // functionalities in one class to reduce the number of WasmFullDecoder
// in one class to reduce the number of WasmFullDecoder instantiations, and thus // instantiations, and thus V8 binary code size.
// V8 binary code size. // In code-generation mode, the result can be retrieved with {computed_value()}
// if {!has_error()}, or with {error()} otherwise.
class V8_EXPORT_PRIVATE ConstantExpressionInterface { class V8_EXPORT_PRIVATE ConstantExpressionInterface {
public: public:
static constexpr Decoder::ValidateFlag validate = Decoder::kFullValidation; static constexpr Decoder::ValidateFlag validate = Decoder::kFullValidation;
......
...@@ -924,8 +924,7 @@ struct ControlBase : public PcForErrors<validate> { ...@@ -924,8 +924,7 @@ struct ControlBase : public PcForErrors<validate> {
F(StartFunctionBody, Control* block) \ F(StartFunctionBody, Control* block) \
F(FinishFunction) \ F(FinishFunction) \
F(OnFirstError) \ F(OnFirstError) \
F(NextInstruction, WasmOpcode) \ F(NextInstruction, WasmOpcode)
F(Forward, const Value& from, Value* to)
#define INTERFACE_CONSTANT_FUNCTIONS(F) /* force 80 columns */ \ #define INTERFACE_CONSTANT_FUNCTIONS(F) /* force 80 columns */ \
F(I32Const, Value* result, int32_t value) \ F(I32Const, Value* result, int32_t value) \
...@@ -979,6 +978,7 @@ struct ControlBase : public PcForErrors<validate> { ...@@ -979,6 +978,7 @@ struct ControlBase : public PcForErrors<validate> {
const IndexImmediate<validate>& imm) \ const IndexImmediate<validate>& imm) \
F(Trap, TrapReason reason) \ F(Trap, TrapReason reason) \
F(NopForTestingUnsupportedInLiftoff) \ F(NopForTestingUnsupportedInLiftoff) \
F(Forward, const Value& from, Value* to) \
F(Select, const Value& cond, const Value& fval, const Value& tval, \ F(Select, const Value& cond, const Value& fval, const Value& tval, \
Value* result) \ Value* result) \
F(BrOrRet, uint32_t depth, uint32_t drop_values) \ F(BrOrRet, uint32_t depth, uint32_t drop_values) \
......
...@@ -44,7 +44,7 @@ struct WasmCompilationResult { ...@@ -44,7 +44,7 @@ struct WasmCompilationResult {
bool succeeded() const { return code_desc.buffer != nullptr; } bool succeeded() const { return code_desc.buffer != nullptr; }
bool failed() const { return !succeeded(); } bool failed() const { return !succeeded(); }
operator bool() const { return succeeded(); } explicit operator bool() const { return succeeded(); }
CodeDesc code_desc; CodeDesc code_desc;
std::unique_ptr<AssemblerBuffer> instr_buffer; std::unique_ptr<AssemblerBuffer> instr_buffer;
......
...@@ -1685,7 +1685,6 @@ class WasmGraphBuildingInterface { ...@@ -1685,7 +1685,6 @@ class WasmGraphBuildingInterface {
TFNode* if_success = nullptr; TFNode* if_success = nullptr;
TFNode* if_exception = nullptr; TFNode* if_exception = nullptr;
// TODO(manoskouk): Can we assign a wasm type to the exception value?
if (!builder_->ThrowsException(node, &if_success, &if_exception)) { if (!builder_->ThrowsException(node, &if_success, &if_exception)) {
return node; return node;
} }
...@@ -2073,7 +2072,6 @@ class WasmGraphBuildingInterface { ...@@ -2073,7 +2072,6 @@ class WasmGraphBuildingInterface {
} }
} }
if (exception_value != nullptr) { if (exception_value != nullptr) {
// TODO(manoskouk): Can we assign a wasm type to the exception value?
*exception_value = builder_->LoopExitValue( *exception_value = builder_->LoopExitValue(
*exception_value, MachineRepresentation::kWord32); *exception_value, MachineRepresentation::kWord32);
} }
......
...@@ -1345,7 +1345,7 @@ class ModuleDecoderTemplate : public Decoder { ...@@ -1345,7 +1345,7 @@ class ModuleDecoderTemplate : public Decoder {
int64_t last_func_idx = -1; int64_t last_func_idx = -1;
for (uint32_t i = 0; i < func_count; i++) { for (uint32_t i = 0; i < func_count; i++) {
uint32_t func_idx = inner.consume_u32v("function index"); uint32_t func_idx = inner.consume_u32v("function index");
if (int64_t(func_idx) <= last_func_idx) { if (int64_t{func_idx} <= last_func_idx) {
inner.errorf("Invalid function index: %d", func_idx); inner.errorf("Invalid function index: %d", func_idx);
break; break;
} }
...@@ -1365,7 +1365,7 @@ class ModuleDecoderTemplate : public Decoder { ...@@ -1365,7 +1365,7 @@ class ModuleDecoderTemplate : public Decoder {
for (uint32_t k = 0; k < mark_size; k++) { for (uint32_t k = 0; k < mark_size; k++) {
trace_mark_id |= inner.consume_u8("trace mark id") << k * 8; trace_mark_id |= inner.consume_u8("trace mark id") << k * 8;
} }
if (int64_t(func_off) <= last_func_off) { if (int64_t{func_off} <= last_func_off) {
inner.errorf("Invalid branch offset: %d", func_off); inner.errorf("Invalid branch offset: %d", func_off);
break; break;
} }
...@@ -1504,7 +1504,7 @@ class ModuleDecoderTemplate : public Decoder { ...@@ -1504,7 +1504,7 @@ class ModuleDecoderTemplate : public Decoder {
int64_t last_func_idx = -1; int64_t last_func_idx = -1;
for (uint32_t i = 0; i < func_count; i++) { for (uint32_t i = 0; i < func_count; i++) {
uint32_t func_idx = inner.consume_u32v("function index"); uint32_t func_idx = inner.consume_u32v("function index");
if (int64_t(func_idx) <= last_func_idx) { if (int64_t{func_idx} <= last_func_idx) {
inner.errorf("Invalid function index: %d", func_idx); inner.errorf("Invalid function index: %d", func_idx);
break; break;
} }
...@@ -1517,7 +1517,7 @@ class ModuleDecoderTemplate : public Decoder { ...@@ -1517,7 +1517,7 @@ class ModuleDecoderTemplate : public Decoder {
int64_t last_br_off = -1; int64_t last_br_off = -1;
for (uint32_t j = 0; j < num_hints; ++j) { for (uint32_t j = 0; j < num_hints; ++j) {
uint32_t br_off = inner.consume_u32v("branch instruction offset"); uint32_t br_off = inner.consume_u32v("branch instruction offset");
if (int64_t(br_off) <= last_br_off) { if (int64_t{br_off} <= last_br_off) {
inner.errorf("Invalid branch offset: %d", br_off); inner.errorf("Invalid branch offset: %d", br_off);
break; break;
} }
......
...@@ -24,6 +24,7 @@ class WasmFeatures; ...@@ -24,6 +24,7 @@ class WasmFeatures;
// Representation of an constant expression. Unlike {ConstantExpression}, this // Representation of an constant expression. Unlike {ConstantExpression}, this
// does not use {WireBytesRef}, i.e., it does not depend on a wasm module's // does not use {WireBytesRef}, i.e., it does not depend on a wasm module's
// bytecode representation. // bytecode representation.
// TODO(manoskouk): Add missing kinds of expressions.
class WasmInitExpr : public ZoneObject { class WasmInitExpr : public ZoneObject {
public: public:
enum Operator { enum Operator {
......
...@@ -1565,8 +1565,6 @@ void WebAssemblyGlobal(const v8::FunctionCallbackInfo<v8::Value>& args) { ...@@ -1565,8 +1565,6 @@ void WebAssemblyGlobal(const v8::FunctionCallbackInfo<v8::Value>& args) {
break; break;
} }
case i::wasm::kRtt: case i::wasm::kRtt:
// TODO(7748): Implement.
UNIMPLEMENTED();
case i::wasm::kI8: case i::wasm::kI8:
case i::wasm::kI16: case i::wasm::kI16:
case i::wasm::kVoid: case i::wasm::kVoid:
...@@ -2725,7 +2723,6 @@ void WebAssemblyGlobalGetValueCommon( ...@@ -2725,7 +2723,6 @@ void WebAssemblyGlobalGetValueCommon(
break; break;
} }
case i::wasm::kRtt: case i::wasm::kRtt:
UNIMPLEMENTED(); // TODO(7748): Implement.
case i::wasm::kI8: case i::wasm::kI8:
case i::wasm::kI16: case i::wasm::kI16:
case i::wasm::kBottom: case i::wasm::kBottom:
......
...@@ -1554,8 +1554,6 @@ wasm::WasmValue WasmStruct::GetFieldValue(uint32_t index) { ...@@ -1554,8 +1554,6 @@ wasm::WasmValue WasmStruct::GetFieldValue(uint32_t index) {
return wasm::WasmValue(ref, field_type); return wasm::WasmValue(ref, field_type);
} }
case wasm::kRtt: case wasm::kRtt:
// TODO(7748): Expose RTTs to DevTools.
UNIMPLEMENTED();
case wasm::kVoid: case wasm::kVoid:
case wasm::kBottom: case wasm::kBottom:
UNREACHABLE(); UNREACHABLE();
...@@ -1583,8 +1581,6 @@ wasm::WasmValue WasmArray::GetElement(uint32_t index) { ...@@ -1583,8 +1581,6 @@ wasm::WasmValue WasmArray::GetElement(uint32_t index) {
return wasm::WasmValue(ref, element_type); return wasm::WasmValue(ref, element_type);
} }
case wasm::kRtt: case wasm::kRtt:
// TODO(7748): Expose RTTs to DevTools.
UNIMPLEMENTED();
case wasm::kVoid: case wasm::kVoid:
case wasm::kBottom: case wasm::kBottom:
UNREACHABLE(); UNREACHABLE();
......
...@@ -3668,8 +3668,7 @@ class WasmInterpreterInternals { ...@@ -3668,8 +3668,7 @@ class WasmInterpreterInternals {
FOREACH_WASMVALUE_CTYPES(CASE_TYPE) FOREACH_WASMVALUE_CTYPES(CASE_TYPE)
#undef CASE_TYPE #undef CASE_TYPE
case kRef: case kRef:
case kRefNull: case kRefNull: {
case kRtt: {
// TODO(7748): Type checks or DCHECKs for ref types? // TODO(7748): Type checks or DCHECKs for ref types?
HandleScope handle_scope(isolate_); // Avoid leaking handles. HandleScope handle_scope(isolate_); // Avoid leaking handles.
Handle<FixedArray> global_buffer; // The buffer of the global. Handle<FixedArray> global_buffer; // The buffer of the global.
...@@ -3681,6 +3680,7 @@ class WasmInterpreterInternals { ...@@ -3681,6 +3680,7 @@ class WasmInterpreterInternals {
global_buffer->set(global_index, *ref); global_buffer->set(global_index, *ref);
break; break;
} }
case kRtt:
case kI8: case kI8:
case kI16: case kI16:
case kVoid: case kVoid:
......
...@@ -842,7 +842,7 @@ class WasmGenerator { ...@@ -842,7 +842,7 @@ class WasmGenerator {
Var local = GetRandomLocal(data); Var local = GetRandomLocal(data);
// TODO(manoskouk): Ideally we would check for subtyping here over type // TODO(manoskouk): Ideally we would check for subtyping here over type
// equality, but we don't have a module. // equality, but we don't have a module.
// TODO(7748): Remove this condition if non-nullable locals are allowed. // TODO(7748): Allow initialized non-nullable locals.
if (nullable == kNullable && local.is_valid() && if (nullable == kNullable && local.is_valid() &&
local.type.is_object_reference() && type == local.type.heap_type()) { local.type.is_object_reference() && type == local.type.heap_type()) {
builder_->EmitWithU32V(kExprLocalGet, local.index); builder_->EmitWithU32V(kExprLocalGet, local.index);
...@@ -2522,8 +2522,8 @@ class WasmCompileFuzzer : public WasmExecutionFuzzer { ...@@ -2522,8 +2522,8 @@ class WasmCompileFuzzer : public WasmExecutionFuzzer {
// performed by adding a function by {FunctionSig}, because we emit // performed by adding a function by {FunctionSig}, because we emit
// everything in one recursive group which blocks signature // everything in one recursive group which blocks signature
// canonicalization. // canonicalization.
// TODO(7748): Relax this when we implement type canonicalization and // TODO(7748): Relax this when we implement proper recursive-group
// proper recursive-group support. // support.
functions.push_back(liftoff_as_reference functions.push_back(liftoff_as_reference
? builder.AddFunction(function_signatures[i]) ? builder.AddFunction(function_signatures[i])
: builder.AddFunction(sig)); : builder.AddFunction(sig));
......
...@@ -380,3 +380,18 @@ d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js"); ...@@ -380,3 +380,18 @@ d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js");
assertThrows(() => builder.instantiate(), WebAssembly.CompileError, assertThrows(() => builder.instantiate(), WebAssembly.CompileError,
/i31.new\[0\] expected type i32, found i64.const of type i64/); /i31.new\[0\] expected type i32, found i64.const of type i64/);
})(); })();
(function TestConstantExprFuncIndexOutOfBounds() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
let struct_index = builder.addStruct([makeField(kWasmFuncRef, true)]);
let func = builder.addFunction("element", kSig_i_i)
.addBody([kExprLocalGet, 0])
.exportFunc()
builder.addGlobal(wasmRefType(struct_index), false,
[kExprRefFunc, func.index + 1, kExprStructNew, struct_index]);
assertThrows(() => builder.instantiate(), WebAssembly.CompileError,
/function index #1 is out of bounds/);
})();
...@@ -36,8 +36,8 @@ d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js"); ...@@ -36,8 +36,8 @@ d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js");
kExprLocalGet, 2, kGCPrefix, kExprRefTest, bottom1, kExprLocalGet, 2, kGCPrefix, kExprRefTest, bottom1,
kExprIf, kWasmVoid, kExprIf, kWasmVoid,
// counter += ((bottom1) temp).field_2; // counter += ((bottom1) temp).field_2;
// TODO(manoskouk): Implement path-based type tracking so we can // Note: This cast should get optimized away with path-based type
// eliminate this check. // tracking.
kExprLocalGet, 2, kGCPrefix, kExprRefCast, bottom1, kExprLocalGet, 2, kGCPrefix, kExprRefCast, bottom1,
kGCPrefix, kExprStructGet, bottom1, 2, kGCPrefix, kExprStructGet, bottom1, 2,
kExprLocalGet, 3, kExprI32Add, kExprLocalSet, 3, kExprLocalGet, 3, kExprI32Add, kExprLocalSet, 3,
......
...@@ -1053,9 +1053,6 @@ class Binary { ...@@ -1053,9 +1053,6 @@ class Binary {
} }
emit_init_expr(expr) { emit_init_expr(expr) {
// TODO(manoskouk): This is redundant, remove it once we are confident we
// check everything.
checkExpr(expr);
this.emit_bytes(expr); this.emit_bytes(expr);
this.emit_u8(kExprEnd); this.emit_u8(kExprEnd);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment