Version 1.11.0-dev.5.5

Cherry-pick f6f338ce67eb8801b350417baacf6d3681b26002 into dev
Cherry-pick 90315a1694a40ba738a5197295b0c1a7b9d03c5f into dev
Cherry-pick 9edc6e5a6d31ec926be7743c06f500f125a04b54 into dev
Cherry-pick 16bb52b88ded9da50508d72bf86825b243ad8258 into dev
Cherry-pick 1009d587de88ec04a66cd60409aba3a281e21f64 into dev
Cherry-pick 3ce2b95070a26d7aa5173673095d49e0494c4151 into dev
diff --git a/runtime/lib/bigint.dart b/runtime/lib/bigint.dart
index f4ff408..04b85b7 100644
--- a/runtime/lib/bigint.dart
+++ b/runtime/lib/bigint.dart
@@ -1265,15 +1265,9 @@
     return other._toBigintOrDouble()._mulFromInteger(this);
   }
   num operator ~/(num other) {
-    if ((other is int) && (other == 0)) {
-      throw const IntegerDivisionByZeroException();
-    }
     return other._toBigintOrDouble()._truncDivFromInteger(this);
   }
   num operator %(num other) {
-    if ((other is int) && (other == 0)) {
-      throw const IntegerDivisionByZeroException();
-    }
     return other._toBigintOrDouble()._moduloFromInteger(this);
   }
   int operator &(int other) {
@@ -1368,9 +1362,15 @@
     return other._toBigint()._mul(this)._toValidInt();
   }
   int _truncDivFromInteger(int other) {
+    if (_used == 0) {
+      throw const IntegerDivisionByZeroException();
+    }
     return other._toBigint()._div(this)._toValidInt();
   }
   int _moduloFromInteger(int other) {
+    if (_used == 0) {
+      throw const IntegerDivisionByZeroException();
+    }
     _Bigint result = other._toBigint()._rem(this);
     if (result._neg) {
       if (_neg) {
@@ -1382,6 +1382,9 @@
     return result._toValidInt();
   }
   int _remainderFromInteger(int other) {
+    if (_used == 0) {
+      throw const IntegerDivisionByZeroException();
+    }
     return other._toBigint()._rem(this)._toValidInt();
   }
   bool _greaterThanFromInteger(int other) {
@@ -1534,6 +1537,218 @@
     assert(!is1);
     return z._revert(r_digits, r_used)._toValidInt();
   }
+
+  // Returns 1/this % m, with m > 0.
+  int modInverse(int m) {
+    if (m is! int) throw new ArgumentError(m);
+    if (m <= 0) throw new RangeError(m);
+    if (m == 1) return 0;
+    m = m._toBigint();
+    var t = this;
+    if (t._neg || (t._absCompare(m) >= 0)) {
+      t %= m;
+      t = t._toBigint();
+    }
+    final bool ac = m.isEven;
+    final t_used = t._used;
+    if ((t_used == 1) && (t._digits[0] == 1)) return 1;
+    if ((t_used == 0) || (ac && t.isEven)) throw new RangeError("Not coprime");
+    final m_digits = m._digits;
+    final m_used = m._used;
+    final tuv_len = m_used + (m_used & 1);
+    final t_digits = _cloneDigits(t._digits, 0, t_used, tuv_len);
+    var u_digits = _cloneDigits(m_digits, 0, m_used, tuv_len);
+    var v_digits = _cloneDigits(t_digits, 0, t_used, tuv_len);
+
+    // Variables a, b, c, and d require one more digit.
+    final abcd_used = m_used + 1;
+    final abcd_len = abcd_used + (abcd_used & 1) + 2;  // +2 to satisfy _absAdd.
+    var a_digits, b_digits, c_digits, d_digits;
+    bool a_neg, b_neg, c_neg, d_neg;
+    if (ac) {
+      a_digits = new Uint32List(abcd_len);
+      a_neg = false;
+      a_digits[0] = 1;
+      c_digits = new Uint32List(abcd_len);
+      c_neg = false;
+    }
+    b_digits = new Uint32List(abcd_len);
+    b_neg = false;
+    d_digits = new Uint32List(abcd_len);
+    d_neg = false;
+    d_digits[0] = 1;
+
+    while (true) {
+      while ((u_digits[0] & 1) == 0) {
+        _rsh(u_digits, m_used, 1, u_digits);
+        if (ac) {
+          if (((a_digits[0] & 1) == 1) || ((b_digits[0] & 1) == 1)) {
+            if (a_neg) {
+              if ((a_digits[m_used] != 0) ||
+                  (_compareDigits(a_digits, m_used, t_digits, m_used)) > 0) {
+                _absSub(a_digits, abcd_used, t_digits, m_used, a_digits);
+              } else {
+                _absSub(t_digits, m_used, a_digits, m_used, a_digits);
+                a_neg = false;
+              }
+            } else {
+              _absAdd(a_digits, abcd_used, t_digits, m_used, a_digits);
+            }
+            if (b_neg) {
+              _absAdd(b_digits, abcd_used, m_digits, m_used, b_digits);
+            } else if ((b_digits[m_used] != 0) ||
+                (_compareDigits(b_digits, m_used, m_digits, m_used) > 0)) {
+              _absSub(b_digits, abcd_used, m_digits, m_used, b_digits);
+            } else {
+              _absSub(m_digits, m_used, b_digits, m_used, b_digits);
+              b_neg = true;
+            }
+          }
+          _rsh(a_digits, abcd_used, 1, a_digits);
+        } else if ((b_digits[0] & 1) == 1) {
+          if (b_neg) {
+            _absAdd(b_digits, abcd_used, m_digits, m_used, b_digits);
+          } else if ((b_digits[m_used] != 0) ||
+                     (_compareDigits(b_digits, m_used, m_digits, m_used) > 0)) {
+            _absSub(b_digits, abcd_used, m_digits, m_used, b_digits);
+          } else {
+            _absSub(m_digits, m_used, b_digits, m_used, b_digits);
+            b_neg = true;
+          }
+        }
+        _rsh(b_digits, abcd_used, 1, b_digits);
+      }
+      while ((v_digits[0] & 1) == 0) {
+        _rsh(v_digits, m_used, 1, v_digits);
+        if (ac) {
+          if (((c_digits[0] & 1) == 1) || ((d_digits[0] & 1) == 1)) {
+            if (c_neg) {
+              if ((c_digits[m_used] != 0) ||
+                  (_compareDigits(c_digits, m_used, t_digits, m_used) > 0)) {
+                _absSub(c_digits, abcd_used, t_digits, m_used, c_digits);
+              } else {
+                _absSub(t_digits, m_used, c_digits, m_used, c_digits);
+                c_neg = false;
+              }
+            } else {
+              _absAdd(c_digits, abcd_used, t_digits, m_used, c_digits);
+            }
+            if (d_neg) {
+              _absAdd(d_digits, abcd_used, m_digits, m_used, d_digits);
+            } else if ((d_digits[m_used] != 0) ||
+                (_compareDigits(d_digits, m_used, m_digits, m_used) > 0)) {
+              _absSub(d_digits, abcd_used, m_digits, m_used, d_digits);
+            } else {
+              _absSub(m_digits, m_used, d_digits, m_used, d_digits);
+              d_neg = true;
+            }
+          }
+          _rsh(c_digits, abcd_used, 1, c_digits);
+        } else if ((d_digits[0] & 1) == 1) {
+          if (d_neg) {
+            _absAdd(d_digits, abcd_used, m_digits, m_used, d_digits);
+          } else if ((d_digits[m_used] != 0) ||
+                     (_compareDigits(d_digits, m_used, m_digits, m_used) > 0)) {
+            _absSub(d_digits, abcd_used, m_digits, m_used, d_digits);
+          } else {
+            _absSub(m_digits, m_used, d_digits, m_used, d_digits);
+            d_neg = true;
+          }
+        }
+        _rsh(d_digits, abcd_used, 1, d_digits);
+      }
+      if (_compareDigits(u_digits, m_used, v_digits, m_used) >= 0) {
+        _absSub(u_digits, m_used, v_digits, m_used, u_digits);
+        if (ac) {
+          if (a_neg == c_neg) {
+            var a_cmp_c =
+                _compareDigits(a_digits, abcd_used, c_digits, abcd_used);
+            if (a_cmp_c > 0) {
+              _absSub(a_digits, abcd_used, c_digits, abcd_used, a_digits);
+            } else {
+              _absSub(c_digits, abcd_used, a_digits, abcd_used, a_digits);
+              a_neg = !a_neg && (a_cmp_c != 0);
+            }
+          } else {
+            _absAdd(a_digits, abcd_used, c_digits, abcd_used, a_digits);
+          }
+        }
+        if (b_neg == d_neg) {
+          var b_cmp_d =
+              _compareDigits(b_digits, abcd_used, d_digits, abcd_used);
+          if (b_cmp_d > 0) {
+            _absSub(b_digits, abcd_used, d_digits, abcd_used, b_digits);
+          } else {
+            _absSub(d_digits, abcd_used, b_digits, abcd_used, b_digits);
+            b_neg = !b_neg && (b_cmp_d != 0);
+          }
+        } else {
+          _absAdd(b_digits, abcd_used, d_digits, abcd_used, b_digits);
+        }
+      } else {
+        _absSub(v_digits, m_used, u_digits, m_used, v_digits);
+        if (ac) {
+          if (c_neg == a_neg) {
+            var c_cmp_a =
+                _compareDigits(c_digits, abcd_used, a_digits, abcd_used);
+            if (c_cmp_a > 0) {
+              _absSub(c_digits, abcd_used, a_digits, abcd_used, c_digits);
+            } else {
+              _absSub(a_digits, abcd_used, c_digits, abcd_used, c_digits);
+              c_neg = !c_neg && (c_cmp_a != 0);
+            }
+          } else {
+            _absAdd(c_digits, abcd_used, a_digits, abcd_used, c_digits);
+          }
+        }
+        if (d_neg == b_neg) {
+          var d_cmp_b =
+              _compareDigits(d_digits, abcd_used, b_digits, abcd_used);
+          if (d_cmp_b > 0) {
+            _absSub(d_digits, abcd_used, b_digits, abcd_used, d_digits);
+          } else {
+            _absSub(b_digits, abcd_used, d_digits, abcd_used, d_digits);
+            d_neg = !d_neg && (d_cmp_ab != 0);
+          }
+        } else {
+          _absAdd(d_digits, abcd_used, b_digits, abcd_used, d_digits);
+        }
+      }
+      // Exit loop if u == 0.
+      var i = m_used;
+      while ((i > 0) && (u_digits[i - 1] == 0)) --i;
+      if (i == 0) break;
+    }
+    // No inverse if v != 1.
+    var i = m_used - 1;
+    while ((i > 0) && (v_digits[i] == 0)) --i;
+    if ((i != 0) || (v_digits[0] != 1)) throw new RangeError("Not coprime");
+
+    if (d_neg) {
+      if ((d_digits[m_used] != 0) ||
+          (_compareDigits(d_digits, m_used, m_digits, m_used) > 0)) {
+        _absSub(d_digits, abcd_used, m_digits, m_used, d_digits);
+        if ((d_digits[m_used] != 0) ||
+            (_compareDigits(d_digits, m_used, m_digits, m_used) > 0)) {
+          _absSub(d_digits, abcd_used, m_digits, m_used, d_digits);
+        } else {
+          _absSub(m_digits, m_used, d_digits, m_used, d_digits);
+          d_neg = false;
+        }
+      } else {
+        _absSub(m_digits, m_used, d_digits, m_used, d_digits);
+        d_neg = false;
+      }
+    } else if ((d_digits[m_used] != 0) ||
+               (_compareDigits(d_digits, m_used, m_digits, m_used) > 0)) {
+      _absSub(d_digits, abcd_used, m_digits, m_used, d_digits);
+      if ((d_digits[m_used] != 0) ||
+          (_compareDigits(d_digits, m_used, m_digits, m_used) > 0)) {
+        _absSub(d_digits, abcd_used, m_digits, m_used, d_digits);
+      }
+    }
+    return new _Bigint(false, m_used, d_digits)._toValidInt();
+  }
 }
 
 // Interface for modular reduction.
diff --git a/runtime/lib/integers.dart b/runtime/lib/integers.dart
index 857a415..1267d15 100644
--- a/runtime/lib/integers.dart
+++ b/runtime/lib/integers.dart
@@ -275,7 +275,6 @@
     if (e is _Bigint || m is _Bigint) {
       return _toBigint().modPow(e, m);
     }
-    if (e < 1) return 1;
     int b = this;
     if (b < 0 || b > m) {
       b %= m;
@@ -290,6 +289,73 @@
     }
     return r;
   }
+
+  // Returns 1/this % m, with m > 0.
+  int modInverse(int m) {
+    if (m is! int) throw new ArgumentError(m);
+    if (m <= 0) throw new RangeError(m);
+    if (m == 1) return 0;
+    if (m is _Bigint) {
+      return _toBigint().modInverse(m);
+    }
+    int t = this;
+    if ((t < 0) || (t >= m)) t %= m;
+    if (t == 1) return 1;
+    final bool ac = m.isEven;
+    if ((t == 0) || (ac && t.isEven)) throw new RangeError("Not coprime");
+    int u = m;
+    int v = t;
+    int a = 1,
+        b = 0,
+        c = 0,
+        d = 1;
+    do {
+      while (u.isEven) {
+        u >>= 1;
+        if (ac) {
+          if (!a.isEven || !b.isEven) {
+            a += t;
+            b -= m;
+          }
+          a >>= 1;
+        } else if (!b.isEven) {
+          b -= m;
+        }
+        b >>= 1;
+      }
+      while (v.isEven) {
+        v >>= 1;
+        if (ac) {
+          if (!c.isEven || !d.isEven) {
+            c += t;
+            d -= m;
+          }
+          c >>= 1;
+        } else if (!d.isEven) {
+          d -= m;
+        }
+        d >>= 1;
+      }
+      if (u >= v) {
+        u -= v;
+        if (ac) a -= c;
+        b -= d;
+      } else {
+        v -= u;
+        if (ac) c -= a;
+        d -= b;
+      }
+    } while (u != 0);
+    if (v != 1) throw new RangeError("Not coprime");
+    if (d < 0) {
+      d += m;
+      if (d < 0) d += m;
+    } else if (d > m) {
+      d -= m;
+      if (d > m) d -= m;
+    }
+    return d;
+  }
 }
 
 class _Smi extends _IntegerImplementation implements int {
diff --git a/runtime/vm/heap.h b/runtime/vm/heap.h
index 928e7c5..6d8752c 100644
--- a/runtime/vm/heap.h
+++ b/runtime/vm/heap.h
@@ -105,10 +105,13 @@
   bool CodeContains(uword addr) const;
   bool StubCodeContains(uword addr) const;
 
-  // Visit all pointers.
+  // Visit all pointers. Caller must ensure concurrent sweeper is not running,
+  // and the visitor must not allocate (see issue 21620).
   void VisitObjectPointers(ObjectPointerVisitor* visitor) const;
 
-  // Visit all objects.
+  // Visit all objects, including FreeListElement "objects". Caller must ensure
+  // concurrent sweeper is not running, and the visitor must not allocate (see
+  // issue 21620).
   void VisitObjects(ObjectVisitor* visitor) const;
 
   // Find an object by visiting all pointers in the specified heap space,
diff --git a/runtime/vm/object_graph.cc b/runtime/vm/object_graph.cc
index 773839d..b07fe0a 100644
--- a/runtime/vm/object_graph.cc
+++ b/runtime/vm/object_graph.cc
@@ -172,6 +172,11 @@
 
 void ObjectGraph::IterateObjects(ObjectGraph::Visitor* visitor) {
   NoSafepointScope no_safepoint_scope_;
+  PageSpace* old_space = isolate()->heap()->old_space();
+  MonitorLocker ml(old_space->tasks_lock());
+  while (old_space->tasks() > 0) {
+    ml.Wait();
+  }
   Stack stack(isolate());
   isolate()->VisitObjectPointers(&stack, false, false);
   stack.TraverseGraph(visitor);
@@ -182,6 +187,11 @@
 void ObjectGraph::IterateObjectsFrom(const Object& root,
                                      ObjectGraph::Visitor* visitor) {
   NoSafepointScope no_safepoint_scope_;
+  PageSpace* old_space = isolate()->heap()->old_space();
+  MonitorLocker ml(old_space->tasks_lock());
+  while (old_space->tasks() > 0) {
+    ml.Wait();
+  }
   Stack stack(isolate());
   RawObject* root_raw = root.raw();
   stack.VisitPointer(&root_raw);
diff --git a/runtime/vm/object_graph_test.cc b/runtime/vm/object_graph_test.cc
index 66771db..00f7768 100644
--- a/runtime/vm/object_graph_test.cc
+++ b/runtime/vm/object_graph_test.cc
@@ -112,6 +112,8 @@
     {
       HANDLESCOPE(isolate);
       Array& path = Array::Handle(Array::New(6, Heap::kNew));
+      // Trigger a full GC to increase probability of concurrent tasks.
+      isolate->heap()->CollectAllGarbage();
       intptr_t length = graph.RetainingPath(&c, path);
       EXPECT_LE(3, length);
       Array& expected_c = Array::Handle();
diff --git a/runtime/vm/pages.cc b/runtime/vm/pages.cc
index 810554a..18eec36 100644
--- a/runtime/vm/pages.cc
+++ b/runtime/vm/pages.cc
@@ -83,6 +83,7 @@
 
 
 void HeapPage::VisitObjects(ObjectVisitor* visitor) const {
+  NoSafepointScope no_safepoint;
   uword obj_addr = object_start();
   uword end_addr = object_end();
   while (obj_addr < end_addr) {
@@ -95,6 +96,7 @@
 
 
 void HeapPage::VisitObjectPointers(ObjectPointerVisitor* visitor) const {
+  NoSafepointScope no_safepoint;
   uword obj_addr = object_start();
   uword end_addr = object_end();
   while (obj_addr < end_addr) {
diff --git a/sdk/lib/_internal/compiler/js_lib/js_number.dart b/sdk/lib/_internal/compiler/js_lib/js_number.dart
index 8ea8a03..8822911 100644
--- a/sdk/lib/_internal/compiler/js_lib/js_number.dart
+++ b/sdk/lib/_internal/compiler/js_lib/js_number.dart
@@ -411,6 +411,70 @@
     return r;
   }
 
+  // Returns 1/this % m, with m > 0.
+  int modInverse(int m) {
+    if (m is! int) throw new ArgumentError(m);
+    if (m <= 0) throw new RangeError(m);
+    if (m == 1) return 0;
+    int t = this;
+    if ((t < 0) || (t >= m)) t %= m;
+    if (t == 1) return 1;
+    final bool ac = m.isEven;
+    if ((t == 0) || (ac && t.isEven)) throw new RangeError("Not coprime");
+    int u = m;
+    int v = t;
+    int a = 1,
+        b = 0,
+        c = 0,
+        d = 1;
+    do {
+      while (u.isEven) {
+        u ~/= 2;
+        if (ac) {
+          if (!a.isEven || !b.isEven) {
+            a += t;
+            b -= m;
+          }
+          a ~/= 2;
+        } else if (!b.isEven) {
+          b -= m;
+        }
+        b ~/= 2;
+      }
+      while (v.isEven) {
+        v ~/= 2;
+        if (ac) {
+          if (!c.isEven || !d.isEven) {
+            c += t;
+            d -= m;
+          }
+          c ~/= 2;
+        } else if (!d.isEven) {
+          d -= m;
+        }
+        d ~/= 2;
+      }
+      if (u >= v) {
+        u -= v;
+        if (ac) a -= c;
+        b -= d;
+      } else {
+        v -= u;
+        if (ac) c -= a;
+        d -= b;
+      }
+    } while (u != 0);
+    if (v != 1) throw new RangeError("Not coprime");
+    if (d < 0) {
+      d += m;
+      if (d < 0) d += m;
+    } else if (d > m) {
+      d -= m;
+      if (d > m) d -= m;
+    }
+    return d;
+  }
+
   // Assumes i is <= 32-bit and unsigned.
   static int _bitCount(int i) {
     // See "Hacker's Delight", section 5-1, "Counting 1-Bits".
diff --git a/sdk/lib/core/int.dart b/sdk/lib/core/int.dart
index 1d29a72..5aee609 100644
--- a/sdk/lib/core/int.dart
+++ b/sdk/lib/core/int.dart
@@ -111,6 +111,15 @@
    */
   int modPow(int exponent, int modulus);
 
+  /**
+   * Returns the modular multiplicative inverse of this integer
+   * modulo [modulus].
+   *
+   * The [modulus] must be positive.
+   * Throws a RangeError if no modular inverse exists.
+   */
+  int modInverse(int modulus);
+
   /** Returns true if and only if this integer is even. */
   bool get isEven;
 
diff --git a/tests/corelib/big_integer_arith_vm_test.dart b/tests/corelib/big_integer_arith_vm_test.dart
index 4c04c03..3353756 100644
--- a/tests/corelib/big_integer_arith_vm_test.dart
+++ b/tests/corelib/big_integer_arith_vm_test.dart
@@ -223,6 +223,76 @@
   Expect.equals(40128068573873018143207285483, x.modPow(e, m));
 }
 
+testBigintModInverse() {
+  var x, m;
+  x = 1;
+  m = 1;
+  Expect.equals(0, x.modInverse(m));
+  x = 0;
+  m = 1000000001;
+  Expect.throws(() => x.modInverse(m), (e) => e is RangeError);  // Not coprime.
+  x = 1234567890;
+  m = 19;
+  Expect.equals(11, x.modInverse(m));
+  x = 1234567890;
+  m = 1000000001;
+  Expect.equals(189108911, x.modInverse(m));
+  x = 19;
+  m = 1000000001;
+  Expect.throws(() => x.modInverse(m), (e) => e is RangeError);  // Not coprime.
+  x = 19;
+  m = 1234567890;
+  Expect.equals(519818059, x.modInverse(m));
+  x = 1000000001;
+  m = 1234567890;
+  Expect.equals(1001100101, x.modInverse(m));
+  x = 1000000001;
+  m = 19;
+  Expect.throws(() => x.modInverse(m), (e) => e is RangeError);  // Not coprime.
+  x = 12345678901234567890;
+  m = 19;
+  Expect.equals(3, x.modInverse(m));
+  x = 12345678901234567890;
+  m = 10000000000000000001;
+  Expect.equals(9736746307686209582, x.modInverse(m));
+  x = 19;
+  m = 10000000000000000001;
+  Expect.equals(6315789473684210527, x.modInverse(m));
+  x = 19;
+  m = 12345678901234567890;
+  Expect.equals(10396361179987004539, x.modInverse(m));
+  x = 10000000000000000001;
+  m = 12345678901234567890;
+  Expect.equals(325004555487045911, x.modInverse(m));
+  x = 10000000000000000001;
+  m = 19;
+  Expect.equals(7, x.modInverse(m));
+  x = 12345678901234567890;
+  m = 10000000000000000001;
+  Expect.equals(9736746307686209582, x.modInverse(m));
+  x = 12345678901234567890;
+  m = 19;
+  Expect.equals(3, x.modInverse(m));
+  x = 123456789012345678901234567890;
+  m = 123456789012345678901234567899;
+  Expect.throws(() => x.modInverse(m), (e) => e is RangeError);  // Not coprime.
+  x = 123456789012345678901234567890;
+  m = 123456789012345678901234567891;
+  Expect.equals(123456789012345678901234567890, x.modInverse(m));
+  x = 123456789012345678901234567899;
+  m = 123456789012345678901234567891;
+  Expect.equals(77160493132716049313271604932, x.modInverse(m));
+  x = 123456789012345678901234567899;
+  m = 123456789012345678901234567890;
+  Expect.throws(() => x.modInverse(m), (e) => e is RangeError);  // Not coprime.
+  x = 123456789012345678901234567891;
+  m = 123456789012345678901234567890;
+  Expect.equals(1, x.modInverse(m));
+  x = 123456789012345678901234567891;
+  m = 123456789012345678901234567899;
+  Expect.equals(46296295879629629587962962962, x.modInverse(m));
+}
+
 testBigintNegate() {
   var a = 0xF000000000000000F;
   var b = ~a;  // negate.
@@ -254,6 +324,7 @@
   testBigintDiv();
   testBigintModulo();
   testBigintModPow();
+  testBigintModInverse();
   testBigintNegate();
   testShiftAmount();
   Expect.equals(12345678901234567890, (12345678901234567890).abs());
diff --git a/tools/VERSION b/tools/VERSION
index b996cf7..1782662 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -28,4 +28,4 @@
 MINOR 11
 PATCH 0
 PRERELEASE 5
-PRERELEASE_PATCH 4
+PRERELEASE_PATCH 5