Commit 4c1f4b79 authored by Jaroslav Sevcik's avatar Jaroslav Sevcik

[turbofan] Weakening of types must weaken ranges inside unions.

BUG=
R=rossberg@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#25311}
parent d7f8ea2c
...@@ -1119,10 +1119,9 @@ Bounds Typer::Visitor::TypeJSLoadNamed(Node* node) { ...@@ -1119,10 +1119,9 @@ Bounds Typer::Visitor::TypeJSLoadNamed(Node* node) {
// in the graph. In the current implementation, we are // in the graph. In the current implementation, we are
// increasing the limits to the closest power of two. // increasing the limits to the closest power of two.
Type* Typer::Visitor::Weaken(Type* current_type, Type* previous_type) { Type* Typer::Visitor::Weaken(Type* current_type, Type* previous_type) {
if (current_type->IsRange() && previous_type->IsRange()) { Type::RangeType* previous = previous_type->GetRange();
Type::RangeType* previous = previous_type->AsRange(); Type::RangeType* current = current_type->GetRange();
Type::RangeType* current = current_type->AsRange(); if (previous != NULL && current != NULL) {
double current_min = current->Min()->Number(); double current_min = current->Min()->Number();
Handle<Object> new_min = current->Min(); Handle<Object> new_min = current->Min();
...@@ -1152,7 +1151,9 @@ Type* Typer::Visitor::Weaken(Type* current_type, Type* previous_type) { ...@@ -1152,7 +1151,9 @@ Type* Typer::Visitor::Weaken(Type* current_type, Type* previous_type) {
} }
} }
return Type::Range(new_min, new_max, typer_->zone()); return Type::Union(current_type,
Type::Range(new_min, new_max, typer_->zone()),
typer_->zone());
} }
return current_type; return current_type;
} }
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include <iomanip>
#include "src/types.h" #include "src/types.h"
#include "src/ostreams.h" #include "src/ostreams.h"
...@@ -1017,8 +1019,12 @@ void TypeImpl<Config>::PrintTo(std::ostream& os, PrintDimension dim) { ...@@ -1017,8 +1019,12 @@ void TypeImpl<Config>::PrintTo(std::ostream& os, PrintDimension dim) {
} else if (this->IsConstant()) { } else if (this->IsConstant()) {
os << "Constant(" << Brief(*this->AsConstant()->Value()) << ")"; os << "Constant(" << Brief(*this->AsConstant()->Value()) << ")";
} else if (this->IsRange()) { } else if (this->IsRange()) {
os << "Range(" << this->AsRange()->Min()->Number() std::ostream::fmtflags saved_flags = os.setf(std::ios::fixed);
<< ", " << this->AsRange()->Max()->Number() << ")"; std::streamsize saved_precision = os.precision(0);
os << "Range(" << this->AsRange()->Min()->Number() << ", "
<< this->AsRange()->Max()->Number() << ")";
os.flags(saved_flags);
os.precision(saved_precision);
} else if (this->IsContext()) { } else if (this->IsContext()) {
os << "Context("; os << "Context(";
this->AsContext()->Outer()->PrintTo(os, dim); this->AsContext()->Outer()->PrintTo(os, dim);
......
...@@ -464,6 +464,11 @@ class TypeImpl : public Config::Base { ...@@ -464,6 +464,11 @@ class TypeImpl : public Config::Base {
double Min(); double Min();
double Max(); double Max();
// Extracts a range from the type. If the type is a range, it just
// returns it; if it is a union, it returns the range component.
// Note that it does not contain range for constants.
RangeType* GetRange();
int NumClasses(); int NumClasses();
int NumConstants(); int NumConstants();
...@@ -551,7 +556,6 @@ class TypeImpl : public Config::Base { ...@@ -551,7 +556,6 @@ class TypeImpl : public Config::Base {
static bool Contains(RangeType* lhs, RangeType* rhs); static bool Contains(RangeType* lhs, RangeType* rhs);
static bool Contains(RangeType* range, i::Object* val); static bool Contains(RangeType* range, i::Object* val);
RangeType* GetRange();
static int UpdateRange( static int UpdateRange(
RangeHandle type, UnionHandle result, int size, Region* region); RangeHandle type, UnionHandle result, int size, Region* region);
......
...@@ -1831,6 +1831,48 @@ struct Tests : Rep { ...@@ -1831,6 +1831,48 @@ struct Tests : Rep {
*/ */
} }
TypeHandle RangeToHandle(typename Type::RangeType* range) {
return T.Range(range->Min(), range->Max());
}
void GetRange() {
// GetRange(Range(a, b)) = Range(a, b).
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
TypeHandle type1 = *it1;
if (type1->IsRange()) {
typename Type::RangeType* range = type1->GetRange();
CHECK(type1->Equals(RangeToHandle(range)));
}
}
// 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) {
TypeHandle type1 = *it1;
TypeHandle type2 = *it2;
if (type1->IsConstant() && type2->IsRange()) {
TypeHandle u = T.Union(type1, type2);
CHECK(type2->Equals(RangeToHandle(u->GetRange())));
}
}
}
// GetRange is monotone whenever it is defined.
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
TypeHandle type1 = *it1;
TypeHandle type2 = *it2;
if (type1->GetRange() != NULL && type2->GetRange() != NULL &&
type1->Is(type2)) {
TypeHandle r1 = RangeToHandle(type1->GetRange());
TypeHandle r2 = RangeToHandle(type2->GetRange());
CHECK(r1->Is(r2));
}
}
}
}
template<class Type2, class TypeHandle2, class Region2, class Rep2> template<class Type2, class TypeHandle2, class Region2, class Rep2>
void Convert() { void Convert() {
Types<Type2, TypeHandle2, Region2> T2( Types<Type2, TypeHandle2, Region2> T2(
...@@ -2030,6 +2072,13 @@ TEST(Distributivity) { ...@@ -2030,6 +2072,13 @@ TEST(Distributivity) {
} }
TEST(GetRange) {
CcTest::InitializeVM();
ZoneTests().GetRange();
HeapTests().GetRange();
}
TEST(Convert) { TEST(Convert) {
CcTest::InitializeVM(); CcTest::InitializeVM();
ZoneTests().Convert<HeapType, Handle<HeapType>, Isolate, HeapRep>(); ZoneTests().Convert<HeapType, Handle<HeapType>, Isolate, HeapRep>();
......
// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
function f() {
for (var j = 1; j < 1; j *= -8) {
}
for (var i = 1; i < 1; j += 2) {
j * -1;
}
}
f();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment