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

[wasm][turbofan] Annotate nodes with wasm types

We introduce wasm types to Turbofan. They are represented by a new
subtype of {TypeBase}.
Types are attached to nodes during graph generation, as nodes are
assigned to wasm values. Therefore, phi nodes corresponding to merges
are not typed. Missing types will be computed, and assigned types will
be narrowed as much as possible, in a retyping phase that will be
introduced later.

Bug: v8:7748
Change-Id: I943559cf1d512edfab3bb2d22f8748c072cb1911
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3660248Reviewed-by: 's avatarMaya Lekova <mslekova@chromium.org>
Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80778}
parent 42ff412a
......@@ -13,6 +13,10 @@
#include "src/objects/turbofan-types.h"
#include "src/utils/ostreams.h"
#ifdef V8_ENABLE_WEBASSEMBLY
#include "src/wasm/wasm-subtyping.h"
#endif
namespace v8 {
namespace internal {
namespace compiler {
......@@ -572,6 +576,16 @@ bool Type::SlowIs(Type that) const {
}
if (this->IsRange()) return false;
#ifdef V8_ENABLE_WEBASSEMBLY
if (this->IsWasm()) {
if (!that.IsWasm()) return false;
wasm::TypeInModule this_type = this->AsWasm();
wasm::TypeInModule that_type = that.AsWasm();
return wasm::IsSubtypeOf(this_type.type, that_type.type, this_type.module,
that_type.module);
}
#endif
return this->SimplyEquals(that);
}
......@@ -1062,6 +1076,10 @@ void Type::PrintTo(std::ostream& os) const {
os << type_i;
}
os << ">";
#ifdef V8_ENABLE_WEBASSEMBLY
} else if (this->IsWasm()) {
os << "Wasm:" << this->AsWasm().type.name();
#endif
} else {
UNREACHABLE();
}
......@@ -1146,6 +1164,25 @@ const UnionType* Type::AsUnion() const {
return static_cast<const UnionType*>(ToTypeBase());
}
#ifdef V8_ENABLE_WEBASSEMBLY
// static
Type Type::Wasm(wasm::ValueType value_type, const wasm::WasmModule* module,
Zone* zone) {
return FromTypeBase(WasmType::New(value_type, module, zone));
}
// static
Type Type::Wasm(wasm::TypeInModule type_in_module, Zone* zone) {
return Wasm(type_in_module.type, type_in_module.module, zone);
}
wasm::TypeInModule Type::AsWasm() const {
DCHECK(IsKind(TypeBase::kWasm));
auto wasm_type = static_cast<const WasmType*>(ToTypeBase());
return {wasm_type->value_type(), wasm_type->module()};
}
#endif
std::ostream& operator<<(std::ostream& os, Type type) {
type.PrintTo(os);
return os;
......
......@@ -13,8 +13,15 @@
#include "src/objects/objects.h"
#include "src/utils/ostreams.h"
#ifdef V8_ENABLE_WEBASSEMBLY
#include "src/wasm/value-type.h"
#endif
namespace v8 {
namespace internal {
namespace wasm {
struct TypeInModule;
}
namespace compiler {
// SUMMARY
......@@ -95,7 +102,7 @@ namespace compiler {
// clang-format off
#define INTERNAL_BITSET_TYPE_LIST(V) \
#define INTERNAL_BITSET_TYPE_LIST(V) \
V(OtherUnsigned31, uint64_t{1} << 1) \
V(OtherUnsigned32, uint64_t{1} << 2) \
V(OtherSigned32, uint64_t{1} << 3) \
......@@ -305,7 +312,14 @@ class TypeBase {
protected:
friend class Type;
enum Kind { kHeapConstant, kOtherNumberConstant, kTuple, kUnion, kRange };
enum Kind {
kHeapConstant,
kOtherNumberConstant,
kTuple,
kUnion,
kRange,
kWasm
};
Kind kind() const { return kind_; }
explicit TypeBase(Kind kind) : kind_(kind) {}
......@@ -367,6 +381,25 @@ class RangeType : public TypeBase {
Limits limits_;
};
#ifdef V8_ENABLE_WEBASSEMBLY
class WasmType : public TypeBase {
public:
static WasmType* New(wasm::ValueType value_type,
const wasm::WasmModule* module, Zone* zone) {
return zone->New<WasmType>(value_type, module);
}
wasm::ValueType value_type() const { return value_type_; }
const wasm::WasmModule* module() const { return module_; }
private:
friend Zone;
explicit WasmType(wasm::ValueType value_type, const wasm::WasmModule* module)
: TypeBase(kWasm), value_type_(value_type), module_(module) {}
wasm::ValueType value_type_;
const wasm::WasmModule* module_;
};
#endif // V8_ENABLE_WEBASSEMBLY
// -----------------------------------------------------------------------------
// The actual type.
......@@ -393,6 +426,11 @@ class V8_EXPORT_PRIVATE Type {
static Type Union(Type type1, Type type2, Zone* zone);
static Type Intersect(Type type1, Type type2, Zone* zone);
#ifdef V8_ENABLE_WEBASSEMBLY
static Type Wasm(wasm::ValueType value_type, const wasm::WasmModule* module,
Zone* zone);
static Type Wasm(wasm::TypeInModule type_in_module, Zone* zone);
#endif
static Type For(MapRef const& type) {
return NewBitset(BitsetType::ExpandInternals(BitsetType::Lub(type)));
......@@ -416,6 +454,9 @@ class V8_EXPORT_PRIVATE Type {
return IsKind(TypeBase::kOtherNumberConstant);
}
bool IsTuple() const { return IsKind(TypeBase::kTuple); }
#ifdef V8_ENABLE_WEBASSEMBLY
bool IsWasm() const { return IsKind(TypeBase::kWasm); }
#endif
bool IsSingleton() const {
if (IsNone()) return false;
......@@ -431,6 +472,7 @@ class V8_EXPORT_PRIVATE Type {
const OtherNumberConstantType* AsOtherNumberConstant() const;
const RangeType* AsRange() const;
const TupleType* AsTuple() const;
wasm::TypeInModule AsWasm() const;
// Minimum and maximum of a numeric type.
// These functions do not distinguish between -0 and +0. NaN is ignored.
......
......@@ -5464,9 +5464,7 @@ Node* WasmGraphBuilder::RefTest(Node* object, Node* rtt,
Node* WasmGraphBuilder::RefCast(Node* object, Node* rtt,
WasmTypeCheckConfig config,
wasm::WasmCodePosition position) {
return FLAG_experimental_wasm_assume_ref_cast_succeeds
? object
: gasm_->WasmTypeCast(object, rtt, config);
return gasm_->WasmTypeCast(object, rtt, config);
}
void WasmGraphBuilder::BrOnCast(Node* object, Node* rtt,
......@@ -5597,6 +5595,13 @@ void WasmGraphBuilder::BrOnI31(Node* object, Node* /* rtt */,
*no_match_effect = effect();
}
Node* WasmGraphBuilder::TypeGuard(Node* value, wasm::ValueType type) {
DCHECK_NOT_NULL(env_);
return SetEffect(graph()->NewNode(mcgraph()->common()->TypeGuard(Type::Wasm(
type, env_->module, graph()->zone())),
value, effect(), control()));
}
Node* WasmGraphBuilder::StructGet(Node* struct_object,
const wasm::StructType* struct_type,
uint32_t field_index, CheckForNull null_check,
......@@ -5758,6 +5763,19 @@ Node* WasmGraphBuilder::I31GetU(Node* input) {
gasm_->WordShr(input, gasm_->IntPtrConstant(kI31To32BitSmiShift)));
}
Node* WasmGraphBuilder::SetType(Node* node, wasm::ValueType type) {
DCHECK_NOT_NULL(env_);
if (!compiler::NodeProperties::IsTyped(node)) {
compiler::NodeProperties::SetType(
node, compiler::Type::Wasm(type, env_->module, graph_zone()));
} else {
// We might try to set the type twice since some nodes are cached in the
// graph assembler, but we should never change the type.
DCHECK_EQ(compiler::NodeProperties::GetType(node).AsWasm().type, type);
}
return node;
}
class WasmDecorator final : public GraphDecorator {
public:
explicit WasmDecorator(NodeOriginTable* origins, wasm::Decoder* decoder)
......
......@@ -418,6 +418,8 @@ class WasmGraphBuilder {
return effect_and_control;
}
Node* SetType(Node* node, wasm::ValueType type);
// Utilities to manipulate sets of instance cache nodes.
void InitInstanceCache(WasmInstanceCacheNodes* instance_cache);
void PrepareInstanceCacheForLoop(WasmInstanceCacheNodes* instance_cache,
......@@ -537,6 +539,8 @@ class WasmGraphBuilder {
Node** match_control, Node** match_effect,
Node** no_match_control, Node** no_match_effect);
Node* StringNewWtf8(uint32_t memory, Node* offset, Node* size);
Node* IsNull(Node* object);
Node* TypeGuard(Node* value, wasm::ValueType type);
bool has_simd() const { return has_simd_; }
......@@ -695,8 +699,6 @@ class WasmGraphBuilder {
void MemTypeToUintPtrOrOOBTrap(std::initializer_list<Node**> nodes,
wasm::WasmCodePosition position);
Node* IsNull(Node* object);
Node* AssertNotNull(Node* object, wasm::WasmCodePosition position);
void GetGlobalBaseAndOffset(const wasm::WasmGlobal&, Node** base_node,
......
......@@ -52,6 +52,8 @@ Reduction WasmGCLowering::Reduce(Node* node) {
return ReduceIsNull(node);
case IrOpcode::kRttCanon:
return ReduceRttCanon(node);
case IrOpcode::kTypeGuard:
return ReduceTypeGuard(node);
default:
return NoChange();
}
......@@ -201,6 +203,7 @@ Reduction WasmGCLowering::ReduceIsNull(Node* node) {
}
Reduction WasmGCLowering::ReduceRttCanon(Node* node) {
DCHECK_EQ(node->opcode(), IrOpcode::kRttCanon);
int type_index = OpParameter<int>(node->op());
Node* maps_list = gasm_.LoadImmutable(
MachineType::TaggedPointer(), instance_node_,
......@@ -210,6 +213,14 @@ Reduction WasmGCLowering::ReduceRttCanon(Node* node) {
wasm::ObjectAccess::ElementOffsetInTaggedFixedArray(type_index)));
}
Reduction WasmGCLowering::ReduceTypeGuard(Node* node) {
DCHECK_EQ(node->opcode(), IrOpcode::kTypeGuard);
Node* alias = NodeProperties::GetValueInput(node, 0);
ReplaceWithValue(node, alias);
node->Kill();
return Replace(alias);
}
} // namespace compiler
} // namespace internal
} // namespace v8
......@@ -34,6 +34,7 @@ class WasmGCLowering final : public AdvancedReducer {
Reduction ReduceNull(Node* node);
Reduction ReduceIsNull(Node* node);
Reduction ReduceRttCanon(Node* node);
Reduction ReduceTypeGuard(Node* node);
Node* Null();
WasmGraphAssembler gasm_;
Node* dead_;
......
This diff is collapsed.
......@@ -95,6 +95,12 @@ V8_EXPORT_PRIVATE bool ValidSubtypeDefinition(uint32_t subtype_index,
uint32_t supertype_index,
const WasmModule* sub_module,
const WasmModule* super_module);
struct TypeInModule {
ValueType type;
const WasmModule* module;
};
} // namespace wasm
} // namespace internal
} // namespace v8
......
......@@ -2089,11 +2089,16 @@ static void TestBuildGraphForSimpleExpression(WasmOpcode opcode) {
compiler::JSGraph jsgraph(isolate, &graph, &common, nullptr, nullptr,
&machine);
const FunctionSig* sig = WasmOpcodes::Signature(opcode);
WasmModule module;
WasmFeatures enabled;
CompilationEnv env(&module, BoundsCheckStrategy::kExplicitBoundsChecks,
RuntimeExceptionSupport::kRuntimeExceptionSupport, enabled,
DynamicTiering::kDynamicTiering);
if (sig->parameter_count() == 1) {
byte code[] = {WASM_NO_LOCALS, kExprLocalGet, 0, static_cast<byte>(opcode),
WASM_END};
TestBuildingGraph(&zone, &jsgraph, nullptr, sig, nullptr, code,
TestBuildingGraph(&zone, &jsgraph, &env, sig, nullptr, code,
code + arraysize(code));
} else {
CHECK_EQ(2, sig->parameter_count());
......@@ -2104,7 +2109,7 @@ static void TestBuildGraphForSimpleExpression(WasmOpcode opcode) {
1,
static_cast<byte>(opcode),
WASM_END};
TestBuildingGraph(&zone, &jsgraph, nullptr, sig, nullptr, code,
TestBuildingGraph(&zone, &jsgraph, &env, sig, nullptr, code,
code + arraysize(code));
}
}
......
......@@ -413,10 +413,10 @@ void TestBuildingGraphWithBuilder(compiler::WasmGraphBuilder* builder,
}
void TestBuildingGraph(Zone* zone, compiler::JSGraph* jsgraph,
CompilationEnv* module, const FunctionSig* sig,
CompilationEnv* env, const FunctionSig* sig,
compiler::SourcePositionTable* source_position_table,
const byte* start, const byte* end) {
compiler::WasmGraphBuilder builder(module, zone, jsgraph, sig,
compiler::WasmGraphBuilder builder(env, zone, jsgraph, sig,
source_position_table);
TestBuildingGraphWithBuilder(&builder, zone, sig, start, end);
}
......
......@@ -310,7 +310,7 @@ class TestingModuleBuilder {
};
void TestBuildingGraph(Zone* zone, compiler::JSGraph* jsgraph,
CompilationEnv* module, const FunctionSig* sig,
CompilationEnv* env, const FunctionSig* sig,
compiler::SourcePositionTable* source_position_table,
const byte* start, const byte* end);
......
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