From: Jaroslav Sevcik Date: Thu, 13 Nov 2014 05:18:26 +0000 (+0100) Subject: [turbofan] Weakening of types must weaken ranges inside unions. X-Git-Tag: upstream/4.7.83~5729 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4c1f4b796d1c455fc6a023abe145a5e48c4b7b1f;p=platform%2Fupstream%2Fv8.git [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} --- diff --git a/src/compiler/typer.cc b/src/compiler/typer.cc index 97b43f4..20a39d9 100644 --- a/src/compiler/typer.cc +++ b/src/compiler/typer.cc @@ -1119,10 +1119,9 @@ 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) { - if (current_type->IsRange() && previous_type->IsRange()) { - Type::RangeType* previous = previous_type->AsRange(); - Type::RangeType* current = current_type->AsRange(); - + Type::RangeType* previous = previous_type->GetRange(); + Type::RangeType* current = current_type->GetRange(); + if (previous != NULL && current != NULL) { double current_min = current->Min()->Number(); Handle new_min = current->Min(); @@ -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; } diff --git a/src/types.cc b/src/types.cc index 162c35a..b423bee 100644 --- a/src/types.cc +++ b/src/types.cc @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include + #include "src/types.h" #include "src/ostreams.h" @@ -1017,8 +1019,12 @@ void TypeImpl::PrintTo(std::ostream& os, PrintDimension dim) { } else if (this->IsConstant()) { os << "Constant(" << Brief(*this->AsConstant()->Value()) << ")"; } else if (this->IsRange()) { - os << "Range(" << this->AsRange()->Min()->Number() - << ", " << this->AsRange()->Max()->Number() << ")"; + std::ostream::fmtflags saved_flags = os.setf(std::ios::fixed); + 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()) { os << "Context("; this->AsContext()->Outer()->PrintTo(os, dim); diff --git a/src/types.h b/src/types.h index 1d506d0..aafaf07 100644 --- a/src/types.h +++ b/src/types.h @@ -464,6 +464,11 @@ class TypeImpl : public Config::Base { double Min(); 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 NumConstants(); @@ -551,7 +556,6 @@ class TypeImpl : public Config::Base { static bool Contains(RangeType* lhs, RangeType* rhs); static bool Contains(RangeType* range, i::Object* val); - RangeType* GetRange(); static int UpdateRange( RangeHandle type, UnionHandle result, int size, Region* region); diff --git a/test/cctest/test-types.cc b/test/cctest/test-types.cc index e564c6c..ad46607 100644 --- a/test/cctest/test-types.cc +++ b/test/cctest/test-types.cc @@ -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 void Convert() { Types T2( @@ -2030,6 +2072,13 @@ TEST(Distributivity) { } +TEST(GetRange) { + CcTest::InitializeVM(); + ZoneTests().GetRange(); + HeapTests().GetRange(); +} + + TEST(Convert) { CcTest::InitializeVM(); ZoneTests().Convert, Isolate, HeapRep>(); diff --git a/test/mjsunit/regress/regress-weakening-multiplication.js b/test/mjsunit/regress/regress-weakening-multiplication.js new file mode 100644 index 0000000..dcf0011 --- /dev/null +++ b/test/mjsunit/regress/regress-weakening-multiplication.js @@ -0,0 +1,12 @@ +// 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();