Commit 8bd0bd52 authored by jarin's avatar jarin Committed by Commit bot

[turbofan] Make the representation type component independent of the semantic component.

R=rossberg@chromium.org
BUG=

Review URL: https://codereview.chromium.org/904863002

Cr-Commit-Position: refs/heads/master@{#26621}
parent 30c71859
......@@ -436,14 +436,14 @@ void Typer::Decorator::Decorate(Node* node, bool incomplete) {
Bounds Typer::Visitor::TypeUnaryOp(Node* node, UnaryTyperFun f) {
Bounds input = Operand(node, 0);
Type* upper = input.upper->Is(Type::None())
? Type::None()
: f(input.upper, typer_);
Type* lower = input.lower->Is(Type::None())
? Type::None()
: (input.lower == input.upper || upper->IsConstant())
? upper // TODO(neis): Extend this to Range(x,x), NaN, MinusZero, ...?
: f(input.lower, typer_);
Type* upper =
input.upper->IsInhabited() ? f(input.upper, typer_) : Type::None();
Type* lower = input.lower->IsInhabited()
? ((input.lower == input.upper || upper->IsConstant())
? upper // TODO(neis): Extend this to Range(x,x),
// NaN, MinusZero, ...?
: f(input.lower, typer_))
: Type::None();
// TODO(neis): Figure out what to do with lower bound.
return Bounds(lower, upper);
}
......@@ -452,15 +452,16 @@ Bounds Typer::Visitor::TypeUnaryOp(Node* node, UnaryTyperFun f) {
Bounds Typer::Visitor::TypeBinaryOp(Node* node, BinaryTyperFun f) {
Bounds left = Operand(node, 0);
Bounds right = Operand(node, 1);
Type* upper = left.upper->Is(Type::None()) || right.upper->Is(Type::None())
? Type::None()
: f(left.upper, right.upper, typer_);
Type* lower = left.lower->Is(Type::None()) || right.lower->Is(Type::None())
? Type::None()
: ((left.lower == left.upper && right.lower == right.upper) ||
upper->IsConstant())
? upper
: f(left.lower, right.lower, typer_);
Type* upper = left.upper->IsInhabited() && right.upper->IsInhabited()
? f(left.upper, right.upper, typer_)
: Type::None();
Type* lower =
left.lower->IsInhabited() && right.lower->IsInhabited()
? (((left.lower == left.upper && right.lower == right.upper) ||
upper->IsConstant())
? upper
: f(left.lower, right.lower, typer_))
: Type::None();
// TODO(neis): Figure out what to do with lower bound.
return Bounds(lower, upper);
}
......
......@@ -15,7 +15,7 @@ namespace internal {
template <class T>
HType HType::FromType(typename T::TypeHandle type) {
if (T::Any()->Is(type)) return HType::Any();
if (type->Is(T::None())) return HType::None();
if (!type->IsInhabited()) return HType::None();
if (type->Is(T::SignedSmall())) return HType::Smi();
if (type->Is(T::Number())) return HType::TaggedNumber();
if (type->Is(T::Null())) return HType::Null();
......
This diff is collapsed.
......@@ -430,8 +430,11 @@ class TypeImpl : public Config::Base {
return Of(*value, region);
}
// Predicates.
// Extraction of components.
static TypeHandle Representation(TypeHandle t, Region* region);
static TypeHandle Semantic(TypeHandle t, Region* region);
// Predicates.
bool IsInhabited() { return BitsetType::IsInhabited(this->BitsetLub()); }
bool Is(TypeImpl* that) { return this == that || this->SlowIs(that); }
......@@ -563,12 +566,16 @@ class TypeImpl : public Config::Base {
}
UnionType* AsUnion() { return UnionType::cast(this); }
bitset Representation();
// Auxiliary functions.
bool SemanticMaybe(TypeImpl* that);
bitset BitsetGlb() { return BitsetType::Glb(this); }
bitset BitsetLub() { return BitsetType::Lub(this); }
bool SlowIs(TypeImpl* that);
bool SemanticIs(TypeImpl* that);
static bool IsInteger(double x) {
return nearbyint(x) == x && !i::IsMinusZero(x); // Allows for infinities.
......@@ -580,16 +587,9 @@ class TypeImpl : public Config::Base {
struct Limits {
double min;
double max;
bitset representation;
Limits(double min, double max, bitset representation)
: min(min), max(max), representation(representation) {}
explicit Limits(RangeType* range)
: min(range->Min()),
max(range->Max()),
representation(REPRESENTATION(range->Bound())) {}
static Limits Empty(Region* region) {
return Limits(1, 0, BitsetType::kNone);
}
Limits(double min, double max) : min(min), max(max) {}
explicit Limits(RangeType* range) : min(range->Min()), max(range->Max()) {}
static Limits Empty(Region* region) { return Limits(1, 0); }
};
static bool IsEmpty(Limits lim);
......@@ -649,11 +649,13 @@ class TypeImpl<Config>::BitsetType : public TypeImpl<Config> {
if (FLAG_enable_slow_asserts) CheckNumberBits(bits);
return Config::from_bitset(bits, region);
}
// TODO(neis): Eventually allow again for types with empty semantics
// part and modify intersection and possibly subtyping accordingly.
static bool IsInhabited(bitset bits) {
return bits & kSemantic;
return SEMANTIC(bits) != kNone && REPRESENTATION(bits) != kNone;
}
static bool SemanticIsInhabited(bitset bits) {
return SEMANTIC(bits) != kNone;
}
static bool Is(bitset bits1, bitset bits2) {
......@@ -855,8 +857,8 @@ class TypeImpl<Config>::RangeType : public TypeImpl<Config> {
return Config::template cast<RangeType>(Config::from_range(range));
}
static RangeHandle New(Limits lim, Region* region) {
return New(lim.min, lim.max, BitsetType::New(lim.representation, region),
static RangeHandle New(Limits lim, bitset representation, Region* region) {
return New(lim.min, lim.max, BitsetType::New(representation, region),
region);
}
......@@ -866,7 +868,6 @@ class TypeImpl<Config>::RangeType : public TypeImpl<Config> {
}
};
// TODO(neis): Also cache min and max values.
// TODO(neis): Allow restricting the representation.
// -----------------------------------------------------------------------------
......
......@@ -88,7 +88,6 @@
'compiler/test-run-stackcheck.cc',
'compiler/test-run-variables.cc',
'compiler/test-simplified-lowering.cc',
'compiler/test-typer.cc',
'cctest.cc',
'gay-fixed.cc',
'gay-precision.cc',
......
......@@ -109,7 +109,8 @@ struct Tests : Rep {
: isolate(CcTest::i_isolate()),
scope(isolate),
zone(),
T(Rep::ToRegion(&zone, isolate), isolate) {}
T(Rep::ToRegion(&zone, isolate), isolate,
isolate->random_number_generator()) {}
bool Equal(TypeHandle type1, TypeHandle type2) {
return
......@@ -234,17 +235,85 @@ struct Tests : Rep {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
TypeHandle type1 = *it1;
TypeHandle type2 = *it2;
TypeHandle intersect12 = T.Intersect(type1, type2);
if (this->IsBitset(type1) && this->IsBitset(type2)) {
TypeHandle intersect12 = T.Intersect(type1, type2);
bitset bits = this->AsBitset(type1) & this->AsBitset(type2);
CHECK(
(Rep::BitsetType::IsInhabited(bits) ? bits : 0) ==
this->AsBitset(intersect12));
CHECK(bits == this->AsBitset(intersect12));
}
}
}
}
void PointwiseRepresentation() {
// Check we can decompose type into semantics and representation and
// then compose it back to get an equivalent type.
int counter = 0;
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
counter++;
printf("Counter: %i\n", counter);
fflush(stdout);
TypeHandle type1 = *it1;
TypeHandle representation = T.Representation(type1);
TypeHandle semantic = T.Semantic(type1);
TypeHandle composed = T.Union(representation, semantic);
CHECK(type1->Equals(composed));
}
// Pointwiseness of Union.
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
TypeHandle type1 = *it1;
TypeHandle type2 = *it2;
TypeHandle representation1 = T.Representation(type1);
TypeHandle semantic1 = T.Semantic(type1);
TypeHandle representation2 = T.Representation(type2);
TypeHandle semantic2 = T.Semantic(type2);
TypeHandle direct_union = T.Union(type1, type2);
TypeHandle representation_union =
T.Union(representation1, representation2);
TypeHandle semantic_union = T.Union(semantic1, semantic2);
TypeHandle composed_union =
T.Union(representation_union, semantic_union);
CHECK(direct_union->Equals(composed_union));
}
}
// Pointwiseness of Intersect.
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
TypeHandle type1 = *it1;
TypeHandle type2 = *it2;
TypeHandle representation1 = T.Representation(type1);
TypeHandle semantic1 = T.Semantic(type1);
TypeHandle representation2 = T.Representation(type2);
TypeHandle semantic2 = T.Semantic(type2);
TypeHandle direct_intersection = T.Intersect(type1, type2);
TypeHandle representation_intersection =
T.Intersect(representation1, representation2);
TypeHandle semantic_intersection = T.Intersect(semantic1, semantic2);
TypeHandle composed_intersection =
T.Union(representation_intersection, semantic_intersection);
CHECK(direct_intersection->Equals(composed_intersection));
}
}
// Pointwiseness of Is.
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
TypeHandle type1 = *it1;
TypeHandle type2 = *it2;
TypeHandle representation1 = T.Representation(type1);
TypeHandle semantic1 = T.Semantic(type1);
TypeHandle representation2 = T.Representation(type2);
TypeHandle semantic2 = T.Semantic(type2);
bool representation_is = representation1->Is(representation2);
bool semantic_is = semantic1->Is(semantic2);
bool direct_is = type1->Is(type2);
CHECK(direct_is == (semantic_is && representation_is));
}
}
}
void Class() {
// Constructor
for (MapIterator mt = T.maps.begin(); mt != T.maps.end(); ++mt) {
......@@ -657,11 +726,11 @@ struct Tests : Rep {
}
}
// Rangification: If T->Is(Range(-inf,+inf)) and !T->Is(None), then
// Rangification: If T->Is(Range(-inf,+inf)) and T is inhabited, then
// T->Is(Range(T->Min(), T->Max())).
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
TypeHandle type = *it;
CHECK(!(type->Is(T.Integer) && !type->Is(T.None)) ||
CHECK(!type->Is(T.Integer) || !type->IsInhabited() ||
type->Is(T.Range(type->Min(), type->Max())));
}
}
......@@ -801,7 +870,7 @@ struct Tests : Rep {
(type1->IsContext() && type2->IsContext()) ||
(type1->IsArray() && type2->IsArray()) ||
(type1->IsFunction() && type2->IsFunction()) ||
type1->Equals(T.None));
!type1->IsInhabited());
}
}
}
......@@ -1305,7 +1374,7 @@ struct Tests : Rep {
CheckDisjoint(T.SignedFunction1, T.MethodFunction);
CheckOverlap(T.ObjectConstant1, T.ObjectClass); // !!!
CheckOverlap(T.ObjectConstant2, T.ObjectClass); // !!!
CheckOverlap(T.NumberClass, T.Intersect(T.Number, T.Untagged)); // !!!
CheckOverlap(T.NumberClass, T.Intersect(T.Number, T.Tagged)); // !!!
}
void Union1() {
......@@ -1694,24 +1763,24 @@ struct Tests : Rep {
// Bitset-class
CheckEqual(T.Intersect(T.ObjectClass, T.Object), T.ObjectClass);
CheckEqual(T.Intersect(T.ObjectClass, T.Array), T.None);
CheckEqual(T.Intersect(T.ObjectClass, T.Number), T.None);
CheckEqual(T.Semantic(T.Intersect(T.ObjectClass, T.Array)), T.None);
CheckEqual(T.Semantic(T.Intersect(T.ObjectClass, T.Number)), T.None);
// Bitset-array
CheckEqual(T.Intersect(T.NumberArray, T.Object), T.NumberArray);
CheckEqual(T.Intersect(T.AnyArray, T.Proxy), T.None);
CheckEqual(T.Semantic(T.Intersect(T.AnyArray, T.Proxy)), T.None);
// Bitset-function
CheckEqual(T.Intersect(T.MethodFunction, T.Object), T.MethodFunction);
CheckEqual(T.Intersect(T.NumberFunction1, T.Proxy), T.None);
CheckEqual(T.Semantic(T.Intersect(T.NumberFunction1, T.Proxy)), T.None);
// Bitset-union
CheckEqual(
T.Intersect(T.Object, T.Union(T.ObjectConstant1, T.ObjectClass)),
T.Union(T.ObjectConstant1, T.ObjectClass));
CHECK(
!T.Intersect(T.Union(T.ArrayClass, T.ObjectConstant1), T.Number)
->IsInhabited());
CheckEqual(T.Semantic(T.Intersect(T.Union(T.ArrayClass, T.ObjectConstant1),
T.Number)),
T.None);
// Class-constant
CHECK(T.Intersect(T.ObjectConstant1, T.ObjectClass)->IsInhabited()); // !!!
......@@ -1867,8 +1936,9 @@ struct Tests : Rep {
template<class Type2, class TypeHandle2, class Region2, class Rep2>
void Convert() {
Types<Type2, TypeHandle2, Region2> T2(
Rep2::ToRegion(&zone, isolate), isolate);
Types<Type2, TypeHandle2, Region2> T2(Rep2::ToRegion(&zone, isolate),
isolate,
isolate->random_number_generator());
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
TypeHandle type1 = *it;
TypeHandle2 type2 = T2.template Convert<Type>(type1);
......@@ -1901,6 +1971,13 @@ TEST(IsSomeType) {
}
TEST(PointwiseRepresentation) {
CcTest::InitializeVM();
// ZoneTests().PointwiseRepresentation();
HeapTests().PointwiseRepresentation();
}
TEST(BitsetType) {
CcTest::InitializeVM();
ZoneTests().Bitset();
......
......@@ -28,6 +28,7 @@
#ifndef V8_TEST_CCTEST_TYPES_H_
#define V8_TEST_CCTEST_TYPES_H_
#include "src/base/utils/random-number-generator.h"
#include "src/v8.h"
namespace v8 {
......@@ -37,8 +38,8 @@ namespace internal {
template<class Type, class TypeHandle, class Region>
class Types {
public:
Types(Region* region, Isolate* isolate)
: region_(region), rng_(isolate->random_number_generator()) {
Types(Region* region, Isolate* isolate, v8::base::RandomNumberGenerator* rng)
: region_(region), rng_(rng) {
#define DECLARE_TYPE(name, value) \
name = Type::name(region); \
types.push_back(name);
......@@ -132,6 +133,10 @@ class Types {
#define DECLARE_TYPE(name, value) TypeHandle name;
PROPER_BITSET_TYPE_LIST(DECLARE_TYPE)
#undef DECLARE_TYPE
#define DECLARE_TYPE(name, value) TypeHandle Mask##name##ForTesting;
MASK_BITSET_TYPE_LIST(DECLARE_TYPE)
#undef DECLARE_TYPE
TypeHandle SignedSmall;
TypeHandle UnsignedSmall;
......@@ -212,10 +217,19 @@ class Types {
TypeHandle Union(TypeHandle t1, TypeHandle t2) {
return Type::Union(t1, t2, region_);
}
TypeHandle Intersect(TypeHandle t1, TypeHandle t2) {
return Type::Intersect(t1, t2, region_);
}
TypeHandle Representation(TypeHandle t) {
return Type::Representation(t, region_);
}
// TypeHandle Semantic(TypeHandle t) { return Intersect(t,
// MaskSemanticForTesting); }
TypeHandle Semantic(TypeHandle t) { return Type::Semantic(t, region_); }
template<class Type2, class TypeHandle2>
TypeHandle Convert(TypeHandle2 t) {
return Type::template Convert<Type2>(t, region_);
......
......@@ -73,6 +73,7 @@
'compiler/scheduler-unittest.cc',
'compiler/simplified-operator-reducer-unittest.cc',
'compiler/simplified-operator-unittest.cc',
'compiler/typer-unittest.cc',
'compiler/value-numbering-reducer-unittest.cc',
'compiler/zone-pool-unittest.cc',
'libplatform/default-platform-unittest.cc',
......
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