Commit be2705c8 authored by Manos Koukoutos's avatar Manos Koukoutos Committed by Commit Bot

[wasm-gc] Implement br_on_* type relaxation

Additional arguments are allowed along with the reference, but the
targeted branch must have at least one output (corresponding to the
cast reference).

Bug: v8:7748
Change-Id: I17383165e4bae1cada1676c6282437e1fa71905d
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2685161Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Cr-Commit-Position: refs/heads/master@{#72649}
parent b471bc93
......@@ -4198,23 +4198,26 @@ class WasmFullDecoder : public WasmDecoder<validate> {
return 0;
}
Control* c = control_at(branch_depth.depth);
ValueType type_on_branch =
rtt.type.is_bottom()
? kWasmBottom
: ValueType::Ref(rtt.type.ref_index(), kNonNullable);
TypeCheckBranchResult check_result = TypeCheckBrOn(c, type_on_branch);
if (c->br_merge()->arity == 0) {
this->DecodeError(
"br_on_cast must target a branch of arity at least 1");
return 0;
}
// We temporarily push this value to the stack for TypeCheckBranchResult
// and for MergeValuesInto in the interface.
Value* result_on_branch =
Push(rtt.type.is_bottom()
? kWasmBottom
: ValueType::Ref(rtt.type.ref_index(), kNonNullable));
TypeCheckBranchResult check_result = TypeCheckBranch(c, true);
if (V8_LIKELY(check_result == kReachableBranch)) {
// We temporarily push this value for the interface to merge it into
// the branch merge.
Value* result_on_branch = Push(type_on_branch);
CALL_INTERFACE(BrOnCast, obj, rtt, result_on_branch,
branch_depth.depth);
c->br_merge()->reached = true;
Pop(0); // Drop {result_on_branch}, restore original value.
} else if (check_result == kInvalidStack) {
return 0;
}
Pop(0); // Drop {result_on_branch}, restore original value.
Value* result_on_fallthrough = Push(obj.type);
*result_on_fallthrough = obj;
return opcode_length + branch_depth.length;
......@@ -4264,14 +4267,16 @@ class WasmFullDecoder : public WasmDecoder<validate> {
opcode == kExprBrOnFunc
? HeapType::kFunc
: opcode == kExprBrOnData ? HeapType::kData : HeapType::kI31;
ValueType type_on_branch = ValueType::Ref(heap_type, kNonNullable);
TypeCheckBranchResult check_result = TypeCheckBrOn(c, type_on_branch);
if (c->br_merge()->arity == 0) {
this->DecodeError("%s must target a branch of arity at least 1",
SafeOpcodeNameAt(this->pc_));
return 0;
}
// We temporarily push this value to the stack for TypeCheckBranchResult
// and for MergeValuesInto in the interface.
Value* result_on_branch = Push(ValueType::Ref(heap_type, kNonNullable));
TypeCheckBranchResult check_result = TypeCheckBranch(c, true);
if (V8_LIKELY(check_result == kReachableBranch)) {
// We temporarily push this value for the interface to merge it into
// the branch merge.
Value* result_on_branch = Push(type_on_branch);
if (opcode == kExprBrOnFunc) {
CALL_INTERFACE(BrOnFunc, obj, result_on_branch, branch_depth.depth);
} else if (opcode == kExprBrOnData) {
......@@ -4280,10 +4285,10 @@ class WasmFullDecoder : public WasmDecoder<validate> {
CALL_INTERFACE(BrOnI31, obj, result_on_branch, branch_depth.depth);
}
c->br_merge()->reached = true;
Pop(0); // Drop {result_on_branch}, restore original value.
} else if (check_result == kInvalidStack) {
return 0;
}
Pop(0); // Drop {result_on_branch}, restore original value.
Value* result_on_fallthrough = Push(obj.type);
*result_on_fallthrough = obj;
return opcode_length + branch_depth.length;
......@@ -4699,25 +4704,6 @@ class WasmFullDecoder : public WasmDecoder<validate> {
: kInvalidStack;
}
TypeCheckBranchResult TypeCheckBrOn(Control* c, ValueType type_on_branch) {
if (V8_LIKELY(control_.back().reachable())) {
// We only do type-checking here. This is only needed during validation.
if (!VALIDATE(c->br_merge()->arity == 1 &&
(type_on_branch == kWasmBottom ||
IsSubtypeOf(type_on_branch, (*c->br_merge())[0].type,
this->module_)))) {
this->DecodeError("%s must target a branch of a supertype of type %s",
SafeOpcodeNameAt(this->pc_),
type_on_branch.name().c_str());
return kInvalidStack;
}
return kReachableBranch;
}
return TypeCheckUnreachableMerge(*c->br_merge(), false) ? kUnreachableBranch
: kInvalidStack;
}
bool TypeCheckReturn() {
int num_returns = static_cast<int>(this->sig_->return_count());
// No type checking is needed if there are no returns.
......
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