[wasm-gc] Introduce typed-based optimizations
We introduce a Turbofan pass which optimizes wasm-gc nodes based on the types of their inputs. Bug: v8:7748 Change-Id: I281eb0785e9e4201ef925ec201d76dc3d274ad05 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3679198 Reviewed-by: Maya Lekova <mslekova@chromium.org> Reviewed-by: Jakob Kummerow <jkummerow@chromium.org> Commit-Queue: Manos Koukoutos <manoskouk@chromium.org> Cr-Commit-Position: refs/heads/main@{#80929}
This commit is contained in:
parent
80c0e707ae
commit
51d662f712
@ -2876,6 +2876,8 @@ filegroup(
|
||||
"src/compiler/wasm-loop-peeling.h",
|
||||
"src/compiler/wasm-gc-lowering.cc",
|
||||
"src/compiler/wasm-gc-lowering.h",
|
||||
"src/compiler/wasm-gc-operator-reducer.cc",
|
||||
"src/compiler/wasm-gc-operator-reducer.h",
|
||||
"src/compiler/wasm-graph-assembler.cc",
|
||||
"src/compiler/wasm-graph-assembler.h",
|
||||
"src/compiler/wasm-inlining.cc",
|
||||
|
2
BUILD.gn
2
BUILD.gn
@ -3562,6 +3562,7 @@ v8_header_set("v8_internal_headers") {
|
||||
"src/compiler/wasm-compiler.h",
|
||||
"src/compiler/wasm-escape-analysis.h",
|
||||
"src/compiler/wasm-gc-lowering.h",
|
||||
"src/compiler/wasm-gc-operator-reducer.h",
|
||||
"src/compiler/wasm-graph-assembler.h",
|
||||
"src/compiler/wasm-inlining.h",
|
||||
"src/compiler/wasm-loop-peeling.h",
|
||||
@ -4063,6 +4064,7 @@ if (v8_enable_webassembly) {
|
||||
"src/compiler/wasm-compiler.cc",
|
||||
"src/compiler/wasm-escape-analysis.cc",
|
||||
"src/compiler/wasm-gc-lowering.cc",
|
||||
"src/compiler/wasm-gc-operator-reducer.cc",
|
||||
"src/compiler/wasm-graph-assembler.cc",
|
||||
"src/compiler/wasm-inlining.cc",
|
||||
"src/compiler/wasm-loop-peeling.cc",
|
||||
|
@ -507,6 +507,7 @@
|
||||
#define SIMPLIFIED_WASM_OP_LIST(V) \
|
||||
V(AssertNotNull) \
|
||||
V(IsNull) \
|
||||
V(IsNotNull) \
|
||||
V(Null) \
|
||||
V(RttCanon) \
|
||||
V(WasmTypeCast) \
|
||||
|
@ -107,6 +107,7 @@
|
||||
#include "src/compiler/wasm-compiler.h"
|
||||
#include "src/compiler/wasm-escape-analysis.h"
|
||||
#include "src/compiler/wasm-gc-lowering.h"
|
||||
#include "src/compiler/wasm-gc-operator-reducer.h"
|
||||
#include "src/compiler/wasm-inlining.h"
|
||||
#include "src/compiler/wasm-loop-peeling.h"
|
||||
#include "src/compiler/wasm-typer.h"
|
||||
@ -2073,6 +2074,20 @@ struct WasmTypingPhase {
|
||||
}
|
||||
};
|
||||
|
||||
struct WasmGCOptimizationPhase {
|
||||
DECL_PIPELINE_PHASE_CONSTANTS(WasmGCOptimization)
|
||||
|
||||
void Run(PipelineData* data, Zone* temp_zone,
|
||||
const wasm::WasmModule* module) {
|
||||
GraphReducer graph_reducer(
|
||||
temp_zone, data->graph(), &data->info()->tick_counter(), data->broker(),
|
||||
data->jsgraph()->Dead(), data->observe_node_manager());
|
||||
WasmGCOperatorReducer wasm_gc(&graph_reducer, data->mcgraph(), module);
|
||||
AddReducer(data, &graph_reducer, &wasm_gc);
|
||||
graph_reducer.ReduceGraph();
|
||||
}
|
||||
};
|
||||
|
||||
struct WasmGCLoweringPhase {
|
||||
DECL_PIPELINE_PHASE_CONSTANTS(WasmGCLowering)
|
||||
|
||||
@ -3299,6 +3314,8 @@ void Pipeline::GenerateCodeForWasmFunction(
|
||||
if (FLAG_experimental_wasm_gc) {
|
||||
pipeline.Run<WasmTypingPhase>(function_index);
|
||||
pipeline.RunPrintAndVerify(WasmTypingPhase::phase_name(), true);
|
||||
pipeline.Run<WasmGCOptimizationPhase>(module);
|
||||
pipeline.RunPrintAndVerify(WasmGCOptimizationPhase::phase_name(), true);
|
||||
pipeline.Run<WasmGCLoweringPhase>();
|
||||
pipeline.RunPrintAndVerify(WasmGCLoweringPhase::phase_name(), true);
|
||||
}
|
||||
|
@ -1153,6 +1153,13 @@ struct SimplifiedOperatorGlobalCache final {
|
||||
};
|
||||
IsNullOperator kIsNull;
|
||||
|
||||
struct IsNotNullOperator final : public Operator {
|
||||
explicit IsNotNullOperator()
|
||||
: Operator(IrOpcode::kIsNotNull, Operator::kPure, "IsNotNull", 1, 0, 0,
|
||||
1, 0, 0) {}
|
||||
};
|
||||
IsNotNullOperator kIsNotNull;
|
||||
|
||||
struct NullOperator final : public Operator {
|
||||
NullOperator()
|
||||
: Operator(IrOpcode::kNull, Operator::kPure, "Null", 0, 0, 0, 1, 0, 0) {
|
||||
@ -1360,6 +1367,9 @@ const Operator* SimplifiedOperatorBuilder::AssertNotNull() {
|
||||
}
|
||||
|
||||
const Operator* SimplifiedOperatorBuilder::IsNull() { return &cache_.kIsNull; }
|
||||
const Operator* SimplifiedOperatorBuilder::IsNotNull() {
|
||||
return &cache_.kIsNotNull;
|
||||
}
|
||||
#endif // V8_ENABLE_WEBASSEMBLY
|
||||
|
||||
const Operator* SimplifiedOperatorBuilder::CheckIf(
|
||||
|
@ -1064,6 +1064,7 @@ class V8_EXPORT_PRIVATE SimplifiedOperatorBuilder final
|
||||
#if V8_ENABLE_WEBASSEMBLY
|
||||
const Operator* AssertNotNull();
|
||||
const Operator* IsNull();
|
||||
const Operator* IsNotNull();
|
||||
const Operator* Null();
|
||||
const Operator* RttCanon(int index);
|
||||
const Operator* WasmTypeCheck(WasmTypeCheckConfig config);
|
||||
|
@ -1651,6 +1651,7 @@ void Verifier::Visitor::Check(Node* node, const AllNodes& all) {
|
||||
case IrOpcode::kRttCanon:
|
||||
case IrOpcode::kNull:
|
||||
case IrOpcode::kIsNull:
|
||||
case IrOpcode::kIsNotNull:
|
||||
case IrOpcode::kAssertNotNull:
|
||||
// TODO(manoskouk): What are the constraints here?
|
||||
break;
|
||||
|
@ -50,6 +50,8 @@ Reduction WasmGCLowering::Reduce(Node* node) {
|
||||
return ReduceNull(node);
|
||||
case IrOpcode::kIsNull:
|
||||
return ReduceIsNull(node);
|
||||
case IrOpcode::kIsNotNull:
|
||||
return ReduceIsNotNull(node);
|
||||
case IrOpcode::kRttCanon:
|
||||
return ReduceRttCanon(node);
|
||||
case IrOpcode::kTypeGuard:
|
||||
@ -202,6 +204,13 @@ Reduction WasmGCLowering::ReduceIsNull(Node* node) {
|
||||
return Replace(gasm_.TaggedEqual(object, Null()));
|
||||
}
|
||||
|
||||
Reduction WasmGCLowering::ReduceIsNotNull(Node* node) {
|
||||
DCHECK_EQ(node->opcode(), IrOpcode::kIsNotNull);
|
||||
Node* object = NodeProperties::GetValueInput(node, 0);
|
||||
return Replace(gasm_.Word32Equal(gasm_.TaggedEqual(object, Null()),
|
||||
gasm_.Int32Constant(0)));
|
||||
}
|
||||
|
||||
Reduction WasmGCLowering::ReduceRttCanon(Node* node) {
|
||||
DCHECK_EQ(node->opcode(), IrOpcode::kRttCanon);
|
||||
int type_index = OpParameter<int>(node->op());
|
||||
|
@ -33,6 +33,7 @@ class WasmGCLowering final : public AdvancedReducer {
|
||||
Reduction ReduceAssertNotNull(Node* node);
|
||||
Reduction ReduceNull(Node* node);
|
||||
Reduction ReduceIsNull(Node* node);
|
||||
Reduction ReduceIsNotNull(Node* node);
|
||||
Reduction ReduceRttCanon(Node* node);
|
||||
Reduction ReduceTypeGuard(Node* node);
|
||||
Node* Null();
|
||||
|
195
src/compiler/wasm-gc-operator-reducer.cc
Normal file
195
src/compiler/wasm-gc-operator-reducer.cc
Normal file
@ -0,0 +1,195 @@
|
||||
// Copyright 2022 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "src/compiler/wasm-gc-operator-reducer.h"
|
||||
|
||||
#include "src/compiler/node-properties.h"
|
||||
#include "src/compiler/simplified-operator.h"
|
||||
#include "src/compiler/wasm-compiler-definitions.h"
|
||||
#include "src/wasm/wasm-subtyping.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
namespace compiler {
|
||||
|
||||
WasmGCOperatorReducer::WasmGCOperatorReducer(Editor* editor,
|
||||
MachineGraph* mcgraph,
|
||||
const wasm::WasmModule* module)
|
||||
: AdvancedReducer(editor),
|
||||
mcgraph_(mcgraph),
|
||||
gasm_(mcgraph, mcgraph->zone()),
|
||||
module_(module) {}
|
||||
|
||||
Reduction WasmGCOperatorReducer::Reduce(Node* node) {
|
||||
switch (node->opcode()) {
|
||||
case IrOpcode::kAssertNotNull:
|
||||
return ReduceAssertNotNull(node);
|
||||
case IrOpcode::kIsNull:
|
||||
return ReduceIsNull(node);
|
||||
case IrOpcode::kWasmTypeCheck:
|
||||
return ReduceWasmTypeCheck(node);
|
||||
case IrOpcode::kWasmTypeCast:
|
||||
return ReduceWasmTypeCast(node);
|
||||
default:
|
||||
return NoChange();
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
bool InDeadBranch(Node* node) {
|
||||
return node->opcode() == IrOpcode::kDead ||
|
||||
NodeProperties::GetType(node).AsWasm().type.is_bottom();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
Node* WasmGCOperatorReducer::SetType(Node* node, wasm::ValueType type) {
|
||||
NodeProperties::SetType(node, Type::Wasm(type, module_, graph()->zone()));
|
||||
return node;
|
||||
}
|
||||
|
||||
Reduction WasmGCOperatorReducer::ReduceAssertNotNull(Node* node) {
|
||||
DCHECK_EQ(node->opcode(), IrOpcode::kAssertNotNull);
|
||||
Node* object = NodeProperties::GetValueInput(node, 0);
|
||||
|
||||
if (InDeadBranch(object)) return NoChange();
|
||||
|
||||
// Optimize the check away if the argument is known to be non-null.
|
||||
if (!NodeProperties::GetType(object).AsWasm().type.is_nullable()) {
|
||||
ReplaceWithValue(node, object);
|
||||
node->Kill();
|
||||
return Replace(object);
|
||||
}
|
||||
|
||||
return NoChange();
|
||||
}
|
||||
|
||||
Reduction WasmGCOperatorReducer::ReduceIsNull(Node* node) {
|
||||
DCHECK_EQ(node->opcode(), IrOpcode::kIsNull);
|
||||
Node* object = NodeProperties::GetValueInput(node, 0);
|
||||
|
||||
if (InDeadBranch(object)) return NoChange();
|
||||
|
||||
// Optimize the check away if the argument is known to be non-null.
|
||||
if (!NodeProperties::GetType(object).AsWasm().type.is_nullable()) {
|
||||
ReplaceWithValue(node, gasm_.Int32Constant(0));
|
||||
node->Kill();
|
||||
return Replace(object); // Irrelevant replacement.
|
||||
}
|
||||
|
||||
// Optimize the check away if the argument is known to be null.
|
||||
if (object->opcode() == IrOpcode::kNull) {
|
||||
ReplaceWithValue(node, gasm_.Int32Constant(1));
|
||||
node->Kill();
|
||||
return Replace(object); // Irrelevant replacement.
|
||||
}
|
||||
|
||||
return NoChange();
|
||||
}
|
||||
|
||||
Reduction WasmGCOperatorReducer::ReduceWasmTypeCast(Node* node) {
|
||||
DCHECK_EQ(node->opcode(), IrOpcode::kWasmTypeCast);
|
||||
Node* effect = NodeProperties::GetEffectInput(node);
|
||||
Node* control = NodeProperties::GetControlInput(node);
|
||||
Node* object = NodeProperties::GetValueInput(node, 0);
|
||||
Node* rtt = NodeProperties::GetValueInput(node, 1);
|
||||
|
||||
if (InDeadBranch(object) || InDeadBranch(rtt)) return NoChange();
|
||||
|
||||
wasm::TypeInModule object_type = NodeProperties::GetType(object).AsWasm();
|
||||
wasm::TypeInModule rtt_type = NodeProperties::GetType(rtt).AsWasm();
|
||||
|
||||
if (object_type.type.is_bottom()) return NoChange();
|
||||
|
||||
if (wasm::IsHeapSubtypeOf(object_type.type.heap_type(),
|
||||
wasm::HeapType(rtt_type.type.ref_index()),
|
||||
object_type.module, rtt_type.module)) {
|
||||
// Type cast will always succeed. Remove it.
|
||||
ReplaceWithValue(node, object);
|
||||
node->Kill();
|
||||
return Replace(object);
|
||||
}
|
||||
|
||||
if (wasm::HeapTypesUnrelated(object_type.type.heap_type(),
|
||||
wasm::HeapType(rtt_type.type.ref_index()),
|
||||
object_type.module, rtt_type.module)) {
|
||||
gasm_.InitializeEffectControl(effect, control);
|
||||
// A cast between unrelated types can only succeed if the argument is null.
|
||||
// Otherwise, it always fails.
|
||||
Node* non_trapping_condition = object_type.type.is_nullable()
|
||||
? gasm_.IsNull(object)
|
||||
: gasm_.Int32Constant(0);
|
||||
Node* trap =
|
||||
gasm_.TrapUnless(SetType(non_trapping_condition, wasm::kWasmI32),
|
||||
TrapId::kTrapIllegalCast);
|
||||
// TODO(manoskouk): Improve the type when we have nullref.
|
||||
Node* null_node = gasm_.Null();
|
||||
ReplaceWithValue(
|
||||
node,
|
||||
SetType(null_node, wasm::ValueType::Ref(rtt_type.type.ref_index(),
|
||||
wasm::kNullable)),
|
||||
effect, trap);
|
||||
node->Kill();
|
||||
return Replace(null_node);
|
||||
}
|
||||
|
||||
// Remove the null check from the cast if able.
|
||||
if (!object_type.type.is_nullable() &&
|
||||
OpParameter<WasmTypeCheckConfig>(node->op()).object_can_be_null) {
|
||||
uint8_t rtt_depth = OpParameter<WasmTypeCheckConfig>(node->op()).rtt_depth;
|
||||
NodeProperties::ChangeOp(
|
||||
node, gasm_.simplified()->WasmTypeCast(
|
||||
{/* object_can_be_null = */ false, rtt_depth}));
|
||||
return Changed(node);
|
||||
}
|
||||
|
||||
return NoChange();
|
||||
}
|
||||
|
||||
Reduction WasmGCOperatorReducer::ReduceWasmTypeCheck(Node* node) {
|
||||
DCHECK_EQ(node->opcode(), IrOpcode::kWasmTypeCheck);
|
||||
Node* object = NodeProperties::GetValueInput(node, 0);
|
||||
Node* rtt = NodeProperties::GetValueInput(node, 1);
|
||||
|
||||
if (InDeadBranch(object) || InDeadBranch(rtt)) return NoChange();
|
||||
|
||||
wasm::TypeInModule object_type = NodeProperties::GetType(object).AsWasm();
|
||||
wasm::TypeInModule rtt_type = NodeProperties::GetType(rtt).AsWasm();
|
||||
|
||||
if (wasm::IsHeapSubtypeOf(object_type.type.heap_type(),
|
||||
wasm::HeapType(rtt_type.type.ref_index()),
|
||||
object_type.module, rtt_type.module)) {
|
||||
// Type cast will fail only on null.
|
||||
Node* condition =
|
||||
SetType(object_type.type.is_nullable() ? gasm_.IsNotNull(object)
|
||||
: gasm_.Int32Constant(1),
|
||||
wasm::kWasmI32);
|
||||
ReplaceWithValue(node, condition);
|
||||
node->Kill();
|
||||
return Replace(condition);
|
||||
}
|
||||
|
||||
if (wasm::HeapTypesUnrelated(object_type.type.heap_type(),
|
||||
wasm::HeapType(rtt_type.type.ref_index()),
|
||||
object_type.module, rtt_type.module)) {
|
||||
Node* condition = SetType(gasm_.Int32Constant(0), wasm::kWasmI32);
|
||||
ReplaceWithValue(node, condition);
|
||||
node->Kill();
|
||||
return Replace(condition);
|
||||
}
|
||||
|
||||
// Remove the null check from the typecheck if able.
|
||||
if (!object_type.type.is_nullable() &&
|
||||
OpParameter<WasmTypeCheckConfig>(node->op()).object_can_be_null) {
|
||||
uint8_t rtt_depth = OpParameter<WasmTypeCheckConfig>(node->op()).rtt_depth;
|
||||
NodeProperties::ChangeOp(
|
||||
node, gasm_.simplified()->WasmTypeCheck({false, rtt_depth}));
|
||||
return Changed(node);
|
||||
}
|
||||
|
||||
return NoChange();
|
||||
}
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace internal
|
||||
} // namespace v8
|
50
src/compiler/wasm-gc-operator-reducer.h
Normal file
50
src/compiler/wasm-gc-operator-reducer.h
Normal file
@ -0,0 +1,50 @@
|
||||
// Copyright 2022 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#if !V8_ENABLE_WEBASSEMBLY
|
||||
#error This header should only be included if WebAssembly is enabled.
|
||||
#endif // !V8_ENABLE_WEBASSEMBLY
|
||||
|
||||
#ifndef V8_COMPILER_WASM_GC_OPERATOR_REDUCER_H_
|
||||
#define V8_COMPILER_WASM_GC_OPERATOR_REDUCER_H_
|
||||
|
||||
#include "src/compiler/graph-reducer.h"
|
||||
#include "src/compiler/wasm-graph-assembler.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
namespace compiler {
|
||||
|
||||
class MachineGraph;
|
||||
|
||||
class WasmGCOperatorReducer final : public AdvancedReducer {
|
||||
public:
|
||||
WasmGCOperatorReducer(Editor* editor, MachineGraph* mcgraph,
|
||||
const wasm::WasmModule* module);
|
||||
|
||||
const char* reducer_name() const override { return "WasmGCOperatorReducer"; }
|
||||
|
||||
Reduction Reduce(Node* node) final;
|
||||
|
||||
private:
|
||||
Reduction ReduceAssertNotNull(Node* node);
|
||||
Reduction ReduceIsNull(Node* node);
|
||||
Reduction ReduceWasmTypeCheck(Node* node);
|
||||
Reduction ReduceWasmTypeCast(Node* node);
|
||||
|
||||
Node* SetType(Node* node, wasm::ValueType type);
|
||||
|
||||
Graph* graph() { return mcgraph_->graph(); }
|
||||
CommonOperatorBuilder* common() { return mcgraph_->common(); }
|
||||
|
||||
MachineGraph* mcgraph_;
|
||||
WasmGraphAssembler gasm_;
|
||||
const wasm::WasmModule* module_;
|
||||
};
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_COMPILER_WASM_GC_OPERATOR_REDUCER_H_
|
@ -368,6 +368,10 @@ Node* WasmGraphAssembler::IsNull(Node* object) {
|
||||
return AddNode(graph()->NewNode(simplified_.IsNull(), object));
|
||||
}
|
||||
|
||||
Node* WasmGraphAssembler::IsNotNull(Node* object) {
|
||||
return AddNode(graph()->NewNode(simplified_.IsNotNull(), object));
|
||||
}
|
||||
|
||||
Node* WasmGraphAssembler::AssertNotNull(Node* object) {
|
||||
return AddNode(graph()->NewNode(simplified_.AssertNotNull(), object, effect(),
|
||||
control()));
|
||||
|
@ -248,6 +248,8 @@ class WasmGraphAssembler : public GraphAssembler {
|
||||
|
||||
Node* IsNull(Node* object);
|
||||
|
||||
Node* IsNotNull(Node* object);
|
||||
|
||||
Node* AssertNotNull(Node* object);
|
||||
|
||||
// Generic helpers.
|
||||
|
@ -103,6 +103,35 @@ Reduction WasmTyper::Reduce(Node* node) {
|
||||
break;
|
||||
}
|
||||
case IrOpcode::kAssertNotNull: {
|
||||
{
|
||||
Node* object = NodeProperties::GetValueInput(node, 0);
|
||||
Node* effect = NodeProperties::GetEffectInput(node);
|
||||
Node* control = NodeProperties::GetControlInput(node);
|
||||
|
||||
// Optimize the common pattern where a TypeCast is followed by an
|
||||
// AssertNotNull: Reverse the order of these operations, as this will
|
||||
// unlock more optimizations later.
|
||||
// We are implementing this in the typer so we can retype the nodes.
|
||||
if (control->opcode() == IrOpcode::kWasmTypeCast && effect == object &&
|
||||
control == object) {
|
||||
Node* initial_object = NodeProperties::GetValueInput(object, 0);
|
||||
Node* previous_control = NodeProperties::GetControlInput(object);
|
||||
Node* previous_effect = NodeProperties::GetEffectInput(object);
|
||||
ReplaceWithValue(node, object);
|
||||
node->ReplaceInput(NodeProperties::FirstValueIndex(node),
|
||||
initial_object);
|
||||
node->ReplaceInput(NodeProperties::FirstEffectIndex(node),
|
||||
previous_effect);
|
||||
node->ReplaceInput(NodeProperties::FirstControlIndex(node),
|
||||
previous_control);
|
||||
// We do not replace {object}'s effect input to {node} because {node}
|
||||
// has no effect output.
|
||||
object->ReplaceInput(NodeProperties::FirstValueIndex(object), node);
|
||||
object->ReplaceInput(NodeProperties::FirstControlIndex(object), node);
|
||||
Revisit(object);
|
||||
}
|
||||
}
|
||||
|
||||
if (!AllInputsTyped(node)) return NoChange();
|
||||
TypeInModule object_type =
|
||||
NodeProperties::GetType(NodeProperties::GetValueInput(node, 0))
|
||||
|
@ -380,6 +380,7 @@ class RuntimeCallTimer final {
|
||||
ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, VerifyGraph) \
|
||||
ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, WasmBaseOptimization) \
|
||||
ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, WasmGCLowering) \
|
||||
ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, WasmGCOptimization) \
|
||||
ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, WasmInlining) \
|
||||
ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, WasmLoopPeeling) \
|
||||
ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, WasmLoopUnrolling) \
|
||||
|
@ -4220,12 +4220,10 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
|
||||
this->module_);
|
||||
}
|
||||
|
||||
// Checks it {obj} is a nominal type which is a subtype of {rtt}'s index, thus
|
||||
// checking will always succeed. Does not account for nullability.
|
||||
// Checks it {obj} is a subtype of {rtt}'s type, thus checking will always
|
||||
// succeed. Does not account for nullability.
|
||||
bool TypeCheckAlwaysSucceeds(Value obj, Value rtt) {
|
||||
return obj.type.has_index() &&
|
||||
this->module_->has_supertype(obj.type.ref_index()) &&
|
||||
IsSubtypeOf(obj.type,
|
||||
return IsSubtypeOf(obj.type,
|
||||
ValueType::Ref(rtt.type.ref_index(), kNullable),
|
||||
this->module_);
|
||||
}
|
||||
|
@ -90,6 +90,13 @@ V8_INLINE bool IsHeapSubtypeOf(HeapType subtype, HeapType supertype,
|
||||
return IsHeapSubtypeOfImpl(subtype, supertype, module, module);
|
||||
}
|
||||
|
||||
V8_INLINE bool HeapTypesUnrelated(HeapType heap1, HeapType heap2,
|
||||
const WasmModule* module1,
|
||||
const WasmModule* module2) {
|
||||
return !IsHeapSubtypeOf(heap1, heap2, module1, module2) &&
|
||||
!IsHeapSubtypeOf(heap2, heap1, module2, module1);
|
||||
}
|
||||
|
||||
// Checks whether {subtype_index} is valid as a declared subtype of
|
||||
// {supertype_index}.
|
||||
// - Both type must be of the same kind (function, struct, or array).
|
||||
|
Loading…
Reference in New Issue
Block a user