Version 1.2.0-dev.5.15

svn merge -c 32927 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 32951 https://dart.googlecode.com/svn/branches/bleeding_edge trunk

R=ricow@google.com

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

git-svn-id: http://dart.googlecode.com/svn/trunk@32954 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
index 4792747..ad93039 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
@@ -1817,6 +1817,8 @@
       handledBySpecialCase = true;
       if (input is HIs) {
         emitIs(input, '!==');
+      } else if (input is HNot) {
+        use(input.inputs[0]);
       } else if (input is HIdentity) {
         HIdentity identity = input;
         emitIdentityComparison(identity.left, identity.right, true);
@@ -1866,11 +1868,7 @@
     } else if (node.inputs[1].isConstantBoolean()) {
       String operation = node.inputs[1].isConstantFalse() ? '&&' : '||';
       if (operation == '||') {
-        if (input is HNot) {
-          use(input.inputs[0]);
-        } else {
-          generateNot(input);
-        }
+        generateNot(input);
       } else {
         use(input);
       }
diff --git a/tests/compiler/dart2js/dart2js.status b/tests/compiler/dart2js/dart2js.status
index 3bfe7a8..f73cebd 100644
--- a/tests/compiler/dart2js/dart2js.status
+++ b/tests/compiler/dart2js/dart2js.status
@@ -17,6 +17,8 @@
 mirrors/relation_assignable_test: Fail # Issue 16736
 mirrors/relation_subclass_test: Fail # Issue 16737
 
+logical_expression_test: Fail # Issue 17027
+
 [ $mode == debug ]
 mirror_final_field_inferrer2_test: Crash, Pass, Slow # dartbug.com/15581
 
diff --git a/tests/compiler/dart2js/logical_expression_test.dart b/tests/compiler/dart2js/logical_expression_test.dart
new file mode 100644
index 0000000..75d69e9
--- /dev/null
+++ b/tests/compiler/dart2js/logical_expression_test.dart
@@ -0,0 +1,47 @@
+// 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 logical or-expressions don't introduce unnecessary nots.
+
+import "package:async_helper/async_helper.dart";
+import 'compiler_helper.dart';
+
+const String TEST_ONE = r"""
+foo(bar, gee) {
+  bool cond1 = bar();
+  if (cond1 || gee()) gee();
+  if (cond1 || gee()) gee();
+}
+""";
+
+const String TEST_TWO = r"""
+void foo(list, bar) {
+  if (list == null) bar();
+  if (list == null || bar()) bar();
+  if (list == null || bar()) bar();
+}
+""";
+
+main() {
+  // We want something like:
+  //     var t1 = bar.call$0() === true;
+  //     if (t1 || gee.call$0() === true) gee.call$0();
+  //     if (t1 || gee.call$0() === true) gee.call$0();
+  compileAndDoNotMatchFuzzy(TEST_ONE, 'foo',
+                       r"""var x = [a-zA-Z0-9$.]+\(\) == true;
+                           if \(x \|\| [a-zA-Z0-9$.]+\(\) === true\) [^;]+;
+                           if \(x \|\| [a-zA-Z0-9$.]+\(\) === true\) [^;]+;""");
+
+
+  // We want something like:
+  //     var t1 = list == null;
+  //     if (t1) bar.call$0();
+  //     if (t1 || bar.call$0() === true) bar.call$0();
+  //     if (t1 || bar.call$0() === true) bar.call$0();
+  compileAndMatchFuzzy(TEST_TWO, 'foo',
+                       r"""var x = x == null;
+                           if \(x\) [^;]+;
+                           if \(x \|\| [a-zA-Z0-9$.]+\(\) === true\) [^;]+;
+                           if \(x \|\| [a-zA-Z0-9$.]+\(\) === true\) [^;]+;""");
+}
diff --git a/tests/language/logical_expression_test.dart b/tests/language/logical_expression_test.dart
new file mode 100644
index 0000000..e3dd195
--- /dev/null
+++ b/tests/language/logical_expression_test.dart
@@ -0,0 +1,119 @@
+// 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.
+// Dart test program for testing if statement.
+
+import "package:expect/expect.dart";
+
+// For logical-or conditions dart2js sometimes inlined expressions, leading to
+// completely broken programs.
+
+int globalCounter = 0;
+
+falseWithSideEffect() {
+  bool confuse() => new DateTime.now().millisecondsSinceEpoch == 42;
+
+  var result = confuse();
+
+  // Make it harder to inline.
+  if (result) {
+    try {
+      try {
+        if (confuse()) falseWithSideEffect();
+        if (confuse()) return 499;
+      } catch (e) {
+        rethrow;
+      }
+    } catch (e) {
+      rethrow;
+    }
+  }
+  globalCounter++;
+  return result;
+}
+
+falseWithoutSideEffect() {
+  bool confuse() => new DateTime.now().millisecondsSinceEpoch == 42;
+
+  var result = confuse();
+
+  // Make it harder to inline.
+  if (result) {
+    try {
+      try {
+        if (confuse()) falseWithSideEffect();
+        if (confuse()) return 499;
+      } catch (e) {
+        rethrow;
+      }
+    } catch (e) {
+      rethrow;
+    }
+  }
+  return result;
+}
+
+testLogicalOr() {
+  globalCounter = 0;
+  bool cond1 = falseWithSideEffect();
+  if (cond1 || falseWithoutSideEffect()) Expect.fail("must be false");
+  if (cond1 || falseWithoutSideEffect()) Expect.fail("must be false");
+  if (cond1 || falseWithoutSideEffect()) Expect.fail("must be false");
+  Expect.equals(1, globalCounter);
+
+  cond1 = (falseWithSideEffect() == 499);
+  if (cond1 || falseWithoutSideEffect()) Expect.fail("must be false");
+  if (cond1 || falseWithoutSideEffect()) Expect.fail("must be false");
+  if (cond1 || falseWithoutSideEffect()) Expect.fail("must be false");
+  Expect.equals(2, globalCounter);
+}
+
+List globalList = [];
+void testLogicalOr2() {
+  globalList.clear();
+  testValueOr([]);
+  testValueOr(null);
+  Expect.listEquals([1, 2, 3], globalList);
+}
+
+void testValueOr(List list) {
+  if (list == null) globalList.add(1);
+  if (list == null || list.contains("2")) globalList.add(2);
+  if (list == null || list.contains("3")) globalList.add(3);
+}
+
+testLogicalAnd() {
+  globalCounter = 0;
+  bool cond1 = falseWithSideEffect();
+  if (cond1 && falseWithoutSideEffect()) Expect.fail("must be false");
+  if (cond1 && falseWithoutSideEffect()) Expect.fail("must be false");
+  if (cond1 && falseWithoutSideEffect()) Expect.fail("must be false");
+  Expect.equals(1, globalCounter);
+
+  cond1 = (falseWithSideEffect() == 499);
+  if (cond1 && falseWithoutSideEffect()) Expect.fail("must be false");
+  if (cond1 && falseWithoutSideEffect()) Expect.fail("must be false");
+  if (cond1 && falseWithoutSideEffect()) Expect.fail("must be false");
+  Expect.equals(2, globalCounter);
+}
+
+void testLogicalAnd2() {
+  globalList.clear();
+  testValueAnd([]);
+  testValueAnd(null);
+  Expect.listEquals([1, 2, 3], globalList);
+}
+
+void testValueAnd(List list) {
+  if (list == null) globalList.add(1);
+  if (list == null && globalList.contains(1)) globalList.add(2);
+  if (list == null && globalList.contains(1)) globalList.add(3);
+}
+
+main() {
+  testLogicalOr();
+  testLogicalOr2();
+
+  testLogicalAnd();
+  testLogicalAnd2();
+}
diff --git a/tools/VERSION b/tools/VERSION
index 51c8aeb..2d4e26f 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -28,4 +28,4 @@
 MINOR 2
 PATCH 0
 PRERELEASE 5
-PRERELEASE_PATCH 14
+PRERELEASE_PATCH 15