Version 2.0.0-dev.69.5

 * Cherry-pick cb70de8afaf72ffccc2cb296960d3ed755979167 to dev
 * Cherry-pick 4482d13ff75dadc68df64758a35976c5cbeadbc6 to dev
 * Cherry-pick 5a45b2a62b3d647b7b4feca78da5948b5d108573 to dev
 * Cherry-pick 24158b773d29d36305ce6e8dbc1a1ce24a54e58e to dev
 * Cherry-pick 68bfaf3ac349e78cf5a7ea78d48e0b51bae2e605 to dev
 * Cherry-pick 23ba527735b386371395cd06c4cf39381072fc89 to dev
 * Cherry-pick 72960de5f9a8bc36c7a6265d56c6643d93c512b5 to dev
diff --git a/CHANGELOG.md b/CHANGELOG.md
index cca1d02..8701a43 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,19 @@
+## 2.0.0-dev.69.5
+* Cherry-pick cb70de8afaf72ffccc2cb296960d3ed755979167 to dev
+* Cherry-pick 4482d13ff75dadc68df64758a35976c5cbeadbc6 to dev
+* Cherry-pick 5a45b2a62b3d647b7b4feca78da5948b5d108573 to dev
+* Cherry-pick 24158b773d29d36305ce6e8dbc1a1ce24a54e58e to dev
+* Cherry-pick 68bfaf3ac349e78cf5a7ea78d48e0b51bae2e605 to dev
+* Cherry-pick 23ba527735b386371395cd06c4cf39381072fc89 to dev
+* Cherry-pick 72960de5f9a8bc36c7a6265d56c6643d93c512b5 to dev
+
+## 2.0.0-dev.69.4
+
+* Revert cherry-pick 9727a4a to dev
+* Cherry-pick 6bddb6c to dev
+* Cherry-pick 57e11e3 to dev
+* Cherry-pick 0998153 to dev
+
 ## 2.0.0-dev.69.3
 
 Cherry-pick f3625375744979a4c65e289a3140cbdd7fbf6f32 to dev
diff --git a/foo b/foo
deleted file mode 100644
index e69de29..0000000
--- a/foo
+++ /dev/null
diff --git a/runtime/tests/vm/dart/appjit_cha_deopt_test.dart b/runtime/tests/vm/dart/appjit_cha_deopt_test.dart
index 9c6f60f..fabc41b 100644
--- a/runtime/tests/vm/dart/appjit_cha_deopt_test.dart
+++ b/runtime/tests/vm/dart/appjit_cha_deopt_test.dart
@@ -8,34 +8,7 @@
 // optimized code.
 
 import 'dart:async';
-import 'dart:io';
-
-import 'package:expect/expect.dart';
-import 'package:path/path.dart' as p;
 
 import 'snapshot_test_helper.dart';
 
-const snapshotName = 'app.jit';
-
-Future<void> main() async {
-  final Directory temp = Directory.systemTemp.createTempSync();
-  final snapshotPath = p.join(temp.path, 'app.jit');
-  final testPath = Platform.script
-      .toFilePath()
-      .replaceAll(new RegExp(r'_test.dart$'), '_test_body.dart');
-
-  await temp.create();
-  try {
-    final trainingResult = await runDartBinary('TRAINING RUN', [
-      '--snapshot=$snapshotPath',
-      '--snapshot-kind=app-jit',
-      testPath,
-      '--train'
-    ]);
-    expectOutput("OK(Trained)", trainingResult);
-    final runResult = await runDartBinary('RUN FROM SNAPSHOT', [snapshotPath]);
-    expectOutput("OK(Run)", runResult);
-  } finally {
-    await temp.delete(recursive: true);
-  }
-}
+Future<void> main() => runAppJitTest();
diff --git a/runtime/tests/vm/dart/appjit_load_static_licm_test.dart b/runtime/tests/vm/dart/appjit_load_static_licm_test.dart
new file mode 100644
index 0000000..9f51b70
--- /dev/null
+++ b/runtime/tests/vm/dart/appjit_load_static_licm_test.dart
@@ -0,0 +1,12 @@
+// Copyright (c) 2018, 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.
+
+// Verify that app-jit snapshot contains dependencies between classes and CHA
+// optimized code.
+
+import 'dart:async';
+
+import 'snapshot_test_helper.dart';
+
+Future<void> main() => runAppJitTest();
diff --git a/runtime/tests/vm/dart/appjit_load_static_licm_test_body.dart b/runtime/tests/vm/dart/appjit_load_static_licm_test_body.dart
new file mode 100644
index 0000000..4006853
--- /dev/null
+++ b/runtime/tests/vm/dart/appjit_load_static_licm_test_body.dart
@@ -0,0 +1,48 @@
+// Copyright (c) 2018, 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.
+
+// Verify that LoadStaticField IL instruction can't be hoisted above
+// InitStaticField instruction.
+
+import 'package:expect/expect.dart';
+
+// Classes used to trigger deoptimization when running from app-jit snapshot.
+class A {
+  void foo() {}
+}
+
+class B {
+  void foo() {}
+}
+
+// Static final field with a non-trivial initializer.
+// This field will be reset before snapshot is written.
+final field = (() => 'value')();
+
+dynamic bar(dynamic o, {bool loadField: false}) {
+  o.foo();
+  // Create loop to trigger loop invariant code motion. We are testing that
+  // field load can't be hoisted above field initialization.
+  for (var i = 0; i < 2; i++) {
+    final v = loadField ? field : null;
+    if (loadField) {
+      return v;
+    }
+  }
+  return null;
+}
+
+void main(List<String> args) {
+  final isTraining = args.contains("--train");
+  dynamic o = isTraining ? new A() : new B();
+  for (var i = 0; i < 20000; i++) {
+    bar(o, loadField: false);
+    if (isTraining) {
+      // Initialize the field when training.
+      bar(o, loadField: true);
+    }
+  }
+  Expect.equals('value', bar(o, loadField: true));
+  print(isTraining ? 'OK(Trained)' : 'OK(Run)');
+}
diff --git a/runtime/tests/vm/dart/regress_33999_test.dart b/runtime/tests/vm/dart/regress_33999_test.dart
new file mode 100644
index 0000000..933d2e0
--- /dev/null
+++ b/runtime/tests/vm/dart/regress_33999_test.dart
@@ -0,0 +1,50 @@
+// Copyright (c) 2018, 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 checking that canonicalization rules for AssertAssignable IL
+// instructions take into account that these instructions can be
+// on unreachable code paths.
+
+// Class with two type parameters.
+class A<U, T> {
+  T field;
+}
+
+// Class with a single type parameter
+class B<T> {
+  T field;
+}
+
+var TRUE = true;
+
+void foo(bool f) {
+  dynamic x = f ? new B<int>() : new A<String, int>();
+  if (f == TRUE) {
+    // Prevent constant folding by accessing a global
+    x.field = 10;
+  } else {
+    x.field = 10;
+  }
+}
+
+void bar() {
+  // When foo() is inlined into bar() a graph where
+  // allocation of B will flow into code-path that
+  // expects A will arise. On that code-path (which
+  // is dynamically unreachable because it is guarded
+  // by CheckClass) there will be an assert assignable
+  // against A.T.
+  // Canonicalization rule should not crash when it tries
+  // to instantiate this type.
+  foo(true);
+}
+
+void main() {
+  // Execute both paths to populate ICData.
+  foo(true);
+  foo(false);
+
+  // Force optimization of bar().
+  for (var i = 0; i < 100000; i++) bar();
+}
diff --git a/runtime/tests/vm/dart/snapshot_test_helper.dart b/runtime/tests/vm/dart/snapshot_test_helper.dart
index 2de2bbf..2eced21 100644
--- a/runtime/tests/vm/dart/snapshot_test_helper.dart
+++ b/runtime/tests/vm/dart/snapshot_test_helper.dart
@@ -94,3 +94,25 @@
     await temp.delete(recursive: true);
   }
 }
+
+Future<void> runAppJitTest() async {
+  final Directory temp = Directory.systemTemp.createTempSync();
+  final snapshotPath = p.join(temp.path, 'app.jit');
+  final testPath = Platform.script
+      .toFilePath()
+      .replaceAll(new RegExp(r'_test.dart$'), '_test_body.dart');
+
+  try {
+    final trainingResult = await runDartBinary('TRAINING RUN', [
+      '--snapshot=$snapshotPath',
+      '--snapshot-kind=app-jit',
+      testPath,
+      '--train'
+    ]);
+    expectOutput("OK(Trained)", trainingResult);
+    final runResult = await runDartBinary('RUN FROM SNAPSHOT', [snapshotPath]);
+    expectOutput("OK(Run)", runResult);
+  } finally {
+    await temp.delete(recursive: true);
+  }
+}
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 66ef97f..aba685b 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -24,7 +24,7 @@
 cc/CodeImmutability: Fail, OK # Address Sanitizer turns a crash into a failure.
 
 [ $builder_tag == optimization_counter_threshold ]
-dart/appjit_cha_deopt_test: SkipByDesign # Test needs to a particular opt-counter value
+dart/appjit*: SkipByDesign # Test needs to a particular opt-counter value
 
 [ $compiler == app_jit ]
 dart/snapshot_version_test: Fail, OK # Expects to find script snapshot relative to Dart source.
@@ -55,7 +55,6 @@
 
 [ $compiler == dartk ]
 cc/DartAPI_New: Fail # Issue #33041
-dart/appjit_cha_deopt_test: SkipSlow # Issue 33266
 dart/redirection_type_shuffling_test/00: RuntimeError, Pass
 dart/redirection_type_shuffling_test/none: RuntimeError
 
@@ -230,11 +229,6 @@
 cc/ScriptSnapshot1: Fail, Crash, OK # Script snapshots not supported in Dart 2
 cc/ScriptSnapshotsUpdateSubclasses: Fail, Crash, OK # Script snapshots not supported in Dart 2
 
-[ $compiler == dartk && ($arch == simarm || $arch == simarm64 || $arch == simdbc || $arch == simdbc64) ]
-dart/appjit_cha_deopt_test: SkipSlow # DFE too slow
-dart/appjit_determinism_test: SkipSlow # DFE too slow
-dart/script_determinism_test: SkipSlow # DFE too slow
-
 # Enabling of dartk for sim{arm,arm64,dbc64} revelaed these test failures, which
 # are to be triaged.  Isolate tests are skipped on purpose due to the usage of
 # batch mode.
@@ -245,9 +239,8 @@
 [ $compiler == dartk && ($hot_reload || $hot_reload_rollback) ]
 dart/data_uri_spawn_test: Skip # Timeout
 
-[ $compiler != dartk && $compiler != none ]
-dart/appjit_cha_deopt_test: SkipByDesign # Test needs to run from source
-dart/appjit_determinism_test: SkipByDesign # Test needs to run from source
+[ $compiler != dartk && $compiler != dartkb && $compiler != none ]
+dart/appjit*: SkipByDesign # Test needs to run from source
 dart/script_determinism_test: SkipByDesign # Test needs to run from source
 
 [ $compiler == dartkp && ($runtime == dart_precompiled || $runtime == vm) ]
@@ -269,6 +262,10 @@
 dart/inline_stack_frame_test: Skip
 dart/optimized_stacktrace_line_test: Skip
 
+[ ($arch == simarm || $arch == simarm64 || $arch == simdbc || $arch == simdbc64) && ($compiler == dartk || $compiler == dartkb) ]
+dart/appjit*: SkipSlow # DFE too slow
+dart/script_determinism_test: SkipSlow # DFE too slow
+
 # Profiler is completely disabled in SIMDBC builds.
 # On the simluator stack traces produced by the Profiler do not match
 # up with the real Dart stack trace and hence we don't get correct
@@ -359,8 +356,7 @@
 dart/redirection_type_shuffling_test: SkipByDesign # Imports dart:mirrors
 
 [ $hot_reload || $hot_reload_rollback ]
-dart/appjit_cha_deopt_test: SkipByDesign # Cannot reload with URI pointing to app snapshot.
-dart/appjit_determinism_test: SkipByDesign # Reload affects determinisim
+dart/appjit*: SkipByDesign # Cannot reload with URI pointing to app snapshot.
 dart/script_determinism_test: SkipByDesign # Cannot reload with URI pointing to script snapshot.
 dart/slow_path_shared_stub_test: SkipSlow # Too slow with --slow-path-triggers-gc flag and not relevant outside precompiled.
 dart/spawn_infinite_loop_test: Skip # We can shutdown an isolate before it reloads.
diff --git a/runtime/vm/compiler/assembler/assembler.h b/runtime/vm/compiler/assembler/assembler.h
index bc16cba..3eddf5d 100644
--- a/runtime/vm/compiler/assembler/assembler.h
+++ b/runtime/vm/compiler/assembler/assembler.h
@@ -24,7 +24,7 @@
 class AssemblerBuffer;
 class MemoryRegion;
 
-class Label : public ValueObject {
+class Label : public ZoneAllocated {
  public:
   Label() : position_(0), unresolved_(0) {
 #ifdef DEBUG
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index 0dd7ed5..f8beb87 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -822,9 +822,13 @@
 }
 
 const Field& LoadStaticFieldInstr::StaticField() const {
-  Field& field = Field::ZoneHandle();
-  field ^= field_value()->BoundConstant().raw();
-  return field;
+  return Field::Cast(field_value()->BoundConstant());
+}
+
+bool LoadStaticFieldInstr::IsFieldInitialized() const {
+  const Field& field = StaticField();
+  return (field.StaticValue() != Object::sentinel().raw()) &&
+         (field.StaticValue() != Object::transition_sentinel().raw());
 }
 
 ConstantInstr::ConstantInstr(const Object& value, TokenPosition token_pos)
@@ -2489,8 +2493,14 @@
   if (dst_type().IsInstantiated()) {
     return this;
   }
+
   // For uninstantiated target types: If the instantiator and function
   // type arguments are constant, instantiate the target type here.
+  // Note: these constant type arguments might not necessarily correspond
+  // to the correct instantiator because AssertAssignable might
+  // be located in the unreachable part of the graph (e.g.
+  // it might be dominated by CheckClass that always fails).
+  // This means that the code below must guard against such possibility.
   ConstantInstr* constant_instantiator_type_args =
       instantiator_type_arguments()->definition()->AsConstant();
   ConstantInstr* constant_function_type_args =
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index f6bff3f..c77946d 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -4250,6 +4250,7 @@
   virtual CompileType ComputeType() const;
 
   const Field& StaticField() const;
+  bool IsFieldInitialized() const;
 
   Value* field_value() const { return inputs_[0]; }
 
diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc
index 36a33a2..7505abd 100644
--- a/runtime/vm/compiler/backend/il_arm.cc
+++ b/runtime/vm/compiler/backend/il_arm.cc
@@ -3372,6 +3372,12 @@
       __ b(instruction()->is_negated() ? labels_.true_label
                                        : labels_.false_label);
     } else {
+      if (instruction()->is_negated()) {
+        // Need to negate the result of slow path call.
+        __ CompareObject(result, Bool::True());
+        __ LoadObject(result, Bool::True(), NE);
+        __ LoadObject(result, Bool::False(), EQ);
+      }
       __ b(exit_label());
     }
   }
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index 6049bb7..5312520 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -3079,7 +3079,9 @@
            EQ);
       __ b(instruction()->is_negated() ? labels_.true_label
                                        : labels_.false_label);
+      ASSERT(exit_label()->IsUnused());
     } else {
+      ASSERT(!instruction()->is_negated());
       __ b(exit_label());
     }
   }
@@ -3138,28 +3140,38 @@
   Condition true_condition = EmitComparisonCode(compiler, labels);
   ASSERT(true_condition != kInvalidCondition);
   EmitBranchOnCondition(compiler, true_condition, labels);
-  __ Bind(slow_path->exit_label());
+  // No need to bind slow_path->exit_label() as slow path exits through
+  // true/false branch labels.
 }
 
 void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  Label true_label, false_label, done;
-  BranchLabels labels = {&true_label, &false_label, &false_label};
+  // Zone-allocate labels to pass them to slow-path which outlives local scope.
+  Label* true_label = new (Z) Label();
+  Label* false_label = new (Z) Label();
+  Label done;
+  BranchLabels labels = {true_label, false_label, false_label};
+  // In case of negated comparison result of a slow path call should be negated.
+  // For this purpose, 'merged' slow path is generated: it tests
+  // result of a call and jumps directly to true or false label.
   CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath(
       this, compiler->CurrentTryIndex(), labels,
-      /* merged = */ false);
+      /* merged = */ is_negated());
   compiler->AddSlowPathCode(slow_path);
   EMIT_SMI_CHECK;
   Condition true_condition = EmitComparisonCode(compiler, labels);
   ASSERT(true_condition != kInvalidCondition);
   EmitBranchOnCondition(compiler, true_condition, labels);
   Register result = locs()->out(0).reg();
-  __ Bind(&false_label);
+  __ Bind(false_label);
   __ LoadObject(result, Bool::False());
   __ b(&done);
-  __ Bind(&true_label);
+  __ Bind(true_label);
   __ LoadObject(result, Bool::True());
   __ Bind(&done);
-  __ Bind(slow_path->exit_label());
+  // In case of negated comparison slow path exits through true/false labels.
+  if (!is_negated()) {
+    __ Bind(slow_path->exit_label());
+  }
 }
 
 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Zone* zone,
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index 5c5658f..8365db6 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -2994,7 +2994,7 @@
   CheckedSmiComparisonSlowPath(CheckedSmiComparisonInstr* instruction,
                                intptr_t try_index,
                                BranchLabels labels,
-                               bool merged = false)
+                               bool merged)
       : TemplateSlowPathCode(instruction),
         try_index_(try_index),
         labels_(labels),
@@ -3033,7 +3033,9 @@
                                               : labels_.true_label);
       __ jmp(instruction()->is_negated() ? labels_.true_label
                                          : labels_.false_label);
+      ASSERT(exit_label()->IsUnused());
     } else {
+      ASSERT(!instruction()->is_negated());
       __ jmp(exit_label());
     }
   }
@@ -3093,28 +3095,38 @@
   Condition true_condition = EmitComparisonCode(compiler, labels);
   ASSERT(true_condition != INVALID_CONDITION);
   EmitBranchOnCondition(compiler, true_condition, labels);
-  __ Bind(slow_path->exit_label());
+  // No need to bind slow_path->exit_label() as slow path exits through
+  // true/false branch labels.
 }
 
 void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  Label true_label, false_label, done;
-  BranchLabels labels = {&true_label, &false_label, &false_label};
+  // Zone-allocate labels to pass them to slow-path which outlives local scope.
+  Label* true_label = new (Z) Label();
+  Label* false_label = new (Z) Label();
+  Label done;
+  BranchLabels labels = {true_label, false_label, false_label};
+  // In case of negated comparison result of a slow path call should be negated.
+  // For this purpose, 'merged' slow path is generated: it tests
+  // result of a call and jumps directly to true or false label.
   CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath(
       this, compiler->CurrentTryIndex(), labels,
-      /* merged = */ false);
+      /* merged = */ is_negated());
   compiler->AddSlowPathCode(slow_path);
   EMIT_SMI_CHECK;
   Condition true_condition = EmitComparisonCode(compiler, labels);
   ASSERT(true_condition != INVALID_CONDITION);
   EmitBranchOnCondition(compiler, true_condition, labels);
   Register result = locs()->out(0).reg();
-  __ Bind(&false_label);
+  __ Bind(false_label);
   __ LoadObject(result, Bool::False());
   __ jmp(&done);
-  __ Bind(&true_label);
+  __ Bind(true_label);
   __ LoadObject(result, Bool::True());
   __ Bind(&done);
-  __ Bind(slow_path->exit_label());
+  // In case of negated comparison slow path exits through true/false labels.
+  if (!is_negated()) {
+    __ Bind(slow_path->exit_label());
+  }
 }
 
 static bool CanBeImmediate(const Object& constant) {
diff --git a/runtime/vm/compiler/backend/redundancy_elimination.cc b/runtime/vm/compiler/backend/redundancy_elimination.cc
index b34c1b5..0e4eea8 100644
--- a/runtime/vm/compiler/backend/redundancy_elimination.cc
+++ b/runtime/vm/compiler/backend/redundancy_elimination.cc
@@ -1377,6 +1377,16 @@
       BlockEntryInstr* block = flow_graph()->preorder()[loop_it.Current()];
       for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
         Instruction* current = it.Current();
+
+        // Treat loads of static final fields specially: we can CSE them but
+        // we should not move them around unless the field is initialized.
+        // Otherwise we might move load past the initialization.
+        if (LoadStaticFieldInstr* load = current->AsLoadStaticField()) {
+          if (load->AllowsCSE() && !load->IsFieldInitialized()) {
+            continue;
+          }
+        }
+
         if ((current->AllowsCSE() ||
              IsLoopInvariantLoad(loop_invariant_loads, i, current)) &&
             !current->MayThrow()) {
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 057eff5..2ac08b7 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -6834,10 +6834,11 @@
                          Heap::kOld)) {
     // For more informative error reporting, use the location of the other
     // function here, since the caller will use the location of this function.
+    auto space = Thread::Current()->IsMutatorThread() ? Heap::kNew : Heap::kOld;
     *bound_error = LanguageError::NewFormatted(
         *bound_error,  // A bound error if non null.
         Script::Handle(other.script()), other.token_pos(), Report::AtLocation,
-        Report::kError, Heap::kNew,
+        Report::kError, space,
         "signature type '%s' of function '%s' is not a subtype of signature "
         "type '%s' of function '%s'\n",
         String::Handle(UserVisibleSignature()).ToCString(),
@@ -18641,6 +18642,19 @@
   if (instantiator_type_arguments.IsNull()) {
     return Type::DynamicType();
   }
+  if (instantiator_type_arguments.Length() <= index()) {
+    // InstantiateFrom can be invoked from a compilation pipeline with
+    // mismatching type arguments vector. This can only happen for
+    // a dynamically unreachable code - which compiler can't remove
+    // statically for some reason.
+    // To prevent crashes we treat it as a bound error.
+    // (see AssertAssignableInstr::Canonicalize).
+    auto space = Thread::Current()->IsMutatorThread() ? Heap::kNew : Heap::kOld;
+    *bound_error = LanguageError::New(
+        String::Handle(String::New("Mismatching type argument vector.", space)),
+        Report::kError, space);
+    return raw();
+  }
   return instantiator_type_arguments.TypeAt(index());
   // There is no need to canonicalize the instantiated type parameter, since all
   // type arguments are canonicalized at type finalization time. It would be too
@@ -19418,11 +19432,15 @@
         // Division special case: overflow in int64_t.
         // MIN_VALUE / -1 = (MAX_VALUE + 1), which wraps around to MIN_VALUE
         return Integer::New(Mint::kMinValue, space);
-      } else {
-        return Integer::New(left_value / right_value, space);
       }
+      return Integer::New(left_value / right_value, space);
 
     case Token::kMOD: {
+      if ((left_value == Mint::kMinValue) && (right_value == -1)) {
+        // Modulo special case: overflow in int64_t.
+        // MIN_VALUE % -1 = 0 for reason given above.
+        return Integer::New(0, space);
+      }
       const int64_t remainder = left_value % right_value;
       if (remainder < 0) {
         if (right_value < 0) {
diff --git a/tests/language_2/vm/modtruncdiv_int_test.dart b/tests/language_2/vm/modtruncdiv_int_test.dart
new file mode 100644
index 0000000..9d3f222
--- /dev/null
+++ b/tests/language_2/vm/modtruncdiv_int_test.dart
@@ -0,0 +1,214 @@
+// Copyright (c) 2018, 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=--no_background_compilation --optimization_counter_threshold=10
+
+import "package:expect/expect.dart";
+
+// Tests for long trunc div and mod under
+// 64-bit arithmetic wrap-around semantics.
+
+final int maxInt32 = 2147483647;
+final int minInt32 = -2147483648;
+final int maxInt64 = 0x7fffffffffffffff;
+final int minInt64 = 0x8000000000000000;
+
+int mod(int x, int y) {
+  return x % y;
+}
+
+int truncdiv(int x, int y) {
+  return x ~/ y;
+}
+
+doModConstants() {
+  Expect.equals(0, mod(0, 1));
+  Expect.equals(0, mod(0, -1));
+  Expect.equals(1, mod(1, 2));
+  Expect.equals(1, mod(-1, 2));
+  Expect.equals(1, mod(1, -2));
+  Expect.equals(1, mod(-1, -2));
+  Expect.equals(2, mod(8, 3));
+  Expect.equals(1, mod(-8, 3));
+  Expect.equals(2, mod(8, -3));
+  Expect.equals(1, mod(-8, -3));
+  Expect.equals(0, mod(6, 3));
+  Expect.equals(1, mod(7, 3));
+  Expect.equals(2, mod(8, 3));
+  Expect.equals(0, mod(9, 3));
+
+  Expect.equals(1, mod(1, maxInt32));
+  Expect.equals(1, mod(1, maxInt64));
+  Expect.equals(1, mod(1, minInt32));
+  Expect.equals(1, mod(1, minInt64));
+
+  Expect.equals(maxInt32 - 1, mod(-1, maxInt32));
+  Expect.equals(maxInt64 - 1, mod(-1, maxInt64));
+  Expect.equals(maxInt32, mod(-1, minInt32));
+  Expect.equals(maxInt64, mod(-1, minInt64));
+
+  Expect.equals(0, mod(minInt32, -1));
+  Expect.equals(0, mod(maxInt32, -1));
+  Expect.equals(0, mod(minInt64, -1));
+  Expect.equals(0, mod(maxInt64, -1));
+
+  Expect.equals(0, mod(maxInt32, maxInt32));
+  Expect.equals(maxInt32, mod(maxInt32, minInt32));
+  Expect.equals(maxInt32, mod(maxInt32, maxInt64));
+  Expect.equals(maxInt32, mod(maxInt32, minInt64));
+
+  Expect.equals(maxInt32 - 1, mod(minInt32, maxInt32));
+  Expect.equals(0, mod(minInt32, minInt32));
+  Expect.equals(9223372034707292159, mod(minInt32, maxInt64));
+  Expect.equals(9223372034707292160, mod(minInt32, minInt64));
+
+  Expect.equals(1, mod(maxInt64, maxInt32));
+  Expect.equals(0, mod(maxInt64 - 1, maxInt32));
+  Expect.equals(maxInt32 - 1, mod(maxInt64 - 2, maxInt32));
+  Expect.equals(maxInt32, mod(maxInt64, minInt32));
+  Expect.equals(0, mod(maxInt64, maxInt64));
+  Expect.equals(maxInt64, mod(maxInt64, minInt64));
+
+  Expect.equals(maxInt32 - 2, mod(minInt64, maxInt32));
+  Expect.equals(0, mod(minInt64, minInt32));
+  Expect.equals(maxInt64 - 1, mod(minInt64, maxInt64));
+  Expect.equals(0, mod(minInt64, minInt64));
+
+  Expect.equals(maxInt32 - 1, mod(maxInt32 - 1, maxInt32));
+  Expect.equals(1, mod(maxInt32 + 1, maxInt32));
+  Expect.equals(maxInt32 - 2, mod(minInt32 - 1, maxInt32));
+  Expect.equals(0, mod(minInt32 + 1, maxInt32));
+}
+
+doTruncDivConstants() {
+  Expect.equals(0, truncdiv(0, 1));
+  Expect.equals(0, truncdiv(0, -1));
+  Expect.equals(0, truncdiv(1, 2));
+  Expect.equals(0, truncdiv(-1, 2));
+  Expect.equals(0, truncdiv(1, -2));
+  Expect.equals(0, truncdiv(-1, -2));
+  Expect.equals(2, truncdiv(8, 3));
+  Expect.equals(-2, truncdiv(-8, 3));
+  Expect.equals(-2, truncdiv(8, -3));
+  Expect.equals(2, truncdiv(-8, -3));
+  Expect.equals(2, truncdiv(6, 3));
+  Expect.equals(2, truncdiv(7, 3));
+  Expect.equals(2, truncdiv(8, 3));
+  Expect.equals(3, truncdiv(9, 3));
+
+  Expect.equals(0, truncdiv(1, maxInt32));
+  Expect.equals(0, truncdiv(1, maxInt64));
+  Expect.equals(0, truncdiv(1, minInt32));
+  Expect.equals(0, truncdiv(1, minInt64));
+
+  Expect.equals(0, truncdiv(-1, maxInt32));
+  Expect.equals(0, truncdiv(-1, maxInt64));
+  Expect.equals(0, truncdiv(-1, minInt32));
+  Expect.equals(0, truncdiv(-1, minInt64));
+
+  Expect.equals(-minInt32, truncdiv(minInt32, -1));
+  Expect.equals(-maxInt32, truncdiv(maxInt32, -1));
+  Expect.equals(minInt64, truncdiv(minInt64, -1));
+  Expect.equals(-maxInt64, truncdiv(maxInt64, -1));
+
+  Expect.equals(1, truncdiv(maxInt32, maxInt32));
+  Expect.equals(0, truncdiv(maxInt32, minInt32));
+  Expect.equals(0, truncdiv(maxInt32, maxInt64));
+  Expect.equals(0, truncdiv(maxInt32, minInt64));
+
+  Expect.equals(-1, truncdiv(minInt32, maxInt32));
+  Expect.equals(1, truncdiv(minInt32, minInt32));
+  Expect.equals(0, truncdiv(minInt32, maxInt64));
+  Expect.equals(0, truncdiv(minInt32, minInt64));
+
+  Expect.equals(4294967298, truncdiv(maxInt64, maxInt32));
+  Expect.equals(4294967298, truncdiv(maxInt64 - 1, maxInt32));
+  Expect.equals(4294967297, truncdiv(maxInt64 - 2, maxInt32));
+  Expect.equals(-4294967295, truncdiv(maxInt64, minInt32));
+  Expect.equals(1, truncdiv(maxInt64, maxInt64));
+  Expect.equals(0, truncdiv(maxInt64, minInt64));
+
+  Expect.equals(-4294967298, truncdiv(minInt64, maxInt32));
+  Expect.equals(4294967296, truncdiv(minInt64, minInt32));
+  Expect.equals(-1, truncdiv(minInt64, maxInt64));
+  Expect.equals(1, truncdiv(minInt64, minInt64));
+
+  Expect.equals(0, truncdiv(maxInt32 - 1, maxInt32));
+  Expect.equals(1, truncdiv(maxInt32 + 1, maxInt32));
+  Expect.equals(-1, truncdiv(minInt32 - 1, maxInt32));
+  Expect.equals(-1, truncdiv(minInt32 + 1, maxInt32));
+}
+
+int acc;
+
+doModVars(int xlo, int xhi, int ylo, int yhi) {
+  for (int x = xlo; x <= xhi; x++) {
+    for (int y = ylo; y <= yhi; y++) {
+      acc += mod(x, y);
+    }
+  }
+}
+
+doTruncDivVars(int xlo, int xhi, int ylo, int yhi) {
+  for (int x = xlo; x <= xhi; x++) {
+    for (int y = ylo; y <= yhi; y++) {
+      acc += truncdiv(x, y);
+    }
+  }
+}
+
+main() {
+  // Repeat constant tests to enter JIT (when applicable).
+
+  for (int i = 0; i < 20; i++) {
+    doModConstants();
+    doTruncDivConstants();
+  }
+
+  // Variable ranges.
+
+  acc = 0;
+  doModVars(3, 5, 2, 6);
+  Expect.equals(28, acc);
+
+  acc = 0;
+  doModVars((3 << 32) - 1, (3 << 32) + 1, (3 << 32) - 1, (3 << 32) + 1);
+  Expect.equals(38654705666, acc);
+
+  acc = 0;
+  doTruncDivVars(3, 5, 2, 6);
+  Expect.equals(11, acc);
+
+  acc = 0;
+  doTruncDivVars(-5, -3, 2, 6);
+  Expect.equals(-11, acc);
+
+  acc = 0;
+  doTruncDivVars(3, 5, -6, -2);
+  Expect.equals(-11, acc);
+
+  acc = 0;
+  doTruncDivVars(-5, -3, -6, -2);
+  Expect.equals(11, acc);
+
+  acc = 0;
+  doTruncDivVars((3 << 32) - 1, (3 << 32) + 1, 3, 6);
+  Expect.equals(36721970376, acc);
+
+  // Exceptions at the right time.
+
+  acc = 0;
+  try {
+    doModVars(9, 9, -9, 0);
+    acc = 0; // don't reach!
+  } catch (e, s) {}
+  Expect.equals(12, acc);
+
+  acc = 0;
+  try {
+    doTruncDivVars(9, 9, -9, 0);
+    acc = 0; // don't reach!
+  } catch (e, s) {}
+  Expect.equals(-23, acc);
+}
diff --git a/tests/language_2/vm/regress_flutter_19612_test.dart b/tests/language_2/vm/regress_flutter_19612_test.dart
new file mode 100644
index 0000000..e7b3af1
--- /dev/null
+++ b/tests/language_2/vm/regress_flutter_19612_test.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2018, 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.
+
+// Regression test for https://github.com/flutter/flutter/issues/19612.
+// This test verifies that negated condition is correctly handled by the
+// AOT compiler.
+
+import "package:expect/expect.dart";
+
+class X {
+  final int maxLines;
+  X([this.maxLines]);
+
+  bool get isMultiline => maxLines != 1;
+}
+
+X x1 = new X(1);
+X x2 = new X(42);
+X x3 = new X();
+
+main() {
+  Expect.isFalse(x1.isMultiline);
+  Expect.isTrue(x2.isMultiline);
+  Expect.isTrue(x3.isMultiline);
+}
diff --git a/tools/VERSION b/tools/VERSION
index 7c09085..01a87d1 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -28,4 +28,4 @@
 MINOR 0
 PATCH 0
 PRERELEASE 69
-PRERELEASE_PATCH 4
+PRERELEASE_PATCH 5
diff --git a/tools/apps/update_homebrew/pubspec.yaml b/tools/apps/update_homebrew/pubspec.yaml
index b90401e..0645811 100644
--- a/tools/apps/update_homebrew/pubspec.yaml
+++ b/tools/apps/update_homebrew/pubspec.yaml
@@ -3,7 +3,7 @@
 dependencies:
   _discoveryapis_commons: ^0.1.3+1
   args: ^0.13.0
-  googleapis: ^0.35.0
+  googleapis: ^0.51.0
   http: ^0.11.1+1
   path: ^1.4.1
   stack_trace: ^1.3.2