Commit 2764fd8d authored by rossberg's avatar rossberg Committed by Commit bot

Steps towards unification of number bitset and range types.

- New invariant on union types: if the union has a range then the number
  bits in the bitset must be cleared.

- Various tweaks in intersection and union to satisfy the invariant.

- Exposed and used representation bits in range types (and the Limits
  helper class).

- Implemented Glb for ranges so that the Is predicate handles
  ranges correctly.

- Change typer weakening so that it does not rely on GetRange.
  However, the code still seems to be a bit fragile.

- Removed the Smi types from the type system core, instead introduced
  Signed31, Unsigned30 and created constructors for Small(Un)Signed
  that point to the right type for the architecture.

- Punched a hole in the config to be able to get to the isolate so
  that it is possible to allocate heap numbers for newly created
  ranges.

Patch by jarin@chromium.prg, original review here:
https://codereview.chromium.org/795713003/

TBR=jarin@chromium.org
BUG=

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

Cr-Commit-Position: refs/heads/master@{#26197}
parent 78ae35c0
......@@ -163,7 +163,7 @@ Reduction ChangeLowering::ChangeInt32ToTagged(Node* value, Node* control) {
machine()->Word64Shl(),
graph()->NewNode(machine()->ChangeInt32ToInt64(), value),
SmiShiftBitsConstant()));
} else if (NodeProperties::GetBounds(value).upper->Is(Type::SignedSmall())) {
} else if (NodeProperties::GetBounds(value).upper->Is(Type::Signed31())) {
return Replace(
graph()->NewNode(machine()->WordShl(), value, SmiShiftBitsConstant()));
}
......
......@@ -888,12 +888,12 @@ Type* Typer::Visitor::JSBitwiseXorTyper(Type* lhs, Type* rhs, Typer* t) {
double rmax = rhs->Max();
if ((lmin >= 0 && rmin >= 0) || (lmax < 0 && rmax < 0)) {
// Xor-ing negative or non-negative values results in a non-negative value.
return Type::NonNegativeSigned32();
return Type::Unsigned31();
}
if ((lmax < 0 && rmin >= 0) || (lmin >= 0 && rmax < 0)) {
// Xor-ing a negative and a non-negative value results in a negative value.
// TODO(jarin) Use a range here.
return Type::NegativeSigned32();
return Type::Negative32();
}
return Type::Signed32();
}
......@@ -1258,43 +1258,54 @@ Bounds Typer::Visitor::TypeJSLoadNamed(Node* node) {
// in the graph. In the current implementation, we are
// increasing the limits to the closest power of two.
Type* Typer::Visitor::Weaken(Type* current_type, Type* previous_type) {
Type::RangeType* previous = previous_type->GetRange();
Type::RangeType* current = current_type->GetRange();
if (previous != NULL && current != NULL) {
double current_min = current->Min()->Number();
Handle<Object> new_min = current->Min();
// Find the closest lower entry in the list of allowed
// minima (or negative infinity if there is no such entry).
if (current_min != previous->Min()->Number()) {
new_min = typer_->integer->AsRange()->Min();
for (const auto val : typer_->weaken_min_limits_) {
if (val->Number() <= current_min) {
new_min = val;
break;
}
// If the types have nothing to do with integers, return the types.
if (!current_type->Maybe(typer_->integer) ||
!previous_type->Maybe(typer_->integer)) {
return current_type;
}
Type* previous_number =
Type::Intersect(previous_type, typer_->integer, zone());
Type* current_number = Type::Intersect(current_type, typer_->integer, zone());
if (!current_number->IsRange() || !previous_number->IsRange()) {
return current_type;
}
Type::RangeType* previous = previous_number->AsRange();
Type::RangeType* current = current_number->AsRange();
double current_min = current->Min()->Number();
Handle<Object> new_min = current->Min();
// Find the closest lower entry in the list of allowed
// minima (or negative infinity if there is no such entry).
if (current_min != previous->Min()->Number()) {
new_min = typer_->integer->AsRange()->Min();
for (const auto val : typer_->weaken_min_limits_) {
if (val->Number() <= current_min) {
new_min = val;
break;
}
}
}
double current_max = current->Max()->Number();
Handle<Object> new_max = current->Max();
// Find the closest greater entry in the list of allowed
// maxima (or infinity if there is no such entry).
if (current_max != previous->Max()->Number()) {
new_max = typer_->integer->AsRange()->Max();
for (const auto val : typer_->weaken_max_limits_) {
if (val->Number() >= current_max) {
new_max = val;
break;
}
double current_max = current->Max()->Number();
Handle<Object> new_max = current->Max();
// Find the closest greater entry in the list of allowed
// maxima (or infinity if there is no such entry).
if (current_max != previous->Max()->Number()) {
new_max = typer_->integer->AsRange()->Max();
for (const auto val : typer_->weaken_max_limits_) {
if (val->Number() >= current_max) {
new_max = val;
break;
}
}
return Type::Union(current_type,
Type::Range(new_min, new_max, typer_->zone()),
typer_->zone());
}
return current_type;
return Type::Union(current_type,
Type::Range(new_min, new_max, typer_->zone()),
typer_->zone());
}
......
......@@ -16,6 +16,20 @@ namespace internal {
// -----------------------------------------------------------------------------
// TypeImpl
template <class Config>
typename TypeImpl<Config>::bitset
TypeImpl<Config>::BitsetType::SignedSmall() {
return i::SmiValuesAre31Bits() ? kSigned31 : kSigned32;
}
template <class Config>
typename TypeImpl<Config>::bitset
TypeImpl<Config>::BitsetType::UnsignedSmall() {
return i::SmiValuesAre31Bits() ? kUnsigned30 : kUnsigned31;
}
template<class Config>
TypeImpl<Config>* TypeImpl<Config>::cast(typename Config::Base* object) {
TypeImpl* t = static_cast<TypeImpl*>(object);
......@@ -201,6 +215,9 @@ void ZoneTypeConfig::struct_set_value(
}
// static
i::Isolate* ZoneTypeConfig::isolate(Zone* zone) { return zone->isolate(); }
// -----------------------------------------------------------------------------
// HeapTypeConfig
......@@ -348,6 +365,8 @@ void HeapTypeConfig::struct_set_value(
structure->set(i + 1, *x);
}
// static
i::Isolate* HeapTypeConfig::isolate(Isolate* isolate) { return isolate; }
} } // namespace v8::internal
#endif // V8_TYPES_INL_H_
This diff is collapsed.
This diff is collapsed.
......@@ -176,20 +176,17 @@ static Type* kStringTypes[] = {Type::InternalizedString(), Type::OtherString(),
Type::String()};
static Type* kInt32Types[] = {
Type::UnsignedSmall(), Type::NegativeSigned32(),
Type::NonNegativeSigned32(), Type::SignedSmall(),
Type::Signed32(), Type::Unsigned32(),
Type::Integral32()};
static Type* kInt32Types[] = {Type::UnsignedSmall(), Type::Negative32(),
Type::Unsigned31(), Type::SignedSmall(),
Type::Signed32(), Type::Unsigned32(),
Type::Integral32()};
static Type* kNumberTypes[] = {
Type::UnsignedSmall(), Type::NegativeSigned32(),
Type::NonNegativeSigned32(), Type::SignedSmall(),
Type::Signed32(), Type::Unsigned32(),
Type::Integral32(), Type::MinusZero(),
Type::NaN(), Type::OrderedNumber(),
Type::PlainNumber(), Type::Number()};
Type::UnsignedSmall(), Type::Negative32(), Type::Unsigned31(),
Type::SignedSmall(), Type::Signed32(), Type::Unsigned32(),
Type::Integral32(), Type::MinusZero(), Type::NaN(),
Type::OrderedNumber(), Type::PlainNumber(), Type::Number()};
static Type* kJSTypes[] = {Type::Undefined(), Type::Null(), Type::Boolean(),
......@@ -316,13 +313,12 @@ class JSBitwiseShiftTypedLoweringTester : public JSTypedLoweringTester {
TEST(Int32BitwiseShifts) {
JSBitwiseShiftTypedLoweringTester R;
Type* types[] = {Type::SignedSmall(), Type::UnsignedSmall(),
Type::NegativeSigned32(), Type::NonNegativeSigned32(),
Type::Unsigned32(), Type::Signed32(),
Type::MinusZero(), Type::NaN(),
Type::Undefined(), Type::Null(),
Type::Boolean(), Type::Number(),
Type::PlainNumber(), Type::String()};
Type* types[] = {
Type::SignedSmall(), Type::UnsignedSmall(), Type::Negative32(),
Type::Unsigned31(), Type::Unsigned32(), Type::Signed32(),
Type::MinusZero(), Type::NaN(), Type::Undefined(),
Type::Null(), Type::Boolean(), Type::Number(),
Type::PlainNumber(), Type::String()};
for (size_t i = 0; i < arraysize(types); ++i) {
Node* p0 = R.Parameter(types[i], 0);
......
......@@ -136,6 +136,14 @@ struct Tests : Rep {
}
}
void CheckSubOrEqual(TypeHandle type1, TypeHandle type2) {
CHECK(type1->Is(type2));
if (this->IsBitset(type1) && this->IsBitset(type2)) {
CHECK((this->AsBitset(type1) | this->AsBitset(type2))
== this->AsBitset(type2));
}
}
void CheckUnordered(TypeHandle type1, TypeHandle type2) {
CHECK(!type1->Is(type2));
CHECK(!type2->Is(type1));
......@@ -294,39 +302,33 @@ struct Tests : Rep {
CHECK(T.Constant(fac->NewNumber(0))->Is(T.UnsignedSmall));
CHECK(T.Constant(fac->NewNumber(1))->Is(T.UnsignedSmall));
CHECK(T.Constant(fac->NewNumber(0x3fffffff))->Is(T.UnsignedSmall));
CHECK(T.Constant(fac->NewNumber(-1))->Is(T.NegativeSignedSmall));
CHECK(T.Constant(fac->NewNumber(-0x3fffffff))->Is(T.NegativeSignedSmall));
CHECK(T.Constant(fac->NewNumber(-0x40000000))->Is(T.NegativeSignedSmall));
CHECK(T.Constant(fac->NewNumber(-1))->Is(T.Negative31));
CHECK(T.Constant(fac->NewNumber(-0x3fffffff))->Is(T.Negative31));
CHECK(T.Constant(fac->NewNumber(-0x40000000))->Is(T.Negative31));
CHECK(T.Constant(fac->NewNumber(0x40000000))->Is(T.Unsigned31));
CHECK(!T.Constant(fac->NewNumber(0x40000000))->Is(T.Unsigned30));
CHECK(T.Constant(fac->NewNumber(0x7fffffff))->Is(T.Unsigned31));
CHECK(!T.Constant(fac->NewNumber(0x7fffffff))->Is(T.Unsigned30));
CHECK(T.Constant(fac->NewNumber(-0x40000001))->Is(T.Negative32));
CHECK(!T.Constant(fac->NewNumber(-0x40000001))->Is(T.Negative31));
CHECK(T.Constant(fac->NewNumber(-0x7fffffff))->Is(T.Negative32));
CHECK(!T.Constant(fac->NewNumber(-0x7fffffff - 1))->Is(T.Negative31));
if (SmiValuesAre31Bits()) {
CHECK(T.Constant(fac->NewNumber(0x40000000))->Is(T.NonNegativeSigned32));
CHECK(!T.Constant(fac->NewNumber(0x40000000))->Is(T.UnsignedSmall));
CHECK(T.Constant(fac->NewNumber(0x7fffffff))->Is(T.NonNegativeSigned32));
CHECK(!T.Constant(fac->NewNumber(0x7fffffff))->Is(T.UnsignedSmall));
CHECK(T.Constant(fac->NewNumber(-0x40000001))->Is(T.NegativeSigned32));
CHECK(
!T.Constant(fac->NewNumber(-0x40000001))->Is(T.NegativeSignedSmall));
CHECK(T.Constant(fac->NewNumber(-0x7fffffff))->Is(T.NegativeSigned32));
CHECK(!T.Constant(fac->NewNumber(-0x7fffffff - 1))
->Is(T.NegativeSignedSmall));
CHECK(!T.Constant(fac->NewNumber(-0x40000001))->Is(T.SignedSmall));
CHECK(!T.Constant(fac->NewNumber(-0x7fffffff - 1))->Is(T.SignedSmall));
} else {
CHECK(SmiValuesAre32Bits());
CHECK(T.Constant(fac->NewNumber(0x40000000))->Is(T.UnsignedSmall));
CHECK(T.Constant(fac->NewNumber(0x7fffffff))->Is(T.UnsignedSmall));
CHECK(T.Constant(fac->NewNumber(0x40000000))->Is(T.NonNegativeSigned32));
CHECK(T.Constant(fac->NewNumber(0x7fffffff))->Is(T.NonNegativeSigned32));
CHECK(T.Constant(fac->NewNumber(-0x40000001))->Is(T.NegativeSignedSmall));
CHECK(T.Constant(fac->NewNumber(-0x7fffffff))->Is(T.NegativeSignedSmall));
CHECK(T.Constant(fac->NewNumber(-0x7fffffff - 1))
->Is(T.NegativeSignedSmall));
CHECK(T.Constant(fac->NewNumber(-0x40000001))->Is(T.NegativeSigned32));
CHECK(T.Constant(fac->NewNumber(-0x7fffffff))->Is(T.NegativeSigned32));
CHECK(
T.Constant(fac->NewNumber(-0x7fffffff - 1))->Is(T.NegativeSigned32));
CHECK(T.Constant(fac->NewNumber(-0x40000001))->Is(T.SignedSmall));
CHECK(T.Constant(fac->NewNumber(-0x7fffffff - 1))->Is(T.SignedSmall));
}
CHECK(T.Constant(fac->NewNumber(0x80000000u))->Is(T.Unsigned32));
CHECK(!T.Constant(fac->NewNumber(0x80000000u))->Is(T.NonNegativeSigned32));
CHECK(!T.Constant(fac->NewNumber(0x80000000u))->Is(T.Unsigned31));
CHECK(T.Constant(fac->NewNumber(0xffffffffu))->Is(T.Unsigned32));
CHECK(!T.Constant(fac->NewNumber(0xffffffffu))->Is(T.NonNegativeSigned32));
CHECK(!T.Constant(fac->NewNumber(0xffffffffu))->Is(T.Unsigned31));
CHECK(T.Constant(fac->NewNumber(0xffffffffu + 1.0))->Is(T.PlainNumber));
CHECK(!T.Constant(fac->NewNumber(0xffffffffu + 1.0))->Is(T.Integral32));
CHECK(T.Constant(fac->NewNumber(-0x7fffffff - 2.0))->Is(T.PlainNumber));
......@@ -796,6 +798,7 @@ struct Tests : Rep {
(type1->IsClass() && type2->IsClass()) ||
(type1->IsConstant() && type2->IsConstant()) ||
(type1->IsConstant() && type2->IsRange()) ||
(this->IsBitset(type1) && type2->IsRange()) ||
(type1->IsRange() && type2->IsRange()) ||
(type1->IsContext() && type2->IsContext()) ||
(type1->IsArray() && type2->IsArray()) ||
......@@ -934,7 +937,7 @@ struct Tests : Rep {
CheckSub(T.SignedSmall, T.Number);
CheckSub(T.Signed32, T.Number);
CheckSub(T.SignedSmall, T.Signed32);
CheckSubOrEqual(T.SignedSmall, T.Signed32);
CheckUnordered(T.SignedSmall, T.MinusZero);
CheckUnordered(T.Signed32, T.Unsigned32);
......@@ -1478,8 +1481,8 @@ struct Tests : Rep {
CheckDisjoint(T.Union(T.NumberFunction1, T.String), T.Number);
// Bitset-class
CheckSub(
T.Union(T.ObjectClass, T.SignedSmall), T.Union(T.Object, T.Number));
CheckSub(T.Union(T.ObjectClass, T.SignedSmall),
T.Union(T.Object, T.Number));
CheckSub(T.Union(T.ObjectClass, T.Array), T.Object);
CheckUnordered(T.Union(T.ObjectClass, T.String), T.Array);
CheckOverlap(T.Union(T.ObjectClass, T.String), T.Object);
......@@ -1549,11 +1552,9 @@ struct Tests : Rep {
T.Union(T.ObjectConstant2, T.ObjectConstant1),
T.Union(T.ObjectConstant1, T.ObjectConstant2)),
T.Union(T.ObjectConstant2, T.ObjectConstant1));
CheckEqual(
T.Union(
T.Union(T.Number, T.ArrayClass),
T.Union(T.SignedSmall, T.Array)),
T.Union(T.Number, T.Array));
CheckEqual(T.Union(T.Union(T.Number, T.ArrayClass),
T.Union(T.SignedSmall, T.Array)),
T.Union(T.Number, T.Array));
}
void Intersect() {
......@@ -1767,11 +1768,9 @@ struct Tests : Rep {
->IsInhabited()); // !!!
// Union-union
CheckEqual(
T.Intersect(
T.Union(T.Number, T.ArrayClass),
T.Union(T.SignedSmall, T.Array)),
T.Union(T.SignedSmall, T.ArrayClass));
CheckEqual(T.Intersect(T.Union(T.Number, T.ArrayClass),
T.Union(T.SignedSmall, T.Array)),
T.Union(T.SignedSmall, T.ArrayClass));
CheckEqual(
T.Intersect(
T.Union(T.Number, T.ObjectClass),
......
......@@ -45,6 +45,9 @@ class Types {
PROPER_BITSET_TYPE_LIST(DECLARE_TYPE)
#undef DECLARE_TYPE
SignedSmall = Type::SignedSmall(region);
UnsignedSmall = Type::UnsignedSmall(region);
object_map = isolate->factory()->NewMap(
JS_OBJECT_TYPE, JSObject::kHeaderSize);
array_map = isolate->factory()->NewMap(
......@@ -130,6 +133,8 @@ class Types {
#define DECLARE_TYPE(name, value) TypeHandle name;
PROPER_BITSET_TYPE_LIST(DECLARE_TYPE)
#undef DECLARE_TYPE
TypeHandle SignedSmall;
TypeHandle UnsignedSmall;
TypeHandle ObjectClass;
TypeHandle ArrayClass;
......
......@@ -211,7 +211,7 @@ TARGET_TEST_F(ChangeLowering32Test, ChangeInt32ToTagged) {
TARGET_TEST_F(ChangeLowering32Test, ChangeInt32ToTaggedSmall) {
Node* val = Parameter(0);
Node* node = graph()->NewNode(simplified()->ChangeInt32ToTagged(), val);
NodeProperties::SetBounds(val, Bounds(Type::None(), Type::SignedSmall()));
NodeProperties::SetBounds(val, Bounds(Type::None(), Type::Signed31()));
Reduction reduction = Reduce(node);
ASSERT_TRUE(reduction.Changed());
......
......@@ -53,12 +53,10 @@ namespace {
// TODO(mstarzinger): Find a common place and unify with test-js-typed-lowering.
Type* const kNumberTypes[] = {
Type::UnsignedSmall(), Type::NegativeSigned32(),
Type::NonNegativeSigned32(), Type::SignedSmall(),
Type::Signed32(), Type::Unsigned32(),
Type::Integral32(), Type::MinusZero(),
Type::NaN(), Type::OrderedNumber(),
Type::PlainNumber(), Type::Number()};
Type::UnsignedSmall(), Type::Negative32(), Type::Unsigned31(),
Type::SignedSmall(), Type::Signed32(), Type::Unsigned32(),
Type::Integral32(), Type::MinusZero(), Type::NaN(),
Type::OrderedNumber(), Type::PlainNumber(), Type::Number()};
} // namespace
......
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