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