[turbofan] Weakening of types must weaken ranges inside unions.
authorJaroslav Sevcik <jarin@chromium.org>
Thu, 13 Nov 2014 05:18:26 +0000 (06:18 +0100)
committerJaroslav Sevcik <jarin@chromium.org>
Thu, 13 Nov 2014 05:31:47 +0000 (05:31 +0000)
BUG=
R=rossberg@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#25311}

src/compiler/typer.cc
src/types.cc
src/types.h
test/cctest/test-types.cc
test/mjsunit/regress/regress-weakening-multiplication.js [new file with mode: 0644]

index 97b43f4..20a39d9 100644 (file)
@@ -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<Object> 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;
 }
index 162c35a..b423bee 100644 (file)
@@ -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 <iomanip>
+
 #include "src/types.h"
 
 #include "src/ostreams.h"
@@ -1017,8 +1019,12 @@ void TypeImpl<Config>::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);
index 1d506d0..aafaf07 100644 (file)
@@ -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);
 
index e564c6c..ad46607 100644 (file)
@@ -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>
   void Convert() {
     Types<Type2, TypeHandle2, Region2> T2(
@@ -2030,6 +2072,13 @@ TEST(Distributivity) {
 }
 
 
+TEST(GetRange) {
+  CcTest::InitializeVM();
+  ZoneTests().GetRange();
+  HeapTests().GetRange();
+}
+
+
 TEST(Convert) {
   CcTest::InitializeVM();
   ZoneTests().Convert<HeapType, Handle<HeapType>, Isolate, HeapRep>();
diff --git a/test/mjsunit/regress/regress-weakening-multiplication.js b/test/mjsunit/regress/regress-weakening-multiplication.js
new file mode 100644 (file)
index 0000000..dcf0011
--- /dev/null
@@ -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();