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

[wasm-gc] Implement br_on_array, br_on_non_array

Bug: v8:7748
Change-Id: I5280a22240ef5e920f701e991ed13d8b8881fc6b
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3377122Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Cr-Commit-Position: refs/heads/main@{#78584}
parent 93f28d16
...@@ -5914,6 +5914,19 @@ Node* WasmGraphBuilder::RefAsArray(Node* object, bool object_can_be_null, ...@@ -5914,6 +5914,19 @@ Node* WasmGraphBuilder::RefAsArray(Node* object, bool object_can_be_null,
return object; return object;
} }
void WasmGraphBuilder::BrOnArray(Node* object, Node* /*rtt*/,
ObjectReferenceKnowledge config,
Node** match_control, Node** match_effect,
Node** no_match_control,
Node** no_match_effect) {
BrOnCastAbs(match_control, match_effect, no_match_control, no_match_effect,
[=](Callbacks callbacks) -> void {
return ManagedObjectInstanceCheck(object,
config.object_can_be_null,
WASM_ARRAY_TYPE, callbacks);
});
}
Node* WasmGraphBuilder::RefIsI31(Node* object) { return gasm_->IsI31(object); } Node* WasmGraphBuilder::RefIsI31(Node* object) { return gasm_->IsI31(object); }
Node* WasmGraphBuilder::RefAsI31(Node* object, Node* WasmGraphBuilder::RefAsI31(Node* object,
......
...@@ -525,6 +525,9 @@ class WasmGraphBuilder { ...@@ -525,6 +525,9 @@ class WasmGraphBuilder {
Node* RefIsArray(Node* object, bool object_can_be_null); Node* RefIsArray(Node* object, bool object_can_be_null);
Node* RefAsArray(Node* object, bool object_can_be_null, Node* RefAsArray(Node* object, bool object_can_be_null,
wasm::WasmCodePosition position); wasm::WasmCodePosition position);
void BrOnArray(Node* object, Node* rtt, ObjectReferenceKnowledge config,
Node** match_control, Node** match_effect,
Node** no_match_control, Node** no_match_effect);
Node* RefIsI31(Node* object); Node* RefIsI31(Node* object);
Node* RefAsI31(Node* object, wasm::WasmCodePosition position); Node* RefAsI31(Node* object, wasm::WasmCodePosition position);
void BrOnI31(Node* object, Node* rtt, ObjectReferenceKnowledge config, void BrOnI31(Node* object, Node* rtt, ObjectReferenceKnowledge config,
......
...@@ -5773,6 +5773,12 @@ class LiftoffCompiler { ...@@ -5773,6 +5773,12 @@ class LiftoffCompiler {
br_depth); br_depth);
} }
void BrOnArray(FullDecoder* decoder, const Value& object,
Value* /* value_on_branch */, uint32_t br_depth) {
return BrOnAbstractType<&LiftoffCompiler::ArrayCheck>(object, decoder,
br_depth);
}
void BrOnNonData(FullDecoder* decoder, const Value& object, void BrOnNonData(FullDecoder* decoder, const Value& object,
Value* /* value_on_branch */, uint32_t br_depth) { Value* /* value_on_branch */, uint32_t br_depth) {
return BrOnNonAbstractType<&LiftoffCompiler::DataCheck>(object, decoder, return BrOnNonAbstractType<&LiftoffCompiler::DataCheck>(object, decoder,
...@@ -5791,6 +5797,12 @@ class LiftoffCompiler { ...@@ -5791,6 +5797,12 @@ class LiftoffCompiler {
br_depth); br_depth);
} }
void BrOnNonArray(FullDecoder* decoder, const Value& object,
Value* /* value_on_branch */, uint32_t br_depth) {
return BrOnNonAbstractType<&LiftoffCompiler::ArrayCheck>(object, decoder,
br_depth);
}
void Forward(FullDecoder* decoder, const Value& from, Value* to) { void Forward(FullDecoder* decoder, const Value& from, Value* to) {
// Nothing to do here. // Nothing to do here.
} }
......
...@@ -945,146 +945,149 @@ struct ControlBase : public PcForErrors<validate> { ...@@ -945,146 +945,149 @@ struct ControlBase : public PcForErrors<validate> {
WasmRttSubMode mode) \ WasmRttSubMode mode) \
F(DoReturn, uint32_t drop_values) F(DoReturn, uint32_t drop_values)
#define INTERFACE_NON_CONSTANT_FUNCTIONS(F) \ #define INTERFACE_NON_CONSTANT_FUNCTIONS(F) /* force 80 columns */ \
/* Control: */ \ /* Control: */ \
F(Block, Control* block) \ F(Block, Control* block) \
F(Loop, Control* block) \ F(Loop, Control* block) \
F(Try, Control* block) \ F(Try, Control* block) \
F(If, const Value& cond, Control* if_block) \ F(If, const Value& cond, Control* if_block) \
F(FallThruTo, Control* c) \ F(FallThruTo, Control* c) \
F(PopControl, Control* block) \ F(PopControl, Control* block) \
/* Instructions: */ \ /* Instructions: */ \
F(UnOp, WasmOpcode opcode, const Value& value, Value* result) \ F(UnOp, WasmOpcode opcode, const Value& value, Value* result) \
F(BinOp, WasmOpcode opcode, const Value& lhs, const Value& rhs, \ F(BinOp, WasmOpcode opcode, const Value& lhs, const Value& rhs, \
Value* result) \ Value* result) \
F(RefAsNonNull, const Value& arg, Value* result) \ F(RefAsNonNull, const Value& arg, Value* result) \
F(Drop) \ F(Drop) \
F(LocalGet, Value* result, const IndexImmediate<validate>& imm) \ F(LocalGet, Value* result, const IndexImmediate<validate>& imm) \
F(LocalSet, const Value& value, const IndexImmediate<validate>& imm) \ F(LocalSet, const Value& value, const IndexImmediate<validate>& imm) \
F(LocalTee, const Value& value, Value* result, \ F(LocalTee, const Value& value, Value* result, \
const IndexImmediate<validate>& imm) \ const IndexImmediate<validate>& imm) \
F(AllocateLocals, base::Vector<Value> local_values) \ F(AllocateLocals, base::Vector<Value> local_values) \
F(DeallocateLocals, uint32_t count) \ F(DeallocateLocals, uint32_t count) \
F(GlobalSet, const Value& value, const GlobalIndexImmediate<validate>& imm) \ F(GlobalSet, const Value& value, const GlobalIndexImmediate<validate>& imm) \
F(TableGet, const Value& index, Value* result, \ F(TableGet, const Value& index, Value* result, \
const IndexImmediate<validate>& imm) \ const IndexImmediate<validate>& imm) \
F(TableSet, const Value& index, const Value& value, \ F(TableSet, const Value& index, const Value& value, \
const IndexImmediate<validate>& imm) \ const IndexImmediate<validate>& imm) \
F(Trap, TrapReason reason) \ F(Trap, TrapReason reason) \
F(NopForTestingUnsupportedInLiftoff) \ F(NopForTestingUnsupportedInLiftoff) \
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) \
F(BrIf, const Value& cond, uint32_t depth) \ F(BrIf, const Value& cond, uint32_t depth) \
F(BrTable, const BranchTableImmediate<validate>& imm, const Value& key) \ F(BrTable, const BranchTableImmediate<validate>& imm, const Value& key) \
F(Else, Control* if_block) \ F(Else, Control* if_block) \
F(LoadMem, LoadType type, const MemoryAccessImmediate<validate>& imm, \ F(LoadMem, LoadType type, const MemoryAccessImmediate<validate>& imm, \
const Value& index, Value* result) \ const Value& index, Value* result) \
F(LoadTransform, LoadType type, LoadTransformationKind transform, \ F(LoadTransform, LoadType type, LoadTransformationKind transform, \
const MemoryAccessImmediate<validate>& imm, const Value& index, \ const MemoryAccessImmediate<validate>& imm, const Value& index, \
Value* result) \ Value* result) \
F(LoadLane, LoadType type, const Value& value, const Value& index, \ F(LoadLane, LoadType type, const Value& value, const Value& index, \
const MemoryAccessImmediate<validate>& imm, const uint8_t laneidx, \ const MemoryAccessImmediate<validate>& imm, const uint8_t laneidx, \
Value* result) \ Value* result) \
F(StoreMem, StoreType type, const MemoryAccessImmediate<validate>& imm, \ F(StoreMem, StoreType type, const MemoryAccessImmediate<validate>& imm, \
const Value& index, const Value& value) \ const Value& index, const Value& value) \
F(StoreLane, StoreType type, const MemoryAccessImmediate<validate>& imm, \ F(StoreLane, StoreType type, const MemoryAccessImmediate<validate>& imm, \
const Value& index, const Value& value, const uint8_t laneidx) \ const Value& index, const Value& value, const uint8_t laneidx) \
F(CurrentMemoryPages, Value* result) \ F(CurrentMemoryPages, Value* result) \
F(MemoryGrow, const Value& value, Value* result) \ F(MemoryGrow, const Value& value, Value* result) \
F(CallDirect, const CallFunctionImmediate<validate>& imm, \ F(CallDirect, const CallFunctionImmediate<validate>& imm, \
const Value args[], Value returns[]) \ const Value args[], Value returns[]) \
F(CallIndirect, const Value& index, \ F(CallIndirect, const Value& index, \
const CallIndirectImmediate<validate>& imm, const Value args[], \ const CallIndirectImmediate<validate>& imm, const Value args[], \
Value returns[]) \ Value returns[]) \
F(CallRef, const Value& func_ref, const FunctionSig* sig, \ F(CallRef, const Value& func_ref, const FunctionSig* sig, \
uint32_t sig_index, const Value args[], const Value returns[]) \ uint32_t sig_index, const Value args[], const Value returns[]) \
F(ReturnCallRef, const Value& func_ref, const FunctionSig* sig, \ F(ReturnCallRef, const Value& func_ref, const FunctionSig* sig, \
uint32_t sig_index, const Value args[]) \ uint32_t sig_index, const Value args[]) \
F(ReturnCall, const CallFunctionImmediate<validate>& imm, \ F(ReturnCall, const CallFunctionImmediate<validate>& imm, \
const Value args[]) \ const Value args[]) \
F(ReturnCallIndirect, const Value& index, \ F(ReturnCallIndirect, const Value& index, \
const CallIndirectImmediate<validate>& imm, const Value args[]) \ const CallIndirectImmediate<validate>& imm, const Value args[]) \
F(BrOnNull, const Value& ref_object, uint32_t depth, \ F(BrOnNull, const Value& ref_object, uint32_t depth, \
bool pass_null_along_branch, Value* result_on_fallthrough) \ bool pass_null_along_branch, Value* result_on_fallthrough) \
F(BrOnNonNull, const Value& ref_object, uint32_t depth) \ F(BrOnNonNull, const Value& ref_object, uint32_t depth) \
F(SimdOp, WasmOpcode opcode, base::Vector<Value> args, Value* result) \ F(SimdOp, WasmOpcode opcode, base::Vector<Value> args, Value* result) \
F(SimdLaneOp, WasmOpcode opcode, const SimdLaneImmediate<validate>& imm, \ F(SimdLaneOp, WasmOpcode opcode, const SimdLaneImmediate<validate>& imm, \
const base::Vector<Value> inputs, Value* result) \ const base::Vector<Value> inputs, Value* result) \
F(S128Const, const Simd128Immediate<validate>& imm, Value* result) \ F(S128Const, const Simd128Immediate<validate>& imm, Value* result) \
F(Simd8x16ShuffleOp, const Simd128Immediate<validate>& imm, \ F(Simd8x16ShuffleOp, const Simd128Immediate<validate>& imm, \
const Value& input0, const Value& input1, Value* result) \ const Value& input0, const Value& input1, Value* result) \
F(Throw, const TagIndexImmediate<validate>& imm, \ F(Throw, const TagIndexImmediate<validate>& imm, \
const base::Vector<Value>& args) \ const base::Vector<Value>& args) \
F(Rethrow, Control* block) \ F(Rethrow, Control* block) \
F(CatchException, const TagIndexImmediate<validate>& imm, Control* block, \ F(CatchException, const TagIndexImmediate<validate>& imm, Control* block, \
base::Vector<Value> caught_values) \ base::Vector<Value> caught_values) \
F(Delegate, uint32_t depth, Control* block) \ F(Delegate, uint32_t depth, Control* block) \
F(CatchAll, Control* block) \ F(CatchAll, Control* block) \
F(AtomicOp, WasmOpcode opcode, base::Vector<Value> args, \ F(AtomicOp, WasmOpcode opcode, base::Vector<Value> args, \
const MemoryAccessImmediate<validate>& imm, Value* result) \ const MemoryAccessImmediate<validate>& imm, Value* result) \
F(AtomicFence) \ F(AtomicFence) \
F(MemoryInit, const MemoryInitImmediate<validate>& imm, const Value& dst, \ F(MemoryInit, const MemoryInitImmediate<validate>& imm, const Value& dst, \
const Value& src, const Value& size) \ const Value& src, const Value& size) \
F(DataDrop, const IndexImmediate<validate>& imm) \ F(DataDrop, const IndexImmediate<validate>& imm) \
F(MemoryCopy, const MemoryCopyImmediate<validate>& imm, const Value& dst, \ F(MemoryCopy, const MemoryCopyImmediate<validate>& imm, const Value& dst, \
const Value& src, const Value& size) \ const Value& src, const Value& size) \
F(MemoryFill, const MemoryIndexImmediate<validate>& imm, const Value& dst, \ F(MemoryFill, const MemoryIndexImmediate<validate>& imm, const Value& dst, \
const Value& value, const Value& size) \ const Value& value, const Value& size) \
F(TableInit, const TableInitImmediate<validate>& imm, \ F(TableInit, const TableInitImmediate<validate>& imm, \
base::Vector<Value> args) \ base::Vector<Value> args) \
F(ElemDrop, const IndexImmediate<validate>& imm) \ F(ElemDrop, const IndexImmediate<validate>& imm) \
F(TableCopy, const TableCopyImmediate<validate>& imm, \ F(TableCopy, const TableCopyImmediate<validate>& imm, \
base::Vector<Value> args) \ base::Vector<Value> args) \
F(TableGrow, const IndexImmediate<validate>& imm, const Value& value, \ F(TableGrow, const IndexImmediate<validate>& imm, const Value& value, \
const Value& delta, Value* result) \ const Value& delta, Value* result) \
F(TableSize, const IndexImmediate<validate>& imm, Value* result) \ F(TableSize, const IndexImmediate<validate>& imm, Value* result) \
F(TableFill, const IndexImmediate<validate>& imm, const Value& start, \ F(TableFill, const IndexImmediate<validate>& imm, const Value& start, \
const Value& value, const Value& count) \ const Value& value, const Value& count) \
F(StructGet, const Value& struct_object, \ F(StructGet, const Value& struct_object, \
const FieldImmediate<validate>& field, bool is_signed, Value* result) \ const FieldImmediate<validate>& field, bool is_signed, Value* result) \
F(StructSet, const Value& struct_object, \ F(StructSet, const Value& struct_object, \
const FieldImmediate<validate>& field, const Value& field_value) \ const FieldImmediate<validate>& field, const Value& field_value) \
F(ArrayNewWithRtt, const ArrayIndexImmediate<validate>& imm, \ F(ArrayNewWithRtt, const ArrayIndexImmediate<validate>& imm, \
const Value& length, const Value& initial_value, const Value& rtt, \ const Value& length, const Value& initial_value, const Value& rtt, \
Value* result) \ Value* result) \
F(ArrayNewDefault, const ArrayIndexImmediate<validate>& imm, \ F(ArrayNewDefault, const ArrayIndexImmediate<validate>& imm, \
const Value& length, const Value& rtt, Value* result) \ const Value& length, const Value& rtt, Value* result) \
F(ArrayGet, const Value& array_obj, \ F(ArrayGet, const Value& array_obj, \
const ArrayIndexImmediate<validate>& imm, const Value& index, \ const ArrayIndexImmediate<validate>& imm, const Value& index, \
bool is_signed, Value* result) \ bool is_signed, Value* result) \
F(ArraySet, const Value& array_obj, \ F(ArraySet, const Value& array_obj, \
const ArrayIndexImmediate<validate>& imm, const Value& index, \ const ArrayIndexImmediate<validate>& imm, const Value& index, \
const Value& value) \ const Value& value) \
F(ArrayLen, const Value& array_obj, Value* result) \ F(ArrayLen, const Value& array_obj, Value* result) \
F(ArrayCopy, const Value& src, const Value& src_index, const Value& dst, \ F(ArrayCopy, const Value& src, const Value& src_index, const Value& dst, \
const Value& dst_index, const Value& length) \ const Value& dst_index, const Value& length) \
F(I31New, const Value& input, Value* result) \ F(I31New, const Value& input, Value* result) \
F(I31GetS, const Value& input, Value* result) \ F(I31GetS, const Value& input, Value* result) \
F(I31GetU, const Value& input, Value* result) \ F(I31GetU, const Value& input, Value* result) \
F(RefTest, const Value& obj, const Value& rtt, Value* result) \ F(RefTest, const Value& obj, const Value& rtt, Value* result) \
F(RefCast, const Value& obj, const Value& rtt, Value* result) \ F(RefCast, const Value& obj, const Value& rtt, Value* result) \
F(AssertNull, const Value& obj, Value* result) \ F(AssertNull, const Value& obj, Value* result) \
F(BrOnCast, const Value& obj, const Value& rtt, Value* result_on_branch, \ F(BrOnCast, const Value& obj, const Value& rtt, Value* result_on_branch, \
uint32_t depth) \ uint32_t depth) \
F(BrOnCastFail, const Value& obj, const Value& rtt, \ F(BrOnCastFail, const Value& obj, const Value& rtt, \
Value* result_on_fallthrough, uint32_t depth) \ Value* result_on_fallthrough, uint32_t depth) \
F(RefIsFunc, const Value& object, Value* result) \ F(RefIsFunc, const Value& object, Value* result) \
F(RefIsData, const Value& object, Value* result) \ F(RefIsData, const Value& object, Value* result) \
F(RefIsI31, const Value& object, Value* result) \ F(RefIsI31, const Value& object, Value* result) \
F(RefIsArray, const Value& object, Value* result) \ F(RefIsArray, const Value& object, Value* result) \
F(RefAsFunc, const Value& object, Value* result) \ F(RefAsFunc, const Value& object, Value* result) \
F(RefAsData, const Value& object, Value* result) \ F(RefAsData, const Value& object, Value* result) \
F(RefAsI31, const Value& object, Value* result) \ F(RefAsI31, const Value& object, Value* result) \
F(RefAsArray, const Value& object, Value* result) \ F(RefAsArray, const Value& object, Value* result) \
F(BrOnFunc, const Value& object, Value* value_on_branch, uint32_t br_depth) \ F(BrOnFunc, const Value& object, Value* value_on_branch, uint32_t br_depth) \
F(BrOnData, const Value& object, Value* value_on_branch, uint32_t br_depth) \ F(BrOnData, const Value& object, Value* value_on_branch, uint32_t br_depth) \
F(BrOnI31, const Value& object, Value* value_on_branch, uint32_t br_depth) \ F(BrOnI31, const Value& object, Value* value_on_branch, uint32_t br_depth) \
F(BrOnNonFunc, const Value& object, Value* value_on_fallthrough, \ F(BrOnArray, const Value& object, Value* value_on_branch, uint32_t br_depth) \
uint32_t br_depth) \ F(BrOnNonFunc, const Value& object, Value* value_on_fallthrough, \
F(BrOnNonData, const Value& object, Value* value_on_fallthrough, \ uint32_t br_depth) \
uint32_t br_depth) \ F(BrOnNonData, const Value& object, Value* value_on_fallthrough, \
F(BrOnNonI31, const Value& object, Value* value_on_fallthrough, \ uint32_t br_depth) \
F(BrOnNonI31, const Value& object, Value* value_on_fallthrough, \
uint32_t br_depth) \
F(BrOnNonArray, const Value& object, Value* value_on_fallthrough, \
uint32_t br_depth) uint32_t br_depth)
// Generic Wasm bytecode decoder with utilities for decoding immediates, // Generic Wasm bytecode decoder with utilities for decoding immediates,
...@@ -4797,6 +4800,7 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> { ...@@ -4797,6 +4800,7 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
case kExprBrOnData: case kExprBrOnData:
case kExprBrOnFunc: case kExprBrOnFunc:
case kExprBrOnArray:
case kExprBrOnI31: { case kExprBrOnI31: {
NON_CONST_ONLY NON_CONST_ONLY
BranchDepthImmediate<validate> branch_depth(this, BranchDepthImmediate<validate> branch_depth(this,
...@@ -4823,7 +4827,10 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> { ...@@ -4823,7 +4827,10 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
HeapType::Representation heap_type = HeapType::Representation heap_type =
opcode == kExprBrOnFunc opcode == kExprBrOnFunc
? HeapType::kFunc ? HeapType::kFunc
: opcode == kExprBrOnData ? HeapType::kData : HeapType::kI31; : opcode == kExprBrOnData
? HeapType::kData
: opcode == kExprBrOnArray ? HeapType::kArray
: HeapType::kI31;
Value result_on_branch = Value result_on_branch =
CreateValue(ValueType::Ref(heap_type, kNonNullable)); CreateValue(ValueType::Ref(heap_type, kNonNullable));
Push(result_on_branch); Push(result_on_branch);
...@@ -4837,6 +4844,8 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> { ...@@ -4837,6 +4844,8 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
CALL_INTERFACE(BrOnFunc, obj, value_on_branch, branch_depth.depth); CALL_INTERFACE(BrOnFunc, obj, value_on_branch, branch_depth.depth);
} else if (opcode == kExprBrOnData) { } else if (opcode == kExprBrOnData) {
CALL_INTERFACE(BrOnData, obj, value_on_branch, branch_depth.depth); CALL_INTERFACE(BrOnData, obj, value_on_branch, branch_depth.depth);
} else if (opcode == kExprBrOnArray) {
CALL_INTERFACE(BrOnArray, obj, value_on_branch, branch_depth.depth);
} else { } else {
CALL_INTERFACE(BrOnI31, obj, value_on_branch, branch_depth.depth); CALL_INTERFACE(BrOnI31, obj, value_on_branch, branch_depth.depth);
} }
...@@ -4848,6 +4857,7 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> { ...@@ -4848,6 +4857,7 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
} }
case kExprBrOnNonData: case kExprBrOnNonData:
case kExprBrOnNonFunc: case kExprBrOnNonFunc:
case kExprBrOnNonArray:
case kExprBrOnNonI31: { case kExprBrOnNonI31: {
NON_CONST_ONLY NON_CONST_ONLY
BranchDepthImmediate<validate> branch_depth(this, BranchDepthImmediate<validate> branch_depth(this,
...@@ -4869,7 +4879,10 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> { ...@@ -4869,7 +4879,10 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
HeapType::Representation heap_type = HeapType::Representation heap_type =
opcode == kExprBrOnNonFunc opcode == kExprBrOnNonFunc
? HeapType::kFunc ? HeapType::kFunc
: opcode == kExprBrOnNonData ? HeapType::kData : HeapType::kI31; : opcode == kExprBrOnNonData
? HeapType::kData
: opcode == kExprBrOnNonArray ? HeapType::kArray
: HeapType::kI31;
Value value_on_fallthrough = Value value_on_fallthrough =
CreateValue(ValueType::Ref(heap_type, kNonNullable)); CreateValue(ValueType::Ref(heap_type, kNonNullable));
...@@ -4880,6 +4893,9 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> { ...@@ -4880,6 +4893,9 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
} else if (opcode == kExprBrOnNonData) { } else if (opcode == kExprBrOnNonData) {
CALL_INTERFACE(BrOnNonData, obj, &value_on_fallthrough, CALL_INTERFACE(BrOnNonData, obj, &value_on_fallthrough,
branch_depth.depth); branch_depth.depth);
} else if (opcode == kExprBrOnNonArray) {
CALL_INTERFACE(BrOnNonArray, obj, &value_on_fallthrough,
branch_depth.depth);
} else { } else {
CALL_INTERFACE(BrOnNonI31, obj, &value_on_fallthrough, CALL_INTERFACE(BrOnNonI31, obj, &value_on_fallthrough,
branch_depth.depth); branch_depth.depth);
......
...@@ -1257,6 +1257,20 @@ class WasmGraphBuildingInterface { ...@@ -1257,6 +1257,20 @@ class WasmGraphBuildingInterface {
decoder->position()); decoder->position());
} }
void BrOnArray(FullDecoder* decoder, const Value& object,
Value* value_on_branch, uint32_t br_depth) {
BrOnCastAbs<&compiler::WasmGraphBuilder::BrOnArray>(
decoder, object, Value{nullptr, kWasmBottom}, value_on_branch, br_depth,
true);
}
void BrOnNonArray(FullDecoder* decoder, const Value& object,
Value* value_on_fallthrough, uint32_t br_depth) {
BrOnCastAbs<&compiler::WasmGraphBuilder::BrOnArray>(
decoder, object, Value{nullptr, kWasmBottom}, value_on_fallthrough,
br_depth, false);
}
void RefIsI31(FullDecoder* decoder, const Value& object, Value* result) { void RefIsI31(FullDecoder* decoder, const Value& object, Value* result) {
result->node = builder_->RefIsI31(object.node); result->node = builder_->RefIsI31(object.node);
} }
......
...@@ -439,9 +439,11 @@ constexpr const char* WasmOpcodes::OpcodeName(WasmOpcode opcode) { ...@@ -439,9 +439,11 @@ constexpr const char* WasmOpcodes::OpcodeName(WasmOpcode opcode) {
CASE_OP(BrOnFunc, "br_on_func") CASE_OP(BrOnFunc, "br_on_func")
CASE_OP(BrOnData, "br_on_data") CASE_OP(BrOnData, "br_on_data")
CASE_OP(BrOnI31, "br_on_i31") CASE_OP(BrOnI31, "br_on_i31")
CASE_OP(BrOnArray, "br_on_array")
CASE_OP(BrOnNonFunc, "br_on_non_func") CASE_OP(BrOnNonFunc, "br_on_non_func")
CASE_OP(BrOnNonData, "br_on_non_data") CASE_OP(BrOnNonData, "br_on_non_data")
CASE_OP(BrOnNonI31, "br_on_non_i31") CASE_OP(BrOnNonI31, "br_on_non_i31")
CASE_OP(BrOnNonArray, "br_on_non_array")
case kNumericPrefix: case kNumericPrefix:
case kSimdPrefix: case kSimdPrefix:
......
...@@ -707,9 +707,11 @@ bool V8_EXPORT_PRIVATE IsJSCompatibleSignature(const FunctionSig* sig, ...@@ -707,9 +707,11 @@ bool V8_EXPORT_PRIVATE IsJSCompatibleSignature(const FunctionSig* sig,
V(BrOnFunc, 0xfb60, _) \ V(BrOnFunc, 0xfb60, _) \
V(BrOnData, 0xfb61, _) \ V(BrOnData, 0xfb61, _) \
V(BrOnI31, 0xfb62, _) \ V(BrOnI31, 0xfb62, _) \
V(BrOnArray, 0xfb66, _) /* not standardized - V8 experimental */ \
V(BrOnNonFunc, 0xfb63, _) \ V(BrOnNonFunc, 0xfb63, _) \
V(BrOnNonData, 0xfb64, _) \ V(BrOnNonData, 0xfb64, _) \
V(BrOnNonI31, 0xfb65, _) V(BrOnNonI31, 0xfb65, _) \
V(BrOnNonArray, 0xfb67, _) /* not standardized - V8 experimental */
#define FOREACH_ATOMIC_0_OPERAND_OPCODE(V) \ #define FOREACH_ATOMIC_0_OPERAND_OPCODE(V) \
/* AtomicFence does not target a particular linear memory. */ \ /* AtomicFence does not target a particular linear memory. */ \
......
...@@ -2000,6 +2000,11 @@ WASM_COMPILED_EXEC_TEST(AbstractTypeChecks) { ...@@ -2000,6 +2000,11 @@ WASM_COMPILED_EXEC_TEST(AbstractTypeChecks) {
byte kBrOnDataNotTaken = BR_ON(DATA, Data, WASM_REF_FUNC(function_index)); byte kBrOnDataNotTaken = BR_ON(DATA, Data, WASM_REF_FUNC(function_index));
byte kBrOnFuncTaken = BR_ON(FUNC, Func, WASM_REF_FUNC(function_index)); byte kBrOnFuncTaken = BR_ON(FUNC, Func, WASM_REF_FUNC(function_index));
byte kBrOnFuncNotTaken = BR_ON(FUNC, Func, WASM_I31_NEW(WASM_I32V(42))); byte kBrOnFuncNotTaken = BR_ON(FUNC, Func, WASM_I31_NEW(WASM_I32V(42)));
byte kBrOnArrayTaken =
BR_ON(ARRAY, Array,
WASM_ARRAY_NEW_DEFAULT_WITH_RTT(array_index, WASM_I32V(10),
WASM_RTT_CANON(array_index)));
byte kBrOnArrayNotTaken = BR_ON(ARRAY, Array, WASM_I31_NEW(WASM_I32V(42)));
byte kBrOnI31Taken = BR_ON(I31, I31, WASM_I31_NEW(WASM_I32V(42))); byte kBrOnI31Taken = BR_ON(I31, I31, WASM_I31_NEW(WASM_I32V(42)));
byte kBrOnI31NotTaken = byte kBrOnI31NotTaken =
BR_ON(I31, I31, BR_ON(I31, I31,
...@@ -2026,6 +2031,12 @@ WASM_COMPILED_EXEC_TEST(AbstractTypeChecks) { ...@@ -2026,6 +2031,12 @@ WASM_COMPILED_EXEC_TEST(AbstractTypeChecks) {
byte kBrOnNonFuncNotTaken = byte kBrOnNonFuncNotTaken =
BR_ON_NON(FUNC, Func, WASM_REF_FUNC(function_index)); BR_ON_NON(FUNC, Func, WASM_REF_FUNC(function_index));
byte kBrOnNonFuncTaken = BR_ON_NON(FUNC, Func, WASM_I31_NEW(WASM_I32V(42))); byte kBrOnNonFuncTaken = BR_ON_NON(FUNC, Func, WASM_I31_NEW(WASM_I32V(42)));
byte kBrOnNonArrayNotTaken =
BR_ON_NON(ARRAY, Array,
WASM_ARRAY_NEW_DEFAULT_WITH_RTT(array_index, WASM_I32V(10),
WASM_RTT_CANON(array_index)));
byte kBrOnNonArrayTaken =
BR_ON_NON(ARRAY, Array, WASM_I31_NEW(WASM_I32V(42)));
byte kBrOnNonI31NotTaken = BR_ON_NON(I31, I31, WASM_I31_NEW(WASM_I32V(42))); byte kBrOnNonI31NotTaken = BR_ON_NON(I31, I31, WASM_I31_NEW(WASM_I32V(42)));
byte kBrOnNonI31Taken = byte kBrOnNonI31Taken =
BR_ON_NON(I31, I31, BR_ON_NON(I31, I31,
...@@ -2069,6 +2080,8 @@ WASM_COMPILED_EXEC_TEST(AbstractTypeChecks) { ...@@ -2069,6 +2080,8 @@ WASM_COMPILED_EXEC_TEST(AbstractTypeChecks) {
tester.CheckResult(kBrOnDataNotTaken, 0); tester.CheckResult(kBrOnDataNotTaken, 0);
tester.CheckResult(kBrOnFuncTaken, 1); tester.CheckResult(kBrOnFuncTaken, 1);
tester.CheckResult(kBrOnFuncNotTaken, 0); tester.CheckResult(kBrOnFuncNotTaken, 0);
tester.CheckResult(kBrOnArrayTaken, 1);
tester.CheckResult(kBrOnArrayNotTaken, 0);
tester.CheckResult(kBrOnI31Taken, 1); tester.CheckResult(kBrOnI31Taken, 1);
tester.CheckResult(kBrOnI31NotTaken, 0); tester.CheckResult(kBrOnI31NotTaken, 0);
...@@ -2076,6 +2089,8 @@ WASM_COMPILED_EXEC_TEST(AbstractTypeChecks) { ...@@ -2076,6 +2089,8 @@ WASM_COMPILED_EXEC_TEST(AbstractTypeChecks) {
tester.CheckResult(kBrOnNonDataNotTaken, 1); tester.CheckResult(kBrOnNonDataNotTaken, 1);
tester.CheckResult(kBrOnNonFuncTaken, 0); tester.CheckResult(kBrOnNonFuncTaken, 0);
tester.CheckResult(kBrOnNonFuncNotTaken, 1); tester.CheckResult(kBrOnNonFuncNotTaken, 1);
tester.CheckResult(kBrOnNonArrayTaken, 0);
tester.CheckResult(kBrOnNonArrayNotTaken, 1);
tester.CheckResult(kBrOnNonI31Taken, 0); tester.CheckResult(kBrOnNonI31Taken, 0);
tester.CheckResult(kBrOnNonI31NotTaken, 1); tester.CheckResult(kBrOnNonI31NotTaken, 1);
} }
......
...@@ -539,11 +539,15 @@ inline WasmOpcode LoadStoreOpcodeOf(MachineType type, bool store) { ...@@ -539,11 +539,15 @@ inline WasmOpcode LoadStoreOpcodeOf(MachineType type, bool store) {
#define WASM_REF_AS_I31(ref) ref, WASM_GC_OP(kExprRefAsI31) #define WASM_REF_AS_I31(ref) ref, WASM_GC_OP(kExprRefAsI31)
#define WASM_BR_ON_FUNC(depth) \ #define WASM_BR_ON_FUNC(depth) \
WASM_GC_OP(kExprBrOnFunc), static_cast<byte>(depth) WASM_GC_OP(kExprBrOnFunc), static_cast<byte>(depth)
#define WASM_BR_ON_ARRAY(depth) \
WASM_GC_OP(kExprBrOnArray), static_cast<byte>(depth)
#define WASM_BR_ON_DATA(depth) \ #define WASM_BR_ON_DATA(depth) \
WASM_GC_OP(kExprBrOnData), static_cast<byte>(depth) WASM_GC_OP(kExprBrOnData), static_cast<byte>(depth)
#define WASM_BR_ON_I31(depth) WASM_GC_OP(kExprBrOnI31), static_cast<byte>(depth) #define WASM_BR_ON_I31(depth) WASM_GC_OP(kExprBrOnI31), static_cast<byte>(depth)
#define WASM_BR_ON_NON_FUNC(depth) \ #define WASM_BR_ON_NON_FUNC(depth) \
WASM_GC_OP(kExprBrOnNonFunc), static_cast<byte>(depth) WASM_GC_OP(kExprBrOnNonFunc), static_cast<byte>(depth)
#define WASM_BR_ON_NON_ARRAY(depth) \
WASM_GC_OP(kExprBrOnNonArray), static_cast<byte>(depth)
#define WASM_BR_ON_NON_DATA(depth) \ #define WASM_BR_ON_NON_DATA(depth) \
WASM_GC_OP(kExprBrOnNonData), static_cast<byte>(depth) WASM_GC_OP(kExprBrOnNonData), static_cast<byte>(depth)
#define WASM_BR_ON_NON_I31(depth) \ #define WASM_BR_ON_NON_I31(depth) \
......
...@@ -515,6 +515,11 @@ let kExprRefAsArray = 0x5b; ...@@ -515,6 +515,11 @@ let kExprRefAsArray = 0x5b;
let kExprBrOnFunc = 0x60; let kExprBrOnFunc = 0x60;
let kExprBrOnData = 0x61; let kExprBrOnData = 0x61;
let kExprBrOnI31 = 0x62; let kExprBrOnI31 = 0x62;
let kExprBrOnArray = 0x66;
let kExprBrOnNonFunc = 0x63;
let kExprBrOnNonData = 0x64;
let kExprBrOnNonI31 = 0x65;
let kExprBrOnNonArray = 0x67;
// Numeric opcodes. // Numeric opcodes.
let kExprI32SConvertSatF32 = 0x00; let kExprI32SConvertSatF32 = 0x00;
......
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