summaryrefslogtreecommitdiff
path: root/deps/v8/src/compiler/typer.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/compiler/typer.cc')
-rw-r--r--deps/v8/src/compiler/typer.cc388
1 files changed, 236 insertions, 152 deletions
diff --git a/deps/v8/src/compiler/typer.cc b/deps/v8/src/compiler/typer.cc
index 137829e92d..9af65597bf 100644
--- a/deps/v8/src/compiler/typer.cc
+++ b/deps/v8/src/compiler/typer.cc
@@ -2,12 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "src/base/flags.h"
#include "src/bootstrapper.h"
-#include "src/compiler/graph-inl.h"
#include "src/compiler/graph-reducer.h"
#include "src/compiler/js-operator.h"
#include "src/compiler/node.h"
-#include "src/compiler/node-properties-inl.h"
#include "src/compiler/node-properties.h"
#include "src/compiler/simplified-operator.h"
#include "src/compiler/typer.h"
@@ -45,7 +44,8 @@ enum LazyCachedType {
// TODO(turbofan): these types could be globally cached or cached per isolate.
class LazyTypeCache FINAL : public ZoneObject {
public:
- explicit LazyTypeCache(Zone* zone) : zone_(zone) {
+ explicit LazyTypeCache(Isolate* isolate, Zone* zone)
+ : isolate_(isolate), zone_(zone) {
memset(cache_, 0, sizeof(cache_));
}
@@ -128,15 +128,15 @@ class LazyTypeCache FINAL : public ZoneObject {
}
Type* CreateRange(double min, double max) const {
- return Type::Range(factory()->NewNumber(min), factory()->NewNumber(max),
- zone());
+ return Type::Range(min, max, zone());
}
Factory* factory() const { return isolate()->factory(); }
- Isolate* isolate() const { return zone()->isolate(); }
+ Isolate* isolate() const { return isolate_; }
Zone* zone() const { return zone_; }
Type* cache_[kNumLazyCachedTypes];
+ Isolate* isolate_;
Zone* zone_;
};
@@ -144,25 +144,24 @@ class LazyTypeCache FINAL : public ZoneObject {
class Typer::Decorator FINAL : public GraphDecorator {
public:
explicit Decorator(Typer* typer) : typer_(typer) {}
- void Decorate(Node* node) FINAL;
+ void Decorate(Node* node, bool incomplete) FINAL;
private:
Typer* typer_;
};
-Typer::Typer(Graph* graph, MaybeHandle<Context> context)
- : graph_(graph),
+Typer::Typer(Isolate* isolate, Graph* graph, MaybeHandle<Context> context)
+ : isolate_(isolate),
+ graph_(graph),
context_(context),
decorator_(NULL),
- cache_(new (graph->zone()) LazyTypeCache(graph->zone())),
+ cache_(new (graph->zone()) LazyTypeCache(isolate, graph->zone())),
weaken_min_limits_(graph->zone()),
weaken_max_limits_(graph->zone()) {
Zone* zone = this->zone();
- Factory* f = zone->isolate()->factory();
+ Factory* f = isolate->factory();
- Handle<Object> zero = f->NewNumber(0);
- Handle<Object> one = f->NewNumber(1);
Handle<Object> infinity = f->NewNumber(+V8_INFINITY);
Handle<Object> minusinfinity = f->NewNumber(-V8_INFINITY);
@@ -180,8 +179,8 @@ Typer::Typer(Graph* graph, MaybeHandle<Context> context)
undefined_or_number = Type::Union(Type::Undefined(), Type::Number(), zone);
singleton_false = Type::Constant(f->false_value(), zone);
singleton_true = Type::Constant(f->true_value(), zone);
- singleton_zero = Type::Range(zero, zero, zone);
- singleton_one = Type::Range(one, one, zone);
+ singleton_zero = Type::Range(0.0, 0.0, zone);
+ singleton_one = Type::Range(1.0, 1.0, zone);
zero_or_one = Type::Union(singleton_zero, singleton_one, zone);
zeroish = Type::Union(singleton_zero, nan_or_minuszero, zone);
signed32ish = Type::Union(signed32, truncating_to_zero, zone);
@@ -193,7 +192,7 @@ Typer::Typer(Graph* graph, MaybeHandle<Context> context)
truish = Type::Union(
singleton_true,
Type::Union(Type::DetectableReceiver(), Type::Symbol(), zone), zone);
- integer = Type::Range(minusinfinity, infinity, zone);
+ integer = Type::Range(-V8_INFINITY, V8_INFINITY, zone);
weakint = Type::Union(integer, nan_or_minuszero, zone);
number_fun0_ = Type::Function(number, zone);
@@ -209,11 +208,11 @@ Typer::Typer(Graph* graph, MaybeHandle<Context> context)
weaken_max_limits_.reserve(limits_count + 1);
double limit = 1 << 30;
- weaken_min_limits_.push_back(f->NewNumber(0));
- weaken_max_limits_.push_back(f->NewNumber(0));
+ weaken_min_limits_.push_back(0);
+ weaken_max_limits_.push_back(0);
for (int i = 0; i < limits_count; i++) {
- weaken_min_limits_.push_back(f->NewNumber(-limit));
- weaken_max_limits_.push_back(f->NewNumber(limit - 1));
+ weaken_min_limits_.push_back(-limit);
+ weaken_max_limits_.push_back(limit - 1);
limit *= 2;
}
@@ -313,14 +312,7 @@ class Typer::Visitor : public Reducer {
return BoundsOrNone(operand_node);
}
- Bounds ContextOperand(Node* node) {
- Bounds result = BoundsOrNone(NodeProperties::GetContextInput(node));
- DCHECK(result.upper->Maybe(Type::Internal()));
- // TODO(rossberg): More precisely, instead of the above assertion, we should
- // back-propagate the constraint that it has to be a subtype of Internal.
- return result;
- }
-
+ Bounds WrapContextBoundsForInput(Node* node);
Type* Weaken(Type* current_type, Type* previous_type);
Zone* zone() { return typer_->zone(); }
@@ -334,8 +326,16 @@ class Typer::Visitor : public Reducer {
Bounds TypeUnaryOp(Node* node, UnaryTyperFun);
Bounds TypeBinaryOp(Node* node, BinaryTyperFun);
+ enum ComparisonOutcomeFlags {
+ kComparisonTrue = 1,
+ kComparisonFalse = 2,
+ kComparisonUndefined = 4
+ };
+ typedef base::Flags<ComparisonOutcomeFlags> ComparisonOutcome;
+
+ static ComparisonOutcome Invert(ComparisonOutcome, Typer*);
static Type* Invert(Type*, Typer*);
- static Type* FalsifyUndefined(Type*, Typer*);
+ static Type* FalsifyUndefined(ComparisonOutcome, Typer*);
static Type* Rangify(Type*, Typer*);
static Type* ToPrimitive(Type*, Typer*);
@@ -351,7 +351,7 @@ class Typer::Visitor : public Reducer {
static Type* JSDivideRanger(Type::RangeType*, Type::RangeType*, Typer*);
static Type* JSModulusRanger(Type::RangeType*, Type::RangeType*, Typer*);
- static Type* JSCompareTyper(Type*, Type*, Typer*);
+ static ComparisonOutcome JSCompareTyper(Type*, Type*, Typer*);
#define DECLARE_METHOD(x) static Type* x##Typer(Type*, Type*, Typer*);
JS_SIMPLE_BINOP_LIST(DECLARE_METHOD)
@@ -417,7 +417,8 @@ void Typer::Run() {
}
-void Typer::Decorator::Decorate(Node* node) {
+void Typer::Decorator::Decorate(Node* node, bool incomplete) {
+ if (incomplete) return;
if (node->op()->ValueOutputCount() > 0) {
// Only eagerly type-decorate nodes with known input types.
// Other cases will generally require a proper fixpoint iteration with Run.
@@ -444,14 +445,14 @@ void Typer::Decorator::Decorate(Node* node) {
Bounds Typer::Visitor::TypeUnaryOp(Node* node, UnaryTyperFun f) {
Bounds input = Operand(node, 0);
- Type* upper = input.upper->Is(Type::None())
- ? Type::None()
- : f(input.upper, typer_);
- Type* lower = input.lower->Is(Type::None())
- ? Type::None()
- : (input.lower == input.upper || upper->IsConstant())
- ? upper // TODO(neis): Extend this to Range(x,x), NaN, MinusZero, ...?
- : f(input.lower, typer_);
+ Type* upper =
+ input.upper->IsInhabited() ? f(input.upper, typer_) : Type::None();
+ Type* lower = input.lower->IsInhabited()
+ ? ((input.lower == input.upper || upper->IsConstant())
+ ? upper // TODO(neis): Extend this to Range(x,x),
+ // NaN, MinusZero, ...?
+ : f(input.lower, typer_))
+ : Type::None();
// TODO(neis): Figure out what to do with lower bound.
return Bounds(lower, upper);
}
@@ -460,30 +461,49 @@ Bounds Typer::Visitor::TypeUnaryOp(Node* node, UnaryTyperFun f) {
Bounds Typer::Visitor::TypeBinaryOp(Node* node, BinaryTyperFun f) {
Bounds left = Operand(node, 0);
Bounds right = Operand(node, 1);
- Type* upper = left.upper->Is(Type::None()) || right.upper->Is(Type::None())
- ? Type::None()
- : f(left.upper, right.upper, typer_);
- Type* lower = left.lower->Is(Type::None()) || right.lower->Is(Type::None())
- ? Type::None()
- : ((left.lower == left.upper && right.lower == right.upper) ||
- upper->IsConstant())
- ? upper
- : f(left.lower, right.lower, typer_);
+ Type* upper = left.upper->IsInhabited() && right.upper->IsInhabited()
+ ? f(left.upper, right.upper, typer_)
+ : Type::None();
+ Type* lower =
+ left.lower->IsInhabited() && right.lower->IsInhabited()
+ ? (((left.lower == left.upper && right.lower == right.upper) ||
+ upper->IsConstant())
+ ? upper
+ : f(left.lower, right.lower, typer_))
+ : Type::None();
// TODO(neis): Figure out what to do with lower bound.
return Bounds(lower, upper);
}
Type* Typer::Visitor::Invert(Type* type, Typer* t) {
+ DCHECK(type->Is(Type::Boolean()));
+ DCHECK(type->IsInhabited());
if (type->Is(t->singleton_false)) return t->singleton_true;
if (type->Is(t->singleton_true)) return t->singleton_false;
return type;
}
-Type* Typer::Visitor::FalsifyUndefined(Type* type, Typer* t) {
- if (type->Is(Type::Undefined())) return t->singleton_false;
- return type;
+Typer::Visitor::ComparisonOutcome Typer::Visitor::Invert(
+ ComparisonOutcome outcome, Typer* t) {
+ ComparisonOutcome result(0);
+ if ((outcome & kComparisonUndefined) != 0) result |= kComparisonUndefined;
+ if ((outcome & kComparisonTrue) != 0) result |= kComparisonFalse;
+ if ((outcome & kComparisonFalse) != 0) result |= kComparisonTrue;
+ return result;
+}
+
+
+Type* Typer::Visitor::FalsifyUndefined(ComparisonOutcome outcome, Typer* t) {
+ if ((outcome & kComparisonFalse) != 0 ||
+ (outcome & kComparisonUndefined) != 0) {
+ return (outcome & kComparisonTrue) != 0 ? Type::Boolean()
+ : t->singleton_false;
+ }
+ // Type should be non empty, so we know it should be true.
+ DCHECK((outcome & kComparisonTrue) != 0);
+ return t->singleton_true;
}
@@ -500,8 +520,7 @@ Type* Typer::Visitor::Rangify(Type* type, Typer* t) {
DCHECK(std::isnan(max));
return type;
}
- Factory* f = t->isolate()->factory();
- return Type::Range(f->NewNumber(min), f->NewNumber(max), t->zone());
+ return Type::Range(min, max, t->zone());
}
@@ -593,14 +612,33 @@ Bounds Typer::Visitor::TypeStart(Node* node) {
// Common operators.
+Bounds Typer::Visitor::TypeAlways(Node* node) {
+ return Bounds(Type::None(zone()), Type::Boolean(zone()));
+}
+
+
Bounds Typer::Visitor::TypeParameter(Node* node) {
return Bounds::Unbounded(zone());
}
+Bounds Typer::Visitor::TypeOsrValue(Node* node) {
+ if (node->InputAt(0)->opcode() == IrOpcode::kOsrLoopEntry) {
+ // Before deconstruction, OSR values have type {None} to avoid polluting
+ // the types of phis and other nodes in the graph.
+ return Bounds(Type::None(), Type::None());
+ }
+ if (NodeProperties::IsTyped(node)) {
+ // After deconstruction, OSR values may have had a type explicitly set.
+ return NodeProperties::GetBounds(node);
+ }
+ // Otherwise, be conservative.
+ return Bounds::Unbounded(zone());
+}
+
+
Bounds Typer::Visitor::TypeInt32Constant(Node* node) {
- Factory* f = isolate()->factory();
- Handle<Object> number = f->NewNumber(OpParameter<int32_t>(node));
+ double number = OpParameter<int32_t>(node);
return Bounds(Type::Intersect(
Type::Range(number, number, zone()), Type::UntaggedSigned32(), zone()));
}
@@ -664,6 +702,12 @@ Bounds Typer::Visitor::TypeEffectPhi(Node* node) {
}
+Bounds Typer::Visitor::TypeEffectSet(Node* node) {
+ UNREACHABLE();
+ return Bounds();
+}
+
+
Bounds Typer::Visitor::TypeValueEffect(Node* node) {
UNREACHABLE();
return Bounds();
@@ -761,26 +805,41 @@ Type* Typer::Visitor::JSStrictNotEqualTyper(Type* lhs, Type* rhs, Typer* t) {
// (<, <=, >=, >) with the help of a single abstract one. It behaves like <
// but returns undefined when the inputs cannot be compared.
// We implement the typing analogously.
-Type* Typer::Visitor::JSCompareTyper(Type* lhs, Type* rhs, Typer* t) {
+Typer::Visitor::ComparisonOutcome Typer::Visitor::JSCompareTyper(Type* lhs,
+ Type* rhs,
+ Typer* t) {
lhs = ToPrimitive(lhs, t);
rhs = ToPrimitive(rhs, t);
if (lhs->Maybe(Type::String()) && rhs->Maybe(Type::String())) {
- return Type::Boolean();
+ return ComparisonOutcome(kComparisonTrue) |
+ ComparisonOutcome(kComparisonFalse);
}
lhs = ToNumber(lhs, t);
rhs = ToNumber(rhs, t);
- if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::Undefined();
+
+ // Shortcut for NaNs.
+ if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return kComparisonUndefined;
+
+ ComparisonOutcome result;
if (lhs->IsConstant() && rhs->Is(lhs)) {
- // Types are equal and are inhabited only by a single semantic value,
- // which is not NaN due to the previous check.
- return t->singleton_false;
+ // Types are equal and are inhabited only by a single semantic value.
+ result = kComparisonFalse;
+ } else if (lhs->Min() >= rhs->Max()) {
+ result = kComparisonFalse;
+ } else if (lhs->Max() < rhs->Min()) {
+ result = kComparisonTrue;
+ } else {
+ // We cannot figure out the result, return both true and false. (We do not
+ // have to return undefined because that cannot affect the result of
+ // FalsifyUndefined.)
+ return ComparisonOutcome(kComparisonTrue) |
+ ComparisonOutcome(kComparisonFalse);
}
- if (lhs->Min() >= rhs->Max()) return t->singleton_false;
- if (lhs->Max() < rhs->Min() &&
- !lhs->Maybe(Type::NaN()) && !rhs->Maybe(Type::NaN())) {
- return t->singleton_true;
+ // Add the undefined if we could see NaN.
+ if (lhs->Maybe(Type::NaN()) || rhs->Maybe(Type::NaN())) {
+ result |= kComparisonUndefined;
}
- return Type::Boolean();
+ return result;
}
@@ -809,7 +868,6 @@ Type* Typer::Visitor::JSGreaterThanOrEqualTyper(
Type* Typer::Visitor::JSBitwiseOrTyper(Type* lhs, Type* rhs, Typer* t) {
- Factory* f = t->isolate()->factory();
lhs = NumberToInt32(ToNumber(lhs, t), t);
rhs = NumberToInt32(ToNumber(rhs, t), t);
double lmin = lhs->Min();
@@ -837,13 +895,12 @@ Type* Typer::Visitor::JSBitwiseOrTyper(Type* lhs, Type* rhs, Typer* t) {
// value.
max = std::min(max, -1.0);
}
- return Type::Range(f->NewNumber(min), f->NewNumber(max), t->zone());
+ return Type::Range(min, max, t->zone());
// TODO(neis): Be precise for singleton inputs, here and elsewhere.
}
Type* Typer::Visitor::JSBitwiseAndTyper(Type* lhs, Type* rhs, Typer* t) {
- Factory* f = t->isolate()->factory();
lhs = NumberToInt32(ToNumber(lhs, t), t);
rhs = NumberToInt32(ToNumber(rhs, t), t);
double lmin = lhs->Min();
@@ -865,7 +922,7 @@ Type* Typer::Visitor::JSBitwiseAndTyper(Type* lhs, Type* rhs, Typer* t) {
min = 0;
max = std::min(max, rmax);
}
- return Type::Range(f->NewNumber(min), f->NewNumber(max), t->zone());
+ return Type::Range(min, max, t->zone());
}
@@ -878,12 +935,12 @@ Type* Typer::Visitor::JSBitwiseXorTyper(Type* lhs, Type* rhs, Typer* t) {
double rmax = rhs->Max();
if ((lmin >= 0 && rmin >= 0) || (lmax < 0 && rmax < 0)) {
// Xor-ing negative or non-negative values results in a non-negative value.
- return Type::NonNegativeSigned32();
+ return Type::Unsigned31();
}
if ((lmax < 0 && rmin >= 0) || (lmin >= 0 && rmax < 0)) {
// Xor-ing a negative and a non-negative value results in a negative value.
// TODO(jarin) Use a range here.
- return Type::NegativeSigned32();
+ return Type::Negative32();
}
return Type::Signed32();
}
@@ -903,11 +960,17 @@ Type* Typer::Visitor::JSShiftRightTyper(Type* lhs, Type* rhs, Typer* t) {
// Right-shifting a non-negative value cannot make it negative, nor larger.
min = std::max(min, 0.0);
max = std::min(max, lhs->Max());
+ if (rhs->Min() > 0 && rhs->Max() <= 31) {
+ max = static_cast<int>(max) >> static_cast<int>(rhs->Min());
+ }
}
if (lhs->Max() < 0) {
// Right-shifting a negative value cannot make it non-negative, nor smaller.
min = std::max(min, lhs->Min());
max = std::min(max, -1.0);
+ if (rhs->Min() > 0 && rhs->Max() <= 31) {
+ min = static_cast<int>(min) >> static_cast<int>(rhs->Min());
+ }
}
if (rhs->Min() > 0 && rhs->Max() <= 31) {
// Right-shifting by a positive value yields a small integer value.
@@ -919,8 +982,7 @@ Type* Typer::Visitor::JSShiftRightTyper(Type* lhs, Type* rhs, Typer* t) {
// TODO(jarin) Ideally, the following micro-optimization should be performed
// by the type constructor.
if (max != Type::Signed32()->Max() || min != Type::Signed32()->Min()) {
- Factory* f = t->isolate()->factory();
- return Type::Range(f->NewNumber(min), f->NewNumber(max), t->zone());
+ return Type::Range(min, max, t->zone());
}
return Type::Signed32();
}
@@ -928,11 +990,8 @@ Type* Typer::Visitor::JSShiftRightTyper(Type* lhs, Type* rhs, Typer* t) {
Type* Typer::Visitor::JSShiftRightLogicalTyper(Type* lhs, Type* rhs, Typer* t) {
lhs = NumberToUint32(ToNumber(lhs, t), t);
- Factory* f = t->isolate()->factory();
// Logical right-shifting any value cannot make it larger.
- Handle<Object> min = f->NewNumber(0);
- Handle<Object> max = f->NewNumber(lhs->Max());
- return Type::Range(min, max, t->zone());
+ return Type::Range(0.0, lhs->Max(), t->zone());
}
@@ -974,10 +1033,10 @@ static double array_max(double a[], size_t n) {
Type* Typer::Visitor::JSAddRanger(Type::RangeType* lhs, Type::RangeType* rhs,
Typer* t) {
double results[4];
- results[0] = lhs->Min()->Number() + rhs->Min()->Number();
- results[1] = lhs->Min()->Number() + rhs->Max()->Number();
- results[2] = lhs->Max()->Number() + rhs->Min()->Number();
- results[3] = lhs->Max()->Number() + rhs->Max()->Number();
+ results[0] = lhs->Min() + rhs->Min();
+ results[1] = lhs->Min() + rhs->Max();
+ results[2] = lhs->Max() + rhs->Min();
+ results[3] = lhs->Max() + rhs->Max();
// Since none of the inputs can be -0, the result cannot be -0 either.
// However, it can be nan (the sum of two infinities of opposite sign).
// On the other hand, if none of the "results" above is nan, then the actual
@@ -987,9 +1046,8 @@ Type* Typer::Visitor::JSAddRanger(Type::RangeType* lhs, Type::RangeType* rhs,
if (std::isnan(results[i])) ++nans;
}
if (nans == 4) return Type::NaN(); // [-inf..-inf] + [inf..inf] or vice versa
- Factory* f = t->isolate()->factory();
- Type* range = Type::Range(f->NewNumber(array_min(results, 4)),
- f->NewNumber(array_max(results, 4)), t->zone());
+ Type* range =
+ Type::Range(array_min(results, 4), array_max(results, 4), t->zone());
return nans == 0 ? range : Type::Union(range, Type::NaN(), t->zone());
// Examples:
// [-inf, -inf] + [+inf, +inf] = NaN
@@ -1023,10 +1081,10 @@ Type* Typer::Visitor::JSAddTyper(Type* lhs, Type* rhs, Typer* t) {
Type* Typer::Visitor::JSSubtractRanger(Type::RangeType* lhs,
Type::RangeType* rhs, Typer* t) {
double results[4];
- results[0] = lhs->Min()->Number() - rhs->Min()->Number();
- results[1] = lhs->Min()->Number() - rhs->Max()->Number();
- results[2] = lhs->Max()->Number() - rhs->Min()->Number();
- results[3] = lhs->Max()->Number() - rhs->Max()->Number();
+ results[0] = lhs->Min() - rhs->Min();
+ results[1] = lhs->Min() - rhs->Max();
+ results[2] = lhs->Max() - rhs->Min();
+ results[3] = lhs->Max() - rhs->Max();
// Since none of the inputs can be -0, the result cannot be -0.
// However, it can be nan (the subtraction of two infinities of same sign).
// On the other hand, if none of the "results" above is nan, then the actual
@@ -1036,9 +1094,8 @@ Type* Typer::Visitor::JSSubtractRanger(Type::RangeType* lhs,
if (std::isnan(results[i])) ++nans;
}
if (nans == 4) return Type::NaN(); // [inf..inf] - [inf..inf] (all same sign)
- Factory* f = t->isolate()->factory();
- Type* range = Type::Range(f->NewNumber(array_min(results, 4)),
- f->NewNumber(array_max(results, 4)), t->zone());
+ Type* range =
+ Type::Range(array_min(results, 4), array_max(results, 4), t->zone());
return nans == 0 ? range : Type::Union(range, Type::NaN(), t->zone());
// Examples:
// [-inf, +inf] - [-inf, +inf] = [-inf, +inf] \/ NaN
@@ -1062,10 +1119,10 @@ Type* Typer::Visitor::JSSubtractTyper(Type* lhs, Type* rhs, Typer* t) {
Type* Typer::Visitor::JSMultiplyRanger(Type::RangeType* lhs,
Type::RangeType* rhs, Typer* t) {
double results[4];
- double lmin = lhs->Min()->Number();
- double lmax = lhs->Max()->Number();
- double rmin = rhs->Min()->Number();
- double rmax = rhs->Max()->Number();
+ double lmin = lhs->Min();
+ double lmax = lhs->Max();
+ double rmin = rhs->Min();
+ double rmax = rhs->Max();
results[0] = lmin * rmin;
results[1] = lmin * rmax;
results[2] = lmax * rmin;
@@ -1081,9 +1138,8 @@ Type* Typer::Visitor::JSMultiplyRanger(Type::RangeType* lhs,
if (maybe_nan) return t->weakint; // Giving up.
bool maybe_minuszero = (lhs->Maybe(t->singleton_zero) && rmin < 0) ||
(rhs->Maybe(t->singleton_zero) && lmin < 0);
- Factory* f = t->isolate()->factory();
- Type* range = Type::Range(f->NewNumber(array_min(results, 4)),
- f->NewNumber(array_max(results, 4)), t->zone());
+ Type* range =
+ Type::Range(array_min(results, 4), array_max(results, 4), t->zone());
return maybe_minuszero ? Type::Union(range, Type::MinusZero(), t->zone())
: range;
}
@@ -1116,10 +1172,10 @@ Type* Typer::Visitor::JSDivideTyper(Type* lhs, Type* rhs, Typer* t) {
Type* Typer::Visitor::JSModulusRanger(Type::RangeType* lhs,
Type::RangeType* rhs, Typer* t) {
- double lmin = lhs->Min()->Number();
- double lmax = lhs->Max()->Number();
- double rmin = rhs->Min()->Number();
- double rmax = rhs->Max()->Number();
+ double lmin = lhs->Min();
+ double lmax = lhs->Max();
+ double rmin = rhs->Min();
+ double rmax = rhs->Max();
double labs = std::max(std::abs(lmin), std::abs(lmax));
double rabs = std::max(std::abs(rmin), std::abs(rmax)) - 1;
@@ -1140,8 +1196,7 @@ Type* Typer::Visitor::JSModulusRanger(Type::RangeType* lhs,
maybe_minus_zero = true;
}
- Factory* f = t->isolate()->factory();
- Type* result = Type::Range(f->NewNumber(omin), f->NewNumber(omax), t->zone());
+ Type* result = Type::Range(omin, omax, t->zone());
if (maybe_minus_zero)
result = Type::Union(result, Type::MinusZero(), t->zone());
return result;
@@ -1248,43 +1303,53 @@ Bounds Typer::Visitor::TypeJSLoadNamed(Node* node) {
// in the graph. In the current implementation, we are
// increasing the limits to the closest power of two.
Type* Typer::Visitor::Weaken(Type* current_type, Type* previous_type) {
- Type::RangeType* previous = previous_type->GetRange();
- Type::RangeType* current = current_type->GetRange();
- if (previous != NULL && current != NULL) {
- double current_min = current->Min()->Number();
- Handle<Object> new_min = current->Min();
-
- // Find the closest lower entry in the list of allowed
- // minima (or negative infinity if there is no such entry).
- if (current_min != previous->Min()->Number()) {
- new_min = typer_->integer->AsRange()->Min();
- for (const auto val : typer_->weaken_min_limits_) {
- if (val->Number() <= current_min) {
- new_min = val;
- break;
- }
+ // If the types have nothing to do with integers, return the types.
+ if (!current_type->Maybe(typer_->integer) ||
+ !previous_type->Maybe(typer_->integer)) {
+ return current_type;
+ }
+
+ Type* previous_number =
+ Type::Intersect(previous_type, typer_->integer, zone());
+ Type* current_number = Type::Intersect(current_type, typer_->integer, zone());
+ if (!current_number->IsRange() || !previous_number->IsRange()) {
+ return current_type;
+ }
+
+ Type::RangeType* previous = previous_number->AsRange();
+ Type::RangeType* current = current_number->AsRange();
+
+ double current_min = current->Min();
+ double new_min = current_min;
+ // Find the closest lower entry in the list of allowed
+ // minima (or negative infinity if there is no such entry).
+ if (current_min != previous->Min()) {
+ new_min = typer_->integer->AsRange()->Min();
+ for (const auto val : typer_->weaken_min_limits_) {
+ if (val <= current_min) {
+ new_min = val;
+ break;
}
}
+ }
- double current_max = current->Max()->Number();
- Handle<Object> new_max = current->Max();
- // Find the closest greater entry in the list of allowed
- // maxima (or infinity if there is no such entry).
- if (current_max != previous->Max()->Number()) {
- new_max = typer_->integer->AsRange()->Max();
- for (const auto val : typer_->weaken_max_limits_) {
- if (val->Number() >= current_max) {
- new_max = val;
- break;
- }
+ double current_max = current->Max();
+ double new_max = current_max;
+ // Find the closest greater entry in the list of allowed
+ // maxima (or infinity if there is no such entry).
+ if (current_max != previous->Max()) {
+ new_max = typer_->integer->AsRange()->Max();
+ for (const auto val : typer_->weaken_max_limits_) {
+ if (val >= current_max) {
+ new_max = val;
+ break;
}
}
-
- return Type::Union(current_type,
- Type::Range(new_min, new_max, typer_->zone()),
- typer_->zone());
}
- return current_type;
+
+ return Type::Union(current_type,
+ Type::Range(new_min, new_max, typer_->zone()),
+ typer_->zone());
}
@@ -1368,40 +1433,45 @@ Bounds Typer::Visitor::TypeJSStoreContext(Node* node) {
}
+Bounds Typer::Visitor::WrapContextBoundsForInput(Node* node) {
+ Bounds outer = BoundsOrNone(NodeProperties::GetContextInput(node));
+ if (outer.upper->Is(Type::None())) {
+ return Bounds(Type::None());
+ } else {
+ DCHECK(outer.upper->Maybe(Type::Internal()));
+ return Bounds(Type::Context(outer.upper, zone()));
+ }
+}
+
+
Bounds Typer::Visitor::TypeJSCreateFunctionContext(Node* node) {
- Bounds outer = ContextOperand(node);
- return Bounds(Type::Context(outer.upper, zone()));
+ return WrapContextBoundsForInput(node);
}
Bounds Typer::Visitor::TypeJSCreateCatchContext(Node* node) {
- Bounds outer = ContextOperand(node);
- return Bounds(Type::Context(outer.upper, zone()));
+ return WrapContextBoundsForInput(node);
}
Bounds Typer::Visitor::TypeJSCreateWithContext(Node* node) {
- Bounds outer = ContextOperand(node);
- return Bounds(Type::Context(outer.upper, zone()));
+ return WrapContextBoundsForInput(node);
}
Bounds Typer::Visitor::TypeJSCreateBlockContext(Node* node) {
- Bounds outer = ContextOperand(node);
- return Bounds(Type::Context(outer.upper, zone()));
+ return WrapContextBoundsForInput(node);
}
Bounds Typer::Visitor::TypeJSCreateModuleContext(Node* node) {
// TODO(rossberg): this is probably incorrect
- Bounds outer = ContextOperand(node);
- return Bounds(Type::Context(outer.upper, zone()));
+ return WrapContextBoundsForInput(node);
}
Bounds Typer::Visitor::TypeJSCreateScriptContext(Node* node) {
- Bounds outer = ContextOperand(node);
- return Bounds(Type::Context(outer.upper, zone()));
+ return WrapContextBoundsForInput(node);
}
@@ -1429,6 +1499,16 @@ Bounds Typer::Visitor::TypeJSCallFunction(Node* node) {
Bounds Typer::Visitor::TypeJSCallRuntime(Node* node) {
+ switch (CallRuntimeParametersOf(node->op()).id()) {
+ case Runtime::kInlineIsSmi:
+ case Runtime::kInlineIsNonNegativeSmi:
+ case Runtime::kInlineIsArray:
+ case Runtime::kInlineIsFunction:
+ case Runtime::kInlineIsRegExp:
+ return Bounds(Type::None(zone()), Type::Boolean(zone()));
+ default:
+ break;
+ }
return Bounds::Unbounded(zone());
}
@@ -1452,7 +1532,7 @@ Bounds Typer::Visitor::TypeBooleanNot(Node* node) {
Bounds Typer::Visitor::TypeBooleanToNumber(Node* node) {
- return Bounds(Type::None(zone()), typer_->zero_or_one);
+ return TypeUnaryOp(node, ToNumber);
}
@@ -1506,6 +1586,11 @@ Bounds Typer::Visitor::TypeNumberToUint32(Node* node) {
}
+Bounds Typer::Visitor::TypePlainPrimitiveToNumber(Node* node) {
+ return TypeUnaryOp(node, ToNumber);
+}
+
+
Bounds Typer::Visitor::TypeReferenceEqual(Node* node) {
return Bounds(Type::None(zone()), Type::Boolean(zone()));
}
@@ -1608,9 +1693,8 @@ Bounds Typer::Visitor::TypeChangeBoolToBit(Node* node) {
Bounds Typer::Visitor::TypeChangeBitToBool(Node* node) {
Bounds arg = Operand(node, 0);
// TODO(neis): DCHECK(arg.upper->Is(Type::Boolean()));
- return Bounds(
- ChangeRepresentation(arg.lower, Type::TaggedPointer(), zone()),
- ChangeRepresentation(arg.upper, Type::TaggedPointer(), zone()));
+ return Bounds(ChangeRepresentation(arg.lower, Type::TaggedPointer(), zone()),
+ ChangeRepresentation(arg.upper, Type::TaggedPointer(), zone()));
}