[Turbofan] Introduce OtherNumberConstant.

With this CL, we devolve all Constants introduced as they are with an object handle into

* Range - for integers
* Nan
* MinusZero
* OtherNumberConstant - for doubles
* HeapConstant

We reduce the amount we have to inspect an object handle during optimization. Also, simplifications result. For example, you never have to check if a Range contains a HeapConstant.

BUG=

Review-Url: https://codereview.chromium.org/2381523002
Cr-Commit-Position: refs/heads/master@{#40041}
This commit is contained in:
mvstanton 2016-10-06 07:13:34 -07:00 committed by Commit bot
parent 1f89d369fc
commit 978fe70beb
15 changed files with 365 additions and 260 deletions

View File

@ -330,9 +330,9 @@ bool HasInstanceTypeWitness(Node* receiver, Node* effect,
for (int i = 1; i < dominator->op()->ValueInputCount(); ++i) {
Node* const map = NodeProperties::GetValueInput(dominator, i);
Type* const map_type = NodeProperties::GetType(map);
if (!map_type->IsConstant()) return false;
if (!map_type->IsHeapConstant()) return false;
Handle<Map> const map_value =
Handle<Map>::cast(map_type->AsConstant()->Value());
Handle<Map>::cast(map_type->AsHeapConstant()->Value());
if (map_value->instance_type() != instance_type) return false;
}
return true;

View File

@ -231,13 +231,12 @@ Reduction JSCreateLowering::ReduceJSCreate(Node* node) {
Type* const new_target_type = NodeProperties::GetType(new_target);
Node* const effect = NodeProperties::GetEffectInput(node);
// Extract constructor and original constructor function.
if (target_type->IsConstant() &&
new_target_type->IsConstant() &&
new_target_type->AsConstant()->Value()->IsJSFunction()) {
if (target_type->IsHeapConstant() && new_target_type->IsHeapConstant() &&
new_target_type->AsHeapConstant()->Value()->IsJSFunction()) {
Handle<JSFunction> constructor =
Handle<JSFunction>::cast(target_type->AsConstant()->Value());
Handle<JSFunction>::cast(target_type->AsHeapConstant()->Value());
Handle<JSFunction> original_constructor =
Handle<JSFunction>::cast(new_target_type->AsConstant()->Value());
Handle<JSFunction>::cast(new_target_type->AsHeapConstant()->Value());
DCHECK(constructor->IsConstructor());
DCHECK(original_constructor->IsConstructor());

View File

@ -82,16 +82,16 @@ class JSBinopReduction final {
if (BothInputsAre(Type::String()) ||
((lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) &&
BinaryOperationHintOf(node_->op()) == BinaryOperationHint::kString)) {
if (left_type()->IsConstant() &&
left_type()->AsConstant()->Value()->IsString()) {
if (left_type()->IsHeapConstant() &&
left_type()->AsHeapConstant()->Value()->IsString()) {
Handle<String> left_string =
Handle<String>::cast(left_type()->AsConstant()->Value());
Handle<String>::cast(left_type()->AsHeapConstant()->Value());
if (left_string->length() >= ConsString::kMinLength) return true;
}
if (right_type()->IsConstant() &&
right_type()->AsConstant()->Value()->IsString()) {
if (right_type()->IsHeapConstant() &&
right_type()->AsHeapConstant()->Value()->IsString()) {
Handle<String> right_string =
Handle<String>::cast(right_type()->AsConstant()->Value());
Handle<String>::cast(right_type()->AsHeapConstant()->Value());
if (right_string->length() >= ConsString::kMinLength) return true;
}
}
@ -447,7 +447,6 @@ class JSBinopReduction final {
// - immediately put in type bounds for all new nodes
// - relax effects from generic but not-side-effecting operations
JSTypedLowering::JSTypedLowering(Editor* editor,
CompilationDependencies* dependencies,
Flags flags, JSGraph* jsgraph, Zone* zone)
@ -456,7 +455,7 @@ JSTypedLowering::JSTypedLowering(Editor* editor,
flags_(flags),
jsgraph_(jsgraph),
the_hole_type_(
Type::Constant(factory()->the_hole_value(), graph()->zone())),
Type::HeapConstant(factory()->the_hole_value(), graph()->zone())),
type_cache_(TypeCache::Get()) {
for (size_t k = 0; k < arraysize(shifted_int32_ranges_); ++k) {
double min = kMinInt / (1 << k);
@ -598,9 +597,9 @@ Reduction JSTypedLowering::ReduceCreateConsString(Node* node) {
// Determine the {first} length.
Node* first_length =
first_type->IsConstant()
first_type->IsHeapConstant()
? jsgraph()->Constant(
Handle<String>::cast(first_type->AsConstant()->Value())
Handle<String>::cast(first_type->AsHeapConstant()->Value())
->length())
: effect = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForStringLength()),
@ -608,9 +607,9 @@ Reduction JSTypedLowering::ReduceCreateConsString(Node* node) {
// Determine the {second} length.
Node* second_length =
second_type->IsConstant()
second_type->IsHeapConstant()
? jsgraph()->Constant(
Handle<String>::cast(second_type->AsConstant()->Value())
Handle<String>::cast(second_type->AsHeapConstant()->Value())
->length())
: effect = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForStringLength()),
@ -980,8 +979,8 @@ Reduction JSTypedLowering::ReduceJSToLength(Node* node) {
Reduction JSTypedLowering::ReduceJSToNumberInput(Node* input) {
// Try constant-folding of JSToNumber with constant inputs.
Type* input_type = NodeProperties::GetType(input);
if (input_type->IsConstant()) {
Handle<Object> input_value = input_type->AsConstant()->Value();
if (input_type->IsHeapConstant()) {
Handle<Object> input_value = input_type->AsHeapConstant()->Value();
if (input_value->IsString()) {
return Replace(jsgraph()->Constant(
String::ToNumber(Handle<String>::cast(input_value))));
@ -1280,13 +1279,13 @@ Reduction JSTypedLowering::ReduceJSInstanceOf(Node* node) {
Node* effect = r.effect();
Node* control = r.control();
if (!r.right_type()->IsConstant() ||
!r.right_type()->AsConstant()->Value()->IsJSFunction()) {
if (!r.right_type()->IsHeapConstant() ||
!r.right_type()->AsHeapConstant()->Value()->IsJSFunction()) {
return NoChange();
}
Handle<JSFunction> function =
Handle<JSFunction>::cast(r.right_type()->AsConstant()->Value());
Handle<JSFunction>::cast(r.right_type()->AsHeapConstant()->Value());
Handle<SharedFunctionInfo> shared(function->shared(), isolate());
// Make sure the prototype of {function} is the %FunctionPrototype%, and it
@ -1485,9 +1484,9 @@ Reduction JSTypedLowering::ReduceJSConvertReceiver(Node* node) {
// with the global proxy unconditionally.
if (receiver_type->Is(Type::NullOrUndefined()) ||
mode == ConvertReceiverMode::kNullOrUndefined) {
if (context_type->IsConstant()) {
if (context_type->IsHeapConstant()) {
Handle<JSObject> global_proxy(
Handle<Context>::cast(context_type->AsConstant()->Value())
Handle<Context>::cast(context_type->AsHeapConstant()->Value())
->global_proxy(),
isolate());
receiver = jsgraph()->Constant(global_proxy);
@ -1590,9 +1589,9 @@ Reduction JSTypedLowering::ReduceJSConvertReceiver(Node* node) {
Node* eglobal = effect;
Node* rglobal;
{
if (context_type->IsConstant()) {
if (context_type->IsHeapConstant()) {
Handle<JSObject> global_proxy(
Handle<Context>::cast(context_type->AsConstant()->Value())
Handle<Context>::cast(context_type->AsHeapConstant()->Value())
->global_proxy(),
isolate());
rglobal = jsgraph()->Constant(global_proxy);
@ -1715,10 +1714,10 @@ Reduction JSTypedLowering::ReduceJSCallConstruct(Node* node) {
Node* control = NodeProperties::GetControlInput(node);
// Check if {target} is a known JSFunction.
if (target_type->IsConstant() &&
target_type->AsConstant()->Value()->IsJSFunction()) {
if (target_type->IsHeapConstant() &&
target_type->AsHeapConstant()->Value()->IsJSFunction()) {
Handle<JSFunction> function =
Handle<JSFunction>::cast(target_type->AsConstant()->Value());
Handle<JSFunction>::cast(target_type->AsHeapConstant()->Value());
Handle<SharedFunctionInfo> shared(function->shared(), isolate());
const int builtin_index = shared->construct_stub()->builtin_index();
const bool is_builtin = (builtin_index != -1);
@ -1800,10 +1799,10 @@ Reduction JSTypedLowering::ReduceJSCallFunction(Node* node) {
}
// Check if {target} is a known JSFunction.
if (target_type->IsConstant() &&
target_type->AsConstant()->Value()->IsJSFunction()) {
if (target_type->IsHeapConstant() &&
target_type->AsHeapConstant()->Value()->IsJSFunction()) {
Handle<JSFunction> function =
Handle<JSFunction>::cast(target_type->AsConstant()->Value());
Handle<JSFunction>::cast(target_type->AsHeapConstant()->Value());
Handle<SharedFunctionInfo> shared(function->shared(), isolate());
const int builtin_index = shared->code()->builtin_index();
const bool is_builtin = (builtin_index != -1);

View File

@ -19,14 +19,14 @@ namespace compiler {
OperationTyper::OperationTyper(Isolate* isolate, Zone* zone)
: zone_(zone), cache_(TypeCache::Get()) {
Factory* factory = isolate->factory();
infinity_ = Type::Constant(factory->infinity_value(), zone);
minus_infinity_ = Type::Constant(factory->minus_infinity_value(), zone);
infinity_ = Type::NewConstant(factory->infinity_value(), zone);
minus_infinity_ = Type::NewConstant(factory->minus_infinity_value(), zone);
Type* truncating_to_zero = Type::MinusZeroOrNaN();
DCHECK(!truncating_to_zero->Maybe(Type::Integral32()));
singleton_false_ = Type::Constant(factory->false_value(), zone);
singleton_true_ = Type::Constant(factory->true_value(), zone);
singleton_the_hole_ = Type::Constant(factory->the_hole_value(), zone);
singleton_false_ = Type::HeapConstant(factory->false_value(), zone);
singleton_true_ = Type::HeapConstant(factory->true_value(), zone);
singleton_the_hole_ = Type::HeapConstant(factory->the_hole_value(), zone);
signed32ish_ = Type::Union(Type::Signed32(), truncating_to_zero, zone);
unsigned32ish_ = Type::Union(Type::Unsigned32(), truncating_to_zero, zone);
}

View File

@ -1031,10 +1031,10 @@ class RepresentationSelector {
// undefined, because these special oddballs are always in the root set.
return kNoWriteBarrier;
}
if (value_type->IsConstant() &&
value_type->AsConstant()->Value()->IsHeapObject()) {
if (value_type->IsHeapConstant() &&
value_type->AsHeapConstant()->Value()->IsHeapObject()) {
Handle<HeapObject> value_object =
Handle<HeapObject>::cast(value_type->AsConstant()->Value());
Handle<HeapObject>::cast(value_type->AsHeapConstant()->Value());
RootIndexMap root_index_map(jsgraph_->isolate());
int root_index = root_index_map.Lookup(*value_object);
if (root_index != RootIndexMap::kInvalidRootIndex &&

View File

@ -22,8 +22,9 @@ TypedOptimization::TypedOptimization(Editor* editor,
dependencies_(dependencies),
flags_(flags),
jsgraph_(jsgraph),
true_type_(Type::Constant(factory()->true_value(), graph()->zone())),
false_type_(Type::Constant(factory()->false_value(), graph()->zone())),
true_type_(Type::HeapConstant(factory()->true_value(), graph()->zone())),
false_type_(
Type::HeapConstant(factory()->false_value(), graph()->zone())),
type_cache_(TypeCache::Get()) {}
TypedOptimization::~TypedOptimization() {}
@ -43,8 +44,9 @@ Reduction TypedOptimization::Reduce(Node* node) {
// the Operator::kNoDeopt property).
Type* upper = NodeProperties::GetType(node);
if (upper->IsInhabited()) {
if (upper->IsConstant()) {
Node* replacement = jsgraph()->Constant(upper->AsConstant()->Value());
if (upper->IsHeapConstant()) {
Node* replacement =
jsgraph()->Constant(upper->AsHeapConstant()->Value());
ReplaceWithValue(node, replacement);
return Changed(replacement);
} else if (upper->Is(Type::MinusZero())) {
@ -96,10 +98,11 @@ Reduction TypedOptimization::Reduce(Node* node) {
namespace {
MaybeHandle<Map> GetStableMapFromObjectType(Type* object_type) {
if (object_type->IsConstant() &&
object_type->AsConstant()->Value()->IsHeapObject()) {
if (object_type->IsHeapConstant() &&
object_type->AsHeapConstant()->Value()->IsHeapObject()) {
Handle<Map> object_map(
Handle<HeapObject>::cast(object_type->AsConstant()->Value())->map());
Handle<HeapObject>::cast(object_type->AsHeapConstant()->Value())
->map());
if (object_map->is_stable()) return object_map;
}
return MaybeHandle<Map>();
@ -121,8 +124,8 @@ Reduction TypedOptimization::ReduceCheckMaps(Node* node) {
for (int i = 1; i < node->op()->ValueInputCount(); ++i) {
Node* const map = NodeProperties::GetValueInput(node, i);
Type* const map_type = NodeProperties::GetType(map);
if (map_type->IsConstant() &&
map_type->AsConstant()->Value().is_identical_to(object_map)) {
if (map_type->IsHeapConstant() &&
map_type->AsHeapConstant()->Value().is_identical_to(object_map)) {
if (object_map->CanTransition()) {
dependencies()->AssumeMapStable(object_map);
}

View File

@ -41,9 +41,9 @@ Typer::Typer(Isolate* isolate, Graph* graph)
Zone* zone = this->zone();
Factory* const factory = isolate->factory();
singleton_false_ = Type::Constant(factory->false_value(), zone);
singleton_true_ = Type::Constant(factory->true_value(), zone);
singleton_the_hole_ = Type::Constant(factory->the_hole_value(), zone);
singleton_false_ = Type::HeapConstant(factory->false_value(), zone);
singleton_true_ = Type::HeapConstant(factory->true_value(), zone);
singleton_the_hole_ = Type::HeapConstant(factory->the_hole_value(), zone);
falsish_ = Type::Union(
Type::Undetectable(),
Type::Union(Type::Union(singleton_false_, cache_.kZeroish, zone),
@ -604,15 +604,10 @@ Type* Typer::Visitor::TypeFloat64Constant(Node* node) {
Type* Typer::Visitor::TypeNumberConstant(Node* node) {
Factory* f = isolate()->factory();
double number = OpParameter<double>(node);
if (Type::IsInteger(number)) {
return Type::Range(number, number, zone());
}
return Type::Constant(f->NewNumber(number), zone());
return Type::NewConstant(number, zone());
}
Type* Typer::Visitor::TypeHeapConstant(Node* node) {
return TypeConstant(OpParameter<Handle<HeapObject>>(node));
}
@ -836,7 +831,7 @@ Type* Typer::Visitor::JSEqualTyper(Type* lhs, Type* rhs, Typer* t) {
(lhs->Max() < rhs->Min() || lhs->Min() > rhs->Max())) {
return t->singleton_false_;
}
if (lhs->IsConstant() && rhs->Is(lhs)) {
if (lhs->IsHeapConstant() && rhs->Is(lhs)) {
// Types are equal and are inhabited only by a single semantic value,
// which is not nan due to the earlier check.
return t->singleton_true_;
@ -873,7 +868,7 @@ Type* Typer::Visitor::JSStrictEqualTyper(Type* lhs, Type* rhs, Typer* t) {
!lhs->Maybe(rhs)) {
return t->singleton_false_;
}
if (lhs->IsConstant() && rhs->Is(lhs)) {
if (lhs->IsHeapConstant() && rhs->Is(lhs)) {
// Types are equal and are inhabited only by a single semantic value,
// which is not nan due to the earlier check.
return t->singleton_true_;
@ -907,7 +902,7 @@ Typer::Visitor::ComparisonOutcome Typer::Visitor::JSCompareTyper(Type* lhs,
if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return kComparisonUndefined;
ComparisonOutcome result;
if (lhs->IsConstant() && rhs->Is(lhs)) {
if (lhs->IsHeapConstant() && rhs->Is(lhs)) {
// Types are equal and are inhabited only by a single semantic value.
result = kComparisonFalse;
} else if (lhs->Min() >= rhs->Max()) {
@ -1021,23 +1016,26 @@ Type* Typer::Visitor::JSModulusTyper(Type* lhs, Type* rhs, Typer* t) {
Type* Typer::Visitor::JSTypeOfTyper(Type* type, Typer* t) {
Factory* const f = t->isolate()->factory();
if (type->Is(Type::Boolean())) {
return Type::Constant(f->boolean_string(), t->zone());
return Type::HeapConstant(f->boolean_string(), t->zone());
} else if (type->Is(Type::Number())) {
return Type::Constant(f->number_string(), t->zone());
return Type::HeapConstant(f->number_string(), t->zone());
} else if (type->Is(Type::String())) {
return Type::Constant(f->string_string(), t->zone());
return Type::HeapConstant(f->string_string(), t->zone());
} else if (type->Is(Type::Symbol())) {
return Type::Constant(f->symbol_string(), t->zone());
return Type::HeapConstant(f->symbol_string(), t->zone());
} else if (type->Is(Type::Union(Type::Undefined(), Type::OtherUndetectable(),
t->zone()))) {
return Type::Constant(f->undefined_string(), t->zone());
return Type::HeapConstant(f->undefined_string(), t->zone());
} else if (type->Is(Type::Null())) {
return Type::Constant(f->object_string(), t->zone());
return Type::HeapConstant(f->object_string(), t->zone());
} else if (type->Is(Type::Function())) {
return Type::Constant(f->function_string(), t->zone());
} else if (type->IsConstant()) {
return Type::Constant(
Object::TypeOf(t->isolate(), type->AsConstant()->Value()), t->zone());
return Type::HeapConstant(f->function_string(), t->zone());
} else if (type->IsHeapConstant()) {
return Type::HeapConstant(
Object::TypeOf(t->isolate(), type->AsHeapConstant()->Value()),
t->zone());
} else if (type->IsOtherNumberConstant()) {
return Type::HeapConstant(f->number_string(), t->zone());
}
return Type::InternalizedString();
}
@ -1292,9 +1290,9 @@ Type* Typer::Visitor::TypeJSCallConstruct(Node* node) {
Type* Typer::Visitor::JSCallFunctionTyper(Type* fun, Typer* t) {
if (fun->IsConstant() && fun->AsConstant()->Value()->IsJSFunction()) {
if (fun->IsHeapConstant() && fun->AsHeapConstant()->Value()->IsJSFunction()) {
Handle<JSFunction> function =
Handle<JSFunction>::cast(fun->AsConstant()->Value());
Handle<JSFunction>::cast(fun->AsHeapConstant()->Value());
if (function->shared()->HasBuiltinFunctionId()) {
switch (function->shared()->builtin_function_id()) {
case kMathRandom:
@ -1537,7 +1535,7 @@ Type* Typer::Visitor::TypePlainPrimitiveToFloat64(Node* node) {
// static
Type* Typer::Visitor::ReferenceEqualTyper(Type* lhs, Type* rhs, Typer* t) {
if (lhs->IsConstant() && rhs->Is(lhs)) {
if (lhs->IsHeapConstant() && rhs->Is(lhs)) {
return t->singleton_true_;
}
return Type::Boolean();
@ -1564,7 +1562,7 @@ Type* Typer::Visitor::StringFromCharCodeTyper(Type* type, Typer* t) {
if (min == max) {
uint32_t code = static_cast<uint32_t>(min) & String::kMaxUtf16CodeUnitU;
Handle<String> string = f->LookupSingleCharacterStringFromCode(code);
return Type::Constant(string, t->zone());
return Type::HeapConstant(string, t->zone());
}
return Type::String();
}
@ -1577,7 +1575,7 @@ Type* Typer::Visitor::StringFromCodePointTyper(Type* type, Typer* t) {
if (min == max) {
uint32_t code = static_cast<uint32_t>(min) & String::kMaxUtf16CodeUnitU;
Handle<String> string = f->LookupSingleCharacterStringFromCode(code);
return Type::Constant(string, t->zone());
return Type::HeapConstant(string, t->zone());
}
return Type::String();
}
@ -1752,7 +1750,7 @@ Type* Typer::Visitor::TypeConstant(Handle<Object> value) {
if (Type::IsInteger(*value)) {
return Type::Range(value->Number(), value->Number(), zone());
}
return Type::Constant(value, zone());
return Type::NewConstant(value, zone());
}
} // namespace compiler

View File

@ -56,12 +56,6 @@ bool Type::Contains(RangeType* lhs, RangeType* rhs) {
return lhs->Min() <= rhs->Min() && rhs->Max() <= lhs->Max();
}
bool Type::Contains(RangeType* lhs, ConstantType* rhs) {
DisallowHeapAllocation no_allocation;
return IsInteger(*rhs->Value()) && lhs->Min() <= rhs->Value()->Number() &&
rhs->Value()->Number() <= lhs->Max();
}
bool Type::Contains(RangeType* range, i::Object* val) {
DisallowHeapAllocation no_allocation;
return IsInteger(val) && range->Min() <= val->Number() &&
@ -82,7 +76,8 @@ double Type::Min() {
return min;
}
if (this->IsRange()) return this->AsRange()->Min();
if (this->IsConstant()) return this->AsConstant()->Value()->Number();
if (this->IsOtherNumberConstant())
return this->AsOtherNumberConstant()->Value();
UNREACHABLE();
return 0;
}
@ -98,7 +93,8 @@ double Type::Max() {
return max;
}
if (this->IsRange()) return this->AsRange()->Max();
if (this->IsConstant()) return this->AsConstant()->Value()->Number();
if (this->IsOtherNumberConstant())
return this->AsOtherNumberConstant()->Value();
UNREACHABLE();
return 0;
}
@ -139,7 +135,9 @@ Type::bitset BitsetType::Lub(Type* type) {
}
return bitset;
}
if (type->IsConstant()) return type->AsConstant()->Lub();
if (type->IsHeapConstant()) return type->AsHeapConstant()->Lub();
if (type->IsOtherNumberConstant())
return type->AsOtherNumberConstant()->Lub();
if (type->IsRange()) return type->AsRange()->Lub();
if (type->IsTuple()) return kOtherInternal;
UNREACHABLE();
@ -390,14 +388,43 @@ double BitsetType::Max(bitset bits) {
return std::numeric_limits<double>::quiet_NaN();
}
// static
bool OtherNumberConstantType::IsOtherNumberConstant(double value) {
// Not an integer, not NaN, and not -0.
return !std::isnan(value) && !Type::IsInteger(value) &&
!i::IsMinusZero(value);
}
// static
bool OtherNumberConstantType::IsOtherNumberConstant(Object* value) {
return value->IsHeapNumber() &&
IsOtherNumberConstant(HeapNumber::cast(value)->value());
}
HeapConstantType::HeapConstantType(BitsetType::bitset bitset,
i::Handle<i::Object> object)
: TypeBase(kHeapConstant), bitset_(bitset), object_(object) {
// All number types should be expressed as Ranges, OtherNumberConstants,
// or bitsets (nan, negative-zero).
DCHECK(!object->IsSmi() && !object->IsHeapNumber());
}
// -----------------------------------------------------------------------------
// Predicates.
bool Type::SimplyEquals(Type* that) {
DisallowHeapAllocation no_allocation;
if (this->IsConstant()) {
return that->IsConstant() &&
*this->AsConstant()->Value() == *that->AsConstant()->Value();
if (this->IsHeapConstant()) {
return that->IsHeapConstant() &&
*this->AsHeapConstant()->Value() == *that->AsHeapConstant()->Value();
}
if (this->IsOtherNumberConstant()) {
return that->IsOtherNumberConstant() &&
this->AsOtherNumberConstant()->Value() ==
that->AsOtherNumberConstant()->Value();
}
if (this->IsRange()) {
if (that->IsHeapConstant() || that->IsOtherNumberConstant()) return false;
}
if (this->IsTuple()) {
if (!that->IsTuple()) return false;
@ -446,9 +473,7 @@ bool Type::SlowIs(Type* that) {
}
if (that->IsRange()) {
return (this->IsRange() && Contains(that->AsRange(), this->AsRange())) ||
(this->IsConstant() &&
Contains(that->AsRange(), this->AsConstant()));
return (this->IsRange() && Contains(that->AsRange(), this->AsRange()));
}
if (this->IsRange()) return false;
@ -481,9 +506,6 @@ bool Type::Maybe(Type* that) {
if (this->IsBitset() && that->IsBitset()) return true;
if (this->IsRange()) {
if (that->IsConstant()) {
return Contains(this->AsRange(), that->AsConstant());
}
if (that->IsRange()) {
return Overlap(this->AsRange(), that->AsRange());
}
@ -673,9 +695,6 @@ int Type::IntersectAux(Type* lhs, Type* rhs, UnionType* result, int size,
}
return size;
}
if (rhs->IsConstant() && Contains(lhs->AsRange(), rhs->AsConstant())) {
return AddToUnion(rhs, result, size, zone);
}
if (rhs->IsRange()) {
RangeType::Limits lim = RangeType::Limits::Intersect(
RangeType::Limits(lhs->AsRange()), RangeType::Limits(rhs->AsRange()));
@ -743,6 +762,29 @@ Type* Type::NormalizeRangeAndBitset(Type* range, bitset* bits, Zone* zone) {
return RangeType::New(range_min, range_max, zone);
}
Type* Type::NewConstant(double value, Zone* zone) {
if (IsInteger(value)) {
return Range(value, value, zone);
} else if (i::IsMinusZero(value)) {
return Type::MinusZero();
} else if (std::isnan(value)) {
return Type::NaN();
}
DCHECK(OtherNumberConstantType::IsOtherNumberConstant(value));
return OtherNumberConstant(value, zone);
}
Type* Type::NewConstant(i::Handle<i::Object> value, Zone* zone) {
if (IsInteger(*value)) {
double v = value->Number();
return Range(v, v, zone);
} else if (value->IsHeapNumber()) {
return NewConstant(value->Number(), zone);
}
return HeapConstant(value, zone);
}
Type* Type::Union(Type* type1, Type* type2, Zone* zone) {
// Fast case: bit sets.
if (type1->IsBitset() && type2->IsBitset()) {
@ -833,17 +875,14 @@ Type* Type::NormalizeUnion(Type* union_type, int size, Zone* zone) {
return union_type;
}
// -----------------------------------------------------------------------------
// Iteration.
int Type::NumConstants() {
DisallowHeapAllocation no_allocation;
if (this->IsConstant()) {
if (this->IsHeapConstant() || this->IsOtherNumberConstant()) {
return 1;
} else if (this->IsUnion()) {
int result = 0;
for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) {
if (this->AsUnion()->Get(i)->IsConstant()) ++result;
if (this->AsUnion()->Get(i)->IsHeapConstant()) ++result;
}
return result;
} else {
@ -905,8 +944,11 @@ void Type::PrintTo(std::ostream& os) {
DisallowHeapAllocation no_allocation;
if (this->IsBitset()) {
BitsetType::Print(os, this->AsBitset());
} else if (this->IsConstant()) {
os << "Constant(" << Brief(*this->AsConstant()->Value()) << ")";
} else if (this->IsHeapConstant()) {
os << "HeapConstant(" << Brief(*this->AsHeapConstant()->Value()) << ")";
} else if (this->IsOtherNumberConstant()) {
os << "OtherNumberConstant(" << this->AsOtherNumberConstant()->Value()
<< ")";
} else if (this->IsRange()) {
std::ostream::fmtflags saved_flags = os.setf(std::ios::fixed);
std::streamsize saved_precision = os.precision(0);

View File

@ -263,7 +263,7 @@ class TypeBase {
protected:
friend class Type;
enum Kind { kConstant, kTuple, kUnion, kRange };
enum Kind { kHeapConstant, kOtherNumberConstant, kTuple, kUnion, kRange };
Kind kind() const { return kind_; }
explicit TypeBase(Kind kind) : kind_(kind) {}
@ -287,7 +287,38 @@ class TypeBase {
// -----------------------------------------------------------------------------
// Constant types.
class ConstantType : public TypeBase {
class OtherNumberConstantType : public TypeBase {
public:
double Value() { return value_; }
static bool IsOtherNumberConstant(double value);
static bool IsOtherNumberConstant(Object* value);
private:
friend class Type;
friend class BitsetType;
static Type* New(double value, Zone* zone) {
return AsType(new (zone->New(sizeof(OtherNumberConstantType)))
OtherNumberConstantType(value)); // NOLINT
}
static OtherNumberConstantType* cast(Type* type) {
DCHECK(IsKind(type, kOtherNumberConstant));
return static_cast<OtherNumberConstantType*>(FromType(type));
}
explicit OtherNumberConstantType(double value)
: TypeBase(kOtherNumberConstant), value_(value) {
CHECK(IsOtherNumberConstant(value));
}
BitsetType::bitset Lub() { return BitsetType::kOtherNumber; }
double value_;
};
class HeapConstantType : public TypeBase {
public:
i::Handle<i::Object> Value() { return object_; }
@ -297,24 +328,22 @@ class ConstantType : public TypeBase {
static Type* New(i::Handle<i::Object> value, Zone* zone) {
BitsetType::bitset bitset = BitsetType::Lub(*value);
return AsType(new (zone->New(sizeof(ConstantType)))
ConstantType(bitset, value));
return AsType(new (zone->New(sizeof(HeapConstantType)))
HeapConstantType(bitset, value));
}
static ConstantType* cast(Type* type) {
DCHECK(IsKind(type, kConstant));
return static_cast<ConstantType*>(FromType(type));
static HeapConstantType* cast(Type* type) {
DCHECK(IsKind(type, kHeapConstant));
return static_cast<HeapConstantType*>(FromType(type));
}
ConstantType(BitsetType::bitset bitset, i::Handle<i::Object> object)
: TypeBase(kConstant), bitset_(bitset), object_(object) {}
HeapConstantType(BitsetType::bitset bitset, i::Handle<i::Object> object);
BitsetType::bitset Lub() { return bitset_; }
BitsetType::bitset bitset_;
Handle<i::Object> object_;
};
// TODO(neis): Also cache value if numerical.
// -----------------------------------------------------------------------------
// Range types.
@ -474,8 +503,11 @@ class Type {
return BitsetType::New(BitsetType::UnsignedSmall());
}
static Type* Constant(i::Handle<i::Object> value, Zone* zone) {
return ConstantType::New(value, zone);
static Type* OtherNumberConstant(double value, Zone* zone) {
return OtherNumberConstantType::New(value, zone);
}
static Type* HeapConstant(i::Handle<i::Object> value, Zone* zone) {
return HeapConstantType::New(value, zone);
}
static Type* Range(double min, double max, Zone* zone) {
return RangeType::New(min, max, zone);
@ -488,6 +520,10 @@ class Type {
return tuple;
}
// NewConstant is a factory that returns Constant, Range or Number.
static Type* NewConstant(i::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);
@ -515,10 +551,16 @@ class Type {
// Inspection.
bool IsRange() { return IsKind(TypeBase::kRange); }
bool IsConstant() { return IsKind(TypeBase::kConstant); }
bool IsHeapConstant() { return IsKind(TypeBase::kHeapConstant); }
bool IsOtherNumberConstant() {
return IsKind(TypeBase::kOtherNumberConstant);
}
bool IsTuple() { return IsKind(TypeBase::kTuple); }
ConstantType* AsConstant() { return ConstantType::cast(this); }
HeapConstantType* AsHeapConstant() { return HeapConstantType::cast(this); }
OtherNumberConstantType* AsOtherNumberConstant() {
return OtherNumberConstantType::cast(this);
}
RangeType* AsRange() { return RangeType::cast(this); }
TupleType* AsTuple() { return TupleType::cast(this); }
@ -582,7 +624,6 @@ class Type {
static bool Overlap(RangeType* lhs, RangeType* rhs);
static bool Contains(RangeType* lhs, RangeType* rhs);
static bool Contains(RangeType* range, ConstantType* constant);
static bool Contains(RangeType* range, i::Object* val);
static int UpdateRange(Type* type, UnionType* result, int size, Zone* zone);

View File

@ -31,12 +31,6 @@ static bool IsInteger(double x) {
return nearbyint(x) == x && !i::IsMinusZero(x); // Allows for infinities.
}
static bool IsInteger(i::Object* x) {
return x->IsNumber() && IsInteger(x->Number());
}
typedef uint32_t bitset;
struct Tests {
@ -113,8 +107,8 @@ struct Tests {
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
Type* t = *it;
CHECK(1 ==
this->IsBitset(t) + t->IsConstant() + t->IsRange() +
this->IsUnion(t));
this->IsBitset(t) + t->IsHeapConstant() + t->IsRange() +
t->IsOtherNumberConstant() + this->IsUnion(t));
}
}
@ -191,15 +185,25 @@ struct Tests {
// Constructor
for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
Handle<i::Object> value = *vt;
Type* type = T.Constant(value);
CHECK(type->IsConstant());
Type* type = T.NewConstant(value);
CHECK(type->IsHeapConstant() || type->IsOtherNumberConstant() ||
type->IsRange());
}
// Value attribute
for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
Handle<i::Object> value = *vt;
Type* type = T.Constant(value);
CHECK(*value == *type->AsConstant()->Value());
Type* type = T.NewConstant(value);
if (type->IsHeapConstant()) {
CHECK(*value == *type->AsHeapConstant()->Value());
} else if (type->IsOtherNumberConstant()) {
CHECK(value->IsHeapNumber());
CHECK(value->Number() == type->AsOtherNumberConstant()->Value());
} else {
CHECK(type->IsRange());
double v = value->Number();
CHECK(v == type->AsRange()->Min() && v == type->AsRange()->Max());
}
}
// Functionality & Injectivity: Constant(V1) = Constant(V2) iff V1 = V2
@ -207,61 +211,72 @@ struct Tests {
for (ValueIterator vt2 = T.values.begin(); vt2 != T.values.end(); ++vt2) {
Handle<i::Object> value1 = *vt1;
Handle<i::Object> value2 = *vt2;
Type* type1 = T.Constant(value1);
Type* type2 = T.Constant(value2);
CHECK(Equal(type1, type2) == (*value1 == *value2));
Type* type1 = T.NewConstant(value1);
Type* type2 = T.NewConstant(value2);
if (type1->IsOtherNumberConstant() && type2->IsOtherNumberConstant()) {
CHECK(Equal(type1, type2) ==
(type1->AsOtherNumberConstant()->Value() ==
type2->AsOtherNumberConstant()->Value()));
} else if (type1->IsRange() && type2->IsRange()) {
CHECK(Equal(type1, type2) ==
((type1->AsRange()->Min() == type2->AsRange()->Min()) &&
(type1->AsRange()->Max() == type2->AsRange()->Max())));
} else {
CHECK(Equal(type1, type2) == (*value1 == *value2));
}
}
}
// Typing of numbers
Factory* fac = isolate->factory();
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.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));
CHECK(T.NewConstant(fac->NewNumber(0))->Is(T.UnsignedSmall));
CHECK(T.NewConstant(fac->NewNumber(1))->Is(T.UnsignedSmall));
CHECK(T.NewConstant(fac->NewNumber(0x3fffffff))->Is(T.UnsignedSmall));
CHECK(T.NewConstant(fac->NewNumber(-1))->Is(T.Negative31));
CHECK(T.NewConstant(fac->NewNumber(-0x3fffffff))->Is(T.Negative31));
CHECK(T.NewConstant(fac->NewNumber(-0x40000000))->Is(T.Negative31));
CHECK(T.NewConstant(fac->NewNumber(0x40000000))->Is(T.Unsigned31));
CHECK(!T.NewConstant(fac->NewNumber(0x40000000))->Is(T.Unsigned30));
CHECK(T.NewConstant(fac->NewNumber(0x7fffffff))->Is(T.Unsigned31));
CHECK(!T.NewConstant(fac->NewNumber(0x7fffffff))->Is(T.Unsigned30));
CHECK(T.NewConstant(fac->NewNumber(-0x40000001))->Is(T.Negative32));
CHECK(!T.NewConstant(fac->NewNumber(-0x40000001))->Is(T.Negative31));
CHECK(T.NewConstant(fac->NewNumber(-0x7fffffff))->Is(T.Negative32));
CHECK(!T.NewConstant(fac->NewNumber(-0x7fffffff - 1))->Is(T.Negative31));
if (SmiValuesAre31Bits()) {
CHECK(!T.Constant(fac->NewNumber(0x40000000))->Is(T.UnsignedSmall));
CHECK(!T.Constant(fac->NewNumber(0x7fffffff))->Is(T.UnsignedSmall));
CHECK(!T.Constant(fac->NewNumber(-0x40000001))->Is(T.SignedSmall));
CHECK(!T.Constant(fac->NewNumber(-0x7fffffff - 1))->Is(T.SignedSmall));
CHECK(!T.NewConstant(fac->NewNumber(0x40000000))->Is(T.UnsignedSmall));
CHECK(!T.NewConstant(fac->NewNumber(0x7fffffff))->Is(T.UnsignedSmall));
CHECK(!T.NewConstant(fac->NewNumber(-0x40000001))->Is(T.SignedSmall));
CHECK(!T.NewConstant(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(-0x40000001))->Is(T.SignedSmall));
CHECK(T.Constant(fac->NewNumber(-0x7fffffff - 1))->Is(T.SignedSmall));
CHECK(T.NewConstant(fac->NewNumber(0x40000000))->Is(T.UnsignedSmall));
CHECK(T.NewConstant(fac->NewNumber(0x7fffffff))->Is(T.UnsignedSmall));
CHECK(T.NewConstant(fac->NewNumber(-0x40000001))->Is(T.SignedSmall));
CHECK(T.NewConstant(fac->NewNumber(-0x7fffffff - 1))->Is(T.SignedSmall));
}
CHECK(T.Constant(fac->NewNumber(0x80000000u))->Is(T.Unsigned32));
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.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));
CHECK(!T.Constant(fac->NewNumber(-0x7fffffff - 2.0))->Is(T.Integral32));
CHECK(T.Constant(fac->NewNumber(0.1))->Is(T.PlainNumber));
CHECK(!T.Constant(fac->NewNumber(0.1))->Is(T.Integral32));
CHECK(T.Constant(fac->NewNumber(-10.1))->Is(T.PlainNumber));
CHECK(!T.Constant(fac->NewNumber(-10.1))->Is(T.Integral32));
CHECK(T.Constant(fac->NewNumber(10e60))->Is(T.PlainNumber));
CHECK(!T.Constant(fac->NewNumber(10e60))->Is(T.Integral32));
CHECK(T.Constant(fac->NewNumber(-1.0*0.0))->Is(T.MinusZero));
CHECK(T.Constant(fac->NewNumber(std::numeric_limits<double>::quiet_NaN()))
->Is(T.NaN));
CHECK(T.Constant(fac->NewNumber(V8_INFINITY))->Is(T.PlainNumber));
CHECK(!T.Constant(fac->NewNumber(V8_INFINITY))->Is(T.Integral32));
CHECK(T.Constant(fac->NewNumber(-V8_INFINITY))->Is(T.PlainNumber));
CHECK(!T.Constant(fac->NewNumber(-V8_INFINITY))->Is(T.Integral32));
CHECK(T.NewConstant(fac->NewNumber(0x80000000u))->Is(T.Unsigned32));
CHECK(!T.NewConstant(fac->NewNumber(0x80000000u))->Is(T.Unsigned31));
CHECK(T.NewConstant(fac->NewNumber(0xffffffffu))->Is(T.Unsigned32));
CHECK(!T.NewConstant(fac->NewNumber(0xffffffffu))->Is(T.Unsigned31));
CHECK(T.NewConstant(fac->NewNumber(0xffffffffu + 1.0))->Is(T.PlainNumber));
CHECK(!T.NewConstant(fac->NewNumber(0xffffffffu + 1.0))->Is(T.Integral32));
CHECK(T.NewConstant(fac->NewNumber(-0x7fffffff - 2.0))->Is(T.PlainNumber));
CHECK(!T.NewConstant(fac->NewNumber(-0x7fffffff - 2.0))->Is(T.Integral32));
CHECK(T.NewConstant(fac->NewNumber(0.1))->Is(T.PlainNumber));
CHECK(!T.NewConstant(fac->NewNumber(0.1))->Is(T.Integral32));
CHECK(T.NewConstant(fac->NewNumber(-10.1))->Is(T.PlainNumber));
CHECK(!T.NewConstant(fac->NewNumber(-10.1))->Is(T.Integral32));
CHECK(T.NewConstant(fac->NewNumber(10e60))->Is(T.PlainNumber));
CHECK(!T.NewConstant(fac->NewNumber(10e60))->Is(T.Integral32));
CHECK(T.NewConstant(fac->NewNumber(-1.0 * 0.0))->Is(T.MinusZero));
CHECK(
T.NewConstant(fac->NewNumber(std::numeric_limits<double>::quiet_NaN()))
->Is(T.NaN));
CHECK(T.NewConstant(fac->NewNumber(V8_INFINITY))->Is(T.PlainNumber));
CHECK(!T.NewConstant(fac->NewNumber(V8_INFINITY))->Is(T.Integral32));
CHECK(T.NewConstant(fac->NewNumber(-V8_INFINITY))->Is(T.PlainNumber));
CHECK(!T.NewConstant(fac->NewNumber(-V8_INFINITY))->Is(T.Integral32));
}
void Range() {
@ -317,7 +332,7 @@ struct Tests {
// Constant(V)->Is(Of(V))
for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
Handle<i::Object> value = *vt;
Type* const_type = T.Constant(value);
Type* const_type = T.NewConstant(value);
Type* of_type = T.Of(value);
CHECK(const_type->Is(of_type));
}
@ -327,7 +342,7 @@ struct Tests {
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
Handle<i::Object> value = *vt;
Type* type = *it;
Type* const_type = T.Constant(value);
Type* const_type = T.NewConstant(value);
Type* of_type = T.Of(value);
CHECK(!of_type->Is(type) || const_type->Is(type));
}
@ -338,7 +353,7 @@ struct Tests {
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
Handle<i::Object> value = *vt;
Type* type = *it;
Type* const_type = T.Constant(value);
Type* const_type = T.NewConstant(value);
Type* of_type = T.Of(value);
CHECK(!const_type->Is(type) ||
of_type->Is(type) || type->Maybe(const_type));
@ -521,10 +536,11 @@ struct Tests {
Type* type2 = *j;
CHECK(!type1->Is(type2) || this->IsBitset(type2) ||
this->IsUnion(type2) || this->IsUnion(type1) ||
(type1->IsConstant() && type2->IsConstant()) ||
(type1->IsConstant() && type2->IsRange()) ||
(type1->IsHeapConstant() && type2->IsHeapConstant()) ||
(this->IsBitset(type1) && type2->IsRange()) ||
(type1->IsRange() && type2->IsRange()) ||
(type1->IsOtherNumberConstant() &&
type2->IsOtherNumberConstant()) ||
!type1->IsInhabited());
}
}
@ -559,37 +575,27 @@ struct Tests {
for (ValueIterator vt2 = T.values.begin(); vt2 != T.values.end(); ++vt2) {
Handle<i::Object> value1 = *vt1;
Handle<i::Object> value2 = *vt2;
Type* const_type1 = T.Constant(value1);
Type* const_type2 = T.Constant(value2);
CHECK(const_type1->Is(const_type2) == (*value1 == *value2));
Type* const_type1 = T.NewConstant(value1);
Type* const_type2 = T.NewConstant(value2);
if (const_type1->IsOtherNumberConstant() &&
const_type2->IsOtherNumberConstant()) {
CHECK(const_type1->Is(const_type2) ==
(const_type1->AsOtherNumberConstant()->Value() ==
const_type2->AsOtherNumberConstant()->Value()));
} else if (const_type1->IsRange() && const_type2->IsRange()) {
CHECK(Equal(const_type1, const_type2) ==
((const_type1->AsRange()->Min() ==
const_type2->AsRange()->Min()) &&
(const_type1->AsRange()->Max() ==
const_type2->AsRange()->Max())));
} else {
CHECK(const_type1->Is(const_type2) == (*value1 == *value2));
}
}
}
// Range-specific subtyping
// If IsInteger(v) then Constant(v)->Is(Range(v, v)).
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
Type* type = *it;
if (type->IsConstant() && IsInteger(*type->AsConstant()->Value())) {
CHECK(type->Is(T.Range(type->AsConstant()->Value()->Number(),
type->AsConstant()->Value()->Number())));
}
}
// If Constant(x)->Is(Range(min,max)) then IsInteger(v) and min <= x <= max.
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
Type* type1 = *it1;
Type* type2 = *it2;
if (type1->IsConstant() && type2->IsRange() && type1->Is(type2)) {
double x = type1->AsConstant()->Value()->Number();
double min = type2->AsRange()->Min();
double max = type2->AsRange()->Max();
CHECK(IsInteger(x) && min <= x && x <= max);
}
}
}
// Lub(Range(x,y))->Is(T.Union(T.Integral32, T.OtherNumber))
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
Type* type = *it;
@ -712,9 +718,22 @@ struct Tests {
for (ValueIterator vt2 = T.values.begin(); vt2 != T.values.end(); ++vt2) {
Handle<i::Object> value1 = *vt1;
Handle<i::Object> value2 = *vt2;
Type* const_type1 = T.Constant(value1);
Type* const_type2 = T.Constant(value2);
CHECK(const_type1->Maybe(const_type2) == (*value1 == *value2));
Type* const_type1 = T.NewConstant(value1);
Type* const_type2 = T.NewConstant(value2);
if (const_type1->IsOtherNumberConstant() &&
const_type2->IsOtherNumberConstant()) {
CHECK(const_type1->Maybe(const_type2) ==
(const_type1->AsOtherNumberConstant()->Value() ==
const_type2->AsOtherNumberConstant()->Value()));
} else if (const_type1->IsRange() && const_type2->IsRange()) {
CHECK(Equal(const_type1, const_type2) ==
((const_type1->AsRange()->Min() ==
const_type2->AsRange()->Min()) &&
(const_type1->AsRange()->Max() ==
const_type2->AsRange()->Max())));
} else {
CHECK(const_type1->Maybe(const_type2) == (*value1 == *value2));
}
}
}
@ -1054,20 +1073,6 @@ struct Tests {
CHECK(type1->Max() == range->Max());
}
}
// GetRange(Union(Constant(x), Range(min,max))) == Range(min, max).
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
Type* type1 = *it1;
Type* type2 = *it2;
if (type1->IsConstant() && type2->IsRange()) {
Type* u = T.Union(type1, type2);
CHECK(type2->Min() == u->GetRange()->Min());
CHECK(type2->Max() == u->GetRange()->Max());
}
}
}
}
};

View File

@ -54,27 +54,37 @@ class Types {
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);
// 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::Constant(smi, zone);
Signed32Constant = Type::Constant(signed32, zone);
SmiConstant = Type::NewConstant(smi, zone);
Signed32Constant = Type::NewConstant(signed32, zone);
ObjectConstant1 = Type::Constant(object1, zone);
ObjectConstant2 = Type::Constant(object2, zone);
ArrayConstant = Type::Constant(array, zone);
UninitializedConstant = Type::Constant(uninitialized, zone);
ObjectConstant1 = Type::HeapConstant(object1, zone);
ObjectConstant2 = Type::HeapConstant(object2, zone);
ArrayConstant = Type::HeapConstant(array, zone);
UninitializedConstant = Type::HeapConstant(uninitialized, zone);
values.push_back(smi);
values.push_back(boxed_smi);
values.push_back(signed32);
values.push_back(object1);
values.push_back(object2);
values.push_back(array);
values.push_back(uninitialized);
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::Constant(*it, zone));
types.push_back(Type::NewConstant(*it, zone));
}
integers.push_back(isolate->factory()->NewNumber(-V8_INFINITY));
@ -98,7 +108,11 @@ 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;
@ -129,8 +143,12 @@ class Types {
Type* Of(Handle<i::Object> value) { return Type::Of(value, zone_); }
Type* Constant(Handle<i::Object> value) {
return Type::Constant(value, zone_);
Type* NewConstant(Handle<i::Object> value) {
return Type::NewConstant(value, zone_);
}
Type* HeapConstant(Handle<i::Object> value) {
return Type::HeapConstant(value, zone_);
}
Type* Range(double min, double max) { return Type::Range(min, max, zone_); }
@ -170,7 +188,7 @@ class Types {
}
case 1: { // constant
int i = rng_->NextInt(static_cast<int>(values.size()));
return Type::Constant(values[i], zone_);
return Type::NewConstant(values[i], zone_);
}
case 2: { // range
int i = rng_->NextInt(static_cast<int>(integers.size()));

View File

@ -54,7 +54,7 @@ Node* GraphTest::NumberConstant(volatile double value) {
Node* GraphTest::HeapConstant(const Handle<HeapObject>& value) {
Node* node = graph()->NewNode(common()->HeapConstant(value));
Type* type = Type::Constant(value, zone());
Type* type = Type::HeapConstant(value, zone());
NodeProperties::SetType(node, type);
return node;
}

View File

@ -65,7 +65,7 @@ class JSCreateLoweringTest : public TypedGraphTest {
TEST_F(JSCreateLoweringTest, JSCreate) {
Handle<JSFunction> function = isolate()->object_function();
Node* const target = Parameter(Type::Constant(function, graph()->zone()));
Node* const target = Parameter(Type::HeapConstant(function, graph()->zone()));
Node* const context = Parameter(Type::Any());
Node* const effect = graph()->start();
Reduction r = Reduce(graph()->NewNode(javascript()->Create(), target, target,

View File

@ -88,7 +88,7 @@ class TypedOptimizationTest : public TypedGraphTest {
TEST_F(TypedOptimizationTest, ParameterWithMinusZero) {
{
Reduction r = Reduce(
Parameter(Type::Constant(factory()->minus_zero_value(), zone())));
Parameter(Type::NewConstant(factory()->minus_zero_value(), zone())));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsNumberConstant(-0.0));
}
@ -98,9 +98,9 @@ TEST_F(TypedOptimizationTest, ParameterWithMinusZero) {
EXPECT_THAT(r.replacement(), IsNumberConstant(-0.0));
}
{
Reduction r = Reduce(Parameter(
Type::Union(Type::MinusZero(),
Type::Constant(factory()->NewNumber(0), zone()), zone())));
Reduction r = Reduce(Parameter(Type::Union(
Type::MinusZero(), Type::NewConstant(factory()->NewNumber(0), zone()),
zone())));
EXPECT_FALSE(r.Changed());
}
}
@ -108,7 +108,7 @@ TEST_F(TypedOptimizationTest, ParameterWithMinusZero) {
TEST_F(TypedOptimizationTest, ParameterWithNull) {
Handle<HeapObject> null = factory()->null_value();
{
Reduction r = Reduce(Parameter(Type::Constant(null, zone())));
Reduction r = Reduce(Parameter(Type::NewConstant(null, zone())));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsHeapConstant(null));
}
@ -125,13 +125,13 @@ TEST_F(TypedOptimizationTest, ParameterWithNaN) {
std::numeric_limits<double>::signaling_NaN()};
TRACED_FOREACH(double, nan, kNaNs) {
Handle<Object> constant = factory()->NewNumber(nan);
Reduction r = Reduce(Parameter(Type::Constant(constant, zone())));
Reduction r = Reduce(Parameter(Type::NewConstant(constant, zone())));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsNumberConstant(IsNaN()));
}
{
Reduction r =
Reduce(Parameter(Type::Constant(factory()->nan_value(), zone())));
Reduce(Parameter(Type::NewConstant(factory()->nan_value(), zone())));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsNumberConstant(IsNaN()));
}
@ -145,7 +145,7 @@ TEST_F(TypedOptimizationTest, ParameterWithNaN) {
TEST_F(TypedOptimizationTest, ParameterWithPlainNumber) {
TRACED_FOREACH(double, value, kFloat64Values) {
Handle<Object> constant = factory()->NewNumber(value);
Reduction r = Reduce(Parameter(Type::Constant(constant, zone())));
Reduction r = Reduce(Parameter(Type::NewConstant(constant, zone())));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsNumberConstant(value));
}
@ -164,7 +164,7 @@ TEST_F(TypedOptimizationTest, ParameterWithUndefined) {
EXPECT_THAT(r.replacement(), IsHeapConstant(undefined));
}
{
Reduction r = Reduce(Parameter(Type::Constant(undefined, zone())));
Reduction r = Reduce(Parameter(Type::NewConstant(undefined, zone())));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsHeapConstant(undefined));
}
@ -182,9 +182,9 @@ TEST_F(TypedOptimizationTest, JSToBooleanWithFalsish) {
Type::Undefined(),
Type::Union(
Type::Undetectable(),
Type::Union(
Type::Constant(factory()->false_value(), zone()),
Type::Range(0.0, 0.0, zone()), zone()),
Type::Union(Type::NewConstant(
factory()->false_value(), zone()),
Type::Range(0.0, 0.0, zone()), zone()),
zone()),
zone()),
zone()),
@ -201,7 +201,7 @@ TEST_F(TypedOptimizationTest, JSToBooleanWithFalsish) {
TEST_F(TypedOptimizationTest, JSToBooleanWithTruish) {
Node* input = Parameter(
Type::Union(
Type::Constant(factory()->true_value(), zone()),
Type::NewConstant(factory()->true_value(), zone()),
Type::Union(Type::DetectableReceiver(), Type::Symbol(), zone()),
zone()),
0);

View File

@ -135,7 +135,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::Constant(
Type* result_type = Type::NewConstant(
isolate()->factory()->NewNumber(result_value), zone());
EXPECT_TRUE(result_type->Is(expected_type));
}
@ -156,7 +156,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::Constant(
Type* result_type = Type::NewConstant(
isolate()->factory()->NewNumber(result_value), zone());
EXPECT_TRUE(result_type->Is(expected_type));
}
@ -173,10 +173,10 @@ class TyperTest : public TypedGraphTest {
double x1 = RandomInt(r1->AsRange());
double x2 = RandomInt(r2->AsRange());
bool result_value = opfun(x1, x2);
Type* result_type =
Type::Constant(result_value ? isolate()->factory()->true_value()
: isolate()->factory()->false_value(),
zone());
Type* result_type = Type::NewConstant(
result_value ? isolate()->factory()->true_value()
: isolate()->factory()->false_value(),
zone());
EXPECT_TRUE(result_type->Is(expected_type));
}
}
@ -192,7 +192,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::Constant(
Type* result_type = Type::NewConstant(
isolate()->factory()->NewNumber(result_value), zone());
EXPECT_TRUE(result_type->Is(expected_type));
}