[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:
parent
1f89d369fc
commit
978fe70beb
@ -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;
|
||||
|
@ -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());
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 &&
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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()));
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user