Commit 8372a7c5 authored by Georg Neis's avatar Georg Neis Committed by Commit Bot

[turbofan] Normalize types for Oddball constants

... such that we have only a single representation for special
constants such as undefined, namely the corresponding bitset.
With this CL the following property holds:
    t1.IsSingleton() /\ t2.Is(t1) => t1.Is(t2)

Also clean up the Type interface and improve test coverage a little.

Change-Id: I074e20047c92e2c8215c2d438f2627f4ffdbc409
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2096631
Commit-Queue: Tobias Tebbi <tebbi@chromium.org>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Auto-Submit: Georg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#66684}
parent 72c6a832
......@@ -428,8 +428,8 @@ JSTypedLowering::JSTypedLowering(Editor* editor, JSGraph* jsgraph,
: AdvancedReducer(editor),
jsgraph_(jsgraph),
broker_(broker),
empty_string_type_(Type::HeapConstant(broker, factory()->empty_string(),
graph()->zone())),
empty_string_type_(
Type::Constant(broker, factory()->empty_string(), graph()->zone())),
pointer_comparable_type_(
Type::Union(Type::Oddball(),
Type::Union(Type::SymbolOrReceiver(), empty_string_type_,
......
......@@ -20,21 +20,18 @@ namespace compiler {
OperationTyper::OperationTyper(JSHeapBroker* broker, Zone* zone)
: zone_(zone), cache_(TypeCache::Get()) {
Factory* factory = broker->isolate()->factory();
infinity_ = Type::NewConstant(V8_INFINITY, zone);
minus_infinity_ = Type::NewConstant(-V8_INFINITY, zone);
infinity_ = Type::Constant(V8_INFINITY, zone);
minus_infinity_ = Type::Constant(-V8_INFINITY, zone);
Type truncating_to_zero = Type::MinusZeroOrNaN();
DCHECK(!truncating_to_zero.Maybe(Type::Integral32()));
singleton_empty_string_ =
Type::HeapConstant(broker, factory->empty_string(), zone);
singleton_NaN_string_ =
Type::HeapConstant(broker, factory->NaN_string(), zone);
singleton_zero_string_ =
Type::HeapConstant(broker, factory->zero_string(), zone);
singleton_false_ = Type::HeapConstant(broker, factory->false_value(), zone);
singleton_true_ = Type::HeapConstant(broker, factory->true_value(), zone);
singleton_the_hole_ =
Type::HeapConstant(broker, factory->the_hole_value(), zone);
Type::Constant(broker, factory->empty_string(), zone);
singleton_NaN_string_ = Type::Constant(broker, factory->NaN_string(), zone);
singleton_zero_string_ = Type::Constant(broker, factory->zero_string(), zone);
singleton_false_ = Type::Constant(broker, factory->false_value(), zone);
singleton_true_ = Type::Constant(broker, factory->true_value(), zone);
singleton_the_hole_ = Type::Hole();
signed32ish_ = Type::Union(Type::Signed32(), truncating_to_zero, zone);
unsigned32ish_ = Type::Union(Type::Unsigned32(), truncating_to_zero, zone);
......
......@@ -26,9 +26,9 @@ TypedOptimization::TypedOptimization(Editor* editor,
jsgraph_(jsgraph),
broker_(broker),
true_type_(
Type::HeapConstant(broker, factory()->true_value(), graph()->zone())),
false_type_(Type::HeapConstant(broker, factory()->false_value(),
graph()->zone())),
Type::Constant(broker, factory()->true_value(), graph()->zone())),
false_type_(
Type::Constant(broker, factory()->false_value(), graph()->zone())),
type_cache_(TypeCache::Get()) {}
TypedOptimization::~TypedOptimization() = default;
......
......@@ -547,10 +547,10 @@ Type Typer::Visitor::ToLength(Type type, Typer* t) {
double min = type.Min();
double max = type.Max();
if (max <= 0.0) {
return Type::NewConstant(0, t->zone());
return Type::Constant(0, t->zone());
}
if (min >= kMaxSafeInteger) {
return Type::NewConstant(kMaxSafeInteger, t->zone());
return Type::Constant(kMaxSafeInteger, t->zone());
}
if (min <= 0.0) min = 0.0;
if (max >= kMaxSafeInteger) max = kMaxSafeInteger;
......@@ -782,7 +782,7 @@ Type Typer::Visitor::TypeFloat64Constant(Node* node) { UNREACHABLE(); }
Type Typer::Visitor::TypeNumberConstant(Node* node) {
double number = OpParameter<double>(node->op());
return Type::NewConstant(number, zone());
return Type::Constant(number, zone());
}
Type Typer::Visitor::TypeHeapConstant(Node* node) {
......@@ -2393,7 +2393,7 @@ Type Typer::Visitor::TypeAssertType(Node* node) { UNREACHABLE(); }
// Heap constants.
Type Typer::Visitor::TypeConstant(Handle<Object> value) {
return Type::NewConstant(typer_->broker(), value, zone());
return Type::Constant(typer_->broker(), value, zone());
}
Type Typer::Visitor::TypeJSGetIterator(Node* node) { return Type::Any(); }
......
......@@ -841,7 +841,7 @@ Type Type::NormalizeRangeAndBitset(Type range, bitset* bits, Zone* zone) {
return Type::Range(range_min, range_max, zone);
}
Type Type::NewConstant(double value, Zone* zone) {
Type Type::Constant(double value, Zone* zone) {
if (RangeType::IsInteger(value)) {
return Range(value, value, zone);
} else if (IsMinusZero(value)) {
......@@ -854,14 +854,13 @@ Type Type::NewConstant(double value, Zone* zone) {
return OtherNumberConstant(value, zone);
}
Type Type::NewConstant(JSHeapBroker* broker, Handle<i::Object> value,
Zone* zone) {
Type Type::Constant(JSHeapBroker* broker, Handle<i::Object> value, Zone* zone) {
ObjectRef ref(broker, value);
if (ref.IsSmi()) {
return NewConstant(static_cast<double>(ref.AsSmi()), zone);
return Constant(static_cast<double>(ref.AsSmi()), zone);
}
if (ref.IsHeapNumber()) {
return NewConstant(ref.AsHeapNumber().value(), zone);
return Constant(ref.AsHeapNumber().value(), zone);
}
if (ref.IsString() && !ref.IsInternalizedString()) {
return Type::String();
......@@ -1093,16 +1092,13 @@ Type Type::OtherNumberConstant(double value, Zone* zone) {
return FromTypeBase(OtherNumberConstantType::New(value, zone));
}
// static
Type Type::HeapConstant(JSHeapBroker* broker, Handle<i::Object> value,
Zone* zone) {
return FromTypeBase(
HeapConstantType::New(HeapObjectRef(broker, value), zone));
}
// static
Type Type::HeapConstant(const HeapObjectRef& value, Zone* zone) {
return HeapConstantType::New(value, zone);
DCHECK(!value.IsHeapNumber());
DCHECK_IMPLIES(value.IsString(), value.IsInternalizedString());
BitsetType::bitset bitset = BitsetType::Lub(value.GetHeapObjectType());
if (Type(bitset).IsSingleton()) return Type(bitset);
return HeapConstantType::New(value, bitset, zone);
}
// static
......@@ -1115,11 +1111,6 @@ Type Type::Range(RangeType::Limits lims, Zone* zone) {
return FromTypeBase(RangeType::New(lims, zone));
}
// static
Type Type::Union(int length, Zone* zone) {
return FromTypeBase(UnionType::New(length, zone));
}
const HeapConstantType* Type::AsHeapConstant() const {
DCHECK(IsKind(TypeBase::kHeapConstant));
return static_cast<const HeapConstantType*>(ToTypeBase());
......
......@@ -369,26 +369,15 @@ class V8_EXPORT_PRIVATE Type {
static Type SignedSmall() { return NewBitset(BitsetType::SignedSmall()); }
static Type UnsignedSmall() { return NewBitset(BitsetType::UnsignedSmall()); }
static Type OtherNumberConstant(double value, Zone* zone);
static Type HeapConstant(JSHeapBroker* broker, Handle<i::Object> value,
Zone* zone);
static Type HeapConstant(const HeapObjectRef& value, Zone* zone);
static Type Constant(JSHeapBroker* broker, Handle<i::Object> value,
Zone* zone);
static Type Constant(double value, Zone* zone);
static Type Range(double min, double max, Zone* zone);
static Type Range(RangeType::Limits lims, Zone* zone);
static Type Tuple(Type first, Type second, Type third, Zone* zone);
static Type Union(int length, Zone* zone);
// NewConstant is a factory that returns Constant, Range or Number.
static Type NewConstant(JSHeapBroker* broker, Handle<i::Object> value,
Zone* zone);
static Type NewConstant(double value, Zone* zone);
static Type Union(Type type1, Type type2, Zone* zone);
static Type Intersect(Type type1, Type type2, Zone* zone);
static Type For(HeapObjectType const& type) {
return NewBitset(BitsetType::ExpandInternals(BitsetType::Lub(type)));
}
static Type For(MapRef const& type) {
return NewBitset(BitsetType::ExpandInternals(BitsetType::Lub(type)));
}
......@@ -466,6 +455,7 @@ class V8_EXPORT_PRIVATE Type {
friend size_t hash_value(Type type);
explicit Type(bitset bits) : payload_(bits | 1u) {}
Type(TypeBase* type_base) // NOLINT(runtime/explicit)
: payload_(reinterpret_cast<uintptr_t>(type_base)) {}
......@@ -498,6 +488,10 @@ class V8_EXPORT_PRIVATE Type {
static Type NewBitset(bitset bits) { return Type(bits); }
static Type Range(RangeType::Limits lims, Zone* zone);
static Type OtherNumberConstant(double value, Zone* zone);
static Type HeapConstant(const HeapObjectRef& value, Zone* zone);
static bool Overlap(const RangeType* lhs, const RangeType* rhs);
static bool Contains(const RangeType* lhs, const RangeType* rhs);
......@@ -560,10 +554,8 @@ class V8_EXPORT_PRIVATE HeapConstantType : public NON_EXPORTED_BASE(TypeBase) {
friend class Type;
friend class BitsetType;
static HeapConstantType* New(const HeapObjectRef& heap_ref, Zone* zone) {
DCHECK(!heap_ref.IsHeapNumber());
DCHECK_IMPLIES(heap_ref.IsString(), heap_ref.IsInternalizedString());
BitsetType::bitset bitset = BitsetType::Lub(heap_ref.GetHeapObjectType());
static HeapConstantType* New(const HeapObjectRef& heap_ref,
BitsetType::bitset bitset, Zone* zone) {
return new (zone->New(sizeof(HeapConstantType)))
HeapConstantType(bitset, heap_ref);
}
......
This diff is collapsed.
......@@ -53,29 +53,34 @@ class Types {
SignedSmall = Type::SignedSmall();
UnsignedSmall = Type::UnsignedSmall();
object_map =
Handle<i::Map> object_map =
isolate->factory()->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
smi = handle(Smi::FromInt(666), isolate);
boxed_smi = isolate->factory()->NewHeapNumber(666);
signed32 = isolate->factory()->NewHeapNumber(0x40000000);
float1 = isolate->factory()->NewHeapNumber(1.53);
float2 = isolate->factory()->NewHeapNumber(0.53);
Handle<i::Smi> smi = handle(Smi::FromInt(666), isolate);
Handle<i::HeapNumber> boxed_smi = isolate->factory()->NewHeapNumber(666);
Handle<i::HeapNumber> signed32 =
isolate->factory()->NewHeapNumber(0x40000000);
Handle<i::HeapNumber> float1 = isolate->factory()->NewHeapNumber(1.53);
Handle<i::HeapNumber> float2 = isolate->factory()->NewHeapNumber(0.53);
// float3 is identical to float1 in order to test that OtherNumberConstant
// types are equal by double value and not by handle pointer value.
float3 = isolate->factory()->NewHeapNumber(1.53);
object1 = isolate->factory()->NewJSObjectFromMap(object_map);
object2 = isolate->factory()->NewJSObjectFromMap(object_map);
array = isolate->factory()->NewJSArray(20);
uninitialized = isolate->factory()->uninitialized_value();
SmiConstant = Type::NewConstant(js_heap_broker(), smi, zone);
Signed32Constant = Type::NewConstant(js_heap_broker(), signed32, zone);
ObjectConstant1 = Type::HeapConstant(js_heap_broker(), object1, zone);
ObjectConstant2 = Type::HeapConstant(js_heap_broker(), object2, zone);
ArrayConstant = Type::HeapConstant(js_heap_broker(), array, zone);
Handle<i::HeapNumber> float3 = isolate->factory()->NewHeapNumber(1.53);
Handle<i::JSObject> object1 =
isolate->factory()->NewJSObjectFromMap(object_map);
Handle<i::JSObject> object2 =
isolate->factory()->NewJSObjectFromMap(object_map);
Handle<i::JSArray> array = isolate->factory()->NewJSArray(20);
Handle<i::Oddball> uninitialized =
isolate->factory()->uninitialized_value();
Handle<i::Oddball> undefined = isolate->factory()->undefined_value();
Handle<i::HeapNumber> nan = isolate->factory()->nan_value();
SmiConstant = Type::Constant(js_heap_broker(), smi, zone);
Signed32Constant = Type::Constant(js_heap_broker(), signed32, zone);
ObjectConstant1 = Type::Constant(js_heap_broker(), object1, zone);
ObjectConstant2 = Type::Constant(js_heap_broker(), object2, zone);
ArrayConstant = Type::Constant(js_heap_broker(), array, zone);
UninitializedConstant =
Type::HeapConstant(js_heap_broker(), uninitialized, zone);
Type::Constant(js_heap_broker(), uninitialized, zone);
values.push_back(smi);
values.push_back(boxed_smi);
......@@ -84,11 +89,13 @@ class Types {
values.push_back(object2);
values.push_back(array);
values.push_back(uninitialized);
values.push_back(undefined);
values.push_back(nan);
values.push_back(float1);
values.push_back(float2);
values.push_back(float3);
for (ValueVector::iterator it = values.begin(); it != values.end(); ++it) {
types.push_back(Type::NewConstant(js_heap_broker(), *it, zone));
types.push_back(Type::Constant(js_heap_broker(), *it, zone));
}
integers.push_back(isolate->factory()->NewNumber(-V8_INFINITY));
......@@ -109,19 +116,6 @@ class Types {
}
}
Handle<i::Map> object_map;
Handle<i::Smi> smi;
Handle<i::HeapNumber> boxed_smi;
Handle<i::HeapNumber> signed32;
Handle<i::HeapNumber> float1;
Handle<i::HeapNumber> float2;
Handle<i::HeapNumber> float3;
Handle<i::JSObject> object1;
Handle<i::JSObject> object2;
Handle<i::JSArray> array;
Handle<i::Oddball> uninitialized;
#define DECLARE_TYPE(name, value) Type name;
PROPER_BITSET_TYPE_LIST(DECLARE_TYPE)
#undef DECLARE_TYPE
......@@ -145,12 +139,12 @@ class Types {
ValueVector values;
ValueVector integers; // "Integer" values used for range limits.
Type NewConstant(Handle<i::Object> value) {
return Type::NewConstant(js_heap_broker(), value, zone_);
Type Constant(Handle<i::Object> value) {
return Type::Constant(js_heap_broker(), value, zone_);
}
Type HeapConstant(Handle<i::HeapObject> value) {
return Type::HeapConstant(js_heap_broker(), value, zone_);
return Type::Constant(js_heap_broker(), value, zone_);
}
Type Range(double min, double max) { return Type::Range(min, max, zone_); }
......@@ -188,7 +182,7 @@ class Types {
}
case 1: { // constant
int i = rng_->NextInt(static_cast<int>(values.size()));
return Type::NewConstant(js_heap_broker(), values[i], zone_);
return Type::Constant(js_heap_broker(), values[i], zone_);
}
case 2: { // range
int i = rng_->NextInt(static_cast<int>(integers.size()));
......
......@@ -92,7 +92,7 @@ class ConstantFoldingReducerTest : public TypedGraphTest {
TEST_F(ConstantFoldingReducerTest, ParameterWithMinusZero) {
{
Reduction r = Reduce(Parameter(
Type::NewConstant(broker(), factory()->minus_zero_value(), zone())));
Type::Constant(broker(), factory()->minus_zero_value(), zone())));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsNumberConstant(-0.0));
}
......@@ -104,7 +104,7 @@ TEST_F(ConstantFoldingReducerTest, ParameterWithMinusZero) {
{
Reduction r = Reduce(Parameter(Type::Union(
Type::MinusZero(),
Type::NewConstant(broker(), factory()->NewNumber(0), zone()), zone())));
Type::Constant(broker(), factory()->NewNumber(0), zone()), zone())));
EXPECT_FALSE(r.Changed());
}
}
......@@ -112,7 +112,7 @@ TEST_F(ConstantFoldingReducerTest, ParameterWithMinusZero) {
TEST_F(ConstantFoldingReducerTest, ParameterWithNull) {
Handle<HeapObject> null = factory()->null_value();
{
Reduction r = Reduce(Parameter(Type::NewConstant(broker(), null, zone())));
Reduction r = Reduce(Parameter(Type::Constant(broker(), null, zone())));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsHeapConstant(null));
}
......@@ -129,14 +129,13 @@ TEST_F(ConstantFoldingReducerTest, ParameterWithNaN) {
std::numeric_limits<double>::signaling_NaN()};
TRACED_FOREACH(double, nan, kNaNs) {
Handle<Object> constant = factory()->NewNumber(nan);
Reduction r =
Reduce(Parameter(Type::NewConstant(broker(), constant, zone())));
Reduction r = Reduce(Parameter(Type::Constant(broker(), constant, zone())));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsNumberConstant(IsNaN()));
}
{
Reduction r = Reduce(
Parameter(Type::NewConstant(broker(), factory()->nan_value(), zone())));
Parameter(Type::Constant(broker(), factory()->nan_value(), zone())));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsNumberConstant(IsNaN()));
}
......@@ -150,8 +149,7 @@ TEST_F(ConstantFoldingReducerTest, ParameterWithNaN) {
TEST_F(ConstantFoldingReducerTest, ParameterWithPlainNumber) {
TRACED_FOREACH(double, value, kFloat64Values) {
Handle<Object> constant = factory()->NewNumber(value);
Reduction r =
Reduce(Parameter(Type::NewConstant(broker(), constant, zone())));
Reduction r = Reduce(Parameter(Type::Constant(broker(), constant, zone())));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsNumberConstant(value));
}
......@@ -171,7 +169,7 @@ TEST_F(ConstantFoldingReducerTest, ParameterWithUndefined) {
}
{
Reduction r =
Reduce(Parameter(Type::NewConstant(broker(), undefined, zone())));
Reduce(Parameter(Type::Constant(broker(), undefined, zone())));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsHeapConstant(undefined));
}
......@@ -193,8 +191,8 @@ TEST_F(ConstantFoldingReducerTest, ToBooleanWithFalsish) {
Type::Union(
Type::Undetectable(),
Type::Union(
Type::NewConstant(
broker(), factory()->false_value(), zone()),
Type::Constant(broker(), factory()->false_value(),
zone()),
Type::Range(0.0, 0.0, zone()), zone()),
zone()),
zone()),
......@@ -210,7 +208,7 @@ TEST_F(ConstantFoldingReducerTest, ToBooleanWithFalsish) {
TEST_F(ConstantFoldingReducerTest, ToBooleanWithTruish) {
Node* input = Parameter(
Type::Union(
Type::NewConstant(broker(), factory()->true_value(), zone()),
Type::Constant(broker(), factory()->true_value(), zone()),
Type::Union(Type::DetectableReceiver(), Type::Symbol(), zone()),
zone()),
0);
......
......@@ -66,7 +66,7 @@ Node* GraphTest::NumberConstant(volatile double value) {
Node* GraphTest::HeapConstant(const Handle<HeapObject>& value) {
Node* node = graph()->NewNode(common()->HeapConstant(value));
Type type = Type::NewConstant(broker(), value, zone());
Type type = Type::Constant(broker(), value, zone());
NodeProperties::SetType(node, type);
return node;
}
......
......@@ -175,7 +175,7 @@ class TyperTest : public TypedGraphTest {
for (int x1 = lmin; x1 < lmin + width; x1++) {
for (int x2 = rmin; x2 < rmin + width; x2++) {
double result_value = opfun(x1, x2);
Type result_type = Type::NewConstant(
Type result_type = Type::Constant(
&broker_, isolate()->factory()->NewNumber(result_value),
zone());
EXPECT_TRUE(result_type.Is(expected_type));
......@@ -197,7 +197,7 @@ class TyperTest : public TypedGraphTest {
double x1 = RandomInt(r1.AsRange());
double x2 = RandomInt(r2.AsRange());
double result_value = opfun(x1, x2);
Type result_type = Type::NewConstant(
Type result_type = Type::Constant(
&broker_, isolate()->factory()->NewNumber(result_value), zone());
EXPECT_TRUE(result_type.Is(expected_type));
}
......@@ -205,13 +205,13 @@ class TyperTest : public TypedGraphTest {
// Test extreme cases.
double x1 = +1e-308;
double x2 = -1e-308;
Type r1 = Type::NewConstant(&broker_, isolate()->factory()->NewNumber(x1),
zone());
Type r2 = Type::NewConstant(&broker_, isolate()->factory()->NewNumber(x2),
zone());
Type r1 =
Type::Constant(&broker_, isolate()->factory()->NewNumber(x1), zone());
Type r2 =
Type::Constant(&broker_, isolate()->factory()->NewNumber(x2), zone());
Type expected_type = TypeBinaryOp(op, r1, r2);
double result_value = opfun(x1, x2);
Type result_type = Type::NewConstant(
Type result_type = Type::Constant(
&broker_, isolate()->factory()->NewNumber(result_value), zone());
EXPECT_TRUE(result_type.Is(expected_type));
}
......@@ -226,11 +226,11 @@ class TyperTest : public TypedGraphTest {
double x1 = RandomInt(r1.AsRange());
double x2 = RandomInt(r2.AsRange());
bool result_value = opfun(x1, x2);
Type result_type = Type::NewConstant(
&broker_,
result_value ? isolate()->factory()->true_value()
: isolate()->factory()->false_value(),
zone());
Type result_type =
Type::Constant(&broker_,
result_value ? isolate()->factory()->true_value()
: isolate()->factory()->false_value(),
zone());
EXPECT_TRUE(result_type.Is(expected_type));
}
}
......@@ -246,7 +246,7 @@ class TyperTest : public TypedGraphTest {
int32_t x1 = static_cast<int32_t>(RandomInt(r1.AsRange()));
int32_t x2 = static_cast<int32_t>(RandomInt(r2.AsRange()));
double result_value = opfun(x1, x2);
Type result_type = Type::NewConstant(
Type result_type = Type::Constant(
&broker_, isolate()->factory()->NewNumber(result_value), zone());
EXPECT_TRUE(result_type.Is(expected_type));
}
......
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