Version 1.8.6
svn merge -c 43014 https://dart.googlecode.com/svn/branches/bleeding_edge 1.8
svn merge -c 42396 https://dart.googlecode.com/svn/branches/bleeding_edge 1.8
svn merge -c 44046 https://dart.googlecode.com/svn/branches/bleeding_edge 1.8 --accept working
R=vegorov@google.com
Review URL: https://codereview.chromium.org//963483002
git-svn-id: http://dart.googlecode.com/svn/branches/1.8@44048 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/runtime/vm/flow_graph_compiler.cc b/runtime/vm/flow_graph_compiler.cc
index 5bb8e09..adf62e1 100644
--- a/runtime/vm/flow_graph_compiler.cc
+++ b/runtime/vm/flow_graph_compiler.cc
@@ -685,57 +685,11 @@
// corresponding spill slot locations.
for (Environment::DeepIterator it(env); !it.Done(); it.Advance()) {
Location loc = it.CurrentLocation();
- if (loc.IsRegister()) {
- intptr_t index = cpu_reg_slots[loc.reg()];
- ASSERT(index >= 0);
- it.SetCurrentLocation(Location::StackSlot(index));
- } else if (loc.IsFpuRegister()) {
- intptr_t index = fpu_reg_slots[loc.fpu_reg()];
- ASSERT(index >= 0);
- Value* value = it.CurrentValue();
- switch (value->definition()->representation()) {
- case kUnboxedDouble:
- it.SetCurrentLocation(Location::DoubleStackSlot(index));
- break;
- case kUnboxedFloat32x4:
- case kUnboxedInt32x4:
- case kUnboxedFloat64x2:
- it.SetCurrentLocation(Location::QuadStackSlot(index));
- break;
- default:
- UNREACHABLE();
- }
- } else if (loc.IsPairLocation()) {
- intptr_t representation =
- it.CurrentValue()->definition()->representation();
- ASSERT(representation == kUnboxedMint);
- PairLocation* value_pair = loc.AsPairLocation();
- intptr_t index_lo;
- intptr_t index_hi;
- if (value_pair->At(0).IsRegister()) {
- index_lo = cpu_reg_slots[value_pair->At(0).reg()];
- } else {
- ASSERT(value_pair->At(0).IsStackSlot());
- index_lo = value_pair->At(0).stack_index();
- }
- if (value_pair->At(1).IsRegister()) {
- index_hi = cpu_reg_slots[value_pair->At(1).reg()];
- } else {
- ASSERT(value_pair->At(1).IsStackSlot());
- index_hi = value_pair->At(1).stack_index();
- }
- it.SetCurrentLocation(Location::Pair(Location::StackSlot(index_lo),
- Location::StackSlot(index_hi)));
- } else if (loc.IsInvalid()) {
- Definition* def =
- it.CurrentValue()->definition();
- ASSERT(def != NULL);
- if (def->IsMaterializeObject()) {
- def->AsMaterializeObject()->RemapRegisters(fpu_reg_slots,
- cpu_reg_slots);
- }
- }
+ Value* value = it.CurrentValue();
+ it.SetCurrentLocation(loc.RemapForSlowPath(
+ value->definition(), cpu_reg_slots, fpu_reg_slots));
}
+
return env;
}
diff --git a/runtime/vm/flow_graph_range_analysis.cc b/runtime/vm/flow_graph_range_analysis.cc
index d4f192a..c752e93 100644
--- a/runtime/vm/flow_graph_range_analysis.cc
+++ b/runtime/vm/flow_graph_range_analysis.cc
@@ -2540,12 +2540,22 @@
((left_max == 0) || (right_max <= kMaxInt64 / left_max))) {
// Product of left and right max values stays in 64 bit range.
const int64_t mul_max = left_max * right_max;
- const int64_t r_min =
- OnlyPositiveOrZero(*left_range, *right_range) ? 0 : -mul_max;
- *result_min = RangeBoundary::FromConstant(r_min);
- const int64_t r_max =
- OnlyNegativeOrZero(*left_range, *right_range) ? 0 : mul_max;
- *result_max = RangeBoundary::FromConstant(r_max);
+ if (OnlyPositiveOrZero(*left_range, *right_range) ||
+ OnlyNegativeOrZero(*left_range, *right_range)) {
+ // If both ranges are of the same sign then the range of the result
+ // is positive and is between multiplications of absolute minimums
+ // and absolute maximums.
+ const int64_t mul_min =
+ ConstantAbsMin(left_range) * ConstantAbsMin(right_range);
+ *result_min = RangeBoundary::FromConstant(mul_min);
+ *result_max = RangeBoundary::FromConstant(mul_max);
+ } else {
+ // If ranges have mixed signs then use conservative approximation:
+ // absolute value of the result is less or equal to multiplication
+ // of absolute maximums.
+ *result_min = RangeBoundary::FromConstant(-mul_max);
+ *result_max = RangeBoundary::FromConstant(mul_max);
+ }
return;
}
@@ -2585,6 +2595,17 @@
}
+// Return the minimum absolute value included in range.
+int64_t Range::ConstantAbsMin(const Range* range) {
+ if (range == NULL) {
+ return 0;
+ }
+ const int64_t abs_min = Utils::Abs(Range::ConstantMin(range).ConstantValue());
+ const int64_t abs_max = Utils::Abs(Range::ConstantMax(range).ConstantValue());
+ return Utils::Minimum(abs_min, abs_max);
+}
+
+
void Range::BinaryOp(const Token::Kind op,
const Range* left_range,
const Range* right_range,
diff --git a/runtime/vm/flow_graph_range_analysis.h b/runtime/vm/flow_graph_range_analysis.h
index 3b39ba2..7ab76a0 100644
--- a/runtime/vm/flow_graph_range_analysis.h
+++ b/runtime/vm/flow_graph_range_analysis.h
@@ -473,6 +473,9 @@
// Return the maximum absolute value included in range.
static int64_t ConstantAbsMax(const Range* range);
+ // Return the minimum absolute value included in range.
+ static int64_t ConstantAbsMin(const Range* range);
+
static void BinaryOp(const Token::Kind op,
const Range* left_range,
const Range* right_range,
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc
index 8040c50..2a05f0d 100644
--- a/runtime/vm/intermediate_language.cc
+++ b/runtime/vm/intermediate_language.cc
@@ -191,7 +191,7 @@
ASSERT(IsDenseSwitch());
intptr_t mask = 0;
for (intptr_t i = 0; i < cids_.length(); ++i) {
- mask |= 1 << (cids_[i] - cids_[0]);
+ mask |= static_cast<intptr_t>(1) << (cids_[i] - cids_[0]);
}
return mask;
}
@@ -2632,42 +2632,16 @@
// This function should be kept in sync with
// FlowGraphCompiler::SlowPathEnvironmentFor().
-void MaterializeObjectInstr::RemapRegisters(intptr_t* fpu_reg_slots,
- intptr_t* cpu_reg_slots) {
+void MaterializeObjectInstr::RemapRegisters(intptr_t* cpu_reg_slots,
+ intptr_t* fpu_reg_slots) {
if (registers_remapped_) {
return;
}
registers_remapped_ = true;
for (intptr_t i = 0; i < InputCount(); i++) {
- Location loc = LocationAt(i);
- if (loc.IsRegister()) {
- intptr_t index = cpu_reg_slots[loc.reg()];
- ASSERT(index >= 0);
- locations_[i] = Location::StackSlot(index);
- } else if (loc.IsFpuRegister()) {
- intptr_t index = fpu_reg_slots[loc.fpu_reg()];
- ASSERT(index >= 0);
- Value* value = InputAt(i);
- switch (value->definition()->representation()) {
- case kUnboxedDouble:
- locations_[i] = Location::DoubleStackSlot(index);
- break;
- case kUnboxedFloat32x4:
- case kUnboxedInt32x4:
- case kUnboxedFloat64x2:
- locations_[i] = Location::QuadStackSlot(index);
- break;
- default:
- UNREACHABLE();
- }
- } else if (loc.IsPairLocation()) {
- UNREACHABLE();
- } else if (loc.IsInvalid() &&
- InputAt(i)->definition()->IsMaterializeObject()) {
- InputAt(i)->definition()->AsMaterializeObject()->RemapRegisters(
- fpu_reg_slots, cpu_reg_slots);
- }
+ locations_[i] = LocationAt(i).RemapForSlowPath(
+ InputAt(i)->definition(), cpu_reg_slots, fpu_reg_slots);
}
}
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
index b877e93..5552b74 100644
--- a/runtime/vm/intermediate_language.h
+++ b/runtime/vm/intermediate_language.h
@@ -3926,8 +3926,8 @@
virtual bool MayThrow() const { return false; }
- void RemapRegisters(intptr_t* fpu_reg_slots,
- intptr_t* cpu_reg_slots);
+ void RemapRegisters(intptr_t* cpu_reg_slots,
+ intptr_t* fpu_reg_slots);
bool was_visited_for_liveness() const { return visited_for_liveness_; }
void mark_visited_for_liveness() {
diff --git a/runtime/vm/locations.cc b/runtime/vm/locations.cc
index 0951aa9..2419594 100644
--- a/runtime/vm/locations.cc
+++ b/runtime/vm/locations.cc
@@ -244,6 +244,59 @@
}
+Location Location::RemapForSlowPath(Definition* def,
+ intptr_t* cpu_reg_slots,
+ intptr_t* fpu_reg_slots) const {
+ if (IsRegister()) {
+ intptr_t index = cpu_reg_slots[reg()];
+ ASSERT(index >= 0);
+ return Location::StackSlot(index);
+ } else if (IsFpuRegister()) {
+ intptr_t index = fpu_reg_slots[fpu_reg()];
+ ASSERT(index >= 0);
+ switch (def->representation()) {
+ case kUnboxedDouble:
+ return Location::DoubleStackSlot(index);
+
+ case kUnboxedFloat32x4:
+ case kUnboxedInt32x4:
+ case kUnboxedFloat64x2:
+ return Location::QuadStackSlot(index);
+
+ default:
+ UNREACHABLE();
+ }
+ } else if (IsPairLocation()) {
+ ASSERT(def->representation() == kUnboxedMint);
+ PairLocation* value_pair = AsPairLocation();
+ intptr_t index_lo;
+ intptr_t index_hi;
+
+ if (value_pair->At(0).IsRegister()) {
+ index_lo = cpu_reg_slots[value_pair->At(0).reg()];
+ } else {
+ ASSERT(value_pair->At(0).IsStackSlot());
+ index_lo = value_pair->At(0).stack_index();
+ }
+
+ if (value_pair->At(1).IsRegister()) {
+ index_hi = cpu_reg_slots[value_pair->At(1).reg()];
+ } else {
+ ASSERT(value_pair->At(1).IsStackSlot());
+ index_hi = value_pair->At(1).stack_index();
+ }
+
+ return Location::Pair(Location::StackSlot(index_lo),
+ Location::StackSlot(index_hi));
+ } else if (IsInvalid() && def->IsMaterializeObject()) {
+ def->AsMaterializeObject()->RemapRegisters(cpu_reg_slots, fpu_reg_slots);
+ return *this;
+ }
+
+ return *this;
+}
+
+
void LocationSummary::PrintTo(BufferFormatter* f) const {
if (input_count() > 0) {
f->Print(" (");
diff --git a/runtime/vm/locations.h b/runtime/vm/locations.h
index e4bf340..0b9bf50 100644
--- a/runtime/vm/locations.h
+++ b/runtime/vm/locations.h
@@ -11,10 +11,12 @@
namespace dart {
+
class BufferFormatter;
-class Value;
-class PairLocation;
class ConstantInstr;
+class Definition;
+class PairLocation;
+class Value;
enum Representation {
@@ -370,6 +372,10 @@
Location Copy() const;
+ Location RemapForSlowPath(Definition* def,
+ intptr_t* cpu_reg_slots,
+ intptr_t* fpu_reg_slots) const;
+
private:
explicit Location(uword value) : value_(value) { }
diff --git a/tests/language/vm/optimized_check_class_test.dart b/tests/language/vm/optimized_check_class_test.dart
new file mode 100644
index 0000000..c1e32bf
--- /dev/null
+++ b/tests/language/vm/optimized_check_class_test.dart
@@ -0,0 +1,70 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--optimization-counter-threshold=10 --no-use-osr
+
+import "package:expect/expect.dart";
+
+// Test dense class-id checks. Regression test for issue 22104.
+
+class A {
+ toString() => "an A";
+}
+
+class A1 extends A { }
+class A2 extends A { }
+class A3 extends A { }
+class A4 extends A { toString() => "ha"; }
+class A5 extends A { }
+class A6 extends A { }
+class A7 extends A { }
+class A8 extends A { }
+class A9 extends A { }
+class A10 extends A { }
+class A11 extends A { }
+class A12 extends A { }
+class A13 extends A { }
+class A14 extends A { }
+class A15 extends A { }
+class A16 extends A { }
+class A17 extends A { }
+class A18 extends A { }
+class A19 extends A { }
+class A20 extends A { }
+class A21 extends A { }
+class A22 extends A { }
+class A23 extends A { }
+class A24 extends A { }
+class A25 extends A { }
+class A26 extends A { }
+class A27 extends A { }
+class A28 extends A { }
+class A29 extends A { }
+class A30 extends A { }
+class A31 extends A { }
+class A32 extends A { }
+class A33 extends A { }
+class A34 extends A { }
+class A35 extends A { }
+class A36 extends A { }
+
+test_class_check(e) => e.toString();
+
+main() {
+ var list = [
+ new A1(),
+ new A2(),
+ new A11(),
+ new A36()
+ ];
+ for (var i = 0; i < list.length; i++) {
+ test_class_check(list[i]);
+ }
+ for (var i = 0; i < 100; i++) {
+ Expect.equals("an A", test_class_check(new A1()));
+ }
+ Expect.equals("ha", test_class_check(new A4()));
+}
+
+
+
diff --git a/tests/language/vm/regress_22541_vm_test.dart b/tests/language/vm/regress_22541_vm_test.dart
new file mode 100644
index 0000000..36b4618
--- /dev/null
+++ b/tests/language/vm/regress_22541_vm_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Test range inference for multiplication of two negative values.
+// VMOptions=--optimization-counter-threshold=10 --no-use-osr
+
+import 'package:expect/expect.dart';
+
+test(a) {
+ var x = a ? -1 : -2;
+ if (0 < (x * x)) {
+ return "ok";
+ } else {
+ return "fail";
+ }
+}
+
+main() {
+ for (var j = 0; j < 20; j++) {
+ Expect.equals("ok", test(false));
+ }
+}
diff --git a/tests/standalone/pair_location_remapping_test.dart b/tests/standalone/pair_location_remapping_test.dart
new file mode 100644
index 0000000..277ccc5
--- /dev/null
+++ b/tests/standalone/pair_location_remapping_test.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Test that pair locations are remaped in slow path environments.
+// VMOptions=--optimization_counter_threshold=10 --no-use-osr
+
+import "package:expect/expect.dart";
+
+class A {
+ final f;
+ A(this.f);
+}
+
+foo(i) {
+ var j = 0x7fffffffffffffff + i;
+ var c = new A(j); // allocation will be sunk
+ var r = 0;
+ for (var k = 0; k < 10; k++) {
+ if ((j & (1 << k)) != 0) {
+ r++;
+ }
+ }
+ return c.f - r;
+}
+
+main() {
+ for (var i = 0; i < 1000; i++) {
+ Expect.equals(0x7fffffffffffffff - 10, foo(0));
+ }
+}
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status
index d51d56e..a9ebe42 100644
--- a/tests/standalone/standalone.status
+++ b/tests/standalone/standalone.status
@@ -88,6 +88,7 @@
javascript_compatibility_errors_test: Skip
javascript_compatibility_warnings_test: Skip
unboxed_int_converter_test: Skip
+pair_location_remapping_test: Skip
[ $compiler == dart2js && $jscl ]
assert_test: RuntimeError, OK # Assumes unspecified fields on the AssertionError.
diff --git a/tools/VERSION b/tools/VERSION
index ad37b7d..3a08bad 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -26,6 +26,6 @@
CHANNEL stable
MAJOR 1
MINOR 8
-PATCH 5
+PATCH 6
PRERELEASE 0
PRERELEASE_PATCH 0