Frank-Rainer Grahl 6 months ago
parent
commit
d4bc02a28b
100 changed files with 4565 additions and 9593 deletions
  1. 4 4
      frg/work-js/mozilla-release/patches/1033916-1-63a1.patch
  2. 10 10
      frg/work-js/mozilla-release/patches/1040316-63a1.patch
  3. 0 0
      frg/work-js/mozilla-release/patches/1073753-63a1.patch
  4. 0 0
      frg/work-js/mozilla-release/patches/1341261-0-63a1.patch
  5. 0 0
      frg/work-js/mozilla-release/patches/1341261-1-63a1.patch
  6. 0 0
      frg/work-js/mozilla-release/patches/1341261-2-63a1.patch
  7. 0 0
      frg/work-js/mozilla-release/patches/1341261-3-63a1.patch
  8. 0 0
      frg/work-js/mozilla-release/patches/1341261-4-63a1.patch
  9. 0 0
      frg/work-js/mozilla-release/patches/1341261-5-63a1.patch
  10. 0 0
      frg/work-js/mozilla-release/patches/1341261-6-63a1.patch
  11. 0 0
      frg/work-js/mozilla-release/patches/1341261-7-63a1.patch
  12. 0 0
      frg/work-js/mozilla-release/patches/1341261-8-63a1.patch
  13. 0 0
      frg/work-js/mozilla-release/patches/1341261-9-63a1.patch
  14. 0 0
      frg/work-js/mozilla-release/patches/1343981-63a1.patch
  15. 12 12
      frg/work-js/mozilla-release/patches/1346211-2-63a1.patch
  16. 2 3
      frg/work-js/mozilla-release/patches/1346211-6-63a1.patch
  17. 22 2
      frg/work-js/mozilla-release/patches/1378808-3-63a1.patch
  18. 5 5
      frg/work-js/mozilla-release/patches/1423577-63a1.patch
  19. 36 688
      frg/work-js/mozilla-release/patches/1469395-1-63a1.patch
  20. 0 0
      frg/work-js/mozilla-release/patches/1469395-2-63a1.patch
  21. 0 0
      frg/work-js/mozilla-release/patches/1473213-1-63a1.patch
  22. 3 3
      frg/work-js/mozilla-release/patches/1473213-2-63a1.patch
  23. 0 0
      frg/work-js/mozilla-release/patches/1473213-3-63a1.patch
  24. 17 17
      frg/work-js/mozilla-release/patches/1473213-4-63a1.patch
  25. 6 6
      frg/work-js/mozilla-release/patches/1473213-5-63a1.patch
  26. 1085 0
      frg/work-js/mozilla-release/patches/1478885-63a1.patch
  27. 3 3
      frg/work-js/mozilla-release/patches/1478892-2-63a1.patch
  28. 2 3
      frg/work-js/mozilla-release/patches/1478892-3-63a1.patch
  29. 38 41
      frg/work-js/mozilla-release/patches/1479900-2-63a1.patch
  30. 0 0
      frg/work-js/mozilla-release/patches/1480004-63a1.patch
  31. 760 0
      frg/work-js/mozilla-release/patches/1480323-63a1.patch
  32. 49 0
      frg/work-js/mozilla-release/patches/1480361-1-63a1.patch
  33. 137 0
      frg/work-js/mozilla-release/patches/1480361-2-63a1.patch
  34. 0 0
      frg/work-js/mozilla-release/patches/1480575-63a1.patch
  35. 319 0
      frg/work-js/mozilla-release/patches/1480650-63a1.patch
  36. 0 0
      frg/work-js/mozilla-release/patches/1480668-63a1.patch
  37. 0 0
      frg/work-js/mozilla-release/patches/1480843-63a1.patch
  38. 0 0
      frg/work-js/mozilla-release/patches/1481138-1-63a1.patch
  39. 0 0
      frg/work-js/mozilla-release/patches/1481138-2-63a1.patch
  40. 157 0
      frg/work-js/mozilla-release/patches/1481138-3-63a1.patch
  41. 13 12
      frg/work-js/mozilla-release/patches/1481171-1-63a1.patch
  42. 0 0
      frg/work-js/mozilla-release/patches/1481171-2-63a1.patch
  43. 0 0
      frg/work-js/mozilla-release/patches/1481171-3-63a1.patch
  44. 0 0
      frg/work-js/mozilla-release/patches/1481239-63a1.patch
  45. 0 0
      frg/work-js/mozilla-release/patches/1481247-63a1.patch
  46. 0 0
      frg/work-js/mozilla-release/patches/1481484-63a1.patch
  47. 0 0
      frg/work-js/mozilla-release/patches/1481556-63a1.patch
  48. 0 0
      frg/work-js/mozilla-release/patches/1481858-63a1.patch
  49. 51 0
      frg/work-js/mozilla-release/patches/1481998-2no1-63a1.patch
  50. 97 333
      frg/work-js/mozilla-release/patches/1481998-3-63a1.patch
  51. 0 0
      frg/work-js/mozilla-release/patches/1482133-1-63a1.patch
  52. 0 0
      frg/work-js/mozilla-release/patches/1482133-2-63a1.patch
  53. 0 0
      frg/work-js/mozilla-release/patches/1482133-3-63a1.patch
  54. 0 0
      frg/work-js/mozilla-release/patches/1482135-63a1.patch
  55. 0 0
      frg/work-js/mozilla-release/patches/1482359-63a1.patch
  56. 0 0
      frg/work-js/mozilla-release/patches/1482365-63a1.patch
  57. 0 0
      frg/work-js/mozilla-release/patches/1482846-1-63a1.patch
  58. 0 0
      frg/work-js/mozilla-release/patches/1482846-2-63a1.patch
  59. 0 0
      frg/work-js/mozilla-release/patches/1482846-3-63a1.patch
  60. 0 0
      frg/work-js/mozilla-release/patches/1482846-4-63a1.patch
  61. 18 18
      frg/work-js/mozilla-release/patches/1482931-1-63a1.patch
  62. 41 0
      frg/work-js/mozilla-release/patches/1483062-1-63a1.patch
  63. 92 0
      frg/work-js/mozilla-release/patches/1483062-2-63a1.patch
  64. 205 0
      frg/work-js/mozilla-release/patches/1483062-3-63a1.patch
  65. 80 0
      frg/work-js/mozilla-release/patches/1483062-4-63a1.patch
  66. 53 0
      frg/work-js/mozilla-release/patches/1483062-5-63a1.patch
  67. 43 0
      frg/work-js/mozilla-release/patches/1483062-6-63a1.patch
  68. 104 0
      frg/work-js/mozilla-release/patches/1483062-7-63a1.patch
  69. 59 0
      frg/work-js/mozilla-release/patches/1483062-8-63a1.patch
  70. 307 0
      frg/work-js/mozilla-release/patches/1483182-1-63a1.patch
  71. 32 0
      frg/work-js/mozilla-release/patches/1483182-2-63a1.patch
  72. 0 0
      frg/work-js/mozilla-release/patches/1483189-1-63a1.patch
  73. 0 0
      frg/work-js/mozilla-release/patches/1483189-2-63a1.patch
  74. 0 0
      frg/work-js/mozilla-release/patches/1483542-63a1.patch
  75. 4 4
      frg/work-js/mozilla-release/patches/1486577-6-63a1.patch
  76. 243 180
      frg/work-js/mozilla-release/patches/1488698-7-WIP-64a1.patch
  77. 4 20
      frg/work-js/mozilla-release/patches/1489698-5-65a1.patch
  78. 56 56
      frg/work-js/mozilla-release/patches/1494752-604.patch
  79. 10 10
      frg/work-js/mozilla-release/patches/1502886-1-65a1.patch
  80. 318 0
      frg/work-js/mozilla-release/patches/1503116-65a1.patch
  81. 15 15
      frg/work-js/mozilla-release/patches/1557583-2-69a1.patch
  82. 11 9
      frg/work-js/mozilla-release/patches/1727374-914.patch
  83. 17 17
      frg/work-js/mozilla-release/patches/TOP-NOBUG-REGEXP-04-1539690-68a1-25318.patch
  84. 3 3
      frg/work-js/mozilla-release/patches/TOP-NOBUG-REGEXP-22-1637977-78a1-25318.patch
  85. 7 7
      frg/work-js/mozilla-release/patches/TOP-NOBUG-REGEXP-24-1631504-77a1-25318.patch
  86. 15 15
      frg/work-js/mozilla-release/patches/TOP-NOBUG-REGEXP-37-1642493-79a1-25318.patch
  87. 0 33
      frg/work-js/mozilla-release/patches/mozilla-central-push_430283.patch
  88. 0 37
      frg/work-js/mozilla-release/patches/mozilla-central-push_430518.patch
  89. 0 352
      frg/work-js/mozilla-release/patches/mozilla-central-push_430534.patch
  90. 0 1589
      frg/work-js/mozilla-release/patches/mozilla-central-push_430605.patch
  91. 0 122
      frg/work-js/mozilla-release/patches/mozilla-central-push_430690.patch
  92. 0 47
      frg/work-js/mozilla-release/patches/mozilla-central-push_430691.patch
  93. 0 216
      frg/work-js/mozilla-release/patches/mozilla-central-push_430692.patch
  94. 0 62
      frg/work-js/mozilla-release/patches/mozilla-central-push_430732.patch
  95. 0 945
      frg/work-js/mozilla-release/patches/mozilla-central-push_430740.patch
  96. 0 1043
      frg/work-js/mozilla-release/patches/mozilla-central-push_430741.patch
  97. 0 952
      frg/work-js/mozilla-release/patches/mozilla-central-push_430918.patch
  98. 0 1092
      frg/work-js/mozilla-release/patches/mozilla-central-push_430919.patch
  99. 0 667
      frg/work-js/mozilla-release/patches/mozilla-central-push_430920.patch
  100. 0 940
      frg/work-js/mozilla-release/patches/mozilla-central-push_430921.patch

+ 4 - 4
frg/work-js/mozilla-release/patches/1033916-1-63a1.patch

@@ -2,7 +2,7 @@
 # User Jeff Walden <jwalden@mit.edu>
 # User Jeff Walden <jwalden@mit.edu>
 # Date 1534776368 25200
 # Date 1534776368 25200
 # Node ID 67d5039dcbc2522e187bcf3dbec1c6e92bd32167
 # Node ID 67d5039dcbc2522e187bcf3dbec1c6e92bd32167
-# Parent  4747226f3acc079743e8d98e52d29fd32ca528e9
+# Parent  d2f9c12b057cf777ea69ab0ac6a855cdae701411
 Bug 1033916 - Move JSAutoByteString out of jsapi.h into js/public/AutoByteString.h, incidentally breaking the jsfriendapi.h -> jsapi.h dependency.  r=jandem
 Bug 1033916 - Move JSAutoByteString out of jsapi.h into js/public/AutoByteString.h, incidentally breaking the jsfriendapi.h -> jsapi.h dependency.  r=jandem
 
 
 diff --git a/dom/base/ChromeUtils.cpp b/dom/base/ChromeUtils.cpp
 diff --git a/dom/base/ChromeUtils.cpp b/dom/base/ChromeUtils.cpp
@@ -801,7 +801,7 @@ diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp
 diff --git a/js/src/vm/BytecodeUtil.cpp b/js/src/vm/BytecodeUtil.cpp
 diff --git a/js/src/vm/BytecodeUtil.cpp b/js/src/vm/BytecodeUtil.cpp
 --- a/js/src/vm/BytecodeUtil.cpp
 --- a/js/src/vm/BytecodeUtil.cpp
 +++ b/js/src/vm/BytecodeUtil.cpp
 +++ b/js/src/vm/BytecodeUtil.cpp
-@@ -28,16 +28,17 @@
+@@ -27,16 +27,17 @@
  #include "jstypes.h"
  #include "jstypes.h"
  #include "jsutil.h"
  #include "jsutil.h"
  
  
@@ -1180,7 +1180,8 @@ diff --git a/js/src/vm/Xdr.h b/js/src/vm/Xdr.h
 diff --git a/js/src/wasm/AsmJS.cpp b/js/src/wasm/AsmJS.cpp
 diff --git a/js/src/wasm/AsmJS.cpp b/js/src/wasm/AsmJS.cpp
 --- a/js/src/wasm/AsmJS.cpp
 --- a/js/src/wasm/AsmJS.cpp
 +++ b/js/src/wasm/AsmJS.cpp
 +++ b/js/src/wasm/AsmJS.cpp
-@@ -28,16 +28,17 @@
+@@ -27,16 +27,17 @@
+ #include <new>
  
  
  #include "jsmath.h"
  #include "jsmath.h"
  #include "jsutil.h"
  #include "jsutil.h"
@@ -1188,7 +1189,6 @@ diff --git a/js/src/wasm/AsmJS.cpp b/js/src/wasm/AsmJS.cpp
  #include "builtin/String.h"
  #include "builtin/String.h"
  #include "frontend/Parser.h"
  #include "frontend/Parser.h"
  #include "gc/Policy.h"
  #include "gc/Policy.h"
- #include "jit/AtomicOperations.h"
 +#include "js/AutoByteString.h"
 +#include "js/AutoByteString.h"
  #include "js/MemoryMetrics.h"
  #include "js/MemoryMetrics.h"
  #include "js/Printf.h"
  #include "js/Printf.h"

+ 10 - 10
frg/work-js/mozilla-release/patches/1040316-63a1.patch

@@ -2,7 +2,7 @@
 # User Jeff Walden <jwalden@mit.edu>
 # User Jeff Walden <jwalden@mit.edu>
 # Date 1534776284 25200
 # Date 1534776284 25200
 # Node ID 6d10eda7f12de64044246e544d581537f30f8998
 # Node ID 6d10eda7f12de64044246e544d581537f30f8998
-# Parent  cc5a2884e3f81b30b80b4da0e8f6922db63c8c6a
+# Parent  2487164942a9bf4856a73a596d368630930a5e33
 Bug 1040316 - Move AutoStableStringChars out of friendapi into public API.  r=jandem
 Bug 1040316 - Move AutoStableStringChars out of friendapi into public API.  r=jandem
 
 
 diff --git a/dom/base/nsJSUtils.h b/dom/base/nsJSUtils.h
 diff --git a/dom/base/nsJSUtils.h b/dom/base/nsJSUtils.h
@@ -973,7 +973,7 @@ diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp
  #include "shell/jsshell.h"
  #include "shell/jsshell.h"
  #include "shell/OSObject.h"
  #include "shell/OSObject.h"
  #include "threading/ConditionVariable.h"
  #include "threading/ConditionVariable.h"
-@@ -117,16 +118,18 @@
+@@ -118,16 +119,18 @@
  #include "vm/JSObject-inl.h"
  #include "vm/JSObject-inl.h"
  #include "vm/Realm-inl.h"
  #include "vm/Realm-inl.h"
  #include "vm/Stack-inl.h"
  #include "vm/Stack-inl.h"
@@ -1061,12 +1061,12 @@ diff --git a/js/src/vm/Compartment.cpp b/js/src/vm/Compartment.cpp
 +
 +
  Compartment::Compartment(Zone* zone)
  Compartment::Compartment(Zone* zone)
    : zone_(zone),
    : zone_(zone),
-     runtime_(zone->runtimeFromAnyThread())
+     runtime_(zone->runtimeFromAnyThread()),
+     crossCompartmentWrappers(0)
  {}
  {}
  
  
- bool
- Compartment::init(JSContext* cx)
- {
+ #ifdef JSGC_HASH_TABLE_CHECKS
+ 
 diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp
 diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp
 --- a/js/src/vm/Debugger.cpp
 --- a/js/src/vm/Debugger.cpp
 +++ b/js/src/vm/Debugger.cpp
 +++ b/js/src/vm/Debugger.cpp
@@ -1106,7 +1106,7 @@ diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp
  using mozilla::Maybe;
  using mozilla::Maybe;
  using mozilla::Some;
  using mozilla::Some;
  using mozilla::Nothing;
  using mozilla::Nothing;
-@@ -5084,17 +5086,17 @@ Debugger::isCompilableUnit(JSContext* cx
+@@ -5029,17 +5031,17 @@ Debugger::isCompilableUnit(JSContext* cx
      if (!args[0].isString()) {
      if (!args[0].isString()) {
          JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_NOT_EXPECTED_TYPE,
          JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_NOT_EXPECTED_TYPE,
                                    "Debugger.isCompilableUnit", "string",
                                    "Debugger.isCompilableUnit", "string",
@@ -1393,13 +1393,13 @@ diff --git a/js/src/vm/UbiNodeCensus.cpp b/js/src/vm/UbiNodeCensus.cpp
 diff --git a/js/src/wasm/AsmJS.cpp b/js/src/wasm/AsmJS.cpp
 diff --git a/js/src/wasm/AsmJS.cpp b/js/src/wasm/AsmJS.cpp
 --- a/js/src/wasm/AsmJS.cpp
 --- a/js/src/wasm/AsmJS.cpp
 +++ b/js/src/wasm/AsmJS.cpp
 +++ b/js/src/wasm/AsmJS.cpp
-@@ -30,16 +30,17 @@
+@@ -29,16 +29,17 @@
+ #include "jsmath.h"
  #include "jsutil.h"
  #include "jsutil.h"
  
  
  #include "builtin/String.h"
  #include "builtin/String.h"
  #include "frontend/Parser.h"
  #include "frontend/Parser.h"
  #include "gc/Policy.h"
  #include "gc/Policy.h"
- #include "jit/AtomicOperations.h"
  #include "js/MemoryMetrics.h"
  #include "js/MemoryMetrics.h"
  #include "js/Printf.h"
  #include "js/Printf.h"
 +#include "js/StableStringChars.h"
 +#include "js/StableStringChars.h"
@@ -1411,7 +1411,7 @@ diff --git a/js/src/wasm/AsmJS.cpp b/js/src/wasm/AsmJS.cpp
  #include "vm/Time.h"
  #include "vm/Time.h"
  #include "vm/TypedArrayObject.h"
  #include "vm/TypedArrayObject.h"
  #include "wasm/WasmCompile.h"
  #include "wasm/WasmCompile.h"
-@@ -66,16 +67,17 @@ using mozilla::HashGeneric;
+@@ -65,16 +66,17 @@ using mozilla::HashGeneric;
  using mozilla::IsNaN;
  using mozilla::IsNaN;
  using mozilla::IsNegativeZero;
  using mozilla::IsNegativeZero;
  using mozilla::IsPositiveZero;
  using mozilla::IsPositiveZero;

+ 0 - 0
frg/work-js/mozilla-release/patches/mozilla-central-push_430503.patch → frg/work-js/mozilla-release/patches/1073753-63a1.patch


+ 0 - 0
frg/work-js/mozilla-release/patches/mozilla-central-push_431250.patch → frg/work-js/mozilla-release/patches/1341261-0-63a1.patch


+ 0 - 0
frg/work-js/mozilla-release/patches/mozilla-central-push_431251.patch → frg/work-js/mozilla-release/patches/1341261-1-63a1.patch


+ 0 - 0
frg/work-js/mozilla-release/patches/mozilla-central-push_431252.patch → frg/work-js/mozilla-release/patches/1341261-2-63a1.patch


+ 0 - 0
frg/work-js/mozilla-release/patches/mozilla-central-push_431253.patch → frg/work-js/mozilla-release/patches/1341261-3-63a1.patch


+ 0 - 0
frg/work-js/mozilla-release/patches/mozilla-central-push_431254.patch → frg/work-js/mozilla-release/patches/1341261-4-63a1.patch


+ 0 - 0
frg/work-js/mozilla-release/patches/mozilla-central-push_431255.patch → frg/work-js/mozilla-release/patches/1341261-5-63a1.patch


+ 0 - 0
frg/work-js/mozilla-release/patches/mozilla-central-push_431256.patch → frg/work-js/mozilla-release/patches/1341261-6-63a1.patch


+ 0 - 0
frg/work-js/mozilla-release/patches/mozilla-central-push_431257.patch → frg/work-js/mozilla-release/patches/1341261-7-63a1.patch


+ 0 - 0
frg/work-js/mozilla-release/patches/mozilla-central-push_431258.patch → frg/work-js/mozilla-release/patches/1341261-8-63a1.patch


+ 0 - 0
frg/work-js/mozilla-release/patches/mozilla-central-push_431259.patch → frg/work-js/mozilla-release/patches/1341261-9-63a1.patch


+ 0 - 0
frg/work-js/mozilla-release/patches/mozilla-central-push_430830.patch → frg/work-js/mozilla-release/patches/1343981-63a1.patch


+ 12 - 12
frg/work-js/mozilla-release/patches/1346211-2-63a1.patch

@@ -2,7 +2,7 @@
 # User Andre Bargull <andre.bargull@gmail.com>
 # User Andre Bargull <andre.bargull@gmail.com>
 # Date 1534435998 25200
 # Date 1534435998 25200
 # Node ID 62d58886e8d759f52c871a82dbe4d9c2a266c0c7
 # Node ID 62d58886e8d759f52c871a82dbe4d9c2a266c0c7
-# Parent  ae401d109b1753770507553ac341a8d76eb29bfd
+# Parent  3e876330e68a2879b634dfe96853cfff96c1367e
 Bug 1346211 - Part 2: Split JS::ResetTimeZone into an external and internal implementation. r=Waldo
 Bug 1346211 - Part 2: Split JS::ResetTimeZone into an external and internal implementation. r=Waldo
 
 
 diff --git a/js/public/Date.h b/js/public/Date.h
 diff --git a/js/public/Date.h b/js/public/Date.h
@@ -399,7 +399,7 @@ diff --git a/js/src/vm/Realm.cpp b/js/src/vm/Realm.cpp
  #include "gc/GC-inl.h"
  #include "gc/GC-inl.h"
  #include "gc/Marking-inl.h"
  #include "gc/Marking-inl.h"
  #include "vm/JSAtom-inl.h"
  #include "vm/JSAtom-inl.h"
-@@ -107,17 +108,17 @@ bool
+@@ -102,17 +103,17 @@ bool
  Realm::init(JSContext* cx)
  Realm::init(JSContext* cx)
  {
  {
      /*
      /*
@@ -414,10 +414,10 @@ diff --git a/js/src/vm/Realm.cpp b/js/src/vm/Realm.cpp
      if (!objects_.init(cx))
      if (!objects_.init(cx))
          return false;
          return false;
  
  
-     if (!savedStacks_.init() ||
-         !varNames_.init())
-     {
-         ReportOutOfMemory(cx);
+     return true;
+ }
+ 
+ jit::JitRuntime*
 diff --git a/js/src/vm/Runtime.cpp b/js/src/vm/Runtime.cpp
 diff --git a/js/src/vm/Runtime.cpp b/js/src/vm/Runtime.cpp
 --- a/js/src/vm/Runtime.cpp
 --- a/js/src/vm/Runtime.cpp
 +++ b/js/src/vm/Runtime.cpp
 +++ b/js/src/vm/Runtime.cpp
@@ -439,8 +439,8 @@ diff --git a/js/src/vm/Runtime.cpp b/js/src/vm/Runtime.cpp
  #include "vm/TraceLoggingGraph.h"
  #include "vm/TraceLoggingGraph.h"
  
  
  #include "gc/GC-inl.h"
  #include "gc/GC-inl.h"
-@@ -227,17 +228,17 @@ JSRuntime::init(JSContext* cx, uint32_t 
-         return false;
+@@ -223,17 +224,17 @@ JSRuntime::init(JSContext* cx, uint32_t 
+     gc.atomsZone = atomsZone.release();
  
  
      /* The garbage collector depends on everything before this point being initialized. */
      /* The garbage collector depends on everything before this point being initialized. */
      gcInitialized = true;
      gcInitialized = true;
@@ -455,13 +455,13 @@ diff --git a/js/src/vm/Runtime.cpp b/js/src/vm/Runtime.cpp
      jitSupportsUnalignedAccesses = js::jit::JitSupportsUnalignedAccesses();
      jitSupportsUnalignedAccesses = js::jit::JitSupportsUnalignedAccesses();
      jitSupportsSimd = js::jit::JitSupportsSimd();
      jitSupportsSimd = js::jit::JitSupportsSimd();
  
  
-     if (!geckoProfiler().init())
-         return false;
- 
+     if (!parentRuntime) {
+         sharedImmutableStrings_ = js::SharedImmutableStringsCache::Create();
+         if (!sharedImmutableStrings_)
 diff --git a/js/src/vm/Runtime.h b/js/src/vm/Runtime.h
 diff --git a/js/src/vm/Runtime.h b/js/src/vm/Runtime.h
 --- a/js/src/vm/Runtime.h
 --- a/js/src/vm/Runtime.h
 +++ b/js/src/vm/Runtime.h
 +++ b/js/src/vm/Runtime.h
-@@ -36,17 +36,16 @@
+@@ -37,17 +37,16 @@
  #endif
  #endif
  #include "js/UniquePtr.h"
  #include "js/UniquePtr.h"
  #include "js/Utility.h"
  #include "js/Utility.h"

+ 2 - 3
frg/work-js/mozilla-release/patches/1346211-6-63a1.patch

@@ -2,7 +2,7 @@
 # User Andre Bargull <andre.bargull@gmail.com>
 # User Andre Bargull <andre.bargull@gmail.com>
 # Date 1534500279 25200
 # Date 1534500279 25200
 # Node ID 7b1a3a49547dc9564aaa6ecf90b919b66b7ada8d
 # Node ID 7b1a3a49547dc9564aaa6ecf90b919b66b7ada8d
-# Parent  18dbc987f837f547838c2b012aeba86c1169384c
+# Parent  dc10e4300c0519229d03cd66cb4abd10c357f896
 Bug 1346211 - Part 6: Use ICU for all time zone computations when available. r=Waldo
 Bug 1346211 - Part 6: Use ICU for all time zone computations when available. r=Waldo
 
 
 diff --git a/browser/components/resistfingerprinting/test/browser/browser_timezone.js b/browser/components/resistfingerprinting/test/browser/browser_timezone.js
 diff --git a/browser/components/resistfingerprinting/test/browser/browser_timezone.js b/browser/components/resistfingerprinting/test/browser/browser_timezone.js
@@ -3431,7 +3431,7 @@ diff --git a/js/src/vm/DateTime.h b/js/src/vm/DateTime.h
 diff --git a/js/src/vm/MutexIDs.h b/js/src/vm/MutexIDs.h
 diff --git a/js/src/vm/MutexIDs.h b/js/src/vm/MutexIDs.h
 --- a/js/src/vm/MutexIDs.h
 --- a/js/src/vm/MutexIDs.h
 +++ b/js/src/vm/MutexIDs.h
 +++ b/js/src/vm/MutexIDs.h
-@@ -37,31 +37,31 @@
+@@ -37,30 +37,30 @@
    _(ShellOffThreadState,         500) \
    _(ShellOffThreadState,         500) \
    _(SimulatorCacheLock,          500) \
    _(SimulatorCacheLock,          500) \
    _(Arm64SimulatorLock,          500) \
    _(Arm64SimulatorLock,          500) \
@@ -3448,7 +3448,6 @@ diff --git a/js/src/vm/MutexIDs.h b/js/src/vm/MutexIDs.h
    _(RuntimeScriptData,           500) \
    _(RuntimeScriptData,           500) \
    _(WasmFuncTypeIdSet,           500) \
    _(WasmFuncTypeIdSet,           500) \
    _(WasmCodeProfilingLabels,     500) \
    _(WasmCodeProfilingLabels,     500) \
-   _(WasmModuleTieringLock,       500) \
    _(WasmCompileTaskState,        500) \
    _(WasmCompileTaskState,        500) \
    _(WasmCodeStreamEnd,           500) \
    _(WasmCodeStreamEnd,           500) \
    _(WasmTailBytesPtr,            500) \
    _(WasmTailBytesPtr,            500) \

+ 22 - 2
frg/work-js/mozilla-release/patches/1378808-3-63a1.patch

@@ -2,13 +2,13 @@
 # User Logan F Smyth <loganfsmyth@gmail.com>
 # User Logan F Smyth <loganfsmyth@gmail.com>
 # Date 1531421477 25200
 # Date 1531421477 25200
 # Node ID 50338591c8f31326a22921c10cc470849aa4e430
 # Node ID 50338591c8f31326a22921c10cc470849aa4e430
-# Parent  6b41490df55b98d9ae91f1015040a757267e01a9
+# Parent  45de846732534bba82ecf0c6a79c0afb490c823f
 Bug 1378808 - Use ::Arguments or ::PropertyName location for method call column offsets. r=jorendorff, r=ckerschb
 Bug 1378808 - Use ::Arguments or ::PropertyName location for method call column offsets. r=jorendorff, r=ckerschb
 
 
 diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp
 diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp
 --- a/js/src/frontend/BytecodeEmitter.cpp
 --- a/js/src/frontend/BytecodeEmitter.cpp
 +++ b/js/src/frontend/BytecodeEmitter.cpp
 +++ b/js/src/frontend/BytecodeEmitter.cpp
-@@ -9683,27 +9683,72 @@ BytecodeEmitter::emitCallOrNew(ParseNode
+@@ -6641,27 +6641,72 @@ BytecodeEmitter::emitCallOrNew(ParseNode
              if (!emitDupAt(argc + 1))
              if (!emitDupAt(argc + 1))
                  return false;
                  return false;
          } else {
          } else {
@@ -199,6 +199,26 @@ diff --git a/js/src/jsapi-tests/testSavedStacks.cpp b/js/src/jsapi-tests/testSav
      lin = str->ensureLinear(cx);
      lin = str->ensureLinear(cx);
      CHECK(lin);
      CHECK(lin);
      CHECK(js::StringEqualsAscii(lin, "one"));
      CHECK(js::StringEqualsAscii(lin, "one"));
+diff --git a/js/xpconnect/tests/unit/test_getCallerLocation.js b/js/xpconnect/tests/unit/test_getCallerLocation.js
+--- a/js/xpconnect/tests/unit/test_getCallerLocation.js
++++ b/js/xpconnect/tests/unit/test_getCallerLocation.js
+@@ -32,14 +32,14 @@ add_task(async function() {
+   `, sandbox, undefined, "thing.js");
+ 
+   Cu.exportFunction(foo, sandbox, {defineAs: "foo"});
+ 
+   let frame = sandbox.thing();
+ 
+   equal(frame.source, "thing.js", "Frame source");
+   equal(frame.line, 5, "Frame line");
+-  equal(frame.column, 14, "Frame column");
++  equal(frame.column, 18, "Frame column");
+   equal(frame.functionDisplayName, "it", "Frame function name");
+   equal(frame.parent, null, "Frame parent");
+ 
+-  equal(String(frame), "it@thing.js:5:14\n", "Stringified frame");
++  equal(String(frame), "it@thing.js:5:18\n", "Stringified frame");
+ });
 diff --git a/js/xpconnect/tests/unit/test_getCallerLocation.js.3-1378808.later b/js/xpconnect/tests/unit/test_getCallerLocation.js.3-1378808.later
 diff --git a/js/xpconnect/tests/unit/test_getCallerLocation.js.3-1378808.later b/js/xpconnect/tests/unit/test_getCallerLocation.js.3-1378808.later
 new file mode 100644
 new file mode 100644
 --- /dev/null
 --- /dev/null

+ 5 - 5
frg/work-js/mozilla-release/patches/mozilla-central-push_430232.patch → frg/work-js/mozilla-release/patches/1423577-63a1.patch

@@ -3,7 +3,7 @@
 # Date 1533283750 -7200
 # Date 1533283750 -7200
 #      Fri Aug 03 10:09:10 2018 +0200
 #      Fri Aug 03 10:09:10 2018 +0200
 # Node ID 7e1f880b5f882732370ad70d02e7378b14b302f8
 # Node ID 7e1f880b5f882732370ad70d02e7378b14b302f8
-# Parent  854bba84bd3447fbeb1dcfbe3f062b0299919963
+# Parent  5c58d606dcb27cd80728a85a308cd1391b8084bd
 Bug 1423577 - Remove asm.js atomics support.  r=luke
 Bug 1423577 - Remove asm.js atomics support.  r=luke
 
 
 diff --git a/js/src/jit-test/tests/asm.js/gating.js b/js/src/jit-test/tests/asm.js/gating.js
 diff --git a/js/src/jit-test/tests/asm.js/gating.js b/js/src/jit-test/tests/asm.js/gating.js
@@ -2465,7 +2465,7 @@ diff --git a/js/src/jit/JitOptions.h b/js/src/jit/JitOptions.h
 diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp
 diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp
 --- a/js/src/jsapi.cpp
 --- a/js/src/jsapi.cpp
 +++ b/js/src/jsapi.cpp
 +++ b/js/src/jsapi.cpp
-@@ -7175,19 +7175,16 @@ JS_SetGlobalJitCompilerOption(JSContext*
+@@ -7113,19 +7113,16 @@ JS_SetGlobalJitCompilerOption(JSContext*
          jit::JitOptions.spectreStringMitigations = !!value;
          jit::JitOptions.spectreStringMitigations = !!value;
          break;
          break;
        case JSJITCOMPILER_SPECTRE_VALUE_MASKING:
        case JSJITCOMPILER_SPECTRE_VALUE_MASKING:
@@ -2485,7 +2485,7 @@ diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp
          break;
          break;
  #ifdef DEBUG
  #ifdef DEBUG
        case JSJITCOMPILER_FULL_DEBUG_CHECKS:
        case JSJITCOMPILER_FULL_DEBUG_CHECKS:
-@@ -7223,19 +7220,16 @@ JS_GetGlobalJitCompilerOption(JSContext*
+@@ -7161,19 +7158,16 @@ JS_GetGlobalJitCompilerOption(JSContext*
          *valueOut = JS::ContextOptionsRef(cx).ion();
          *valueOut = JS::ContextOptionsRef(cx).ion();
          break;
          break;
        case JSJITCOMPILER_BASELINE_ENABLE:
        case JSJITCOMPILER_BASELINE_ENABLE:
@@ -2508,8 +2508,8 @@ diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp
 diff --git a/js/src/jsapi.h b/js/src/jsapi.h
 diff --git a/js/src/jsapi.h b/js/src/jsapi.h
 --- a/js/src/jsapi.h
 --- a/js/src/jsapi.h
 +++ b/js/src/jsapi.h
 +++ b/js/src/jsapi.h
-@@ -5656,17 +5656,16 @@ JS_SetOffthreadIonCompilationEnabled(JSC
-     Register(TRACK_OPTIMIZATIONS, "jit.track-optimizations")                \
+@@ -5597,17 +5597,16 @@ JS_SetOffthreadIonCompilationEnabled(JSC
+     Register(UNBOXED_OBJECTS, "unboxed_objects")                            \
      Register(SIMULATOR_ALWAYS_INTERRUPT, "simulator.always-interrupt")      \
      Register(SIMULATOR_ALWAYS_INTERRUPT, "simulator.always-interrupt")      \
      Register(SPECTRE_INDEX_MASKING, "spectre.index-masking")                \
      Register(SPECTRE_INDEX_MASKING, "spectre.index-masking")                \
      Register(SPECTRE_OBJECT_MITIGATIONS_BARRIERS, "spectre.object-mitigations.barriers") \
      Register(SPECTRE_OBJECT_MITIGATIONS_BARRIERS, "spectre.object-mitigations.barriers") \

+ 36 - 688
frg/work-js/mozilla-release/patches/mozilla-central-push_430706.patch → frg/work-js/mozilla-release/patches/1469395-1-63a1.patch

@@ -3,13 +3,13 @@
 # Date 1533748396 18000
 # Date 1533748396 18000
 #      Wed Aug 08 12:13:16 2018 -0500
 #      Wed Aug 08 12:13:16 2018 -0500
 # Node ID b0f4e67b3ae1bd2e084e12a6dd6cd816636c3a8c
 # Node ID b0f4e67b3ae1bd2e084e12a6dd6cd816636c3a8c
-# Parent  e9b7afb7ae54a845c535c750f783654a1ad26f2d
+# Parent  a3e3bcee532839d9ee350f64609b5b4bf286fe98
 Bug 1469395 - Remove support for storing WebAssembly.Modules in IDB (r=lth,janv,Ms2ger)
 Bug 1469395 - Remove support for storing WebAssembly.Modules in IDB (r=lth,janv,Ms2ger)
 
 
 diff --git a/dom/indexedDB/ActorsChild.cpp b/dom/indexedDB/ActorsChild.cpp
 diff --git a/dom/indexedDB/ActorsChild.cpp b/dom/indexedDB/ActorsChild.cpp
 --- a/dom/indexedDB/ActorsChild.cpp
 --- a/dom/indexedDB/ActorsChild.cpp
 +++ b/dom/indexedDB/ActorsChild.cpp
 +++ b/dom/indexedDB/ActorsChild.cpp
-@@ -670,54 +670,60 @@ DeserializeStructuredCloneFiles(
+@@ -672,54 +672,60 @@ DeserializeStructuredCloneFiles(
            StructuredCloneFile* file = aFiles.AppendElement();
            StructuredCloneFile* file = aFiles.AppendElement();
            MOZ_ASSERT(file);
            MOZ_ASSERT(file);
  
  
@@ -77,7 +77,7 @@ diff --git a/dom/indexedDB/ActorsChild.cpp b/dom/indexedDB/ActorsChild.cpp
  }
  }
  
  
  void
  void
-@@ -1476,41 +1482,36 @@ DispatchFileHandleSuccessEvent(FileHandl
+@@ -1478,41 +1484,36 @@ DispatchFileHandleSuccessEvent(FileHandl
   ******************************************************************************/
   ******************************************************************************/
  
  
  // CancelableRunnable is used to make workers happy.
  // CancelableRunnable is used to make workers happy.
@@ -121,7 +121,7 @@ diff --git a/dom/indexedDB/ActorsChild.cpp b/dom/indexedDB/ActorsChild.cpp
      aActor->AssertIsOnOwningThread();
      aActor->AssertIsOnOwningThread();
    }
    }
  
  
-@@ -1550,17 +1551,17 @@ private:
+@@ -1552,17 +1553,17 @@ private:
        mTaskQueue->BeginShutdown();
        mTaskQueue->BeginShutdown();
      }
      }
    }
    }
@@ -140,7 +140,7 @@ diff --git a/dom/indexedDB/ActorsChild.cpp b/dom/indexedDB/ActorsChild.cpp
    ContinueWithStatus(nsresult aStatus);
    ContinueWithStatus(nsresult aStatus);
  
  
    nsresult
    nsresult
-@@ -3382,57 +3383,36 @@ BackgroundRequestChild::RecvPreprocess(c
+@@ -3387,57 +3388,36 @@ BackgroundRequestChild::RecvPreprocess(c
  
  
  nsresult
  nsresult
  BackgroundRequestChild::
  BackgroundRequestChild::
@@ -203,7 +203,7 @@ diff --git a/dom/indexedDB/ActorsChild.cpp b/dom/indexedDB/ActorsChild.cpp
  BackgroundRequestChild::
  BackgroundRequestChild::
  PreprocessHelper::Dispatch()
  PreprocessHelper::Dispatch()
  {
  {
-@@ -3475,76 +3455,57 @@ PreprocessHelper::RunOnOwningThread()
+@@ -3480,76 +3460,57 @@ PreprocessHelper::RunOnOwningThread()
      } else {
      } else {
        mActor->OnPreprocessFailed(mModuleSetIndex, mResultCode);
        mActor->OnPreprocessFailed(mModuleSetIndex, mResultCode);
      }
      }
@@ -286,7 +286,7 @@ diff --git a/dom/indexedDB/ActorsChild.cpp b/dom/indexedDB/ActorsChild.cpp
  BackgroundRequestChild::
  BackgroundRequestChild::
  PreprocessHelper::WaitForStreamReady(nsIInputStream* aInputStream)
  PreprocessHelper::WaitForStreamReady(nsIInputStream* aInputStream)
  {
  {
-@@ -3579,28 +3540,27 @@ PreprocessHelper::WaitForStreamReady(nsI
+@@ -3583,28 +3544,27 @@ PreprocessHelper::WaitForStreamReady(nsI
  void
  void
  BackgroundRequestChild::
  BackgroundRequestChild::
  PreprocessHelper::ContinueWithStatus(nsresult aStatus)
  PreprocessHelper::ContinueWithStatus(nsresult aStatus)
@@ -317,7 +317,7 @@ diff --git a/dom/indexedDB/ActorsChild.cpp b/dom/indexedDB/ActorsChild.cpp
      eventTarget = mTaskQueueEventTarget;
      eventTarget = mTaskQueueEventTarget;
    }
    }
  
  
-@@ -3614,17 +3574,17 @@ NS_IMPL_ISUPPORTS_INHERITED(BackgroundRe
+@@ -3618,17 +3578,17 @@ NS_IMPL_ISUPPORTS_INHERITED(BackgroundRe
  
  
  NS_IMETHODIMP
  NS_IMETHODIMP
  BackgroundRequestChild::
  BackgroundRequestChild::
@@ -336,7 +336,7 @@ diff --git a/dom/indexedDB/ActorsChild.cpp b/dom/indexedDB/ActorsChild.cpp
  NS_IMETHODIMP
  NS_IMETHODIMP
  BackgroundRequestChild::
  BackgroundRequestChild::
  PreprocessHelper::OnInputStreamReady(nsIAsyncInputStream* aStream)
  PreprocessHelper::OnInputStreamReady(nsIAsyncInputStream* aStream)
-@@ -3643,40 +3603,28 @@ PreprocessHelper::OnFileMetadataReady(ns
+@@ -3647,40 +3607,28 @@ PreprocessHelper::OnFileMetadataReady(ns
  }
  }
  
  
  nsresult
  nsresult
@@ -383,7 +383,7 @@ diff --git a/dom/indexedDB/ActorsChild.cpp b/dom/indexedDB/ActorsChild.cpp
 diff --git a/dom/indexedDB/ActorsParent.cpp b/dom/indexedDB/ActorsParent.cpp
 diff --git a/dom/indexedDB/ActorsParent.cpp b/dom/indexedDB/ActorsParent.cpp
 --- a/dom/indexedDB/ActorsParent.cpp
 --- a/dom/indexedDB/ActorsParent.cpp
 +++ b/dom/indexedDB/ActorsParent.cpp
 +++ b/dom/indexedDB/ActorsParent.cpp
-@@ -9629,39 +9629,28 @@ public:
+@@ -9597,39 +9597,28 @@ public:
  
  
    nsresult
    nsresult
    Init();
    Init();
@@ -423,7 +423,7 @@ diff --git a/dom/indexedDB/ActorsParent.cpp b/dom/indexedDB/ActorsParent.cpp
             uint32_t aBufferSize);
             uint32_t aBufferSize);
  
  
    nsresult
    nsresult
-@@ -9731,159 +9720,28 @@ DeserializeStructuredCloneFile(FileManag
+@@ -9699,159 +9688,28 @@ DeserializeStructuredCloneFile(FileManag
  
  
    aFile->mFileInfo.swap(fileInfo);
    aFile->mFileInfo.swap(fileInfo);
    aFile->mType = type;
    aFile->mType = type;
@@ -583,7 +583,7 @@ diff --git a/dom/indexedDB/ActorsParent.cpp b/dom/indexedDB/ActorsParent.cpp
      StructuredCloneFile* file = aResult.AppendElement();
      StructuredCloneFile* file = aResult.AppendElement();
      rv = DeserializeStructuredCloneFile(aFileManager, token, file);
      rv = DeserializeStructuredCloneFile(aFileManager, token, file);
      if (NS_WARN_IF(NS_FAILED(rv))) {
      if (NS_WARN_IF(NS_FAILED(rv))) {
-@@ -9893,36 +9751,20 @@ DeserializeStructuredCloneFiles(FileMana
+@@ -9861,36 +9719,20 @@ DeserializeStructuredCloneFiles(FileMana
      if (!aHasPreprocessInfo) {
      if (!aHasPreprocessInfo) {
        continue;
        continue;
      }
      }
@@ -620,7 +620,7 @@ diff --git a/dom/indexedDB/ActorsParent.cpp b/dom/indexedDB/ActorsParent.cpp
  }
  }
  
  
  bool
  bool
-@@ -9973,19 +9815,17 @@ SerializeStructuredCloneFiles(
+@@ -9941,19 +9783,17 @@ SerializeStructuredCloneFiles(
  
  
    if (NS_WARN_IF(!aResult.SetCapacity(count, fallible))) {
    if (NS_WARN_IF(!aResult.SetCapacity(count, fallible))) {
      return NS_ERROR_OUT_OF_MEMORY;
      return NS_ERROR_OUT_OF_MEMORY;
@@ -640,8 +640,8 @@ diff --git a/dom/indexedDB/ActorsParent.cpp b/dom/indexedDB/ActorsParent.cpp
      MOZ_ASSERT(fileId > 0);
      MOZ_ASSERT(fileId > 0);
  
  
      nsCOMPtr<nsIFile> nativeFile =
      nsCOMPtr<nsIFile> nativeFile =
-       mozilla::dom::indexedDB::FileManager::GetCheckedFileForId(directory, fileId);
-@@ -10059,25 +9899,24 @@ SerializeStructuredCloneFiles(
+       fileManager->GetCheckedFileForId(directory, fileId);
+@@ -10027,25 +9867,24 @@ SerializeStructuredCloneFiles(
          MOZ_ASSERT(file);
          MOZ_ASSERT(file);
  
  
          file->file() = null_t();
          file->file() = null_t();
@@ -669,7 +669,7 @@ diff --git a/dom/indexedDB/ActorsParent.cpp b/dom/indexedDB/ActorsParent.cpp
            nsresult rv =
            nsresult rv =
              IPCBlobUtils::Serialize(impl, aBackgroundActor, ipcBlob);
              IPCBlobUtils::Serialize(impl, aBackgroundActor, ipcBlob);
            if (NS_WARN_IF(NS_FAILED(rv))) {
            if (NS_WARN_IF(NS_FAILED(rv))) {
-@@ -10086,24 +9925,34 @@ SerializeStructuredCloneFiles(
+@@ -10054,24 +9893,34 @@ SerializeStructuredCloneFiles(
              return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
              return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
            }
            }
  
  
@@ -705,7 +705,7 @@ diff --git a/dom/indexedDB/ActorsParent.cpp b/dom/indexedDB/ActorsParent.cpp
    return NS_OK;
    return NS_OK;
  }
  }
  
  
-@@ -29133,32 +28982,16 @@ FileHelper::GetFile(FileInfo* aFileInfo)
+@@ -29103,32 +28952,16 @@ FileHelper::GetFile(FileInfo* aFileInfo)
    MOZ_ASSERT(fileId > 0);
    MOZ_ASSERT(fileId > 0);
  
  
    nsCOMPtr<nsIFile> file =
    nsCOMPtr<nsIFile> file =
@@ -738,7 +738,7 @@ diff --git a/dom/indexedDB/ActorsParent.cpp b/dom/indexedDB/ActorsParent.cpp
    MOZ_ASSERT(mJournalDirectory);
    MOZ_ASSERT(mJournalDirectory);
  
  
    const int64_t fileId = aFileInfo->Id();
    const int64_t fileId = aFileInfo->Id();
-@@ -29275,69 +29108,16 @@ FileHelper::CreateFileFromStream(nsIFile
+@@ -29245,69 +29078,16 @@ FileHelper::CreateFileFromStream(nsIFile
    if (NS_WARN_IF(NS_FAILED(rv))) {
    if (NS_WARN_IF(NS_FAILED(rv))) {
      return rv;
      return rv;
    }
    }
@@ -808,7 +808,7 @@ diff --git a/dom/indexedDB/ActorsParent.cpp b/dom/indexedDB/ActorsParent.cpp
    int64_t fileSize;
    int64_t fileSize;
  
  
    if (mFileManager->EnforcingQuota()) {
    if (mFileManager->EnforcingQuota()) {
-@@ -29365,24 +29145,16 @@ FileHelper::RemoveFile(nsIFile* aFile,
+@@ -29335,24 +29115,16 @@ FileHelper::RemoveFile(nsIFile* aFile,
    rv = aJournalFile->Remove(false);
    rv = aJournalFile->Remove(false);
    if (NS_WARN_IF(NS_FAILED(rv))) {
    if (NS_WARN_IF(NS_FAILED(rv))) {
      return rv;
      return rv;
@@ -836,7 +836,7 @@ diff --git a/dom/indexedDB/ActorsParent.cpp b/dom/indexedDB/ActorsParent.cpp
 diff --git a/dom/indexedDB/IDBObjectStore.cpp b/dom/indexedDB/IDBObjectStore.cpp
 diff --git a/dom/indexedDB/IDBObjectStore.cpp b/dom/indexedDB/IDBObjectStore.cpp
 --- a/dom/indexedDB/IDBObjectStore.cpp
 --- a/dom/indexedDB/IDBObjectStore.cpp
 +++ b/dom/indexedDB/IDBObjectStore.cpp
 +++ b/dom/indexedDB/IDBObjectStore.cpp
-@@ -204,298 +204,16 @@ GenerateRequest(JSContext* aCx, IDBObjec
+@@ -205,298 +205,16 @@ GenerateRequest(JSContext* aCx, IDBObjec
  
  
    RefPtr<IDBRequest> request =
    RefPtr<IDBRequest> request =
      IDBRequest::Create(aCx, aObjectStore, transaction->Database(), transaction);
      IDBRequest::Create(aCx, aObjectStore, transaction->Database(), transaction);
@@ -1114,7 +1114,7 @@ diff --git a/dom/indexedDB/IDBObjectStore.cpp b/dom/indexedDB/IDBObjectStore.cpp
 -      reinterpret_cast<uint8_t*>(compiled.BeginWriting()), compiledSize);
 -      reinterpret_cast<uint8_t*>(compiled.BeginWriting()), compiledSize);
 -
 -
 -    MOZ_ALWAYS_SUCCEEDS(NS_NewCStringInputStream(getter_AddRefs(mStream),
 -    MOZ_ALWAYS_SUCCEEDS(NS_NewCStringInputStream(getter_AddRefs(mStream),
--                                                 std::move(compiled)));
+-                                                 compiled));
 -
 -
 -    mModule = nullptr;
 -    mModule = nullptr;
 -
 -
@@ -1135,7 +1135,7 @@ diff --git a/dom/indexedDB/IDBObjectStore.cpp b/dom/indexedDB/IDBObjectStore.cpp
  {
  {
    MOZ_ASSERT(aCx);
    MOZ_ASSERT(aCx);
    MOZ_ASSERT(aWriter);
    MOZ_ASSERT(aWriter);
-@@ -642,71 +360,16 @@ StructuredCloneWriteCallback(JSContext* 
+@@ -643,70 +361,16 @@ StructuredCloneWriteCallback(JSContext* 
        StructuredCloneFile* newFile = cloneWriteInfo->mFiles.AppendElement();
        StructuredCloneFile* newFile = cloneWriteInfo->mFiles.AppendElement();
        newFile->mBlob = blob;
        newFile->mBlob = blob;
        newFile->mType = StructuredCloneFile::eBlob;
        newFile->mType = StructuredCloneFile::eBlob;
@@ -1149,7 +1149,7 @@ diff --git a/dom/indexedDB/IDBObjectStore.cpp b/dom/indexedDB/IDBObjectStore.cpp
 -    MOZ_ASSERT(module);
 -    MOZ_ASSERT(module);
 -
 -
 -    size_t bytecodeSize = module->bytecodeSerializedSize();
 -    size_t bytecodeSize = module->bytecodeSerializedSize();
--    UniquePtr<uint8_t[], JS::FreePolicy> bytecode(js_pod_malloc<uint8_t>(bytecodeSize));
+-    UniquePtr<uint8_t[]> bytecode(new uint8_t[bytecodeSize]);
 -    module->bytecodeSerialize(bytecode.get(), bytecodeSize);
 -    module->bytecodeSerialize(bytecode.get(), bytecodeSize);
 -
 -
 -    RefPtr<BlobImpl> blobImpl =
 -    RefPtr<BlobImpl> blobImpl =
@@ -1167,8 +1167,7 @@ diff --git a/dom/indexedDB/IDBObjectStore.cpp b/dom/indexedDB/IDBObjectStore.cpp
 -    } else {
 -    } else {
 -      nsCOMPtr<nsIInputStream> stream(new WasmCompiledModuleStream(module));
 -      nsCOMPtr<nsIInputStream> stream(new WasmCompiledModuleStream(module));
 -
 -
--      blobImpl = StreamBlobImpl::Create(stream.forget(), EmptyString(),
--                                        UINT64_MAX);
+-      blobImpl = StreamBlobImpl::Create(stream, EmptyString(), UINT64_MAX);
 -    }
 -    }
 -
 -
 -    RefPtr<Blob> compiledBlob = Blob::Create(nullptr, blobImpl);
 -    RefPtr<Blob> compiledBlob = Blob::Create(nullptr, blobImpl);
@@ -1207,7 +1206,7 @@ diff --git a/dom/indexedDB/IDBObjectStore.cpp b/dom/indexedDB/IDBObjectStore.cpp
                                      JSStructuredCloneWriter* aWriter,
                                      JSStructuredCloneWriter* aWriter,
                                      JS::Handle<JSObject*> aObj,
                                      JS::Handle<JSObject*> aObj,
                                      void* aClosure)
                                      void* aClosure)
-@@ -763,39 +426,16 @@ CopyingStructuredCloneWriteCallback(JSCo
+@@ -763,39 +427,16 @@ CopyingStructuredCloneWriteCallback(JSCo
        StructuredCloneFile* newFile = cloneInfo->mFiles.AppendElement();
        StructuredCloneFile* newFile = cloneInfo->mFiles.AppendElement();
        newFile->mMutableFile = mutableFile;
        newFile->mMutableFile = mutableFile;
        newFile->mType = StructuredCloneFile::eMutableFile;
        newFile->mType = StructuredCloneFile::eMutableFile;
@@ -1247,7 +1246,7 @@ diff --git a/dom/indexedDB/IDBObjectStore.cpp b/dom/indexedDB/IDBObjectStore.cpp
  {
  {
    static const JSStructuredCloneCallbacks kStructuredCloneCallbacks = {
    static const JSStructuredCloneCallbacks kStructuredCloneCallbacks = {
      nullptr /* read */,
      nullptr /* read */,
-@@ -1111,17 +751,17 @@ public:
+@@ -1111,17 +752,17 @@ public:
  
  
    static bool
    static bool
    CreateAndWrapWasmModule(JSContext* aCx,
    CreateAndWrapWasmModule(JSContext* aCx,
@@ -1266,7 +1265,7 @@ diff --git a/dom/indexedDB/IDBObjectStore.cpp b/dom/indexedDB/IDBObjectStore.cpp
      if (!aFile.mWasmModule) {
      if (!aFile.mWasmModule) {
        JS::Rooted<JSObject*> obj(aCx, JS_NewPlainObject(aCx));
        JS::Rooted<JSObject*> obj(aCx, JS_NewPlainObject(aCx));
  
  
-@@ -1179,17 +819,17 @@ CommonStructuredCloneReadCallback(JSCont
+@@ -1179,17 +820,17 @@ CommonStructuredCloneReadCallback(JSCont
        MOZ_ASSERT(!data.flags);
        MOZ_ASSERT(!data.flags);
  
  
        if (data.bytecodeIndex >= cloneReadInfo->mFiles.Length() ||
        if (data.bytecodeIndex >= cloneReadInfo->mFiles.Length() ||
@@ -1288,7 +1287,7 @@ diff --git a/dom/indexedDB/IDBObjectStore.cpp b/dom/indexedDB/IDBObjectStore.cpp
 diff --git a/dom/indexedDB/test/mochitest.ini b/dom/indexedDB/test/mochitest.ini
 diff --git a/dom/indexedDB/test/mochitest.ini b/dom/indexedDB/test/mochitest.ini
 --- a/dom/indexedDB/test/mochitest.ini
 --- a/dom/indexedDB/test/mochitest.ini
 +++ b/dom/indexedDB/test/mochitest.ini
 +++ b/dom/indexedDB/test/mochitest.ini
-@@ -109,22 +109,17 @@ support-files =
+@@ -105,22 +105,17 @@ support-files =
    unit/test_transaction_duplicate_store_names.js
    unit/test_transaction_duplicate_store_names.js
    unit/test_transaction_error.js
    unit/test_transaction_error.js
    unit/test_transaction_lifetimes.js
    unit/test_transaction_lifetimes.js
@@ -1311,7 +1310,7 @@ diff --git a/dom/indexedDB/test/mochitest.ini b/dom/indexedDB/test/mochitest.ini
  [test_add_twice_failure.html]
  [test_add_twice_failure.html]
  [test_advance.html]
  [test_advance.html]
  [test_autoIncrement.html]
  [test_autoIncrement.html]
-@@ -266,14 +261,9 @@ scheme=https
+@@ -256,14 +251,9 @@ scheme=https
  [test_transaction_duplicate_store_names.html]
  [test_transaction_duplicate_store_names.html]
  [test_transaction_error.html]
  [test_transaction_error.html]
  [test_transaction_lifetimes.html]
  [test_transaction_lifetimes.html]
@@ -2091,7 +2090,7 @@ deleted file mode 100644
 diff --git a/dom/indexedDB/test/unit/xpcshell-head-parent-process.js b/dom/indexedDB/test/unit/xpcshell-head-parent-process.js
 diff --git a/dom/indexedDB/test/unit/xpcshell-head-parent-process.js b/dom/indexedDB/test/unit/xpcshell-head-parent-process.js
 --- a/dom/indexedDB/test/unit/xpcshell-head-parent-process.js
 --- a/dom/indexedDB/test/unit/xpcshell-head-parent-process.js
 +++ b/dom/indexedDB/test/unit/xpcshell-head-parent-process.js
 +++ b/dom/indexedDB/test/unit/xpcshell-head-parent-process.js
-@@ -641,12 +641,8 @@ var SpecialPowers = {
+@@ -663,12 +663,8 @@ var SpecialPowers = {
          try {
          try {
            testFile.remove(false);
            testFile.remove(false);
          } catch (e) {}
          } catch (e) {}
@@ -2107,11 +2106,11 @@ diff --git a/dom/indexedDB/test/unit/xpcshell-head-parent-process.js b/dom/index
 diff --git a/dom/indexedDB/test/unit/xpcshell-parent-process.ini b/dom/indexedDB/test/unit/xpcshell-parent-process.ini
 diff --git a/dom/indexedDB/test/unit/xpcshell-parent-process.ini b/dom/indexedDB/test/unit/xpcshell-parent-process.ini
 --- a/dom/indexedDB/test/unit/xpcshell-parent-process.ini
 --- a/dom/indexedDB/test/unit/xpcshell-parent-process.ini
 +++ b/dom/indexedDB/test/unit/xpcshell-parent-process.ini
 +++ b/dom/indexedDB/test/unit/xpcshell-parent-process.ini
-@@ -61,20 +61,11 @@ skip-if = true
+@@ -58,20 +58,11 @@ skip-if = true
+ [test_schema18upgrade.js]
+ [test_schema21upgrade.js]
  [test_schema23upgrade.js]
  [test_schema23upgrade.js]
  [test_snappyUpgrade.js]
  [test_snappyUpgrade.js]
- [test_storageOption_pref.js]
- skip-if = os == "android"
  [test_storagePersistentUpgrade.js]
  [test_storagePersistentUpgrade.js]
  [test_temporary_storage.js]
  [test_temporary_storage.js]
  # bug 951017: intermittent failure on Android x86 emulator
  # bug 951017: intermittent failure on Android x86 emulator
@@ -2131,7 +2130,7 @@ diff --git a/dom/indexedDB/test/unit/xpcshell-parent-process.ini b/dom/indexedDB
 diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp
 diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp
 --- a/js/src/jsapi.cpp
 --- a/js/src/jsapi.cpp
 +++ b/js/src/jsapi.cpp
 +++ b/js/src/jsapi.cpp
-@@ -7634,28 +7634,21 @@ JS::IsWasmModuleObject(HandleObject obj)
+@@ -7562,28 +7562,21 @@ JS::IsWasmModuleObject(HandleObject obj)
  
  
  JS_PUBLIC_API(RefPtr<JS::WasmModule>)
  JS_PUBLIC_API(RefPtr<JS::WasmModule>)
  JS::GetWasmModule(HandleObject obj)
  JS::GetWasmModule(HandleObject obj)
@@ -2167,7 +2166,7 @@ diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp
 diff --git a/js/src/jsapi.h b/js/src/jsapi.h
 diff --git a/js/src/jsapi.h b/js/src/jsapi.h
 --- a/js/src/jsapi.h
 --- a/js/src/jsapi.h
 +++ b/js/src/jsapi.h
 +++ b/js/src/jsapi.h
-@@ -5974,39 +5974,16 @@ SetBuildIdOp(JSContext* cx, BuildIdOp bu
+@@ -5912,39 +5912,16 @@ SetBuildIdOp(JSContext* cx, BuildIdOp bu
   *
   *
   * - GetWasmModule() is called when making a structured clone of payload
   * - GetWasmModule() is called when making a structured clone of payload
   * containing a WebAssembly.Module object. The structured clone buffer holds a
   * containing a WebAssembly.Module object. The structured clone buffer holds a
@@ -2207,7 +2206,7 @@ diff --git a/js/src/jsapi.h b/js/src/jsapi.h
      virtual ~WasmModuleListener() {}
      virtual ~WasmModuleListener() {}
  
  
    public:
    public:
-@@ -6018,43 +5995,27 @@ class WasmModuleListener
+@@ -5956,43 +5933,27 @@ class WasmModuleListener
      virtual MozExternalRefCountType MOZ_XPCOM_ABI Release() = 0;
      virtual MozExternalRefCountType MOZ_XPCOM_ABI Release() = 0;
  
  
      virtual void onCompilationComplete() = 0;
      virtual void onCompilationComplete() = 0;
@@ -2373,654 +2372,3 @@ diff --git a/js/src/wasm/WasmModule.h b/js/src/wasm/WasmModule.h
  } // namespace js
  } // namespace js
  
  
  #endif // wasm_module_h
  #endif // wasm_module_h
-diff --git a/testing/web-platform/meta/MANIFEST.json b/testing/web-platform/meta/MANIFEST.json
---- a/testing/web-platform/meta/MANIFEST.json
-+++ b/testing/web-platform/meta/MANIFEST.json
-@@ -307812,26 +307812,16 @@
-      {}
-     ]
-    ],
-    "wasm/resources/service-worker.js": [
-     [
-      {}
-     ]
-    ],
--   "wasm/wasm_idb_worker.js": [
--    [
--     {}
--    ]
--   ],
--   "wasm/wasm_indexeddb_test.js": [
--    [
--     {}
--    ]
--   ],
-    "wasm/wasm_serialization_tests.js": [
-     [
-      {}
-     ]
-    ],
-    "wasm/wasm_serialization_worker.js": [
-     [
-      {}
-@@ -319717,24 +319707,16 @@
-     ]
-    ],
-    "IndexedDB/value_recursive.htm": [
-     [
-      "/IndexedDB/value_recursive.htm",
-      {}
-     ]
-    ],
--   "IndexedDB/wasm-module-value.html": [
--    [
--     "/IndexedDB/wasm-module-value.html",
--     {
--      "timeout": "long"
--     }
--    ]
--   ],
-    "IndexedDB/writer-starvation.htm": [
-     [
-      "/IndexedDB/writer-starvation.htm",
-      {
-       "timeout": "long"
-      }
-     ]
-    ],
-@@ -391595,22 +391577,16 @@
-       "jsshell": true
-      }
-     ],
-     [
-      "/wasm/jsapi/table/constructor.any.worker.html",
-      {}
-     ]
-    ],
--   "wasm/wasm_indexeddb_test.https.html": [
--    [
--     "/wasm/wasm_indexeddb_test.https.html",
--     {}
--    ]
--   ],
-    "wasm/wasm_local_iframe_test.html": [
-     [
-      "/wasm/wasm_local_iframe_test.html",
-      {}
-     ]
-    ],
-    "wasm/wasm_serialization_tests.html": [
-     [
-@@ -426148,20 +426124,16 @@
-   "IndexedDB/value.htm": [
-    "36e8339524852590d52ce2275a9f0c0f372f6d31",
-    "testharness"
-   ],
-   "IndexedDB/value_recursive.htm": [
-    "f49a1ccbc59ae14eb5ba74e37dccf8d6e56aa8b5",
-    "testharness"
-   ],
--  "IndexedDB/wasm-module-value.html": [
--   "9fcfd780b8e59ff49e54406fbc4106e683c76025",
--   "testharness"
--  ],
-   "IndexedDB/writer-starvation.htm": [
-    "412308387fcea53499ca7c57d0c38cfeebc1007e",
-    "testharness"
-   ],
-   "LICENSE": [
-    "28fcc080cb44907fdc7c6aeb7190652c1b65d7a2",
-    "support"
-   ],
-@@ -641764,28 +641736,16 @@
-   "wasm/resources/load_wasm.js": [
-    "512324639059da8a9d76e9d740d97fc56ebdebc4",
-    "support"
-   ],
-   "wasm/resources/service-worker.js": [
-    "bb0ec21cc570bef2ecc880d8a03cf88395a56b76",
-    "support"
-   ],
--  "wasm/wasm_idb_worker.js": [
--   "9d36d748ded87434e9dd14c30a1bbfd389db2f95",
--   "support"
--  ],
--  "wasm/wasm_indexeddb_test.https.html": [
--   "320f046426d923e5df693d0347d77377961ce6b2",
--   "testharness"
--  ],
--  "wasm/wasm_indexeddb_test.js": [
--   "a5a582cd29305b47b4e32511a740c7a1a9a742a3",
--   "support"
--  ],
-   "wasm/wasm_local_iframe_test.html": [
-    "0f4fbd0c7191ece3a901b0a065f147c03431a2d4",
-    "testharness"
-   ],
-   "wasm/wasm_serialization_tests.html": [
-    "49766c770525bcef9d66ee0b735e410bc5a7ebb8",
-    "testharness"
-   ],
-diff --git a/testing/web-platform/mozilla/meta/MANIFEST.json b/testing/web-platform/mozilla/meta/MANIFEST.json
---- a/testing/web-platform/mozilla/meta/MANIFEST.json
-+++ b/testing/web-platform/mozilla/meta/MANIFEST.json
-@@ -293,21 +293,16 @@
-      {}
-     ]
-    ],
-    "wasm/js/imports.wast.js": [
-     [
-      {}
-     ]
-    ],
--   "wasm/js/indexeddb.js": [
--    [
--     {}
--    ]
--   ],
-    "wasm/js/int_exprs.wast.js": [
-     [
-      {}
-     ]
-    ],
-    "wasm/js/int_literals.wast.js": [
-     [
-      {}
-@@ -863,22 +858,16 @@
-     ]
-    ],
-    "wasm/imports.wast.js.html": [
-     [
-      "/_mozilla/wasm/imports.wast.js.html",
-      {}
-     ]
-    ],
--   "wasm/indexeddb.js.html": [
--    [
--     "/_mozilla/wasm/indexeddb.js.html",
--     {}
--    ]
--   ],
-    "wasm/int_exprs.wast.js.html": [
-     [
-      "/_mozilla/wasm/int_exprs.wast.js.html",
-      {}
-     ]
-    ],
-    "wasm/int_literals.wast.js.html": [
-     [
-@@ -1410,20 +1399,16 @@
-   "wasm/if.wast.js.html": [
-    "1015e3a926e53e6e8f4719456696a8c4ab567142",
-    "testharness"
-   ],
-   "wasm/imports.wast.js.html": [
-    "d684d926f4328482dd5a41cee07ea2d4c472cdb2",
-    "testharness"
-   ],
--  "wasm/indexeddb.js.html": [
--   "f7f6d778cc350b5db5d938f0e276df8befbcb464",
--   "testharness"
--  ],
-   "wasm/int_exprs.wast.js.html": [
-    "b2fce1586af5a68d17a03e97a56595760a0b0fc2",
-    "testharness"
-   ],
-   "wasm/int_literals.wast.js.html": [
-    "c85eb9db74d37420c52a8dee2a21449720d77ae6",
-    "testharness"
-   ],
-@@ -1566,20 +1551,16 @@
-   "wasm/js/if.wast.js": [
-    "59ea29d20f60ea1187bd782b6e79978eaa3a37bc",
-    "support"
-   ],
-   "wasm/js/imports.wast.js": [
-    "ce2c6f93b8102fdd0d9fde9c038c1261858a3056",
-    "support"
-   ],
--  "wasm/js/indexeddb.js": [
--   "f6e18fb66be0fa51219f1759940fd66f913c0629",
--   "support"
--  ],
-   "wasm/js/int_exprs.wast.js": [
-    "c7b1a5cd565107a9d2ed860c88bbbda7f20c111f",
-    "support"
-   ],
-   "wasm/js/int_literals.wast.js": [
-    "60ae9db6154aa04e03604c80a769061b042ad490",
-    "support"
-   ],
-diff --git a/testing/web-platform/mozilla/tests/wasm/indexeddb.js.html b/testing/web-platform/mozilla/tests/wasm/indexeddb.js.html
-deleted file mode 100644
---- a/testing/web-platform/mozilla/tests/wasm/indexeddb.js.html
-+++ /dev/null
-@@ -1,18 +0,0 @@
--<!doctype html>
--<html>
--    <head>
--        <meta charset="UTF-8">
--        <title>WebAssembly Web Platform Test</title>
--    </head>
--    <body>
--
--        <script src=/resources/testharness.js></script>
--        <script src=/resources/testharnessreport.js></script>
--        <script src=./js/harness/index.js></script>
--        <script src=./js/harness/wasm-constants.js></script>
--        <script src=./js/harness/wasm-module-builder.js></script>
--
--        <div id=log></div>
--        <script src=./js/indexeddb.js></script>
--    </body>
--</html>
-diff --git a/testing/web-platform/mozilla/tests/wasm/js/indexeddb.js b/testing/web-platform/mozilla/tests/wasm/js/indexeddb.js
-deleted file mode 100644
---- a/testing/web-platform/mozilla/tests/wasm/js/indexeddb.js
-+++ /dev/null
-@@ -1,115 +0,0 @@
--/*
-- * Copyright 2017 WebAssembly Community Group participants
-- *
-- * Licensed under the Apache License, Version 2.0 (the "License");
-- * you may not use this file except in compliance with the License.
-- * You may obtain a copy of the License at
-- *
-- *     http://www.apache.org/licenses/LICENSE-2.0
-- *
-- * Unless required by applicable law or agreed to in writing, software
-- * distributed under the License is distributed on an "AS IS" BASIS,
-- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- * See the License for the specific language governing permissions and
-- * limitations under the License.
--*/
--
--(function testIndexedDB() {
--    const IDB_NAME = "spec-test";
--    const OBJECT_STORE_NAME = "wasm";
--
--    let db = null;
--
--    function openDB() {
--        console.log('Opening db...');
--        return new Promise((resolve, reject) => {
--            request = indexedDB.open(IDB_NAME, 1);
--            request.onerror = reject;
--            request.onsuccess = () => {
--                db = request.result;
--                console.log('Retrieved db:', db);
--                resolve();
--            };
--            request.onupgradeneeded = () => {
--                console.log('Creating object store...');
--                request.result.createObjectStore(OBJECT_STORE_NAME);
--                request.onerror = reject;
--                request.onupgradeneeded = reject;
--                request.onsuccess = () => {
--                    db = request.result;
--                    console.log('Created db:', db);
--                    resolve();
--                };
--            };
--        });
--    }
--
--    function getObjectStore() {
--        return db.transaction([OBJECT_STORE_NAME], "readwrite").objectStore(OBJECT_STORE_NAME);
--    }
--
--    function clearStore() {
--        console.log('Clearing store...');
--        return new Promise((resolve, reject) => {
--            var request = getObjectStore().clear();
--            request.onerror = reject;
--            request.onupgradeneeded = reject;
--            request.onsuccess = resolve;
--        });
--    }
--
--    function makeModule() {
--        return new Promise(resolve => {
--            let builder = new WasmModuleBuilder();
--            builder.addFunction('run', kSig_i_v)
--                .addBody([
--                    kExprI32Const,
--                    42,
--                    kExprReturn,
--                    kExprEnd
--                ])
--                .exportFunc();
--            let source = builder.toBuffer();
--
--            let module = new WebAssembly.Module(source);
--            let i = new WebAssembly.Instance(module);
--            assert_equals(i.exports.run(), 42);
--
--            resolve(module);
--        });
--    }
--
--    function storeWasm(module) {
--        console.log('Storing wasm object...', module);
--        return new Promise((resolve, reject) => {
--            request = getObjectStore().add(module, 1);
--            request.onsuccess = resolve;
--            request.onerror = reject;
--            request.onupgradeneeded = reject;
--        });
--    }
--
--    function loadWasm() {
--        console.log('Loading wasm object...');
--        return new Promise((resolve, reject) => {
--            var request = getObjectStore().get(1);
--            request.onsuccess = () => {
--                let i = new WebAssembly.Instance(request.result);
--                assert_equals(i.exports.run(), 42);
--                resolve();
--            }
--            request.onerror = reject;
--            request.onupgradeneeded = reject;
--        });
--    }
--
--    function run() {
--        return openDB()
--        .then(() => clearStore())
--        .then(() => makeModule())
--        .then(wasm => storeWasm(wasm))
--        .then(() => loadWasm());
--    }
--
--    promise_test(run, "store and load from indexeddb");
--})();
-diff --git a/testing/web-platform/tests/IndexedDB/wasm-module-value.html b/testing/web-platform/tests/IndexedDB/wasm-module-value.html
-deleted file mode 100644
---- a/testing/web-platform/tests/IndexedDB/wasm-module-value.html
-+++ /dev/null
-@@ -1,109 +0,0 @@
--<!doctype html>
--<meta charset="utf8">
--<meta name="timeout" content="long">
--<title>IndexedDB: WebAssembly module values</title>
--<link rel="help" href="https://w3c.github.io/IndexedDB/">
--<link rel="help" href="https://webassembly.github.io/spec/">
--<link rel="author" href="pwnall@chromium.org" title="Victor Costan">
--<script src="/resources/testharness.js"></script>
--<script src="/resources/testharnessreport.js"></script>
--<script src="support-promises.js"></script>
--<script>
--'use strict';
--
--// Binary representation for a WASM module that exports an "inc" function.
--//
--// This test covers storing WASM modules in IndexedDB. Its failure should only
--// be debugged if WASM specification tests pass. To this end, the test does not
--// use the WASM module builder helpers, trading off WASM debuggability in return
--// for having the WASM wire bytes listed explicitly in the test body. Having the
--// wire bytes spelled out can be helpful when debugging IndexedDB failures.
--let wasm_module_bytes = new Uint8Array([
--  0x00, 0x61, 0x73, 0x6d,  // Magic.
--  0x01, 0x00, 0x00, 0x00,  // Version.
--  0x01, 0x06, 0x01,              // Type section - 6 bytes, 1 entry
--  0x60, 0x01, 0x7f, 0x01, 0x7f,  // Type 0. Function: (i32) -> (i32)
--  0x03, 0x02, 0x01,   // Function section - 2 bytes, 1 entry
--  0x00,               // Function 0: Type 0
--  0x07, 0x07, 0x01,              // Export section - 7 bytes, 1 entry
--  0x03, 0x69, 0x6e, 0x63,        // Export 1. { name: "inc"
--  0x00, 0x00,                    //             desc: function 0 }
--  0x0a, 0x09, 0x01,  // Code section: 9 bytes, 1 entry
--  0x07, 0x00,        // Function 1: 7 code bytes, 0 locals
--  0x20, 0x00,        //   getlocal 0
--  0x41, 0x01,        //   i32.const 1
--  0x6a,              //   i32.add
--  0x0b,              //   end
--]);
--
--promise_test(async testCase => {
--  const wasm_module = await WebAssembly.compile(wasm_module_bytes.buffer);
--
--  const database = await createDatabase(testCase, (database, transaction) => {
--    const store = database.createObjectStore('store');
--    store.put(wasm_module, 'key1');
--  });
--
--  const result = await new Promise((resolve, reject) => {
--    const transaction = database.transaction(['store'], 'readonly');
--    const store = transaction.objectStore('store');
--    const request = store.get('key1');
--    request.onsuccess = (event) => resolve(event.target.result);
--    request.onerror = (event) => reject(event.target.error);
--  });
--
--  database.close();
--
--  const instance = await WebAssembly.instantiate(result);
--  assert_equals(
--      instance.exports['inc'](42), 43, 'inc should increment its argument');
--}, 'WebAssembly module as an IndexedDB value');
--
--promise_test(async testCase => {
--  const wasm_module = await WebAssembly.compile(wasm_module_bytes.buffer);
--
--  const database = await createDatabase(testCase, (database, transaction) => {
--    const store = database.createObjectStore('store');
--    store.put({ module: wasm_module }, 'key1');
--  });
--
--  const result = await new Promise((resolve, reject) => {
--    const transaction = database.transaction(['store'], 'readonly');
--    const store = transaction.objectStore('store');
--    const request = store.get('key1');
--    request.onsuccess = (event) => resolve(event.target.result);
--    request.onerror = (event) => reject(event.target.error);
--  });
--
--  database.close();
--
--  const instance = await WebAssembly.instantiate(result.module);
--  assert_equals(
--      instance.exports['inc'](42), 43, 'inc should increment its argument');
--}, 'WebAssembly module in a JavaScript object IndexedDB value');
--
--promise_test(async testCase => {
--  const wasm_module = await WebAssembly.compile(wasm_module_bytes.buffer);
--
--  const database = await createDatabase(testCase, (database, transaction) => {
--    const store = database.createObjectStore('store', { keyPath: 'key' });
--    store.put({ key: 'key1', module: wasm_module });
--  });
--
--  const result = await new Promise((resolve, reject) => {
--    const transaction = database.transaction(['store'], 'readonly');
--    const store = transaction.objectStore('store');
--    const request = store.get('key1');
--    request.onsuccess = (event) => resolve(event.target.result);
--    request.onerror = (event) => reject(event.target.error);
--  });
--
--  database.close();
--
--  assert_equals('key1', result.key);
--  const instance = await WebAssembly.instantiate(result.module);
--  assert_equals(
--      instance.exports['inc'](42), 43, 'inc should increment its argument');
--}, 'WebAssembly module in an IndexedDB value with an inline key');
--
--</script>
-diff --git a/testing/web-platform/tests/wasm/wasm_idb_worker.js b/testing/web-platform/tests/wasm/wasm_idb_worker.js
-deleted file mode 100644
---- a/testing/web-platform/tests/wasm/wasm_idb_worker.js
-+++ /dev/null
-@@ -1,26 +0,0 @@
--// Copyright 2017 The Chromium Authors. All rights reserved.
--// Use of this source code is governed by a BSD-style license that can be
--// found in the LICENSE file.
--
--importScripts('/resources/testharness.js');
--importScripts('resources/load_wasm.js');
--importScripts('wasm_indexeddb_test.js');
--
--onmessage = function(e) {
--  if (e.data.command === "load") {
--    loadFromIndexedDB(e.data.db_name)
--      .then(res => {
--        if (res === 2) postMessage("ok");
--        else postMessage("error");
--      },
--            error => postMessage(error));
--  } else if (e.data.command === "save") {
--    createAndSaveToIndexedDB(e.data.db_name)
--      .then((m) => {
--        postMessage("ok");
--      },
--            () => postMessage("error"));
--  } else {
--    postMessage("unknown message: " + e.data);
--  }
--}
-diff --git a/testing/web-platform/tests/wasm/wasm_indexeddb_test.https.html b/testing/web-platform/tests/wasm/wasm_indexeddb_test.https.html
-deleted file mode 100644
---- a/testing/web-platform/tests/wasm/wasm_indexeddb_test.https.html
-+++ /dev/null
-@@ -1,17 +0,0 @@
--<!DOCTYPE html>
--<html>
--<head>
--<script src="/resources/testharness.js"></script>
--<script src="/resources/testharnessreport.js"></script>
--<script src="/common/get-host-info.sub.js"></script>
--<script src="resources/load_wasm.js"></script>
--<script src="wasm_indexeddb_test.js"></script>
--</head>
--<body>
--<script>
--  promise_test(TestIndexedDBLoadStoreSecure, "serialize/deserialize to IndexedDB ");
--  promise_test(SaveToIDBAndLoadInWorker, "Save to IDB and load in worker");
--  promise_test(SaveToIDBInWorkerAndLoadInMain, "Save in worker to IDB and load in window");
--</script>
--</body>
--</html>
-diff --git a/testing/web-platform/tests/wasm/wasm_indexeddb_test.js b/testing/web-platform/tests/wasm/wasm_indexeddb_test.js
-deleted file mode 100644
---- a/testing/web-platform/tests/wasm/wasm_indexeddb_test.js
-+++ /dev/null
-@@ -1,118 +0,0 @@
--// Copyright 2016 The Chromium Authors. All rights reserved.
--// Use of this source code is governed by a BSD-style license that can be
--// found in the LICENSE file.
--
--var db_name = "db_wasm_test";
--var obj_store = 'store';
--var module_key = 'my_module';
--
--function createAndSaveToIndexedDB(db_name) {
--  return createWasmModule()
--    .then(mod => new Promise((resolve, reject) => {
--      var delete_request = indexedDB.deleteDatabase(db_name);
--      delete_request.onsuccess = function() {
--        var open_request = indexedDB.open(db_name);
--        open_request.onupgradeneeded = function() {
--          var db = open_request.result;
--          db.createObjectStore(obj_store);
--        };
--        open_request.onsuccess = function() {
--          var db = open_request.result;
--          var tx = db.transaction(obj_store, 'readwrite');
--          var store = tx.objectStore(obj_store);
--          try {
--            store.put(mod, module_key);
--          } catch(e) {
--            db.close();
--            reject(e);
--            return;
--          }
--          tx.oncomplete = function() {
--            db.close();
--            resolve();
--            return;
--          };
--        };
--      };
--    }));
--}
--
--function loadFromIndexedDB(db_name) {
--  var open_request = indexedDB.open(db_name);
--
--  return new Promise((resolve, reject) => {
--    open_request.onsuccess = function() {
--      var db = open_request.result;
--      var tx = db.transaction(obj_store);
--      var store = tx.objectStore(obj_store);
--      var get_request = store.get(module_key);
--      get_request.onsuccess = function() {
--        var mod = get_request.result;
--        db.close();
--        assert_true(mod instanceof WebAssembly.Module);
--        try {
--          var instance = new WebAssembly.Instance(mod);
--          resolve(instance.exports.increment(1));
--        } catch(e) {
--          reject(e);
--        }
--      };
--      get_request.onerror = reject;
--    };
--  });
--}
--
--function TestIndexedDBLoadStoreSecure() {
--  return createAndSaveToIndexedDB(db_name)
--    .then(() => loadFromIndexedDB(db_name))
--    .then(res => assert_equals(res, 2),
--          error => assert_unreached(error));
--}
--
--function TestIndexedDBLoadStoreInsecure() {
--  return createAndSaveToIndexedDB(db_name)
--    .then(assert_unreached,
--          error => {
--            assert_true(error instanceof DOMException);
--            assert_equals(error.name, 'DataCloneError');
--          });
--}
--
--function SaveToIDBAndLoadInWorker() {
--  return createAndSaveToIndexedDB(db_name)
--  .then(() => {
--    var worker = new Worker("wasm_idb_worker.js");
--    return new Promise((resolve, reject) => {
--      worker.onmessage = function (event) {
--        if (typeof (event.data) == "string") {
--          resolve(event.data);
--          worker.terminate();
--          worker = undefined;
--        }
--      };
--      worker.postMessage({command: "load", db_name: db_name});
--    })
--  })
--.then(data => assert_equals(data, "ok"),
--    error => assert_unreached(error));
--}
--
--function SaveToIDBInWorkerAndLoadInMain() {
--  var worker = new Worker("wasm_idb_worker.js");
--  var ret = new Promise((resolve, reject) => {
--    worker.onmessage = function (event) {
--      if (typeof (event.data) == "string") {
--        resolve(event.data);
--        worker.terminate();
--        worker = undefined;
--      }
--    };
--  })
--  worker.postMessage({command: "save", db_name: db_name});
--  return ret
--    .then(data => assert_equals(data, "ok"),
--          error => assert_unreached(error))
--    .then(() => loadFromIndexedDB(db_name))
--    .then(res => assert_equals(res, 2),
--          assert_unreached);
--}

+ 0 - 0
frg/work-js/mozilla-release/patches/mozilla-central-push_430707.patch → frg/work-js/mozilla-release/patches/1469395-2-63a1.patch


+ 0 - 0
frg/work-js/mozilla-release/patches/mozilla-central-push_431384.patch → frg/work-js/mozilla-release/patches/1473213-1-63a1.patch


+ 3 - 3
frg/work-js/mozilla-release/patches/mozilla-central-push_431385.patch → frg/work-js/mozilla-release/patches/1473213-2-63a1.patch

@@ -3,13 +3,13 @@
 # Date 1531705009 -36000
 # Date 1531705009 -36000
 #      Mon Jul 16 11:36:49 2018 +1000
 #      Mon Jul 16 11:36:49 2018 +1000
 # Node ID 8217b33680fa66e2553d27c9076a6bf429df3431
 # Node ID 8217b33680fa66e2553d27c9076a6bf429df3431
-# Parent  9022f602d14632498cab4a73c947797365b2f459
+# Parent  7bce57696684f3fa500aa8f4d49e8624254378bc
 Bug 1473213 (Part 2) - add a comment about an invariant required by the JIT r=sfink
 Bug 1473213 (Part 2) - add a comment about an invariant required by the JIT r=sfink
 
 
 diff --git a/js/src/gc/Nursery.cpp b/js/src/gc/Nursery.cpp
 diff --git a/js/src/gc/Nursery.cpp b/js/src/gc/Nursery.cpp
 --- a/js/src/gc/Nursery.cpp
 --- a/js/src/gc/Nursery.cpp
 +++ b/js/src/gc/Nursery.cpp
 +++ b/js/src/gc/Nursery.cpp
-@@ -240,16 +240,18 @@ js::Nursery::disable()
+@@ -235,16 +235,18 @@ js::Nursery::disable()
  {
  {
      MOZ_ASSERT(isEmpty());
      MOZ_ASSERT(isEmpty());
      if (!isEnabled())
      if (!isEnabled())
@@ -22,9 +22,9 @@ diff --git a/js/src/gc/Nursery.cpp b/js/src/gc/Nursery.cpp
 +    // nursery.  JIT'd code uses this even if the nursery is disabled.
 +    // nursery.  JIT'd code uses this even if the nursery is disabled.
      currentEnd_ = 0;
      currentEnd_ = 0;
      currentStringEnd_ = 0;
      currentStringEnd_ = 0;
+     position_ = 0;
      runtime()->gc.storeBuffer().disable();
      runtime()->gc.storeBuffer().disable();
  }
  }
  
  
  void
  void
  js::Nursery::enableStrings()
  js::Nursery::enableStrings()
- {

+ 0 - 0
frg/work-js/mozilla-release/patches/mozilla-central-push_431386.patch → frg/work-js/mozilla-release/patches/1473213-3-63a1.patch


+ 17 - 17
frg/work-js/mozilla-release/patches/mozilla-central-push_431387.patch → frg/work-js/mozilla-release/patches/1473213-4-63a1.patch

@@ -3,7 +3,7 @@
 # Date 1533696890 -36000
 # Date 1533696890 -36000
 #      Wed Aug 08 12:54:50 2018 +1000
 #      Wed Aug 08 12:54:50 2018 +1000
 # Node ID f3796f1a571b6e11e247f366dc45cecd97d77729
 # Node ID f3796f1a571b6e11e247f366dc45cecd97d77729
-# Parent  5f35c86a0d22072c5287f46f338bcbd36ea5d76c
+# Parent  de8d54a4df6a2840676858dbb1d129a2a4af8d2b
 Bug 1473213 (Part 4) - Add cells allocated statistics r=sfink
 Bug 1473213 (Part 4) - Add cells allocated statistics r=sfink
 
 
 diff --git a/js/src/gc/Allocator.cpp b/js/src/gc/Allocator.cpp
 diff --git a/js/src/gc/Allocator.cpp b/js/src/gc/Allocator.cpp
@@ -30,7 +30,7 @@ diff --git a/js/src/gc/Allocator.cpp b/js/src/gc/Allocator.cpp
 diff --git a/js/src/gc/GC.cpp b/js/src/gc/GC.cpp
 diff --git a/js/src/gc/GC.cpp b/js/src/gc/GC.cpp
 --- a/js/src/gc/GC.cpp
 --- a/js/src/gc/GC.cpp
 +++ b/js/src/gc/GC.cpp
 +++ b/js/src/gc/GC.cpp
-@@ -7947,16 +7947,24 @@ GCRuntime::minorGC(JS::gcreason::Reason 
+@@ -7967,16 +7967,24 @@ GCRuntime::minorGC(JS::gcreason::Reason 
  {
  {
      MOZ_ASSERT(!JS::RuntimeHeapIsBusy());
      MOZ_ASSERT(!JS::RuntimeHeapIsBusy());
  
  
@@ -55,7 +55,7 @@ diff --git a/js/src/gc/GC.cpp b/js/src/gc/GC.cpp
      nursery().collect(reason);
      nursery().collect(reason);
      MOZ_ASSERT(nursery().isEmpty());
      MOZ_ASSERT(nursery().isEmpty());
  
  
-@@ -8234,16 +8242,18 @@ GCRuntime::mergeRealms(Realm* source, Re
+@@ -8255,16 +8263,18 @@ GCRuntime::mergeRealms(Realm* source, Re
      }
      }
  
  
      // The source should be the only realm in its zone.
      // The source should be the only realm in its zone.
@@ -77,7 +77,7 @@ diff --git a/js/src/gc/GC.cpp b/js/src/gc/GC.cpp
 diff --git a/js/src/gc/GCRuntime.h b/js/src/gc/GCRuntime.h
 diff --git a/js/src/gc/GCRuntime.h b/js/src/gc/GCRuntime.h
 --- a/js/src/gc/GCRuntime.h
 --- a/js/src/gc/GCRuntime.h
 +++ b/js/src/gc/GCRuntime.h
 +++ b/js/src/gc/GCRuntime.h
-@@ -1018,16 +1018,19 @@ class GCRuntime
+@@ -1019,16 +1019,19 @@ class GCRuntime
          return nursery_.refNoCheck().addressOfPosition();
          return nursery_.refNoCheck().addressOfPosition();
      }
      }
      const void* addressOfNurseryCurrentEnd() {
      const void* addressOfNurseryCurrentEnd() {
@@ -100,8 +100,8 @@ diff --git a/js/src/gc/GCRuntime.h b/js/src/gc/GCRuntime.h
 diff --git a/js/src/gc/Nursery.cpp b/js/src/gc/Nursery.cpp
 diff --git a/js/src/gc/Nursery.cpp b/js/src/gc/Nursery.cpp
 --- a/js/src/gc/Nursery.cpp
 --- a/js/src/gc/Nursery.cpp
 +++ b/js/src/gc/Nursery.cpp
 +++ b/js/src/gc/Nursery.cpp
-@@ -387,16 +387,17 @@ js::Nursery::allocate(size_t size)
-             timeInChunkAlloc_ += ReallyNow() - start;
+@@ -383,16 +383,17 @@ js::Nursery::allocate(size_t size)
+             timeInChunkAlloc_ += TimeStamp::Now() - start;
              MOZ_ASSERT(chunkno < allocatedChunkCount());
              MOZ_ASSERT(chunkno < allocatedChunkCount());
          }
          }
          setCurrentChunk(chunkno);
          setCurrentChunk(chunkno);
@@ -118,7 +118,7 @@ diff --git a/js/src/gc/Nursery.cpp b/js/src/gc/Nursery.cpp
          auto canary = reinterpret_cast<Canary*>(position() - CanarySize);
          auto canary = reinterpret_cast<Canary*>(position() - CanarySize);
          canary->magicValue = CanaryMagicValue;
          canary->magicValue = CanaryMagicValue;
          canary->next = nullptr;
          canary->next = nullptr;
-@@ -607,16 +608,18 @@ js::Nursery::renderProfileJSON(JSONPrint
+@@ -603,16 +604,18 @@ js::Nursery::renderProfileJSON(JSONPrint
      json.property("cur_capacity", previousGC.nurseryCapacity);
      json.property("cur_capacity", previousGC.nurseryCapacity);
      const size_t newCapacity = spaceToEnd(maxChunkCount());
      const size_t newCapacity = spaceToEnd(maxChunkCount());
      if (newCapacity != previousGC.nurseryCapacity)
      if (newCapacity != previousGC.nurseryCapacity)
@@ -140,7 +140,7 @@ diff --git a/js/src/gc/Nursery.cpp b/js/src/gc/Nursery.cpp
 diff --git a/js/src/gc/Statistics.cpp b/js/src/gc/Statistics.cpp
 diff --git a/js/src/gc/Statistics.cpp b/js/src/gc/Statistics.cpp
 --- a/js/src/gc/Statistics.cpp
 --- a/js/src/gc/Statistics.cpp
 +++ b/js/src/gc/Statistics.cpp
 +++ b/js/src/gc/Statistics.cpp
-@@ -747,16 +747,17 @@ Statistics::formatJsonPhaseTimes(const P
+@@ -730,16 +730,17 @@ Statistics::formatJsonPhaseTimes(const P
      }
      }
  }
  }
  
  
@@ -158,7 +158,7 @@ diff --git a/js/src/gc/Statistics.cpp b/js/src/gc/Statistics.cpp
      startingMajorGCNumber(0),
      startingMajorGCNumber(0),
      startingSliceNumber(0),
      startingSliceNumber(0),
      maxPauseInInterval(0),
      maxPauseInInterval(0),
-@@ -1041,16 +1042,18 @@ Statistics::beginNurseryCollection(JS::g
+@@ -1024,16 +1025,18 @@ Statistics::beginNurseryCollection(JS::g
  void
  void
  Statistics::endNurseryCollection(JS::gcreason::Reason reason)
  Statistics::endNurseryCollection(JS::gcreason::Reason reason)
  {
  {
@@ -218,14 +218,14 @@ diff --git a/js/src/gc/Statistics.h b/js/src/gc/Statistics.h
  
  
      UniqueChars formatCompactSliceMessage() const;
      UniqueChars formatCompactSliceMessage() const;
      UniqueChars formatCompactSummaryMessage() const;
      UniqueChars formatCompactSummaryMessage() const;
-@@ -310,16 +331,25 @@ struct Statistics
+@@ -309,16 +330,25 @@ struct Statistics
+     PhaseTimeTable phaseTimes;
      PhaseTimeTable parallelTimes;
      PhaseTimeTable parallelTimes;
  
  
      /* Number of events of this type for this GC. */
      /* Number of events of this type for this GC. */
      EnumeratedArray<Stat,
      EnumeratedArray<Stat,
                      STAT_LIMIT,
                      STAT_LIMIT,
-                     mozilla::Atomic<uint32_t, mozilla::ReleaseAcquire,
-                                     mozilla::recordreplay::Behavior::DontPreserve>> counts;
+                     mozilla::Atomic<uint32_t, mozilla::ReleaseAcquire>> counts;
  
  
 +    /*
 +    /*
 +     * These events cannot be kept in the above array, we need to take their
 +     * These events cannot be kept in the above array, we need to take their
@@ -268,7 +268,7 @@ diff --git a/js/src/gc/Zone.cpp b/js/src/gc/Zone.cpp
 diff --git a/js/src/gc/Zone.h b/js/src/gc/Zone.h
 diff --git a/js/src/gc/Zone.h b/js/src/gc/Zone.h
 --- a/js/src/gc/Zone.h
 --- a/js/src/gc/Zone.h
 +++ b/js/src/gc/Zone.h
 +++ b/js/src/gc/Zone.h
-@@ -335,16 +335,30 @@ class Zone : public JS::shadow::Zone,
+@@ -336,16 +336,30 @@ class Zone : public JS::shadow::Zone,
       * - to avoid attaching allocation stacks to allocation stack nodes, which
       * - to avoid attaching allocation stacks to allocation stack nodes, which
       *   is silly
       *   is silly
       * And so on.
       * And so on.
@@ -279,7 +279,7 @@ diff --git a/js/src/gc/Zone.h b/js/src/gc/Zone.h
  
  
 +  private:
 +  private:
 +    // Number of allocations since the most recent minor GC for this thread.
 +    // Number of allocations since the most recent minor GC for this thread.
-+    mozilla::Atomic<uint32_t, mozilla::Relaxed, mozilla::recordreplay::Behavior::DontPreserve>
++    mozilla::Atomic<uint32_t, mozilla::Relaxed>
 +        tenuredAllocsSinceMinorGC_;
 +        tenuredAllocsSinceMinorGC_;
 +
 +
 +  public:
 +  public:
@@ -391,7 +391,7 @@ diff --git a/js/src/jit/CompileWrappers.h b/js/src/jit/CompileWrappers.h
 diff --git a/js/src/jit/MacroAssembler.cpp b/js/src/jit/MacroAssembler.cpp
 diff --git a/js/src/jit/MacroAssembler.cpp b/js/src/jit/MacroAssembler.cpp
 --- a/js/src/jit/MacroAssembler.cpp
 --- a/js/src/jit/MacroAssembler.cpp
 +++ b/js/src/jit/MacroAssembler.cpp
 +++ b/js/src/jit/MacroAssembler.cpp
-@@ -826,16 +826,20 @@ MacroAssembler::freeListAllocate(Registe
+@@ -892,16 +892,20 @@ MacroAssembler::freeListAllocate(Registe
      addPtr(temp, result); // Turn the offset into a pointer.
      addPtr(temp, result); // Turn the offset into a pointer.
      Push(result);
      Push(result);
      // Update the free list to point to the next span (which may be empty).
      // Update the free list to point to the next span (which may be empty).
@@ -412,7 +412,7 @@ diff --git a/js/src/jit/MacroAssembler.cpp b/js/src/jit/MacroAssembler.cpp
      // These registers must match the ones in JitRuntime::generateMallocStub.
      // These registers must match the ones in JitRuntime::generateMallocStub.
      const Register regReturn = CallTempReg0;
      const Register regReturn = CallTempReg0;
      const Register regZone = CallTempReg0;
      const Register regZone = CallTempReg0;
-@@ -988,16 +992,27 @@ MacroAssembler::bumpPointerAllocate(Regi
+@@ -1054,16 +1058,27 @@ MacroAssembler::bumpPointerAllocate(Regi
      addPtr(Imm32(totalSize), result);
      addPtr(Imm32(totalSize), result);
      CheckedInt<int32_t> endOffset = (CheckedInt<uintptr_t>(uintptr_t(curEndAddr)) -
      CheckedInt<int32_t> endOffset = (CheckedInt<uintptr_t>(uintptr_t(curEndAddr)) -
          CheckedInt<uintptr_t>(uintptr_t(posAddr))).toChecked<int32_t>();
          CheckedInt<uintptr_t>(uintptr_t(posAddr))).toChecked<int32_t>();
@@ -443,7 +443,7 @@ diff --git a/js/src/jit/MacroAssembler.cpp b/js/src/jit/MacroAssembler.cpp
 diff --git a/js/src/vm/JSContext-inl.h b/js/src/vm/JSContext-inl.h
 diff --git a/js/src/vm/JSContext-inl.h b/js/src/vm/JSContext-inl.h
 --- a/js/src/vm/JSContext-inl.h
 --- a/js/src/vm/JSContext-inl.h
 +++ b/js/src/vm/JSContext-inl.h
 +++ b/js/src/vm/JSContext-inl.h
-@@ -417,16 +417,21 @@ JSContext::enterAtomsZone()
+@@ -392,16 +392,21 @@ JSContext::enterAtomsZone()
  {
  {
      realm_ = nullptr;
      realm_ = nullptr;
      setZone(runtime_->unsafeAtomsZone(), AtomsZone);
      setZone(runtime_->unsafeAtomsZone(), AtomsZone);

+ 6 - 6
frg/work-js/mozilla-release/patches/mozilla-central-push_431388.patch → frg/work-js/mozilla-release/patches/1473213-5-63a1.patch

@@ -3,7 +3,7 @@
 # Date 1532529325 -36000
 # Date 1532529325 -36000
 #      Thu Jul 26 00:35:25 2018 +1000
 #      Thu Jul 26 00:35:25 2018 +1000
 # Node ID e496e1a130b4c3fdca5d99f90dde3da7a3b91770
 # Node ID e496e1a130b4c3fdca5d99f90dde3da7a3b91770
-# Parent  f3796f1a571b6e11e247f366dc45cecd97d77729
+# Parent  8f21bdc6a4187607803b2d1a5a677d4a68488f2b
 Bug 1473213 (Part 5) - Only record allocation counts on Nightly builds r=jonco
 Bug 1473213 (Part 5) - Only record allocation counts on Nightly builds r=jonco
 
 
 diff --git a/js/src/gc/Allocator.cpp b/js/src/gc/Allocator.cpp
 diff --git a/js/src/gc/Allocator.cpp b/js/src/gc/Allocator.cpp
@@ -32,8 +32,8 @@ diff --git a/js/src/gc/Allocator.cpp b/js/src/gc/Allocator.cpp
 diff --git a/js/src/gc/Nursery.cpp b/js/src/gc/Nursery.cpp
 diff --git a/js/src/gc/Nursery.cpp b/js/src/gc/Nursery.cpp
 --- a/js/src/gc/Nursery.cpp
 --- a/js/src/gc/Nursery.cpp
 +++ b/js/src/gc/Nursery.cpp
 +++ b/js/src/gc/Nursery.cpp
-@@ -387,17 +387,19 @@ js::Nursery::allocate(size_t size)
-             timeInChunkAlloc_ += ReallyNow() - start;
+@@ -383,17 +383,19 @@ js::Nursery::allocate(size_t size)
+             timeInChunkAlloc_ += TimeStamp::Now() - start;
              MOZ_ASSERT(chunkno < allocatedChunkCount());
              MOZ_ASSERT(chunkno < allocatedChunkCount());
          }
          }
          setCurrentChunk(chunkno);
          setCurrentChunk(chunkno);
@@ -52,7 +52,7 @@ diff --git a/js/src/gc/Nursery.cpp b/js/src/gc/Nursery.cpp
          auto canary = reinterpret_cast<Canary*>(position() - CanarySize);
          auto canary = reinterpret_cast<Canary*>(position() - CanarySize);
          canary->magicValue = CanaryMagicValue;
          canary->magicValue = CanaryMagicValue;
          canary->next = nullptr;
          canary->next = nullptr;
-@@ -608,18 +610,23 @@ js::Nursery::renderProfileJSON(JSONPrint
+@@ -604,18 +606,23 @@ js::Nursery::renderProfileJSON(JSONPrint
      json.property("cur_capacity", previousGC.nurseryCapacity);
      json.property("cur_capacity", previousGC.nurseryCapacity);
      const size_t newCapacity = spaceToEnd(maxChunkCount());
      const size_t newCapacity = spaceToEnd(maxChunkCount());
      if (newCapacity != previousGC.nurseryCapacity)
      if (newCapacity != previousGC.nurseryCapacity)
@@ -79,7 +79,7 @@ diff --git a/js/src/gc/Nursery.cpp b/js/src/gc/Nursery.cpp
 diff --git a/js/src/jit/MacroAssembler.cpp b/js/src/jit/MacroAssembler.cpp
 diff --git a/js/src/jit/MacroAssembler.cpp b/js/src/jit/MacroAssembler.cpp
 --- a/js/src/jit/MacroAssembler.cpp
 --- a/js/src/jit/MacroAssembler.cpp
 +++ b/js/src/jit/MacroAssembler.cpp
 +++ b/js/src/jit/MacroAssembler.cpp
-@@ -827,19 +827,22 @@ MacroAssembler::freeListAllocate(Registe
+@@ -893,19 +893,22 @@ MacroAssembler::freeListAllocate(Registe
      Push(result);
      Push(result);
      // Update the free list to point to the next span (which may be empty).
      // Update the free list to point to the next span (which may be empty).
      load32(Address(result, 0), result);
      load32(Address(result, 0), result);
@@ -102,7 +102,7 @@ diff --git a/js/src/jit/MacroAssembler.cpp b/js/src/jit/MacroAssembler.cpp
      // These registers must match the ones in JitRuntime::generateMallocStub.
      // These registers must match the ones in JitRuntime::generateMallocStub.
      const Register regReturn = CallTempReg0;
      const Register regReturn = CallTempReg0;
      const Register regZone = CallTempReg0;
      const Register regZone = CallTempReg0;
-@@ -993,26 +996,30 @@ MacroAssembler::bumpPointerAllocate(Regi
+@@ -1059,26 +1062,30 @@ MacroAssembler::bumpPointerAllocate(Regi
      CheckedInt<int32_t> endOffset = (CheckedInt<uintptr_t>(uintptr_t(curEndAddr)) -
      CheckedInt<int32_t> endOffset = (CheckedInt<uintptr_t>(uintptr_t(curEndAddr)) -
          CheckedInt<uintptr_t>(uintptr_t(posAddr))).toChecked<int32_t>();
          CheckedInt<uintptr_t>(uintptr_t(posAddr))).toChecked<int32_t>();
      MOZ_ASSERT(endOffset.isValid(),
      MOZ_ASSERT(endOffset.isValid(),

+ 1085 - 0
frg/work-js/mozilla-release/patches/1478885-63a1.patch

@@ -0,0 +1,1085 @@
+# HG changeset patch
+# User Nicholas Nethercote <nnethercote@mozilla.com>
+# Date 1533242001 -36000
+# Node ID 5b878f64a697a9e95ee56257aa293d31fa5838de
+# Parent  055397065a0bc8616ec1cfa72fa44af3555a5cb6
+Bug 1478885 - Improve docs for mozilla::Hash{Set,Map}. r=luke
+
+This patch does the following:
+
+- Adds a bunch of useful high-level info at the top of the file, making the
+  types easier to use for newcomers.
+
+- Adds a comment to every Hash{Set,Map} method that lacked one.
+
+- Tweaks lots of existing comments for clarity.
+
+- Removes comments in Hash{Set,Map} referring to details within HashTable. That
+  dependence is now covered in the top-level comment.
+
+- Tweaks the signatures in hash policy classes to be more consistent.
+
+diff --git a/mfbt/HashTable.h b/mfbt/HashTable.h
+--- a/mfbt/HashTable.h
++++ b/mfbt/HashTable.h
+@@ -1,33 +1,73 @@
+ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+  * vim: set ts=8 sts=4 et sw=4 tw=99:
+  * This Source Code Form is subject to the terms of the Mozilla Public
+  * License, v. 2.0. If a copy of the MPL was not distributed with this
+  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+ 
+-// A note on the differences between mozilla::HashTable and PLDHashTable (and
+-// its subclasses, such as nsTHashtable).
++//---------------------------------------------------------------------------
++// Overview
++//---------------------------------------------------------------------------
++//
++// This file defines HashMap<Key, Value> and HashSet<T>, hash tables that are
++// fast and have a nice API.
++//
++// Both hash tables have two optional template parameters.
++//
++// - HashPolicy. This defines the operations for hashing and matching keys. The
++//   default HashPolicy is appropriate when both of the following two
++//   conditions are true.
++//
++//   - The key type stored in the table (|Key| for |HashMap<Key, Value>|, |T|
++//     for |HashSet<T>|) is an integer, pointer, UniquePtr, float, double, or
++//     char*.
++//
++//   - The type used for lookups (|Lookup|) is the same as the key type. This
++//     is usually the case, but not always.
++//
++//   Otherwise, you must provide your own hash policy; see the "Hash Policy"
++//   section below.
++//
++// - AllocPolicy. This defines how allocations are done by the table.
++//
++//   - |MallocAllocPolicy| is the default and is usually appropriate; note that
++//     operations (such as insertions) that might cause allocations are
++//     fallible and must be checked for OOM. These checks are enforced by the
++//     use of MOZ_MUST_USE.
++//
++//   - |InfallibleAllocPolicy| is another possibility; it allows the
++//     abovementioned OOM checks to be done with MOZ_ALWAYS_TRUE().
++//
++//  See AllocPolicy.h for more details.
++//
++// Documentation on how to use HashMap and HashSet, including examples, is
++// present within those classes. Search for "class HashMap" and "class
++// HashSet".
++//
++// Both HashMap and HashSet are implemented on top of a third class, HashTable.
++// You only need to look at HashTable if you want to understand the
++// implementation.
++//
++// How does mozilla::HashTable (this file) compare with PLDHashTable (and its
++// subclasses, such as nsTHashtable)?
+ //
+ // - mozilla::HashTable is a lot faster, largely because it uses templates
+ //   throughout *and* inlines everything. PLDHashTable inlines operations much
+ //   less aggressively, and also uses "virtual ops" for operations like hashing
+ //   and matching entries that require function calls.
+ //
+ // - Correspondingly, mozilla::HashTable use is likely to increase executable
+ //   size much more than PLDHashTable.
+ //
+ // - mozilla::HashTable has a nicer API, with a proper HashSet vs. HashMap
+ //   distinction.
+ //
+-// - mozilla::HashTable requires more explicit OOM checking. Use
+-//   mozilla::InfallibleAllocPolicy to make allocations infallible; note that
+-//   return values of possibly-allocating methods such as add() will still need
+-//   checking in some fashion -- e.g. with MOZ_ALWAYS_TRUE() -- due to the use
+-//   of MOZ_MUST_USE.
++// - mozilla::HashTable requires more explicit OOM checking. As mentioned
++//   above, the use of |InfallibleAllocPolicy| can simplify things.
+ //
+ // - mozilla::HashTable has a default capacity on creation of 32 and a minimum
+ //   capacity of 4. PLDHashTable has a default capacity on creation of 8 and a
+ //   minimum capacity of 8.
+ //
+ // - mozilla::HashTable allocates memory eagerly. PLDHashTable delays
+ //   allocating until the first element is inserted.
+ 
+@@ -62,45 +102,44 @@ namespace detail {
+ template<typename T>
+ class HashTableEntry;
+ 
+ template<class T, class HashPolicy, class AllocPolicy>
+ class HashTable;
+ 
+ } // namespace detail
+ 
+-/*****************************************************************************/
+-
+ // The "generation" of a hash table is an opaque value indicating the state of
+ // modification of the hash table through its lifetime.  If the generation of
+ // a hash table compares equal at times T1 and T2, then lookups in the hash
+ // table, pointers to (or into) hash table entries, etc. at time T1 are valid
+ // at time T2.  If the generation compares unequal, these computations are all
+ // invalid and must be performed again to be used.
+ //
+ // Generations are meaningfully comparable only with respect to a single hash
+ // table.  It's always nonsensical to compare the generation of distinct hash
+ // tables H1 and H2.
+ using Generation = Opaque<uint64_t>;
+ 
+-// A performant, STL-like container providing a hash-based map from keys to
+-// values. In particular, HashMap calls constructors and destructors of all
+-// objects added so non-PODs may be used safely.
++//---------------------------------------------------------------------------
++// HashMap
++//---------------------------------------------------------------------------
++
++// HashMap is a fast hash-based map from keys to values.
+ //
+-// Key/Value requirements:
+-//  - movable, destructible, assignable
+-// HashPolicy requirements:
+-//  - see Hash Policy section below
+-// AllocPolicy:
+-//  - see AllocPolicy.h
++// Template parameter requirements:
++// - Key/Value: movable, destructible, assignable.
++// - HashPolicy: see the "Hash Policy" section below.
++// - AllocPolicy: see AllocPolicy.h.
+ //
+ // Note:
+ // - HashMap is not reentrant: Key/Value/HashPolicy/AllocPolicy members
+ //   called by HashMap must not call back into the same HashMap object.
+ // - Due to the lack of exception handling, the user must call |init()|.
++//
+ template<class Key,
+          class Value,
+          class HashPolicy = DefaultHasher<Key>,
+          class AllocPolicy = MallocAllocPolicy>
+ class HashMap
+ {
+   using TableEntry = HashMapEntry<Key, Value>;
+ 
+@@ -119,109 +158,111 @@ class HashMap
+ 
+   using Impl = detail::HashTable<TableEntry, MapHashPolicy, AllocPolicy>;
+   Impl mImpl;
+ 
+ public:
+   using Lookup = typename HashPolicy::Lookup;
+   using Entry = TableEntry;
+ 
+-  // HashMap construction is fallible (due to OOM); thus the user must call
+-  // init after constructing a HashMap and check the return value.
++  // HashMap construction is fallible (due to possible OOM). The user must
++  // call init() after construction and check the return value.
+   explicit HashMap(AllocPolicy aPolicy = AllocPolicy())
+     : mImpl(aPolicy)
+   {
+   }
+ 
++  // Initialize the map for use. Must be called after construction, before
++  // any other operations (other than initialized()).
+   MOZ_MUST_USE bool init(uint32_t aLen = 16) { return mImpl.init(aLen); }
+ 
++  // Has the map been initialized?
+   bool initialized() const { return mImpl.initialized(); }
+ 
+-  // Return whether the given lookup value is present in the map. E.g.:
++  // Return a Ptr indicating whether a key/value matching |aLookup| is
++  // present in the map. E.g.:
+   //
+   //   using HM = HashMap<int,char>;
+   //   HM h;
+   //   if (HM::Ptr p = h.lookup(3)) {
+-  //     const HM::Entry& e = *p; // p acts like a pointer to Entry
+-  //     assert(p->key == 3);     // Entry contains the key
+-  //     char val = p->value;     // and value
++  //     assert(p->key() == 3);
++  //     char val = p->value();
+   //   }
+   //
+-  // Also see the definition of Ptr in HashTable above (with T = Entry).
+   using Ptr = typename Impl::Ptr;
+   MOZ_ALWAYS_INLINE Ptr lookup(const Lookup& aLookup) const
+   {
+     return mImpl.lookup(aLookup);
+   }
+ 
+-  // Like lookup, but does not assert if two threads call lookup at the same
++  // Like lookup(), but does not assert if two threads call it at the same
+   // time. Only use this method when none of the threads will modify the map.
+   MOZ_ALWAYS_INLINE Ptr readonlyThreadsafeLookup(const Lookup& aLookup) const
+   {
+     return mImpl.readonlyThreadsafeLookup(aLookup);
+   }
+ 
+-  // Assuming |p.found()|, remove |*p|.
++  // Remove a previously found key/value (assuming aPtr.found()). The map
++  // must not have been mutated in the interim.
+   void remove(Ptr aPtr) { mImpl.remove(aPtr); }
+ 
+   // Like |lookup(l)|, but on miss, |p = lookupForAdd(l)| allows efficient
+   // insertion of Key |k| (where |HashPolicy::match(k,l) == true|) using
+-  // |add(p,k,v)|. After |add(p,k,v)|, |p| points to the new Entry. E.g.:
++  // |add(p,k,v)|. After |add(p,k,v)|, |p| points to the new key/value. E.g.:
+   //
+   //   using HM = HashMap<int,char>;
+   //   HM h;
+   //   HM::AddPtr p = h.lookupForAdd(3);
+   //   if (!p) {
+   //     if (!h.add(p, 3, 'a')) {
+   //       return false;
+   //     }
+   //   }
+-  //   const HM::Entry& e = *p;   // p acts like a pointer to Entry
+-  //   assert(p->key == 3);       // Entry contains the key
+-  //   char val = p->value;       // and value
+-  //
+-  // Also see the definition of AddPtr in HashTable above (with T = Entry).
++  //   assert(p->key() == 3);
++  //   char val = p->value();
+   //
+-  // N.B. The caller must ensure that no mutating hash table operations
+-  // occur between a pair of |lookupForAdd| and |add| calls. To avoid
+-  // looking up the key a second time, the caller may use the more efficient
+-  // relookupOrAdd method. This method reuses part of the hashing computation
+-  // to more efficiently insert the key if it has not been added. For
+-  // example, a mutation-handling version of the previous example:
++  // N.B. The caller must ensure that no mutating hash table operations occur
++  // between a pair of lookupForAdd() and add() calls. To avoid looking up the
++  // key a second time, the caller may use the more efficient relookupOrAdd()
++  // method. This method reuses part of the hashing computation to more
++  // efficiently insert the key if it has not been added. For example, a
++  // mutation-handling version of the previous example:
+   //
+   //    HM::AddPtr p = h.lookupForAdd(3);
+   //    if (!p) {
+   //      call_that_may_mutate_h();
+   //      if (!h.relookupOrAdd(p, 3, 'a')) {
+   //        return false;
+   //      }
+   //    }
+-  //    const HM::Entry& e = *p;
+-  //    assert(p->key == 3);
+-  //    char val = p->value;
++  //    assert(p->key() == 3);
++  //    char val = p->value();
+   //
+   using AddPtr = typename Impl::AddPtr;
+   MOZ_ALWAYS_INLINE AddPtr lookupForAdd(const Lookup& aLookup) const
+   {
+     return mImpl.lookupForAdd(aLookup);
+   }
+ 
++  // Add a key/value. Returns false on OOM.
+   template<typename KeyInput, typename ValueInput>
+   MOZ_MUST_USE bool add(AddPtr& aPtr, KeyInput&& aKey, ValueInput&& aValue)
+   {
+     return mImpl.add(
+       aPtr, std::forward<KeyInput>(aKey), std::forward<ValueInput>(aValue));
+   }
+ 
++  // Add a given key and a default value. Returns false on OOM.
+   template<typename KeyInput>
+   MOZ_MUST_USE bool add(AddPtr& aPtr, KeyInput&& aKey)
+   {
+     return mImpl.add(aPtr, std::forward<KeyInput>(aKey), Value());
+   }
+ 
++  // See the comment above lookupForAdd() for details.
+   template<typename KeyInput, typename ValueInput>
+   MOZ_MUST_USE bool relookupOrAdd(AddPtr& aPtr,
+                                   KeyInput&& aKey,
+                                   ValueInput&& aValue)
+   {
+     return mImpl.relookupOrAdd(aPtr,
+                                aKey,
+                                std::forward<KeyInput>(aKey),
+@@ -230,138 +271,136 @@ public:
+ 
+   // |iter()| returns an Iterator:
+   //
+   //   HashMap<int, char> h;
+   //   for (auto iter = h.iter(); !iter.done(); iter.next()) {
+   //     char c = iter.get().value();
+   //   }
+   //
+-  // Also see the definition of Iterator in HashTable above (with T = Entry).
+   using Iterator = typename Impl::Iterator;
+   Iterator iter() const { return mImpl.iter(); }
+ 
+   // |modIter()| returns a ModIterator:
+   //
+   //   HashMap<int, char> h;
+   //   for (auto iter = h.modIter(); !iter.done(); iter.next()) {
+   //     if (iter.get().value() == 'l') {
+   //       iter.remove();
+   //     }
+   //   }
+   //
+-  // Table resize may occur in ModIterator's destructor. Also see the
+-  // definition of ModIterator in HashTable above (with T = Entry).
++  // Table resize may occur in ModIterator's destructor.
+   using ModIterator = typename Impl::ModIterator;
+   ModIterator modIter() { return mImpl.modIter(); }
+ 
+-  // These are similar to Iterator/ModIterator/iter(), but use less common
++  // These are similar to Iterator/ModIterator/iter(), but use different
+   // terminology.
+   using Range = typename Impl::Range;
+   using Enum = typename Impl::Enum;
+   Range all() const { return mImpl.all(); }
+ 
+-  // Remove all entries. This does not shrink the table. For that consider
+-  // using the finish() method.
++  // Remove all keys/values without changing the capacity.
+   void clear() { mImpl.clear(); }
+ 
+-  // Remove all entries. Unlike clear() this method tries to shrink the table.
+-  // Unlike finish() it does not require the map to be initialized again.
++  // Remove all keys/values and attempt to minimize the capacity.
+   void clearAndShrink() { mImpl.clearAndShrink(); }
+ 
+-  // Remove all the entries and release all internal buffers. The map must
+-  // be initialized again before any use.
++  // Remove all keys/values and release entry storage. The map must be
++  // initialized via init() again before further use.
+   void finish() { mImpl.finish(); }
+ 
+-  // Does the table contain any entries?
++  // Is the map empty?
+   bool empty() const { return mImpl.empty(); }
+ 
+-  // Number of live elements in the map.
++  // Number of keys/values in the map.
+   uint32_t count() const { return mImpl.count(); }
+ 
+-  // Total number of allocation in the dynamic table. Note: resize will
+-  // happen well before count() == capacity().
++  // Number of key/value slots in the map. Note: resize will happen well before
++  // count() == capacity().
+   size_t capacity() const { return mImpl.capacity(); }
+ 
+-  // Measure the size of the HashMap's entry storage. If the entries contain
+-  // pointers to other heap blocks, you must iterate over the table and measure
++  // The size of the map's entry storage, in bytes. If the keys/values contain
++  // pointers to other heap blocks, you must iterate over the map and measure
+   // them separately; hence the "shallow" prefix.
+   size_t shallowSizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
+   {
+     return mImpl.shallowSizeOfExcludingThis(aMallocSizeOf);
+   }
+   size_t shallowSizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
+   {
+     return aMallocSizeOf(this) +
+            mImpl.shallowSizeOfExcludingThis(aMallocSizeOf);
+   }
+ 
++  // The map's current generation.
+   Generation generation() const { return mImpl.generation(); }
+ 
+   /************************************************** Shorthand operations */
+ 
++  // Does the map contain a key/value matching |aLookup|?
+   bool has(const Lookup& aLookup) const
+   {
+     return mImpl.lookup(aLookup).found();
+   }
+ 
+-  // Overwrite existing value with aValue. Return false on oom.
++  // Overwrite existing value with |aValue|, or add it if not present. Returns
++  // false on OOM.
+   template<typename KeyInput, typename ValueInput>
+   MOZ_MUST_USE bool put(KeyInput&& aKey, ValueInput&& aValue)
+   {
+     AddPtr p = lookupForAdd(aKey);
+     if (p) {
+       p->value() = std::forward<ValueInput>(aValue);
+       return true;
+     }
+     return add(
+       p, std::forward<KeyInput>(aKey), std::forward<ValueInput>(aValue));
+   }
+ 
+-  // Like put, but assert that the given key is not already present.
++  // Like put(), but asserts that the given key is not already present.
+   template<typename KeyInput, typename ValueInput>
+   MOZ_MUST_USE bool putNew(KeyInput&& aKey, ValueInput&& aValue)
+   {
+     return mImpl.putNew(
+       aKey, std::forward<KeyInput>(aKey), std::forward<ValueInput>(aValue));
+   }
+ 
+   // Only call this to populate an empty map after reserving space with init().
+   template<typename KeyInput, typename ValueInput>
+   void putNewInfallible(KeyInput&& aKey, ValueInput&& aValue)
+   {
+     mImpl.putNewInfallible(
+       aKey, std::forward<KeyInput>(aKey), std::forward<ValueInput>(aValue));
+   }
+ 
+   // Add (aKey,aDefaultValue) if |aKey| is not found. Return a false-y Ptr on
+-  // oom.
++  // OOM.
+   Ptr lookupWithDefault(const Key& aKey, const Value& aDefaultValue)
+   {
+     AddPtr p = lookupForAdd(aKey);
+     if (p) {
+       return p;
+     }
+     bool ok = add(p, aKey, aDefaultValue);
+-    MOZ_ASSERT_IF(!ok, !p); // p is left false-y on oom.
++    MOZ_ASSERT_IF(!ok, !p); // p is left false-y on OOM.
+     (void)ok;
+     return p;
+   }
+ 
+-  // Remove if present.
++  // Lookup and remove the key/value matching |aLookup|, if present.
+   void remove(const Lookup& aLookup)
+   {
+     if (Ptr p = lookup(aLookup)) {
+       remove(p);
+     }
+   }
+ 
+-  // Infallibly rekey one entry, if necessary.
+-  // Requires template parameters Key and HashPolicy::Lookup to be the same
+-  // type.
++  // Infallibly rekey one entry, if necessary. Requires that template
++  // parameters Key and HashPolicy::Lookup are the same type.
+   void rekeyIfMoved(const Key& aOldKey, const Key& aNewKey)
+   {
+     if (aOldKey != aNewKey) {
+       rekeyAs(aOldKey, aNewKey, aNewKey);
+     }
+   }
+ 
+   // Infallibly rekey one entry if present, and return whether that happened.
+@@ -371,131 +410,133 @@ public:
+   {
+     if (Ptr p = lookup(aOldLookup)) {
+       mImpl.rekeyAndMaybeRehash(p, aNewLookup, aNewKey);
+       return true;
+     }
+     return false;
+   }
+ 
+-  // HashMap is movable
++  // HashMap is movable.
+   HashMap(HashMap&& aRhs)
+     : mImpl(std::move(aRhs.mImpl))
+   {
+   }
+   void operator=(HashMap&& aRhs)
+   {
+     MOZ_ASSERT(this != &aRhs, "self-move assignment is prohibited");
+     mImpl = std::move(aRhs.mImpl);
+   }
+ 
+ private:
+-  // HashMap is not copyable or assignable
++  // HashMap is not copyable or assignable.
+   HashMap(const HashMap& hm) = delete;
+   HashMap& operator=(const HashMap& hm) = delete;
+ 
+   friend class Impl::Enum;
+ };
+ 
+-/*****************************************************************************/
++//---------------------------------------------------------------------------
++// HashSet
++//---------------------------------------------------------------------------
+ 
+-// A performant, STL-like container providing a hash-based set of values. In
+-// particular, HashSet calls constructors and destructors of all objects added
+-// so non-PODs may be used safely.
++// HashSet is a fast hash-based set of values.
+ //
+-// T requirements:
+-//  - movable, destructible, assignable
+-// HashPolicy requirements:
+-//  - see Hash Policy section below
+-// AllocPolicy:
+-//  - see AllocPolicy.h
++// Template parameter requirements:
++// - T: movable, destructible, assignable.
++// - HashPolicy: see the "Hash Policy" section below.
++// - AllocPolicy: see AllocPolicy.h
+ //
+ // Note:
+ // - HashSet is not reentrant: T/HashPolicy/AllocPolicy members called by
+ //   HashSet must not call back into the same HashSet object.
+ // - Due to the lack of exception handling, the user must call |init()|.
++//
+ template<class T,
+          class HashPolicy = DefaultHasher<T>,
+          class AllocPolicy = MallocAllocPolicy>
+ class HashSet
+ {
+-  struct SetOps : HashPolicy
++  struct SetHashPolicy : HashPolicy
+   {
+     using Base = HashPolicy;
+     using KeyType = T;
+ 
+     static const KeyType& getKey(const T& aT) { return aT; }
++
+     static void setKey(T& aT, KeyType& aKey) { HashPolicy::rekey(aT, aKey); }
+   };
+ 
+-  using Impl = detail::HashTable<const T, SetOps, AllocPolicy>;
++  using Impl = detail::HashTable<const T, SetHashPolicy, AllocPolicy>;
+   Impl mImpl;
+ 
+ public:
+   using Lookup = typename HashPolicy::Lookup;
+   using Entry = T;
+ 
+-  // HashSet construction is fallible (due to OOM); thus the user must call
+-  // init after constructing a HashSet and check the return value.
++  // HashSet construction is fallible (due to possible OOM). The user must call
++  // init() after construction and check the return value.
+   explicit HashSet(AllocPolicy a = AllocPolicy())
+     : mImpl(a)
+   {
+   }
+ 
++  // Initialize the set for use. Must be called after construction, before
++  // any other operations (other than initialized()).
+   MOZ_MUST_USE bool init(uint32_t aLen = 16) { return mImpl.init(aLen); }
+ 
++  // Has the set been initialized?
+   bool initialized() const { return mImpl.initialized(); }
+ 
+-  // Return whether the given lookup value is present in the map. E.g.:
++  // Return a Ptr indicating whether an element matching |aLookup| is present
++  // in the set. E.g.:
+   //
+   //   using HS = HashSet<int>;
+   //   HS h;
+   //   if (HS::Ptr p = h.lookup(3)) {
+   //     assert(*p == 3);   // p acts like a pointer to int
+   //   }
+   //
+-  // Also see the definition of Ptr in HashTable above.
+   using Ptr = typename Impl::Ptr;
+   MOZ_ALWAYS_INLINE Ptr lookup(const Lookup& aLookup) const
+   {
+     return mImpl.lookup(aLookup);
+   }
+ 
+-  // Like lookup, but does not assert if two threads call lookup at the same
+-  // time. Only use this method when none of the threads will modify the map.
++  // Like lookup(), but does not assert if two threads call it at the same
++  // time. Only use this method when none of the threads will modify the set.
+   MOZ_ALWAYS_INLINE Ptr readonlyThreadsafeLookup(const Lookup& aLookup) const
+   {
+     return mImpl.readonlyThreadsafeLookup(aLookup);
+   }
+ 
+-  // Assuming |aPtr.found()|, remove |*aPtr|.
++  // Remove a previously found element (assuming aPtr.found()). The set must
++  // not have been mutated in the interim.
+   void remove(Ptr aPtr) { mImpl.remove(aPtr); }
+ 
+   // Like |lookup(l)|, but on miss, |p = lookupForAdd(l)| allows efficient
+   // insertion of T value |t| (where |HashPolicy::match(t,l) == true|) using
+   // |add(p,t)|. After |add(p,t)|, |p| points to the new element. E.g.:
+   //
+   //   using HS = HashSet<int>;
+   //   HS h;
+   //   HS::AddPtr p = h.lookupForAdd(3);
+   //   if (!p) {
+   //     if (!h.add(p, 3)) {
+   //       return false;
+   //     }
+   //   }
+   //   assert(*p == 3);   // p acts like a pointer to int
+   //
+-  // Also see the definition of AddPtr in HashTable above.
+-  //
+-  // N.B. The caller must ensure that no mutating hash table operations
+-  // occur between a pair of |lookupForAdd| and |add| calls. To avoid
+-  // looking up the key a second time, the caller may use the more efficient
+-  // relookupOrAdd method. This method reuses part of the hashing computation
+-  // to more efficiently insert the key if it has not been added. For
+-  // example, a mutation-handling version of the previous example:
++  // N.B. The caller must ensure that no mutating hash table operations occur
++  // between a pair of lookupForAdd() and add() calls. To avoid looking up the
++  // key a second time, the caller may use the more efficient relookupOrAdd()
++  // method. This method reuses part of the hashing computation to more
++  // efficiently insert the key if it has not been added. For example, a
++  // mutation-handling version of the previous example:
+   //
+   //    HS::AddPtr p = h.lookupForAdd(3);
+   //    if (!p) {
+   //      call_that_may_mutate_h();
+   //      if (!h.relookupOrAdd(p, 3, 3)) {
+   //        return false;
+   //      }
+   //    }
+@@ -504,140 +545,142 @@ public:
+   // Note that relookupOrAdd(p,l,t) performs Lookup using |l| and adds the
+   // entry |t|, where the caller ensures match(l,t).
+   using AddPtr = typename Impl::AddPtr;
+   MOZ_ALWAYS_INLINE AddPtr lookupForAdd(const Lookup& aLookup) const
+   {
+     return mImpl.lookupForAdd(aLookup);
+   }
+ 
++  // Add an element. Returns false on OOM.
+   template<typename U>
+   MOZ_MUST_USE bool add(AddPtr& aPtr, U&& aU)
+   {
+     return mImpl.add(aPtr, std::forward<U>(aU));
+   }
+ 
++  // See the comment above lookupForAdd() for details.
+   template<typename U>
+   MOZ_MUST_USE bool relookupOrAdd(AddPtr& aPtr, const Lookup& aLookup, U&& aU)
+   {
+     return mImpl.relookupOrAdd(aPtr, aLookup, std::forward<U>(aU));
+   }
+ 
+   // |iter()| returns an Iterator:
+   //
+   //   HashSet<int> h;
+   //   for (auto iter = h.iter(); !iter.done(); iter.next()) {
+   //     int i = iter.get();
+   //   }
+   //
+-  // Also see the definition of Iterator in HashTable above.
+   typedef typename Impl::Iterator Iterator;
+   Iterator iter() const { return mImpl.iter(); }
+ 
+   // |modIter()| returns a ModIterator:
+   //
+   //   HashSet<int> h;
+   //   for (auto iter = h.modIter(); !iter.done(); iter.next()) {
+   //     if (iter.get() == 42) {
+   //       iter.remove();
+   //     }
+   //   }
+   //
+-  // Table resize may occur in ModIterator's destructor. Also see the
+-  // definition of ModIterator in HashTable above.
++  // Table resize may occur in ModIterator's destructor.
+   typedef typename Impl::ModIterator ModIterator;
+   ModIterator modIter() { return mImpl.modIter(); }
+ 
+   // These are similar to Iterator/ModIterator/iter(), but use different
+   // terminology.
+   using Range = typename Impl::Range;
+   using Enum = typename Impl::Enum;
+   Range all() const { return mImpl.all(); }
+ 
+-  // Remove all entries. This does not shrink the table. For that consider
+-  // using the finish() method.
++  // Remove all elements without changing the capacity.
+   void clear() { mImpl.clear(); }
+ 
+-  // Remove all entries. Unlike clear() this method tries to shrink the table.
+-  // Unlike finish() it does not require the set to be initialized again.
++  // Remove all elements and attempt to minimize the capacity.
+   void clearAndShrink() { mImpl.clearAndShrink(); }
+ 
+-  // Remove all the entries and release all internal buffers. The set must
+-  // be initialized again before any use.
++  // Remove all keys/values and release entry storage. The set must be
++  // initialized via init() again before further use.
+   void finish() { mImpl.finish(); }
+ 
+-  // Does the table contain any entries?
++  // Is the set empty?
+   bool empty() const { return mImpl.empty(); }
+ 
+-  // Number of live elements in the map.
++  // Number of elements in the set.
+   uint32_t count() const { return mImpl.count(); }
+ 
+-  // Total number of allocation in the dynamic table. Note: resize will
+-  // happen well before count() == capacity().
++  // Number of element slots in the set. Note: resize will happen well before
++  // count() == capacity().
+   size_t capacity() const { return mImpl.capacity(); }
+ 
+-  // Measure the size of the HashSet's entry storage. If the entries contain
+-  // pointers to other heap blocks, you must iterate over the table and measure
++  // The size of the HashSet's entry storage, in bytes. If the elements contain
++  // pointers to other heap blocks, you must iterate over the set and measure
+   // them separately; hence the "shallow" prefix.
+   size_t shallowSizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
+   {
+     return mImpl.shallowSizeOfExcludingThis(aMallocSizeOf);
+   }
+   size_t shallowSizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
+   {
+     return aMallocSizeOf(this) +
+            mImpl.shallowSizeOfExcludingThis(aMallocSizeOf);
+   }
+ 
++  // The set's current generation.
+   Generation generation() const { return mImpl.generation(); }
+ 
+   /************************************************** Shorthand operations */
+ 
++  // Does the set contain an element matching |aLookup|?
+   bool has(const Lookup& aLookup) const
+   {
+     return mImpl.lookup(aLookup).found();
+   }
+ 
+-  // Add |aU| if it is not present already. Return false on oom.
++  // Add |aU| if it is not present already. Returns false on OOM.
+   template<typename U>
+   MOZ_MUST_USE bool put(U&& aU)
+   {
+     AddPtr p = lookupForAdd(aU);
+     return p ? true : add(p, std::forward<U>(aU));
+   }
+ 
+-  // Like put, but assert that the given key is not already present.
++  // Like put(), but asserts that the given key is not already present.
+   template<typename U>
+   MOZ_MUST_USE bool putNew(U&& aU)
+   {
+     return mImpl.putNew(aU, std::forward<U>(aU));
+   }
+ 
++  // Like the other putNew(), but for when |Lookup| is different to |T|.
+   template<typename U>
+   MOZ_MUST_USE bool putNew(const Lookup& aLookup, U&& aU)
+   {
+     return mImpl.putNew(aLookup, std::forward<U>(aU));
+   }
+ 
+   // Only call this to populate an empty set after reserving space with init().
+   template<typename U>
+   void putNewInfallible(const Lookup& aLookup, U&& aU)
+   {
+     mImpl.putNewInfallible(aLookup, std::forward<U>(aU));
+   }
+ 
++  // Lookup and remove the element matching |aLookup|, if present.
+   void remove(const Lookup& aLookup)
+   {
+     if (Ptr p = lookup(aLookup)) {
+       remove(p);
+     }
+   }
+ 
+-  // Infallibly rekey one entry, if present.
+-  // Requires template parameters T and HashPolicy::Lookup to be the same type.
++  // Infallibly rekey one entry, if present. Requires that template parameters
++  // T and HashPolicy::Lookup are the same type.
+   void rekeyIfMoved(const Lookup& aOldValue, const T& aNewValue)
+   {
+     if (aOldValue != aNewValue) {
+       rekeyAs(aOldValue, aNewValue, aNewValue);
+     }
+   }
+ 
+   // Infallibly rekey one entry if present, and return whether that happened.
+@@ -647,30 +690,30 @@ public:
+   {
+     if (Ptr p = lookup(aOldLookup)) {
+       mImpl.rekeyAndMaybeRehash(p, aNewLookup, aNewValue);
+       return true;
+     }
+     return false;
+   }
+ 
+-  // Infallibly replace the current key at |p| with an equivalent key.
++  // Infallibly replace the current key at |aPtr| with an equivalent key.
+   // Specifically, both HashPolicy::hash and HashPolicy::match must return
+   // identical results for the new and old key when applied against all
+   // possible matching values.
+   void replaceKey(Ptr aPtr, const T& aNewValue)
+   {
+     MOZ_ASSERT(aPtr.found());
+     MOZ_ASSERT(*aPtr != aNewValue);
+     MOZ_ASSERT(HashPolicy::hash(*aPtr) == HashPolicy::hash(aNewValue));
+     MOZ_ASSERT(HashPolicy::match(*aPtr, aNewValue));
+     const_cast<T&>(*aPtr) = aNewValue;
+   }
+ 
+-  // HashSet is movable
++  // HashSet is movable.
+   HashSet(HashSet&& aRhs)
+     : mImpl(std::move(aRhs.mImpl))
+   {
+   }
+   void operator=(HashSet&& aRhs)
+   {
+     MOZ_ASSERT(this != &aRhs, "self-move assignment is prohibited");
+     mImpl = std::move(aRhs.mImpl);
+@@ -679,46 +722,47 @@ public:
+ private:
+   // HashSet is not copyable or assignable.
+   HashSet(const HashSet& hs) = delete;
+   HashSet& operator=(const HashSet& hs) = delete;
+ 
+   friend class Impl::Enum;
+ };
+ 
+-/*****************************************************************************/
++//---------------------------------------------------------------------------
++// Hash Policy
++//---------------------------------------------------------------------------
+ 
+-// Hash Policy
++// A hash policy |HP| for a hash table with key-type |Key| must provide:
+ //
+-// A hash policy P for a hash table with key-type Key must provide:
+-//  - a type |P::Lookup| to use to lookup table entries;
+-//  - a static member function |P::hash| with signature
++//  - a type |HP::Lookup| to use to lookup table entries;
+ //
+-//      static mozilla::HashNumber hash(Lookup)
++//  - a static member function |HP::hash| that hashes lookup values:
++//
++//      static mozilla::HashNumber hash(const Lookup&);
+ //
+-//    to use to hash the lookup type; and
+-//  - a static member function |P::match| with signature
++//  - a static member function |HP::match| that tests equality of key and
++//    lookup values:
+ //
+-//      static bool match(Key, Lookup)
+-//
+-//    to use to test equality of key and lookup values.
++//      static bool match(const Key&, const Lookup&);
+ //
+ // Normally, Lookup = Key. In general, though, different values and types of
+-// values can be used to lookup and store. If a Lookup value |l| is != to the
+-// added Key value |k|, the user must ensure that |P::match(k,l)|. E.g.:
++// values can be used to lookup and store. If a Lookup value |l| is not equal
++// to the added Key value |k|, the user must ensure that |HP::match(k,l)| is
++// true. E.g.:
+ //
+-//   mozilla::HashSet<Key, P>::AddPtr p = h.lookup(l);
++//   mozilla::HashSet<Key, HP>::AddPtr p = h.lookup(l);
+ //   if (!p) {
+-//     assert(P::match(k, l));  // must hold
++//     assert(HP::match(k, l));  // must hold
+ //     h.add(p, k);
+ //   }
+ 
+-// Pointer hashing policy that uses HashGeneric() to create good hashes for
+-// pointers.  Note that we don't shift out the lowest k bits to generate a
+-// good distribution for arena allocated pointers.
++// A pointer hashing policy that uses HashGeneric() to create good hashes for
++// pointers. Note that we don't shift out the lowest k bits because we don't
++// want to assume anything about the alignment of the pointers.
+ template<typename Key>
+ struct PointerHasher
+ {
+   using Lookup = Key;
+ 
+   static HashNumber hash(const Lookup& aLookup)
+   {
+     size_t word = reinterpret_cast<size_t>(aLookup);
+@@ -728,124 +772,132 @@ struct PointerHasher
+   static bool match(const Key& aKey, const Lookup& aLookup)
+   {
+     return aKey == aLookup;
+   }
+ 
+   static void rekey(Key& aKey, const Key& aNewKey) { aKey = aNewKey; }
+ };
+ 
+-// Default hash policy: just use the 'lookup' value. This of course only
+-// works if the lookup value is integral. HashTable applies ScrambleHashCode to
+-// the result of the 'hash' which means that it is 'ok' if the lookup value is
+-// not well distributed over the HashNumber domain.
++// The default hash policy, which only works with integers.
+ template<class Key>
+ struct DefaultHasher
+ {
+   using Lookup = Key;
+ 
+   static HashNumber hash(const Lookup& aLookup)
+   {
+-    // Hash if can implicitly cast to hash number type.
++    // Just convert the integer to a HashNumber and use that as is. (This
++    // discards the high 32-bits of 64-bit integers!) ScrambleHashCode() is
++    // subsequently called on the value to improve the distribution.
+     return aLookup;
+   }
+ 
+   static bool match(const Key& aKey, const Lookup& aLookup)
+   {
+     // Use builtin or overloaded operator==.
+     return aKey == aLookup;
+   }
+ 
+   static void rekey(Key& aKey, const Key& aNewKey) { aKey = aNewKey; }
+ };
+ 
+-// Specialize hashing policy for pointer types. It assumes that the type is
+-// at least word-aligned. For types with smaller size use PointerHasher.
++// A DefaultHasher specialization for pointers.
+ template<class T>
+ struct DefaultHasher<T*> : PointerHasher<T*>
+ {
+ };
+ 
+-// Specialize hashing policy for mozilla::UniquePtr to proxy the UniquePtr's
+-// raw pointer to PointerHasher.
++// A DefaultHasher specialization for mozilla::UniquePtr.
+ template<class T, class D>
+ struct DefaultHasher<UniquePtr<T, D>>
+ {
+-  using Lookup = UniquePtr<T, D>;
++  using Key = UniquePtr<T, D>;
++  using Lookup = Key;
+   using PtrHasher = PointerHasher<T*>;
+ 
+   static HashNumber hash(const Lookup& aLookup)
+   {
+     return PtrHasher::hash(aLookup.get());
+   }
+ 
+-  static bool match(const UniquePtr<T, D>& aKey, const Lookup& aLookup)
++  static bool match(const Key& aKey, const Lookup& aLookup)
+   {
+     return PtrHasher::match(aKey.get(), aLookup.get());
+   }
+ 
+   static void rekey(UniquePtr<T, D>& aKey, UniquePtr<T, D>&& aNewKey)
+   {
+     aKey = std::move(aNewKey);
+   }
+ };
+ 
+-// For doubles, we can xor the two uint32s.
++// A DefaultHasher specialization for doubles.
+ template<>
+ struct DefaultHasher<double>
+ {
+-  using Lookup = double;
++  using Key = double;
++  using Lookup = Key;
+ 
+-  static HashNumber hash(double aVal)
++  static HashNumber hash(const Lookup& aLookup)
+   {
++    // Just xor the high bits with the low bits, and then treat the bits of the
++    // result as a uint32_t.
+     static_assert(sizeof(HashNumber) == 4,
+                   "subsequent code assumes a four-byte hash");
+-    uint64_t u = BitwiseCast<uint64_t>(aVal);
++    uint64_t u = BitwiseCast<uint64_t>(aLookup);
+     return HashNumber(u ^ (u >> 32));
+   }
+ 
+-  static bool match(double aLhs, double aRhs)
++  static bool match(const Key& aKey, const Lookup& aLookup)
+   {
+-    return BitwiseCast<uint64_t>(aLhs) == BitwiseCast<uint64_t>(aRhs);
++    return BitwiseCast<uint64_t>(aKey) == BitwiseCast<uint64_t>(aLookup);
+   }
+ };
+ 
++// A DefaultHasher specialization for floats.
+ template<>
+ struct DefaultHasher<float>
+ {
+-  using Lookup = float;
++  using Key = float;
++  using Lookup = Key;
+ 
+-  static HashNumber hash(float aVal)
++  static HashNumber hash(const Lookup& aLookup)
+   {
++    // Just use the value as if its bits form an integer. ScrambleHashCode() is
++    // subsequently called on the value to improve the distribution.
+     static_assert(sizeof(HashNumber) == 4,
+                   "subsequent code assumes a four-byte hash");
+-    return HashNumber(BitwiseCast<uint32_t>(aVal));
++    return HashNumber(BitwiseCast<uint32_t>(aLookup));
+   }
+ 
+-  static bool match(float aLhs, float aRhs)
++  static bool match(const Key& aKey, const Lookup& aLookup)
+   {
+-    return BitwiseCast<uint32_t>(aLhs) == BitwiseCast<uint32_t>(aRhs);
++    return BitwiseCast<uint32_t>(aKey) == BitwiseCast<uint32_t>(aLookup);
+   }
+ };
+ 
+-// A hash policy that compares C strings.
++// A hash policy for C strings.
+ struct CStringHasher
+ {
++  using Key = const char*;
+   using Lookup = const char*;
+ 
+-  static HashNumber hash(Lookup aLookup) { return HashString(aLookup); }
++  static HashNumber hash(const Lookup& aLookup) { return HashString(aLookup); }
+ 
+-  static bool match(const char* key, Lookup lookup)
++  static bool match(const Key& aKey, const Lookup& aLookup)
+   {
+-    return strcmp(key, lookup) == 0;
++    return strcmp(aKey, aLookup) == 0;
+   }
+ };
+ 
+-// Fallible hashing interface.
+-//
++//---------------------------------------------------------------------------
++// Fallible Hashing Interface
++//---------------------------------------------------------------------------
++
+ // Most of the time generating a hash code is infallible so this class provides
+ // default methods that always succeed.  Specialize this class for your own hash
+ // policy to provide fallible hashing.
+ //
+ // This is used by MovableCellHasher to handle the fact that generating a unique
+ // ID for cell pointer may fail due to OOM.
+ template<typename HashPolicy>
+ struct FallibleHashMethods
+@@ -878,17 +930,19 @@ HasHash(Lookup&& aLookup)
+ template<typename HashPolicy, typename Lookup>
+ static bool
+ EnsureHash(Lookup&& aLookup)
+ {
+   return FallibleHashMethods<typename HashPolicy::Base>::ensureHash(
+     std::forward<Lookup>(aLookup));
+ }
+ 
+-/*****************************************************************************/
++//---------------------------------------------------------------------------
++// Implementation Details (HashMapEntry, HashTableEntry, HashTable)
++//---------------------------------------------------------------------------
+ 
+ // Both HashMap and HashSet are implemented by a single HashTable that is even
+ // more heavily parameterized than the other two. This leaves HashTable gnarly
+ // and extremely coupled to HashMap and HashSet; thus code should not use
+ // HashTable directly.
+ 
+ template<class Key, class Value>
+ class HashMapEntry
+@@ -922,16 +976,19 @@ public:
+     key_ = std::move(aRhs.key_);
+     value_ = std::move(aRhs.value_);
+   }
+ 
+   using KeyType = Key;
+   using ValueType = Value;
+ 
+   const Key& key() const { return key_; }
++
++  // Use this method with caution! If the key is changed such that its hash
++  // value also changes, the map will be left in an invalid state.
+   Key& mutableKey() { return key_; }
+ 
+   const Value& value() const { return value_; }
+   Value& value() { return value_; }
+ 
+ private:
+   HashMapEntry(const HashMapEntry&) = delete;
+   void operator=(const HashMapEntry&) = delete;
+

+ 3 - 3
frg/work-js/mozilla-release/patches/1478892-2-63a1.patch

@@ -3,13 +3,13 @@
 # Date 1532990135 25200
 # Date 1532990135 25200
 #      Mon Jul 30 15:35:35 2018 -0700
 #      Mon Jul 30 15:35:35 2018 -0700
 # Node ID ba7c501f82f538585c54947a9392e6f450c7c24c
 # Node ID ba7c501f82f538585c54947a9392e6f450c7c24c
-# Parent  4321a61b9f4343d7d6a89c809149e737ad6a99f7
+# Parent  79c8a2d2d34d8a75e43a34c7e67354d2255cff27
 Bug 1478892 - Instantiate GeneralParser for UTF-8 source text.  r=arai
 Bug 1478892 - Instantiate GeneralParser for UTF-8 source text.  r=arai
 
 
 diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp
 diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp
 --- a/js/src/frontend/Parser.cpp
 --- a/js/src/frontend/Parser.cpp
 +++ b/js/src/frontend/Parser.cpp
 +++ b/js/src/frontend/Parser.cpp
-@@ -10202,16 +10202,18 @@ GeneralParser<ParseHandler, CharT>::expr
+@@ -10172,16 +10172,17 @@ GeneralParser<ParseHandler, CharT>::expr
                                                   PossibleError* possibleError /* = nullptr */)
                                                   PossibleError* possibleError /* = nullptr */)
  {
  {
      MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Lp));
      MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Lp));
@@ -25,6 +25,6 @@ diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp
  template class Parser<FullParseHandler, char16_t>;
  template class Parser<FullParseHandler, char16_t>;
  template class Parser<SyntaxParseHandler, char16_t>;
  template class Parser<SyntaxParseHandler, char16_t>;
  
  
- 
+-
  } /* namespace frontend */
  } /* namespace frontend */
  } /* namespace js */
  } /* namespace js */

+ 2 - 3
frg/work-js/mozilla-release/patches/1478892-3-63a1.patch

@@ -3,13 +3,13 @@
 # Date 1533873862 25200
 # Date 1533873862 25200
 #      Thu Aug 09 21:04:22 2018 -0700
 #      Thu Aug 09 21:04:22 2018 -0700
 # Node ID f244ce374cd26b231d5309900b4648db90ad39cb
 # Node ID f244ce374cd26b231d5309900b4648db90ad39cb
-# Parent  0328a2aa5c686a57b4dcae146063f9a727075c35
+# Parent  cd1bdc7d4d55cdf54bf2d4cc6500c839bf0911d3
 Bug 1478892 - Instantiate Parser for UTF-8 source text.  r=arai
 Bug 1478892 - Instantiate Parser for UTF-8 source text.  r=arai
 
 
 diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp
 diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp
 --- a/js/src/frontend/Parser.cpp
 --- a/js/src/frontend/Parser.cpp
 +++ b/js/src/frontend/Parser.cpp
 +++ b/js/src/frontend/Parser.cpp
-@@ -10206,14 +10206,16 @@ GeneralParser<ParseHandler, CharT>::expr
+@@ -10176,13 +10176,15 @@ GeneralParser<ParseHandler, CharT>::expr
  }
  }
  
  
  template class PerHandlerParser<FullParseHandler>;
  template class PerHandlerParser<FullParseHandler>;
@@ -23,6 +23,5 @@ diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp
  template class Parser<FullParseHandler, char16_t>;
  template class Parser<FullParseHandler, char16_t>;
  template class Parser<SyntaxParseHandler, char16_t>;
  template class Parser<SyntaxParseHandler, char16_t>;
  
  
- 
  } /* namespace frontend */
  } /* namespace frontend */
  } /* namespace js */
  } /* namespace js */

+ 38 - 41
frg/work-js/mozilla-release/patches/1479900-2-63a1.patch

@@ -1,8 +1,9 @@
 # HG changeset patch
 # HG changeset patch
 # User Ted Campbell <tcampbell@mozilla.com>
 # User Ted Campbell <tcampbell@mozilla.com>
 # Date 1533234736 25200
 # Date 1533234736 25200
+#      Thu Aug 02 11:32:16 2018 -0700
 # Node ID 819b923159847ebf0227a910e966490f4f9dc177
 # Node ID 819b923159847ebf0227a910e966490f4f9dc177
-# Parent  eef40cddead40534e37bf9b74f67f3a61285c96a
+# Parent  ebac10c8c8b9ab70465097b02de34eee86bf41be
 Bug 1479900 - Part 2: Refactor GC relocation to use a reserved flag. r=sfink
 Bug 1479900 - Part 2: Refactor GC relocation to use a reserved flag. r=sfink
 
 
 This refactors gc::Cell derived types to start with a uintptr_t-sized
 This refactors gc::Cell derived types to start with a uintptr_t-sized
@@ -236,7 +237,7 @@ diff --git a/js/src/gc/GC.cpp b/js/src/gc/GC.cpp
  #endif
  #endif
  #include "vm/Debugger.h"
  #include "vm/Debugger.h"
  #include "vm/GeckoProfiler.h"
  #include "vm/GeckoProfiler.h"
-@@ -382,16 +383,27 @@ static const int IGC_MARK_SLICE_MULTIPLI
+@@ -379,16 +380,27 @@ static const int IGC_MARK_SLICE_MULTIPLI
  const AllocKind gc::slotsToThingKind[] = {
  const AllocKind gc::slotsToThingKind[] = {
      /*  0 */ AllocKind::OBJECT0,  AllocKind::OBJECT2,  AllocKind::OBJECT2,  AllocKind::OBJECT4,
      /*  0 */ AllocKind::OBJECT0,  AllocKind::OBJECT2,  AllocKind::OBJECT2,  AllocKind::OBJECT4,
      /*  4 */ AllocKind::OBJECT4,  AllocKind::OBJECT8,  AllocKind::OBJECT8,  AllocKind::OBJECT8,
      /*  4 */ AllocKind::OBJECT4,  AllocKind::OBJECT8,  AllocKind::OBJECT8,  AllocKind::OBJECT8,
@@ -264,7 +265,7 @@ diff --git a/js/src/gc/GC.cpp b/js/src/gc/GC.cpp
                    #sizedType " is smaller than SortedArenaList::MinThingSize!"); \
                    #sizedType " is smaller than SortedArenaList::MinThingSize!"); \
      static_assert(sizeof(sizedType) >= sizeof(FreeSpan), \
      static_assert(sizeof(sizedType) >= sizeof(FreeSpan), \
                    #sizedType " is smaller than FreeSpan"); \
                    #sizedType " is smaller than FreeSpan"); \
-@@ -2372,17 +2384,17 @@ RelocateArena(Arena* arena, SliceBudget&
+@@ -2339,17 +2351,17 @@ RelocateArena(Arena* arena, SliceBudget&
      for (ArenaCellIterUnderGC i(arena); !i.done(); i.next()) {
      for (ArenaCellIterUnderGC i(arena); !i.done(); i.next()) {
          RelocateCell(zone, i.getCell(), thingKind, thingSize);
          RelocateCell(zone, i.getCell(), thingKind, thingSize);
          sliceBudget.step();
          sliceBudget.step();
@@ -283,7 +284,7 @@ diff --git a/js/src/gc/GC.cpp b/js/src/gc/GC.cpp
  }
  }
  
  
  static inline bool
  static inline bool
-@@ -8502,18 +8514,18 @@ js::gc::AssertGCThingHasType(js::gc::Cel
+@@ -8467,18 +8479,18 @@ js::gc::AssertGCThingHasType(js::gc::Cel
      if (!cell) {
      if (!cell) {
          MOZ_ASSERT(kind == JS::TraceKind::Null);
          MOZ_ASSERT(kind == JS::TraceKind::Null);
          return;
          return;
@@ -549,33 +550,29 @@ diff --git a/js/src/gc/RelocationOverlay.h b/js/src/gc/RelocationOverlay.h
  } // namespace js
  } // namespace js
  
  
  #endif /* gc_RelocationOverlay_h */
  #endif /* gc_RelocationOverlay_h */
-diff --git a/js/src/gc/Verifier.cpp.1479900-2.later b/js/src/gc/Verifier.cpp.1479900-2.later
-new file mode 100644
---- /dev/null
-+++ b/js/src/gc/Verifier.cpp.1479900-2.later
-@@ -0,0 +1,22 @@
-+--- Verifier.cpp
-++++ Verifier.cpp
-+@@ -638,18 +638,17 @@ IsValidGCThingPointer(Cell* cell)
-+ }
-+ 
-+ void
-+ CheckHeapTracer::checkCell(Cell* cell)
-+ {
-+     // Moving
-+     if (!IsValidGCThingPointer(cell) ||
-+         ((gcType == GCType::Moving) && !IsGCThingValidAfterMovingGC(cell)) ||
-+-        ((gcType == GCType::NonMoving) &&
-+-            RelocationOverlay::isCellForwarded(cell)))
-++        ((gcType == GCType::NonMoving) && cell->isForwarded()))
-+     {
-+         failures++;
-+         fprintf(stderr, "Bad pointer %p\n", cell);
-+         dumpCellPath();
-+     }
-+ }
-+ 
-+ void
+diff --git a/js/src/gc/Verifier.cpp b/js/src/gc/Verifier.cpp
+--- a/js/src/gc/Verifier.cpp
++++ b/js/src/gc/Verifier.cpp
+@@ -638,18 +638,17 @@ IsValidGCThingPointer(Cell* cell)
+ }
+ 
+ void
+ CheckHeapTracer::checkCell(Cell* cell)
+ {
+     // Moving
+     if (!IsValidGCThingPointer(cell) ||
+         ((gcType == GCType::Moving) && !IsGCThingValidAfterMovingGC(cell)) ||
+-        ((gcType == GCType::NonMoving) &&
+-            RelocationOverlay::isCellForwarded(cell)))
++        ((gcType == GCType::NonMoving) && cell->isForwarded()))
+     {
+         failures++;
+         fprintf(stderr, "Bad pointer %p\n", cell);
+         dumpCellPath();
+     }
+ }
+ 
+ void
 diff --git a/js/src/vm/BigIntType.h b/js/src/vm/BigIntType.h
 diff --git a/js/src/vm/BigIntType.h b/js/src/vm/BigIntType.h
 --- a/js/src/vm/BigIntType.h
 --- a/js/src/vm/BigIntType.h
 +++ b/js/src/vm/BigIntType.h
 +++ b/js/src/vm/BigIntType.h
@@ -615,7 +612,7 @@ diff --git a/js/src/vm/BigIntType.h b/js/src/vm/BigIntType.h
 diff --git a/js/src/vm/Scope.h b/js/src/vm/Scope.h
 diff --git a/js/src/vm/Scope.h b/js/src/vm/Scope.h
 --- a/js/src/vm/Scope.h
 --- a/js/src/vm/Scope.h
 +++ b/js/src/vm/Scope.h
 +++ b/js/src/vm/Scope.h
-@@ -299,44 +299,34 @@ class WrappedPtrOperations<Scope*, Wrapp
+@@ -300,44 +300,34 @@ class WrappedPtrOperations<Scope*, Wrapp
  
  
  //
  //
  // The base class of all Scopes.
  // The base class of all Scopes.
@@ -645,18 +642,18 @@ diff --git a/js/src/vm/Scope.h b/js/src/vm/Scope.h
      GCPtrShape environmentShape_;
      GCPtrShape environmentShape_;
  
  
    protected:
    protected:
-     uintptr_t data_;
+     BaseScopeData* data_;
  
  
      Scope(ScopeKind kind, Scope* enclosing, Shape* environmentShape)
      Scope(ScopeKind kind, Scope* enclosing, Shape* environmentShape)
        : enclosing_(enclosing),
        : enclosing_(enclosing),
 +        kind_(kind),
 +        kind_(kind),
          environmentShape_(environmentShape),
          environmentShape_(environmentShape),
--        data_(0)
+-        data_(nullptr)
 -    {
 -    {
 -        paddedKind_ = 0;
 -        paddedKind_ = 0;
 -        kind_ = kind;
 -        kind_ = kind;
 -    }
 -    }
-+        data_(0) { }
++        data_(nullptr) { }
  
  
      static Scope* create(JSContext* cx, ScopeKind kind, HandleScope enclosing,
      static Scope* create(JSContext* cx, ScopeKind kind, HandleScope enclosing,
                           HandleShape envShape);
                           HandleShape envShape);
@@ -983,7 +980,7 @@ diff --git a/js/src/vm/StringType.h b/js/src/vm/StringType.h
 diff --git a/js/src/vm/SymbolType.h b/js/src/vm/SymbolType.h
 diff --git a/js/src/vm/SymbolType.h b/js/src/vm/SymbolType.h
 --- a/js/src/vm/SymbolType.h
 --- a/js/src/vm/SymbolType.h
 +++ b/js/src/vm/SymbolType.h
 +++ b/js/src/vm/SymbolType.h
-@@ -27,45 +27,53 @@
+@@ -27,45 +27,48 @@
  namespace js {
  namespace js {
  class AutoAccessAtomsZone;
  class AutoAccessAtomsZone;
  } // namespace js
  } // namespace js
@@ -1006,11 +1003,11 @@ diff --git a/js/src/vm/SymbolType.h b/js/src/vm/SymbolType.h
  
  
      JSAtom* description_;
      JSAtom* description_;
  
  
-     // The minimum allocation size is sizeof(JSString): 16 bytes on 32-bit
-     // architectures and 24 bytes on 64-bit.  A size_t of padding makes Symbol
-     // the minimum size on both.
-     size_t unused_;
- 
+-    // The minimum allocation size is sizeof(JSString): 16 bytes on 32-bit
+-    // architectures and 24 bytes on 64-bit.  A size_t of padding makes Symbol
+-    // the minimum size on both.
+-    size_t unused_;
+-
      Symbol(SymbolCode code, js::HashNumber hash, JSAtom* desc)
      Symbol(SymbolCode code, js::HashNumber hash, JSAtom* desc)
 -        : code_(code), hash_(hash), description_(desc)
 -        : code_(code), hash_(hash), description_(desc)
 -    {
 -    {

+ 0 - 0
frg/work-js/mozilla-release/patches/mozilla-central-push_431335.patch → frg/work-js/mozilla-release/patches/1480004-63a1.patch


+ 760 - 0
frg/work-js/mozilla-release/patches/1480323-63a1.patch

@@ -0,0 +1,760 @@
+# HG changeset patch
+# User Nicholas Nethercote <nnethercote@mozilla.com>
+# Date 1533255929 -36000
+# Node ID 3abea9c60292bd8492e457c3c3c067caf35ee930
+# Parent  9022686cf0298051729b226397246f91f80f8961
+Bug 1480323 - Reorder methods in Hash{Set,Map}. r=luke
+
+And add comments delimiting different operation groups. Together these changes
+make Hash{Set,Map} much easier to navigate.
+
+diff --git a/mfbt/HashTable.h b/mfbt/HashTable.h
+--- a/mfbt/HashTable.h
++++ b/mfbt/HashTable.h
+@@ -136,16 +136,22 @@ using Generation = Opaque<uint64_t>;
+ // - Due to the lack of exception handling, the user must call |init()|.
+ //
+ template<class Key,
+          class Value,
+          class HashPolicy = DefaultHasher<Key>,
+          class AllocPolicy = MallocAllocPolicy>
+ class HashMap
+ {
++  // -- Implementation details -----------------------------------------------
++
++  // HashMap is not copyable or assignable.
++  HashMap(const HashMap& hm) = delete;
++  HashMap& operator=(const HashMap& hm) = delete;
++
+   using TableEntry = HashMapEntry<Key, Value>;
+ 
+   struct MapHashPolicy : HashPolicy
+   {
+     using Base = HashPolicy;
+     using KeyType = Key;
+ 
+     static const Key& getKey(TableEntry& aEntry) { return aEntry.key(); }
+@@ -154,34 +160,85 @@ class HashMap
+     {
+       HashPolicy::rekey(aEntry.mutableKey(), aKey);
+     }
+   };
+ 
+   using Impl = detail::HashTable<TableEntry, MapHashPolicy, AllocPolicy>;
+   Impl mImpl;
+ 
++  friend class Impl::Enum;
++
+ public:
+   using Lookup = typename HashPolicy::Lookup;
+   using Entry = TableEntry;
+ 
++  // -- Initialization -------------------------------------------------------
++
+   // HashMap construction is fallible (due to possible OOM). The user must
+   // call init() after construction and check the return value.
+   explicit HashMap(AllocPolicy aPolicy = AllocPolicy())
+     : mImpl(aPolicy)
+   {
+   }
+ 
++  // HashMap is movable.
++  HashMap(HashMap&& aRhs)
++    : mImpl(std::move(aRhs.mImpl))
++  {
++  }
++  void operator=(HashMap&& aRhs)
++  {
++    MOZ_ASSERT(this != &aRhs, "self-move assignment is prohibited");
++    mImpl = std::move(aRhs.mImpl);
++  }
++
+   // Initialize the map for use. Must be called after construction, before
+   // any other operations (other than initialized()).
+   MOZ_MUST_USE bool init(uint32_t aLen = 16) { return mImpl.init(aLen); }
+ 
++  // -- Status and sizing ----------------------------------------------------
++
+   // Has the map been initialized?
+   bool initialized() const { return mImpl.initialized(); }
+ 
++  // The map's current generation.
++  Generation generation() const { return mImpl.generation(); }
++
++  // Is the map empty?
++  bool empty() const { return mImpl.empty(); }
++
++  // Number of keys/values in the map.
++  uint32_t count() const { return mImpl.count(); }
++
++  // Number of key/value slots in the map. Note: resize will happen well before
++  // count() == capacity().
++  size_t capacity() const { return mImpl.capacity(); }
++
++  // The size of the map's entry storage, in bytes. If the keys/values contain
++  // pointers to other heap blocks, you must iterate over the map and measure
++  // them separately; hence the "shallow" prefix.
++  size_t shallowSizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
++  {
++    return mImpl.shallowSizeOfExcludingThis(aMallocSizeOf);
++  }
++  size_t shallowSizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
++  {
++    return aMallocSizeOf(this) +
++           mImpl.shallowSizeOfExcludingThis(aMallocSizeOf);
++  }
++
++  // -- Lookups --------------------------------------------------------------
++
++  // Does the map contain a key/value matching |aLookup|?
++  bool has(const Lookup& aLookup) const
++  {
++    return mImpl.lookup(aLookup).found();
++  }
++
+   // Return a Ptr indicating whether a key/value matching |aLookup| is
+   // present in the map. E.g.:
+   //
+   //   using HM = HashMap<int,char>;
+   //   HM h;
+   //   if (HM::Ptr p = h.lookup(3)) {
+   //     assert(p->key() == 3);
+   //     char val = p->value();
+@@ -195,19 +252,61 @@ public:
+ 
+   // Like lookup(), but does not assert if two threads call it at the same
+   // time. Only use this method when none of the threads will modify the map.
+   MOZ_ALWAYS_INLINE Ptr readonlyThreadsafeLookup(const Lookup& aLookup) const
+   {
+     return mImpl.readonlyThreadsafeLookup(aLookup);
+   }
+ 
+-  // Remove a previously found key/value (assuming aPtr.found()). The map
+-  // must not have been mutated in the interim.
+-  void remove(Ptr aPtr) { mImpl.remove(aPtr); }
++  // -- Insertions -----------------------------------------------------------
++
++  // Overwrite existing value with |aValue|, or add it if not present. Returns
++  // false on OOM.
++  template<typename KeyInput, typename ValueInput>
++  MOZ_MUST_USE bool put(KeyInput&& aKey, ValueInput&& aValue)
++  {
++    AddPtr p = lookupForAdd(aKey);
++    if (p) {
++      p->value() = std::forward<ValueInput>(aValue);
++      return true;
++    }
++    return add(
++      p, std::forward<KeyInput>(aKey), std::forward<ValueInput>(aValue));
++  }
++
++  // Like put(), but asserts that the given key is not already present.
++  template<typename KeyInput, typename ValueInput>
++  MOZ_MUST_USE bool putNew(KeyInput&& aKey, ValueInput&& aValue)
++  {
++    return mImpl.putNew(
++      aKey, std::forward<KeyInput>(aKey), std::forward<ValueInput>(aValue));
++  }
++
++  // Only call this to populate an empty map after reserving space with init().
++  template<typename KeyInput, typename ValueInput>
++  void putNewInfallible(KeyInput&& aKey, ValueInput&& aValue)
++  {
++    mImpl.putNewInfallible(
++      aKey, std::forward<KeyInput>(aKey), std::forward<ValueInput>(aValue));
++  }
++
++  // Add (aKey,aDefaultValue) if |aKey| is not found. Return a false-y Ptr on
++  // OOM.
++  Ptr lookupWithDefault(const Key& aKey, const Value& aDefaultValue)
++  {
++    AddPtr p = lookupForAdd(aKey);
++    if (p) {
++      return p;
++    }
++    bool ok = add(p, aKey, aDefaultValue);
++    MOZ_ASSERT_IF(!ok, !p); // p is left false-y on OOM.
++    (void)ok;
++    return p;
++  }
+ 
+   // Like |lookup(l)|, but on miss, |p = lookupForAdd(l)| allows efficient
+   // insertion of Key |k| (where |HashPolicy::match(k,l) == true|) using
+   // |add(p,k,v)|. After |add(p,k,v)|, |p| points to the new key/value. E.g.:
+   //
+   //   using HM = HashMap<int,char>;
+   //   HM h;
+   //   HM::AddPtr p = h.lookupForAdd(3);
+@@ -264,16 +363,55 @@ public:
+                                   ValueInput&& aValue)
+   {
+     return mImpl.relookupOrAdd(aPtr,
+                                aKey,
+                                std::forward<KeyInput>(aKey),
+                                std::forward<ValueInput>(aValue));
+   }
+ 
++  // -- Removal --------------------------------------------------------------
++
++  // Lookup and remove the key/value matching |aLookup|, if present.
++  void remove(const Lookup& aLookup)
++  {
++    if (Ptr p = lookup(aLookup)) {
++      remove(p);
++    }
++  }
++
++  // Remove a previously found key/value (assuming aPtr.found()). The map must
++  // not have been mutated in the interim.
++  void remove(Ptr aPtr) { mImpl.remove(aPtr); }
++
++  // -- Rekeying -------------------------------------------------------------
++
++  // Infallibly rekey one entry, if necessary. Requires that template
++  // parameters Key and HashPolicy::Lookup are the same type.
++  void rekeyIfMoved(const Key& aOldKey, const Key& aNewKey)
++  {
++    if (aOldKey != aNewKey) {
++      rekeyAs(aOldKey, aNewKey, aNewKey);
++    }
++  }
++
++  // Infallibly rekey one entry if present, and return whether that happened.
++  bool rekeyAs(const Lookup& aOldLookup,
++               const Lookup& aNewLookup,
++               const Key& aNewKey)
++  {
++    if (Ptr p = lookup(aOldLookup)) {
++      mImpl.rekeyAndMaybeRehash(p, aNewLookup, aNewKey);
++      return true;
++    }
++    return false;
++  }
++
++  // -- Iteration ------------------------------------------------------------
++
+   // |iter()| returns an Iterator:
+   //
+   //   HashMap<int, char> h;
+   //   for (auto iter = h.iter(); !iter.done(); iter.next()) {
+   //     char c = iter.get().value();
+   //   }
+   //
+   using Iterator = typename Impl::Iterator;
+@@ -293,150 +431,27 @@ public:
+   ModIterator modIter() { return mImpl.modIter(); }
+ 
+   // These are similar to Iterator/ModIterator/iter(), but use different
+   // terminology.
+   using Range = typename Impl::Range;
+   using Enum = typename Impl::Enum;
+   Range all() const { return mImpl.all(); }
+ 
++  // -- Clearing -------------------------------------------------------------
++
+   // Remove all keys/values without changing the capacity.
+   void clear() { mImpl.clear(); }
+ 
+   // Remove all keys/values and attempt to minimize the capacity.
+   void clearAndShrink() { mImpl.clearAndShrink(); }
+ 
+   // Remove all keys/values and release entry storage. The map must be
+   // initialized via init() again before further use.
+   void finish() { mImpl.finish(); }
+-
+-  // Is the map empty?
+-  bool empty() const { return mImpl.empty(); }
+-
+-  // Number of keys/values in the map.
+-  uint32_t count() const { return mImpl.count(); }
+-
+-  // Number of key/value slots in the map. Note: resize will happen well before
+-  // count() == capacity().
+-  size_t capacity() const { return mImpl.capacity(); }
+-
+-  // The size of the map's entry storage, in bytes. If the keys/values contain
+-  // pointers to other heap blocks, you must iterate over the map and measure
+-  // them separately; hence the "shallow" prefix.
+-  size_t shallowSizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
+-  {
+-    return mImpl.shallowSizeOfExcludingThis(aMallocSizeOf);
+-  }
+-  size_t shallowSizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
+-  {
+-    return aMallocSizeOf(this) +
+-           mImpl.shallowSizeOfExcludingThis(aMallocSizeOf);
+-  }
+-
+-  // The map's current generation.
+-  Generation generation() const { return mImpl.generation(); }
+-
+-  /************************************************** Shorthand operations */
+-
+-  // Does the map contain a key/value matching |aLookup|?
+-  bool has(const Lookup& aLookup) const
+-  {
+-    return mImpl.lookup(aLookup).found();
+-  }
+-
+-  // Overwrite existing value with |aValue|, or add it if not present. Returns
+-  // false on OOM.
+-  template<typename KeyInput, typename ValueInput>
+-  MOZ_MUST_USE bool put(KeyInput&& aKey, ValueInput&& aValue)
+-  {
+-    AddPtr p = lookupForAdd(aKey);
+-    if (p) {
+-      p->value() = std::forward<ValueInput>(aValue);
+-      return true;
+-    }
+-    return add(
+-      p, std::forward<KeyInput>(aKey), std::forward<ValueInput>(aValue));
+-  }
+-
+-  // Like put(), but asserts that the given key is not already present.
+-  template<typename KeyInput, typename ValueInput>
+-  MOZ_MUST_USE bool putNew(KeyInput&& aKey, ValueInput&& aValue)
+-  {
+-    return mImpl.putNew(
+-      aKey, std::forward<KeyInput>(aKey), std::forward<ValueInput>(aValue));
+-  }
+-
+-  // Only call this to populate an empty map after reserving space with init().
+-  template<typename KeyInput, typename ValueInput>
+-  void putNewInfallible(KeyInput&& aKey, ValueInput&& aValue)
+-  {
+-    mImpl.putNewInfallible(
+-      aKey, std::forward<KeyInput>(aKey), std::forward<ValueInput>(aValue));
+-  }
+-
+-  // Add (aKey,aDefaultValue) if |aKey| is not found. Return a false-y Ptr on
+-  // OOM.
+-  Ptr lookupWithDefault(const Key& aKey, const Value& aDefaultValue)
+-  {
+-    AddPtr p = lookupForAdd(aKey);
+-    if (p) {
+-      return p;
+-    }
+-    bool ok = add(p, aKey, aDefaultValue);
+-    MOZ_ASSERT_IF(!ok, !p); // p is left false-y on OOM.
+-    (void)ok;
+-    return p;
+-  }
+-
+-  // Lookup and remove the key/value matching |aLookup|, if present.
+-  void remove(const Lookup& aLookup)
+-  {
+-    if (Ptr p = lookup(aLookup)) {
+-      remove(p);
+-    }
+-  }
+-
+-  // Infallibly rekey one entry, if necessary. Requires that template
+-  // parameters Key and HashPolicy::Lookup are the same type.
+-  void rekeyIfMoved(const Key& aOldKey, const Key& aNewKey)
+-  {
+-    if (aOldKey != aNewKey) {
+-      rekeyAs(aOldKey, aNewKey, aNewKey);
+-    }
+-  }
+-
+-  // Infallibly rekey one entry if present, and return whether that happened.
+-  bool rekeyAs(const Lookup& aOldLookup,
+-               const Lookup& aNewLookup,
+-               const Key& aNewKey)
+-  {
+-    if (Ptr p = lookup(aOldLookup)) {
+-      mImpl.rekeyAndMaybeRehash(p, aNewLookup, aNewKey);
+-      return true;
+-    }
+-    return false;
+-  }
+-
+-  // HashMap is movable.
+-  HashMap(HashMap&& aRhs)
+-    : mImpl(std::move(aRhs.mImpl))
+-  {
+-  }
+-  void operator=(HashMap&& aRhs)
+-  {
+-    MOZ_ASSERT(this != &aRhs, "self-move assignment is prohibited");
+-    mImpl = std::move(aRhs.mImpl);
+-  }
+-
+-private:
+-  // HashMap is not copyable or assignable.
+-  HashMap(const HashMap& hm) = delete;
+-  HashMap& operator=(const HashMap& hm) = delete;
+-
+-  friend class Impl::Enum;
+ };
+ 
+ //---------------------------------------------------------------------------
+ // HashSet
+ //---------------------------------------------------------------------------
+ 
+ // HashSet is a fast hash-based set of values.
+ //
+@@ -450,47 +465,104 @@ private:
+ //   HashSet must not call back into the same HashSet object.
+ // - Due to the lack of exception handling, the user must call |init()|.
+ //
+ template<class T,
+          class HashPolicy = DefaultHasher<T>,
+          class AllocPolicy = MallocAllocPolicy>
+ class HashSet
+ {
++  // -- Implementation details -----------------------------------------------
++
++  // HashSet is not copyable or assignable.
++  HashSet(const HashSet& hs) = delete;
++  HashSet& operator=(const HashSet& hs) = delete;
++
+   struct SetHashPolicy : HashPolicy
+   {
+     using Base = HashPolicy;
+     using KeyType = T;
+ 
+     static const KeyType& getKey(const T& aT) { return aT; }
+ 
+     static void setKey(T& aT, KeyType& aKey) { HashPolicy::rekey(aT, aKey); }
+   };
+ 
+   using Impl = detail::HashTable<const T, SetHashPolicy, AllocPolicy>;
+   Impl mImpl;
+ 
++  friend class Impl::Enum;
++
+ public:
+   using Lookup = typename HashPolicy::Lookup;
+   using Entry = T;
+ 
++  // -- Initialization -------------------------------------------------------
++
+   // HashSet construction is fallible (due to possible OOM). The user must call
+   // init() after construction and check the return value.
+   explicit HashSet(AllocPolicy a = AllocPolicy())
+     : mImpl(a)
+   {
+   }
+ 
++  // HashSet is movable.
++  HashSet(HashSet&& aRhs)
++    : mImpl(std::move(aRhs.mImpl))
++  {
++  }
++  void operator=(HashSet&& aRhs)
++  {
++    MOZ_ASSERT(this != &aRhs, "self-move assignment is prohibited");
++    mImpl = std::move(aRhs.mImpl);
++  }
++
+   // Initialize the set for use. Must be called after construction, before
+   // any other operations (other than initialized()).
+   MOZ_MUST_USE bool init(uint32_t aLen = 16) { return mImpl.init(aLen); }
+ 
++  // -- Status and sizing ----------------------------------------------------
++
+   // Has the set been initialized?
+   bool initialized() const { return mImpl.initialized(); }
+ 
++  // The set's current generation.
++  Generation generation() const { return mImpl.generation(); }
++
++  // Is the set empty?
++  bool empty() const { return mImpl.empty(); }
++
++  // Number of elements in the set.
++  uint32_t count() const { return mImpl.count(); }
++
++  // Number of element slots in the set. Note: resize will happen well before
++  // count() == capacity().
++  size_t capacity() const { return mImpl.capacity(); }
++
++  // The size of the set's entry storage, in bytes. If the elements contain
++  // pointers to other heap blocks, you must iterate over the set and measure
++  // them separately; hence the "shallow" prefix.
++  size_t shallowSizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
++  {
++    return mImpl.shallowSizeOfExcludingThis(aMallocSizeOf);
++  }
++  size_t shallowSizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
++  {
++    return aMallocSizeOf(this) +
++           mImpl.shallowSizeOfExcludingThis(aMallocSizeOf);
++  }
++
++  // -- Lookups --------------------------------------------------------------
++
++  // Does the set contain an element matching |aLookup|?
++  bool has(const Lookup& aLookup) const
++  {
++    return mImpl.lookup(aLookup).found();
++  }
++
+   // Return a Ptr indicating whether an element matching |aLookup| is present
+   // in the set. E.g.:
+   //
+   //   using HS = HashSet<int>;
+   //   HS h;
+   //   if (HS::Ptr p = h.lookup(3)) {
+   //     assert(*p == 3);   // p acts like a pointer to int
+   //   }
+@@ -503,19 +575,46 @@ public:
+ 
+   // Like lookup(), but does not assert if two threads call it at the same
+   // time. Only use this method when none of the threads will modify the set.
+   MOZ_ALWAYS_INLINE Ptr readonlyThreadsafeLookup(const Lookup& aLookup) const
+   {
+     return mImpl.readonlyThreadsafeLookup(aLookup);
+   }
+ 
+-  // Remove a previously found element (assuming aPtr.found()). The set must
+-  // not have been mutated in the interim.
+-  void remove(Ptr aPtr) { mImpl.remove(aPtr); }
++  // -- Insertions -----------------------------------------------------------
++
++  // Add |aU| if it is not present already. Returns false on OOM.
++  template<typename U>
++  MOZ_MUST_USE bool put(U&& aU)
++  {
++    AddPtr p = lookupForAdd(aU);
++    return p ? true : add(p, std::forward<U>(aU));
++  }
++
++  // Like put(), but asserts that the given key is not already present.
++  template<typename U>
++  MOZ_MUST_USE bool putNew(U&& aU)
++  {
++    return mImpl.putNew(aU, std::forward<U>(aU));
++  }
++
++  // Like the other putNew(), but for when |Lookup| is different to |T|.
++  template<typename U>
++  MOZ_MUST_USE bool putNew(const Lookup& aLookup, U&& aU)
++  {
++    return mImpl.putNew(aLookup, std::forward<U>(aU));
++  }
++
++  // Only call this to populate an empty set after reserving space with init().
++  template<typename U>
++  void putNewInfallible(const Lookup& aLookup, U&& aU)
++  {
++    mImpl.putNewInfallible(aLookup, std::forward<U>(aU));
++  }
+ 
+   // Like |lookup(l)|, but on miss, |p = lookupForAdd(l)| allows efficient
+   // insertion of T value |t| (where |HashPolicy::match(t,l) == true|) using
+   // |add(p,t)|. After |add(p,t)|, |p| points to the new element. E.g.:
+   //
+   //   using HS = HashSet<int>;
+   //   HS h;
+   //   HS::AddPtr p = h.lookupForAdd(3);
+@@ -559,126 +658,32 @@ public:
+ 
+   // See the comment above lookupForAdd() for details.
+   template<typename U>
+   MOZ_MUST_USE bool relookupOrAdd(AddPtr& aPtr, const Lookup& aLookup, U&& aU)
+   {
+     return mImpl.relookupOrAdd(aPtr, aLookup, std::forward<U>(aU));
+   }
+ 
+-  // |iter()| returns an Iterator:
+-  //
+-  //   HashSet<int> h;
+-  //   for (auto iter = h.iter(); !iter.done(); iter.next()) {
+-  //     int i = iter.get();
+-  //   }
+-  //
+-  typedef typename Impl::Iterator Iterator;
+-  Iterator iter() const { return mImpl.iter(); }
+-
+-  // |modIter()| returns a ModIterator:
+-  //
+-  //   HashSet<int> h;
+-  //   for (auto iter = h.modIter(); !iter.done(); iter.next()) {
+-  //     if (iter.get() == 42) {
+-  //       iter.remove();
+-  //     }
+-  //   }
+-  //
+-  // Table resize may occur in ModIterator's destructor.
+-  typedef typename Impl::ModIterator ModIterator;
+-  ModIterator modIter() { return mImpl.modIter(); }
+-
+-  // These are similar to Iterator/ModIterator/iter(), but use different
+-  // terminology.
+-  using Range = typename Impl::Range;
+-  using Enum = typename Impl::Enum;
+-  Range all() const { return mImpl.all(); }
+-
+-  // Remove all elements without changing the capacity.
+-  void clear() { mImpl.clear(); }
+-
+-  // Remove all elements and attempt to minimize the capacity.
+-  void clearAndShrink() { mImpl.clearAndShrink(); }
+-
+-  // Remove all keys/values and release entry storage. The set must be
+-  // initialized via init() again before further use.
+-  void finish() { mImpl.finish(); }
+-
+-  // Is the set empty?
+-  bool empty() const { return mImpl.empty(); }
+-
+-  // Number of elements in the set.
+-  uint32_t count() const { return mImpl.count(); }
+-
+-  // Number of element slots in the set. Note: resize will happen well before
+-  // count() == capacity().
+-  size_t capacity() const { return mImpl.capacity(); }
+-
+-  // The size of the HashSet's entry storage, in bytes. If the elements contain
+-  // pointers to other heap blocks, you must iterate over the set and measure
+-  // them separately; hence the "shallow" prefix.
+-  size_t shallowSizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
+-  {
+-    return mImpl.shallowSizeOfExcludingThis(aMallocSizeOf);
+-  }
+-  size_t shallowSizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
+-  {
+-    return aMallocSizeOf(this) +
+-           mImpl.shallowSizeOfExcludingThis(aMallocSizeOf);
+-  }
+-
+-  // The set's current generation.
+-  Generation generation() const { return mImpl.generation(); }
+-
+-  /************************************************** Shorthand operations */
+-
+-  // Does the set contain an element matching |aLookup|?
+-  bool has(const Lookup& aLookup) const
+-  {
+-    return mImpl.lookup(aLookup).found();
+-  }
+-
+-  // Add |aU| if it is not present already. Returns false on OOM.
+-  template<typename U>
+-  MOZ_MUST_USE bool put(U&& aU)
+-  {
+-    AddPtr p = lookupForAdd(aU);
+-    return p ? true : add(p, std::forward<U>(aU));
+-  }
+-
+-  // Like put(), but asserts that the given key is not already present.
+-  template<typename U>
+-  MOZ_MUST_USE bool putNew(U&& aU)
+-  {
+-    return mImpl.putNew(aU, std::forward<U>(aU));
+-  }
+-
+-  // Like the other putNew(), but for when |Lookup| is different to |T|.
+-  template<typename U>
+-  MOZ_MUST_USE bool putNew(const Lookup& aLookup, U&& aU)
+-  {
+-    return mImpl.putNew(aLookup, std::forward<U>(aU));
+-  }
+-
+-  // Only call this to populate an empty set after reserving space with init().
+-  template<typename U>
+-  void putNewInfallible(const Lookup& aLookup, U&& aU)
+-  {
+-    mImpl.putNewInfallible(aLookup, std::forward<U>(aU));
+-  }
++  // -- Removal --------------------------------------------------------------
+ 
+   // Lookup and remove the element matching |aLookup|, if present.
+   void remove(const Lookup& aLookup)
+   {
+     if (Ptr p = lookup(aLookup)) {
+       remove(p);
+     }
+   }
+ 
++  // Remove a previously found element (assuming aPtr.found()). The set must
++  // not have been mutated in the interim.
++  void remove(Ptr aPtr) { mImpl.remove(aPtr); }
++
++  // -- Rekeying -------------------------------------------------------------
++
+   // Infallibly rekey one entry, if present. Requires that template parameters
+   // T and HashPolicy::Lookup are the same type.
+   void rekeyIfMoved(const Lookup& aOldValue, const T& aNewValue)
+   {
+     if (aOldValue != aNewValue) {
+       rekeyAs(aOldValue, aNewValue, aNewValue);
+     }
+   }
+@@ -703,33 +708,58 @@ public:
+   {
+     MOZ_ASSERT(aPtr.found());
+     MOZ_ASSERT(*aPtr != aNewValue);
+     MOZ_ASSERT(HashPolicy::hash(*aPtr) == HashPolicy::hash(aNewValue));
+     MOZ_ASSERT(HashPolicy::match(*aPtr, aNewValue));
+     const_cast<T&>(*aPtr) = aNewValue;
+   }
+ 
+-  // HashSet is movable.
+-  HashSet(HashSet&& aRhs)
+-    : mImpl(std::move(aRhs.mImpl))
+-  {
+-  }
+-  void operator=(HashSet&& aRhs)
+-  {
+-    MOZ_ASSERT(this != &aRhs, "self-move assignment is prohibited");
+-    mImpl = std::move(aRhs.mImpl);
+-  }
++  // -- Iteration ------------------------------------------------------------
++
++  // |iter()| returns an Iterator:
++  //
++  //   HashSet<int> h;
++  //   for (auto iter = h.iter(); !iter.done(); iter.next()) {
++  //     int i = iter.get();
++  //   }
++  //
++  using Iterator = typename Impl::Iterator;
++  Iterator iter() const { return mImpl.iter(); }
+ 
+-private:
+-  // HashSet is not copyable or assignable.
+-  HashSet(const HashSet& hs) = delete;
+-  HashSet& operator=(const HashSet& hs) = delete;
++  // |modIter()| returns a ModIterator:
++  //
++  //   HashSet<int> h;
++  //   for (auto iter = h.modIter(); !iter.done(); iter.next()) {
++  //     if (iter.get() == 42) {
++  //       iter.remove();
++  //     }
++  //   }
++  //
++  // Table resize may occur in ModIterator's destructor.
++  using ModIterator = typename Impl::ModIterator;
++  ModIterator modIter() { return mImpl.modIter(); }
+ 
+-  friend class Impl::Enum;
++  // These are similar to Iterator/ModIterator/iter(), but use different
++  // terminology.
++  using Range = typename Impl::Range;
++  using Enum = typename Impl::Enum;
++  Range all() const { return mImpl.all(); }
++
++  // -- Clearing -------------------------------------------------------------
++
++  // Remove all elements without changing the capacity.
++  void clear() { mImpl.clear(); }
++
++  // Remove all elements and attempt to minimize the capacity.
++  void clearAndShrink() { mImpl.clearAndShrink(); }
++
++  // Remove all keys/values and release entry storage. The set must be
++  // initialized via init() again before further use.
++  void finish() { mImpl.finish(); }
+ };
+ 
+ //---------------------------------------------------------------------------
+ // Hash Policy
+ //---------------------------------------------------------------------------
+ 
+ // A hash policy |HP| for a hash table with key-type |Key| must provide:
+ //
+

+ 49 - 0
frg/work-js/mozilla-release/patches/1480361-1-63a1.patch

@@ -0,0 +1,49 @@
+# HG changeset patch
+# User Nicholas Nethercote <nnethercote@mozilla.com>
+# Date 1533254611 -36000
+# Node ID d9baec9cf420acf68530b10bca19f67b72e3cb2b
+# Parent  d4ca2c8982afbcac4494d91b65cff5c64e59498a
+Bug 1480361 - Tweak handling of removed entries in HashTable::lookup(). r=luke
+
+There are two improvements here.
+
+- When we're just doing a lookup (i.e. aCollisionBit==0), we don't need to
+  do any special handling of removed entries. (Inlining means that the removed
+  entry code is entirely removed for lookups.)
+
+- When we're doing an insertion (i.e. aCollisionBit==sCollisionBit), we now
+  stop adding collision markings once we find a removed entry, because they're
+  unnecessary after that point.
+
+This change brings the code in alignment with PLDHashTable::SearchTable().
+
+diff --git a/mfbt/HashTable.h b/mfbt/HashTable.h
+--- a/mfbt/HashTable.h
++++ b/mfbt/HashTable.h
+@@ -1761,22 +1761,20 @@ private:
+ 
+     // Collision: double hash.
+     DoubleHash dh = hash2(aKeyHash);
+ 
+     // Save the first removed entry pointer so we can recycle later.
+     Entry* firstRemoved = nullptr;
+ 
+     while (true) {
+-      if (MOZ_UNLIKELY(entry->isRemoved())) {
+-        if (!firstRemoved) {
++      if (aCollisionBit == sCollisionBit && !firstRemoved) {
++        if (MOZ_UNLIKELY(entry->isRemoved())) {
+           firstRemoved = entry;
+-        }
+-      } else {
+-        if (aCollisionBit == sCollisionBit) {
++        } else {
+           entry->setCollision();
+         }
+       }
+ 
+       METER(mStats.mSteps++);
+       h1 = applyDoubleHash(h1, dh);
+ 
+       entry = &mTable[h1];
+

+ 137 - 0
frg/work-js/mozilla-release/patches/1480361-2-63a1.patch

@@ -0,0 +1,137 @@
+# HG changeset patch
+# User Nicholas Nethercote <nnethercote@mozilla.com>
+# Date 1533254617 -36000
+# Node ID 6c0410ddd1f6950a7398321c10b520ac1d378ed2
+# Parent  d9baec9cf420acf68530b10bca19f67b72e3cb2b
+Bug 1480361 - Introduce HashTable::LookupReason. r=luke
+
+Again inspired by PLDHashTable, this makes things a bit clearer than passing 0
+or sCollisionBit.
+
+It also guarantees more strongly that we'll end up with appropriately
+specialized code for the Add vs. NonAdd cases. (That guarantee isn't currently
+needed because the compiler inlines things sufficiently anyway, but it can't
+hurt.)
+
+diff --git a/mfbt/HashTable.h b/mfbt/HashTable.h
+--- a/mfbt/HashTable.h
++++ b/mfbt/HashTable.h
+@@ -1723,28 +1723,33 @@ private:
+ 
+   bool underloaded() { return wouldBeUnderloaded(capacity(), mEntryCount); }
+ 
+   static MOZ_ALWAYS_INLINE bool match(Entry& aEntry, const Lookup& aLookup)
+   {
+     return HashPolicy::match(HashPolicy::getKey(aEntry.get()), aLookup);
+   }
+ 
++  enum LookupReason
++  {
++    ForNonAdd,
++    ForAdd
++  };
++
+   // Warning: in order for readonlyThreadsafeLookup() to be safe this
+   // function must not modify the table in any way when |collisionBit| is 0.
+   // (The use of the METER() macro to increment stats violates this
+   // restriction but we will live with that for now because it's enabled so
+   // rarely.)
++  template<LookupReason Reason>
+   MOZ_ALWAYS_INLINE Entry& lookup(const Lookup& aLookup,
+-                                  HashNumber aKeyHash,
+-                                  uint32_t aCollisionBit) const
++                                  HashNumber aKeyHash) const
+   {
+     MOZ_ASSERT(isLiveHash(aKeyHash));
+     MOZ_ASSERT(!(aKeyHash & sCollisionBit));
+-    MOZ_ASSERT(aCollisionBit == 0 || aCollisionBit == sCollisionBit);
+     MOZ_ASSERT(mTable);
+     METER(mStats.mSearches++);
+ 
+     // Compute the primary hash address.
+     HashNumber h1 = hash1(aKeyHash);
+     Entry* entry = &mTable[h1];
+ 
+     // Miss: return space for a new entry.
+@@ -1761,17 +1766,17 @@ private:
+ 
+     // Collision: double hash.
+     DoubleHash dh = hash2(aKeyHash);
+ 
+     // Save the first removed entry pointer so we can recycle later.
+     Entry* firstRemoved = nullptr;
+ 
+     while (true) {
+-      if (aCollisionBit == sCollisionBit && !firstRemoved) {
++      if (Reason == ForAdd && !firstRemoved) {
+         if (MOZ_UNLIKELY(entry->isRemoved())) {
+           firstRemoved = entry;
+         } else {
+           entry->setCollision();
+         }
+       }
+ 
+       METER(mStats.mSteps++);
+@@ -2123,39 +2128,39 @@ public:
+ 
+   MOZ_ALWAYS_INLINE Ptr lookup(const Lookup& aLookup) const
+   {
+     ReentrancyGuard g(*this);
+     if (!HasHash<HashPolicy>(aLookup)) {
+       return Ptr();
+     }
+     HashNumber keyHash = prepareHash(aLookup);
+-    return Ptr(lookup(aLookup, keyHash, 0), *this);
++    return Ptr(lookup<ForNonAdd>(aLookup, keyHash), *this);
+   }
+ 
+   MOZ_ALWAYS_INLINE Ptr readonlyThreadsafeLookup(const Lookup& aLookup) const
+   {
+     if (!HasHash<HashPolicy>(aLookup)) {
+       return Ptr();
+     }
+     HashNumber keyHash = prepareHash(aLookup);
+-    return Ptr(lookup(aLookup, keyHash, 0), *this);
++    return Ptr(lookup<ForNonAdd>(aLookup, keyHash), *this);
+   }
+ 
+   MOZ_ALWAYS_INLINE AddPtr lookupForAdd(const Lookup& aLookup) const
+   {
+     ReentrancyGuard g(*this);
+     if (!EnsureHash<HashPolicy>(aLookup)) {
+       return AddPtr();
+     }
+     HashNumber keyHash = prepareHash(aLookup);
+     // Directly call the constructor in the return statement to avoid
+     // excess copying when building with Visual Studio 2017.
+     // See bug 1385181.
+-    return AddPtr(lookup(aLookup, keyHash, sCollisionBit), *this, keyHash);
++    return AddPtr(lookup<ForAdd>(aLookup, keyHash), *this, keyHash);
+   }
+ 
+   template<typename... Args>
+   MOZ_MUST_USE bool add(AddPtr& aPtr, Args&&... aArgs)
+   {
+     ReentrancyGuard g(*this);
+     MOZ_ASSERT(mTable);
+     MOZ_ASSERT_IF(aPtr.isValid(), aPtr.mTable == this);
+@@ -2247,17 +2252,17 @@ public:
+ #ifdef DEBUG
+     aPtr.mGeneration = generation();
+     aPtr.mMutationCount = mMutationCount;
+ #endif
+     {
+       ReentrancyGuard g(*this);
+       // Check that aLookup has not been destroyed.
+       MOZ_ASSERT(prepareHash(aLookup) == aPtr.mKeyHash);
+-      aPtr.mEntry = &lookup(aLookup, aPtr.mKeyHash, sCollisionBit);
++      aPtr.mEntry = &lookup<ForAdd>(aLookup, aPtr.mKeyHash);
+     }
+     return aPtr.found() || add(aPtr, std::forward<Args>(aArgs)...);
+   }
+ 
+   void remove(Ptr aPtr)
+   {
+     MOZ_ASSERT(mTable);
+     ReentrancyGuard g(*this);
+

+ 0 - 0
frg/work-js/mozilla-release/patches/mozilla-central-push_430689.patch → frg/work-js/mozilla-release/patches/1480575-63a1.patch


+ 319 - 0
frg/work-js/mozilla-release/patches/1480650-63a1.patch

@@ -0,0 +1,319 @@
+# HG changeset patch
+# User Nicholas Nethercote <nnethercote@mozilla.com>
+# Date 1533261566 -36000
+# Node ID 91b59c5ea423615849aae7badd67bf63090f1ae9
+# Parent  3abea9c60292bd8492e457c3c3c067caf35ee930
+Bug 1480650 - Remove mozilla::HashTable::Stats. r=luke
+
+I bet nobody has used them in years. The use of ad hoc profiling (printfs plus
+post-processing with a tool like https://github.com/nnethercote/counts) is
+generally a better approach.
+
+Bug 1179657 did likewise for PLDHashTable.
+
+diff --git a/mfbt/HashTable.h b/mfbt/HashTable.h
+--- a/mfbt/HashTable.h
++++ b/mfbt/HashTable.h
+@@ -1539,36 +1539,16 @@ public:
+   uint64_t mHashShift : 8; // multiplicative hash shift
+   Entry* mTable;           // entry storage
+   uint32_t mEntryCount;    // number of entries in mTable
+   uint32_t mRemovedCount;  // removed entry sentinels in mTable
+ 
+ #ifdef DEBUG
+   uint64_t mMutationCount;
+   mutable bool mEntered;
+-
+-  // Note that some updates to these stats are not thread-safe. See the
+-  // comment on the three-argument overloading of HashTable::lookup().
+-  mutable struct Stats
+-  {
+-    uint32_t mSearches;       // total number of table searches
+-    uint32_t mSteps;          // hash chain links traversed
+-    uint32_t mHits;           // searches that found key
+-    uint32_t mMisses;         // searches that didn't find key
+-    uint32_t mAddOverRemoved; // adds that recycled a removed entry
+-    uint32_t mRemoves;        // calls to remove
+-    uint32_t mRemoveFrees;    // calls to remove that freed the entry
+-    uint32_t mGrows;          // table expansions
+-    uint32_t mShrinks;        // table contractions
+-    uint32_t mCompresses;     // table compressions
+-    uint32_t mRehashes;       // tombstone decontaminations
+-  } mStats;
+-#define METER(x) x
+-#else
+-#define METER(x)
+ #endif
+ 
+   // The default initial capacity is 32 (enough to hold 16 elements), but it
+   // can be as low as 4.
+   static const uint32_t sMinCapacity = 4;
+   static const uint32_t sMaxInit = 1u << (CAP_BITS - 1);
+   static const uint32_t sMaxCapacity = 1u << CAP_BITS;
+ 
+@@ -1693,17 +1673,16 @@ public:
+     MOZ_ASSERT(newCapacity >= aLen);
+     MOZ_ASSERT(newCapacity <= sMaxCapacity);
+ 
+     mTable = createTable(*this, newCapacity);
+     if (!mTable) {
+       return false;
+     }
+     setTableSizeLog2(log2);
+-    METER(memset(&mStats, 0, sizeof(mStats)));
+     return true;
+   }
+ 
+   bool initialized() const { return !!mTable; }
+ 
+   ~HashTable()
+   {
+     if (mTable) {
+@@ -1760,42 +1739,36 @@ private:
+ 
+   enum LookupReason
+   {
+     ForNonAdd,
+     ForAdd
+   };
+ 
+   // Warning: in order for readonlyThreadsafeLookup() to be safe this
+-  // function must not modify the table in any way when |collisionBit| is 0.
+-  // (The use of the METER() macro to increment stats violates this
+-  // restriction but we will live with that for now because it's enabled so
+-  // rarely.)
++  // function must not modify the table in any way when Reason==ForNonAdd.
+   template<LookupReason Reason>
+   MOZ_ALWAYS_INLINE Entry& lookup(const Lookup& aLookup,
+                                   HashNumber aKeyHash) const
+   {
+     MOZ_ASSERT(isLiveHash(aKeyHash));
+     MOZ_ASSERT(!(aKeyHash & sCollisionBit));
+     MOZ_ASSERT(mTable);
+-    METER(mStats.mSearches++);
+ 
+     // Compute the primary hash address.
+     HashNumber h1 = hash1(aKeyHash);
+     Entry* entry = &mTable[h1];
+ 
+     // Miss: return space for a new entry.
+     if (entry->isFree()) {
+-      METER(mStats.mMisses++);
+       return *entry;
+     }
+ 
+     // Hit: return entry.
+     if (entry->matchHash(aKeyHash) && match(*entry, aLookup)) {
+-      METER(mStats.mHits++);
+       return *entry;
+     }
+ 
+     // Collision: double hash.
+     DoubleHash dh = hash2(aKeyHash);
+ 
+     // Save the first removed entry pointer so we can recycle later.
+     Entry* firstRemoved = nullptr;
+@@ -1804,69 +1777,62 @@ private:
+       if (Reason == ForAdd && !firstRemoved) {
+         if (MOZ_UNLIKELY(entry->isRemoved())) {
+           firstRemoved = entry;
+         } else {
+           entry->setCollision();
+         }
+       }
+ 
+-      METER(mStats.mSteps++);
+       h1 = applyDoubleHash(h1, dh);
+ 
+       entry = &mTable[h1];
+       if (entry->isFree()) {
+-        METER(mStats.mMisses++);
+         return firstRemoved ? *firstRemoved : *entry;
+       }
+ 
+       if (entry->matchHash(aKeyHash) && match(*entry, aLookup)) {
+-        METER(mStats.mHits++);
+         return *entry;
+       }
+     }
+   }
+ 
+   // This is a copy of lookup hardcoded to the assumptions:
+   //   1. the lookup is a lookupForAdd
+   //   2. the key, whose |keyHash| has been passed is not in the table,
+   //   3. no entries have been removed from the table.
+   // This specialized search avoids the need for recovering lookup values
+   // from entries, which allows more flexible Lookup/Key types.
+   Entry& findFreeEntry(HashNumber aKeyHash)
+   {
+     MOZ_ASSERT(!(aKeyHash & sCollisionBit));
+     MOZ_ASSERT(mTable);
+-    METER(mStats.mSearches++);
+ 
+     // We assume 'aKeyHash' has already been distributed.
+ 
+     // Compute the primary hash address.
+     HashNumber h1 = hash1(aKeyHash);
+     Entry* entry = &mTable[h1];
+ 
+     // Miss: return space for a new entry.
+     if (!entry->isLive()) {
+-      METER(mStats.mMisses++);
+       return *entry;
+     }
+ 
+     // Collision: double hash.
+     DoubleHash dh = hash2(aKeyHash);
+ 
+     while (true) {
+       MOZ_ASSERT(!entry->isRemoved());
+       entry->setCollision();
+ 
+-      METER(mStats.mSteps++);
+       h1 = applyDoubleHash(h1, dh);
+ 
+       entry = &mTable[h1];
+       if (!entry->isLive()) {
+-        METER(mStats.mMisses++);
+         return *entry;
+       }
+     }
+   }
+ 
+   enum RebuildStatus
+   {
+     NotOverloaded,
+@@ -1924,60 +1890,49 @@ private:
+   }
+ 
+   RebuildStatus checkOverloaded(FailureBehavior aReportFailure = ReportFailure)
+   {
+     if (!overloaded()) {
+       return NotOverloaded;
+     }
+ 
+-    int deltaLog2;
+-    if (shouldCompressTable()) {
+-      METER(mStats.mCompresses++);
+-      deltaLog2 = 0;
+-    } else {
+-      METER(mStats.mGrows++);
+-      deltaLog2 = 1;
+-    }
+-
++    int deltaLog2 = shouldCompressTable() ? 0 : 1;
+     return changeTableSize(deltaLog2, aReportFailure);
+   }
+ 
+   // Infallibly rehash the table if we are overloaded with removals.
+   void checkOverRemoved()
+   {
+     if (overloaded()) {
+       if (checkOverloaded(DontReportFailure) == RehashFailed) {
+         rehashTableInPlace();
+       }
+     }
+   }
+ 
+   void remove(Entry& aEntry)
+   {
+     MOZ_ASSERT(mTable);
+-    METER(mStats.mRemoves++);
+ 
+     if (aEntry.hasCollision()) {
+       aEntry.removeLive();
+       mRemovedCount++;
+     } else {
+-      METER(mStats.mRemoveFrees++);
+       aEntry.clearLive();
+     }
+     mEntryCount--;
+ #ifdef DEBUG
+     mMutationCount++;
+ #endif
+   }
+ 
+   void checkUnderloaded()
+   {
+     if (underloaded()) {
+-      METER(mStats.mShrinks++);
+       (void)changeTableSize(-1, DontReportFailure);
+     }
+   }
+ 
+   // Resize the table down to the largest capacity which doesn't underload the
+   // table.  Since we call checkUnderloaded() on every remove, you only need
+   // to call this after a bulk removal of items done without calling remove().
+   void compactIfUnderloaded()
+@@ -1996,17 +1951,16 @@ private:
+ 
+   // This is identical to changeTableSize(currentSize), but without requiring
+   // a second table.  We do this by recycling the collision bits to tell us if
+   // the element is already inserted or still waiting to be inserted.  Since
+   // already-inserted elements win any conflicts, we get the same table as we
+   // would have gotten through random insertion order.
+   void rehashTableInPlace()
+   {
+-    METER(mStats.mRehashes++);
+     mRemovedCount = 0;
+     mGen++;
+     for (size_t i = 0; i < capacity(); ++i) {
+       mTable[i].unsetCollision();
+     }
+     for (size_t i = 0; i < capacity();) {
+       Entry* src = &mTable[i];
+ 
+@@ -2048,17 +2002,16 @@ private:
+   {
+     MOZ_ASSERT(mTable);
+ 
+     HashNumber keyHash = prepareHash(aLookup);
+     Entry* entry = &findFreeEntry(keyHash);
+     MOZ_ASSERT(entry);
+ 
+     if (entry->isRemoved()) {
+-      METER(mStats.mAddOverRemoved++);
+       mRemovedCount--;
+       keyHash |= sCollisionBit;
+     }
+ 
+     entry->setLive(keyHash, std::forward<Args>(aArgs)...);
+     mEntryCount++;
+ #ifdef DEBUG
+     mMutationCount++;
+@@ -2208,17 +2161,16 @@ public:
+ #endif
+ 
+     // Changing an entry from removed to live does not affect whether we
+     // are overloaded and can be handled separately.
+     if (aPtr.mEntry->isRemoved()) {
+       if (!this->checkSimulatedOOM()) {
+         return false;
+       }
+-      METER(mStats.mAddOverRemoved++);
+       mRemovedCount--;
+       aPtr.mKeyHash |= sCollisionBit;
+     } else {
+       // Preserve the validity of |aPtr.mEntry|.
+       RebuildStatus status = checkOverloaded();
+       if (status == RehashFailed) {
+         return false;
+       }
+@@ -2314,16 +2266,14 @@ public:
+     putNewInfallibleInternal(aLookup, std::move(t));
+   }
+ 
+   void rekeyAndMaybeRehash(Ptr aPtr, const Lookup& aLookup, const Key& aKey)
+   {
+     rekeyWithoutRehash(aPtr, aLookup, aKey);
+     checkOverRemoved();
+   }
+-
+-#undef METER
+ };
+ 
+ } // namespace detail
+ } // namespace mozilla
+ 
+ #endif /* mozilla_HashTable_h */
+

+ 0 - 0
frg/work-js/mozilla-release/patches/mozilla-central-push_430217.patch → frg/work-js/mozilla-release/patches/1480668-63a1.patch


+ 0 - 0
frg/work-js/mozilla-release/patches/mozilla-central-push_431283.patch → frg/work-js/mozilla-release/patches/1480843-63a1.patch


+ 0 - 0
frg/work-js/mozilla-release/patches/mozilla-central-push_430325.patch → frg/work-js/mozilla-release/patches/1481138-1-63a1.patch


+ 0 - 0
frg/work-js/mozilla-release/patches/mozilla-central-push_430326.patch → frg/work-js/mozilla-release/patches/1481138-2-63a1.patch


+ 157 - 0
frg/work-js/mozilla-release/patches/1481138-3-63a1.patch

@@ -0,0 +1,157 @@
+# HG changeset patch
+# User Nicholas Nethercote <nnethercote@mozilla.com>
+# Date 1533520888 -36000
+# Node ID 09cd991472c91745e9e14da56b7f7d227cc3c073
+# Parent  01dcd8f80341ec39c949e364d5f46fd9c97963da
+Bug 1481138 - Clarify that Hash{Map,Set}::putNew() can be used if elements have been removed. r=luke
+
+Hash{Map,Set}::putNew() can be used on a table that has had elements removed,
+despite some comments to the contrary.
+
+This patch fixes those comments. It also clarifies when putNewInfallible() can
+be used.
+
+This patch also removes the !isRemoved() assertion in findFreeEntry(), which is
+confusing -- !isLive() would be more precise, but also obvious from the
+surrounding code.
+
+MozReview-Commit-ID: q4qwKGBsHx
+
+diff --git a/mfbt/HashTable.h b/mfbt/HashTable.h
+--- a/mfbt/HashTable.h
++++ b/mfbt/HashTable.h
+@@ -268,25 +268,39 @@ public:
+     if (p) {
+       p->value() = std::forward<ValueInput>(aValue);
+       return true;
+     }
+     return add(
+       p, std::forward<KeyInput>(aKey), std::forward<ValueInput>(aValue));
+   }
+ 
+-  // Like put(), but asserts that the given key is not already present.
++  // Like put(), but slightly faster. Must only be used when the given key is
++  // not already present. (In debug builds, assertions check this.)
+   template<typename KeyInput, typename ValueInput>
+   MOZ_MUST_USE bool putNew(KeyInput&& aKey, ValueInput&& aValue)
+   {
+     return mImpl.putNew(
+       aKey, std::forward<KeyInput>(aKey), std::forward<ValueInput>(aValue));
+   }
+ 
+-  // Only call this to populate an empty map after reserving space with init().
++  // Like putNew(), but should be only used when the table is known to be big
++  // enough for the insertion, and hashing cannot fail. Typically this is used
++  // to populate an empty map with known-unique keys after reserving space with
++  // init(), e.g.
++  //
++  //   using HM = HashMap<int,char>;
++  //   HM h;
++  //   if (!h.init(3)) {
++  //     MOZ_CRASH("OOM");
++  //   }
++  //   h.putNewInfallible(1, 'a');    // unique key
++  //   h.putNewInfallible(2, 'b');    // unique key
++  //   h.putNewInfallible(3, 'c');    // unique key
++  //
+   template<typename KeyInput, typename ValueInput>
+   void putNewInfallible(KeyInput&& aKey, ValueInput&& aValue)
+   {
+     mImpl.putNewInfallible(
+       aKey, std::forward<KeyInput>(aKey), std::forward<ValueInput>(aValue));
+   }
+ 
+   // Like |lookup(l)|, but on miss, |p = lookupForAdd(l)| allows efficient
+@@ -564,31 +578,45 @@ public:
+   // Add |aU| if it is not present already. Returns false on OOM.
+   template<typename U>
+   MOZ_MUST_USE bool put(U&& aU)
+   {
+     AddPtr p = lookupForAdd(aU);
+     return p ? true : add(p, std::forward<U>(aU));
+   }
+ 
+-  // Like put(), but asserts that the given key is not already present.
++  // Like put(), but slightly faster. Must only be used when the given element
++  // is not already present. (In debug builds, assertions check this.)
+   template<typename U>
+   MOZ_MUST_USE bool putNew(U&& aU)
+   {
+     return mImpl.putNew(aU, std::forward<U>(aU));
+   }
+ 
+   // Like the other putNew(), but for when |Lookup| is different to |T|.
+   template<typename U>
+   MOZ_MUST_USE bool putNew(const Lookup& aLookup, U&& aU)
+   {
+     return mImpl.putNew(aLookup, std::forward<U>(aU));
+   }
+ 
+-  // Only call this to populate an empty set after reserving space with init().
++  // Like putNew(), but should be only used when the table is known to be big
++  // enough for the insertion, and hashing cannot fail. Typically this is used
++  // to populate an empty set with known-unique elements after reserving space
++  // with init(), e.g.
++  //
++  //   using HS = HashMap<int>;
++  //   HS h;
++  //   if (!h.init(3)) {
++  //     MOZ_CRASH("OOM");
++  //   }
++  //   h.putNewInfallible(1);     // unique element
++  //   h.putNewInfallible(2);     // unique element
++  //   h.putNewInfallible(3);     // unique element
++  //
+   template<typename U>
+   void putNewInfallible(const Lookup& aLookup, U&& aU)
+   {
+     mImpl.putNewInfallible(aLookup, std::forward<U>(aU));
+   }
+ 
+   // Like |lookup(l)|, but on miss, |p = lookupForAdd(l)| allows efficient
+   // insertion of T value |t| (where |HashPolicy::match(t,l) == true|) using
+@@ -1769,22 +1797,19 @@ private:
+       }
+ 
+       if (entry->matchHash(aKeyHash) && match(*entry, aLookup)) {
+         return *entry;
+       }
+     }
+   }
+ 
+-  // This is a copy of lookup hardcoded to the assumptions:
+-  //   1. the lookup is a lookupForAdd
+-  //   2. the key, whose |keyHash| has been passed is not in the table,
+-  //   3. no entries have been removed from the table.
+-  // This specialized search avoids the need for recovering lookup values
+-  // from entries, which allows more flexible Lookup/Key types.
++  // This is a copy of lookup() hardcoded to the assumptions:
++  //   1. the lookup is for an add;
++  //   2. the key, whose |keyHash| has been passed is not in the table.
+   Entry& findFreeEntry(HashNumber aKeyHash)
+   {
+     MOZ_ASSERT(!(aKeyHash & sCollisionBit));
+     MOZ_ASSERT(mTable);
+ 
+     // We assume 'aKeyHash' has already been distributed.
+ 
+     // Compute the primary hash address.
+@@ -1795,17 +1820,16 @@ private:
+     if (!entry->isLive()) {
+       return *entry;
+     }
+ 
+     // Collision: double hash.
+     DoubleHash dh = hash2(aKeyHash);
+ 
+     while (true) {
+-      MOZ_ASSERT(!entry->isRemoved());
+       entry->setCollision();
+ 
+       h1 = applyDoubleHash(h1, dh);
+ 
+       entry = &mTable[h1];
+       if (!entry->isLive()) {
+         return *entry;
+       }
+

+ 13 - 12
frg/work-js/mozilla-release/patches/mozilla-central-push_430937.patch → frg/work-js/mozilla-release/patches/1481171-1-63a1.patch

@@ -3,7 +3,7 @@
 # Date 1533563749 -7200
 # Date 1533563749 -7200
 #      Mon Aug 06 15:55:49 2018 +0200
 #      Mon Aug 06 15:55:49 2018 +0200
 # Node ID 413be91a02578a573edcb765117fc3e73ad6c427
 # Node ID 413be91a02578a573edcb765117fc3e73ad6c427
-# Parent  15911e3bde6b790287204c3d657ea30cb5f8a155
+# Parent  b19c9f2a4900df4d038a1a31fa25be8baa720b92
 Bug 1481171 - Wasm-specific atomics operations.  r=luke
 Bug 1481171 - Wasm-specific atomics operations.  r=luke
 
 
 A large and mostly mechanical change: Prune the non-JS atomic APIs in
 A large and mostly mechanical change: Prune the non-JS atomic APIs in
@@ -470,7 +470,7 @@ diff --git a/js/src/jit/arm/CodeGenerator-arm.cpp b/js/src/jit/arm/CodeGenerator
 diff --git a/js/src/jit/arm/MacroAssembler-arm.cpp b/js/src/jit/arm/MacroAssembler-arm.cpp
 diff --git a/js/src/jit/arm/MacroAssembler-arm.cpp b/js/src/jit/arm/MacroAssembler-arm.cpp
 --- a/js/src/jit/arm/MacroAssembler-arm.cpp
 --- a/js/src/jit/arm/MacroAssembler-arm.cpp
 +++ b/js/src/jit/arm/MacroAssembler-arm.cpp
 +++ b/js/src/jit/arm/MacroAssembler-arm.cpp
-@@ -5260,18 +5260,19 @@ ComputePointerForAtomic(MacroAssembler& 
+@@ -5261,18 +5261,19 @@ ComputePointerForAtomic(MacroAssembler& 
  // However note that that discussion uses 'isb' as the trailing fence.
  // However note that that discussion uses 'isb' as the trailing fence.
  // I've not quite figured out why, and I've gone with dmb here which
  // I've not quite figured out why, and I've gone with dmb here which
  // is safe.  Also see the LLVM source, which uses 'dmb ish' generally.
  // is safe.  Also see the LLVM source, which uses 'dmb ish' generally.
@@ -492,7 +492,7 @@ diff --git a/js/src/jit/arm/MacroAssembler-arm.cpp b/js/src/jit/arm/MacroAssembl
  
  
      Label again;
      Label again;
      Label done;
      Label done;
-@@ -5279,39 +5280,44 @@ CompareExchange(MacroAssembler& masm, Sc
+@@ -5280,39 +5281,44 @@ CompareExchange(MacroAssembler& masm, Sc
      SecondScratchRegisterScope scratch2(masm);
      SecondScratchRegisterScope scratch2(masm);
      Register ptr = ComputePointerForAtomic(masm, mem, scratch2);
      Register ptr = ComputePointerForAtomic(masm, mem, scratch2);
  
  
@@ -540,7 +540,7 @@ diff --git a/js/src/jit/arm/MacroAssembler-arm.cpp b/js/src/jit/arm/MacroAssembl
      switch (nbytes) {
      switch (nbytes) {
        case 1:
        case 1:
          masm.as_strexb(scratch, newval, ptr);
          masm.as_strexb(scratch, newval, ptr);
-@@ -5330,31 +5336,45 @@ CompareExchange(MacroAssembler& masm, Sc
+@@ -5331,31 +5337,45 @@ CompareExchange(MacroAssembler& masm, Sc
      masm.memoryBarrierAfter(sync);
      masm.memoryBarrierAfter(sync);
  }
  }
  
  
@@ -590,7 +590,7 @@ diff --git a/js/src/jit/arm/MacroAssembler-arm.cpp b/js/src/jit/arm/MacroAssembl
  
  
      // Bug 1077321: We may further optimize for ARMv8 (AArch32) here.
      // Bug 1077321: We may further optimize for ARMv8 (AArch32) here.
      Label again;
      Label again;
-@@ -5363,53 +5383,72 @@ AtomicExchange(MacroAssembler& masm, Sca
+@@ -5364,53 +5384,72 @@ AtomicExchange(MacroAssembler& masm, Sca
      SecondScratchRegisterScope scratch2(masm);
      SecondScratchRegisterScope scratch2(masm);
      Register ptr = ComputePointerForAtomic(masm, mem, scratch2);
      Register ptr = ComputePointerForAtomic(masm, mem, scratch2);
  
  
@@ -668,7 +668,7 @@ diff --git a/js/src/jit/arm/MacroAssembler-arm.cpp b/js/src/jit/arm/MacroAssembl
  //     dmb
  //     dmb
  // L0  ldrex* output, [ptr]
  // L0  ldrex* output, [ptr]
  //     sxt*   output, output, 0   ; sign-extend if applicable
  //     sxt*   output, output, 0   ; sign-extend if applicable
-@@ -5423,18 +5462,19 @@ MacroAssembler::atomicExchange(Scalar::T
+@@ -5424,18 +5463,19 @@ MacroAssembler::atomicExchange(Scalar::T
  //
  //
  // Observe that the value being operated into the memory element need
  // Observe that the value being operated into the memory element need
  // not be sign-extended because no OP will make use of bits to the
  // not be sign-extended because no OP will make use of bits to the
@@ -690,7 +690,7 @@ diff --git a/js/src/jit/arm/MacroAssembler-arm.cpp b/js/src/jit/arm/MacroAssembl
      MOZ_ASSERT(flagTemp != InvalidReg);
      MOZ_ASSERT(flagTemp != InvalidReg);
      MOZ_ASSERT(output != value);
      MOZ_ASSERT(output != value);
  
  
-@@ -5443,31 +5483,36 @@ AtomicFetchOp(MacroAssembler& masm, Scal
+@@ -5444,31 +5484,36 @@ AtomicFetchOp(MacroAssembler& masm, Scal
      SecondScratchRegisterScope scratch2(masm);
      SecondScratchRegisterScope scratch2(masm);
      Register ptr = ComputePointerForAtomic(masm, mem, scratch2);
      Register ptr = ComputePointerForAtomic(masm, mem, scratch2);
  
  
@@ -730,7 +730,7 @@ diff --git a/js/src/jit/arm/MacroAssembler-arm.cpp b/js/src/jit/arm/MacroAssembl
          masm.as_sub(scratch, output, O2Reg(value));
          masm.as_sub(scratch, output, O2Reg(value));
          break;
          break;
        case AtomicFetchAndOp:
        case AtomicFetchAndOp:
-@@ -5497,69 +5542,89 @@ AtomicFetchOp(MacroAssembler& masm, Scal
+@@ -5498,69 +5543,89 @@ AtomicFetchOp(MacroAssembler& masm, Scal
  
  
      masm.memoryBarrierAfter(sync);
      masm.memoryBarrierAfter(sync);
  }
  }
@@ -827,7 +827,7 @@ diff --git a/js/src/jit/arm/MacroAssembler-arm.cpp b/js/src/jit/arm/MacroAssembl
          masm.as_sub(scratch, scratch, O2Reg(value));
          masm.as_sub(scratch, scratch, O2Reg(value));
          break;
          break;
        case AtomicFetchAndOp:
        case AtomicFetchAndOp:
-@@ -5586,166 +5651,170 @@ AtomicEffectOp(MacroAssembler& masm, Sca
+@@ -5587,166 +5652,170 @@ AtomicEffectOp(MacroAssembler& masm, Sca
      }
      }
      masm.as_cmp(flagTemp, Imm8(1));
      masm.as_cmp(flagTemp, Imm8(1));
      masm.as_b(&again, MacroAssembler::Equal);
      masm.as_b(&again, MacroAssembler::Equal);
@@ -1068,7 +1068,7 @@ diff --git a/js/src/jit/arm/MacroAssembler-arm.cpp b/js/src/jit/arm/MacroAssembl
      MOZ_ASSERT(temp.low.code() + 1 == temp.high.code());
      MOZ_ASSERT(temp.low.code() + 1 == temp.high.code());
  
  
      // We could avoid this pair requirement but in that case we would end up
      // We could avoid this pair requirement but in that case we would end up
-@@ -5756,20 +5825,21 @@ AtomicFetchOp64(MacroAssembler& masm, co
+@@ -5757,20 +5826,21 @@ AtomicFetchOp64(MacroAssembler& masm, co
      MOZ_ASSERT((output.low.code() & 1) == 0);
      MOZ_ASSERT((output.low.code() & 1) == 0);
      MOZ_ASSERT(output.low.code() + 1 == output.high.code());
      MOZ_ASSERT(output.low.code() + 1 == output.high.code());
  
  
@@ -1092,7 +1092,7 @@ diff --git a/js/src/jit/arm/MacroAssembler-arm.cpp b/js/src/jit/arm/MacroAssembl
        case AtomicFetchSubOp:
        case AtomicFetchSubOp:
          masm.as_sub(temp.low, output.low, O2Reg(value.low), SetCC);
          masm.as_sub(temp.low, output.low, O2Reg(value.low), SetCC);
          masm.as_sbc(temp.high, output.high, O2Reg(value.high));
          masm.as_sbc(temp.high, output.high, O2Reg(value.high));
-@@ -5790,31 +5860,31 @@ AtomicFetchOp64(MacroAssembler& masm, co
+@@ -5791,31 +5861,31 @@ AtomicFetchOp64(MacroAssembler& masm, co
  
  
      ScratchRegisterScope scratch(masm);
      ScratchRegisterScope scratch(masm);
  
  
@@ -1139,7 +1139,7 @@ diff --git a/js/src/jit/arm/MacroAssembler-arm.cpp b/js/src/jit/arm/MacroAssembl
  template<typename T>
  template<typename T>
  static void
  static void
  CompareExchangeJS(MacroAssembler& masm, Scalar::Type arrayType, const Synchronization& sync,
  CompareExchangeJS(MacroAssembler& masm, Scalar::Type arrayType, const Synchronization& sync,
-@@ -5900,26 +5970,26 @@ MacroAssembler::atomicFetchOpJS(Scalar::
+@@ -5901,26 +5971,26 @@ MacroAssembler::atomicFetchOpJS(Scalar::
                                  Register value, const BaseIndex& mem, Register temp1, Register temp2,
                                  Register value, const BaseIndex& mem, Register temp1, Register temp2,
                                  AnyRegister output)
                                  AnyRegister output)
  {
  {
@@ -2011,6 +2011,7 @@ diff --git a/js/src/jit/mips32/CodeGenerator-mips32.cpp b/js/src/jit/mips32/Code
 -    masm.atomicStore64(addr, tmp, value);
 -    masm.atomicStore64(addr, tmp, value);
 +    masm.wasmAtomicStore64(lir->mir()->access(), addr, tmp, value);
 +    masm.wasmAtomicStore64(lir->mir()->access(), addr, tmp, value);
  }
  }
+\ No newline at end of file
 diff --git a/js/src/jit/mips32/MacroAssembler-mips32.cpp b/js/src/jit/mips32/MacroAssembler-mips32.cpp
 diff --git a/js/src/jit/mips32/MacroAssembler-mips32.cpp b/js/src/jit/mips32/MacroAssembler-mips32.cpp
 --- a/js/src/jit/mips32/MacroAssembler-mips32.cpp
 --- a/js/src/jit/mips32/MacroAssembler-mips32.cpp
 +++ b/js/src/jit/mips32/MacroAssembler-mips32.cpp
 +++ b/js/src/jit/mips32/MacroAssembler-mips32.cpp

+ 0 - 0
frg/work-js/mozilla-release/patches/mozilla-central-push_430938.patch → frg/work-js/mozilla-release/patches/1481171-2-63a1.patch


+ 0 - 0
frg/work-js/mozilla-release/patches/mozilla-central-push_431204.patch → frg/work-js/mozilla-release/patches/1481171-3-63a1.patch


+ 0 - 0
frg/work-js/mozilla-release/patches/mozilla-central-push_430377.patch → frg/work-js/mozilla-release/patches/1481239-63a1.patch


+ 0 - 0
frg/work-js/mozilla-release/patches/mozilla-central-push_431084.patch → frg/work-js/mozilla-release/patches/1481247-63a1.patch


+ 0 - 0
frg/work-js/mozilla-release/patches/mozilla-central-push_430683.patch → frg/work-js/mozilla-release/patches/1481484-63a1.patch


+ 0 - 0
frg/work-js/mozilla-release/patches/mozilla-central-push_431260.patch → frg/work-js/mozilla-release/patches/1481556-63a1.patch


+ 0 - 0
frg/work-js/mozilla-release/patches/mozilla-central-push_430925.patch → frg/work-js/mozilla-release/patches/1481858-63a1.patch


+ 51 - 0
frg/work-js/mozilla-release/patches/1481998-2no1-63a1.patch

@@ -0,0 +1,51 @@
+# HG changeset patch
+# User Nicholas Nethercote <nnethercote@mozilla.com>
+# Date 1533879313 -36000
+# Node ID 223884f0ad76f8224f046311dd016b83fbb3aa6e
+# Parent  6bb61989d9ae6611277918cbf320e878c55dd825
+Bug 1481998 - Define lookup() in terms of readonlyThreadsafeLookup(). r=luke
+
+The two functions are almost identical. This change minimizes duplication.
+
+diff --git a/mfbt/HashTable.h b/mfbt/HashTable.h
+--- a/mfbt/HashTable.h
++++ b/mfbt/HashTable.h
+@@ -2107,33 +2107,29 @@ public:
+     return aMallocSizeOf(mTable);
+   }
+ 
+   size_t shallowSizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
+   {
+     return aMallocSizeOf(this) + shallowSizeOfExcludingThis(aMallocSizeOf);
+   }
+ 
+-  MOZ_ALWAYS_INLINE Ptr lookup(const Lookup& aLookup) const
++  MOZ_ALWAYS_INLINE Ptr readonlyThreadsafeLookup(const Lookup& aLookup) const
+   {
+-    ReentrancyGuard g(*this);
+     if (!HasHash<HashPolicy>(aLookup)) {
+       return Ptr();
+     }
+     HashNumber keyHash = prepareHash(aLookup);
+     return Ptr(lookup<ForNonAdd>(aLookup, keyHash), *this);
+   }
+ 
+-  MOZ_ALWAYS_INLINE Ptr readonlyThreadsafeLookup(const Lookup& aLookup) const
++  MOZ_ALWAYS_INLINE Ptr lookup(const Lookup& aLookup) const
+   {
+-    if (!HasHash<HashPolicy>(aLookup)) {
+-      return Ptr();
+-    }
+-    HashNumber keyHash = prepareHash(aLookup);
+-    return Ptr(lookup<ForNonAdd>(aLookup, keyHash), *this);
++    ReentrancyGuard g(*this);
++    return readonlyThreadsafeLookup(aLookup);
+   }
+ 
+   MOZ_ALWAYS_INLINE AddPtr lookupForAdd(const Lookup& aLookup) const
+   {
+     ReentrancyGuard g(*this);
+     if (!EnsureHash<HashPolicy>(aLookup)) {
+       return AddPtr();
+     }
+

File diff suppressed because it is too large
+ 97 - 333
frg/work-js/mozilla-release/patches/1481998-3-63a1.patch


+ 0 - 0
frg/work-js/mozilla-release/patches/mozilla-central-push_430883.patch → frg/work-js/mozilla-release/patches/1482133-1-63a1.patch


+ 0 - 0
frg/work-js/mozilla-release/patches/mozilla-central-push_430884.patch → frg/work-js/mozilla-release/patches/1482133-2-63a1.patch


+ 0 - 0
frg/work-js/mozilla-release/patches/mozilla-central-push_430885.patch → frg/work-js/mozilla-release/patches/1482133-3-63a1.patch


+ 0 - 0
frg/work-js/mozilla-release/patches/mozilla-central-push_430888.patch → frg/work-js/mozilla-release/patches/1482135-63a1.patch


+ 0 - 0
frg/work-js/mozilla-release/patches/mozilla-central-push_431376.patch → frg/work-js/mozilla-release/patches/1482359-63a1.patch


+ 0 - 0
frg/work-js/mozilla-release/patches/mozilla-central-push_430968.patch → frg/work-js/mozilla-release/patches/1482365-63a1.patch


+ 0 - 0
frg/work-js/mozilla-release/patches/mozilla-central-push_431377.patch → frg/work-js/mozilla-release/patches/1482846-1-63a1.patch


+ 0 - 0
frg/work-js/mozilla-release/patches/mozilla-central-push_431378.patch → frg/work-js/mozilla-release/patches/1482846-2-63a1.patch


+ 0 - 0
frg/work-js/mozilla-release/patches/mozilla-central-push_431379.patch → frg/work-js/mozilla-release/patches/1482846-3-63a1.patch


+ 0 - 0
frg/work-js/mozilla-release/patches/mozilla-central-push_431380.patch → frg/work-js/mozilla-release/patches/1482846-4-63a1.patch


+ 18 - 18
frg/work-js/mozilla-release/patches/1482931-1-63a1.patch

@@ -2,7 +2,7 @@
 # User Ted Campbell <tcampbell@mozilla.com>
 # User Ted Campbell <tcampbell@mozilla.com>
 # Date 1534169521 14400
 # Date 1534169521 14400
 # Node ID 490b0d605859e612832f6b655d4168e39a30ceb1
 # Node ID 490b0d605859e612832f6b655d4168e39a30ceb1
-# Parent  70c41bcb9cd6529836ee3c5595d6ee5d5c49e11e
+# Parent  5e3c90e38474307691812463f3c0e9722f7eae42
 Bug 1482931 - Cleanup const-ness of statics in js/src. r=waldo
 Bug 1482931 - Cleanup const-ness of statics in js/src. r=waldo
 
 
 Mark read-only global data as const. Replacing |const char* x[]| with
 Mark read-only global data as const. Replacing |const char* x[]| with
@@ -14,7 +14,7 @@ MozReview-Commit-ID: Ftv7ziIAWGh
 diff --git a/js/src/gc/GC.cpp b/js/src/gc/GC.cpp
 diff --git a/js/src/gc/GC.cpp b/js/src/gc/GC.cpp
 --- a/js/src/gc/GC.cpp
 --- a/js/src/gc/GC.cpp
 +++ b/js/src/gc/GC.cpp
 +++ b/js/src/gc/GC.cpp
-@@ -1036,17 +1036,17 @@ GCRuntime::GCRuntime(JSRuntime* rt) :
+@@ -1037,17 +1037,17 @@ GCRuntime::GCRuntime(JSRuntime* rt) :
  void
  void
  GCRuntime::getZealBits(uint32_t* zealBits, uint32_t* frequency, uint32_t* scheduled)
  GCRuntime::getZealBits(uint32_t* zealBits, uint32_t* frequency, uint32_t* scheduled)
  {
  {
@@ -33,7 +33,7 @@ diff --git a/js/src/gc/GC.cpp b/js/src/gc/GC.cpp
      "    0:  (None) Normal amount of collection (resets all modes)\n"
      "    0:  (None) Normal amount of collection (resets all modes)\n"
      "    1:  (RootsChange) Collect when roots are added or removed\n"
      "    1:  (RootsChange) Collect when roots are added or removed\n"
      "    2:  (Alloc) Collect when every N allocations (default: 100)\n"
      "    2:  (Alloc) Collect when every N allocations (default: 100)\n"
-@@ -1244,17 +1244,17 @@ GCRuntime::parseAndSetZeal(const char* s
+@@ -1245,17 +1245,17 @@ GCRuntime::parseAndSetZeal(const char* s
      }
      }
  
  
      return true;
      return true;
@@ -77,11 +77,11 @@ diff --git a/js/src/gc/GC.h b/js/src/gc/GC.h
 diff --git a/js/src/gc/Nursery.cpp b/js/src/gc/Nursery.cpp
 diff --git a/js/src/gc/Nursery.cpp b/js/src/gc/Nursery.cpp
 --- a/js/src/gc/Nursery.cpp
 --- a/js/src/gc/Nursery.cpp
 +++ b/js/src/gc/Nursery.cpp
 +++ b/js/src/gc/Nursery.cpp
-@@ -611,17 +611,17 @@ js::Nursery::renderProfileJSON(JSONPrint
-     if (previousGC.nurseryLazyCapacity != previousGC.nurseryCapacity)
-         json.property("lazy_capacity", previousGC.nurseryLazyCapacity);
-     if (!timeInChunkAlloc_.IsZero())
-         json.property("chunk_alloc_us", timeInChunkAlloc_, json.MICROSECONDS);
+@@ -617,17 +617,17 @@ js::Nursery::renderProfileJSON(JSONPrint
+     // in non-nightly builds.
+     json.property("cells_allocated_nursery", runtime()->gc.stats().allocsSinceMinorGCNursery());
+     json.property("cells_allocated_tenured", runtime()->gc.stats().allocsSinceMinorGCTenured());
+ #endif
  
  
      json.beginObjectProperty("phase_times");
      json.beginObjectProperty("phase_times");
  
  
@@ -137,9 +137,9 @@ diff --git a/js/src/jit/CacheIR.h b/js/src/jit/CacheIR.h
      _(GuardIsObject)                      \
      _(GuardIsObject)                      \
      _(GuardIsObjectOrNull)                \
      _(GuardIsObjectOrNull)                \
      _(GuardIsNullOrUndefined)             \
      _(GuardIsNullOrUndefined)             \
-     _(GuardIsBoolean)                     \
-     _(GuardIsString)                      \
-     _(GuardIsSymbol)                      \
+     _(GuardIsNotNullOrUndefined)          \
+     _(GuardIsNull)                        \
+     _(GuardIsUndefined)                   \
 diff --git a/js/src/jit/IonOptimizationLevels.cpp b/js/src/jit/IonOptimizationLevels.cpp
 diff --git a/js/src/jit/IonOptimizationLevels.cpp b/js/src/jit/IonOptimizationLevels.cpp
 --- a/js/src/jit/IonOptimizationLevels.cpp
 --- a/js/src/jit/IonOptimizationLevels.cpp
 +++ b/js/src/jit/IonOptimizationLevels.cpp
 +++ b/js/src/jit/IonOptimizationLevels.cpp
@@ -423,15 +423,15 @@ diff --git a/js/src/vm/ArrayBufferObject.cpp b/js/src/vm/ArrayBufferObject.cpp
      // ArrayBufferObject entries are only added when there are multiple views.
      // ArrayBufferObject entries are only added when there are multiple views.
      MOZ_ASSERT(buffer->firstView());
      MOZ_ASSERT(buffer->firstView());
  
  
-     if (!map.initialized() && !map.init()) {
+     Map::AddPtr p = map.lookupForAdd(buffer);
 diff --git a/js/src/vm/BytecodeUtil.cpp b/js/src/vm/BytecodeUtil.cpp
 diff --git a/js/src/vm/BytecodeUtil.cpp b/js/src/vm/BytecodeUtil.cpp
 --- a/js/src/vm/BytecodeUtil.cpp
 --- a/js/src/vm/BytecodeUtil.cpp
 +++ b/js/src/vm/BytecodeUtil.cpp
 +++ b/js/src/vm/BytecodeUtil.cpp
-@@ -71,27 +71,27 @@ const JSCodeSpec js::CodeSpec[] = {
+@@ -68,27 +68,27 @@ const JSCodeSpec js::CodeSpec[] = {
+     FOR_EACH_OPCODE(MAKE_CODESPEC)
+ #undef MAKE_CODESPEC
  };
  };
  
  
- const unsigned js::NumCodeSpecs = mozilla::ArrayLength(CodeSpec);
- 
  /*
  /*
   * Each element of the array is either a source literal associated with JS
   * Each element of the array is either a source literal associated with JS
   * bytecode or null.
   * bytecode or null.
@@ -457,7 +457,7 @@ diff --git a/js/src/vm/BytecodeUtil.cpp b/js/src/vm/BytecodeUtil.cpp
  /************************************************************************/
  /************************************************************************/
  
  
  static bool
  static bool
-@@ -112,17 +112,18 @@ js::GetVariableBytecodeLength(jsbytecode
+@@ -109,17 +109,18 @@ js::GetVariableBytecodeLength(jsbytecode
          unsigned ncases = unsigned(high - low + 1);
          unsigned ncases = unsigned(high - low + 1);
          return 1 + 3 * JUMP_OFFSET_LEN + ncases * JUMP_OFFSET_LEN;
          return 1 + 3 * JUMP_OFFSET_LEN + ncases * JUMP_OFFSET_LEN;
        }
        }
@@ -480,7 +480,7 @@ diff --git a/js/src/vm/BytecodeUtil.cpp b/js/src/vm/BytecodeUtil.cpp
 diff --git a/js/src/vm/BytecodeUtil.h b/js/src/vm/BytecodeUtil.h
 diff --git a/js/src/vm/BytecodeUtil.h b/js/src/vm/BytecodeUtil.h
 --- a/js/src/vm/BytecodeUtil.h
 --- a/js/src/vm/BytecodeUtil.h
 +++ b/js/src/vm/BytecodeUtil.h
 +++ b/js/src/vm/BytecodeUtil.h
-@@ -822,17 +822,17 @@ class PCCounts
+@@ -807,17 +807,17 @@ class PCCounts
  
  
      uint64_t& numExec() {
      uint64_t& numExec() {
          return numExec_;
          return numExec_;
@@ -524,7 +524,7 @@ diff --git a/js/src/vm/TraceLoggingGraph.cpp b/js/src/vm/TraceLoggingGraph.cpp
 diff --git a/js/src/wasm/WasmFrameIter.cpp b/js/src/wasm/WasmFrameIter.cpp
 diff --git a/js/src/wasm/WasmFrameIter.cpp b/js/src/wasm/WasmFrameIter.cpp
 --- a/js/src/wasm/WasmFrameIter.cpp
 --- a/js/src/wasm/WasmFrameIter.cpp
 +++ b/js/src/wasm/WasmFrameIter.cpp
 +++ b/js/src/wasm/WasmFrameIter.cpp
-@@ -1284,21 +1284,21 @@ ThunkedNativeToDescription(SymbolicAddre
+@@ -1280,21 +1280,21 @@ ThunkedNativeToDescription(SymbolicAddre
  const char*
  const char*
  ProfilingFrameIterator::label() const
  ProfilingFrameIterator::label() const
  {
  {

+ 41 - 0
frg/work-js/mozilla-release/patches/1483062-1-63a1.patch

@@ -0,0 +1,41 @@
+# HG changeset patch
+# User Nicholas Nethercote <nnethercote@mozilla.com>
+# Date 1533788389 -36000
+#      Thu Aug 09 14:19:49 2018 +1000
+# Node ID e483b91eafbced7dd6636139cea44240a511bb5e
+# Parent  417967cf69de08d624ccbc85886ce8f0e224fdd4
+Bug 1483062 - Remove HashTable::maybeCreateTable. r=luke
+
+It's dead.
+
+diff --git a/mfbt/HashTable.h b/mfbt/HashTable.h
+--- a/mfbt/HashTable.h
++++ b/mfbt/HashTable.h
+@@ -1631,27 +1631,16 @@ public:
+     if (table) {
+       for (uint32_t i = 0; i < aCapacity; i++) {
+         new (&table[i]) Entry();
+       }
+     }
+     return table;
+   }
+ 
+-  static Entry* maybeCreateTable(AllocPolicy& aAllocPolicy, uint32_t aCapacity)
+-  {
+-    Entry* table = aAllocPolicy.template maybe_pod_malloc<Entry>(aCapacity);
+-    if (table) {
+-      for (uint32_t i = 0; i < aCapacity; i++) {
+-        new (&table[i]) Entry();
+-      }
+-    }
+-    return table;
+-  }
+-
+   static void destroyTable(AllocPolicy& aAllocPolicy,
+                            Entry* aOldTable,
+                            uint32_t aCapacity)
+   {
+     Entry* end = aOldTable + aCapacity;
+     for (Entry* e = aOldTable; e < end; ++e) {
+       e->~Entry();
+     }

+ 92 - 0
frg/work-js/mozilla-release/patches/1483062-2-63a1.patch

@@ -0,0 +1,92 @@
+# HG changeset patch
+# User Nicholas Nethercote <nnethercote@mozilla.com>
+# Date 1534203360 -36000
+#      Tue Aug 14 09:36:00 2018 +1000
+# Node ID f1e1cf1d42ec20c547a46cee30163a0b41fa36f4
+# Parent  e483b91eafbced7dd6636139cea44240a511bb5e
+Bug 1483062 - Rename HashTable::findFreeEntry() as findNonLiveEntry(). r=luke
+
+Because that's a more accurate description of what it does -- it finds free
+*and* removed entries.
+
+diff --git a/mfbt/HashTable.h b/mfbt/HashTable.h
+--- a/mfbt/HashTable.h
++++ b/mfbt/HashTable.h
+@@ -1780,18 +1780,18 @@ private:
+       if (entry->matchHash(aKeyHash) && match(*entry, aLookup)) {
+         return *entry;
+       }
+     }
+   }
+ 
+   // This is a copy of lookup() hardcoded to the assumptions:
+   //   1. the lookup is for an add;
+-  //   2. the key, whose |keyHash| has been passed is not in the table.
+-  Entry& findFreeEntry(HashNumber aKeyHash)
++  //   2. the key, whose |keyHash| has been passed, is not in the table.
++  Entry& findNonLiveEntry(HashNumber aKeyHash)
+   {
+     MOZ_ASSERT(!(aKeyHash & sCollisionBit));
+     MOZ_ASSERT(mTable);
+ 
+     // We assume 'aKeyHash' has already been distributed.
+ 
+     // Compute the primary hash address.
+     HashNumber h1 = hash1(aKeyHash);
+@@ -1853,17 +1853,17 @@ private:
+     mGen++;
+     mTable = newTable;
+ 
+     // Copy only live entries, leaving removed ones behind.
+     Entry* end = oldTable + oldCapacity;
+     for (Entry* src = oldTable; src < end; ++src) {
+       if (src->isLive()) {
+         HashNumber hn = src->getKeyHash();
+-        findFreeEntry(hn).setLive(
++        findNonLiveEntry(hn).setLive(
+           hn, std::move(const_cast<typename Entry::NonConstT&>(src->get())));
+       }
+ 
+       src->~Entry();
+     }
+ 
+     // All entries have been destroyed, no need to destroyTable.
+     this->free_(oldTable, oldCapacity);
+@@ -1973,17 +1973,17 @@ private:
+   // Prefer to use putNewInfallible; this function does not check
+   // invariants.
+   template<typename... Args>
+   void putNewInfallibleInternal(const Lookup& aLookup, Args&&... aArgs)
+   {
+     MOZ_ASSERT(mTable);
+ 
+     HashNumber keyHash = prepareHash(aLookup);
+-    Entry* entry = &findFreeEntry(keyHash);
++    Entry* entry = &findNonLiveEntry(keyHash);
+     MOZ_ASSERT(entry);
+ 
+     if (entry->isRemoved()) {
+       mRemovedCount--;
+       keyHash |= sCollisionBit;
+     }
+ 
+     entry->setLive(keyHash, std::forward<Args>(aArgs)...);
+@@ -2172,17 +2172,17 @@ public:
+       RebuildStatus status = checkOverloaded();
+       if (status == RehashFailed) {
+         return false;
+       }
+       if (status == NotOverloaded && !this->checkSimulatedOOM()) {
+         return false;
+       }
+       if (status == Rehashed) {
+-        aPtr.mEntry = &findFreeEntry(aPtr.mKeyHash);
++        aPtr.mEntry = &findNonLiveEntry(aPtr.mKeyHash);
+       }
+     }
+ 
+     aPtr.mEntry->setLive(aPtr.mKeyHash, std::forward<Args>(aArgs)...);
+     mEntryCount++;
+ #ifdef DEBUG
+     mMutationCount++;
+     aPtr.mGeneration = generation();

+ 205 - 0
frg/work-js/mozilla-release/patches/1483062-3-63a1.patch

@@ -0,0 +1,205 @@
+# HG changeset patch
+# User Nicholas Nethercote <nnethercote@mozilla.com>
+# Date 1534209579 -36000
+#      Tue Aug 14 11:19:39 2018 +1000
+# Node ID 43e351bda401e80292efbde947e56d1893b95903
+# Parent  f1e1cf1d42ec20c547a46cee30163a0b41fa36f4
+Bug 1483062 - Rename some HashTable methods. r=luke
+
+Specifically:
+- checkOverloaded  -> rehashIfOverloaded
+- checkUnderloaded -> shrinkIfUnderloaded
+- checkOverRemoved -> rehashIfOverRemoved
+
+Because I've always found that the `check` prefix doesn't clearly explain that
+the table might be changed,
+
+And:
+- shouldCompressTable -> overRemoved
+
+Because that matches `overloaded` and `underloaded`.
+
+diff --git a/mfbt/HashTable.h b/mfbt/HashTable.h
+--- a/mfbt/HashTable.h
++++ b/mfbt/HashTable.h
+@@ -1439,17 +1439,17 @@ public:
+ 
+     void rekey(const Key& k) { rekey(k, k); }
+ 
+     // Potentially rehashes the table.
+     ~ModIterator()
+     {
+       if (mRekeyed) {
+         mTable.mGen++;
+-        mTable.checkOverRemoved();
++        mTable.rehashIfOverRemoved();
+       }
+ 
+       if (mRemoved) {
+         mTable.compact();
+       }
+     }
+   };
+ 
+@@ -1865,42 +1865,43 @@ private:
+       src->~Entry();
+     }
+ 
+     // All entries have been destroyed, no need to destroyTable.
+     this->free_(oldTable, oldCapacity);
+     return Rehashed;
+   }
+ 
+-  bool shouldCompressTable()
++  bool overRemoved()
+   {
+     // Succeed if a quarter or more of all entries are removed. Note that this
+     // always succeeds if capacity() == 0 (i.e. entry storage has not been
+     // allocated), which is what we want, because it means changeTableSize()
+     // will allocate the requested capacity rather than doubling it.
+     return mRemovedCount >= (capacity() >> 2);
+   }
+ 
+-  RebuildStatus checkOverloaded(FailureBehavior aReportFailure = ReportFailure)
++  RebuildStatus rehashIfOverloaded(
++    FailureBehavior aReportFailure = ReportFailure)
+   {
+     if (!overloaded()) {
+       return NotOverloaded;
+     }
+ 
+-    uint32_t newCapacity = shouldCompressTable()
++    uint32_t newCapacity = overRemoved()
+                          ? rawCapacity()
+                          : rawCapacity() * 2;
+     return changeTableSize(newCapacity, aReportFailure);
+   }
+ 
+   // Infallibly rehash the table if we are overloaded with removals.
+-  void checkOverRemoved()
++  void rehashIfOverRemoved()
+   {
+     if (overloaded()) {
+-      if (checkOverloaded(DontReportFailure) == RehashFailed) {
++      if (rehashIfOverloaded(DontReportFailure) == RehashFailed) {
+         rehashTableInPlace();
+       }
+     }
+   }
+ 
+   void remove(Entry& aEntry)
+   {
+     MOZ_ASSERT(mTable);
+@@ -1912,17 +1913,17 @@ private:
+       aEntry.clearLive();
+     }
+     mEntryCount--;
+ #ifdef DEBUG
+     mMutationCount++;
+ #endif
+   }
+ 
+-  void checkUnderloaded()
++  void shrinkIfUnderloaded()
+   {
+     if (underloaded()) {
+       (void)changeTableSize(capacity() / 2, DontReportFailure);
+     }
+   }
+ 
+   // This is identical to changeTableSize(currentSize), but without requiring
+   // a second table.  We do this by recycling the collision bits to tell us if
+@@ -2003,17 +2004,17 @@ public:
+     mRemovedCount = 0;
+     mEntryCount = 0;
+ #ifdef DEBUG
+     mMutationCount++;
+ #endif
+   }
+ 
+   // Resize the table down to the smallest capacity that doesn't overload the
+-  // table. Since we call checkUnderloaded() on every remove, you only need
++  // table. Since we call shrinkIfUnderloaded() on every remove, you only need
+   // to call this after a bulk removal of items done without calling remove().
+   void compact()
+   {
+     if (empty()) {
+       // Free the entry storage.
+       this->free_(mTable, capacity());
+       mGen++;
+       mHashShift = hashShift(0);  // gives minimum capacity on regrowth
+@@ -2164,17 +2165,17 @@ public:
+     if (aPtr.mEntry->isRemoved()) {
+       if (!this->checkSimulatedOOM()) {
+         return false;
+       }
+       mRemovedCount--;
+       aPtr.mKeyHash |= sCollisionBit;
+     } else {
+       // Preserve the validity of |aPtr.mEntry|.
+-      RebuildStatus status = checkOverloaded();
++      RebuildStatus status = rehashIfOverloaded();
+       if (status == RehashFailed) {
+         return false;
+       }
+       if (status == NotOverloaded && !this->checkSimulatedOOM()) {
+         return false;
+       }
+       if (status == Rehashed) {
+         aPtr.mEntry = &findNonLiveEntry(aPtr.mKeyHash);
+@@ -2207,17 +2208,17 @@ public:
+   MOZ_MUST_USE bool putNew(const Lookup& aLookup, Args&&... aArgs)
+   {
+     if (!this->checkSimulatedOOM()) {
+       return false;
+     }
+     if (!EnsureHash<HashPolicy>(aLookup)) {
+       return false;
+     }
+-    if (checkOverloaded() == RehashFailed) {
++    if (rehashIfOverloaded() == RehashFailed) {
+       return false;
+     }
+     putNewInfallible(aLookup, std::forward<Args>(aArgs)...);
+     return true;
+   }
+ 
+   // Note: |aLookup| may be a reference to a piece of |u|, so this function
+   // must take care not to use |aLookup| after moving |u|.
+@@ -2245,17 +2246,17 @@ public:
+ 
+   void remove(Ptr aPtr)
+   {
+     MOZ_ASSERT(mTable);
+     ReentrancyGuard g(*this);
+     MOZ_ASSERT(aPtr.found());
+     MOZ_ASSERT(aPtr.mGeneration == generation());
+     remove(*aPtr.mEntry);
+-    checkUnderloaded();
++    shrinkIfUnderloaded();
+   }
+ 
+   void rekeyWithoutRehash(Ptr aPtr, const Lookup& aLookup, const Key& aKey)
+   {
+     MOZ_ASSERT(mTable);
+     ReentrancyGuard g(*this);
+     MOZ_ASSERT(aPtr.found());
+     MOZ_ASSERT(aPtr.mGeneration == generation());
+@@ -2263,16 +2264,16 @@ public:
+     HashPolicy::setKey(t, const_cast<Key&>(aKey));
+     remove(*aPtr.mEntry);
+     putNewInfallibleInternal(aLookup, std::move(t));
+   }
+ 
+   void rekeyAndMaybeRehash(Ptr aPtr, const Lookup& aLookup, const Key& aKey)
+   {
+     rekeyWithoutRehash(aPtr, aLookup, aKey);
+-    checkOverRemoved();
++    rehashIfOverRemoved();
+   }
+ };
+ 
+ } // namespace detail
+ } // namespace mozilla
+ 
+ #endif /* mozilla_HashTable_h */

+ 80 - 0
frg/work-js/mozilla-release/patches/1483062-4-63a1.patch

@@ -0,0 +1,80 @@
+# HG changeset patch
+# User Nicholas Nethercote <nnethercote@mozilla.com>
+# Date 1534211815 -36000
+#      Tue Aug 14 11:56:55 2018 +1000
+# Node ID 2d9e3360e858f6c502ae9728280efb0f12daa7e4
+# Parent  43e351bda401e80292efbde947e56d1893b95903
+Bug 1483062 - Rename HashTable::rehashIfOverRemoved(). r=luke
+
+infallibleRehashIfOverloaded() actually matches what it does.
+
+Also, the patch removes the `overloaded()` test within the function, because
+`rehashIfOverloaded()` has the same test.
+
+diff --git a/mfbt/HashTable.h b/mfbt/HashTable.h
+--- a/mfbt/HashTable.h
++++ b/mfbt/HashTable.h
+@@ -1439,17 +1439,17 @@ public:
+ 
+     void rekey(const Key& k) { rekey(k, k); }
+ 
+     // Potentially rehashes the table.
+     ~ModIterator()
+     {
+       if (mRekeyed) {
+         mTable.mGen++;
+-        mTable.rehashIfOverRemoved();
++        mTable.infallibleRehashIfOverloaded();
+       }
+ 
+       if (mRemoved) {
+         mTable.compact();
+       }
+     }
+   };
+ 
+@@ -1887,23 +1887,20 @@ private:
+     }
+ 
+     uint32_t newCapacity = overRemoved()
+                          ? rawCapacity()
+                          : rawCapacity() * 2;
+     return changeTableSize(newCapacity, aReportFailure);
+   }
+ 
+-  // Infallibly rehash the table if we are overloaded with removals.
+-  void rehashIfOverRemoved()
++  void infallibleRehashIfOverloaded()
+   {
+-    if (overloaded()) {
+-      if (rehashIfOverloaded(DontReportFailure) == RehashFailed) {
+-        rehashTableInPlace();
+-      }
++    if (rehashIfOverloaded(DontReportFailure) == RehashFailed) {
++      rehashTableInPlace();
+     }
+   }
+ 
+   void remove(Entry& aEntry)
+   {
+     MOZ_ASSERT(mTable);
+ 
+     if (aEntry.hasCollision()) {
+@@ -2264,16 +2261,16 @@ public:
+     HashPolicy::setKey(t, const_cast<Key&>(aKey));
+     remove(*aPtr.mEntry);
+     putNewInfallibleInternal(aLookup, std::move(t));
+   }
+ 
+   void rekeyAndMaybeRehash(Ptr aPtr, const Lookup& aLookup, const Key& aKey)
+   {
+     rekeyWithoutRehash(aPtr, aLookup, aKey);
+-    rehashIfOverRemoved();
++    infallibleRehashIfOverloaded();
+   }
+ };
+ 
+ } // namespace detail
+ } // namespace mozilla
+ 
+ #endif /* mozilla_HashTable_h */

+ 53 - 0
frg/work-js/mozilla-release/patches/1483062-5-63a1.patch

@@ -0,0 +1,53 @@
+# HG changeset patch
+# User Nicholas Nethercote <nnethercote@mozilla.com>
+# Date 1534295456 -36000
+#      Wed Aug 15 11:10:56 2018 +1000
+# Node ID a3bf3a494b0b7c2817e3f6f3daa9cf4ec7624435
+# Parent  2d9e3360e858f6c502ae9728280efb0f12daa7e4
+Bug 1483062 - Inline and remove HashTable::overRemoved(). r=luke
+
+diff --git a/mfbt/HashTable.h b/mfbt/HashTable.h
+--- a/mfbt/HashTable.h
++++ b/mfbt/HashTable.h
+@@ -1865,35 +1865,29 @@ private:
+       src->~Entry();
+     }
+ 
+     // All entries have been destroyed, no need to destroyTable.
+     this->free_(oldTable, oldCapacity);
+     return Rehashed;
+   }
+ 
+-  bool overRemoved()
+-  {
+-    // Succeed if a quarter or more of all entries are removed. Note that this
+-    // always succeeds if capacity() == 0 (i.e. entry storage has not been
+-    // allocated), which is what we want, because it means changeTableSize()
+-    // will allocate the requested capacity rather than doubling it.
+-    return mRemovedCount >= (capacity() >> 2);
+-  }
+-
+   RebuildStatus rehashIfOverloaded(
+     FailureBehavior aReportFailure = ReportFailure)
+   {
+     if (!overloaded()) {
+       return NotOverloaded;
+     }
+ 
+-    uint32_t newCapacity = overRemoved()
+-                         ? rawCapacity()
+-                         : rawCapacity() * 2;
++    // Succeed if a quarter or more of all entries are removed. Note that this
++    // always succeeds if capacity() == 0 (i.e. entry storage has not been
++    // allocated), which is what we want, because it means changeTableSize()
++    // will allocate the requested capacity rather than doubling it.
++    bool manyRemoved = mRemovedCount >= (capacity() >> 2);
++    uint32_t newCapacity = manyRemoved ? rawCapacity() : rawCapacity() * 2;
+     return changeTableSize(newCapacity, aReportFailure);
+   }
+ 
+   void infallibleRehashIfOverloaded()
+   {
+     if (rehashIfOverloaded(DontReportFailure) == RehashFailed) {
+       rehashTableInPlace();
+     }

+ 43 - 0
frg/work-js/mozilla-release/patches/1483062-6-63a1.patch

@@ -0,0 +1,43 @@
+# HG changeset patch
+# User Nicholas Nethercote <nnethercote@mozilla.com>
+# Date 1534295473 -36000
+#      Wed Aug 15 11:11:13 2018 +1000
+# Node ID ca2edc3b4c1ab044694e836f3da6963c929bcf35
+# Parent  a3bf3a494b0b7c2817e3f6f3daa9cf4ec7624435
+Bug 1483062 - Merge HashTable::wouldBeUnderloaded() into underloaded(). r=luke
+
+diff --git a/mfbt/HashTable.h b/mfbt/HashTable.h
+--- a/mfbt/HashTable.h
++++ b/mfbt/HashTable.h
+@@ -1704,27 +1704,25 @@ private:
+                   "multiplication below could overflow");
+ 
+     // Note: if capacity() is zero, this will always succeed, which is
+     // what we want.
+     return mEntryCount + mRemovedCount >=
+            capacity() * sMaxAlphaNumerator / sAlphaDenominator;
+   }
+ 
+-  // Would the table be underloaded if it had the given capacity and entryCount?
+-  static bool wouldBeUnderloaded(uint32_t aCapacity, uint32_t aEntryCount)
++  // True if the current load is equal to or below the minimum.
++  bool underloaded()
+   {
+     static_assert(sMaxCapacity <= UINT32_MAX / sMinAlphaNumerator,
+                   "multiplication below could overflow");
+-    return aCapacity > sMinCapacity &&
+-           aEntryCount <= aCapacity * sMinAlphaNumerator / sAlphaDenominator;
++    return capacity() > sMinCapacity &&
++           mEntryCount <= capacity() * sMinAlphaNumerator / sAlphaDenominator;
+   }
+ 
+-  bool underloaded() { return wouldBeUnderloaded(capacity(), mEntryCount); }
+-
+   static MOZ_ALWAYS_INLINE bool match(Entry& aEntry, const Lookup& aLookup)
+   {
+     return HashPolicy::match(HashPolicy::getKey(aEntry.get()), aLookup);
+   }
+ 
+   enum LookupReason
+   {
+     ForNonAdd,

+ 104 - 0
frg/work-js/mozilla-release/patches/1483062-7-63a1.patch

@@ -0,0 +1,104 @@
+# HG changeset patch
+# User Nicholas Nethercote <nnethercote@mozilla.com>
+# Date 1534374617 -36000
+#      Thu Aug 16 09:10:17 2018 +1000
+# Node ID da46bfc2c089ad5e79bd9387850adc37240f26cb
+# Parent  ca2edc3b4c1ab044694e836f3da6963c929bcf35
+Bug 1483062 - Inline and remove HashTable::{over,under}loaded(). r=luke
+
+Because they each only have a single call site, and the "too many items
+removed?" test is already encapsulated within rehashIfOverloaded().
+
+diff --git a/mfbt/HashTable.h b/mfbt/HashTable.h
+--- a/mfbt/HashTable.h
++++ b/mfbt/HashTable.h
+@@ -1692,37 +1692,16 @@ private:
+   }
+ 
+   static HashNumber applyDoubleHash(HashNumber aHash1,
+                                     const DoubleHash& aDoubleHash)
+   {
+     return (aHash1 - aDoubleHash.mHash2) & aDoubleHash.mSizeMask;
+   }
+ 
+-  // True if the current load is equal to or exceeds the maximum.
+-  bool overloaded()
+-  {
+-    static_assert(sMaxCapacity <= UINT32_MAX / sMaxAlphaNumerator,
+-                  "multiplication below could overflow");
+-
+-    // Note: if capacity() is zero, this will always succeed, which is
+-    // what we want.
+-    return mEntryCount + mRemovedCount >=
+-           capacity() * sMaxAlphaNumerator / sAlphaDenominator;
+-  }
+-
+-  // True if the current load is equal to or below the minimum.
+-  bool underloaded()
+-  {
+-    static_assert(sMaxCapacity <= UINT32_MAX / sMinAlphaNumerator,
+-                  "multiplication below could overflow");
+-    return capacity() > sMinCapacity &&
+-           mEntryCount <= capacity() * sMinAlphaNumerator / sAlphaDenominator;
+-  }
+-
+   static MOZ_ALWAYS_INLINE bool match(Entry& aEntry, const Lookup& aLookup)
+   {
+     return HashPolicy::match(HashPolicy::getKey(aEntry.get()), aLookup);
+   }
+ 
+   enum LookupReason
+   {
+     ForNonAdd,
+@@ -1866,17 +1845,25 @@ private:
+     // All entries have been destroyed, no need to destroyTable.
+     this->free_(oldTable, oldCapacity);
+     return Rehashed;
+   }
+ 
+   RebuildStatus rehashIfOverloaded(
+     FailureBehavior aReportFailure = ReportFailure)
+   {
+-    if (!overloaded()) {
++    static_assert(sMaxCapacity <= UINT32_MAX / sMaxAlphaNumerator,
++                  "multiplication below could overflow");
++
++    // Note: if capacity() is zero, this will always succeed, which is
++    // what we want.
++    bool overloaded = mEntryCount + mRemovedCount >=
++                      capacity() * sMaxAlphaNumerator / sAlphaDenominator;
++
++    if (!overloaded) {
+       return NotOverloaded;
+     }
+ 
+     // Succeed if a quarter or more of all entries are removed. Note that this
+     // always succeeds if capacity() == 0 (i.e. entry storage has not been
+     // allocated), which is what we want, because it means changeTableSize()
+     // will allocate the requested capacity rather than doubling it.
+     bool manyRemoved = mRemovedCount >= (capacity() >> 2);
+@@ -1904,17 +1891,23 @@ private:
+     mEntryCount--;
+ #ifdef DEBUG
+     mMutationCount++;
+ #endif
+   }
+ 
+   void shrinkIfUnderloaded()
+   {
+-    if (underloaded()) {
++    static_assert(sMaxCapacity <= UINT32_MAX / sMinAlphaNumerator,
++                  "multiplication below could overflow");
++    bool underloaded =
++      capacity() > sMinCapacity &&
++      mEntryCount <= capacity() * sMinAlphaNumerator / sAlphaDenominator;
++
++    if (underloaded) {
+       (void)changeTableSize(capacity() / 2, DontReportFailure);
+     }
+   }
+ 
+   // This is identical to changeTableSize(currentSize), but without requiring
+   // a second table.  We do this by recycling the collision bits to tell us if
+   // the element is already inserted or still waiting to be inserted.  Since
+   // already-inserted elements win any conflicts, we get the same table as we

+ 59 - 0
frg/work-js/mozilla-release/patches/1483062-8-63a1.patch

@@ -0,0 +1,59 @@
+# HG changeset patch
+# User Nicholas Nethercote <nnethercote@mozilla.com>
+# Date 1534376744 -36000
+#      Thu Aug 16 09:45:44 2018 +1000
+# Node ID 17896e16e10b4bc4643a76b7f7ff625a64d0b216
+# Parent  da46bfc2c089ad5e79bd9387850adc37240f26cb
+Bug 1483062 - Trivial comment fixes. r=me
+
+diff --git a/mfbt/HashTable.h b/mfbt/HashTable.h
+--- a/mfbt/HashTable.h
++++ b/mfbt/HashTable.h
+@@ -284,21 +284,21 @@ public:
+   {
+     return mImpl.putNew(
+       aKey, std::forward<KeyInput>(aKey), std::forward<ValueInput>(aValue));
+   }
+ 
+   // Like putNew(), but should be only used when the table is known to be big
+   // enough for the insertion, and hashing cannot fail. Typically this is used
+   // to populate an empty map with known-unique keys after reserving space with
+-  // init(), e.g.
++  // reserve(), e.g.
+   //
+   //   using HM = HashMap<int,char>;
+   //   HM h;
+-  //   if (!h.init(3)) {
++  //   if (!h.reserve(3)) {
+   //     MOZ_CRASH("OOM");
+   //   }
+   //   h.putNewInfallible(1, 'a');    // unique key
+   //   h.putNewInfallible(2, 'b');    // unique key
+   //   h.putNewInfallible(3, 'c');    // unique key
+   //
+   template<typename KeyInput, typename ValueInput>
+   void putNewInfallible(KeyInput&& aKey, ValueInput&& aValue)
+@@ -598,21 +598,21 @@ public:
+   MOZ_MUST_USE bool putNew(const Lookup& aLookup, U&& aU)
+   {
+     return mImpl.putNew(aLookup, std::forward<U>(aU));
+   }
+ 
+   // Like putNew(), but should be only used when the table is known to be big
+   // enough for the insertion, and hashing cannot fail. Typically this is used
+   // to populate an empty set with known-unique elements after reserving space
+-  // with init(), e.g.
++  // with reserve(), e.g.
+   //
+   //   using HS = HashMap<int>;
+   //   HS h;
+-  //   if (!h.init(3)) {
++  //   if (!h.reserve(3)) {
+   //     MOZ_CRASH("OOM");
+   //   }
+   //   h.putNewInfallible(1);     // unique element
+   //   h.putNewInfallible(2);     // unique element
+   //   h.putNewInfallible(3);     // unique element
+   //
+   template<typename U>
+   void putNewInfallible(const Lookup& aLookup, U&& aU)

+ 307 - 0
frg/work-js/mozilla-release/patches/1483182-1-63a1.patch

@@ -0,0 +1,307 @@
+# HG changeset patch
+# User Nicholas Nethercote <nnethercote@mozilla.com>
+# Date 1534823357 -36000
+# Node ID 8116d3ee3a5a5564eb0aae5cd2cea501e728deb9
+# Parent  33c2e19cd74f32c65bfd048a9cc8e732ff631ca0
+Bug 1483182 - Don't allocate in HashTable::lookupOrAdd(). r=luke
+
+Currently lookupOrAdd() will allocate if the table has no storage. But it
+doesn't report an error if the allocation fails, which can cause problems.
+
+This patch changes things so that lookupOrAdd() doesn't allocate when the table
+has no storage. Instead, it returns an AddPtr that is not *valid* (its mTable
+is empty) but it is *live*, and can be used in add(), whereupon the allocation
+will occur.
+
+The patch also makes Ptr::isValid() and AddPtr::isValid() non-public, because
+the valid vs. live distinction is non-obvious and best kept hidden within the
+classes.
+
+diff --git a/js/src/ds/Bitmap.cpp b/js/src/ds/Bitmap.cpp
+--- a/js/src/ds/Bitmap.cpp
++++ b/js/src/ds/Bitmap.cpp
+@@ -23,17 +23,17 @@ SparseBitmap::sizeOfExcludingThis(mozill
+     for (Data::Range r(data.all()); !r.empty(); r.popFront())
+         size += mallocSizeOf(r.front().value());
+     return size;
+ }
+ 
+ SparseBitmap::BitBlock&
+ SparseBitmap::createBlock(Data::AddPtr p, size_t blockId, AutoEnterOOMUnsafeRegion& oomUnsafe)
+ {
+-    MOZ_ASSERT(!p && p.isValid());
++    MOZ_ASSERT(!p);
+     BitBlock* block = js_new<BitBlock>();
+     if (!block || !data.add(p, blockId, block))
+         oomUnsafe.crash("Bitmap OOM");
+     std::fill(block->begin(), block->end(), 0);
+     return *block;
+ }
+ 
+ bool
+diff --git a/js/src/jit-test/tests/basic/bug1483182.js b/js/src/jit-test/tests/basic/bug1483182.js
+new file mode 100644
+--- /dev/null
++++ b/js/src/jit-test/tests/basic/bug1483182.js
+@@ -0,0 +1,15 @@
++var lfLogBuffer = `
++  function testOuterForInVar() {
++    return eval("for (var x in {}); (function() { return delete x; })");
++  }
++  testOuterForInVar();
++`;
++loadFile(lfLogBuffer);
++loadFile(lfLogBuffer);
++function loadFile(lfVarx) {
++    try {
++        oomTest(function() {
++            eval(lfVarx);
++        });
++    } catch (lfVare) {}
++}
+diff --git a/js/src/jsapi-tests/testHashTable.cpp b/js/src/jsapi-tests/testHashTable.cpp
+--- a/js/src/jsapi-tests/testHashTable.cpp
++++ b/js/src/jsapi-tests/testHashTable.cpp
+@@ -443,18 +443,44 @@ BEGIN_TEST(testHashLazyStorage)
+ 
+     CHECK(set.putNew(1));
+     CHECK(set.capacity() == minCap);
+ 
+     set.clear();
+     set.compact();
+     CHECK(set.capacity() == 0);
+ 
+-    // lookupForAdd() instantiates, even if not followed by add().
+-    set.lookupForAdd(1);
++    auto p = set.lookupForAdd(1);
++    CHECK(set.capacity() == 0);
++    CHECK(set.add(p, 1));
++    CHECK(set.capacity() == minCap);
++    CHECK(set.has(1));
++
++    set.clear();
++    set.compact();
++    CHECK(set.capacity() == 0);
++
++    p = set.lookupForAdd(1);
++    CHECK(set.putNew(2));
++    CHECK(set.capacity() == minCap);
++    CHECK(set.relookupOrAdd(p, 1, 1));
++    CHECK(set.capacity() == minCap);
++    CHECK(set.has(1));
++
++    set.clear();
++    set.compact();
++    CHECK(set.capacity() == 0);
++
++    CHECK(set.putNew(1));
++    p = set.lookupForAdd(1);
++    set.clear();
++    set.compact();
++    CHECK(set.count() == 0);
++    CHECK(set.relookupOrAdd(p, 1, 1));
++    CHECK(set.count() == 1);
+     CHECK(set.capacity() == minCap);
+ 
+     set.clear();
+     set.compact();
+     CHECK(set.capacity() == 0);
+ 
+     CHECK(set.reserve(0));          // a no-op
+     CHECK(set.capacity() == 0);
+diff --git a/mfbt/HashTable.h b/mfbt/HashTable.h
+--- a/mfbt/HashTable.h
++++ b/mfbt/HashTable.h
+@@ -1204,28 +1204,38 @@ public:
+       : mEntry(&aEntry)
+ #ifdef DEBUG
+       , mTable(&aTable)
+       , mGeneration(aTable.generation())
+ #endif
+     {
+     }
+ 
++    // This constructor is used only by AddPtr() within lookupForAdd().
++    explicit Ptr(const HashTable& aTable)
++      : mEntry(nullptr)
++#ifdef DEBUG
++      , mTable(&aTable)
++      , mGeneration(aTable.generation())
++#endif
++    {
++    }
++
++    bool isValid() const { return !!mEntry; }
++
+   public:
+     Ptr()
+       : mEntry(nullptr)
+ #ifdef DEBUG
+       , mTable(nullptr)
+       , mGeneration(0)
+ #endif
+     {
+     }
+ 
+-    bool isValid() const { return !!mEntry; }
+-
+     bool found() const
+     {
+       if (!isValid()) {
+         return false;
+       }
+ #ifdef DEBUG
+       MOZ_ASSERT(mGeneration == mTable->generation());
+ #endif
+@@ -1281,16 +1291,31 @@ public:
+       : Ptr(aEntry, aTable)
+       , mKeyHash(aHashNumber)
+ #ifdef DEBUG
+       , mMutationCount(aTable.mMutationCount)
+ #endif
+     {
+     }
+ 
++    // This constructor is used when lookupForAdd() is performed on a table
++    // lacking entry storage; it leaves mEntry null but initializes everything
++    // else.
++    AddPtr(const HashTable& aTable, HashNumber aHashNumber)
++      : Ptr(aTable)
++      , mKeyHash(aHashNumber)
++#ifdef DEBUG
++      , mMutationCount(aTable.mMutationCount)
++#endif
++    {
++      MOZ_ASSERT(isLive());
++    }
++
++    bool isLive() const { return isLiveHash(mKeyHash); }
++
+   public:
+     AddPtr()
+       : mKeyHash(0)
+     {
+     }
+   };
+ 
+   // A hash table iterator that (mostly) doesn't allow table modifications.
+@@ -2102,59 +2127,66 @@ public:
+ 
+   MOZ_ALWAYS_INLINE AddPtr lookupForAdd(const Lookup& aLookup)
+   {
+     ReentrancyGuard g(*this);
+     if (!EnsureHash<HashPolicy>(aLookup)) {
+       return AddPtr();
+     }
+ 
++    HashNumber keyHash = prepareHash(aLookup);
++
+     if (!mTable) {
+-      uint32_t newCapacity = rawCapacity();
+-      RebuildStatus status = changeTableSize(newCapacity, ReportFailure);
+-      MOZ_ASSERT(status != NotOverloaded);
+-      if (status == RehashFailed) {
+-        return AddPtr();
+-      }
++      return AddPtr(*this, keyHash);
+     }
+ 
+-    HashNumber keyHash = prepareHash(aLookup);
+     // Directly call the constructor in the return statement to avoid
+     // excess copying when building with Visual Studio 2017.
+     // See bug 1385181.
+     return AddPtr(lookup<ForAdd>(aLookup, keyHash), *this, keyHash);
+   }
+ 
+   template<typename... Args>
+   MOZ_MUST_USE bool add(AddPtr& aPtr, Args&&... aArgs)
+   {
+     ReentrancyGuard g(*this);
+     MOZ_ASSERT_IF(aPtr.isValid(), mTable);
+     MOZ_ASSERT_IF(aPtr.isValid(), aPtr.mTable == this);
+     MOZ_ASSERT(!aPtr.found());
+     MOZ_ASSERT(!(aPtr.mKeyHash & sCollisionBit));
+ 
+     // Check for error from ensureHash() here.
+-    if (!aPtr.isValid()) {
++    if (!aPtr.isLive()) {
+       return false;
+     }
+ 
+     MOZ_ASSERT(aPtr.mGeneration == generation());
+ #ifdef DEBUG
+     MOZ_ASSERT(aPtr.mMutationCount == mMutationCount);
+ #endif
+ 
+-    // Changing an entry from removed to live does not affect whether we
+-    // are overloaded and can be handled separately.
+-    if (aPtr.mEntry->isRemoved()) {
++    if (!aPtr.isValid()) {
++      MOZ_ASSERT(!mTable && mEntryCount == 0);
++      uint32_t newCapacity = rawCapacity();
++      RebuildStatus status = changeTableSize(newCapacity, ReportFailure);
++      MOZ_ASSERT(status != NotOverloaded);
++      if (status == RehashFailed) {
++        return false;
++      }
++      aPtr.mEntry = &findNonLiveEntry(aPtr.mKeyHash);
++
++    } else if (aPtr.mEntry->isRemoved()) {
++      // Changing an entry from removed to live does not affect whether we are
++      // overloaded and can be handled separately.
+       if (!this->checkSimulatedOOM()) {
+         return false;
+       }
+       mRemovedCount--;
+       aPtr.mKeyHash |= sCollisionBit;
++
+     } else {
+       // Preserve the validity of |aPtr.mEntry|.
+       RebuildStatus status = rehashIfOverloaded();
+       if (status == RehashFailed) {
+         return false;
+       }
+       if (status == NotOverloaded && !this->checkSimulatedOOM()) {
+         return false;
+@@ -2205,30 +2237,37 @@ public:
+   // Note: |aLookup| may be a reference to a piece of |u|, so this function
+   // must take care not to use |aLookup| after moving |u|.
+   template<typename... Args>
+   MOZ_MUST_USE bool relookupOrAdd(AddPtr& aPtr,
+                                   const Lookup& aLookup,
+                                   Args&&... aArgs)
+   {
+     // Check for error from ensureHash() here.
+-    if (!aPtr.isValid()) {
++    if (!aPtr.isLive()) {
+       return false;
+     }
+ #ifdef DEBUG
+     aPtr.mGeneration = generation();
+     aPtr.mMutationCount = mMutationCount;
+ #endif
+-    {
++    if (mTable) {
+       ReentrancyGuard g(*this);
+       // Check that aLookup has not been destroyed.
+       MOZ_ASSERT(prepareHash(aLookup) == aPtr.mKeyHash);
+       aPtr.mEntry = &lookup<ForAdd>(aLookup, aPtr.mKeyHash);
++      if (aPtr.found()) {
++        return true;
++      }
++    } else {
++      // Clear aPtr so it's invalid; add() will allocate storage and redo the
++      // lookup.
++      aPtr.mEntry = nullptr;
+     }
+-    return aPtr.found() || add(aPtr, std::forward<Args>(aArgs)...);
++    return add(aPtr, std::forward<Args>(aArgs)...);
+   }
+ 
+   void remove(Ptr aPtr)
+   {
+     MOZ_ASSERT(mTable);
+     ReentrancyGuard g(*this);
+     MOZ_ASSERT(aPtr.found());
+     MOZ_ASSERT(aPtr.mGeneration == generation());
+

+ 32 - 0
frg/work-js/mozilla-release/patches/1483182-2-63a1.patch

@@ -0,0 +1,32 @@
+# HG changeset patch
+# User Nicholas Nethercote <nnethercote@mozilla.com>
+# Date 1534842440 -36000
+# Node ID c3bb26f985552814f9e35639a15acd10a15878bb
+# Parent  8116d3ee3a5a5564eb0aae5cd2cea501e728deb9
+Bug 1483182 - Do report OOM failures in HashTable::reserve(). r=luke
+
+This fixes a typo.
+
+diff --git a/mfbt/HashTable.h b/mfbt/HashTable.h
+--- a/mfbt/HashTable.h
++++ b/mfbt/HashTable.h
+@@ -2050,17 +2050,17 @@ public:
+       return true;
+     }
+ 
+     uint32_t bestCapacity = this->bestCapacity(aLen);
+     if (bestCapacity <= capacity()) {
+       return true;  // Capacity is already sufficient.
+     }
+ 
+-    RebuildStatus status = changeTableSize(bestCapacity, DontReportFailure);
++    RebuildStatus status = changeTableSize(bestCapacity, ReportFailure);
+     MOZ_ASSERT(status != NotOverloaded);
+     return status != RehashFailed;
+   }
+ 
+   Iterator iter() const
+   {
+     return Iterator(*this);
+   }
+

+ 0 - 0
frg/work-js/mozilla-release/patches/mozilla-central-push_431693.patch → frg/work-js/mozilla-release/patches/1483189-1-63a1.patch


+ 0 - 0
frg/work-js/mozilla-release/patches/mozilla-central-push_431694.patch → frg/work-js/mozilla-release/patches/1483189-2-63a1.patch


+ 0 - 0
frg/work-js/mozilla-release/patches/mozilla-central-push_431840.patch → frg/work-js/mozilla-release/patches/1483542-63a1.patch


+ 4 - 4
frg/work-js/mozilla-release/patches/1486577-6-63a1.patch

@@ -3,7 +3,7 @@
 # Date 1535162518 18000
 # Date 1535162518 18000
 #      Fri Aug 24 21:01:58 2018 -0500
 #      Fri Aug 24 21:01:58 2018 -0500
 # Node ID 2dc7007e3924444f55345606b6785f2d2ba89ce1
 # Node ID 2dc7007e3924444f55345606b6785f2d2ba89ce1
-# Parent  7a4d65c3360a3e3f17bdca0c9fa438927e4f5433
+# Parent  7f91a2f2b519a4f12e53b046a7400f00e7fc0c72
 Bug 1486577 - Don't #include js/SourceBufferHolder.h in jsapi.h, and instead require users to do so -- a minor translation-unit size improvement for anyone who never has to use SourceBufferHolder other than by reference.  r=jandem
 Bug 1486577 - Don't #include js/SourceBufferHolder.h in jsapi.h, and instead require users to do so -- a minor translation-unit size improvement for anyone who never has to use SourceBufferHolder other than by reference.  r=jandem
 
 
 diff --git a/dom/base/nsFrameMessageManager.cpp b/dom/base/nsFrameMessageManager.cpp
 diff --git a/dom/base/nsFrameMessageManager.cpp b/dom/base/nsFrameMessageManager.cpp
@@ -769,12 +769,12 @@ diff --git a/js/src/vm/JSScript.cpp b/js/src/vm/JSScript.cpp
 diff --git a/js/src/wasm/AsmJS.cpp b/js/src/wasm/AsmJS.cpp
 diff --git a/js/src/wasm/AsmJS.cpp b/js/src/wasm/AsmJS.cpp
 --- a/js/src/wasm/AsmJS.cpp
 --- a/js/src/wasm/AsmJS.cpp
 +++ b/js/src/wasm/AsmJS.cpp
 +++ b/js/src/wasm/AsmJS.cpp
-@@ -31,16 +31,17 @@
+@@ -30,16 +30,17 @@
+ #include "jsutil.h"
  
  
  #include "builtin/String.h"
  #include "builtin/String.h"
  #include "frontend/Parser.h"
  #include "frontend/Parser.h"
  #include "gc/Policy.h"
  #include "gc/Policy.h"
- #include "jit/AtomicOperations.h"
  #include "js/AutoByteString.h"
  #include "js/AutoByteString.h"
  #include "js/MemoryMetrics.h"
  #include "js/MemoryMetrics.h"
  #include "js/Printf.h"
  #include "js/Printf.h"
@@ -787,7 +787,7 @@ diff --git a/js/src/wasm/AsmJS.cpp b/js/src/wasm/AsmJS.cpp
  #include "vm/SelfHosting.h"
  #include "vm/SelfHosting.h"
  #include "vm/Time.h"
  #include "vm/Time.h"
  #include "vm/TypedArrayObject.h"
  #include "vm/TypedArrayObject.h"
-@@ -70,16 +71,17 @@ using mozilla::IsNegativeZero;
+@@ -69,16 +70,17 @@ using mozilla::IsNegativeZero;
  using mozilla::IsPositiveZero;
  using mozilla::IsPositiveZero;
  using mozilla::IsPowerOfTwo;
  using mozilla::IsPowerOfTwo;
  using mozilla::PodZero;
  using mozilla::PodZero;

File diff suppressed because it is too large
+ 243 - 180
frg/work-js/mozilla-release/patches/1488698-7-WIP-64a1.patch


+ 4 - 20
frg/work-js/mozilla-release/patches/1489698-5-65a1.patch

@@ -3,14 +3,14 @@
 # Date 1536361555 14400
 # Date 1536361555 14400
 #      Fri Sep 07 19:05:55 2018 -0400
 #      Fri Sep 07 19:05:55 2018 -0400
 # Node ID a17dfbac6b10ec140dc69ed3053662987eba25ef
 # Node ID a17dfbac6b10ec140dc69ed3053662987eba25ef
-# Parent  324aa81cd668c40ca676b62da95f950c57307ead
+# Parent  663093856d61cf7a5ff376cb3076d8ff74db0f46
 Bug 1489698 - Add moz.build for js/src/jit. r=jandem,froydnj
 Bug 1489698 - Add moz.build for js/src/jit. r=jandem,froydnj
 
 
 diff --git a/js/src/jit/moz.build b/js/src/jit/moz.build
 diff --git a/js/src/jit/moz.build b/js/src/jit/moz.build
 new file mode 100644
 new file mode 100644
 --- /dev/null
 --- /dev/null
 +++ b/js/src/jit/moz.build
 +++ b/js/src/jit/moz.build
-@@ -0,0 +1,261 @@
+@@ -0,0 +1,253 @@
 +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 +# vim: set filetype=python:
 +# vim: set filetype=python:
 +# This Source Code Form is subject to the terms of the Mozilla Public
 +# This Source Code Form is subject to the terms of the Mozilla Public
@@ -133,7 +133,6 @@ new file mode 100644
 +        'x86-shared/Assembler-x86-shared.cpp',
 +        'x86-shared/Assembler-x86-shared.cpp',
 +        'x86-shared/AssemblerBuffer-x86-shared.cpp',
 +        'x86-shared/AssemblerBuffer-x86-shared.cpp',
 +        'x86-shared/BaselineCompiler-x86-shared.cpp',
 +        'x86-shared/BaselineCompiler-x86-shared.cpp',
-+        'x86-shared/BaselineIC-x86-shared.cpp',
 +        'x86-shared/CodeGenerator-x86-shared.cpp',
 +        'x86-shared/CodeGenerator-x86-shared.cpp',
 +        'x86-shared/Lowering-x86-shared.cpp',
 +        'x86-shared/Lowering-x86-shared.cpp',
 +        'x86-shared/MacroAssembler-x86-shared-SIMD.cpp',
 +        'x86-shared/MacroAssembler-x86-shared-SIMD.cpp',
@@ -149,7 +148,6 @@ new file mode 100644
 +            'x64/Assembler-x64.cpp',
 +            'x64/Assembler-x64.cpp',
 +            'x64/Bailouts-x64.cpp',
 +            'x64/Bailouts-x64.cpp',
 +            'x64/BaselineCompiler-x64.cpp',
 +            'x64/BaselineCompiler-x64.cpp',
-+            'x64/BaselineIC-x64.cpp',
 +            'x64/CodeGenerator-x64.cpp',
 +            'x64/CodeGenerator-x64.cpp',
 +            'x64/Lowering-x64.cpp',
 +            'x64/Lowering-x64.cpp',
 +            'x64/MacroAssembler-x64.cpp',
 +            'x64/MacroAssembler-x64.cpp',
@@ -161,7 +159,6 @@ new file mode 100644
 +            'x86/Assembler-x86.cpp',
 +            'x86/Assembler-x86.cpp',
 +            'x86/Bailouts-x86.cpp',
 +            'x86/Bailouts-x86.cpp',
 +            'x86/BaselineCompiler-x86.cpp',
 +            'x86/BaselineCompiler-x86.cpp',
-+            'x86/BaselineIC-x86.cpp',
 +            'x86/CodeGenerator-x86.cpp',
 +            'x86/CodeGenerator-x86.cpp',
 +            'x86/Lowering-x86.cpp',
 +            'x86/Lowering-x86.cpp',
 +            'x86/MacroAssembler-x86.cpp',
 +            'x86/MacroAssembler-x86.cpp',
@@ -174,7 +171,6 @@ new file mode 100644
 +        'arm/Assembler-arm.cpp',
 +        'arm/Assembler-arm.cpp',
 +        'arm/Bailouts-arm.cpp',
 +        'arm/Bailouts-arm.cpp',
 +        'arm/BaselineCompiler-arm.cpp',
 +        'arm/BaselineCompiler-arm.cpp',
-+        'arm/BaselineIC-arm.cpp',
 +        'arm/CodeGenerator-arm.cpp',
 +        'arm/CodeGenerator-arm.cpp',
 +        'arm/disasm/Constants-arm.cpp',
 +        'arm/disasm/Constants-arm.cpp',
 +        'arm/disasm/Disasm-arm.cpp',
 +        'arm/disasm/Disasm-arm.cpp',
@@ -198,7 +194,6 @@ new file mode 100644
 +        'arm64/Architecture-arm64.cpp',
 +        'arm64/Architecture-arm64.cpp',
 +        'arm64/Assembler-arm64.cpp',
 +        'arm64/Assembler-arm64.cpp',
 +        'arm64/Bailouts-arm64.cpp',
 +        'arm64/Bailouts-arm64.cpp',
-+        'arm64/BaselineIC-arm64.cpp',
 +        'arm64/CodeGenerator-arm64.cpp',
 +        'arm64/CodeGenerator-arm64.cpp',
 +        'arm64/Disassembler-arm64.cpp',
 +        'arm64/Disassembler-arm64.cpp',
 +        'arm64/Lowering-arm64.cpp',
 +        'arm64/Lowering-arm64.cpp',
@@ -230,7 +225,6 @@ new file mode 100644
 +        'mips-shared/Assembler-mips-shared.cpp',
 +        'mips-shared/Assembler-mips-shared.cpp',
 +        'mips-shared/Bailouts-mips-shared.cpp',
 +        'mips-shared/Bailouts-mips-shared.cpp',
 +        'mips-shared/BaselineCompiler-mips-shared.cpp',
 +        'mips-shared/BaselineCompiler-mips-shared.cpp',
-+        'mips-shared/BaselineIC-mips-shared.cpp',
 +        'mips-shared/CodeGenerator-mips-shared.cpp',
 +        'mips-shared/CodeGenerator-mips-shared.cpp',
 +        'mips-shared/Lowering-mips-shared.cpp',
 +        'mips-shared/Lowering-mips-shared.cpp',
 +        'mips-shared/MacroAssembler-mips-shared.cpp',
 +        'mips-shared/MacroAssembler-mips-shared.cpp',
@@ -243,7 +237,6 @@ new file mode 100644
 +            'mips32/Assembler-mips32.cpp',
 +            'mips32/Assembler-mips32.cpp',
 +            'mips32/Bailouts-mips32.cpp',
 +            'mips32/Bailouts-mips32.cpp',
 +            'mips32/BaselineCompiler-mips32.cpp',
 +            'mips32/BaselineCompiler-mips32.cpp',
-+            'mips32/BaselineIC-mips32.cpp',
 +            'mips32/CodeGenerator-mips32.cpp',
 +            'mips32/CodeGenerator-mips32.cpp',
 +            'mips32/Lowering-mips32.cpp',
 +            'mips32/Lowering-mips32.cpp',
 +            'mips32/MacroAssembler-mips32.cpp',
 +            'mips32/MacroAssembler-mips32.cpp',
@@ -261,7 +254,6 @@ new file mode 100644
 +            'mips64/Assembler-mips64.cpp',
 +            'mips64/Assembler-mips64.cpp',
 +            'mips64/Bailouts-mips64.cpp',
 +            'mips64/Bailouts-mips64.cpp',
 +            'mips64/BaselineCompiler-mips64.cpp',
 +            'mips64/BaselineCompiler-mips64.cpp',
-+            'mips64/BaselineIC-mips64.cpp',
 +            'mips64/CodeGenerator-mips64.cpp',
 +            'mips64/CodeGenerator-mips64.cpp',
 +            'mips64/Lowering-mips64.cpp',
 +            'mips64/Lowering-mips64.cpp',
 +            'mips64/MacroAssembler-mips64.cpp',
 +            'mips64/MacroAssembler-mips64.cpp',
@@ -395,7 +387,7 @@ diff --git a/js/src/moz.build b/js/src/moz.build
      'perf/jsperf.cpp',
      'perf/jsperf.cpp',
      'proxy/BaseProxyHandler.cpp',
      'proxy/BaseProxyHandler.cpp',
      'proxy/CrossCompartmentWrapper.cpp',
      'proxy/CrossCompartmentWrapper.cpp',
-@@ -498,168 +412,16 @@ if CONFIG['MOZ_INSTRUMENTS']:
+@@ -498,160 +412,16 @@ if CONFIG['MOZ_INSTRUMENTS']:
  
  
  if CONFIG['ENABLE_TRACE_LOGGING']:
  if CONFIG['ENABLE_TRACE_LOGGING']:
      SOURCES += [
      SOURCES += [
@@ -416,7 +408,6 @@ diff --git a/js/src/moz.build b/js/src/moz.build
 -        'jit/x86-shared/Assembler-x86-shared.cpp',
 -        'jit/x86-shared/Assembler-x86-shared.cpp',
 -        'jit/x86-shared/AssemblerBuffer-x86-shared.cpp',
 -        'jit/x86-shared/AssemblerBuffer-x86-shared.cpp',
 -        'jit/x86-shared/BaselineCompiler-x86-shared.cpp',
 -        'jit/x86-shared/BaselineCompiler-x86-shared.cpp',
--        'jit/x86-shared/BaselineIC-x86-shared.cpp',
 -        'jit/x86-shared/CodeGenerator-x86-shared.cpp',
 -        'jit/x86-shared/CodeGenerator-x86-shared.cpp',
 -        'jit/x86-shared/Lowering-x86-shared.cpp',
 -        'jit/x86-shared/Lowering-x86-shared.cpp',
 -        'jit/x86-shared/MacroAssembler-x86-shared-SIMD.cpp',
 -        'jit/x86-shared/MacroAssembler-x86-shared-SIMD.cpp',
@@ -432,7 +423,6 @@ diff --git a/js/src/moz.build b/js/src/moz.build
 -            'jit/x64/Assembler-x64.cpp',
 -            'jit/x64/Assembler-x64.cpp',
 -            'jit/x64/Bailouts-x64.cpp',
 -            'jit/x64/Bailouts-x64.cpp',
 -            'jit/x64/BaselineCompiler-x64.cpp',
 -            'jit/x64/BaselineCompiler-x64.cpp',
--            'jit/x64/BaselineIC-x64.cpp',
 -            'jit/x64/CodeGenerator-x64.cpp',
 -            'jit/x64/CodeGenerator-x64.cpp',
 -            'jit/x64/Lowering-x64.cpp',
 -            'jit/x64/Lowering-x64.cpp',
 -            'jit/x64/MacroAssembler-x64.cpp',
 -            'jit/x64/MacroAssembler-x64.cpp',
@@ -444,7 +434,6 @@ diff --git a/js/src/moz.build b/js/src/moz.build
 -            'jit/x86/Assembler-x86.cpp',
 -            'jit/x86/Assembler-x86.cpp',
 -            'jit/x86/Bailouts-x86.cpp',
 -            'jit/x86/Bailouts-x86.cpp',
 -            'jit/x86/BaselineCompiler-x86.cpp',
 -            'jit/x86/BaselineCompiler-x86.cpp',
--            'jit/x86/BaselineIC-x86.cpp',
 -            'jit/x86/CodeGenerator-x86.cpp',
 -            'jit/x86/CodeGenerator-x86.cpp',
 -            'jit/x86/Lowering-x86.cpp',
 -            'jit/x86/Lowering-x86.cpp',
 -            'jit/x86/MacroAssembler-x86.cpp',
 -            'jit/x86/MacroAssembler-x86.cpp',
@@ -457,7 +446,6 @@ diff --git a/js/src/moz.build b/js/src/moz.build
 -        'jit/arm/Assembler-arm.cpp',
 -        'jit/arm/Assembler-arm.cpp',
 -        'jit/arm/Bailouts-arm.cpp',
 -        'jit/arm/Bailouts-arm.cpp',
 -        'jit/arm/BaselineCompiler-arm.cpp',
 -        'jit/arm/BaselineCompiler-arm.cpp',
--        'jit/arm/BaselineIC-arm.cpp',
 -        'jit/arm/CodeGenerator-arm.cpp',
 -        'jit/arm/CodeGenerator-arm.cpp',
 -        'jit/arm/disasm/Constants-arm.cpp',
 -        'jit/arm/disasm/Constants-arm.cpp',
 -        'jit/arm/disasm/Disasm-arm.cpp',
 -        'jit/arm/disasm/Disasm-arm.cpp',
@@ -481,7 +469,6 @@ diff --git a/js/src/moz.build b/js/src/moz.build
 -        'jit/arm64/Architecture-arm64.cpp',
 -        'jit/arm64/Architecture-arm64.cpp',
 -        'jit/arm64/Assembler-arm64.cpp',
 -        'jit/arm64/Assembler-arm64.cpp',
 -        'jit/arm64/Bailouts-arm64.cpp',
 -        'jit/arm64/Bailouts-arm64.cpp',
--        'jit/arm64/BaselineIC-arm64.cpp',
 -        'jit/arm64/CodeGenerator-arm64.cpp',
 -        'jit/arm64/CodeGenerator-arm64.cpp',
 -        'jit/arm64/Disassembler-arm64.cpp',
 -        'jit/arm64/Disassembler-arm64.cpp',
 -        'jit/arm64/Lowering-arm64.cpp',
 -        'jit/arm64/Lowering-arm64.cpp',
@@ -513,7 +500,6 @@ diff --git a/js/src/moz.build b/js/src/moz.build
 -        'jit/mips-shared/Assembler-mips-shared.cpp',
 -        'jit/mips-shared/Assembler-mips-shared.cpp',
 -        'jit/mips-shared/Bailouts-mips-shared.cpp',
 -        'jit/mips-shared/Bailouts-mips-shared.cpp',
 -        'jit/mips-shared/BaselineCompiler-mips-shared.cpp',
 -        'jit/mips-shared/BaselineCompiler-mips-shared.cpp',
--        'jit/mips-shared/BaselineIC-mips-shared.cpp',
 -        'jit/mips-shared/CodeGenerator-mips-shared.cpp',
 -        'jit/mips-shared/CodeGenerator-mips-shared.cpp',
 -        'jit/mips-shared/Lowering-mips-shared.cpp',
 -        'jit/mips-shared/Lowering-mips-shared.cpp',
 -        'jit/mips-shared/MacroAssembler-mips-shared.cpp',
 -        'jit/mips-shared/MacroAssembler-mips-shared.cpp',
@@ -526,7 +512,6 @@ diff --git a/js/src/moz.build b/js/src/moz.build
 -            'jit/mips32/Assembler-mips32.cpp',
 -            'jit/mips32/Assembler-mips32.cpp',
 -            'jit/mips32/Bailouts-mips32.cpp',
 -            'jit/mips32/Bailouts-mips32.cpp',
 -            'jit/mips32/BaselineCompiler-mips32.cpp',
 -            'jit/mips32/BaselineCompiler-mips32.cpp',
--            'jit/mips32/BaselineIC-mips32.cpp',
 -            'jit/mips32/CodeGenerator-mips32.cpp',
 -            'jit/mips32/CodeGenerator-mips32.cpp',
 -            'jit/mips32/Lowering-mips32.cpp',
 -            'jit/mips32/Lowering-mips32.cpp',
 -            'jit/mips32/MacroAssembler-mips32.cpp',
 -            'jit/mips32/MacroAssembler-mips32.cpp',
@@ -544,7 +529,6 @@ diff --git a/js/src/moz.build b/js/src/moz.build
 -            'jit/mips64/Assembler-mips64.cpp',
 -            'jit/mips64/Assembler-mips64.cpp',
 -            'jit/mips64/Bailouts-mips64.cpp',
 -            'jit/mips64/Bailouts-mips64.cpp',
 -            'jit/mips64/BaselineCompiler-mips64.cpp',
 -            'jit/mips64/BaselineCompiler-mips64.cpp',
--            'jit/mips64/BaselineIC-mips64.cpp',
 -            'jit/mips64/CodeGenerator-mips64.cpp',
 -            'jit/mips64/CodeGenerator-mips64.cpp',
 -            'jit/mips64/Lowering-mips64.cpp',
 -            'jit/mips64/Lowering-mips64.cpp',
 -            'jit/mips64/MacroAssembler-mips64.cpp',
 -            'jit/mips64/MacroAssembler-mips64.cpp',
@@ -564,7 +548,7 @@ diff --git a/js/src/moz.build b/js/src/moz.build
  else:
  else:
      UNIFIED_SOURCES += [
      UNIFIED_SOURCES += [
          'threading/posix/CpuCount.cpp',
          'threading/posix/CpuCount.cpp',
-@@ -701,16 +463,17 @@ GENERATED_FILES += ['frontend/ReservedWo
+@@ -693,16 +463,17 @@ GENERATED_FILES += ['frontend/ReservedWo
  ReservedWordsGenerated = GENERATED_FILES['frontend/ReservedWordsGenerated.h']
  ReservedWordsGenerated = GENERATED_FILES['frontend/ReservedWordsGenerated.h']
  ReservedWordsGenerated.script = 'frontend/GenerateReservedWords.py'
  ReservedWordsGenerated.script = 'frontend/GenerateReservedWords.py'
  ReservedWordsGenerated.inputs += [
  ReservedWordsGenerated.inputs += [

+ 56 - 56
frg/work-js/mozilla-release/patches/1494752-604.patch

@@ -3,7 +3,7 @@
 # Date 1541688097 18000
 # Date 1541688097 18000
 #      Thu Nov 08 09:41:37 2018 -0500
 #      Thu Nov 08 09:41:37 2018 -0500
 # Node ID c264774b89130cd7759c40977835e2a0d32fd684
 # Node ID c264774b89130cd7759c40977835e2a0d32fd684
-# Parent  204a016793307556609ea8dec84a41ecfc6bd54b
+# Parent  d9f53c74f5c1b5d0e47ff747685ed67b18e7d0e3
 Bug 1494752. r=jonco, a=RyanVM
 Bug 1494752. r=jonco, a=RyanVM
 
 
 diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp
 diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp
@@ -311,7 +311,7 @@ diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp
 diff --git a/js/src/vm/Scope.cpp b/js/src/vm/Scope.cpp
 diff --git a/js/src/vm/Scope.cpp b/js/src/vm/Scope.cpp
 --- a/js/src/vm/Scope.cpp
 --- a/js/src/vm/Scope.cpp
 +++ b/js/src/vm/Scope.cpp
 +++ b/js/src/vm/Scope.cpp
-@@ -210,17 +210,17 @@ NewEmptyScopeData(JSContext* cx, uint32_
+@@ -206,17 +206,17 @@ NewEmptyScopeData(JSContext* cx, uint32_
          new (data) typename ConcreteScope::Data(length);
          new (data) typename ConcreteScope::Data(length);
      return UniquePtr<typename ConcreteScope::Data>(data);
      return UniquePtr<typename ConcreteScope::Data>(data);
  }
  }
@@ -330,7 +330,7 @@ diff --git a/js/src/vm/Scope.cpp b/js/src/vm/Scope.cpp
  
  
      uint8_t flags = bindingName->flagsForXDR();
      uint8_t flags = bindingName->flagsForXDR();
      MOZ_ASSERT(((flags << HasAtomShift) >> HasAtomShift) == flags);
      MOZ_ASSERT(((flags << HasAtomShift) >> HasAtomShift) == flags);
-@@ -229,30 +229,31 @@ XDRBindingName(XDRState<XDR_ENCODE>* xdr
+@@ -225,30 +225,31 @@ XDRBindingName(XDRState<XDR_ENCODE>* xdr
  
  
      if (hasAtom)
      if (hasAtom)
          MOZ_TRY(XDRAtom(xdr, &atom));
          MOZ_TRY(XDRAtom(xdr, &atom));
@@ -364,7 +364,7 @@ diff --git a/js/src/vm/Scope.cpp b/js/src/vm/Scope.cpp
  static void
  static void
  DeleteScopeData(ConcreteScopeData* data)
  DeleteScopeData(ConcreteScopeData* data)
  {
  {
-@@ -276,28 +277,32 @@ Scope::XDRSizedBindingNames(XDRState<mod
+@@ -272,28 +273,32 @@ Scope::XDRSizedBindingNames(XDRState<mod
      MOZ_TRY(xdr->codeUint32(&length));
      MOZ_TRY(xdr->codeUint32(&length));
  
  
      if (mode == XDR_ENCODE) {
      if (mode == XDR_ENCODE) {
@@ -400,7 +400,7 @@ diff --git a/js/src/vm/Scope.cpp b/js/src/vm/Scope.cpp
  /* static */ Scope*
  /* static */ Scope*
  Scope::create(JSContext* cx, ScopeKind kind, HandleScope enclosing, HandleShape envShape)
  Scope::create(JSContext* cx, ScopeKind kind, HandleScope enclosing, HandleShape envShape)
  {
  {
-@@ -1227,16 +1232,31 @@ GenerateWasmName(JSContext* cx, const ch
+@@ -1190,16 +1195,31 @@ GenerateWasmName(JSContext* cx, const ch
      if (!sb.append(prefix))
      if (!sb.append(prefix))
          return nullptr;
          return nullptr;
      if (!NumberValueToStringBuffer(cx, Int32Value(index), sb))
      if (!NumberValueToStringBuffer(cx, Int32Value(index), sb))
@@ -429,61 +429,61 @@ diff --git a/js/src/vm/Scope.cpp b/js/src/vm/Scope.cpp
  {
  {
      // WasmInstanceScope::Data has GCManagedDeletePolicy because it contains a
      // WasmInstanceScope::Data has GCManagedDeletePolicy because it contains a
      // GCPtr. Destruction of |data| below may trigger calls into the GC.
      // GCPtr. Destruction of |data| below may trigger calls into the GC.
-     Rooted<WasmInstanceScope*> wasmInstanceScope(cx);
  
  
-     {
-@@ -1247,38 +1267,38 @@ WasmInstanceScope::create(JSContext* cx,
-         size_t globalsStart = namesCount;
-         size_t globalsCount = instance->instance().metadata().globals.length();
-         namesCount += globalsCount;
+     size_t namesCount = 0;
+     if (instance->instance().memory()) {
+@@ -1208,38 +1228,38 @@ WasmInstanceScope::create(JSContext* cx,
+     size_t globalsStart = namesCount;
+     size_t globalsCount = instance->instance().metadata().globals.length();
+     namesCount += globalsCount;
  
  
-         Rooted<UniquePtr<Data>> data(cx, NewEmptyScopeData<WasmInstanceScope>(cx, namesCount));
-         if (!data)
-             return nullptr;
+     Rooted<UniquePtr<Data>> data(cx, NewEmptyScopeData<WasmInstanceScope>(cx, namesCount));
+     if (!data)
+         return nullptr;
  
  
--        size_t nameIndex = 0;
--        RootedAtom name(cx);
-         if (instance->instance().memory()) {
--            name = GenerateWasmName(cx, "memory", /* index = */ 0);
--            if (!name)
-+            JSAtom* wasmName = GenerateWasmName(cx, "memory", /* index = */ 0);
-+            if (!wasmName) {
-                 return nullptr;
--            new (&data->trailingNames[nameIndex]) BindingName(name, false);
--            nameIndex++;
-+            }
+-    size_t nameIndex = 0;
+-    RootedAtom name(cx);
+     if (instance->instance().memory()) {
+-        name = GenerateWasmName(cx, "memory", /* index = */ 0);
+-        if (!name)
++        JSAtom* wasmName = GenerateWasmName(cx, "memory", /* index = */ 0);
++        if (!wasmName) {
+             return nullptr;
+-        new (&data->trailingNames[nameIndex]) BindingName(name, false);
+-        nameIndex++;
++        }
 +
 +
-+            InitializeNextTrailingName(data, wasmName);
-         }
-         for (size_t i = 0; i < globalsCount; i++) {
--            name = GenerateWasmName(cx, "global", i);
--            if (!name)
-+            JSAtom* wasmName = GenerateWasmName(cx, "global", i);
-+            if (!wasmName) {
-                 return nullptr;
--            new (&data->trailingNames[nameIndex]) BindingName(name, false);
--            nameIndex++;
-+            }
++        InitializeNextTrailingName(data, wasmName);
+     }
+     for (size_t i = 0; i < globalsCount; i++) {
+-        name = GenerateWasmName(cx, "global", i);
+-        if (!name)
++        JSAtom* wasmName = GenerateWasmName(cx, "global", i);
++        if (!wasmName) {
+             return nullptr;
+-        new (&data->trailingNames[nameIndex]) BindingName(name, false);
+-        nameIndex++;
++        }
 +
 +
-+            InitializeNextTrailingName(data, wasmName);
-         }
--        MOZ_ASSERT(nameIndex == namesCount);
++        InitializeNextTrailingName(data, wasmName);
+     }
+-    MOZ_ASSERT(nameIndex == namesCount);
 +
 +
-+        MOZ_ASSERT(data->length == namesCount);
++    MOZ_ASSERT(data->length == namesCount);
  
  
-         data->instance.init(instance);
-         data->memoriesStart = 0;
-         data->globalsStart = globalsStart;
--        data->length = namesCount;
+     data->instance.init(instance);
+     data->memoriesStart = 0;
+     data->globalsStart = globalsStart;
+-    data->length = namesCount;
  
  
-         Rooted<Scope*> enclosingScope(cx, &cx->global()->emptyGlobalScope());
+     Rooted<Scope*> enclosingScope(cx, &cx->global()->emptyGlobalScope());
  
  
-         Scope* scope = Scope::create(cx, ScopeKind::WasmInstance, enclosingScope, /* envShape = */ nullptr);
-         if (!scope)
-             return nullptr;
+     return Scope::create<WasmInstanceScope>(cx, ScopeKind::WasmInstance, enclosingScope,
+                                             /* envShape = */ nullptr, &data);
+ }
  
  
-         wasmInstanceScope = &scope->as<WasmInstanceScope>();
-@@ -1315,25 +1335,27 @@ WasmFunctionScope::create(JSContext* cx,
+ /* static */ Shape*
+@@ -1269,25 +1289,27 @@ WasmFunctionScope::create(JSContext* cx,
      if (!instance->instance().debug().debugGetLocalTypes(funcIndex, &locals, &argsLength))
      if (!instance->instance().debug().debugGetLocalTypes(funcIndex, &locals, &argsLength))
          return nullptr;
          return nullptr;
      uint32_t namesCount = locals.length();
      uint32_t namesCount = locals.length();
@@ -512,10 +512,10 @@ diff --git a/js/src/vm/Scope.cpp b/js/src/vm/Scope.cpp
 -        new (&data->trailingNames[i]) BindingName(name, false);
 -        new (&data->trailingNames[i]) BindingName(name, false);
 -    }
 -    }
  
  
-     Scope* scope = Scope::create(cx, ScopeKind::WasmFunction, enclosing, /* envShape = */ nullptr);
-     if (!scope)
-         return nullptr;
- 
-     wasmFunctionScope = &scope->as<WasmFunctionScope>();
-     wasmFunctionScope->initData(std::move(data.get()));
+     return Scope::create<WasmFunctionScope>(cx, ScopeKind::WasmFunction, enclosing,
+                                             /* envShape = */ nullptr, &data);
+ }
  
  
+ /* static */ Shape*
+ WasmFunctionScope::getEmptyEnvironmentShape(JSContext* cx)
+ {

+ 10 - 10
frg/work-js/mozilla-release/patches/1502886-1-65a1.patch

@@ -2,7 +2,7 @@
 # User Benjamin Bouvier <benj@benj.me>
 # User Benjamin Bouvier <benj@benj.me>
 # Date 1540835717 -3600
 # Date 1540835717 -3600
 # Node ID ab04d8c725fd0cbd61e6c32e4096ee4caa53d55c
 # Node ID ab04d8c725fd0cbd61e6c32e4096ee4caa53d55c
-# Parent  8d446a847e6a78f1343cd8851be248c3558bc9ec
+# Parent  9a55fd146ce411d70f73528d0f04032fbcaa8cbb
 Bug 1502886: Delete wasm breakpoints when the wasm instance's Zone is swept; r=jonco
 Bug 1502886: Delete wasm breakpoints when the wasm instance's Zone is swept; r=jonco
 
 
 diff --git a/js/src/gc/Zone.cpp b/js/src/gc/Zone.cpp
 diff --git a/js/src/gc/Zone.cpp b/js/src/gc/Zone.cpp
@@ -26,7 +26,7 @@ diff --git a/js/src/gc/Zone.cpp b/js/src/gc/Zone.cpp
  using namespace js;
  using namespace js;
  using namespace js::gc;
  using namespace js::gc;
  
  
-@@ -179,16 +180,28 @@ Zone::sweepBreakpoints(FreeOp* fop)
+@@ -174,16 +175,28 @@ Zone::sweepBreakpoints(FreeOp* fop)
  
  
                  bool dying = scriptGone || IsAboutToBeFinalized(&dbgobj);
                  bool dying = scriptGone || IsAboutToBeFinalized(&dbgobj);
                  MOZ_ASSERT_IF(!dying, !IsAboutToBeFinalized(&bp->getHandlerRef()));
                  MOZ_ASSERT_IF(!dying, !IsAboutToBeFinalized(&bp->getHandlerRef()));
@@ -86,7 +86,7 @@ diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp
  {
  {
      return debuggerLink.mNext;
      return debuggerLink.mNext;
  }
  }
-@@ -4137,18 +4139,18 @@ Debugger::removeDebuggeeGlobal(FreeOp* f
+@@ -4108,18 +4110,18 @@ Debugger::removeDebuggeeGlobal(FreeOp* f
          DebuggerFrame* frameobj = e.front().value();
          DebuggerFrame* frameobj = e.front().value();
          if (frame.global() == global) {
          if (frame.global() == global) {
              frameobj->freeFrameIterData(fop);
              frameobj->freeFrameIterData(fop);
@@ -107,7 +107,7 @@ diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp
      // The debuggee zone set is recomputed on demand. This avoids refcounting
      // The debuggee zone set is recomputed on demand. This avoids refcounting
      // and in practice we have relatively few debuggees that tend to all be in
      // and in practice we have relatively few debuggees that tend to all be in
      // the same zone. If after recomputing the debuggee zone set, this global's
      // the same zone. If after recomputing the debuggee zone set, this global's
-@@ -4174,16 +4176,18 @@ Debugger::removeDebuggeeGlobal(FreeOp* f
+@@ -4145,16 +4147,18 @@ Debugger::removeDebuggeeGlobal(FreeOp* f
            case BreakpointSite::Type::JS:
            case BreakpointSite::Type::JS:
              if (bp->site->asJS()->script->realm() == global->realm())
              if (bp->site->asJS()->script->realm() == global->realm())
                  bp->destroy(fop);
                  bp->destroy(fop);
@@ -126,7 +126,7 @@ diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp
      // metadata callback from this global's realm.
      // metadata callback from this global's realm.
      if (trackingAllocationSites)
      if (trackingAllocationSites)
          Debugger::removeAllocationsTracking(*global);
          Debugger::removeAllocationsTracking(*global);
-@@ -6710,31 +6714,37 @@ DebuggerScript_getBreakpoints(JSContext*
+@@ -6653,31 +6657,37 @@ DebuggerScript_getBreakpoints(JSContext*
  
  
  class DebuggerScriptClearBreakpointMatcher
  class DebuggerScriptClearBreakpointMatcher
  {
  {
@@ -169,7 +169,7 @@ diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp
 diff --git a/js/src/vm/Debugger.h b/js/src/vm/Debugger.h
 diff --git a/js/src/vm/Debugger.h b/js/src/vm/Debugger.h
 --- a/js/src/vm/Debugger.h
 --- a/js/src/vm/Debugger.h
 +++ b/js/src/vm/Debugger.h
 +++ b/js/src/vm/Debugger.h
-@@ -1639,28 +1639,28 @@ class BreakpointSite {
+@@ -1636,28 +1636,28 @@ class BreakpointSite {
      using BreakpointList =
      using BreakpointList =
          mozilla::DoublyLinkedList<js::Breakpoint,
          mozilla::DoublyLinkedList<js::Breakpoint,
                                    SiteLinkAccess<js::Breakpoint>>;
                                    SiteLinkAccess<js::Breakpoint>>;
@@ -199,7 +199,7 @@ diff --git a/js/src/vm/Debugger.h b/js/src/vm/Debugger.h
  
  
  /*
  /*
   * Each Breakpoint is a member of two linked lists: its debugger's list and its
   * Each Breakpoint is a member of two linked lists: its debugger's list and its
-@@ -1694,17 +1694,23 @@ class Breakpoint {
+@@ -1691,17 +1691,23 @@ class Breakpoint {
      /**
      /**
       * Link elements for each list this breakpoint can be in.
       * Link elements for each list this breakpoint can be in.
       */
       */
@@ -227,9 +227,9 @@ diff --git a/js/src/vm/Debugger.h b/js/src/vm/Debugger.h
 diff --git a/js/src/wasm/WasmDebug.cpp b/js/src/wasm/WasmDebug.cpp
 diff --git a/js/src/wasm/WasmDebug.cpp b/js/src/wasm/WasmDebug.cpp
 --- a/js/src/wasm/WasmDebug.cpp
 --- a/js/src/wasm/WasmDebug.cpp
 +++ b/js/src/wasm/WasmDebug.cpp
 +++ b/js/src/wasm/WasmDebug.cpp
-@@ -285,45 +285,47 @@ DebugState::destroyBreakpointSite(FreeOp
+@@ -275,45 +275,47 @@ void
+ DebugState::destroyBreakpointSite(FreeOp* fop, uint32_t offset)
  {
  {
-     MOZ_ASSERT(breakpointSites_.initialized());
      WasmBreakpointSiteMap::Ptr p = breakpointSites_.lookup(offset);
      WasmBreakpointSiteMap::Ptr p = breakpointSites_.lookup(offset);
      MOZ_ASSERT(p);
      MOZ_ASSERT(p);
      fop->delete_(p->value());
      fop->delete_(p->value());
@@ -243,7 +243,7 @@ diff --git a/js/src/wasm/WasmDebug.cpp b/js/src/wasm/WasmDebug.cpp
 +                               JSObject* handler)
 +                               JSObject* handler)
  {
  {
      MOZ_ASSERT(instance);
      MOZ_ASSERT(instance);
-     if (!breakpointSites_.initialized())
+     if (breakpointSites_.empty())
 -        return true;
 -        return true;
 +        return;
 +        return;
  
  

+ 318 - 0
frg/work-js/mozilla-release/patches/1503116-65a1.patch

@@ -0,0 +1,318 @@
+# HG changeset patch
+# User Matthew Gaudet <mgaudet@mozilla.com>
+# Date 1540938720 14400
+# Node ID 8c15b6ab74cd55e6b4a16954fedafe779bc39455
+# Parent  72e12afbc5182e6806bf87dbdcc0495343ced46a
+Bug 1503116: Templatize CacheIR IC attachment mechanism in Ion r=khyperia
+
+This also, circumstantially, cleans up an ugly bug in the attachment logic
+in the Binary and Compare IR generators where we would never update the
+IC state.
+
+Differential Revision: https://phabricator.services.mozilla.com/D10317
+
+diff --git a/js/src/jit/IonIC.cpp b/js/src/jit/IonIC.cpp
+--- a/js/src/jit/IonIC.cpp
++++ b/js/src/jit/IonIC.cpp
+@@ -335,37 +335,47 @@ IonSetPropertyIC::update(JSContext* cx, 
+ 
+         if (!attached && !isTemporarilyUnoptimizable)
+             ic->state().trackNotAttached();
+     }
+ 
+     return true;
+ }
+ 
++// This helper handles ICState updates/transitions while attaching CacheIR stubs.
++template<typename IRGenerator, typename IC, typename... Args>
++static void
++TryAttachIonStub(JSContext* cx, IC* ic, IonScript* ionScript, Args&&... args)
++{
++    if (ic->state().maybeTransition()) {
++        ic->discardStubs(cx->zone());
++    }
++
++    if (ic->state().canAttachStub()) {
++        RootedScript script(cx, ic->script());
++        bool attached = false;
++        IRGenerator gen(cx, script, ic->pc(), ic->state().mode(), std::forward<Args>(args)...);
++        if (gen.tryAttachStub()) {
++            ic->attachCacheIRStub(cx, gen.writerRef(), gen.cacheKind(), ionScript, &attached);
++        }
++        if (!attached) {
++            ic->state().trackNotAttached();
++        }
++    }
++}
++
+ /* static */ bool
+ IonGetNameIC::update(JSContext* cx, HandleScript outerScript, IonGetNameIC* ic,
+                      HandleObject envChain, MutableHandleValue res)
+ {
+     IonScript* ionScript = outerScript->ionScript();
+     jsbytecode* pc = ic->pc();
+     RootedPropertyName name(cx, ic->script()->getName(pc));
+ 
+-    if (ic->state().maybeTransition())
+-        ic->discardStubs(cx->zone());
+-
+-    if (ic->state().canAttachStub()) {
+-        bool attached = false;
+-        RootedScript script(cx, ic->script());
+-        GetNameIRGenerator gen(cx, script, pc, ic->state().mode(), envChain, name);
+-        if (gen.tryAttachStub())
+-            ic->attachCacheIRStub(cx, gen.writerRef(), gen.cacheKind(), ionScript, &attached);
+-
+-        if (!attached)
+-            ic->state().trackNotAttached();
+-    }
++    TryAttachIonStub<GetNameIRGenerator, IonGetNameIC>(cx, ic, ionScript, envChain, name);
+ 
+     RootedObject obj(cx);
+     RootedObject holder(cx);
+     Rooted<PropertyResult> prop(cx);
+     if (!LookupName(cx, name, envChain, &obj, &holder, &prop))
+         return false;
+ 
+     if (*GetNextPc(pc) == JSOP_TYPEOF) {
+@@ -385,137 +395,71 @@ IonGetNameIC::update(JSContext* cx, Hand
+ /* static */ JSObject*
+ IonBindNameIC::update(JSContext* cx, HandleScript outerScript, IonBindNameIC* ic,
+                       HandleObject envChain)
+ {
+     IonScript* ionScript = outerScript->ionScript();
+     jsbytecode* pc = ic->pc();
+     RootedPropertyName name(cx, ic->script()->getName(pc));
+ 
+-    if (ic->state().maybeTransition())
+-        ic->discardStubs(cx->zone());
+-
+-    if (ic->state().canAttachStub()) {
+-        bool attached = false;
+-        RootedScript script(cx, ic->script());
+-        BindNameIRGenerator gen(cx, script, pc, ic->state().mode(), envChain, name);
+-        if (gen.tryAttachStub())
+-            ic->attachCacheIRStub(cx, gen.writerRef(), gen.cacheKind(), ionScript, &attached);
+-
+-        if (!attached)
+-            ic->state().trackNotAttached();
+-    }
++    TryAttachIonStub<BindNameIRGenerator, IonBindNameIC>(cx, ic, ionScript, envChain, name);
+ 
+     RootedObject holder(cx);
+     if (!LookupNameUnqualified(cx, name, envChain, &holder))
+         return nullptr;
+ 
+     return holder;
+ }
+ 
+ /* static */ JSObject*
+ IonGetIteratorIC::update(JSContext* cx, HandleScript outerScript, IonGetIteratorIC* ic,
+                          HandleValue value)
+ {
+     IonScript* ionScript = outerScript->ionScript();
+ 
+-    if (ic->state().maybeTransition())
+-        ic->discardStubs(cx->zone());
+-
+-    if (ic->state().canAttachStub()) {
+-        bool attached = false;
+-        RootedScript script(cx, ic->script());
+-        GetIteratorIRGenerator gen(cx, script, ic->pc(), ic->state().mode(), value);
+-        if (gen.tryAttachStub())
+-            ic->attachCacheIRStub(cx, gen.writerRef(), gen.cacheKind(), ionScript, &attached);
+-
+-        if (!attached)
+-            ic->state().trackNotAttached();
+-    }
++    TryAttachIonStub<GetIteratorIRGenerator, IonGetIteratorIC>(cx, ic, ionScript, value);
+ 
+     return ValueToIterator(cx, value);
+ }
+ 
+ /* static */ bool
+ IonHasOwnIC::update(JSContext* cx, HandleScript outerScript, IonHasOwnIC* ic,
+                     HandleValue val, HandleValue idVal, int32_t* res)
+ {
+     IonScript* ionScript = outerScript->ionScript();
+ 
+-    if (ic->state().maybeTransition())
+-        ic->discardStubs(cx->zone());
+-
+-    jsbytecode* pc = ic->pc();
+-
+-    if (ic->state().canAttachStub()) {
+-        bool attached = false;
+-        RootedScript script(cx, ic->script());
+-        HasPropIRGenerator gen(cx, script, pc, CacheKind::HasOwn, ic->state().mode(), idVal, val);
+-        if (gen.tryAttachStub())
+-            ic->attachCacheIRStub(cx, gen.writerRef(), gen.cacheKind(), ionScript, &attached);
+-
+-        if (!attached)
+-            ic->state().trackNotAttached();
+-    }
++    TryAttachIonStub<HasPropIRGenerator, IonHasOwnIC>(cx, ic, ionScript,
++                                                      CacheKind::HasOwn, idVal, val);
+ 
+     bool found;
+     if (!HasOwnProperty(cx, val, idVal, &found))
+         return false;
+ 
+     *res = found;
+     return true;
+ }
+ 
+ /* static */ bool
+ IonInIC::update(JSContext* cx, HandleScript outerScript, IonInIC* ic,
+                 HandleValue key, HandleObject obj, bool* res)
+ {
+     IonScript* ionScript = outerScript->ionScript();
+-
+-    if (ic->state().maybeTransition())
+-        ic->discardStubs(cx->zone());
++    RootedValue objV(cx, ObjectValue(*obj));
+ 
+-    if (ic->state().canAttachStub()) {
+-        bool attached = false;
+-        RootedScript script(cx, ic->script());
+-        RootedValue objV(cx, ObjectValue(*obj));
+-        jsbytecode* pc = ic->pc();
+-        HasPropIRGenerator gen(cx, script, pc, CacheKind::In, ic->state().mode(), key, objV);
+-        if (gen.tryAttachStub())
+-            ic->attachCacheIRStub(cx, gen.writerRef(), gen.cacheKind(), ionScript, &attached);
+-
+-        if (!attached)
+-            ic->state().trackNotAttached();
+-    }
++    TryAttachIonStub<HasPropIRGenerator, IonInIC>(cx, ic, ionScript, CacheKind::In, key, objV);
+ 
+     return OperatorIn(cx, key, obj, res);
+ }
+ /* static */ bool
+ IonInstanceOfIC::update(JSContext* cx, HandleScript outerScript, IonInstanceOfIC* ic,
+                         HandleValue lhs, HandleObject rhs, bool* res)
+ {
+     IonScript* ionScript = outerScript->ionScript();
+ 
+-    if (ic->state().maybeTransition())
+-        ic->discardStubs(cx->zone());
+-
+-    if (ic->state().canAttachStub()) {
+-        bool attached = false;
+-        RootedScript script(cx, ic->script());
+-        jsbytecode* pc = ic->pc();
+-
+-        InstanceOfIRGenerator gen(cx, script, pc, ic->state().mode(),
+-                                  lhs, rhs);
+-
+-        if (gen.tryAttachStub())
+-            ic->attachCacheIRStub(cx, gen.writerRef(), gen.cacheKind(), ionScript, &attached);
+-
+-        if (!attached)
+-            ic->state().trackNotAttached();
+-    }
++    TryAttachIonStub<InstanceOfIRGenerator, IonInstanceOfIC>(cx, ic, ionScript, lhs, rhs);
+ 
+     return HasInstance(cx, rhs, lhs, res);
+ }
+ 
+ /*  static */  bool
+ IonUnaryArithIC::update(JSContext* cx, HandleScript outerScript, IonUnaryArithIC* ic,
+                         HandleValue val, MutableHandleValue res)
+ {
+@@ -538,29 +482,17 @@ IonUnaryArithIC::update(JSContext* cx, H
+         if (!NegOperation(cx, &valCopy, res))
+             return false;
+         break;
+       }
+       default:
+         MOZ_CRASH("Unexpected op");
+     }
+ 
+-    if (ic->state().maybeTransition())
+-        ic->discardStubs(cx->zone());
+-
+-    if (ic->state().canAttachStub()) {
+-        bool attached = false;
+-        UnaryArithIRGenerator gen(cx, script, pc, ic->state().mode(), op, val, res);
+-
+-        if (gen.tryAttachStub())
+-             ic->attachCacheIRStub(cx, gen.writerRef(), gen.cacheKind(), ionScript, &attached);
+-
+-        if (!attached)
+-            ic->state().trackNotAttached();
+-    }
++    TryAttachIonStub<UnaryArithIRGenerator, IonUnaryArithIC>(cx, ic, ionScript, op, val, res);
+ 
+     return true;
+ }
+ 
+ /* static */ bool
+ IonBinaryArithIC::update(JSContext* cx, HandleScript outerScript, IonBinaryArithIC* ic,
+                          HandleValue lhs, HandleValue rhs, MutableHandleValue ret)
+ {
+@@ -617,30 +549,19 @@ IonBinaryArithIC::update(JSContext* cx, 
+             return false;
+         ret.setInt32(result);
+         break;
+       }
+      default:
+         MOZ_CRASH("Unhandled binary arith op");
+     }
+ 
+-    if (ic->state().maybeTransition())
+-        ic->discardStubs(cx->zone());
++    TryAttachIonStub<BinaryArithIRGenerator, IonBinaryArithIC>(cx, ic, ionScript,
++                                                               op, lhs, rhs, ret);
+ 
+-    if (ic->state().canAttachStub()) {
+-        bool attached = false;
+-        BinaryArithIRGenerator gen(cx, script, pc, ic->state().mode(),
+-                                   op, lhs, rhs, ret);
+-        if (gen.tryAttachStub()) {
+-            ic->attachCacheIRStub(cx, gen.writerRef(), gen.cacheKind(), ionScript, &attached);
+-
+-            if (!attached)
+-                ic->state().trackNotAttached();
+-        }
+-    }
+     return true;
+ }
+ 
+ /* static */ bool
+ IonCompareIC::update(JSContext* cx, HandleScript outerScript, IonCompareIC* ic,
+                                     HandleValue lhs, HandleValue rhs, MutableHandleValue res)
+ {
+     IonScript* ionScript = outerScript->ionScript();
+@@ -694,30 +615,18 @@ IonCompareIC::update(JSContext* cx, Hand
+         break;
+       default:
+         MOZ_ASSERT_UNREACHABLE("Unhandled ion compare op");
+         return false;
+     }
+ 
+     res.setBoolean(out);
+ 
+-    if (ic->state().maybeTransition())
+-        ic->discardStubs(cx->zone());
++    TryAttachIonStub<CompareIRGenerator, IonCompareIC>(cx, ic, ionScript, op, lhs, rhs);
+ 
+-    if (ic->state().canAttachStub()) {
+-        bool attached = false;
+-        CompareIRGenerator gen(cx, script, pc, ic->state().mode(),
+-                               op, lhs, rhs);
+-        if (gen.tryAttachStub()) {
+-            ic->attachCacheIRStub(cx, gen.writerRef(), gen.cacheKind(), ionScript, &attached);
+-
+-            if (!attached)
+-                ic->state().trackNotAttached();
+-        }
+-    }
+     return true;
+ }
+ 
+ uint8_t*
+ IonICStub::stubDataStart()
+ {
+     return reinterpret_cast<uint8_t*>(this) + stubInfo_->stubDataOffset();
+ }

+ 15 - 15
frg/work-js/mozilla-release/patches/1557583-2-69a1.patch

@@ -2,7 +2,7 @@
 # User Mike Hommey <mh+mozilla@glandium.org>
 # User Mike Hommey <mh+mozilla@glandium.org>
 # Date 1560378646 0
 # Date 1560378646 0
 # Node ID f0f958b29d69ceaa0faa34955e98c63ecd94af7b
 # Node ID f0f958b29d69ceaa0faa34955e98c63ecd94af7b
-# Parent  48ca7ba2e8dc01d5de03db2d73645299923c232c
+# Parent  30182f5cfb966fc3b56b47d5c913f9c9cef0ce53
 Bug 1557583 - Add a --enable-frame-pointers option. r=chmanchester
 Bug 1557583 - Add a --enable-frame-pointers option. r=chmanchester
 
 
 We've been relying on frame pointers being indirectly enabled via things
 We've been relying on frame pointers being indirectly enabled via things
@@ -100,7 +100,7 @@ diff --git a/build/moz.configure/toolchain.configure b/build/moz.configure/toolc
      elif option:
      elif option:
          val = '1'
          val = '1'
      else:
      else:
-@@ -2286,8 +2286,56 @@ def ar_config(link, toolchain_prefix):
+@@ -2308,8 +2308,56 @@ def ar_config(link, toolchain_prefix):
      )
      )
  
  
  
  
@@ -160,7 +160,7 @@ diff --git a/build/moz.configure/toolchain.configure b/build/moz.configure/toolc
 diff --git a/js/moz.configure b/js/moz.configure
 diff --git a/js/moz.configure b/js/moz.configure
 --- a/js/moz.configure
 --- a/js/moz.configure
 +++ b/js/moz.configure
 +++ b/js/moz.configure
-@@ -234,16 +234,20 @@ js_option('--enable-profiling', env='MOZ
+@@ -268,16 +268,20 @@ js_option('--enable-profiling', env='MOZ
  
  
  @depends('--enable-profiling')
  @depends('--enable-profiling')
  def profiling(value):
  def profiling(value):
@@ -205,7 +205,7 @@ diff --git a/js/src/aclocal.m4 b/js/src/aclocal.m4
 diff --git a/js/src/old-configure.in b/js/src/old-configure.in
 diff --git a/js/src/old-configure.in b/js/src/old-configure.in
 --- a/js/src/old-configure.in
 --- a/js/src/old-configure.in
 +++ b/js/src/old-configure.in
 +++ b/js/src/old-configure.in
-@@ -1263,18 +1263,16 @@ dnl = Enable code optimization. ON by de
+@@ -1261,18 +1261,16 @@ dnl = Enable code optimization. ON by de
  dnl ========================================================
  dnl ========================================================
  
  
  # Use value from moz.configure if one is defined. Else use our computed
  # Use value from moz.configure if one is defined. Else use our computed
@@ -224,12 +224,12 @@ diff --git a/js/src/old-configure.in b/js/src/old-configure.in
      AC_TRY_COMPILE([#include <stdio.h>],
      AC_TRY_COMPILE([#include <stdio.h>],
          [printf("Hello World\n");],
          [printf("Hello World\n");],
          _results=yes,
          _results=yes,
-@@ -1282,17 +1280,16 @@ if test -n "$MOZ_OPTIMIZE"; then
-     AC_MSG_RESULT([$_results])
-     if test "$_results" = "no"; then
-         AC_MSG_ERROR([These compiler flags are invalid: $MOZ_OPTIMIZE_FLAGS])
+@@ -1291,17 +1289,16 @@ if test -n "$MOZ_OPTIMIZE"; then
+         *\ -Os\ *|*\ -Oz\ *)
+             MOZ_OPTIMIZE_LDFLAGS="$MOZ_OPTIMIZE_LDFLAGS -O2"
+             ;;
+         esac
      fi
      fi
-     CFLAGS=$_SAVE_CFLAGS
  fi
  fi
  fi # COMPILE_ENVIRONMENT
  fi # COMPILE_ENVIRONMENT
  
  
@@ -245,7 +245,7 @@ diff --git a/js/src/old-configure.in b/js/src/old-configure.in
 diff --git a/old-configure.in b/old-configure.in
 diff --git a/old-configure.in b/old-configure.in
 --- a/old-configure.in
 --- a/old-configure.in
 +++ b/old-configure.in
 +++ b/old-configure.in
-@@ -2686,18 +2686,16 @@ dnl = Enable code optimization. ON by de
+@@ -2359,18 +2359,16 @@ dnl = Enable code optimization. ON by de
  dnl ========================================================
  dnl ========================================================
  
  
  # Use value from moz.configure if one is defined. Else use our computed
  # Use value from moz.configure if one is defined. Else use our computed
@@ -264,12 +264,12 @@ diff --git a/old-configure.in b/old-configure.in
      AC_TRY_COMPILE([#include <stdio.h>],
      AC_TRY_COMPILE([#include <stdio.h>],
          [printf("Hello World\n");],
          [printf("Hello World\n");],
          _results=yes,
          _results=yes,
-@@ -2705,17 +2703,16 @@ if test -n "$MOZ_OPTIMIZE"; then
-     AC_MSG_RESULT([$_results])
-     if test "$_results" = "no"; then
-         AC_MSG_ERROR([These compiler flags for C are invalid: $MOZ_OPTIMIZE_FLAGS])
+@@ -2389,17 +2387,16 @@ if test -n "$MOZ_OPTIMIZE"; then
+         *\ -Os\ *|*\ -Oz\ *)
+             MOZ_OPTIMIZE_LDFLAGS="$MOZ_OPTIMIZE_LDFLAGS -O2"
+             ;;
+         esac
      fi
      fi
-     CFLAGS=$_SAVE_CFLAGS
  fi
  fi
  fi # COMPILE_ENVIRONMENT
  fi # COMPILE_ENVIRONMENT
  
  

+ 11 - 9
frg/work-js/mozilla-release/patches/1727374-914.patch

@@ -2,7 +2,7 @@
 # User Steve Fink <sfink@mozilla.com>
 # User Steve Fink <sfink@mozilla.com>
 # Date 1630609618 0
 # Date 1630609618 0
 # Node ID c250dd684d8e7e770d562bbb2c7bfac464dc6593
 # Node ID c250dd684d8e7e770d562bbb2c7bfac464dc6593
-# Parent  e857c8268e2fdafdc759ff09f1e2599dc2cffaa3
+# Parent  80757eab75050f28720c72e97c72a52de222ba83
 Bug 1727374 - Root Init dictionaries to fix rooting hazards. r=peterv, a=RyanVM
 Bug 1727374 - Root Init dictionaries to fix rooting hazards. r=peterv, a=RyanVM
 
 
 Differential Revision: https://phabricator.services.mozilla.com/D123633
 Differential Revision: https://phabricator.services.mozilla.com/D123633
@@ -10,7 +10,7 @@ Differential Revision: https://phabricator.services.mozilla.com/D123633
 diff --git a/dom/cache/Cache.cpp b/dom/cache/Cache.cpp
 diff --git a/dom/cache/Cache.cpp b/dom/cache/Cache.cpp
 --- a/dom/cache/Cache.cpp
 --- a/dom/cache/Cache.cpp
 +++ b/dom/cache/Cache.cpp
 +++ b/dom/cache/Cache.cpp
-@@ -347,18 +347,19 @@ Cache::Add(JSContext* aContext, const Re
+@@ -348,18 +348,19 @@ Cache::Add(JSContext* aContext, const Re
    if (!IsValidPutRequestMethod(aRequest, aRv)) {
    if (!IsValidPutRequestMethod(aRequest, aRv)) {
      return nullptr;
      return nullptr;
    }
    }
@@ -32,7 +32,7 @@ diff --git a/dom/cache/Cache.cpp b/dom/cache/Cache.cpp
    request->GetUrl(url);
    request->GetUrl(url);
    if (NS_WARN_IF(!IsValidPutRequestURL(url, aRv))) {
    if (NS_WARN_IF(!IsValidPutRequestURL(url, aRv))) {
      return nullptr;
      return nullptr;
-@@ -395,18 +396,19 @@ Cache::AddAll(JSContext* aContext,
+@@ -396,18 +397,19 @@ Cache::AddAll(JSContext* aContext,
          return nullptr;
          return nullptr;
        }
        }
      } else {
      } else {
@@ -54,7 +54,7 @@ diff --git a/dom/cache/Cache.cpp b/dom/cache/Cache.cpp
      request->GetUrl(url);
      request->GetUrl(url);
      if (NS_WARN_IF(!IsValidPutRequestURL(url, aRv))) {
      if (NS_WARN_IF(!IsValidPutRequestURL(url, aRv))) {
        return nullptr;
        return nullptr;
-@@ -631,18 +633,19 @@ Cache::AddAll(const GlobalObject& aGloba
+@@ -609,18 +611,19 @@ Cache::AddAll(const GlobalObject& aGloba
  
  
    // Begin fetching each request in parallel.  For now, if an error occurs just
    // Begin fetching each request in parallel.  For now, if an error occurs just
    // abandon our previous fetch calls.  In theory we could cancel them in the
    // abandon our previous fetch calls.  In theory we could cancel them in the
@@ -181,7 +181,7 @@ new file mode 100644
 diff --git a/dom/workers/ServiceWorkerPrivate.cpp b/dom/workers/ServiceWorkerPrivate.cpp
 diff --git a/dom/workers/ServiceWorkerPrivate.cpp b/dom/workers/ServiceWorkerPrivate.cpp
 --- a/dom/workers/ServiceWorkerPrivate.cpp
 --- a/dom/workers/ServiceWorkerPrivate.cpp
 +++ b/dom/workers/ServiceWorkerPrivate.cpp
 +++ b/dom/workers/ServiceWorkerPrivate.cpp
-@@ -932,17 +932,17 @@ public:
+@@ -933,17 +933,17 @@ public:
    WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
    WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
    {
    {
      MOZ_ASSERT(aWorkerPrivate);
      MOZ_ASSERT(aWorkerPrivate);
@@ -229,7 +229,7 @@ new file mode 100644
 diff --git a/js/src/wasm/WasmJS.cpp b/js/src/wasm/WasmJS.cpp
 diff --git a/js/src/wasm/WasmJS.cpp b/js/src/wasm/WasmJS.cpp
 --- a/js/src/wasm/WasmJS.cpp
 --- a/js/src/wasm/WasmJS.cpp
 +++ b/js/src/wasm/WasmJS.cpp
 +++ b/js/src/wasm/WasmJS.cpp
-@@ -1075,27 +1075,31 @@ WasmInstanceObject::create(JSContext* cx
+@@ -1075,28 +1075,33 @@ WasmInstanceObject::create(JSContext* cx
                             HandleWasmMemoryObject memory,
                             HandleWasmMemoryObject memory,
                             SharedTableVector&& tables,
                             SharedTableVector&& tables,
                             Handle<FunctionVector> funcImports,
                             Handle<FunctionVector> funcImports,
@@ -242,19 +242,20 @@ diff --git a/js/src/wasm/WasmJS.cpp b/js/src/wasm/WasmJS.cpp
 +    Rooted<UniquePtr<ExportMap>> exports(cx,
 +    Rooted<UniquePtr<ExportMap>> exports(cx,
 +                                         js::MakeUnique<ExportMap>());
 +                                         js::MakeUnique<ExportMap>());
 +
 +
-     if (!exports || !exports->init()) {
+     if (!exports) {
          ReportOutOfMemory(cx);
          ReportOutOfMemory(cx);
          return nullptr;
          return nullptr;
      }
      }
  
  
      UniquePtr<ScopeMap> scopes = js::MakeUnique<ScopeMap>(cx->zone());
      UniquePtr<ScopeMap> scopes = js::MakeUnique<ScopeMap>(cx->zone());
-     if (!scopes || !scopes->init()) {
+     if (!scopes) {
          ReportOutOfMemory(cx);
          ReportOutOfMemory(cx);
          return nullptr;
          return nullptr;
      }
      }
+ 
 +    // Note that `scopes` is a WeakCache, auto-linked into a sweep list on the
 +    // Note that `scopes` is a WeakCache, auto-linked into a sweep list on the
 +    // Zone, and so does not require rooting.
 +    // Zone, and so does not require rooting.
- 
++
      uint32_t indirectGlobals = 0;
      uint32_t indirectGlobals = 0;
  
  
      for (uint32_t i = 0; i < globalObjs.length(); i++) {
      for (uint32_t i = 0; i < globalObjs.length(); i++) {
@@ -262,3 +263,4 @@ diff --git a/js/src/wasm/WasmJS.cpp b/js/src/wasm/WasmJS.cpp
              indirectGlobals++;
              indirectGlobals++;
      }
      }
  
  
+     Rooted<UniquePtr<WasmGlobalObjectVector>> indirectGlobalObjs(cx,

+ 17 - 17
frg/work-js/mozilla-release/patches/TOP-NOBUG-REGEXP-04-1539690-68a1-25318.patch

@@ -1,13 +1,13 @@
 # HG changeset patch
 # HG changeset patch
 # User Dmitry Butskoy <buc@buc.me>
 # User Dmitry Butskoy <buc@buc.me>
 # Date 1690629350 -7200
 # Date 1690629350 -7200
-# Parent  4712114dedc61b09037bb4c4bb5ae72a82129f08
+# Parent  5313c076ea30304ba2d5815314b425996d795760
 No Bug - Import new regexp V8 engine. r=frg a=frg
 No Bug - Import new regexp V8 engine. r=frg a=frg
 
 
 diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp
 diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp
 --- a/dom/base/nsContentUtils.cpp
 --- a/dom/base/nsContentUtils.cpp
 +++ b/dom/base/nsContentUtils.cpp
 +++ b/dom/base/nsContentUtils.cpp
-@@ -7352,17 +7352,17 @@ nsContentUtils::IsPatternMatching(nsAStr
+@@ -7325,17 +7325,17 @@ nsContentUtils::IsPatternMatching(nsAStr
  
  
    // The pattern has to match the entire value.
    // The pattern has to match the entire value.
    aPattern.InsertLiteral(u"^(?:", 0);
    aPattern.InsertLiteral(u"^(?:", 0);
@@ -573,7 +573,7 @@ diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctio
  
  
  // If disableOOMFunctions is set, disable functionality that causes artificial
  // If disableOOMFunctions is set, disable functionality that causes artificial
  // OOM conditions.
  // OOM conditions.
-@@ -4765,17 +4768,17 @@ ParseRegExp(JSContext* cx, unsigned argc
+@@ -4760,17 +4763,17 @@ ParseRegExp(JSContext* cx, unsigned argc
          return false;
          return false;
      }
      }
  
  
@@ -592,7 +592,7 @@ diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctio
          RootedString flagStr(cx, args[1].toString());
          RootedString flagStr(cx, args[1].toString());
          if (!ParseRegExpFlags(cx, flagStr, &flags))
          if (!ParseRegExpFlags(cx, flagStr, &flags))
              return false;
              return false;
-@@ -4794,21 +4797,17 @@ ParseRegExp(JSContext* cx, unsigned argc
+@@ -4789,21 +4792,17 @@ ParseRegExp(JSContext* cx, unsigned argc
      if (!pattern)
      if (!pattern)
          return false;
          return false;
  
  
@@ -1162,7 +1162,7 @@ diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp
  #include "vm/RegExpStatics.h"
  #include "vm/RegExpStatics.h"
  #include "vm/StringType.h"
  #include "vm/StringType.h"
  #include "vm/TraceLogging.h"
  #include "vm/TraceLogging.h"
-@@ -1481,17 +1482,17 @@ PrepareAndExecuteRegExp(JSContext* cx, M
+@@ -1524,17 +1525,17 @@ PrepareAndExecuteRegExp(JSContext* cx, M
      masm.branchPtr(Assembler::Equal, temp1, ImmWord(0), failure);
      masm.branchPtr(Assembler::Equal, temp1, ImmWord(0), failure);
  
  
      // ES6 21.2.2.2 step 2.
      // ES6 21.2.2.2 step 2.
@@ -1675,7 +1675,7 @@ diff --git a/js/src/vm/RegExpObject.cpp b/js/src/vm/RegExpObject.cpp
      JitCodeTables tables;
      JitCodeTables tables;
      irregexp::RegExpCode code = irregexp::CompilePattern(cx, re, &data, input,
      irregexp::RegExpCode code = irregexp::CompilePattern(cx, re, &data, input,
                                                           false /* global() */,
                                                           false /* global() */,
-@@ -1312,17 +1318,17 @@ RegExpRealm::sweep()
+@@ -1303,17 +1309,17 @@ RegExpRealm::sweep()
      if (optimizableRegExpInstanceShape_ &&
      if (optimizableRegExpInstanceShape_ &&
          IsAboutToBeFinalized(&optimizableRegExpInstanceShape_))
          IsAboutToBeFinalized(&optimizableRegExpInstanceShape_))
      {
      {
@@ -1694,7 +1694,7 @@ diff --git a/js/src/vm/RegExpObject.cpp b/js/src/vm/RegExpObject.cpp
      auto shared = Allocate<RegExpShared>(cx);
      auto shared = Allocate<RegExpShared>(cx);
      if (!shared)
      if (!shared)
          return nullptr;
          return nullptr;
-@@ -1335,17 +1341,17 @@ RegExpZone::get(JSContext* cx, HandleAto
+@@ -1326,17 +1332,17 @@ RegExpZone::get(JSContext* cx, HandleAto
      }
      }
  
  
      return shared;
      return shared;
@@ -1713,7 +1713,7 @@ diff --git a/js/src/vm/RegExpObject.cpp b/js/src/vm/RegExpObject.cpp
  
  
  size_t
  size_t
  RegExpZone::sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf)
  RegExpZone::sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf)
-@@ -1379,58 +1385,57 @@ js::CloneRegExpObject(JSContext* cx, Han
+@@ -1370,58 +1376,57 @@ js::CloneRegExpObject(JSContext* cx, Han
      clone->initAndZeroLastIndex(shared->getSource(), shared->getFlags(), cx);
      clone->initAndZeroLastIndex(shared->getSource(), shared->getFlags(), cx);
      clone->setShared(*shared);
      clone->setShared(*shared);
  
  
@@ -1783,7 +1783,7 @@ diff --git a/js/src/vm/RegExpObject.cpp b/js/src/vm/RegExpObject.cpp
      size_t len = linear->length();
      size_t len = linear->length();
  
  
      bool ok;
      bool ok;
-@@ -1457,28 +1462,28 @@ js::ParseRegExpFlags(JSContext* cx, JSSt
+@@ -1448,28 +1453,28 @@ js::ParseRegExpFlags(JSContext* cx, JSSt
  
  
  template<XDRMode mode>
  template<XDRMode mode>
  XDRResult
  XDRResult
@@ -1816,7 +1816,7 @@ diff --git a/js/src/vm/RegExpObject.cpp b/js/src/vm/RegExpObject.cpp
      }
      }
      return Ok();
      return Ok();
  }
  }
-@@ -1512,37 +1517,37 @@ JS::ubi::Concrete<RegExpShared>::size(mo
+@@ -1503,37 +1508,37 @@ JS::ubi::Concrete<RegExpShared>::size(mo
      return js::gc::Arena::thingSize(gc::AllocKind::REGEXP_SHARED) +
      return js::gc::Arena::thingSize(gc::AllocKind::REGEXP_SHARED) +
          get().sizeOfExcludingThis(mallocSizeOf);
          get().sizeOfExcludingThis(mallocSizeOf);
  }
  }
@@ -1858,7 +1858,7 @@ diff --git a/js/src/vm/RegExpObject.cpp b/js/src/vm/RegExpObject.cpp
  {
  {
      AssertHeapIsIdle();
      AssertHeapIsIdle();
      CHECK_REQUEST(cx);
      CHECK_REQUEST(cx);
-@@ -1615,25 +1620,25 @@ JS::ObjectIsRegExp(JSContext* cx, Handle
+@@ -1606,25 +1611,25 @@ JS::ObjectIsRegExp(JSContext* cx, Handle
      ESClass cls;
      ESClass cls;
      if (!GetBuiltinClass(cx, obj, &cls))
      if (!GetBuiltinClass(cx, obj, &cls))
          return false;
          return false;
@@ -2206,13 +2206,13 @@ diff --git a/js/src/vm/RegExpShared.h b/js/src/vm/RegExpShared.h
       * that was not marked is deleted and removed from the set.
       * that was not marked is deleted and removed from the set.
       */
       */
      using Set = JS::WeakCache<JS::GCHashSet<ReadBarriered<RegExpShared*>, Key, ZoneAllocPolicy>>;
      using Set = JS::WeakCache<JS::GCHashSet<ReadBarriered<RegExpShared*>, Key, ZoneAllocPolicy>>;
-@@ -271,22 +248,22 @@ class RegExpZone
+@@ -269,22 +246,22 @@ class RegExpZone
+     explicit RegExpZone(Zone* zone);
+ 
      ~RegExpZone() {
      ~RegExpZone() {
-         MOZ_ASSERT_IF(set_.initialized(), set_.empty());
+         MOZ_ASSERT(set_.empty());
      }
      }
  
  
-     bool init();
- 
      bool empty() const { return set_.empty(); }
      bool empty() const { return set_.empty(); }
  
  
 -    RegExpShared* maybeGet(JSAtom* source, RegExpFlag flags) const {
 -    RegExpShared* maybeGet(JSAtom* source, RegExpFlag flags) const {
@@ -2336,7 +2336,7 @@ diff --git a/js/src/vm/StructuredClone.cpp b/js/src/vm/StructuredClone.cpp
  //
  //
  // Note that SCTAG_END_OF_KEYS is written into the serialized form and should have
  // Note that SCTAG_END_OF_KEYS is written into the serialized form and should have
  // a stable ID, it need not be at the end of the list and should not be used for
  // a stable ID, it need not be at the end of the list and should not be used for
-@@ -1591,17 +1595,17 @@ JSStructuredCloneWriter::startWrite(Hand
+@@ -1596,17 +1600,17 @@ JSStructuredCloneWriter::startWrite(Hand
          ESClass cls;
          ESClass cls;
          if (!GetBuiltinClass(context(), obj, &cls))
          if (!GetBuiltinClass(context(), obj, &cls))
              return false;
              return false;
@@ -2355,7 +2355,7 @@ diff --git a/js/src/vm/StructuredClone.cpp b/js/src/vm/StructuredClone.cpp
              return out.writePair(SCTAG_DATE_OBJECT, 0) && out.writeDouble(unboxed.toNumber());
              return out.writePair(SCTAG_DATE_OBJECT, 0) && out.writeDouble(unboxed.toNumber());
          } else if (JS_IsTypedArrayObject(obj)) {
          } else if (JS_IsTypedArrayObject(obj)) {
              return writeTypedArray(obj);
              return writeTypedArray(obj);
-@@ -2311,17 +2315,17 @@ JSStructuredCloneReader::startRead(Mutab
+@@ -2316,17 +2320,17 @@ JSStructuredCloneReader::startRead(Mutab
          JSObject* obj = NewDateObjectMsec(context(), t);
          JSObject* obj = NewDateObjectMsec(context(), t);
          if (!obj)
          if (!obj)
              return false;
              return false;

+ 3 - 3
frg/work-js/mozilla-release/patches/TOP-NOBUG-REGEXP-22-1637977-78a1-25318.patch

@@ -1,14 +1,14 @@
 # HG changeset patch
 # HG changeset patch
 # User Dmitry Butskoy <buc@buc.me>
 # User Dmitry Butskoy <buc@buc.me>
 # Date 1690630081 -7200
 # Date 1690630081 -7200
-# Parent  0c2ce41f45a123f6693d5fb495aa19d0ba8bef15
+# Parent  9c08d5538c08664bbbfb96d669b3ef8fd87a48cd
 No Bug - Import new regexp V8 engine. r=frg a=frg
 No Bug - Import new regexp V8 engine. r=frg a=frg
 
 
 diff --git a/js/src/vm/MutexIDs.h b/js/src/vm/MutexIDs.h
 diff --git a/js/src/vm/MutexIDs.h b/js/src/vm/MutexIDs.h
 --- a/js/src/vm/MutexIDs.h
 --- a/js/src/vm/MutexIDs.h
 +++ b/js/src/vm/MutexIDs.h
 +++ b/js/src/vm/MutexIDs.h
-@@ -52,16 +52,17 @@
-   _(WasmModuleTieringLock,       500) \
+@@ -51,16 +51,17 @@
+   _(WasmCodeProfilingLabels,     500) \
    _(WasmCompileTaskState,        500) \
    _(WasmCompileTaskState,        500) \
    _(WasmCodeStreamEnd,           500) \
    _(WasmCodeStreamEnd,           500) \
    _(WasmTailBytesPtr,            500) \
    _(WasmTailBytesPtr,            500) \

+ 7 - 7
frg/work-js/mozilla-release/patches/TOP-NOBUG-REGEXP-24-1631504-77a1-25318.patch

@@ -1,7 +1,7 @@
 # HG changeset patch
 # HG changeset patch
 # User Dmitry Butskoy <buc@buc.me>
 # User Dmitry Butskoy <buc@buc.me>
 # Date 1690630283 -7200
 # Date 1690630283 -7200
-# Parent  0fa4aa225d630d12d0b9df65251b7c69e87c90e0
+# Parent  ad28080178b2a8c2af366df6d8454f2a2ec4b1f0
 No Bug - Import new regexp V8 engine. r=frg a=frg
 No Bug - Import new regexp V8 engine. r=frg a=frg
 
 
 diff --git a/js/src/jit/JitOptions.cpp b/js/src/jit/JitOptions.cpp
 diff --git a/js/src/jit/JitOptions.cpp b/js/src/jit/JitOptions.cpp
@@ -30,7 +30,7 @@ diff --git a/js/src/jit/JitOptions.cpp b/js/src/jit/JitOptions.cpp
      // JSScript::hadFrequentBailouts and invalidate.
      // JSScript::hadFrequentBailouts and invalidate.
      SET_DEFAULT(frequentBailoutThreshold, 10);
      SET_DEFAULT(frequentBailoutThreshold, 10);
  
  
-@@ -269,16 +275,19 @@ DefaultJitOptions::enableGvn(bool enable
+@@ -266,16 +272,19 @@ DefaultJitOptions::enableGvn(bool enable
      disableGvn = !enable;
      disableGvn = !enable;
  }
  }
  
  
@@ -53,12 +53,12 @@ diff --git a/js/src/jit/JitOptions.cpp b/js/src/jit/JitOptions.cpp
 diff --git a/js/src/jit/JitOptions.h b/js/src/jit/JitOptions.h
 diff --git a/js/src/jit/JitOptions.h b/js/src/jit/JitOptions.h
 --- a/js/src/jit/JitOptions.h
 --- a/js/src/jit/JitOptions.h
 +++ b/js/src/jit/JitOptions.h
 +++ b/js/src/jit/JitOptions.h
-@@ -70,16 +70,19 @@ struct DefaultJitOptions
+@@ -69,16 +69,19 @@ struct DefaultJitOptions
+     bool eagerCompilation;
      bool forceInlineCaches;
      bool forceInlineCaches;
      bool fullDebugChecks;
      bool fullDebugChecks;
      bool limitScriptSize;
      bool limitScriptSize;
      bool osr;
      bool osr;
-     bool asmJSAtomicsEnable;
      bool wasmFoldOffsets;
      bool wasmFoldOffsets;
      bool wasmDelayTier2;
      bool wasmDelayTier2;
      uint32_t baselineWarmUpThreshold;
      uint32_t baselineWarmUpThreshold;
@@ -76,7 +76,7 @@ diff --git a/js/src/jit/JitOptions.h b/js/src/jit/JitOptions.h
 diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp
 diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp
 --- a/js/src/shell/js.cpp
 --- a/js/src/shell/js.cpp
 +++ b/js/src/shell/js.cpp
 +++ b/js/src/shell/js.cpp
-@@ -8425,16 +8425,23 @@ SetContextOptions(JSContext* cx, const O
+@@ -8895,16 +8895,23 @@ SetContextOptions(JSContext* cx, const O
      int32_t warmUpThreshold = op.getIntOption("ion-warmup-threshold");
      int32_t warmUpThreshold = op.getIntOption("ion-warmup-threshold");
      if (warmUpThreshold >= 0)
      if (warmUpThreshold >= 0)
          jit::JitOptions.setCompilerWarmUpThreshold(warmUpThreshold);
          jit::JitOptions.setCompilerWarmUpThreshold(warmUpThreshold);
@@ -100,7 +100,7 @@ diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp
          if (!jit::JitOptions.forcedRegisterAllocator.isSome())
          if (!jit::JitOptions.forcedRegisterAllocator.isSome())
              return OptionFailure("ion-regalloc", str);
              return OptionFailure("ion-regalloc", str);
      }
      }
-@@ -8786,16 +8793,23 @@ main(int argc, char** argv, char** envp)
+@@ -9263,16 +9270,23 @@ main(int argc, char** argv, char** envp)
          || !op.addBoolOption('\0', "test-wasm-await-tier2", "Forcibly activate tiering and block "
          || !op.addBoolOption('\0', "test-wasm-await-tier2", "Forcibly activate tiering and block "
                                     "instantiation on completion of tier2")
                                     "instantiation on completion of tier2")
  #ifdef ENABLE_WASM_GC
  #ifdef ENABLE_WASM_GC
@@ -127,7 +127,7 @@ diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp
 diff --git a/js/src/vm/RegExpObject.cpp b/js/src/vm/RegExpObject.cpp
 diff --git a/js/src/vm/RegExpObject.cpp b/js/src/vm/RegExpObject.cpp
 --- a/js/src/vm/RegExpObject.cpp
 --- a/js/src/vm/RegExpObject.cpp
 +++ b/js/src/vm/RegExpObject.cpp
 +++ b/js/src/vm/RegExpObject.cpp
-@@ -1167,17 +1167,17 @@ void RegExpShared::useAtomMatch(HandleAt
+@@ -1171,17 +1171,17 @@ void RegExpShared::useAtomMatch(HandleAt
    patternAtom_ = pattern;
    patternAtom_ = pattern;
    pairCount_ = 1;
    pairCount_ = 1;
  }
  }

+ 15 - 15
frg/work-js/mozilla-release/patches/TOP-NOBUG-REGEXP-37-1642493-79a1-25318.patch

@@ -1,7 +1,7 @@
 # HG changeset patch
 # HG changeset patch
 # User Dmitry Butskoy <buc@buc.me>
 # User Dmitry Butskoy <buc@buc.me>
 # Date 1690631112 -7200
 # Date 1690631112 -7200
-# Parent  a8aed28240017221b57d67704958f27e23cdf087
+# Parent  ef2337a25e6d3689bb30c8fc8ce4bad511872cba
 No Bug - Import new regexp V8 engine. r=frg a=frg
 No Bug - Import new regexp V8 engine. r=frg a=frg
 
 
 diff --git a/.clang-format-ignore b/.clang-format-ignore
 diff --git a/.clang-format-ignore b/.clang-format-ignore
@@ -230,7 +230,7 @@ diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctio
  #include "js/AutoByteString.h"
  #include "js/AutoByteString.h"
  #include "js/CompilationAndEvaluation.h"
  #include "js/CompilationAndEvaluation.h"
  #include "js/CompileOptions.h"
  #include "js/CompileOptions.h"
-@@ -4496,370 +4491,16 @@ GetModuleEnvironmentValue(JSContext* cx,
+@@ -4491,370 +4486,16 @@ GetModuleEnvironmentValue(JSContext* cx,
      if (args.rval().isMagic(JS_UNINITIALIZED_LEXICAL)) {
      if (args.rval().isMagic(JS_UNINITIALIZED_LEXICAL)) {
          ReportRuntimeLexicalError(cx, JSMSG_UNINITIALIZED_LEXICAL, id);
          ReportRuntimeLexicalError(cx, JSMSG_UNINITIALIZED_LEXICAL, id);
          return false;
          return false;
@@ -601,7 +601,7 @@ diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctio
  
  
      if (args.length() != 0) {
      if (args.length() != 0) {
          ReportUsageErrorASCII(cx, callee, "Wrong number of arguments");
          ReportUsageErrorASCII(cx, callee, "Wrong number of arguments");
-@@ -6038,26 +5679,16 @@ gc::ZealModeHelpText),
+@@ -6033,26 +5674,16 @@ gc::ZealModeHelpText),
  "    baselineCompile();  for (var i=0; i<1; i++) {} ...\n"
  "    baselineCompile();  for (var i=0; i<1; i++) {} ...\n"
  "  The interpreter will enter the new jitcode at the loop header unless\n"
  "  The interpreter will enter the new jitcode at the loop header unless\n"
  "  baselineCompile returned a string or threw an error.\n"),
  "  baselineCompile returned a string or threw an error.\n"),
@@ -23890,7 +23890,7 @@ diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp
  #include "vm/RegExpStatics.h"
  #include "vm/RegExpStatics.h"
  #include "vm/StringType.h"
  #include "vm/StringType.h"
  #include "vm/TraceLogging.h"
  #include "vm/TraceLogging.h"
-@@ -1521,18 +1516,16 @@ static void UpdateRegExpStatics(MacroAss
+@@ -1542,18 +1537,16 @@ static void UpdateRegExpStatics(MacroAss
                                     RegExpObject::PRIVATE_SLOT)),
                                     RegExpObject::PRIVATE_SLOT)),
                 temp1);
                 temp1);
    masm.loadPtr(Address(temp1, RegExpShared::offsetOfSource()), temp2);
    masm.loadPtr(Address(temp1, RegExpShared::offsetOfSource()), temp2);
@@ -23909,7 +23909,7 @@ diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp
                                      Register regexp, Register input,
                                      Register regexp, Register input,
                                      Register lastIndex, Register temp1,
                                      Register lastIndex, Register temp1,
                                      Register temp2, Register temp3,
                                      Register temp2, Register temp3,
-@@ -1732,216 +1725,16 @@ static bool PrepareAndExecuteRegExp(JSCo
+@@ -1753,216 +1746,16 @@ static bool PrepareAndExecuteRegExp(JSCo
    }
    }
    masm.movePtr(ImmPtr(res), temp1);
    masm.movePtr(ImmPtr(res), temp1);
    UpdateRegExpStatics(masm, regexp, input, lastIndex, temp1, temp2, temp3,
    UpdateRegExpStatics(masm, regexp, input, lastIndex, temp1, temp2, temp3,
@@ -24126,7 +24126,7 @@ diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp
  {
  {
      CharEncoding encoding_;
      CharEncoding encoding_;
      Register string_;
      Register string_;
-@@ -2258,27 +2051,25 @@ JitRealm::generateRegExpMatcherStub(JSCo
+@@ -2279,27 +2072,25 @@ JitRealm::generateRegExpMatcherStub(JSCo
      Label notFound, oolEntry;
      Label notFound, oolEntry;
      if (!PrepareAndExecuteRegExp(cx, masm, regexp, input, lastIndex,
      if (!PrepareAndExecuteRegExp(cx, masm, regexp, input, lastIndex,
                                   temp1, temp2, temp3, inputOutputDataStartOffset,
                                   temp1, temp2, temp3, inputOutputDataStartOffset,
@@ -24154,7 +24154,7 @@ diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp
      masm.bind(&matchResultJoin);
      masm.bind(&matchResultJoin);
  
  
      // Initialize slots of result object.
      // Initialize slots of result object.
-@@ -2293,21 +2084,19 @@ JitRealm::generateRegExpMatcherStub(JSCo
+@@ -2314,21 +2105,19 @@ JitRealm::generateRegExpMatcherStub(JSCo
                  
                  
      // Initialize the slots of the result object with the dummy values
      // Initialize the slots of the result object with the dummy values
      // defined in createMatchResultTemplateObject.
      // defined in createMatchResultTemplateObject.
@@ -24204,7 +24204,7 @@ diff --git a/js/src/jit/JitOptions.cpp b/js/src/jit/JitOptions.cpp
      // Number of bailouts without invalidation before we set
      // Number of bailouts without invalidation before we set
      // JSScript::hadFrequentBailouts and invalidate.
      // JSScript::hadFrequentBailouts and invalidate.
      SET_DEFAULT(frequentBailoutThreshold, 10);
      SET_DEFAULT(frequentBailoutThreshold, 10);
-@@ -275,19 +273,17 @@ DefaultJitOptions::enableGvn(bool enable
+@@ -272,19 +270,17 @@ DefaultJitOptions::enableGvn(bool enable
      disableGvn = !enable;
      disableGvn = !enable;
  }
  }
  
  
@@ -24227,12 +24227,12 @@ diff --git a/js/src/jit/JitOptions.cpp b/js/src/jit/JitOptions.cpp
 diff --git a/js/src/jit/JitOptions.h b/js/src/jit/JitOptions.h
 diff --git a/js/src/jit/JitOptions.h b/js/src/jit/JitOptions.h
 --- a/js/src/jit/JitOptions.h
 --- a/js/src/jit/JitOptions.h
 +++ b/js/src/jit/JitOptions.h
 +++ b/js/src/jit/JitOptions.h
-@@ -70,19 +70,17 @@ struct DefaultJitOptions
+@@ -69,19 +69,17 @@ struct DefaultJitOptions
+     bool eagerCompilation;
      bool forceInlineCaches;
      bool forceInlineCaches;
      bool fullDebugChecks;
      bool fullDebugChecks;
      bool limitScriptSize;
      bool limitScriptSize;
      bool osr;
      bool osr;
-     bool asmJSAtomicsEnable;
      bool wasmFoldOffsets;
      bool wasmFoldOffsets;
      bool wasmDelayTier2;
      bool wasmDelayTier2;
      uint32_t baselineWarmUpThreshold;
      uint32_t baselineWarmUpThreshold;
@@ -41925,7 +41925,7 @@ deleted file mode 100644
 diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp
 diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp
 --- a/js/src/shell/js.cpp
 --- a/js/src/shell/js.cpp
 +++ b/js/src/shell/js.cpp
 +++ b/js/src/shell/js.cpp
-@@ -8751,22 +8751,20 @@ SetContextOptions(JSContext* cx, const O
+@@ -8895,22 +8895,20 @@ SetContextOptions(JSContext* cx, const O
      int32_t warmUpThreshold = op.getIntOption("ion-warmup-threshold");
      int32_t warmUpThreshold = op.getIntOption("ion-warmup-threshold");
      if (warmUpThreshold >= 0)
      if (warmUpThreshold >= 0)
          jit::JitOptions.setCompilerWarmUpThreshold(warmUpThreshold);
          jit::JitOptions.setCompilerWarmUpThreshold(warmUpThreshold);
@@ -41948,7 +41948,7 @@ diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp
          jit::JitOptions.forcedRegisterAllocator = jit::LookupRegisterAllocator(str);
          jit::JitOptions.forcedRegisterAllocator = jit::LookupRegisterAllocator(str);
          if (!jit::JitOptions.forcedRegisterAllocator.isSome())
          if (!jit::JitOptions.forcedRegisterAllocator.isSome())
              return OptionFailure("ion-regalloc", str);
              return OptionFailure("ion-regalloc", str);
-@@ -9126,23 +9124,21 @@ main(int argc, char** argv, char** envp)
+@@ -9270,23 +9268,21 @@ main(int argc, char** argv, char** envp)
          || !op.addBoolOption('\0', "test-wasm-await-tier2", "Forcibly activate tiering and block "
          || !op.addBoolOption('\0', "test-wasm-await-tier2", "Forcibly activate tiering and block "
                                     "instantiation on completion of tier2")
                                     "instantiation on completion of tier2")
  #ifdef ENABLE_WASM_GC
  #ifdef ENABLE_WASM_GC
@@ -42053,7 +42053,7 @@ diff --git a/js/src/vm/JSContext.cpp b/js/src/vm/JSContext.cpp
      return true;
      return true;
  }
  }
  
  
-@@ -1384,19 +1374,17 @@ JSContext::~JSContext()
+@@ -1393,19 +1383,17 @@ JSContext::~JSContext()
  #endif
  #endif
  
  
  #ifdef JS_TRACE_LOGGING
  #ifdef JS_TRACE_LOGGING
@@ -42102,7 +42102,7 @@ diff --git a/js/src/vm/JSContext.h b/js/src/vm/JSContext.h
  struct DtoaState;
  struct DtoaState;
  
  
  namespace js {
  namespace js {
-@@ -378,23 +376,18 @@ struct JSContext : public JS::RootingCon
+@@ -403,23 +401,18 @@ struct JSContext : public JS::RootingCon
      mozilla::GenericErrorResult<JS::Error&> alreadyReportedError();
      mozilla::GenericErrorResult<JS::Error&> alreadyReportedError();
  
  
      /*
      /*
@@ -42933,7 +42933,7 @@ diff --git a/js/src/vm/RegExpObject.cpp b/js/src/vm/RegExpObject.cpp
      AddTypePropertyId(cx, templateObject, JSID_VOID, TypeSet::UndefinedType());
      AddTypePropertyId(cx, templateObject, JSID_VOID, TypeSet::UndefinedType());
  
  
      matchResultTemplateObject_.set(templateObject);
      matchResultTemplateObject_.set(templateObject);
-@@ -1940,23 +1341,18 @@ JS_PUBLIC_API(bool) JS::CheckRegExpSynta
+@@ -1931,23 +1332,18 @@ JS_PUBLIC_API(bool) JS::CheckRegExpSynta
                                           MutableHandleValue error) {
                                           MutableHandleValue error) {
    AssertHeapIsIdle();
    AssertHeapIsIdle();
    CHECK_REQUEST(cx);
    CHECK_REQUEST(cx);

+ 0 - 33
frg/work-js/mozilla-release/patches/mozilla-central-push_430283.patch

@@ -1,33 +0,0 @@
-# HG changeset patch
-# User Jan-Ivar Bruaroey <jib@mozilla.com>
-# Date 1533177977 14400
-#      Wed Aug 01 22:46:17 2018 -0400
-# Node ID 8f69423e522dc1e926b1d4d029945d6bf1ce36ab
-# Parent  a89f17d30427745d1755ad123babc2fbfde73a97
-Bug 1480306: Fix unused variable variable 'hasLineOfContext' in TokenStream.cpp. r=Waldo
-
-MozReview-Commit-ID: EK1IAvCZFwv
-
-diff --git a/js/src/frontend/TokenStream.cpp b/js/src/frontend/TokenStream.cpp
---- a/js/src/frontend/TokenStream.cpp
-+++ b/js/src/frontend/TokenStream.cpp
-@@ -621,17 +621,18 @@ TokenStreamChars<Utf8Unit, AnyCharsAcces
- 
-     do {
-         size_t offset = this->sourceUnits.offset();
- 
-         ErrorMetadata err;
- 
-         TokenStreamAnyChars& anyChars = anyCharsAccess();
- 
--        if (bool hasLineOfContext = anyChars.fillExcludingContext(&err, offset)) {
-+        bool hasLineOfContext = anyChars.fillExcludingContext(&err, offset);
-+        if (hasLineOfContext) {
-             if (!internalComputeLineOfContext(&err, offset))
-                 break;
- 
-             // As this is an encoding error, the computed window-end must be
-             // identical to the location of the error -- any further on and the
-             // window would contain invalid Unicode.
-             MOZ_ASSERT_IF(err.lineOfContext != nullptr,
-                           err.lineLength == err.tokenOffset);

+ 0 - 37
frg/work-js/mozilla-release/patches/mozilla-central-push_430518.patch

@@ -1,37 +0,0 @@
-# HG changeset patch
-# User Chris Peterson <cpeterson@mozilla.com>
-# Date 1532244105 25200
-#      Sun Jul 22 00:21:45 2018 -0700
-# Node ID d32128ee9a77e476503622c244761d17664b5fb9
-# Parent  8fae317831c1181b33603699455c71dfe58e51f6
-Bug 1481097 - wasm: Remove inline template workaround for gcc 4.8.5 bug. r=lth
-
-This gcc 4.8.5 workaround (from bug 1316850) is no longer needed because Firefox currently requires gcc 6.1 or later (as of bug 1444274).
-
-MozReview-Commit-ID: 4JFmOYoJnMH
-
-diff --git a/js/src/wasm/WasmBaselineCompile.cpp b/js/src/wasm/WasmBaselineCompile.cpp
---- a/js/src/wasm/WasmBaselineCompile.cpp
-+++ b/js/src/wasm/WasmBaselineCompile.cpp
-@@ -5877,20 +5877,17 @@ class BaseCompiler final : public BaseCo
-     MOZ_MUST_USE RegI32 maybeLoadTlsForAccess(const AccessCheck& check);
-     MOZ_MUST_USE RegI32 maybeLoadTlsForAccess(const AccessCheck& check, RegI32 specific);
-     MOZ_MUST_USE bool emitLoad(ValType type, Scalar::Type viewType);
-     MOZ_MUST_USE bool loadCommon(MemoryAccessDesc* access, ValType type);
-     MOZ_MUST_USE bool emitStore(ValType resultType, Scalar::Type viewType);
-     MOZ_MUST_USE bool storeCommon(MemoryAccessDesc* access, ValType resultType);
-     MOZ_MUST_USE bool emitSelect();
- 
--    // Mark these templates as inline to work around a compiler crash in
--    // gcc 4.8.5 when compiling for linux64-opt.
--
--    template<bool isSetLocal> MOZ_MUST_USE inline bool emitSetOrTeeLocal(uint32_t slot);
-+    template<bool isSetLocal> MOZ_MUST_USE bool emitSetOrTeeLocal(uint32_t slot);
- 
-     void endBlock(ExprType type);
-     void endLoop(ExprType type);
-     void endIfThen();
-     void endIfThenElse(ExprType type);
- 
-     void doReturn(ExprType returnType, bool popStack);
-     void pushReturnedIfNonVoid(const FunctionCall& call, ExprType type);

+ 0 - 352
frg/work-js/mozilla-release/patches/mozilla-central-push_430534.patch

@@ -1,352 +0,0 @@
-# HG changeset patch
-# User Matthew Gaudet <mgaudet@mozilla.com>
-# Date 1533686512 0
-#      Wed Aug 08 00:01:52 2018 +0000
-# Node ID dacdc94c62badd03b7e2ff0399d50b2d29f8a6ea
-# Parent  d602a2f69ff89abe965c77ff945c143e8014feb8
-Bug 1480493 - Remove initializer kind from JSOP_NEWINIT r=arai
-
-Differential Revision: https://phabricator.services.mozilla.com/D2675
-
-diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp
---- a/js/src/frontend/BytecodeEmitter.cpp
-+++ b/js/src/frontend/BytecodeEmitter.cpp
-@@ -1526,26 +1526,26 @@ BytecodeEmitter::reportExtraWarning(cons
- 
-     bool result = parser->errorReporter().reportExtraWarningErrorNumberVA(nullptr, offset, errorNumber, &args);
- 
-     va_end(args);
-     return result;
- }
- 
- bool
--BytecodeEmitter::emitNewInit(JSProtoKey key)
-+BytecodeEmitter::emitNewInit()
- {
-     const size_t len = 1 + UINT32_INDEX_LEN;
-     ptrdiff_t offset;
-     if (!emitCheck(len, &offset))
-         return false;
- 
-     jsbytecode* code = this->code(offset);
-     code[0] = JSOP_NEWINIT;
--    code[1] = jsbytecode(key);
-+    code[1] = 0;
-     code[2] = 0;
-     code[3] = 0;
-     code[4] = 0;
-     checkTypeSet(JSOP_NEWINIT);
-     updateDepth(offset);
-     return true;
- }
- 
-@@ -3542,17 +3542,17 @@ BytecodeEmitter::emitDestructuringOpsObj
-         // Duplicate the value being destructured to use as a reference base.
-         if (!emitDupAt(emitted))                                  // ... *SET RHS *LREF RHS
-             return false;
- 
-         if (member->isKind(ParseNodeKind::Spread)) {
-             if (!updateSourceCoordNotes(member->pn_pos.begin))
-                 return false;
- 
--            if (!emitNewInit(JSProto_Object))                     // ... *SET RHS *LREF RHS TARGET
-+            if (!emitNewInit())                                   // ... *SET RHS *LREF RHS TARGET
-                 return false;
-             if (!emit1(JSOP_DUP))                                 // ... *SET RHS *LREF RHS TARGET TARGET
-                 return false;
-             if (!emit2(JSOP_PICK, 2))                             // ... *SET RHS *LREF TARGET TARGET RHS
-                 return false;
- 
-             if (needsRestPropertyExcludedSet) {
-                 if (!emit2(JSOP_PICK, emitted + 4))               // ... RHS *LREF TARGET TARGET RHS SET
-@@ -3636,17 +3636,17 @@ BytecodeEmitter::emitDestructuringOpsObj
- bool
- BytecodeEmitter::emitDestructuringObjRestExclusionSet(ParseNode* pattern)
- {
-     MOZ_ASSERT(pattern->isKind(ParseNodeKind::Object));
-     MOZ_ASSERT(pattern->isArity(PN_LIST));
-     MOZ_ASSERT(pattern->last()->isKind(ParseNodeKind::Spread));
- 
-     ptrdiff_t offset = this->offset();
--    if (!emitNewInit(JSProto_Object))
-+    if (!emitNewInit())
-         return false;
- 
-     // Try to construct the shape of the object as we go, so we can emit a
-     // JSOP_NEWOBJECT with the final shape instead.
-     // In the case of computed property names and indices, we cannot fix the
-     // shape at bytecode compile time. When the shape cannot be determined,
-     // |obj| is nulled out.
- 
-@@ -7473,17 +7473,17 @@ BytecodeEmitter::emitObject(ParseNode* p
-         return emitSingletonInitialiser(pn);
- 
-     /*
-      * Emit code for {p:a, '%q':b, 2:c} that is equivalent to constructing
-      * a new object and defining (in source order) each property on the object
-      * (or mutating the object's [[Prototype]], in the case of __proto__).
-      */
-     ptrdiff_t offset = this->offset();
--    if (!emitNewInit(JSProto_Object))
-+    if (!emitNewInit())
-         return false;
- 
-     // Try to construct the shape of the object as we go, so we can emit a
-     // JSOP_NEWOBJECT with the final shape instead.
-     // In the case of computed property names and indices, we cannot fix the
-     // shape at bytecode compile time. When the shape cannot be determined,
-     // |obj| is nulled out.
- 
-@@ -8173,17 +8173,17 @@ BytecodeEmitter::emitClass(ParseNode* pn
-         if (!ifThenElse.emitEnd())
-             return false;
- 
-         if (!emit1(JSOP_OBJWITHPROTO))                          // ... HERITAGE HOMEOBJ
-             return false;
-         if (!emit1(JSOP_SWAP))                                  // ... HOMEOBJ HERITAGE
-             return false;
-     } else {
--        if (!emitNewInit(JSProto_Object))                       // ... HOMEOBJ
-+        if (!emitNewInit())                                     // ... HOMEOBJ
-             return false;
-     }
- 
-     // Stack currently has HOMEOBJ followed by optional HERITAGE. When HERITAGE
-     // is not used, an implicit value of %FunctionPrototype% is implied.
- 
-     if (constructor) {
-         if (!emitFunction(constructor, !!heritageExpression))   // ... HOMEOBJ CONSTRUCTOR
-diff --git a/js/src/frontend/BytecodeEmitter.h b/js/src/frontend/BytecodeEmitter.h
---- a/js/src/frontend/BytecodeEmitter.h
-+++ b/js/src/frontend/BytecodeEmitter.h
-@@ -633,17 +633,17 @@ struct MOZ_STACK_CLASS BytecodeEmitter
-     MOZ_MUST_USE bool emitTDZCheckIfNeeded(JSAtom* name, const NameLocation& loc);
- 
-     MOZ_MUST_USE bool emitNameIncDec(ParseNode* pn);
- 
-     MOZ_MUST_USE bool emitDeclarationList(ParseNode* decls);
-     MOZ_MUST_USE bool emitSingleDeclaration(ParseNode* decls, ParseNode* decl,
-                                             ParseNode* initializer);
- 
--    MOZ_MUST_USE bool emitNewInit(JSProtoKey key);
-+    MOZ_MUST_USE bool emitNewInit();
-     MOZ_MUST_USE bool emitSingletonInitialiser(ParseNode* pn);
- 
-     MOZ_MUST_USE bool emitPrepareIteratorResult();
-     MOZ_MUST_USE bool emitFinishIteratorResult(bool done);
-     MOZ_MUST_USE bool iteratorResultShape(unsigned* shape);
- 
-     MOZ_MUST_USE bool emitGetDotGeneratorInInnermostScope() {
-         return emitGetDotGeneratorInScope(*innermostEmitterScope());
-diff --git a/js/src/jit/BaselineCompiler.cpp b/js/src/jit/BaselineCompiler.cpp
---- a/js/src/jit/BaselineCompiler.cpp
-+++ b/js/src/jit/BaselineCompiler.cpp
-@@ -2162,36 +2162,20 @@ BaselineCompiler::emit_JSOP_NEWOBJECT()
-     frame.push(R0);
-     return true;
- }
- 
- bool
- BaselineCompiler::emit_JSOP_NEWINIT()
- {
-     frame.syncStack(0);
--    JSProtoKey key = JSProtoKey(GET_UINT8(pc));
--
--    if (key == JSProto_Array) {
--        // Pass length in R0.
--        masm.move32(Imm32(0), R0.scratchReg());
--
--        ObjectGroup* group = ObjectGroup::allocationSiteGroup(cx, script, pc, JSProto_Array);
--        if (!group)
--            return false;
--
--        ICNewArray_Fallback::Compiler stubCompiler(cx, group, ICStubCompiler::Engine::Baseline);
--        if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
--            return false;
--    } else {
--        MOZ_ASSERT(key == JSProto_Object);
--
--        ICNewObject_Fallback::Compiler stubCompiler(cx, ICStubCompiler::Engine::Baseline);
--        if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
--            return false;
--    }
-+
-+    ICNewObject_Fallback::Compiler stubCompiler(cx, ICStubCompiler::Engine::Baseline);
-+    if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
-+        return false;
- 
-     frame.push(R0);
-     return true;
- }
- 
- bool
- BaselineCompiler::emit_JSOP_INITELEM()
- {
-diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp
---- a/js/src/jit/CodeGenerator.cpp
-+++ b/js/src/jit/CodeGenerator.cpp
-@@ -2875,29 +2875,20 @@ CodeGenerator::visitNullarySharedStub(LN
-                    "the bytecode emitter must fail to compile code that would "
-                    "produce JSOP_NEWARRAY with a length exceeding int32_t range");
- 
-         // Pass length in R0.
-         masm.move32(Imm32(AssertedCast<int32_t>(length)), R0.scratchReg());
-         emitSharedStub(ICStub::Kind::NewArray_Fallback, lir);
-         break;
-       }
-+      case JSOP_NEWINIT:
-       case JSOP_NEWOBJECT:
-         emitSharedStub(ICStub::Kind::NewObject_Fallback, lir);
-         break;
--      case JSOP_NEWINIT: {
--        JSProtoKey key = JSProtoKey(GET_UINT8(pc));
--        if (key == JSProto_Array) {
--            masm.move32(Imm32(0), R0.scratchReg());
--            emitSharedStub(ICStub::Kind::NewArray_Fallback, lir);
--        } else {
--            emitSharedStub(ICStub::Kind::NewObject_Fallback, lir);
--        }
--        break;
--      }
-       default:
-         MOZ_CRASH("Unsupported jsop in shared stubs.");
-     }
- }
- 
- typedef JSFunction* (*MakeDefaultConstructorFn)(JSContext*, HandleScript,
-                                                 jsbytecode*, HandleObject);
- static const VMFunction MakeDefaultConstructorInfo =
-diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp
---- a/js/src/jit/IonBuilder.cpp
-+++ b/js/src/jit/IonBuilder.cpp
-@@ -2007,27 +2007,23 @@ IonBuilder::inspectOpcode(JSOp op)
-         for (uint32_t i = 0, n = GET_UINT16(pc); i < n; i++)
-             current->pop();
-         return Ok();
- 
-       case JSOP_DUPAT:
-         current->pushSlot(current->stackDepth() - 1 - GET_UINT24(pc));
-         return Ok();
- 
--      case JSOP_NEWINIT:
--        if (GET_UINT8(pc) == JSProto_Array)
--            return jsop_newarray(0);
--        return jsop_newobject();
--
-       case JSOP_NEWARRAY:
-         return jsop_newarray(GET_UINT32(pc));
- 
-       case JSOP_NEWARRAY_COPYONWRITE:
-         return jsop_newarray_copyonwrite();
- 
-+      case JSOP_NEWINIT:
-       case JSOP_NEWOBJECT:
-         return jsop_newobject();
- 
-       case JSOP_INITELEM:
-       case JSOP_INITHIDDENELEM:
-         return jsop_initelem();
- 
-       case JSOP_INITELEM_INC:
-diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp
---- a/js/src/vm/Interpreter.cpp
-+++ b/js/src/vm/Interpreter.cpp
-@@ -3901,24 +3901,17 @@ CASE(JSOP_INITHIDDENELEM_SETTER)
- END_CASE(JSOP_INITELEM_GETTER)
- 
- CASE(JSOP_HOLE)
-     PUSH_MAGIC(JS_ELEMENTS_HOLE);
- END_CASE(JSOP_HOLE)
- 
- CASE(JSOP_NEWINIT)
- {
--    uint8_t i = GET_UINT8(REGS.pc);
--    MOZ_ASSERT(i == JSProto_Array || i == JSProto_Object);
--
--    JSObject* obj;
--    if (i == JSProto_Array)
--        obj = NewArrayOperation(cx, script, REGS.pc, 0);
--    else
--        obj = NewObjectOperation(cx, script, REGS.pc);
-+    JSObject* obj = NewObjectOperation(cx, script, REGS.pc);
- 
-     if (!obj)
-         goto error;
-     PUSH_OBJECT(*obj);
- }
- END_CASE(JSOP_NEWINIT)
- 
- CASE(JSOP_NEWARRAY)
-@@ -5156,18 +5149,23 @@ js::NewObjectOperation(JSContext* cx, Ha
-         if (!group)
-             return nullptr;
- 
-         bool isUnboxed;
-         {
-             AutoSweepObjectGroup sweep(group);
-             if (group->maybePreliminaryObjects(sweep)) {
-                 group->maybePreliminaryObjects(sweep)->maybeAnalyze(cx, group);
--                if (group->maybeUnboxedLayout(sweep))
-+                if (group->maybeUnboxedLayout(sweep)) {
-+                    // This sets the allocation site so that the template object
-+                    // can be read back but if op is NEWINIT, then the template
-+                    // is null. 
-+                    MOZ_ASSERT(JSOp(*pc) != JSOP_NEWINIT);
-                     group->maybeUnboxedLayout(sweep)->setAllocationSite(script, pc);
-+                }
-             }
- 
-             if (group->shouldPreTenure(sweep) || group->maybePreliminaryObjects(sweep))
-                 newKind = TenuredObject;
-             isUnboxed = group->maybeUnboxedLayout(sweep);
-         }
-         if (isUnboxed)
-             return UnboxedPlainObject::create(cx, group, newKind);
-@@ -5175,17 +5173,16 @@ js::NewObjectOperation(JSContext* cx, Ha
- 
-     RootedPlainObject obj(cx);
- 
-     if (*pc == JSOP_NEWOBJECT) {
-         RootedPlainObject baseObject(cx, &script->getObject(pc)->as<PlainObject>());
-         obj = CopyInitializerObject(cx, baseObject, newKind);
-     } else {
-         MOZ_ASSERT(*pc == JSOP_NEWINIT);
--        MOZ_ASSERT(GET_UINT8(pc) == JSProto_Object);
-         obj = NewBuiltinClassInstance<PlainObject>(cx, newKind);
-     }
- 
-     if (!obj)
-         return nullptr;
- 
-     if (newKind == SingletonObject) {
-         if (!JSObject::setSingleton(cx, obj))
-diff --git a/js/src/vm/Opcodes.h b/js/src/vm/Opcodes.h
---- a/js/src/vm/Opcodes.h
-+++ b/js/src/vm/Opcodes.h
-@@ -835,24 +835,21 @@ 1234567890123456789012345678901234567890
-      *   Stack: => val
-      */ \
-     macro(JSOP_UINT16,    88, "uint16",     NULL,         3,  0,  1,  JOF_UINT16) \
-     \
-     /* Object and array literal support. */ \
-     /*
-      * Pushes newly created object onto the stack.
-      *
--     * This opcode takes the kind of initializer (JSProto_Array or
--     * JSProto_Object).
--     *
--     * This opcode has three extra bytes so it can be exchanged with
-+     * This opcode has four extra bytes so it can be exchanged with
-      * JSOP_NEWOBJECT during emit.
-      *   Category: Literals
-      *   Type: Object
--     *   Operands: uint8_t kind (, uint24_t extra)
-+     *   Operands: (uint32_t extra)
-      *   Stack: => obj
-      */ \
-     macro(JSOP_NEWINIT,   89, "newinit",    NULL,         5,  0,  1, JOF_UINT8) \
-     /*
-      * Pushes newly created array onto the stack.
-      *
-      * This opcode takes the final length, which is preallocated.
-      *   Category: Literals

+ 0 - 1589
frg/work-js/mozilla-release/patches/mozilla-central-push_430605.patch

@@ -1,1589 +0,0 @@
-# HG changeset patch
-# User Jon Coppeard <jcoppeard@mozilla.com>
-# Date 1533721203 -3600
-#      Wed Aug 08 10:40:03 2018 +0100
-# Node ID ba122021b8b576cf33a17c148a2e6c73d1d32862
-# Parent  08d651dba0f60e2028ce7a4b891e809ffb7ff16b
-Bug 1481196 - Compile module scripts to a JSScript like we do for classic scripts r=jandem r=baku
-
-diff --git a/dom/base/nsJSUtils.cpp b/dom/base/nsJSUtils.cpp
---- a/dom/base/nsJSUtils.cpp
-+++ b/dom/base/nsJSUtils.cpp
-@@ -468,92 +468,91 @@ nsJSUtils::ExecutionContext::ExtractRetu
-   return NS_OK;
- }
- 
- nsresult
- nsJSUtils::CompileModule(JSContext* aCx,
-                        JS::SourceBufferHolder& aSrcBuf,
-                        JS::Handle<JSObject*> aEvaluationGlobal,
-                        JS::CompileOptions &aCompileOptions,
--                       JS::MutableHandle<JSObject*> aModule)
-+                       JS::MutableHandle<JSScript*> aScript)
- {
-   AUTO_PROFILER_LABEL("nsJSUtils::CompileModule", JS);
- 
-   MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext());
-   MOZ_ASSERT(aSrcBuf.get());
-   MOZ_ASSERT(JS_IsGlobalObject(aEvaluationGlobal));
-   MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx) == aEvaluationGlobal);
-   MOZ_ASSERT(NS_IsMainThread());
-   MOZ_ASSERT(CycleCollectedJSContext::Get() &&
-              CycleCollectedJSContext::Get()->MicroTaskLevel());
- 
-   NS_ENSURE_TRUE(xpc::Scriptability::Get(aEvaluationGlobal).Allowed(), NS_OK);
- 
--  if (!JS::CompileModule(aCx, aCompileOptions, aSrcBuf, aModule)) {
-+  if (!JS::CompileModule(aCx, aCompileOptions, aSrcBuf, aScript)) {
-     return NS_ERROR_FAILURE;
-   }
- 
-   return NS_OK;
- }
- 
- nsresult
- nsJSUtils::InitModuleSourceElement(JSContext* aCx,
--                                   JS::Handle<JSObject*> aModule,
-+                                   JS::Handle<JSScript*> aScript,
-                                    nsIScriptElement* aElement)
- {
-   JS::Rooted<JS::Value> value(aCx);
-   nsresult rv = nsContentUtils::WrapNative(aCx, aElement, &value,
-                                            /* aAllowWrapping = */ true);
-   if (NS_FAILED(rv)) {
-     return rv;
-   }
- 
-   MOZ_ASSERT(value.isObject());
-   JS::Rooted<JSObject*> object(aCx, &value.toObject());
- 
--  JS::Rooted<JSScript*> script(aCx, JS::GetModuleScript(aModule));
--  if (!JS::InitScriptSourceElement(aCx, script, object, nullptr)) {
-+  if (!JS::InitScriptSourceElement(aCx, aScript, object, nullptr)) {
-     return NS_ERROR_FAILURE;
-   }
- 
-   return NS_OK;
- }
- 
- nsresult
--nsJSUtils::ModuleInstantiate(JSContext* aCx, JS::Handle<JSObject*> aModule)
-+nsJSUtils::ModuleInstantiate(JSContext* aCx, JS::Handle<JSScript*> aScript)
- {
-   AUTO_PROFILER_LABEL("nsJSUtils::ModuleInstantiate", JS);
- 
-   MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext());
-   MOZ_ASSERT(NS_IsMainThread());
-   MOZ_ASSERT(CycleCollectedJSContext::Get() &&
-              CycleCollectedJSContext::Get()->MicroTaskLevel());
- 
--  NS_ENSURE_TRUE(xpc::Scriptability::Get(aModule).Allowed(), NS_OK);
-+  NS_ENSURE_TRUE(xpc::Scriptability::Get(aScript).Allowed(), NS_OK);
- 
--  if (!JS::ModuleInstantiate(aCx, aModule)) {
-+  if (!JS::ModuleInstantiate(aCx, aScript)) {
-     return NS_ERROR_FAILURE;
-   }
- 
-   return NS_OK;
- }
- 
- nsresult
--nsJSUtils::ModuleEvaluate(JSContext* aCx, JS::Handle<JSObject*> aModule)
-+nsJSUtils::ModuleEvaluate(JSContext* aCx, JS::Handle<JSScript*> aScript)
- {
-   AUTO_PROFILER_LABEL("nsJSUtils::ModuleEvaluate", JS);
- 
-   MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext());
-   MOZ_ASSERT(NS_IsMainThread());
-   MOZ_ASSERT(CycleCollectedJSContext::Get() &&
-              CycleCollectedJSContext::Get()->MicroTaskLevel());
- 
--  NS_ENSURE_TRUE(xpc::Scriptability::Get(aModule).Allowed(), NS_OK);
-+  NS_ENSURE_TRUE(xpc::Scriptability::Get(aScript).Allowed(), NS_OK);
- 
--  if (!JS::ModuleEvaluate(aCx, aModule)) {
-+  if (!JS::ModuleEvaluate(aCx, aScript)) {
-     return NS_ERROR_FAILURE;
-   }
- 
-   return NS_OK;
- }
- 
- static bool
- AddScopeChainItem(JSContext* aCx,
-diff --git a/dom/base/nsJSUtils.h b/dom/base/nsJSUtils.h
---- a/dom/base/nsJSUtils.h
-+++ b/dom/base/nsJSUtils.h
-@@ -184,27 +184,27 @@ public:
-                                  const uint8_t* aBuf, size_t aLength,
-                                  JS::MutableHandle<JSScript*> aScript);
-   };
- 
-   static nsresult CompileModule(JSContext* aCx,
-                                 JS::SourceBufferHolder& aSrcBuf,
-                                 JS::Handle<JSObject*> aEvaluationGlobal,
-                                 JS::CompileOptions &aCompileOptions,
--                                JS::MutableHandle<JSObject*> aModule);
-+                                JS::MutableHandle<JSScript*> aScript);
- 
-   static nsresult InitModuleSourceElement(JSContext* aCx,
--                                          JS::Handle<JSObject*> aModule,
-+                                          JS::Handle<JSScript*> aScript,
-                                           nsIScriptElement* aElement);
- 
-   static nsresult ModuleInstantiate(JSContext* aCx,
--                                    JS::Handle<JSObject*> aModule);
-+                                    JS::Handle<JSScript*> aScript);
- 
-   static nsresult ModuleEvaluate(JSContext* aCx,
--                                 JS::Handle<JSObject*> aModule);
-+                                 JS::Handle<JSScript*> aScript);
- 
-   // Returns false if an exception got thrown on aCx.  Passing a null
-   // aElement is allowed; that wil produce an empty aScopeChain.
-   static bool GetScopeChainForElement(JSContext* aCx,
-                                       mozilla::dom::Element* aElement,
-                                       JS::AutoObjectVector& aScopeChain);
- 
-   // Returns a scope chain suitable for XBL execution.
-diff --git a/dom/script/ModuleScript.cpp b/dom/script/ModuleScript.cpp
---- a/dom/script/ModuleScript.cpp
-+++ b/dom/script/ModuleScript.cpp
-@@ -16,108 +16,108 @@ namespace dom {
- NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ModuleScript)
- NS_INTERFACE_MAP_END
- 
- NS_IMPL_CYCLE_COLLECTION_CLASS(ModuleScript)
- 
- NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ModuleScript)
-   NS_IMPL_CYCLE_COLLECTION_UNLINK(mLoader)
-   NS_IMPL_CYCLE_COLLECTION_UNLINK(mBaseURL)
--  tmp->UnlinkModuleRecord();
-+  tmp->UnlinkScript();
-   tmp->mParseError.setUndefined();
-   tmp->mErrorToRethrow.setUndefined();
- NS_IMPL_CYCLE_COLLECTION_UNLINK_END
- 
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(ModuleScript)
-   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLoader)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
- 
- NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(ModuleScript)
--  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mModuleRecord)
-+  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mScript)
-   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mParseError)
-   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mErrorToRethrow)
- NS_IMPL_CYCLE_COLLECTION_TRACE_END
- 
- NS_IMPL_CYCLE_COLLECTING_ADDREF(ModuleScript)
- NS_IMPL_CYCLE_COLLECTING_RELEASE(ModuleScript)
- 
- ModuleScript::ModuleScript(ScriptLoader* aLoader, nsIURI* aBaseURL)
-  : mLoader(aLoader),
-    mBaseURL(aBaseURL),
-    mSourceElementAssociated(false)
- {
-   MOZ_ASSERT(mLoader);
-   MOZ_ASSERT(mBaseURL);
--  MOZ_ASSERT(!mModuleRecord);
-+  MOZ_ASSERT(!mScript);
-   MOZ_ASSERT(!HasParseError());
-   MOZ_ASSERT(!HasErrorToRethrow());
- }
- 
- void
--ModuleScript::UnlinkModuleRecord()
-+ModuleScript::UnlinkScript()
- {
-   // Remove module's back reference to this object request if present.
--  if (mModuleRecord) {
--    MOZ_ASSERT(JS::GetModuleHostDefinedField(mModuleRecord).toPrivate() ==
-+  if (mScript) {
-+    MOZ_ASSERT(JS::GetModuleHostDefinedField(mScript).toPrivate() ==
-                this);
--    JS::SetModuleHostDefinedField(mModuleRecord, JS::UndefinedValue());
--    mModuleRecord = nullptr;
-+    JS::SetModuleHostDefinedField(mScript, JS::UndefinedValue());
-+    mScript = nullptr;
-   }
- }
- 
- ModuleScript::~ModuleScript()
- {
-   // The object may be destroyed without being unlinked first.
--  UnlinkModuleRecord();
-+  UnlinkScript();
-   DropJSObjects(this);
- }
- 
- void
--ModuleScript::SetModuleRecord(JS::Handle<JSObject*> aModuleRecord)
-+ModuleScript::SetScript(JS::Handle<JSScript*> aScript)
- {
--  MOZ_ASSERT(!mModuleRecord);
-+  MOZ_ASSERT(!mScript);
-   MOZ_ASSERT(!HasParseError());
-   MOZ_ASSERT(!HasErrorToRethrow());
- 
--  mModuleRecord = aModuleRecord;
-+  mScript = aScript;
- 
-   // Make module's host defined field point to this module script object.
--  // This is cleared in the UnlinkModuleRecord().
--  JS::SetModuleHostDefinedField(mModuleRecord, JS::PrivateValue(this));
-+  // This is cleared in the UnlinkScript().
-+  JS::SetModuleHostDefinedField(mScript, JS::PrivateValue(this));
-   HoldJSObjects(this);
- }
- 
- void
- ModuleScript::SetParseError(const JS::Value& aError)
- {
-   MOZ_ASSERT(!aError.isUndefined());
-   MOZ_ASSERT(!HasParseError());
-   MOZ_ASSERT(!HasErrorToRethrow());
- 
--  UnlinkModuleRecord();
-+  UnlinkScript();
-   mParseError = aError;
-   HoldJSObjects(this);
- }
- 
- void
- ModuleScript::SetErrorToRethrow(const JS::Value& aError)
- {
-   MOZ_ASSERT(!aError.isUndefined());
-   MOZ_ASSERT(!HasErrorToRethrow());
- 
--  // This is only called after SetModuleRecord() or SetParseError() so we don't
-+  // This is only called after SetScript() or SetParseError() so we don't
-   // need to call HoldJSObjects() here.
--  MOZ_ASSERT(mModuleRecord || HasParseError());
-+  MOZ_ASSERT(mScript || HasParseError());
- 
-   mErrorToRethrow = aError;
- }
- 
- void
- ModuleScript::SetSourceElementAssociated()
- {
--  MOZ_ASSERT(mModuleRecord);
-+  MOZ_ASSERT(mScript);
-   MOZ_ASSERT(!mSourceElementAssociated);
- 
-   mSourceElementAssociated = true;
- }
- 
- } // dom namespace
- } // mozilla namespace
-diff --git a/dom/script/ModuleScript.h b/dom/script/ModuleScript.h
---- a/dom/script/ModuleScript.h
-+++ b/dom/script/ModuleScript.h
-@@ -17,43 +17,43 @@ namespace mozilla {
- namespace dom {
- 
- class ScriptLoader;
- 
- class ModuleScript final : public nsISupports
- {
-   RefPtr<ScriptLoader> mLoader;
-   nsCOMPtr<nsIURI> mBaseURL;
--  JS::Heap<JSObject*> mModuleRecord;
-+  JS::Heap<JSScript*> mScript;
-   JS::Heap<JS::Value> mParseError;
-   JS::Heap<JS::Value> mErrorToRethrow;
-   bool mSourceElementAssociated;
- 
-   ~ModuleScript();
- 
- public:
-   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ModuleScript)
- 
-   ModuleScript(ScriptLoader* aLoader,
-                nsIURI* aBaseURL);
- 
--  void SetModuleRecord(JS::Handle<JSObject*> aModuleRecord);
-+  void SetScript(JS::Handle<JSScript*> aScript);
-   void SetParseError(const JS::Value& aError);
-   void SetErrorToRethrow(const JS::Value& aError);
-   void SetSourceElementAssociated();
- 
-   ScriptLoader* Loader() const { return mLoader; }
--  JSObject* ModuleRecord() const { return mModuleRecord; }
-+  JSScript* Script() const { return mScript; }
-   nsIURI* BaseURL() const { return mBaseURL; }
-   JS::Value ParseError() const { return mParseError; }
-   JS::Value ErrorToRethrow() const { return mErrorToRethrow; }
-   bool HasParseError() const { return !mParseError.isUndefined(); }
-   bool HasErrorToRethrow() const { return !mErrorToRethrow.isUndefined(); }
-   bool SourceElementAssociated() const { return mSourceElementAssociated; }
- 
--  void UnlinkModuleRecord();
-+  void UnlinkScript();
- };
- 
- } // dom namespace
- } // mozilla namespace
- 
- #endif // mozilla_dom_ModuleScript_h
-diff --git a/dom/script/ScriptLoader.cpp b/dom/script/ScriptLoader.cpp
---- a/dom/script/ScriptLoader.cpp
-+++ b/dom/script/ScriptLoader.cpp
-@@ -473,60 +473,60 @@ ScriptLoader::CreateModuleScript(ModuleL
-   AutoEntryScript aes(globalObject, "CompileModule", true);
- 
-   bool oldProcessingScriptTag = context->GetProcessingScriptTag();
-   context->SetProcessingScriptTag(true);
- 
-   nsresult rv;
-   {
-     JSContext* cx = aes.cx();
--    JS::Rooted<JSObject*> module(cx);
-+    JS::Rooted<JSScript*> script(cx);
- 
-     if (aRequest->mWasCompiledOMT) {
--      module = JS::FinishOffThreadModule(cx, aRequest->mOffThreadToken);
-+      script = JS::FinishOffThreadModule(cx, aRequest->mOffThreadToken);
-       aRequest->mOffThreadToken = nullptr;
--      rv = module ? NS_OK : NS_ERROR_FAILURE;
-+      rv = script ? NS_OK : NS_ERROR_FAILURE;
-     } else {
-       JS::Rooted<JSObject*> global(cx, globalObject->GetGlobalJSObject());
- 
-       JS::CompileOptions options(cx);
-       rv = FillCompileOptionsForRequest(aes, aRequest, global, &options);
- 
-       if (NS_SUCCEEDED(rv)) {
-         auto srcBuf = GetScriptSource(cx, aRequest);
-         if (srcBuf) {
--          rv = nsJSUtils::CompileModule(cx, *srcBuf, global, options, &module);
-+          rv = nsJSUtils::CompileModule(cx, *srcBuf, global, options, &script);
-         } else {
-           rv = NS_ERROR_OUT_OF_MEMORY;
-         }
-       }
-     }
- 
--    MOZ_ASSERT(NS_SUCCEEDED(rv) == (module != nullptr));
-+    MOZ_ASSERT(NS_SUCCEEDED(rv) == (script != nullptr));
- 
-     RefPtr<ModuleScript> moduleScript = new ModuleScript(this, aRequest->mBaseURL);
-     aRequest->mModuleScript = moduleScript;
- 
--    if (!module) {
-+    if (!script) {
-       LOG(("ScriptLoadRequest (%p):   compilation failed (%d)",
-            aRequest, unsigned(rv)));
- 
-       MOZ_ASSERT(aes.HasException());
-       JS::Rooted<JS::Value> error(cx);
-       if (!aes.StealException(&error)) {
-         aRequest->mModuleScript = nullptr;
-         return NS_ERROR_FAILURE;
-       }
- 
-       moduleScript->SetParseError(error);
-       aRequest->ModuleErrored();
-       return NS_OK;
-     }
- 
--    moduleScript->SetModuleRecord(module);
-+    moduleScript->SetScript(script);
- 
-     // Validate requested modules and treat failure to resolve module specifiers
-     // the same as a parse error.
-     rv = ResolveRequestedModules(aRequest, nullptr);
-     if (NS_FAILED(rv)) {
-       aRequest->ModuleErrored();
-       return NS_OK;
-     }
-@@ -609,24 +609,24 @@ ResolveModuleSpecifier(ModuleScript* aSc
- }
- 
- static nsresult
- ResolveRequestedModules(ModuleLoadRequest* aRequest, nsCOMArray<nsIURI>* aUrlsOut)
- {
-   ModuleScript* ms = aRequest->mModuleScript;
- 
-   AutoJSAPI jsapi;
--  if (!jsapi.Init(ms->ModuleRecord())) {
-+  if (!jsapi.Init(JS::GetScriptGlobal(ms->Script()))) {
-     return NS_ERROR_FAILURE;
-   }
- 
-   JSContext* cx = jsapi.cx();
--  JS::Rooted<JSObject*> moduleRecord(cx, ms->ModuleRecord());
-+  JS::Rooted<JSScript*> script(cx, ms->Script());
-   JS::Rooted<JSObject*> requestedModules(cx);
--  requestedModules = JS::GetRequestedModules(cx, moduleRecord);
-+  requestedModules = JS::GetRequestedModules(cx, script);
-   MOZ_ASSERT(requestedModules);
- 
-   uint32_t length;
-   if (!JS_GetArrayLength(cx, requestedModules, &length)) {
-     return NS_ERROR_FAILURE;
-   }
- 
-   JS::Rooted<JS::Value> element(cx);
-@@ -750,24 +750,24 @@ ScriptLoader::StartFetchingModuleAndDepe
-     childRequest->mReady.Reject(rv, __func__);
-     return ready;
-   }
- 
-   return ready;
- }
- 
- // 8.1.3.8.1 HostResolveImportedModule(referencingModule, specifier)
--JSObject*
--HostResolveImportedModule(JSContext* aCx, JS::Handle<JSObject*> aModule,
-+JSScript*
-+HostResolveImportedModule(JSContext* aCx, JS::Handle<JSScript*> aScript,
-                           JS::Handle<JSString*> aSpecifier)
- {
-   // Let referencing module script be referencingModule.[[HostDefined]].
--  JS::Value value = JS::GetModuleHostDefinedField(aModule);
-+  JS::Value value = JS::GetModuleHostDefinedField(aScript);
-   auto script = static_cast<ModuleScript*>(value.toPrivate());
--  MOZ_ASSERT(script->ModuleRecord() == aModule);
-+  MOZ_ASSERT(script->Script() == aScript);
- 
-   // Let url be the result of resolving a module specifier given referencing
-   // module script and specifier.
-   nsAutoJSString string;
-   if (!string.init(aCx, aSpecifier)) {
-     return nullptr;
-   }
- 
-@@ -778,35 +778,35 @@ HostResolveImportedModule(JSContext* aCx
-   MOZ_ASSERT(uri, "Failed to resolve previously-resolved module specifier");
- 
-   // Let resolved module script be moduleMap[url]. (This entry must exist for us
-   // to have gotten to this point.)
-   ModuleScript* ms = script->Loader()->GetFetchedModule(uri);
-   MOZ_ASSERT(ms, "Resolved module not found in module map");
- 
-   MOZ_ASSERT(!ms->HasParseError());
--  MOZ_ASSERT(ms->ModuleRecord());
--
--  return ms->ModuleRecord();
-+  MOZ_ASSERT(ms->Script());
-+
-+  return ms->Script();
- }
- 
- bool
--HostPopulateImportMeta(JSContext* aCx, JS::Handle<JSObject*> aModule,
-+HostPopulateImportMeta(JSContext* aCx, JS::Handle<JSScript*> aScript,
-                        JS::Handle<JSObject*> aMetaObject)
- {
--  MOZ_DIAGNOSTIC_ASSERT(aModule);
--
--  JS::Value value = JS::GetModuleHostDefinedField(aModule);
-+  MOZ_DIAGNOSTIC_ASSERT(aScript);
-+
-+  JS::Value value = JS::GetModuleHostDefinedField(aScript);
-   if (value.isUndefined()) {
-     JS_ReportErrorASCII(aCx, "Module script not found");
-     return false;
-   }
- 
-   auto script = static_cast<ModuleScript*>(value.toPrivate());
--  MOZ_DIAGNOSTIC_ASSERT(script->ModuleRecord() == aModule);
-+  MOZ_DIAGNOSTIC_ASSERT(script->Script() == aScript);
- 
-   nsAutoCString url;
-   MOZ_DIAGNOSTIC_ASSERT(script->BaseURL());
-   MOZ_ALWAYS_SUCCEEDS(script->BaseURL()->GetAsciiSpec(url));
- 
-   JS::Rooted<JSString*> urlString(aCx, JS_NewStringCopyZ(aCx, url.get()));
-   if (!urlString) {
-     JS_ReportOutOfMemory(aCx);
-@@ -927,28 +927,28 @@ ScriptLoader::InstantiateModuleTree(Modu
- 
-   JS::Value parseError = FindFirstParseError(aRequest);
-   if (!parseError.isUndefined()) {
-     moduleScript->SetErrorToRethrow(parseError);
-     LOG(("ScriptLoadRequest (%p):   found parse error", aRequest));
-     return true;
-   }
- 
--  MOZ_ASSERT(moduleScript->ModuleRecord());
-+  MOZ_ASSERT(moduleScript->Script());
- 
-   nsAutoMicroTask mt;
-   AutoJSAPI jsapi;
--  if (NS_WARN_IF(!jsapi.Init(moduleScript->ModuleRecord()))) {
-+  if (NS_WARN_IF(!jsapi.Init(JS::GetScriptGlobal(moduleScript->Script())))) {
-     return false;
-   }
- 
-   EnsureModuleResolveHook(jsapi.cx());
- 
--  JS::Rooted<JSObject*> module(jsapi.cx(), moduleScript->ModuleRecord());
--  bool ok = NS_SUCCEEDED(nsJSUtils::ModuleInstantiate(jsapi.cx(), module));
-+  JS::Rooted<JSScript*> script(jsapi.cx(), moduleScript->Script());
-+  bool ok = NS_SUCCEEDED(nsJSUtils::ModuleInstantiate(jsapi.cx(), script));
- 
-   if (!ok) {
-     LOG(("ScriptLoadRequest (%p): Instantiate failed", aRequest));
-     MOZ_ASSERT(jsapi.HasException());
-     JS::RootedValue exception(jsapi.cx());
-     if (!jsapi.StealException(&exception)) {
-       return false;
-     }
-@@ -2298,30 +2298,29 @@ ScriptLoader::EvaluateScript(ScriptLoadR
-       ModuleScript* moduleScript = request->mModuleScript;
-       if (moduleScript->HasErrorToRethrow()) {
-         LOG(("ScriptLoadRequest (%p):   module has error to rethrow", aRequest));
-         JS::Rooted<JS::Value> error(cx, moduleScript->ErrorToRethrow());
-         JS_SetPendingException(cx, error);
-         return NS_OK; // An error is reported by AutoEntryScript.
-       }
- 
--      JS::Rooted<JSObject*> module(cx, moduleScript->ModuleRecord());
--      MOZ_ASSERT(module);
-+      JS::Rooted<JSScript*> script(cx, moduleScript->Script());
-+      MOZ_ASSERT(script);
- 
-       if (!moduleScript->SourceElementAssociated()) {
--        rv = nsJSUtils::InitModuleSourceElement(cx, module, aRequest->Element());
-+        rv = nsJSUtils::InitModuleSourceElement(cx, script, aRequest->Element());
-         NS_ENSURE_SUCCESS(rv, rv);
-         moduleScript->SetSourceElementAssociated();
- 
-         // The script is now ready to be exposed to the debugger.
--        JS::Rooted<JSScript*> script(cx, JS::GetModuleScript(module));
-         JS::ExposeScriptToDebugger(cx, script);
-       }
- 
--      rv = nsJSUtils::ModuleEvaluate(cx, module);
-+      rv = nsJSUtils::ModuleEvaluate(cx, script);
-       MOZ_ASSERT(NS_FAILED(rv) == aes.HasException());
-       if (NS_FAILED(rv)) {
-         LOG(("ScriptLoadRequest (%p):   evaluation failed", aRequest));
-         rv = NS_OK; // An error is reported by AutoEntryScript.
-       }
- 
-       aRequest->mCacheInfo = nullptr;
-     } else {
-diff --git a/dom/script/ScriptLoader.h b/dom/script/ScriptLoader.h
---- a/dom/script/ScriptLoader.h
-+++ b/dom/script/ScriptLoader.h
-@@ -515,18 +515,18 @@ private:
-                                                       nsresult aResult);
- 
-   bool IsFetchingModule(ModuleLoadRequest* aRequest) const;
- 
-   bool ModuleMapContainsURL(nsIURI* aURL) const;
-   RefPtr<mozilla::GenericPromise> WaitForModuleFetch(nsIURI* aURL);
-   ModuleScript* GetFetchedModule(nsIURI* aURL) const;
- 
--  friend JSObject*
--  HostResolveImportedModule(JSContext* aCx, JS::Handle<JSObject*> aModule,
-+  friend JSScript*
-+  HostResolveImportedModule(JSContext* aCx, JS::Handle<JSScript*> aScript,
-                           JS::Handle<JSString*> aSpecifier);
- 
-   // Returns wether we should save the bytecode of this script after the
-   // execution of the script.
-   static bool
-   ShouldCacheBytecode(ScriptLoadRequest* aRequest);
- 
-   nsresult CreateModuleScript(ModuleLoadRequest* aRequest);
-diff --git a/js/public/Realm.h b/js/public/Realm.h
---- a/js/public/Realm.h
-+++ b/js/public/Realm.h
-@@ -68,16 +68,21 @@ GetCompartmentForRealm(Realm* realm)
- }
- 
- // Return an object's realm. All objects except cross-compartment wrappers are
- // created in a particular realm, which never changes. Returns null if obj is
- // a cross-compartment wrapper.
- extern JS_PUBLIC_API(Realm*)
- GetObjectRealmOrNull(JSObject* obj);
- 
-+// Return a script's realm. All scripts are created in a particular realm, which
-+// never changes.
-+extern JS_PUBLIC_API(Realm*)
-+GetScriptRealm(JSScript* script);
-+
- // Get the value of the "private data" internal field of the given Realm.
- // This field is initially null and is set using SetRealmPrivate.
- // It's a pointer to embeddding-specific data that SpiderMonkey never uses.
- extern JS_PUBLIC_API(void*)
- GetRealmPrivate(Realm* realm);
- 
- // Set the "private data" internal field of the given Realm.
- extern JS_PUBLIC_API(void)
-diff --git a/js/src/builtin/ModuleObject.cpp b/js/src/builtin/ModuleObject.cpp
---- a/js/src/builtin/ModuleObject.cpp
-+++ b/js/src/builtin/ModuleObject.cpp
-@@ -1638,31 +1638,32 @@ ArrayObject* ModuleBuilder::createArray(
-     uint32_t i = 0;
-     for (auto r = map.all(); !r.empty(); r.popFront())
-         array->initDenseElement(i++, ObjectValue(*r.front().value()));
- 
-     return array;
- }
- 
- JSObject*
--js::GetOrCreateModuleMetaObject(JSContext* cx, HandleObject moduleArg)
-+js::GetOrCreateModuleMetaObject(JSContext* cx, HandleScript script)
- {
--    HandleModuleObject module = moduleArg.as<ModuleObject>();
-+    MOZ_ASSERT(script->module());
-+    RootedModuleObject module(cx, script->module());
-     if (JSObject* obj = module->metaObject())
-         return obj;
- 
-     RootedObject metaObject(cx, NewObjectWithGivenProto<PlainObject>(cx, nullptr));
-     if (!metaObject)
-         return nullptr;
- 
-     JS::ModuleMetadataHook func = cx->runtime()->moduleMetadataHook;
-     if (!func) {
-         JS_ReportErrorASCII(cx, "Module metadata hook not set");
-         return nullptr;
-     }
- 
--    if (!func(cx, module, metaObject))
-+    if (!func(cx, script, metaObject))
-         return nullptr;
- 
-     module->setMetaObject(metaObject);
- 
-     return metaObject;
- }
-diff --git a/js/src/builtin/ModuleObject.h b/js/src/builtin/ModuleObject.h
---- a/js/src/builtin/ModuleObject.h
-+++ b/js/src/builtin/ModuleObject.h
-@@ -407,17 +407,17 @@ class MOZ_STACK_CLASS ModuleBuilder
- 
-     template <typename T>
-     ArrayObject* createArray(const JS::Rooted<GCVector<T>>& vector);
-     template <typename K, typename V>
-     ArrayObject* createArray(const JS::Rooted<GCHashMap<K, V>>& map);
- };
- 
- JSObject*
--GetOrCreateModuleMetaObject(JSContext* cx, HandleObject module);
-+GetOrCreateModuleMetaObject(JSContext* cx, HandleScript script);
- 
- } // namespace js
- 
- template<>
- inline bool
- JSObject::is<js::ModuleNamespaceObject>() const
- {
-     return js::IsDerivedProxyObject(this, &js::ModuleNamespaceObject::proxyHandler);
-diff --git a/js/src/frontend/BytecodeCompiler.cpp b/js/src/frontend/BytecodeCompiler.cpp
---- a/js/src/frontend/BytecodeCompiler.cpp
-+++ b/js/src/frontend/BytecodeCompiler.cpp
-@@ -42,17 +42,17 @@ class MOZ_STACK_CLASS BytecodeCompiler
-     BytecodeCompiler(JSContext* cx,
-                      LifoAlloc& alloc,
-                      const ReadOnlyCompileOptions& options,
-                      SourceBufferHolder& sourceBuffer,
-                      HandleScope enclosingScope);
- 
-     JSScript* compileGlobalScript(ScopeKind scopeKind);
-     JSScript* compileEvalScript(HandleObject environment, HandleScope enclosingScope);
--    ModuleObject* compileModule();
-+    JSScript* compileModule();
-     bool compileStandaloneFunction(MutableHandleFunction fun, GeneratorKind generatorKind,
-                                    FunctionAsyncKind asyncKind,
-                                    const Maybe<uint32_t>& parameterListEnd);
- 
-     ScriptSourceObject* sourceObjectPtr() const;
- 
-   private:
-     JSScript* compileScript(HandleObject environment, SharedContext* sc);
-@@ -389,17 +389,17 @@ BytecodeCompiler::compileGlobalScript(Sc
- JSScript*
- BytecodeCompiler::compileEvalScript(HandleObject environment, HandleScope enclosingScope)
- {
-     EvalSharedContext evalsc(cx, environment, enclosingScope,
-                              directives, options.extraWarningsOption);
-     return compileScript(environment, &evalsc);
- }
- 
--ModuleObject*
-+JSScript*
- BytecodeCompiler::compileModule()
- {
-     if (!createSourceAndParser(ParseGoal::Module))
-         return nullptr;
- 
-     Rooted<ModuleObject*> module(cx, ModuleObject::create(cx));
-     if (!module)
-         return nullptr;
-@@ -433,17 +433,17 @@ BytecodeCompiler::compileModule()
- 
-     module->setInitialEnvironment(env);
- 
-     // Enqueue an off-thread source compression task after finishing parsing.
-     if (!scriptSource->tryCompressOffThread(cx))
-         return nullptr;
- 
-     MOZ_ASSERT_IF(!cx->helperThread(), !cx->isExceptionPending());
--    return module;
-+    return script;
- }
- 
- // Compile a standalone JS function, which might appear as the value of an
- // event handler attribute in an HTML <INPUT> tag, or in a Function()
- // constructor.
- bool
- BytecodeCompiler::compileStandaloneFunction(MutableHandleFunction fun,
-                                             GeneratorKind generatorKind,
-@@ -682,17 +682,17 @@ frontend::CompileEvalScript(JSContext* c
-     JSScript* script = compiler.compileEvalScript(environment, enclosingScope);
-     if (!script)
-         return nullptr;
-     assertException.reset();
-     return script;
- 
- }
- 
--ModuleObject*
-+JSScript*
- frontend::CompileModule(JSContext* cx, const ReadOnlyCompileOptions& optionsInput,
-                         SourceBufferHolder& srcBuf, LifoAlloc& alloc,
-                         ScriptSourceObject** sourceObjectOut)
- {
-     MOZ_ASSERT(srcBuf.get());
-     MOZ_ASSERT_IF(sourceObjectOut, *sourceObjectOut == nullptr);
- 
-     AutoAssertReportedException assertException(cx);
-@@ -700,45 +700,46 @@ frontend::CompileModule(JSContext* cx, c
-     CompileOptions options(cx, optionsInput);
-     options.maybeMakeStrictMode(true); // ES6 10.2.1 Module code is always strict mode code.
-     options.setIsRunOnce(true);
-     options.allowHTMLComments = false;
- 
-     RootedScope emptyGlobalScope(cx, &cx->global()->emptyGlobalScope());
-     BytecodeCompiler compiler(cx, alloc, options, srcBuf, emptyGlobalScope);
-     AutoInitializeSourceObject autoSSO(compiler, sourceObjectOut);
--    ModuleObject* module = compiler.compileModule();
--    if (!module)
-+    JSScript* script = compiler.compileModule();
-+    if (!script)
-         return nullptr;
- 
-     assertException.reset();
--    return module;
-+    return script;
- }
- 
--ModuleObject*
-+JSScript*
- frontend::CompileModule(JSContext* cx, const ReadOnlyCompileOptions& options,
-                         SourceBufferHolder& srcBuf)
- {
-     AutoAssertReportedException assertException(cx);
- 
-     if (!GlobalObject::ensureModulePrototypesCreated(cx, cx->global()))
-         return nullptr;
- 
-     LifoAlloc& alloc = cx->tempLifoAlloc();
--    RootedModuleObject module(cx, CompileModule(cx, options, srcBuf, alloc));
--    if (!module)
-+    RootedScript script(cx, CompileModule(cx, options, srcBuf, alloc));
-+    if (!script)
-         return nullptr;
- 
-     // This happens in GlobalHelperThreadState::finishModuleParseTask() when a
-     // module is compiled off thread.
-+    RootedModuleObject module(cx, script->module());
-     if (!ModuleObject::Freeze(cx, module))
-         return nullptr;
- 
-     assertException.reset();
--    return module;
-+    return script;
- }
- 
- // When leaving this scope, the given function should either:
- //   * be linked to a fully compiled script
- //   * remain linking to a lazy script
- class MOZ_STACK_CLASS AutoAssertFunctionDelazificationCompletion
- {
- #ifdef DEBUG
-diff --git a/js/src/frontend/BytecodeCompiler.h b/js/src/frontend/BytecodeCompiler.h
---- a/js/src/frontend/BytecodeCompiler.h
-+++ b/js/src/frontend/BytecodeCompiler.h
-@@ -16,17 +16,16 @@
- #include "vm/TraceLogging.h"
- 
- class JSLinearString;
- 
- namespace js {
- 
- class LazyScript;
- class LifoAlloc;
--class ModuleObject;
- class ScriptSourceObject;
- 
- namespace frontend {
- 
- class ErrorReporter;
- class FunctionBox;
- class ParseNode;
- 
-@@ -48,21 +47,21 @@ CompileGlobalBinASTScript(JSContext *cx,
- 
- JSScript*
- CompileEvalScript(JSContext* cx, LifoAlloc& alloc,
-                   HandleObject scopeChain, HandleScope enclosingScope,
-                   const ReadOnlyCompileOptions& options,
-                   SourceBufferHolder& srcBuf,
-                   ScriptSourceObject** sourceObjectOut = nullptr);
- 
--ModuleObject*
-+JSScript*
- CompileModule(JSContext* cx, const ReadOnlyCompileOptions& options,
-               SourceBufferHolder& srcBuf);
- 
--ModuleObject*
-+JSScript*
- CompileModule(JSContext* cx, const ReadOnlyCompileOptions& options,
-               SourceBufferHolder& srcBuf, LifoAlloc& alloc,
-               ScriptSourceObject** sourceObjectOut = nullptr);
- 
- MOZ_MUST_USE bool
- CompileLazyFunction(JSContext* cx, Handle<LazyScript*> lazy, const char16_t* chars, size_t length);
- 
- //
-diff --git a/js/src/jit/BaselineCompiler.cpp b/js/src/jit/BaselineCompiler.cpp
---- a/js/src/jit/BaselineCompiler.cpp
-+++ b/js/src/jit/BaselineCompiler.cpp
-@@ -5133,15 +5133,16 @@ BaselineCompiler::emit_JSOP_DERIVEDCONST
- }
- 
- bool
- BaselineCompiler::emit_JSOP_IMPORTMETA()
- {
-     RootedModuleObject module(cx, GetModuleObjectForScript(script));
-     MOZ_ASSERT(module);
- 
--    JSObject* metaObject = GetOrCreateModuleMetaObject(cx, module);
-+    RootedScript moduleScript(cx, module->script());
-+    JSObject* metaObject = GetOrCreateModuleMetaObject(cx, moduleScript);
-     if (!metaObject)
-         return false;
- 
-     frame.push(ObjectValue(*metaObject));
-     return true;
- }
-diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp
---- a/js/src/jsapi.cpp
-+++ b/js/src/jsapi.cpp
-@@ -1266,16 +1266,25 @@ JS::CurrentGlobalOrNull(JSContext* cx)
- JS_PUBLIC_API(JSObject*)
- JS::GetNonCCWObjectGlobal(JSObject* obj)
- {
-     AssertHeapIsIdleOrIterating();
-     MOZ_DIAGNOSTIC_ASSERT(!IsCrossCompartmentWrapper(obj));
-     return &obj->nonCCWGlobal();
- }
- 
-+JS_PUBLIC_API(JSObject*)
-+JS::GetScriptGlobal(JSScript* script)
-+{
-+    AssertHeapIsIdleOrIterating();
-+    JSObject* global = script->realm()->maybeGlobal();
-+    MOZ_ASSERT(global);
-+    return global;
-+}
-+
- JS_PUBLIC_API(bool)
- JS::detail::ComputeThis(JSContext* cx, Value* vp, MutableHandleObject thisObject)
- {
-     AssertHeapIsIdle();
-     assertSameCompartment(cx, vp[0], vp[1]);
- 
-     MutableHandleValue thisv = MutableHandleValue::fromMarkedLocation(&vp[1]);
-     if (!BoxNonStrictThis(cx, thisv, thisv))
-@@ -4242,17 +4251,17 @@ JS_PUBLIC_API(bool)
- JS::CompileOffThreadModule(JSContext* cx, const ReadOnlyCompileOptions& options,
-                            JS::SourceBufferHolder& srcBuf,
-                            OffThreadCompileCallback callback, void* callbackData)
- {
-     MOZ_ASSERT(CanCompileOffThread(cx, options, srcBuf.length()));
-     return StartOffThreadParseModule(cx, options, srcBuf, callback, callbackData);
- }
- 
--JS_PUBLIC_API(JSObject*)
-+JS_PUBLIC_API(JSScript*)
- JS::FinishOffThreadModule(JSContext* cx, JS::OffThreadToken* token)
- {
-     MOZ_ASSERT(cx);
-     MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
-     return HelperThreadState().finishModuleParseTask(cx, token);
- }
- 
- JS_PUBLIC_API(void)
-@@ -4833,63 +4842,71 @@ JS_PUBLIC_API(void)
- JS::SetModuleMetadataHook(JSRuntime* rt, JS::ModuleMetadataHook func)
- {
-     AssertHeapIsIdle();
-     rt->moduleMetadataHook = func;
- }
- 
- JS_PUBLIC_API(bool)
- JS::CompileModule(JSContext* cx, const ReadOnlyCompileOptions& options,
--                  SourceBufferHolder& srcBuf, JS::MutableHandleObject module)
-+                  SourceBufferHolder& srcBuf, JS::MutableHandleScript script)
- {
-     MOZ_ASSERT(!cx->zone()->isAtomsZone());
-     AssertHeapIsIdle();
-     CHECK_REQUEST(cx);
- 
--    module.set(frontend::CompileModule(cx, options, srcBuf));
--    return !!module;
-+    script.set(frontend::CompileModule(cx, options, srcBuf));
-+    return !!script;
- }
- 
- JS_PUBLIC_API(void)
--JS::SetModuleHostDefinedField(JSObject* module, const JS::Value& value)
--{
--    module->as<ModuleObject>().setHostDefinedField(value);
-+JS::SetModuleHostDefinedField(JSScript* script, const JS::Value& value)
-+{
-+    MOZ_ASSERT(script->module());
-+    script->module()->setHostDefinedField(value);
- }
- 
- JS_PUBLIC_API(JS::Value)
--JS::GetModuleHostDefinedField(JSObject* module)
--{
--    return module->as<ModuleObject>().hostDefinedField();
--}
--
--JS_PUBLIC_API(bool)
--JS::ModuleInstantiate(JSContext* cx, JS::HandleObject moduleArg)
--{
--    AssertHeapIsIdle();
--    CHECK_REQUEST(cx);
--    assertSameCompartment(cx, moduleArg);
--    return ModuleObject::Instantiate(cx, moduleArg.as<ModuleObject>());
--}
--
--JS_PUBLIC_API(bool)
--JS::ModuleEvaluate(JSContext* cx, JS::HandleObject moduleArg)
--{
--    AssertHeapIsIdle();
--    CHECK_REQUEST(cx);
--    assertSameCompartment(cx, moduleArg);
--    return ModuleObject::Evaluate(cx, moduleArg.as<ModuleObject>());
-+JS::GetModuleHostDefinedField(JSScript* script)
-+{
-+    MOZ_ASSERT(script->module());
-+    return script->module()->hostDefinedField();
-+}
-+
-+JS_PUBLIC_API(bool)
-+JS::ModuleInstantiate(JSContext* cx, JS::HandleScript script)
-+{
-+    AssertHeapIsIdle();
-+    CHECK_REQUEST(cx);
-+    assertSameCompartment(cx, script);
-+    RootedModuleObject module(cx, script->module());
-+    MOZ_ASSERT(module);
-+    return ModuleObject::Instantiate(cx, module);
-+}
-+
-+JS_PUBLIC_API(bool)
-+JS::ModuleEvaluate(JSContext* cx, JS::HandleScript script)
-+{
-+    AssertHeapIsIdle();
-+    CHECK_REQUEST(cx);
-+    assertSameCompartment(cx, script);
-+    RootedModuleObject module(cx, script->module());
-+    MOZ_ASSERT(module);
-+    return ModuleObject::Evaluate(cx, module);
- }
- 
- JS_PUBLIC_API(JSObject*)
--JS::GetRequestedModules(JSContext* cx, JS::HandleObject moduleArg)
--{
--    AssertHeapIsIdle();
--    CHECK_REQUEST(cx);
--    assertSameCompartment(cx, moduleArg);
--    return &moduleArg->as<ModuleObject>().requestedModules();
-+JS::GetRequestedModules(JSContext* cx, JS::HandleScript script)
-+{
-+    AssertHeapIsIdle();
-+    CHECK_REQUEST(cx);
-+    assertSameCompartment(cx, script);
-+    RootedModuleObject module(cx, script->module());
-+    MOZ_ASSERT(module);
-+    return &module->requestedModules();
- }
- 
- JS_PUBLIC_API(JSString*)
- JS::GetRequestedModuleSpecifier(JSContext* cx, JS::HandleValue value)
- {
-     AssertHeapIsIdle();
-     CHECK_REQUEST(cx);
-     assertSameCompartment(cx, value);
-@@ -4906,23 +4923,16 @@ JS::GetRequestedModuleSourcePos(JSContex
-     assertSameCompartment(cx, value);
-     MOZ_ASSERT(lineNumber);
-     MOZ_ASSERT(columnNumber);
-     auto& requested = value.toObject().as<RequestedModuleObject>();
-     *lineNumber = requested.lineNumber();
-     *columnNumber = requested.columnNumber();
- }
- 
--JS_PUBLIC_API(JSScript*)
--JS::GetModuleScript(JS::HandleObject moduleRecord)
--{
--    AssertHeapIsIdle();
--    return moduleRecord->as<ModuleObject>().script();
--}
--
- JS_PUBLIC_API(JSObject*)
- JS_New(JSContext* cx, HandleObject ctor, const JS::HandleValueArray& inputArgs)
- {
-     AssertHeapIsIdle();
-     CHECK_REQUEST(cx);
-     assertSameCompartment(cx, ctor, inputArgs);
- 
-     RootedValue ctorVal(cx, ObjectValue(*ctor));
-diff --git a/js/src/jsapi.h b/js/src/jsapi.h
---- a/js/src/jsapi.h
-+++ b/js/src/jsapi.h
-@@ -1229,16 +1229,22 @@ CurrentGlobalOrNull(JSContext* cx);
- /**
-  * Get the global object associated with an object's realm. The object must not
-  * be a cross-compartment wrapper (because CCWs are shared by all realms in the
-  * compartment).
-  */
- extern JS_PUBLIC_API(JSObject*)
- GetNonCCWObjectGlobal(JSObject* obj);
- 
-+/**
-+ * Get the global object associated with a script's realm.
-+ */
-+extern JS_PUBLIC_API(JSObject*)
-+GetScriptGlobal(JSScript* script);
-+
- } // namespace JS
- 
- /**
-  * Add 'Reflect.parse', a SpiderMonkey extension, to the Reflect object on the
-  * given global.
-  */
- extern JS_PUBLIC_API(bool)
- JS_InitReflectParse(JSContext* cx, JS::HandleObject global);
-@@ -3687,17 +3693,17 @@ FinishOffThreadScript(JSContext* cx, Off
- extern JS_PUBLIC_API(void)
- CancelOffThreadScript(JSContext* cx, OffThreadToken* token);
- 
- extern JS_PUBLIC_API(bool)
- CompileOffThreadModule(JSContext* cx, const ReadOnlyCompileOptions& options,
-                        JS::SourceBufferHolder& srcBuf,
-                        OffThreadCompileCallback callback, void* callbackData);
- 
--extern JS_PUBLIC_API(JSObject*)
-+extern JS_PUBLIC_API(JSScript*)
- FinishOffThreadModule(JSContext* cx, OffThreadToken* token);
- 
- extern JS_PUBLIC_API(void)
- CancelOffThreadModule(JSContext* cx, OffThreadToken* token);
- 
- extern JS_PUBLIC_API(bool)
- DecodeOffThreadScript(JSContext* cx, const ReadOnlyCompileOptions& options,
-                       mozilla::Vector<uint8_t>& buffer /* TranscodeBuffer& */, size_t cursor,
-@@ -3859,88 +3865,88 @@ Evaluate(JSContext* cx, const ReadOnlyCo
- 
- /**
-  * Evaluate the given file in the scope of the current global of cx.
-  */
- extern JS_PUBLIC_API(bool)
- Evaluate(JSContext* cx, const ReadOnlyCompileOptions& options,
-          const char* filename, JS::MutableHandleValue rval);
- 
--using ModuleResolveHook = JSObject* (*)(JSContext*, HandleObject, HandleString);
-+using ModuleResolveHook = JSScript* (*)(JSContext*, HandleScript, HandleString);
- 
- /**
-  * Get the HostResolveImportedModule hook for the runtime.
-  */
- extern JS_PUBLIC_API(ModuleResolveHook)
- GetModuleResolveHook(JSRuntime* rt);
- 
- /**
-  * Set the HostResolveImportedModule hook for the runtime to the given function.
-  */
- extern JS_PUBLIC_API(void)
- SetModuleResolveHook(JSRuntime* rt, ModuleResolveHook func);
- 
--using ModuleMetadataHook = bool (*)(JSContext*, HandleObject, HandleObject);
-+using ModuleMetadataHook = bool (*)(JSContext*, HandleScript, HandleObject);
- 
- /**
-  * Get the hook for populating the import.meta metadata object.
-  */
- extern JS_PUBLIC_API(ModuleMetadataHook)
- GetModuleMetadataHook(JSRuntime* rt);
- 
- /**
-  * Set the hook for populating the import.meta metadata object to the given
-  * function.
-  */
- extern JS_PUBLIC_API(void)
- SetModuleMetadataHook(JSRuntime* rt, ModuleMetadataHook func);
- 
- /**
-  * Parse the given source buffer as a module in the scope of the current global
-- * of cx and return a source text module record.
-+ * of cx.
-  */
- extern JS_PUBLIC_API(bool)
- CompileModule(JSContext* cx, const ReadOnlyCompileOptions& options,
--              SourceBufferHolder& srcBuf, JS::MutableHandleObject moduleRecord);
-+              SourceBufferHolder& srcBuf, JS::MutableHandleScript script);
- 
- /**
-  * Set the [[HostDefined]] field of a source text module record to the given
-  * value.
-  */
- extern JS_PUBLIC_API(void)
--SetModuleHostDefinedField(JSObject* module, const JS::Value& value);
-+SetModuleHostDefinedField(JSScript* module, const JS::Value& value);
- 
- /**
-  * Get the [[HostDefined]] field of a source text module record.
-  */
- extern JS_PUBLIC_API(JS::Value)
--GetModuleHostDefinedField(JSObject* module);
-+GetModuleHostDefinedField(JSScript* script);
- 
- /*
-  * Perform the ModuleInstantiate operation on the given source text module
-  * record.
-  *
-  * This transitively resolves all module dependencies (calling the
-  * HostResolveImportedModule hook) and initializes the environment record for
-  * the module.
-  */
- extern JS_PUBLIC_API(bool)
--ModuleInstantiate(JSContext* cx, JS::HandleObject moduleRecord);
-+ModuleInstantiate(JSContext* cx, JS::HandleScript script);
- 
- /*
-  * Perform the ModuleEvaluate operation on the given source text module record.
-  *
-  * This does nothing if this module has already been evaluated. Otherwise, it
-  * transitively evaluates all dependences of this module and then evaluates this
-  * module.
-  *
-  * ModuleInstantiate must have completed prior to calling this.
-  */
- extern JS_PUBLIC_API(bool)
--ModuleEvaluate(JSContext* cx, JS::HandleObject moduleRecord);
-+ModuleEvaluate(JSContext* cx, JS::HandleScript script);
- 
- /*
-  * Get a list of the module specifiers used by a source text module
-  * record to request importation of modules.
-  *
-  * The result is a JavaScript array of object values.  To extract the individual
-  * values use only JS_GetArrayLength and JS_GetElement with indices 0 to length
-  * - 1.
-@@ -3949,28 +3955,25 @@ ModuleEvaluate(JSContext* cx, JS::Handle
-  *  - moduleSpecifier: the module specifier string
-  *  - lineNumber: the line number of the import in the source text
-  *  - columnNumber: the column number of the import in the source text
-  *
-  * These property values can be extracted with GetRequestedModuleSpecifier() and
-  * GetRequestedModuleSourcePos()
-  */
- extern JS_PUBLIC_API(JSObject*)
--GetRequestedModules(JSContext* cx, JS::HandleObject moduleRecord);
-+GetRequestedModules(JSContext* cx, JS::HandleScript script);
- 
- extern JS_PUBLIC_API(JSString*)
- GetRequestedModuleSpecifier(JSContext* cx, JS::HandleValue requestedModuleObject);
- 
- extern JS_PUBLIC_API(void)
- GetRequestedModuleSourcePos(JSContext* cx, JS::HandleValue requestedModuleObject,
-                             uint32_t* lineNumber, uint32_t* columnNumber);
- 
--extern JS_PUBLIC_API(JSScript*)
--GetModuleScript(JS::HandleObject moduleRecord);
--
- } /* namespace JS */
- 
- #if defined(JS_BUILD_BINAST)
- 
- namespace JS {
- 
- extern JS_PUBLIC_API(JSScript*)
- DecodeBinAST(JSContext* cx, const ReadOnlyCompileOptions& options,
-diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp
---- a/js/src/shell/js.cpp
-+++ b/js/src/shell/js.cpp
-@@ -4294,21 +4294,21 @@ ParseModule(JSContext* cx, unsigned argc
-     AutoStableStringChars stableChars(cx);
-     if (!stableChars.initTwoByte(cx, scriptContents))
-         return false;
- 
-     const char16_t* chars = stableChars.twoByteRange().begin().get();
-     SourceBufferHolder srcBuf(chars, scriptContents->length(),
-                               SourceBufferHolder::NoOwnership);
- 
--    RootedObject module(cx, frontend::CompileModule(cx, options, srcBuf));
--    if (!module)
--        return false;
--
--    args.rval().setObject(*module);
-+    RootedScript script(cx, frontend::CompileModule(cx, options, srcBuf));
-+    if (!script)
-+        return false;
-+
-+    args.rval().setObject(*script->module());
-     return true;
- }
- 
- static bool
- SetModuleResolveHook(JSContext* cx, unsigned argc, Value* vp)
- {
-     CallArgs args = CallArgsFromVp(argc, vp);
-     if (args.length() != 1) {
-@@ -4325,48 +4325,49 @@ SetModuleResolveHook(JSContext* cx, unsi
- 
-     Handle<GlobalObject*> global = cx->global();
-     global->setReservedSlot(GlobalAppSlotModuleResolveHook, args[0]);
- 
-     args.rval().setUndefined();
-     return true;
- }
- 
--static JSObject*
--CallModuleResolveHook(JSContext* cx, HandleObject module, HandleString specifier)
--{
-+static JSScript*
-+CallModuleResolveHook(JSContext* cx, HandleScript script, HandleString specifier)
-+{
-+    MOZ_ASSERT(script->module());
-+
-     Handle<GlobalObject*> global = cx->global();
-     RootedValue hookValue(cx, global->getReservedSlot(GlobalAppSlotModuleResolveHook));
-     if (hookValue.isUndefined()) {
-         JS_ReportErrorASCII(cx, "Module resolve hook not set");
-         return nullptr;
-     }
-     MOZ_ASSERT(hookValue.toObject().is<JSFunction>());
- 
-     JS::AutoValueArray<2> args(cx);
--    args[0].setObject(*module);
-+    args[0].setObject(*script->module());
-     args[1].setString(specifier);
- 
-     RootedValue result(cx);
-     if (!JS_CallFunctionValue(cx, nullptr, hookValue, args, &result))
-         return nullptr;
- 
-     if (!result.isObject() || !result.toObject().is<ModuleObject>()) {
-          JS_ReportErrorASCII(cx, "Module resolve hook did not return Module object");
-          return nullptr;
-     }
- 
--    return &result.toObject();
--}
--
--static bool
--ShellModuleMetadataHook(JSContext* cx, HandleObject module, HandleObject metaObject)
-+    return result.toObject().as<ModuleObject>().script();
-+}
-+
-+static bool
-+ShellModuleMetadataHook(JSContext* cx, HandleScript script, HandleObject metaObject)
- {
-     // For the shell, just use the script's filename as the base URL.
--    RootedScript script(cx, module->as<ModuleObject>().script());
-     const char* filename = script->scriptSource()->filename();
-     MOZ_ASSERT(filename);
- 
-     RootedString url(cx, NewStringCopyZ<CanGC>(cx, filename));
-     if (!url)
-         return false;
- 
-     if (!JS_DefineProperty(cx, metaObject, "url", url, JSPROP_ENUMERATE))
-@@ -4858,21 +4859,21 @@ FinishOffThreadModule(JSContext* cx, uns
-     if (!job)
-         return false;
- 
-     JS::OffThreadToken* token = job->waitUntilDone(cx);
-     MOZ_ASSERT(token);
- 
-     DeleteOffThreadJob(cx, job);
- 
--    RootedObject module(cx, JS::FinishOffThreadModule(cx, token));
--    if (!module)
--        return false;
--
--    args.rval().setObject(*module);
-+    RootedScript script(cx, JS::FinishOffThreadModule(cx, token));
-+    if (!script)
-+        return false;
-+
-+    args.rval().setObject(*script->module());
-     return true;
- }
- 
- static bool
- OffThreadDecodeScript(JSContext* cx, unsigned argc, Value* vp)
- {
-     if (!CanUseExtraThreads()) {
-         JS_ReportErrorASCII(cx, "Can't use offThreadDecodeScript with --no-threads");
-diff --git a/js/src/vm/HelperThreads.cpp b/js/src/vm/HelperThreads.cpp
---- a/js/src/vm/HelperThreads.cpp
-+++ b/js/src/vm/HelperThreads.cpp
-@@ -520,19 +520,19 @@ ModuleParseTask::ModuleParseTask(JSConte
-     data(std::move(srcBuf))
- {}
- 
- void
- ModuleParseTask::parse(JSContext* cx)
- {
-     Rooted<ScriptSourceObject*> sourceObject(cx);
- 
--    ModuleObject* module = frontend::CompileModule(cx, options, data, alloc, &sourceObject.get());
--    if (module) {
--        scripts.infallibleAppend(module->script());
-+    JSScript* script = frontend::CompileModule(cx, options, data, alloc, &sourceObject.get());
-+    if (script) {
-+        scripts.infallibleAppend(script);
-         if (sourceObject)
-             sourceObjects.infallibleAppend(sourceObject);
-     }
- }
- 
- ScriptDecodeTask::ScriptDecodeTask(JSContext* cx, const JS::TranscodeRange& range,
-                                    JS::OffThreadCompileCallback callback, void* callbackData)
-   : ParseTask(ParseTaskKind::ScriptDecode, cx, callback, callbackData),
-@@ -1801,31 +1801,31 @@ GlobalHelperThreadState::finishBinASTDec
- 
- bool
- GlobalHelperThreadState::finishMultiScriptsDecodeTask(JSContext* cx, JS::OffThreadToken* token,
-                                                       MutableHandle<ScriptVector> scripts)
- {
-     return finishParseTask(cx, ParseTaskKind::MultiScriptsDecode, token, scripts);
- }
- 
--JSObject*
-+JSScript*
- GlobalHelperThreadState::finishModuleParseTask(JSContext* cx, JS::OffThreadToken* token)
- {
--    JSScript* script = finishParseTask(cx, ParseTaskKind::Module, token);
-+    RootedScript script(cx, finishParseTask(cx, ParseTaskKind::Module, token));
-     if (!script)
-         return nullptr;
- 
-     MOZ_ASSERT(script->module());
- 
-     RootedModuleObject module(cx, script->module());
-     module->fixEnvironmentsAfterCompartmentMerge();
-     if (!ModuleObject::Freeze(cx, module))
-         return nullptr;
- 
--    return module;
-+    return script;
- }
- 
- void
- GlobalHelperThreadState::cancelParseTask(JSRuntime* rt, ParseTaskKind kind,
-                                          JS::OffThreadToken* token)
- {
-     destroyParseTask(rt, removeFinishedParseTask(kind, token));
- }
-diff --git a/js/src/vm/HelperThreads.h b/js/src/vm/HelperThreads.h
---- a/js/src/vm/HelperThreads.h
-+++ b/js/src/vm/HelperThreads.h
-@@ -301,17 +301,17 @@ class GlobalHelperThreadState
- 
-     void mergeParseTaskRealm(JSContext* cx, ParseTask* parseTask, JS::Realm* dest);
- 
-     void trace(JSTracer* trc);
- 
-     JSScript* finishScriptParseTask(JSContext* cx, JS::OffThreadToken* token);
-     JSScript* finishScriptDecodeTask(JSContext* cx, JS::OffThreadToken* token);
-     bool finishMultiScriptsDecodeTask(JSContext* cx, JS::OffThreadToken* token, MutableHandle<ScriptVector> scripts);
--    JSObject* finishModuleParseTask(JSContext* cx, JS::OffThreadToken* token);
-+    JSScript* finishModuleParseTask(JSContext* cx, JS::OffThreadToken* token);
- 
- #if defined(JS_BUILD_BINAST)
-     JSScript* finishBinASTDecodeTask(JSContext* cx, JS::OffThreadToken* token);
- #endif
- 
-     bool hasActiveThreads(const AutoLockHelperThreadState&);
-     void waitForAllThreads();
-     void waitForAllThreadsLocked(AutoLockHelperThreadState&);
-diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp
---- a/js/src/vm/Interpreter.cpp
-+++ b/js/src/vm/Interpreter.cpp
-@@ -4398,17 +4398,18 @@ CASE(JSOP_NEWTARGET)
-     MOZ_ASSERT(REGS.sp[-1].isObject() || REGS.sp[-1].isUndefined());
- END_CASE(JSOP_NEWTARGET)
- 
- CASE(JSOP_IMPORTMETA)
- {
-     ReservedRooted<JSObject*> module(&rootObject0, GetModuleObjectForScript(script));
-     MOZ_ASSERT(module);
- 
--    JSObject* metaObject = GetOrCreateModuleMetaObject(cx, module);
-+    ReservedRooted<JSScript*> script(&rootScript0, module->as<ModuleObject>().script());
-+    JSObject* metaObject = GetOrCreateModuleMetaObject(cx, script);
-     if (!metaObject)
-         goto error;
- 
-     PUSH_OBJECT(*metaObject);
- }
- END_CASE(JSOP_NEWTARGET)
- 
- CASE(JSOP_SUPERFUN)
-diff --git a/js/src/vm/Realm.cpp b/js/src/vm/Realm.cpp
---- a/js/src/vm/Realm.cpp
-+++ b/js/src/vm/Realm.cpp
-@@ -1016,16 +1016,22 @@ JS::GetCurrentRealmOrNull(JSContext* cx)
- }
- 
- JS_PUBLIC_API(JS::Realm*)
- JS::GetObjectRealmOrNull(JSObject* obj)
- {
-     return IsCrossCompartmentWrapper(obj) ? nullptr : obj->nonCCWRealm();
- }
- 
-+JS_PUBLIC_API(JS::Realm*)
-+JS::GetScriptRealm(JSScript* script)
-+{
-+    return script->realm();
-+}
-+
- JS_PUBLIC_API(void*)
- JS::GetRealmPrivate(JS::Realm* realm)
- {
-     return realm->realmPrivate();
- }
- 
- JS_PUBLIC_API(void)
- JS::SetRealmPrivate(JS::Realm* realm, void* data)
-diff --git a/js/src/vm/SelfHosting.cpp b/js/src/vm/SelfHosting.cpp
---- a/js/src/vm/SelfHosting.cpp
-+++ b/js/src/vm/SelfHosting.cpp
-@@ -2146,27 +2146,28 @@ intrinsic_HostResolveImportedModule(JSCo
-     RootedString specifier(cx, args[1].toString());
- 
-     JS::ModuleResolveHook moduleResolveHook = cx->runtime()->moduleResolveHook;
-     if (!moduleResolveHook) {
-         JS_ReportErrorASCII(cx, "Module resolve hook not set");
-         return false;
-     }
- 
--    RootedObject result(cx);
--    result = moduleResolveHook(cx, module, specifier);
-+    RootedScript script(cx, module->script());
-+    RootedScript result(cx);
-+    result = moduleResolveHook(cx, script, specifier);
-     if (!result)
-         return false;
- 
--    if (!result->is<ModuleObject>()) {
--        JS_ReportErrorASCII(cx, "Module resolve hook did not return Module object");
-+    if (!result->module()) {
-+        JS_ReportErrorASCII(cx, "Module resolve hook did not return a module script");
-         return false;
-     }
- 
--    args.rval().setObject(*result);
-+    args.rval().setObject(*result->module());
-     return true;
- }
- 
- static bool
- intrinsic_CreateImportBinding(JSContext* cx, unsigned argc, Value* vp)
- {
-     CallArgs args = CallArgsFromVp(argc, vp);
-     MOZ_ASSERT(args.length() == 4);
-diff --git a/js/xpconnect/src/XPCJSRuntime.cpp b/js/xpconnect/src/XPCJSRuntime.cpp
---- a/js/xpconnect/src/XPCJSRuntime.cpp
-+++ b/js/xpconnect/src/XPCJSRuntime.cpp
-@@ -436,16 +436,23 @@ Scriptability::SetDocShellAllowsScript(b
- 
- /* static */
- Scriptability&
- Scriptability::Get(JSObject* aScope)
- {
-     return RealmPrivate::Get(aScope)->scriptability;
- }
- 
-+/* static */
-+Scriptability&
-+Scriptability::Get(JSScript* aScript)
-+{
-+    return RealmPrivate::Get(aScript)->scriptability;
-+}
-+
- bool
- IsContentXBLCompartment(JS::Compartment* compartment)
- {
-     // We always eagerly create compartment privates for content XBL compartments.
-     CompartmentPrivate* priv = CompartmentPrivate::Get(compartment);
-     return priv && priv->isContentXBLCompartment;
- }
- 
-diff --git a/js/xpconnect/src/xpcprivate.h b/js/xpconnect/src/xpcprivate.h
---- a/js/xpconnect/src/xpcprivate.h
-+++ b/js/xpconnect/src/xpcprivate.h
-@@ -2986,16 +2986,23 @@ public:
-     // cross-compartment wrapper, as CCWs aren't dedicated to a particular
-     // realm.
-     static RealmPrivate* Get(JSObject* object)
-     {
-         JS::Realm* realm = JS::GetObjectRealmOrNull(object);
-         return Get(realm);
-     }
- 
-+    // Get the RealmPrivate for a given script.
-+    static RealmPrivate* Get(JSScript* script)
-+    {
-+        JS::Realm* realm = JS::GetScriptRealm(script);
-+        return Get(realm);
-+    }
-+
-     // The scriptability of this realm.
-     Scriptability scriptability;
- 
-     // Our XPCWrappedNativeScope. This is non-null if and only if this is an
-     // XPConnect realm.
-     XPCWrappedNativeScope* scope;
- 
-     const nsACString& GetLocation() {
-diff --git a/js/xpconnect/src/xpcpublic.h b/js/xpconnect/src/xpcpublic.h
---- a/js/xpconnect/src/xpcpublic.h
-+++ b/js/xpconnect/src/xpcpublic.h
-@@ -49,16 +49,17 @@ public:
-     bool Allowed();
-     bool IsImmuneToScriptPolicy();
- 
-     void Block();
-     void Unblock();
-     void SetDocShellAllowsScript(bool aAllowed);
- 
-     static Scriptability& Get(JSObject* aScope);
-+    static Scriptability& Get(JSScript* aScript);
- 
- private:
-     // Whenever a consumer wishes to prevent script from running on a global,
-     // it increments this value with a call to Block(). When it wishes to
-     // re-enable it (if ever), it decrements this value with a call to Unblock().
-     // Script may not run if this value is non-zero.
-     uint32_t mScriptBlocks;
- 

+ 0 - 122
frg/work-js/mozilla-release/patches/mozilla-central-push_430690.patch

@@ -1,122 +0,0 @@
-# HG changeset patch
-# User Andre Bargull <andre.bargull@gmail.com>
-# Date 1533569682 25200
-#      Mon Aug 06 08:34:42 2018 -0700
-# Node ID aef4c2ae8559318068192b484aa82e1d6851bbd7
-# Parent  27adb1a1c96195ec919cdaea57349d4d21483de0
-Bug 1480963: Remove initialized-length is equal to capacity check in getDenseInitializedLength. r=jandem
-
-diff --git a/js/src/vm/JSObject-inl.h b/js/src/vm/JSObject-inl.h
---- a/js/src/vm/JSObject-inl.h
-+++ b/js/src/vm/JSObject-inl.h
-@@ -206,16 +206,23 @@ inline bool
- js::IsExtensible(JSContext* cx, HandleObject obj, bool* extensible)
- {
-     if (obj->is<ProxyObject>()) {
-         MOZ_ASSERT(!cx->helperThread());
-         return Proxy::isExtensible(cx, obj, extensible);
-     }
- 
-     *extensible = obj->nonProxyIsExtensible();
-+
-+    // If the following assertion fails, there's somewhere else a missing
-+    // call to shrinkCapacityToInitializedLength() which needs to be found and
-+    // fixed.
-+    MOZ_ASSERT_IF(obj->isNative() && !*extensible,
-+                  obj->as<NativeObject>().getDenseInitializedLength() ==
-+                  obj->as<NativeObject>().getDenseCapacity());
-     return true;
- }
- 
- inline bool
- js::HasProperty(JSContext* cx, HandleObject obj, PropertyName* name, bool* found)
- {
-     RootedId id(cx, NameToId(name));
-     return HasProperty(cx, obj, id, found);
-diff --git a/js/src/vm/JSObject.cpp b/js/src/vm/JSObject.cpp
---- a/js/src/vm/JSObject.cpp
-+++ b/js/src/vm/JSObject.cpp
-@@ -2732,18 +2732,26 @@ js::SetPrototype(JSContext* cx, HandleOb
- }
- 
- bool
- js::PreventExtensions(JSContext* cx, HandleObject obj, ObjectOpResult& result)
- {
-     if (obj->is<ProxyObject>())
-         return js::Proxy::preventExtensions(cx, obj, result);
- 
--    if (!obj->nonProxyIsExtensible())
-+    if (!obj->nonProxyIsExtensible()) {
-+        // If the following assertion fails, there's somewhere else a missing
-+        // call to shrinkCapacityToInitializedLength() which needs to be found
-+        // and fixed.
-+        MOZ_ASSERT_IF(obj->isNative(),
-+                      obj->as<NativeObject>().getDenseInitializedLength() ==
-+                      obj->as<NativeObject>().getDenseCapacity());
-+
-         return result.succeed();
-+    }
- 
-     if (!MaybeConvertUnboxedObjectToNative(cx, obj))
-         return false;
- 
-     if (obj->isNative()) {
-         // Force lazy properties to be resolved.
-         if (!ResolveLazyProperties(cx, obj.as<NativeObject>()))
-             return false;
-diff --git a/js/src/vm/NativeObject.cpp b/js/src/vm/NativeObject.cpp
---- a/js/src/vm/NativeObject.cpp
-+++ b/js/src/vm/NativeObject.cpp
-@@ -964,17 +964,17 @@ NativeObject::growElements(JSContext* cx
- 
-     return true;
- }
- 
- void
- NativeObject::shrinkElements(JSContext* cx, uint32_t reqCapacity)
- {
-     MOZ_ASSERT(canHaveNonEmptyElements());
--    MOZ_ASSERT(reqCapacity >= getDenseInitializedLengthUnchecked());
-+    MOZ_ASSERT(reqCapacity >= getDenseInitializedLength());
- 
-     if (denseElementsAreCopyOnWrite())
-         MOZ_CRASH();
- 
-     if (!hasDynamicElements())
-         return;
- 
-     // If we have shifted elements, consider moving them.
-diff --git a/js/src/vm/NativeObject.h b/js/src/vm/NativeObject.h
---- a/js/src/vm/NativeObject.h
-+++ b/js/src/vm/NativeObject.h
-@@ -525,30 +525,17 @@ class NativeObject : public ShapedObject
-     }
-     const Value& getDenseElement(uint32_t idx) const {
-         MOZ_ASSERT(idx < getDenseInitializedLength());
-         return elements_[idx];
-     }
-     bool containsDenseElement(uint32_t idx) {
-         return idx < getDenseInitializedLength() && !elements_[idx].isMagic(JS_ELEMENTS_HOLE);
-     }
--
--  private:
--    uint32_t getDenseInitializedLengthUnchecked() const {
--        return getElementsHeader()->initializedLength;
--    }
--
--  public:
-     uint32_t getDenseInitializedLength() const {
--        // If the following assertion fails, there's somewhere else a missing
--        // call to shrinkCapacityToInitializedLength(). Good luck for the hunt
--        // and finding the offender!
--        MOZ_ASSERT_IF(!isExtensible(),
--                      getElementsHeader()->initializedLength == getElementsHeader()->capacity);
--
-         return getElementsHeader()->initializedLength;
-     }
-     uint32_t getDenseCapacity() const {
-         return getElementsHeader()->capacity;
-     }
- 
-     bool isSharedMemory() const {
-         return getElementsHeader()->isSharedMemory();

+ 0 - 47
frg/work-js/mozilla-release/patches/mozilla-central-push_430691.patch

@@ -1,47 +0,0 @@
-# HG changeset patch
-# User Andre Bargull <andre.bargull@gmail.com>
-# Date 1533569736 25200
-#      Mon Aug 06 08:35:36 2018 -0700
-# Node ID b20289e446893be662123b91104e35646408a578
-# Parent  aef4c2ae8559318068192b484aa82e1d6851bbd7
-Bug 1481032: Non-extensible arrays are already shrunk to capacity. r=jandem
-
-diff --git a/js/src/builtin/Array.cpp b/js/src/builtin/Array.cpp
---- a/js/src/builtin/Array.cpp
-+++ b/js/src/builtin/Array.cpp
-@@ -786,18 +786,22 @@ js::ArraySetLength(JSContext* cx, Handle
-             if (!arr->maybeCopyElementsForWrite(cx))
-                 return false;
- 
-             uint32_t oldCapacity = arr->getDenseCapacity();
-             uint32_t oldInitializedLength = arr->getDenseInitializedLength();
-             MOZ_ASSERT(oldCapacity >= oldInitializedLength);
-             if (oldInitializedLength > newLen)
-                 arr->setDenseInitializedLengthMaybeNonExtensible(cx, newLen);
--            if (oldCapacity > newLen)
--                arr->shrinkElements(cx, newLen);
-+            if (oldCapacity > newLen) {
-+                if (arr->isExtensible())
-+                    arr->shrinkElements(cx, newLen);
-+                else
-+                    MOZ_ASSERT(arr->getDenseInitializedLength() == arr->getDenseCapacity());
-+            }
- 
-             // We've done the work of deleting any dense elements needing
-             // deletion, and there are no sparse elements.  Thus we can skip
-             // straight to defining the length.
-             break;
-         }
- 
-         // Step 15.
-diff --git a/js/src/jit-test/tests/auto-regress/bug1481032.js b/js/src/jit-test/tests/auto-regress/bug1481032.js
-new file mode 100644
---- /dev/null
-+++ b/js/src/jit-test/tests/auto-regress/bug1481032.js
-@@ -0,0 +1,6 @@
-+x = [];
-+x[6] = 0;
-+Object.preventExtensions(x);
-+
-+// Don't assert.
-+x.length = 1;

+ 0 - 216
frg/work-js/mozilla-release/patches/mozilla-central-push_430692.patch

@@ -1,216 +0,0 @@
-# HG changeset patch
-# User Andre Bargull <andre.bargull@gmail.com>
-# Date 1533570223 25200
-#      Mon Aug 06 08:43:43 2018 -0700
-# Node ID df05fdfe1af8936b52613cd05b81948846a9bad6
-# Parent  b20289e446893be662123b91104e35646408a578
-Bug 1481248: Use strict instead of sloppy equals for 'throw' method check in yield*. r=arai
-
-diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp
---- a/js/src/frontend/BytecodeEmitter.cpp
-+++ b/js/src/frontend/BytecodeEmitter.cpp
-@@ -6065,21 +6065,23 @@ BytecodeEmitter::emitAwaitInScope(Emitte
- }
- 
- bool
- BytecodeEmitter::emitYieldStar(ParseNode* iter)
- {
-     MOZ_ASSERT(sc->isFunctionBox());
-     MOZ_ASSERT(sc->asFunctionBox()->isGenerator());
- 
--    bool isAsyncGenerator = sc->asFunctionBox()->isAsync();
-+    IteratorKind iterKind = sc->asFunctionBox()->isAsync()
-+                            ? IteratorKind::Async
-+                            : IteratorKind::Sync;
- 
-     if (!emitTree(iter))                                  // ITERABLE
-         return false;
--    if (isAsyncGenerator) {
-+    if (iterKind == IteratorKind::Async) {
-         if (!emitAsyncIterator())                         // NEXT ITER
-             return false;
-     } else {
-         if (!emitIterator())                              // NEXT ITER
-             return false;
-     }
- 
-     // Initial send value is undefined.
-@@ -6097,77 +6099,62 @@ BytecodeEmitter::emitYieldStar(ParseNode
- 
-     JumpTarget tryStart{ offset() };
-     if (!tryCatch.emitTry())                              // NEXT ITER RESULT
-         return false;
- 
-     MOZ_ASSERT(this->stackDepth == startDepth);
- 
-     // 11.4.3.7 AsyncGeneratorYield step 5.
--    if (isAsyncGenerator) {
-+    if (iterKind == IteratorKind::Async) {
-         if (!emitAwaitInInnermostScope())                 // NEXT ITER RESULT
-             return false;
-     }
- 
-     // Load the generator object.
-     if (!emitGetDotGeneratorInInnermostScope())           // NEXT ITER RESULT GENOBJ
-         return false;
- 
-     // Yield RESULT as-is, without re-boxing.
-     if (!emitYieldOp(JSOP_YIELD))                         // NEXT ITER RECEIVED
-         return false;
- 
-     if (!tryCatch.emitCatch())                            // NEXT ITER RESULT
-         return false;
- 
--    stackDepth = startDepth;                              // NEXT ITER RESULT
-+    MOZ_ASSERT(stackDepth == startDepth);
-+
-     if (!emit1(JSOP_EXCEPTION))                           // NEXT ITER RESULT EXCEPTION
-         return false;
-     if (!emitDupAt(2))                                    // NEXT ITER RESULT EXCEPTION ITER
-         return false;
-     if (!emit1(JSOP_DUP))                                 // NEXT ITER RESULT EXCEPTION ITER ITER
-         return false;
-     if (!emitAtomOp(cx->names().throw_, JSOP_CALLPROP))   // NEXT ITER RESULT EXCEPTION ITER THROW
-         return false;
--    if (!emit1(JSOP_DUP))                                 // NEXT ITER RESULT EXCEPTION ITER THROW THROW
--        return false;
--    if (!emit1(JSOP_UNDEFINED))                           // NEXT ITER RESULT EXCEPTION ITER THROW THROW UNDEFINED
--        return false;
--    if (!emit1(JSOP_EQ))                                  // NEXT ITER RESULT EXCEPTION ITER THROW ?EQL
--        return false;
--
--    InternalIfEmitter ifThrowMethodIsNotDefined(this);
--    if (!ifThrowMethodIsNotDefined.emitThen())            // NEXT ITER RESULT EXCEPTION ITER THROW
--        return false;
-+
-     savedDepthTemp = stackDepth;
--    if (!emit1(JSOP_POP))                                 // NEXT ITER RESULT EXCEPTION ITER
--        return false;
--    // ES 14.4.13, YieldExpression : yield * AssignmentExpression, step 5.b.iii.2
--    //
--    // If the iterator does not have a "throw" method, it calls IteratorClose
--    // and then throws a TypeError.
--    IteratorKind iterKind = isAsyncGenerator ? IteratorKind::Async : IteratorKind::Sync;
--    if (!emitIteratorCloseInInnermostScope(iterKind))     // NEXT ITER RESULT EXCEPTION
--        return false;
--    if (!emitUint16Operand(JSOP_THROWMSG, JSMSG_ITERATOR_NO_THROW)) // throw
--        return false;
--    stackDepth = savedDepthTemp;
--    if (!ifThrowMethodIsNotDefined.emitEnd())             // NEXT ITER OLDRESULT EXCEPTION ITER THROW
--        return false;
-+    InternalIfEmitter ifThrowMethodIsNotDefined(this);
-+    if (!emitPushNotUndefinedOrNull())                    // NEXT ITER RESULT EXCEPTION ITER THROW NOT-UNDEF-OR-NULL
-+        return false;
-+
-+    if (!ifThrowMethodIsNotDefined.emitThenElse())        // NEXT ITER RESULT EXCEPTION ITER THROW
-+        return false;
-+
-     // ES 14.4.13, YieldExpression : yield * AssignmentExpression, step 5.b.iii.4.
-     // RESULT = ITER.throw(EXCEPTION)                     // NEXT ITER OLDRESULT EXCEPTION ITER THROW
-     if (!emit1(JSOP_SWAP))                                // NEXT ITER OLDRESULT EXCEPTION THROW ITER
-         return false;
-     if (!emit2(JSOP_PICK, 2))                             // NEXT ITER OLDRESULT THROW ITER EXCEPTION
-         return false;
-     if (!emitCall(JSOP_CALL, 1, iter))                    // NEXT ITER OLDRESULT RESULT
-         return false;
-     checkTypeSet(JSOP_CALL);
- 
--    if (isAsyncGenerator) {
-+    if (iterKind == IteratorKind::Async) {
-         if (!emitAwaitInInnermostScope())                 // NEXT ITER OLDRESULT RESULT
-             return false;
-     }
- 
-     if (!emitCheckIsObj(CheckIsObjectKind::IteratorThrow)) // NEXT ITER OLDRESULT RESULT
-         return false;
-     if (!emit1(JSOP_SWAP))                                // NEXT ITER RESULT OLDRESULT
-         return false;
-@@ -6177,16 +6164,36 @@ BytecodeEmitter::emitYieldStar(ParseNode
-     JumpList checkResult;
-     // ES 14.4.13, YieldExpression : yield * AssignmentExpression, step 5.b.ii.
-     //
-     // Note that there is no GOSUB to the finally block here. If the iterator has a
-     // "throw" method, it does not perform IteratorClose.
-     if (!emitJump(JSOP_GOTO, &checkResult))               // goto checkResult
-         return false;
- 
-+    stackDepth = savedDepthTemp;
-+    if (!ifThrowMethodIsNotDefined.emitElse())            // NEXT ITER RESULT EXCEPTION ITER THROW
-+        return false;
-+
-+    if (!emit1(JSOP_POP))                                 // NEXT ITER RESULT EXCEPTION ITER
-+        return false;
-+    // ES 14.4.13, YieldExpression : yield * AssignmentExpression, step 5.b.iii.2
-+    //
-+    // If the iterator does not have a "throw" method, it calls IteratorClose
-+    // and then throws a TypeError.
-+    if (!emitIteratorCloseInInnermostScope(iterKind))     // NEXT ITER RESULT EXCEPTION
-+        return false;
-+    if (!emitUint16Operand(JSOP_THROWMSG, JSMSG_ITERATOR_NO_THROW)) // throw
-+        return false;
-+
-+    stackDepth = savedDepthTemp;
-+    if (!ifThrowMethodIsNotDefined.emitEnd())
-+        return false;
-+
-+    stackDepth = startDepth;
-     if (!tryCatch.emitFinally())
-          return false;
- 
-     // ES 14.4.13, yield * AssignmentExpression, step 5.c
-     //
-     // Call iterator.return() for receiving a "forced return" completion from
-     // the generator.
- 
-@@ -6298,17 +6305,17 @@ BytecodeEmitter::emitYieldStar(ParseNode
-     if (!emit1(JSOP_DUP2))                                       // RECEIVED NEXT ITER NEXT ITER
-         return false;
-     if (!emit2(JSOP_PICK, 4))                                    // NEXT ITER NEXT ITER RECEIVED
-         return false;
-     if (!emitCall(JSOP_CALL, 1, iter))                           // NEXT ITER RESULT
-         return false;
-     checkTypeSet(JSOP_CALL);
- 
--    if (isAsyncGenerator) {
-+    if (iterKind == IteratorKind::Async) {
-         if (!emitAwaitInInnermostScope())                        // NEXT ITER RESULT RESULT
-             return false;
-     }
- 
-     if (!emitCheckIsObj(CheckIsObjectKind::IteratorNext))        // NEXT ITER RESULT
-         return false;
-     MOZ_ASSERT(this->stackDepth == startDepth);
- 
-diff --git a/js/src/tests/non262/generators/yield-star-throw-htmldda.js b/js/src/tests/non262/generators/yield-star-throw-htmldda.js
-new file mode 100644
---- /dev/null
-+++ b/js/src/tests/non262/generators/yield-star-throw-htmldda.js
-@@ -0,0 +1,28 @@
-+function* g(iter) {
-+    yield* iter;
-+}
-+
-+var calledReturn = false;
-+
-+var it = g({
-+    [Symbol.iterator]() {
-+        return this;
-+    },
-+    next() {
-+        return {done: false};
-+    },
-+    throw: createIsHTMLDDA(),
-+    return() {
-+        calledReturn = true;
-+        return {done: false};
-+    }
-+});
-+
-+it.next();
-+
-+assertThrowsInstanceOf(() => it.throw(""), TypeError);
-+
-+assertEq(calledReturn, false);
-+
-+if (typeof reportCompare === "function")
-+    reportCompare(0, 0);

+ 0 - 62
frg/work-js/mozilla-release/patches/mozilla-central-push_430732.patch

@@ -1,62 +0,0 @@
-# HG changeset patch
-# User Nathan Froyd <froydnj@mozilla.com>
-# Date 1533760625 14400
-#      Wed Aug 08 16:37:05 2018 -0400
-# Node ID 4a6a97131d1835d837a08cf46b5d35c69b7120fd
-# Parent  686d11ab65e47d8c0b58b7ca9e3d372b8898cc1e
-Bug 1481505 - add aarch64 bits to DEFINES and DSO_LDOPTS; r=dmajor
-
-Not having _ARM64_ in DEFINES makes any number of things go wrong.
-
-diff --git a/js/src/old-configure.in b/js/src/old-configure.in
---- a/js/src/old-configure.in
-+++ b/js/src/old-configure.in
-@@ -847,16 +847,22 @@ case "$target" in
-     	AC_DEFINE(_X86_)
- 	;;
-     x86_64-*)
-         if test -n "$_WIN32_MSVC"; then
-             DSO_LDOPTS="$DSO_LDOPTS -MACHINE:X64"
-         fi
-         AC_DEFINE(_AMD64_)
-         ;;
-+    aarch64-*)
-+        if test -n "$_WIN32_MSVC"; then
-+            DSO_LDOPTS="$DSO_LDOPTS -MACHINE:ARM64"
-+        fi
-+        AC_DEFINE(_ARM64_)
-+        ;;
-     *)
-     	AC_DEFINE(_CPU_ARCH_NOT_DEFINED)
- 	;;
-     esac
-     ;;
- 
- *-netbsd*)
-     DSO_CFLAGS=''
-diff --git a/old-configure.in b/old-configure.in
---- a/old-configure.in
-+++ b/old-configure.in
-@@ -1097,16 +1097,22 @@ case "$target" in
-         AC_DEFINE(_X86_)
-         ;;
-     x86_64-*)
-         if test -n "$_WIN32_MSVC"; then
-             DSO_LDOPTS="$DSO_LDOPTS -MACHINE:X64"
-         fi
-         AC_DEFINE(_AMD64_)
-         ;;
-+    aarch64-*)
-+        if test -n "$_WIN32_MSVC"; then
-+            DSO_LDOPTS="$DSO_LDOPTS -MACHINE:ARM64"
-+        fi
-+        AC_DEFINE(_ARM64_)
-+        ;;
-     *)
-         AC_DEFINE(_CPU_ARCH_NOT_DEFINED)
-         ;;
-     esac
-     ;;
- 
- *-netbsd*)
-     DSO_CFLAGS=''

+ 0 - 945
frg/work-js/mozilla-release/patches/mozilla-central-push_430740.patch

@@ -1,945 +0,0 @@
-# HG changeset patch
-# User Ted Campbell <tcampbell@mozilla.com>
-# Date 1533186313 14400
-#      Thu Aug 02 01:05:13 2018 -0400
-# Node ID ebac10c8c8b9ab70465097b02de34eee86bf41be
-# Parent  044705c4d308da03fd8f89f42497ffd7b17614f1
-Bug 1479900 - Part 1: Use accessor methods for JSString::flags/length. r=sfink
-
-Add accessor methods so that underlying storage strategy can be changed
-later. This patch should not change current behaviour.
-
-MozReview-Commit-ID: IRA53TQShe6
-
-diff --git a/js/public/HeapAPI.h b/js/public/HeapAPI.h
---- a/js/public/HeapAPI.h
-+++ b/js/public/HeapAPI.h
-@@ -209,33 +209,40 @@ struct String
-     static const uint32_t LINEAR_BIT       = JS_BIT(1);
-     static const uint32_t INLINE_CHARS_BIT = JS_BIT(3);
-     static const uint32_t LATIN1_CHARS_BIT = JS_BIT(6);
-     static const uint32_t EXTERNAL_FLAGS   = LINEAR_BIT | NON_ATOM_BIT | JS_BIT(5);
-     static const uint32_t TYPE_FLAGS_MASK  = JS_BIT(6) - 1;
-     static const uint32_t PERMANENT_ATOM_MASK    = NON_ATOM_BIT | JS_BIT(5);
-     static const uint32_t PERMANENT_ATOM_FLAGS   = JS_BIT(5);
- 
--    uint32_t flags;
--    uint32_t length;
-+    uint32_t flags_;
-+    uint32_t length_;
-     union {
-         const JS::Latin1Char* nonInlineCharsLatin1;
-         const char16_t* nonInlineCharsTwoByte;
-         JS::Latin1Char inlineStorageLatin1[1];
-         char16_t inlineStorageTwoByte[1];
-     };
-     const JSStringFinalizer* externalFinalizer;
- 
-+    inline uint32_t flags() const {
-+        return flags_;
-+    }
-+    inline uint32_t length() const {
-+        return length_;
-+    }
-+
-     static bool nurseryCellIsString(const js::gc::Cell* cell) {
-         MOZ_ASSERT(IsInsideNursery(cell));
--        return reinterpret_cast<const String*>(cell)->flags & NON_ATOM_BIT;
-+        return reinterpret_cast<const String*>(cell)->flags() & NON_ATOM_BIT;
-     }
- 
-     static bool isPermanentAtom(const js::gc::Cell* cell) {
--        uint32_t flags = reinterpret_cast<const String*>(cell)->flags;
-+        uint32_t flags = reinterpret_cast<const String*>(cell)->flags();
-         return (flags & PERMANENT_ATOM_MASK) == PERMANENT_ATOM_FLAGS;
-     }
- };
- 
- struct Symbol {
-     uint32_t code_;
-     static const uint32_t WellKnownAPILimit = 0x80000000;
- 
-diff --git a/js/src/gc/Marking-inl.h b/js/src/gc/Marking-inl.h
---- a/js/src/gc/Marking-inl.h
-+++ b/js/src/gc/Marking-inl.h
-@@ -94,17 +94,17 @@ RelocationOverlay::forwardTo(Cell* cell)
- {
-     MOZ_ASSERT(!isForwarded());
-     // The location of magic_ is important because it must never be valid to see
-     // the value Relocated there in a GC thing that has not been moved.
-     static_assert(offsetof(RelocationOverlay, magic_) == offsetof(JSObject, group_) + sizeof(uint32_t),
-                   "RelocationOverlay::magic_ is in the wrong location");
-     static_assert(offsetof(RelocationOverlay, magic_) == offsetof(js::Shape, base_) + sizeof(uint32_t),
-                   "RelocationOverlay::magic_ is in the wrong location");
--    static_assert(offsetof(RelocationOverlay, magic_) == offsetof(JSString, d.u1.length),
-+    static_assert(offsetof(RelocationOverlay, magic_) == offsetof(JSString, d.u1.length_),
-                   "RelocationOverlay::magic_ is in the wrong location");
-     magic_ = Relocated;
-     newLocation_ = cell;
- }
- 
- #ifdef JSGC_HASH_TABLE_CHECKS
- 
- template <typename T>
-diff --git a/js/src/jsfriendapi.h b/js/src/jsfriendapi.h
---- a/js/src/jsfriendapi.h
-+++ b/js/src/jsfriendapi.h
-@@ -790,77 +790,77 @@ GetObjectSlot(JSObject* obj, size_t slot
- {
-     MOZ_ASSERT(slot < GetObjectSlotSpan(obj));
-     return reinterpret_cast<const shadow::Object*>(obj)->slotRef(slot);
- }
- 
- MOZ_ALWAYS_INLINE size_t
- GetAtomLength(JSAtom* atom)
- {
--    return reinterpret_cast<JS::shadow::String*>(atom)->length;
-+    return reinterpret_cast<JS::shadow::String*>(atom)->length();
- }
- 
- static const uint32_t MaxStringLength = (1 << 28) - 1;
- 
- MOZ_ALWAYS_INLINE size_t
- GetStringLength(JSString* s)
- {
--    return reinterpret_cast<JS::shadow::String*>(s)->length;
-+    return reinterpret_cast<JS::shadow::String*>(s)->length();
- }
- 
- MOZ_ALWAYS_INLINE size_t
- GetFlatStringLength(JSFlatString* s)
- {
--    return reinterpret_cast<JS::shadow::String*>(s)->length;
-+    return reinterpret_cast<JS::shadow::String*>(s)->length();
- }
- 
- MOZ_ALWAYS_INLINE size_t
- GetLinearStringLength(JSLinearString* s)
- {
--    return reinterpret_cast<JS::shadow::String*>(s)->length;
-+    return reinterpret_cast<JS::shadow::String*>(s)->length();
- }
- 
- MOZ_ALWAYS_INLINE bool
- LinearStringHasLatin1Chars(JSLinearString* s)
- {
--    return reinterpret_cast<JS::shadow::String*>(s)->flags & JS::shadow::String::LATIN1_CHARS_BIT;
-+    return reinterpret_cast<JS::shadow::String*>(s)->flags() & JS::shadow::String::LATIN1_CHARS_BIT;
- }
- 
- MOZ_ALWAYS_INLINE bool
- AtomHasLatin1Chars(JSAtom* atom)
- {
--    return reinterpret_cast<JS::shadow::String*>(atom)->flags & JS::shadow::String::LATIN1_CHARS_BIT;
-+    return reinterpret_cast<JS::shadow::String*>(atom)->flags() & JS::shadow::String::LATIN1_CHARS_BIT;
- }
- 
- MOZ_ALWAYS_INLINE bool
- StringHasLatin1Chars(JSString* s)
- {
--    return reinterpret_cast<JS::shadow::String*>(s)->flags & JS::shadow::String::LATIN1_CHARS_BIT;
-+    return reinterpret_cast<JS::shadow::String*>(s)->flags() & JS::shadow::String::LATIN1_CHARS_BIT;
- }
- 
- MOZ_ALWAYS_INLINE const JS::Latin1Char*
- GetLatin1LinearStringChars(const JS::AutoRequireNoGC& nogc, JSLinearString* linear)
- {
-     MOZ_ASSERT(LinearStringHasLatin1Chars(linear));
- 
-     using JS::shadow::String;
-     String* s = reinterpret_cast<String*>(linear);
--    if (s->flags & String::INLINE_CHARS_BIT)
-+    if (s->flags() & String::INLINE_CHARS_BIT)
-         return s->inlineStorageLatin1;
-     return s->nonInlineCharsLatin1;
- }
- 
- MOZ_ALWAYS_INLINE const char16_t*
- GetTwoByteLinearStringChars(const JS::AutoRequireNoGC& nogc, JSLinearString* linear)
- {
-     MOZ_ASSERT(!LinearStringHasLatin1Chars(linear));
- 
-     using JS::shadow::String;
-     String* s = reinterpret_cast<String*>(linear);
--    if (s->flags & String::INLINE_CHARS_BIT)
-+    if (s->flags() & String::INLINE_CHARS_BIT)
-         return s->inlineStorageTwoByte;
-     return s->nonInlineCharsTwoByte;
- }
- 
- MOZ_ALWAYS_INLINE JSLinearString*
- AtomToLinearString(JSAtom* atom)
- {
-     return reinterpret_cast<JSLinearString*>(atom);
-@@ -891,34 +891,34 @@ GetTwoByteAtomChars(const JS::AutoRequir
- }
- 
- MOZ_ALWAYS_INLINE bool
- IsExternalString(JSString* str, const JSStringFinalizer** fin, const char16_t** chars)
- {
-     using JS::shadow::String;
-     String* s = reinterpret_cast<String*>(str);
- 
--    if ((s->flags & String::TYPE_FLAGS_MASK) != String::EXTERNAL_FLAGS)
-+    if ((s->flags() & String::TYPE_FLAGS_MASK) != String::EXTERNAL_FLAGS)
-         return false;
- 
-     MOZ_ASSERT(JS_IsExternalString(str));
-     *fin = s->externalFinalizer;
-     *chars = s->nonInlineCharsTwoByte;
-     return true;
- }
- 
- JS_FRIEND_API(JSLinearString*)
- StringToLinearStringSlow(JSContext* cx, JSString* str);
- 
- MOZ_ALWAYS_INLINE JSLinearString*
- StringToLinearString(JSContext* cx, JSString* str)
- {
-     using JS::shadow::String;
-     String* s = reinterpret_cast<String*>(str);
--    if (MOZ_UNLIKELY(!(s->flags & String::LINEAR_BIT)))
-+    if (MOZ_UNLIKELY(!(s->flags() & String::LINEAR_BIT)))
-         return StringToLinearStringSlow(cx, str);
-     return reinterpret_cast<JSLinearString*>(str);
- }
- 
- template<typename CharType>
- MOZ_ALWAYS_INLINE void
- CopyLinearStringChars(CharType* dest, JSLinearString* s, size_t len, size_t start = 0);
- 
-diff --git a/js/src/vm/StringType-inl.h b/js/src/vm/StringType-inl.h
---- a/js/src/vm/StringType-inl.h
-+++ b/js/src/vm/StringType-inl.h
-@@ -92,23 +92,37 @@ JSString::validateLength(JSContext* mayb
-     if (MOZ_UNLIKELY(length > JSString::MAX_LENGTH)) {
-         js::ReportAllocationOverflow(maybecx);
-         return false;
-     }
- 
-     return true;
- }
- 
-+template<>
-+MOZ_ALWAYS_INLINE const char16_t*
-+JSString::nonInlineCharsRaw() const
-+{
-+    return d.s.u2.nonInlineCharsTwoByte;
-+}
-+
-+template<>
-+MOZ_ALWAYS_INLINE const JS::Latin1Char*
-+JSString::nonInlineCharsRaw() const
-+{
-+    return d.s.u2.nonInlineCharsLatin1;
-+}
-+
- MOZ_ALWAYS_INLINE void
- JSRope::init(JSContext* cx, JSString* left, JSString* right, size_t length)
- {
--    d.u1.length = length;
--    d.u1.flags = INIT_ROPE_FLAGS;
-     if (left->hasLatin1Chars() && right->hasLatin1Chars())
--        d.u1.flags |= LATIN1_CHARS_BIT;
-+        setLengthAndFlags(length, INIT_ROPE_FLAGS | LATIN1_CHARS_BIT);
-+    else
-+        setLengthAndFlags(length, INIT_ROPE_FLAGS);
-     d.s.u2.left = left;
-     d.s.u3.right = right;
- 
-     // Post-barrier by inserting into the whole cell buffer if either
-     // this -> left or this -> right is a tenured -> nursery edge.
-     if (isTenured()) {
-         js::gc::StoreBuffer* sb = left->storeBuffer();
-         if (!sb)
-@@ -134,23 +148,22 @@ JSRope::new_(JSContext* cx,
-     return str;
- }
- 
- MOZ_ALWAYS_INLINE void
- JSDependentString::init(JSContext* cx, JSLinearString* base, size_t start,
-                         size_t length)
- {
-     MOZ_ASSERT(start + length <= base->length());
--    d.u1.length = length;
-     JS::AutoCheckCannotGC nogc;
-     if (base->hasLatin1Chars()) {
--        d.u1.flags = DEPENDENT_FLAGS | LATIN1_CHARS_BIT;
-+        setLengthAndFlags(length, DEPENDENT_FLAGS | LATIN1_CHARS_BIT);
-         d.s.u2.nonInlineCharsLatin1 = base->latin1Chars(nogc) + start;
-     } else {
--        d.u1.flags = DEPENDENT_FLAGS;
-+        setLengthAndFlags(length, DEPENDENT_FLAGS);
-         d.s.u2.nonInlineCharsTwoByte = base->twoByteChars(nogc) + start;
-     }
-     d.s.u3.base = base;
-     if (isTenured() && !base->isTenured())
-         base->storeBuffer()->putWholeCell(this);
- }
- 
- MOZ_ALWAYS_INLINE JSLinearString*
-@@ -201,26 +214,24 @@ JSDependentString::new_(JSContext* cx, J
-         return nullptr;
-     str->init(cx, base, start, length);
-     return str;
- }
- 
- MOZ_ALWAYS_INLINE void
- JSFlatString::init(const char16_t* chars, size_t length)
- {
--    d.u1.length = length;
--    d.u1.flags = INIT_FLAT_FLAGS;
-+    setLengthAndFlags(length, INIT_FLAT_FLAGS);
-     d.s.u2.nonInlineCharsTwoByte = chars;
- }
- 
- MOZ_ALWAYS_INLINE void
- JSFlatString::init(const JS::Latin1Char* chars, size_t length)
- {
--    d.u1.length = length;
--    d.u1.flags = INIT_FLAT_FLAGS | LATIN1_CHARS_BIT;
-+    setLengthAndFlags(length, INIT_FLAT_FLAGS | LATIN1_CHARS_BIT);
-     d.s.u2.nonInlineCharsLatin1 = chars;
- }
- 
- template <js::AllowGC allowGC, typename CharT>
- MOZ_ALWAYS_INLINE JSFlatString*
- JSFlatString::new_(JSContext* cx, const CharT* chars, size_t length)
- {
-     MOZ_ASSERT(chars[length] == CharT(0));
-@@ -289,58 +300,53 @@ JSFatInlineString::new_(JSContext* cx)
-     return js::Allocate<JSFatInlineString, allowGC>(cx, js::gc::DefaultHeap);
- }
- 
- template<>
- MOZ_ALWAYS_INLINE JS::Latin1Char*
- JSThinInlineString::init<JS::Latin1Char>(size_t length)
- {
-     MOZ_ASSERT(lengthFits<JS::Latin1Char>(length));
--    d.u1.length = length;
--    d.u1.flags = INIT_THIN_INLINE_FLAGS | LATIN1_CHARS_BIT;
-+    setLengthAndFlags(length, INIT_THIN_INLINE_FLAGS | LATIN1_CHARS_BIT);
-     return d.inlineStorageLatin1;
- }
- 
- template<>
- MOZ_ALWAYS_INLINE char16_t*
- JSThinInlineString::init<char16_t>(size_t length)
- {
-     MOZ_ASSERT(lengthFits<char16_t>(length));
--    d.u1.length = length;
--    d.u1.flags = INIT_THIN_INLINE_FLAGS;
-+    setLengthAndFlags(length, INIT_THIN_INLINE_FLAGS);
-     return d.inlineStorageTwoByte;
- }
- 
- template<>
- MOZ_ALWAYS_INLINE JS::Latin1Char*
- JSFatInlineString::init<JS::Latin1Char>(size_t length)
- {
-     MOZ_ASSERT(lengthFits<JS::Latin1Char>(length));
--    d.u1.length = length;
--    d.u1.flags = INIT_FAT_INLINE_FLAGS | LATIN1_CHARS_BIT;
-+    setLengthAndFlags(length, INIT_FAT_INLINE_FLAGS | LATIN1_CHARS_BIT);
-     return d.inlineStorageLatin1;
- }
- 
- template<>
- MOZ_ALWAYS_INLINE char16_t*
- JSFatInlineString::init<char16_t>(size_t length)
- {
-     MOZ_ASSERT(lengthFits<char16_t>(length));
--    d.u1.length = length;
--    d.u1.flags = INIT_FAT_INLINE_FLAGS;
-+    setLengthAndFlags(length, INIT_FAT_INLINE_FLAGS);
-     return d.inlineStorageTwoByte;
- }
- 
- MOZ_ALWAYS_INLINE void
- JSExternalString::init(const char16_t* chars, size_t length, const JSStringFinalizer* fin)
- {
-     MOZ_ASSERT(fin);
-     MOZ_ASSERT(fin->finalize);
--    d.u1.length = length;
--    d.u1.flags = EXTERNAL_FLAGS;
-+    setLengthAndFlags(length, EXTERNAL_FLAGS);
-     d.s.u2.nonInlineCharsTwoByte = chars;
-     d.s.u3.externalFinalizer = fin;
- }
- 
- MOZ_ALWAYS_INLINE JSExternalString*
- JSExternalString::new_(JSContext* cx, const char16_t* chars, size_t length,
-                        const JSStringFinalizer* fin)
- {
-diff --git a/js/src/vm/StringType.cpp b/js/src/vm/StringType.cpp
---- a/js/src/vm/StringType.cpp
-+++ b/js/src/vm/StringType.cpp
-@@ -207,17 +207,17 @@ JSString::dumpRepresentation(js::Generic
-     else if (isFlat())          asFlat()        .dumpRepresentation(out, indent);
-     else
-         MOZ_CRASH("Unexpected JSString representation");
- }
- 
- void
- JSString::dumpRepresentationHeader(js::GenericPrinter& out, const char* subclass) const
- {
--    uint32_t flags = d.u1.flags;
-+    uint32_t flags = JSString::flags();
-     // Print the string's address as an actual C++ expression, to facilitate
-     // copy-and-paste into a debugger.
-     out.printf("((%s*) %p) length: %zu  flags: 0x%x", subclass, this, length(), flags);
-     if (flags & LINEAR_BIT)             out.put(" LINEAR");
-     if (flags & HAS_BASE_BIT)           out.put(" HAS_BASE");
-     if (flags & INLINE_CHARS_BIT)       out.put(" INLINE_CHARS");
-     if (flags & NON_ATOM_BIT)           out.put(" NON_ATOM");
-     else                                out.put(" (ATOM)");
-@@ -513,20 +513,18 @@ JSRope::flattenInternal(JSContext* maybe
-      * pointers in the JSDependentStrings are still valid.
-      */
-     const size_t wholeLength = length();
-     size_t wholeCapacity;
-     CharT* wholeChars;
-     JSString* str = this;
-     CharT* pos;
- 
--    /*
--     * JSString::flattenData is a tagged pointer to the parent node.
--     * The tag indicates what to do when we return to the parent.
--     */
-+    // JSString::setFlattenData() is used to store a tagged pointer to the
-+    // parent node. The tag indicates what to do when we return to the parent.
-     static const uintptr_t Tag_Mask = 0x3;
-     static const uintptr_t Tag_FinishNode = 0x0;
-     static const uintptr_t Tag_VisitRightChild = 0x1;
- 
-     AutoCheckCannotGC nogc;
- 
-     gc::StoreBuffer* bufferIfNursery = storeBuffer();
- 
-@@ -551,29 +549,30 @@ JSRope::flattenInternal(JSContext* maybe
-                 if (b == WithIncrementalBarrier) {
-                     JSString::writeBarrierPre(str->d.s.u2.left);
-                     JSString::writeBarrierPre(str->d.s.u3.right);
-                 }
-                 JSString* child = str->d.s.u2.left;
-                 // 'child' will be post-barriered during the later traversal.
-                 MOZ_ASSERT(child->isRope());
-                 str->setNonInlineChars(wholeChars);
--                child->d.u1.flattenData = uintptr_t(str) | Tag_VisitRightChild;
-+                child->setFlattenData(uintptr_t(str) | Tag_VisitRightChild);
-                 str = child;
-             }
-             if (b == WithIncrementalBarrier) {
-                 JSString::writeBarrierPre(str->d.s.u2.left);
-                 JSString::writeBarrierPre(str->d.s.u3.right);
-             }
-             str->setNonInlineChars(wholeChars);
--            pos = wholeChars + left.d.u1.length;
-+            uint32_t left_len = left.length();
-+            pos = wholeChars + left_len;
-             if (IsSame<CharT, char16_t>::value)
--                left.d.u1.flags = DEPENDENT_FLAGS;
-+                left.setLengthAndFlags(left_len, DEPENDENT_FLAGS);
-             else
--                left.d.u1.flags = DEPENDENT_FLAGS | LATIN1_CHARS_BIT;
-+                left.setLengthAndFlags(left_len, DEPENDENT_FLAGS | LATIN1_CHARS_BIT);
-             left.d.s.u3.base = (JSLinearString*)this;  /* will be true on exit */
-             Nursery& nursery = runtimeFromMainThread()->gc.nursery();
-             bool inTenured = !bufferIfNursery;
-             if (!inTenured && left.isTenured()) {
-                 // tenured leftmost child is giving its chars buffer to the
-                 // nursery-allocated root node.
-                 nursery.registerMallocedBuffer(wholeChars);
-                 // leftmost child -> root is a tenured -> nursery edge.
-@@ -609,54 +608,53 @@ JSRope::flattenInternal(JSContext* maybe
-             JSString::writeBarrierPre(str->d.s.u2.left);
-             JSString::writeBarrierPre(str->d.s.u3.right);
-         }
- 
-         JSString& left = *str->d.s.u2.left;
-         str->setNonInlineChars(pos);
-         if (left.isRope()) {
-             /* Return to this node when 'left' done, then goto visit_right_child. */
--            left.d.u1.flattenData = uintptr_t(str) | Tag_VisitRightChild;
-+            left.setFlattenData(uintptr_t(str) | Tag_VisitRightChild);
-             str = &left;
-             goto first_visit_node;
-         }
-         CopyChars(pos, left.asLinear());
-         pos += left.length();
-     }
-     visit_right_child: {
-         JSString& right = *str->d.s.u3.right;
-         if (right.isRope()) {
-             /* Return to this node when 'right' done, then goto finish_node. */
--            right.d.u1.flattenData = uintptr_t(str) | Tag_FinishNode;
-+            right.setFlattenData(uintptr_t(str) | Tag_FinishNode);
-             str = &right;
-             goto first_visit_node;
-         }
-         CopyChars(pos, right.asLinear());
-         pos += right.length();
-     }
- 
-     finish_node: {
-         if (str == this) {
-             MOZ_ASSERT(pos == wholeChars + wholeLength);
-             *pos = '\0';
--            str->d.u1.length = wholeLength;
-             if (IsSame<CharT, char16_t>::value)
--                str->d.u1.flags = EXTENSIBLE_FLAGS;
-+                str->setLengthAndFlags(wholeLength, EXTENSIBLE_FLAGS);
-             else
--                str->d.u1.flags = EXTENSIBLE_FLAGS | LATIN1_CHARS_BIT;
-+                str->setLengthAndFlags(wholeLength, EXTENSIBLE_FLAGS | LATIN1_CHARS_BIT);
-             str->setNonInlineChars(wholeChars);
-             str->d.s.u3.capacity = wholeCapacity;
-             return &this->asFlat();
-         }
--        uintptr_t flattenData = str->d.u1.flattenData;
-+        uintptr_t flattenData;
-+        uint32_t len = pos - str->nonInlineCharsRaw<CharT>();
-         if (IsSame<CharT, char16_t>::value)
--            str->d.u1.flags = DEPENDENT_FLAGS;
-+            flattenData = str->unsetFlattenData(len, DEPENDENT_FLAGS);
-         else
--            str->d.u1.flags = DEPENDENT_FLAGS | LATIN1_CHARS_BIT;
--        str->d.u1.length = pos - str->asLinear().nonInlineChars<CharT>(nogc);
-+            flattenData = str->unsetFlattenData(len, DEPENDENT_FLAGS | LATIN1_CHARS_BIT);
-         str->d.s.u3.base = (JSLinearString*)this;       /* will be true on exit */
- 
-         // Every interior (rope) node in the rope's tree will be visited during
-         // the traversal and post-barriered here, so earlier additions of
-         // dependent.base -> root pointers are handled by this barrier as well.
-         //
-         // The only time post-barriers need do anything is when the root is in
-         // the nursery. Note that the root was a rope but will be an extensible
-@@ -801,19 +799,19 @@ JSDependentString::undependInternal(JSCo
-     s[n] = '\0';
-     setNonInlineChars<CharT>(s.release());
- 
-     /*
-      * Transform *this into an undepended string so 'base' will remain rooted
-      * for the benefit of any other dependent string that depends on *this.
-      */
-     if (IsSame<CharT, Latin1Char>::value)
--        d.u1.flags = UNDEPENDED_FLAGS | LATIN1_CHARS_BIT;
-+        setLengthAndFlags(n, UNDEPENDED_FLAGS | LATIN1_CHARS_BIT);
-     else
--        d.u1.flags = UNDEPENDED_FLAGS;
-+        setLengthAndFlags(n, UNDEPENDED_FLAGS);
- 
-     return &this->asFlat();
- }
- 
- JSFlatString*
- JSDependentString::undepend(JSContext* cx)
- {
-     MOZ_ASSERT(JSString::isDependent());
-@@ -1378,18 +1376,18 @@ JSExternalString::ensureFlat(JSContext* 
-     }
- 
-     // Release the external chars.
-     finalize(cx->runtime()->defaultFreeOp());
- 
-     // Transform the string into a non-external, flat string. Note that the
-     // resulting string will still be in an AllocKind::EXTERNAL_STRING arena,
-     // but will no longer be an external string.
-+    setLengthAndFlags(n, INIT_FLAT_FLAGS);
-     setNonInlineChars<char16_t>(s.release());
--    d.u1.flags = INIT_FLAT_FLAGS;
- 
-     return &this->asFlat();
- }
- 
- #if defined(DEBUG) || defined(JS_JITSPEW)
- void
- JSAtom::dump(js::GenericPrinter& out)
- {
-diff --git a/js/src/vm/StringType.h b/js/src/vm/StringType.h
---- a/js/src/vm/StringType.h
-+++ b/js/src/vm/StringType.h
-@@ -162,20 +162,20 @@ class JSString : public js::gc::Cell
-     static const size_t NUM_INLINE_CHARS_LATIN1   = 2 * sizeof(void*) / sizeof(JS::Latin1Char);
-     static const size_t NUM_INLINE_CHARS_TWO_BYTE = 2 * sizeof(void*) / sizeof(char16_t);
- 
-     /* Fields only apply to string types commented on the right. */
-     struct Data
-     {
-         union {
-             struct {
--                uint32_t           flags;               /* JSString */
--                uint32_t           length;              /* JSString */
-+                uint32_t           flags_;              /* JSString */
-+                uint32_t           length_;             /* JSString */
-             };
--            uintptr_t              flattenData;         /* JSRope (temporary while flattening) */
-+            uintptr_t              flattenData_;        /* JSRope (temporary while flattening) */
-         } u1;
-         union {
-             union {
-                 /* JS(Fat)InlineString */
-                 JS::Latin1Char     inlineStorageLatin1[NUM_INLINE_CHARS_LATIN1];
-                 char16_t           inlineStorageTwoByte[NUM_INLINE_CHARS_TWO_BYTE];
-             };
-             struct {
-@@ -312,19 +312,19 @@ class JSString : public js::gc::Cell
-                       "Inline Latin1 chars must fit in a JSString");
-         static_assert(sizeof(JSString) ==
-                       (offsetof(JSString, d.inlineStorageTwoByte) +
-                        NUM_INLINE_CHARS_TWO_BYTE * sizeof(char16_t)),
-                       "Inline char16_t chars must fit in a JSString");
- 
-         /* Ensure js::shadow::String has the same layout. */
-         using JS::shadow::String;
--        static_assert(offsetof(JSString, d.u1.length) == offsetof(String, length),
-+        static_assert(offsetof(JSString, d.u1.length_) == offsetof(String, length_),
-                       "shadow::String length offset must match JSString");
--        static_assert(offsetof(JSString, d.u1.flags) == offsetof(String, flags),
-+        static_assert(offsetof(JSString, d.u1.flags_) == offsetof(String, flags_),
-                       "shadow::String flags offset must match JSString");
-         static_assert(offsetof(JSString, d.s.u2.nonInlineCharsLatin1) == offsetof(String, nonInlineCharsLatin1),
-                       "shadow::String nonInlineChars offset must match JSString");
-         static_assert(offsetof(JSString, d.s.u2.nonInlineCharsTwoByte) == offsetof(String, nonInlineCharsTwoByte),
-                       "shadow::String nonInlineChars offset must match JSString");
-         static_assert(offsetof(JSString, d.s.u3.externalFinalizer) == offsetof(String, externalFinalizer),
-                       "shadow::String externalFinalizer offset must match JSString");
-         static_assert(offsetof(JSString, d.inlineStorageLatin1) == offsetof(String, inlineStorageLatin1),
-@@ -350,85 +350,127 @@ class JSString : public js::gc::Cell
- 
-     friend class js::gc::RelocationOverlay;
- 
-   protected:
-     template <typename CharT>
-     MOZ_ALWAYS_INLINE
-     void setNonInlineChars(const CharT* chars);
- 
-+    MOZ_ALWAYS_INLINE
-+    uint32_t flags() const {
-+        return d.u1.flags_;
-+    }
-+
-   public:
--    /* All strings have length. */
-+    MOZ_ALWAYS_INLINE
-+    size_t length() const {
-+        return d.u1.length_;
-+    }
-+
-+  protected:
-+    MOZ_ALWAYS_INLINE
-+    void setFlagBit(uint32_t flags) {
-+        d.u1.flags_ |= flags;
-+    }
- 
-     MOZ_ALWAYS_INLINE
--    size_t length() const {
--        return d.u1.length;
-+    void clearFlagBit(uint32_t flags) {
-+        d.u1.flags_ &= ~flags;
-     }
- 
-     MOZ_ALWAYS_INLINE
-+    void setLengthAndFlags(uint32_t len, uint32_t flags) {
-+        d.u1.flags_ = flags;
-+        d.u1.length_ = len;
-+    }
-+
-+    // Flatten algorithm stores a temporary word by clobbering flags. This is
-+    // not GC-safe and user must ensure JSString::flags are never checked
-+    // (including by asserts) while this data is stored.
-+    MOZ_ALWAYS_INLINE
-+    void setFlattenData(uintptr_t data) {
-+        d.u1.flattenData_ = data;
-+    }
-+
-+    // To get back the data, values to safely re-initialize clobbered flags
-+    // must be provided.
-+    MOZ_ALWAYS_INLINE
-+    uintptr_t unsetFlattenData(uint32_t len, uint32_t flags) {
-+        uintptr_t data = d.u1.flattenData_;
-+        setLengthAndFlags(len, flags);
-+        return data;
-+    }
-+
-+    // Get correct non-inline chars enum arm for given type
-+    template <typename CharT> MOZ_ALWAYS_INLINE const CharT* nonInlineCharsRaw() const;
-+
-+  public:
-+
-+    MOZ_ALWAYS_INLINE
-     bool empty() const {
--        return d.u1.length == 0;
-+        return length() == 0;
-     }
- 
-     inline bool getChar(JSContext* cx, size_t index, char16_t* code);
- 
-     /* Strings have either Latin1 or TwoByte chars. */
-     bool hasLatin1Chars() const {
--        return d.u1.flags & LATIN1_CHARS_BIT;
-+        return flags() & LATIN1_CHARS_BIT;
-     }
-     bool hasTwoByteChars() const {
--        return !(d.u1.flags & LATIN1_CHARS_BIT);
-+        return !(flags() & LATIN1_CHARS_BIT);
-     }
- 
-     /* Strings might contain cached indexes. */
-     bool hasIndexValue() const {
--        return d.u1.flags & INDEX_VALUE_BIT;
-+        return flags() & INDEX_VALUE_BIT;
-     }
-     uint32_t getIndexValue() const {
-         MOZ_ASSERT(hasIndexValue());
-         MOZ_ASSERT(isFlat());
--        return d.u1.flags >> INDEX_VALUE_SHIFT;
-+        return flags() >> INDEX_VALUE_SHIFT;
-     }
- 
-     /* Fallible conversions to more-derived string types. */
- 
-     inline JSLinearString* ensureLinear(JSContext* cx);
-     JSFlatString* ensureFlat(JSContext* cx);
- 
-     static bool ensureLinear(JSContext* cx, JSString* str) {
-         return str->ensureLinear(cx) != nullptr;
-     }
- 
-     /* Type query and debug-checked casts */
- 
-     MOZ_ALWAYS_INLINE
-     bool isRope() const {
--        return !(d.u1.flags & LINEAR_BIT);
-+        return !(flags() & LINEAR_BIT);
-     }
- 
-     MOZ_ALWAYS_INLINE
-     JSRope& asRope() const {
-         MOZ_ASSERT(isRope());
-         return *(JSRope*)this;
-     }
- 
-     MOZ_ALWAYS_INLINE
-     bool isLinear() const {
--        return d.u1.flags & LINEAR_BIT;
-+        return flags() & LINEAR_BIT;
-     }
- 
-     MOZ_ALWAYS_INLINE
-     JSLinearString& asLinear() const {
-         MOZ_ASSERT(JSString::isLinear());
-         return *(JSLinearString*)this;
-     }
- 
-     MOZ_ALWAYS_INLINE
-     bool isDependent() const {
--        return (d.u1.flags & TYPE_FLAGS_MASK) == DEPENDENT_FLAGS;
-+        return (flags() & TYPE_FLAGS_MASK) == DEPENDENT_FLAGS;
-     }
- 
-     MOZ_ALWAYS_INLINE
-     JSDependentString& asDependent() const {
-         MOZ_ASSERT(isDependent());
-         return *(JSDependentString*)this;
-     }
- 
-@@ -440,65 +482,65 @@ class JSString : public js::gc::Cell
-     MOZ_ALWAYS_INLINE
-     JSFlatString& asFlat() const {
-         MOZ_ASSERT(isFlat());
-         return *(JSFlatString*)this;
-     }
- 
-     MOZ_ALWAYS_INLINE
-     bool isExtensible() const {
--        return (d.u1.flags & TYPE_FLAGS_MASK) == EXTENSIBLE_FLAGS;
-+        return (flags() & TYPE_FLAGS_MASK) == EXTENSIBLE_FLAGS;
-     }
- 
-     MOZ_ALWAYS_INLINE
-     JSExtensibleString& asExtensible() const {
-         MOZ_ASSERT(isExtensible());
-         return *(JSExtensibleString*)this;
-     }
- 
-     MOZ_ALWAYS_INLINE
-     bool isInline() const {
--        return d.u1.flags & INLINE_CHARS_BIT;
-+        return flags() & INLINE_CHARS_BIT;
-     }
- 
-     MOZ_ALWAYS_INLINE
-     JSInlineString& asInline() const {
-         MOZ_ASSERT(isInline());
-         return *(JSInlineString*)this;
-     }
- 
-     MOZ_ALWAYS_INLINE
-     bool isFatInline() const {
--        return (d.u1.flags & FAT_INLINE_MASK) == FAT_INLINE_MASK;
-+        return (flags() & FAT_INLINE_MASK) == FAT_INLINE_MASK;
-     }
- 
-     /* For hot code, prefer other type queries. */
-     bool isExternal() const {
--        return (d.u1.flags & TYPE_FLAGS_MASK) == EXTERNAL_FLAGS;
-+        return (flags() & TYPE_FLAGS_MASK) == EXTERNAL_FLAGS;
-     }
- 
-     MOZ_ALWAYS_INLINE
-     JSExternalString& asExternal() const {
-         MOZ_ASSERT(isExternal());
-         return *(JSExternalString*)this;
-     }
- 
-     MOZ_ALWAYS_INLINE
-     bool isUndepended() const {
--        return (d.u1.flags & TYPE_FLAGS_MASK) == UNDEPENDED_FLAGS;
-+        return (flags() & TYPE_FLAGS_MASK) == UNDEPENDED_FLAGS;
-     }
- 
-     MOZ_ALWAYS_INLINE
-     bool isAtom() const {
--        return !(d.u1.flags & NON_ATOM_BIT);
-+        return !(flags() & NON_ATOM_BIT);
-     }
- 
-     MOZ_ALWAYS_INLINE
-     bool isPermanentAtom() const {
--        return (d.u1.flags & PERMANENT_ATOM_MASK) == PERMANENT_ATOM_FLAGS;
-+        return (flags() & PERMANENT_ATOM_MASK) == PERMANENT_ATOM_FLAGS;
-     }
- 
-     MOZ_ALWAYS_INLINE
-     JSAtom& asAtom() const {
-         MOZ_ASSERT(isAtom());
-         return *(JSAtom*)this;
-     }
- 
-@@ -512,17 +554,17 @@ class JSString : public js::gc::Cell
- 
-     // Fills |array| with various strings that represent the different string
-     // kinds and character encodings.
-     static bool fillWithRepresentatives(JSContext* cx, js::HandleArrayObject array);
- 
-     /* Only called by the GC for dependent or undepended strings. */
- 
-     inline bool hasBase() const {
--        return d.u1.flags & HAS_BASE_BIT;
-+        return flags() & HAS_BASE_BIT;
-     }
- 
-     inline JSLinearString* base() const;
- 
-     void traceBase(JSTracer* trc);
- 
-     /* Only called by the GC for strings with the AllocKind::STRING kind. */
- 
-@@ -530,20 +572,20 @@ class JSString : public js::gc::Cell
- 
-     /* Gets the number of bytes that the chars take on the heap. */
- 
-     size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf);
- 
-     /* Offsets for direct field from jit code. */
- 
-     static size_t offsetOfLength() {
--        return offsetof(JSString, d.u1.length);
-+        return offsetof(JSString, d.u1.length_);
-     }
-     static size_t offsetOfFlags() {
--        return offsetof(JSString, d.u1.flags);
-+        return offsetof(JSString, d.u1.flags_);
-     }
- 
-   private:
-     // To help avoid writing Spectre-unsafe code, we only allow MacroAssembler
-     // to call the method below.
-     friend class js::jit::MacroAssembler;
-     static size_t offsetOfNonInlineChars() {
-         static_assert(offsetof(JSString, d.s.u2.nonInlineCharsTwoByte) ==
-@@ -926,17 +968,17 @@ class JSFlatString : public JSLinearStri
- 
-         if (hasIndexValue() || index > UINT16_MAX)
-             return;
- 
-         mozilla::DebugOnly<uint32_t> containedIndex;
-         MOZ_ASSERT(isIndexSlow(&containedIndex));
-         MOZ_ASSERT(index == containedIndex);
- 
--        d.u1.flags |= (index << INDEX_VALUE_SHIFT) | INDEX_VALUE_BIT;
-+        setFlagBit((index << INDEX_VALUE_SHIFT) | INDEX_VALUE_BIT);
-     }
- 
-     /*
-      * Returns a property name represented by this string, or null on failure.
-      * You must verify that this is not an index per isIndex before calling
-      * this method.
-      */
-     inline js::PropertyName* toPropertyName(JSContext* cx);
-@@ -1162,29 +1204,29 @@ class JSAtom : public JSFlatString
-     bool isPermanent() const {
-         return JSString::isPermanentAtom();
-     }
- 
-     // Transform this atom into a permanent atom. This is only done during
-     // initialization of the runtime. Permanent atoms are always pinned.
-     MOZ_ALWAYS_INLINE void morphIntoPermanentAtom() {
-         MOZ_ASSERT(static_cast<JSString*>(this)->isAtom());
--        d.u1.flags |= PERMANENT_ATOM_FLAGS | PINNED_ATOM_BIT;
-+        setFlagBit(PERMANENT_ATOM_FLAGS | PINNED_ATOM_BIT);
-     }
- 
-     MOZ_ALWAYS_INLINE
-     bool isPinned() const {
--        return d.u1.flags & PINNED_ATOM_BIT;
-+        return flags() & PINNED_ATOM_BIT;
-     }
- 
-     // Mark the atom as pinned. For use by atomization only.
-     MOZ_ALWAYS_INLINE void setPinned() {
-         MOZ_ASSERT(static_cast<JSString*>(this)->isAtom());
-         MOZ_ASSERT(!isPinned());
--        d.u1.flags |= PINNED_ATOM_BIT;
-+        setFlagBit(PINNED_ATOM_BIT);
-     }
- 
-     inline js::HashNumber hash() const;
-     inline void initHash(js::HashNumber hash);
- 
- #if defined(DEBUG) || defined(JS_JITSPEW)
-     void dump(js::GenericPrinter& out);
-     void dump();
-@@ -1252,28 +1294,28 @@ JSAtom::initHash(js::HashNumber hash)
-         return static_cast<js::FatInlineAtom*>(this)->initHash(hash);
-     return static_cast<js::NormalAtom*>(this)->initHash(hash);
- }
- 
- MOZ_ALWAYS_INLINE JSAtom*
- JSFlatString::morphAtomizedStringIntoAtom(js::HashNumber hash)
- {
-     MOZ_ASSERT(!isAtom());
--    d.u1.flags &= ~NON_ATOM_BIT;
-+    clearFlagBit(NON_ATOM_BIT);
-     JSAtom* atom = &asAtom();
-     atom->initHash(hash);
-     return atom;
- }
- 
- MOZ_ALWAYS_INLINE JSAtom*
- JSFlatString::morphAtomizedStringIntoPermanentAtom(js::HashNumber hash)
- {
-     MOZ_ASSERT(!isAtom());
--    d.u1.flags |= PERMANENT_ATOM_FLAGS | PINNED_ATOM_BIT;
--    d.u1.flags &= ~NON_ATOM_BIT;
-+    setFlagBit(PERMANENT_ATOM_FLAGS | PINNED_ATOM_BIT);
-+    clearFlagBit(NON_ATOM_BIT);
-     JSAtom* atom = &asAtom();
-     atom->initHash(hash);
-     return atom;
- }
- 
- namespace js {
- 
- class StaticStrings

+ 0 - 1043
frg/work-js/mozilla-release/patches/mozilla-central-push_430741.patch

@@ -1,1043 +0,0 @@
-# HG changeset patch
-# User Ted Campbell <tcampbell@mozilla.com>
-# Date 1533234736 25200
-#      Thu Aug 02 11:32:16 2018 -0700
-# Node ID 819b923159847ebf0227a910e966490f4f9dc177
-# Parent  ebac10c8c8b9ab70465097b02de34eee86bf41be
-Bug 1479900 - Part 2: Refactor GC relocation to use a reserved flag. r=sfink
-
-This refactors gc::Cell derived types to start with a uintptr_t-sized
-field with the low bits reserved for the GC and uses these bits for
-relocation mechanism.
-
-- JSString now stores flags in a uintptr_t. On 32-bit platforms, a
-  second field is used to hold length.
-- Redefine JSString flag bit positions to avoid cell reserved bits.
-- Forwarded Cells are now indicated by a reserved flag instead of a
-  magic invalid-pointer-like value.
-- gc::RelocationOverlay now extends gc::Cell
-- Update js::Symbol, js::Scope and js::BigInt fields to be compatible.
-
-MozReview-Commit-ID: Cs5OavbHmqK
-
-diff --git a/js/public/HeapAPI.h b/js/public/HeapAPI.h
---- a/js/public/HeapAPI.h
-+++ b/js/public/HeapAPI.h
-@@ -21,22 +21,16 @@ namespace js {
- 
- JS_FRIEND_API(bool)
- CurrentThreadCanAccessZone(JS::Zone* zone);
- 
- namespace gc {
- 
- struct Cell;
- 
--/*
-- * The low bit is set so this should never equal a normal pointer, and the high
-- * bit is set so this should never equal the upper 32 bits of a 64-bit pointer.
-- */
--const uint32_t Relocated = uintptr_t(0xbad0bad1);
--
- const size_t ArenaShift = 12;
- const size_t ArenaSize = size_t(1) << ArenaShift;
- const size_t ArenaMask = ArenaSize - 1;
- 
- #ifdef JS_GC_SMALL_CHUNK_SIZE
- const size_t ChunkShift = 18;
- #else
- const size_t ChunkShift = 20;
-@@ -200,54 +194,57 @@ struct Zone
- 
-     static MOZ_ALWAYS_INLINE JS::shadow::Zone* asShadowZone(JS::Zone* zone) {
-         return reinterpret_cast<JS::shadow::Zone*>(zone);
-     }
- };
- 
- struct String
- {
--    static const uint32_t NON_ATOM_BIT     = JS_BIT(0);
--    static const uint32_t LINEAR_BIT       = JS_BIT(1);
--    static const uint32_t INLINE_CHARS_BIT = JS_BIT(3);
--    static const uint32_t LATIN1_CHARS_BIT = JS_BIT(6);
--    static const uint32_t EXTERNAL_FLAGS   = LINEAR_BIT | NON_ATOM_BIT | JS_BIT(5);
--    static const uint32_t TYPE_FLAGS_MASK  = JS_BIT(6) - 1;
--    static const uint32_t PERMANENT_ATOM_MASK    = NON_ATOM_BIT | JS_BIT(5);
--    static const uint32_t PERMANENT_ATOM_FLAGS   = JS_BIT(5);
-+    static const uint32_t NON_ATOM_BIT     = JS_BIT(1);
-+    static const uint32_t LINEAR_BIT       = JS_BIT(4);
-+    static const uint32_t INLINE_CHARS_BIT = JS_BIT(6);
-+    static const uint32_t LATIN1_CHARS_BIT = JS_BIT(9);
-+    static const uint32_t EXTERNAL_FLAGS   = LINEAR_BIT | NON_ATOM_BIT | JS_BIT(8);
-+    static const uint32_t TYPE_FLAGS_MASK  = JS_BITMASK(9) - JS_BIT(2) - JS_BIT(0);
-+    static const uint32_t PERMANENT_ATOM_MASK    = NON_ATOM_BIT | JS_BIT(8);
-+    static const uint32_t PERMANENT_ATOM_FLAGS   = JS_BIT(8);
- 
--    uint32_t flags_;
-+    uintptr_t flags_;
-+  #if JS_BITS_PER_WORD == 32
-     uint32_t length_;
-+  #endif
-+
-     union {
-         const JS::Latin1Char* nonInlineCharsLatin1;
-         const char16_t* nonInlineCharsTwoByte;
-         JS::Latin1Char inlineStorageLatin1[1];
-         char16_t inlineStorageTwoByte[1];
-     };
-     const JSStringFinalizer* externalFinalizer;
- 
-     inline uint32_t flags() const {
--        return flags_;
-+        return uint32_t(flags_);
-     }
-     inline uint32_t length() const {
-+  #if JS_BITS_PER_WORD == 32
-         return length_;
--    }
--
--    static bool nurseryCellIsString(const js::gc::Cell* cell) {
--        MOZ_ASSERT(IsInsideNursery(cell));
--        return reinterpret_cast<const String*>(cell)->flags() & NON_ATOM_BIT;
-+  #else
-+        return uint32_t(flags_ >> 32);
-+  #endif
-     }
- 
-     static bool isPermanentAtom(const js::gc::Cell* cell) {
-         uint32_t flags = reinterpret_cast<const String*>(cell)->flags();
-         return (flags & PERMANENT_ATOM_MASK) == PERMANENT_ATOM_FLAGS;
-     }
- };
- 
- struct Symbol {
-+    uintptr_t reserved_;
-     uint32_t code_;
-     static const uint32_t WellKnownAPILimit = 0x80000000;
- 
-     static bool isWellKnownSymbol(const js::gc::Cell* cell) {
-         return reinterpret_cast<const Symbol*>(cell)->code_ < WellKnownAPILimit;
-     }
- };
- 
-diff --git a/js/src/gc/Cell.h b/js/src/gc/Cell.h
---- a/js/src/gc/Cell.h
-+++ b/js/src/gc/Cell.h
-@@ -43,20 +43,45 @@ TraceManuallyBarrieredGenericPointerEdge
- namespace gc {
- 
- class Arena;
- enum class AllocKind : uint8_t;
- struct Chunk;
- class StoreBuffer;
- class TenuredCell;
- 
--// A GC cell is the base class for all GC things.
-+// [SMDOC] GC Cell
-+//
-+// A GC cell is the base class for all GC things. All types allocated on the GC
-+// heap extend either gc::Cell or gc::TenuredCell. If a type is always tenured,
-+// prefer the TenuredCell class as base.
-+//
-+// The first word (a pointer or uintptr_t) of each Cell must reserve the low
-+// Cell::ReservedBits bits for GC purposes. The remaining bits are available to
-+// sub-classes and typically store a pointer to another gc::Cell.
-+//
-+// During moving GC operation a Cell may be marked as forwarded. This indicates
-+// that a gc::RelocationOverlay is currently stored in the Cell's memory and
-+// should be used to find the new location of the Cell.
- struct alignas(gc::CellAlignBytes) Cell
- {
-   public:
-+    // The low bits of the first word of each Cell are reserved for GC flags.
-+    static constexpr int ReservedBits = 2;
-+    static constexpr uintptr_t RESERVED_MASK = JS_BITMASK(ReservedBits);
-+
-+    // Indicates if the cell is currently a RelocationOverlay
-+    static constexpr uintptr_t FORWARD_BIT = JS_BIT(0);
-+
-+    // When a Cell is in the nursery, this will indicate if it is a JSString (1)
-+    // or JSObject (0). When not in nursery, this bit is still reserved for
-+    // JSString to use as JSString::NON_ATOM bit. This may be removed by Bug
-+    // 1376646.
-+    static constexpr uintptr_t JSSTRING_BIT = JS_BIT(1);
-+
-     MOZ_ALWAYS_INLINE bool isTenured() const { return !IsInsideNursery(this); }
-     MOZ_ALWAYS_INLINE const TenuredCell& asTenured() const;
-     MOZ_ALWAYS_INLINE TenuredCell& asTenured();
- 
-     MOZ_ALWAYS_INLINE bool isMarkedAny() const;
-     MOZ_ALWAYS_INLINE bool isMarkedBlack() const;
-     MOZ_ALWAYS_INLINE bool isMarkedGray() const;
- 
-@@ -72,16 +97,27 @@ struct alignas(gc::CellAlignBytes) Cell
-     // The StoreBuffer used to record incoming pointers from the tenured heap.
-     // This will return nullptr for a tenured cell.
-     inline StoreBuffer* storeBuffer() const;
- 
-     inline JS::TraceKind getTraceKind() const;
- 
-     static MOZ_ALWAYS_INLINE bool needWriteBarrierPre(JS::Zone* zone);
- 
-+    inline bool isForwarded() const {
-+        uintptr_t firstWord = *reinterpret_cast<const uintptr_t*>(this);
-+        return firstWord & FORWARD_BIT;
-+    }
-+
-+    inline bool nurseryCellIsString() const {
-+        MOZ_ASSERT(!isTenured());
-+        uintptr_t firstWord = *reinterpret_cast<const uintptr_t*>(this);
-+        return firstWord & JSSTRING_BIT;
-+    }
-+
-     template <class T>
-     inline bool is() const {
-         return getTraceKind() == JS::MapTypeToTraceKind<T>::kind;
-     }
- 
-     template<class T>
-     inline T* as() {
-         // |this|-qualify the |is| call below to avoid compile errors with even
-@@ -250,17 +286,17 @@ Cell::storeBuffer() const
-     return chunk()->trailer.storeBuffer;
- }
- 
- inline JS::TraceKind
- Cell::getTraceKind() const
- {
-     if (isTenured())
-         return asTenured().getTraceKind();
--    if (JS::shadow::String::nurseryCellIsString(this))
-+    if (nurseryCellIsString())
-         return JS::TraceKind::String;
-     return JS::TraceKind::Object;
- }
- 
- /* static */ MOZ_ALWAYS_INLINE bool
- Cell::needWriteBarrierPre(JS::Zone* zone) {
-     return JS::shadow::Zone::asShadowZone(zone)->needsIncrementalBarrier();
- }
-diff --git a/js/src/gc/GC.cpp b/js/src/gc/GC.cpp
---- a/js/src/gc/GC.cpp
-+++ b/js/src/gc/GC.cpp
-@@ -219,16 +219,17 @@
- #include "gc/GCTrace.h"
- #include "gc/Memory.h"
- #include "gc/Policy.h"
- #include "gc/WeakMap.h"
- #include "jit/BaselineJIT.h"
- #include "jit/IonCode.h"
- #include "jit/JitcodeMap.h"
- #include "jit/JitRealm.h"
-+#include "jit/MacroAssembler.h"
- #include "js/SliceBudget.h"
- #include "proxy/DeadObjectProxy.h"
- #include "util/Windows.h"
- #ifdef ENABLE_BIGINT
- #include "vm/BigIntType.h"
- #endif
- #include "vm/Debugger.h"
- #include "vm/GeckoProfiler.h"
-@@ -379,16 +380,27 @@ static const int IGC_MARK_SLICE_MULTIPLI
- const AllocKind gc::slotsToThingKind[] = {
-     /*  0 */ AllocKind::OBJECT0,  AllocKind::OBJECT2,  AllocKind::OBJECT2,  AllocKind::OBJECT4,
-     /*  4 */ AllocKind::OBJECT4,  AllocKind::OBJECT8,  AllocKind::OBJECT8,  AllocKind::OBJECT8,
-     /*  8 */ AllocKind::OBJECT8,  AllocKind::OBJECT12, AllocKind::OBJECT12, AllocKind::OBJECT12,
-     /* 12 */ AllocKind::OBJECT12, AllocKind::OBJECT16, AllocKind::OBJECT16, AllocKind::OBJECT16,
-     /* 16 */ AllocKind::OBJECT16
- };
- 
-+// Check that reserved bits of a Cell are compatible with our typical allocators
-+// since most derived classes will store a pointer in the first word.
-+static_assert(js::detail::LIFO_ALLOC_ALIGN > JS_BITMASK(Cell::ReservedBits),
-+              "Cell::ReservedBits should support LifoAlloc");
-+static_assert(CellAlignBytes > JS_BITMASK(Cell::ReservedBits),
-+              "Cell::ReservedBits should support gc::Cell");
-+static_assert(sizeof(uintptr_t) > JS_BITMASK(Cell::ReservedBits),
-+              "Cell::ReservedBits should support small malloc / aligned globals");
-+static_assert(js::jit::CodeAlignment > JS_BITMASK(Cell::ReservedBits),
-+              "Cell::ReservedBits should support JIT code");
-+
- static_assert(mozilla::ArrayLength(slotsToThingKind) == SLOTS_TO_THING_KIND_LIMIT,
-               "We have defined a slot count for each kind.");
- 
- #define CHECK_THING_SIZE(allocKind, traceKind, type, sizedType, bgFinal, nursery, compact) \
-     static_assert(sizeof(sizedType) >= SortedArenaList::MinThingSize, \
-                   #sizedType " is smaller than SortedArenaList::MinThingSize!"); \
-     static_assert(sizeof(sizedType) >= sizeof(FreeSpan), \
-                   #sizedType " is smaller than FreeSpan"); \
-@@ -2339,17 +2351,17 @@ RelocateArena(Arena* arena, SliceBudget&
-     for (ArenaCellIterUnderGC i(arena); !i.done(); i.next()) {
-         RelocateCell(zone, i.getCell(), thingKind, thingSize);
-         sliceBudget.step();
-     }
- 
- #ifdef DEBUG
-     for (ArenaCellIterUnderGC i(arena); !i.done(); i.next()) {
-         TenuredCell* src = i.getCell();
--        MOZ_ASSERT(RelocationOverlay::isCellForwarded(src));
-+        MOZ_ASSERT(src->isForwarded());
-         TenuredCell* dest = Forwarded(src);
-         MOZ_ASSERT(src->isMarkedBlack() == dest->isMarkedBlack());
-         MOZ_ASSERT(src->isMarkedGray() == dest->isMarkedGray());
-     }
- #endif
- }
- 
- static inline bool
-@@ -8467,18 +8479,18 @@ js::gc::AssertGCThingHasType(js::gc::Cel
-     if (!cell) {
-         MOZ_ASSERT(kind == JS::TraceKind::Null);
-         return;
-     }
- 
-     MOZ_ASSERT(IsCellPointerValid(cell));
- 
-     if (IsInsideNursery(cell)) {
--        MOZ_ASSERT(kind == (JSString::nurseryCellIsString(cell) ? JS::TraceKind::String
--                                                                : JS::TraceKind::Object));
-+        MOZ_ASSERT(kind == (cell->nurseryCellIsString() ? JS::TraceKind::String
-+                                                        : JS::TraceKind::Object));
-         return;
-     }
- 
-     MOZ_ASSERT(MapAllocToTraceKind(cell->asTenured().getAllocKind()) == kind);
- }
- #endif
- 
- #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
-diff --git a/js/src/gc/GCInternals.h b/js/src/gc/GCInternals.h
---- a/js/src/gc/GCInternals.h
-+++ b/js/src/gc/GCInternals.h
-@@ -172,17 +172,17 @@ struct MovingTracer : JS::CallbackTracer
-     void onShapeEdge(Shape** shapep) override;
-     void onStringEdge(JSString** stringp) override;
-     void onScriptEdge(JSScript** scriptp) override;
-     void onLazyScriptEdge(LazyScript** lazyp) override;
-     void onBaseShapeEdge(BaseShape** basep) override;
-     void onScopeEdge(Scope** basep) override;
-     void onRegExpSharedEdge(RegExpShared** sharedp) override;
-     void onChild(const JS::GCCellPtr& thing) override {
--        MOZ_ASSERT(!RelocationOverlay::isCellForwarded(thing.asCell()));
-+        MOZ_ASSERT(!thing.asCell()->isForwarded());
-     }
- 
- #ifdef DEBUG
-     TracerKind getTracerKind() const override { return TracerKind::Moving; }
- #endif
- 
-   private:
-     template <typename T>
-diff --git a/js/src/gc/Marking-inl.h b/js/src/gc/Marking-inl.h
---- a/js/src/gc/Marking-inl.h
-+++ b/js/src/gc/Marking-inl.h
-@@ -35,23 +35,22 @@ struct MightBeForwarded
-                               mozilla::IsBaseOf<js::Scope, T>::value ||
-                               mozilla::IsBaseOf<js::RegExpShared, T>::value;
- };
- 
- template <typename T>
- inline bool
- IsForwarded(const T* t)
- {
--    const RelocationOverlay* overlay = RelocationOverlay::fromCell(t);
-     if (!MightBeForwarded<T>::value) {
--        MOZ_ASSERT(!overlay->isForwarded());
-+        MOZ_ASSERT(!t->isForwarded());
-         return false;
-     }
- 
--    return overlay->isForwarded();
-+    return t->isForwarded();
- }
- 
- struct IsForwardedFunctor : public BoolDefaultAdaptor<Value, false> {
-     template <typename T> bool operator()(const T* t) { return IsForwarded(t); }
- };
- 
- inline bool
- IsForwarded(const JS::Value& value)
-@@ -88,35 +87,33 @@ MaybeForwarded(T t)
-         t = Forwarded(t);
-     return t;
- }
- 
- inline void
- RelocationOverlay::forwardTo(Cell* cell)
- {
-     MOZ_ASSERT(!isForwarded());
--    // The location of magic_ is important because it must never be valid to see
--    // the value Relocated there in a GC thing that has not been moved.
--    static_assert(offsetof(RelocationOverlay, magic_) == offsetof(JSObject, group_) + sizeof(uint32_t),
--                  "RelocationOverlay::magic_ is in the wrong location");
--    static_assert(offsetof(RelocationOverlay, magic_) == offsetof(js::Shape, base_) + sizeof(uint32_t),
--                  "RelocationOverlay::magic_ is in the wrong location");
--    static_assert(offsetof(RelocationOverlay, magic_) == offsetof(JSString, d.u1.length_),
--                  "RelocationOverlay::magic_ is in the wrong location");
--    magic_ = Relocated;
--    newLocation_ = cell;
-+
-+    // Preserve old flags because nursery may check them before checking
-+    // if this is a forwarded Cell.
-+    //
-+    // This is pretty terrible and we should find a better way to implement
-+    // Cell::getTrackKind() that doesn't rely on this behavior.
-+    uintptr_t gcFlags = dataWithTag_ & Cell::RESERVED_MASK;
-+    dataWithTag_ = uintptr_t(cell) | gcFlags | Cell::FORWARD_BIT;
- }
- 
- #ifdef JSGC_HASH_TABLE_CHECKS
- 
- template <typename T>
- inline bool
- IsGCThingValidAfterMovingGC(T* t)
- {
--    return !IsInsideNursery(t) && !RelocationOverlay::isCellForwarded(t);
-+    return !IsInsideNursery(t) && !t->isForwarded();
- }
- 
- template <typename T>
- inline void
- CheckGCThingAfterMovingGC(T* t)
- {
-     if (t)
-         MOZ_RELEASE_ASSERT(IsGCThingValidAfterMovingGC(t));
-diff --git a/js/src/gc/Marking.cpp b/js/src/gc/Marking.cpp
---- a/js/src/gc/Marking.cpp
-+++ b/js/src/gc/Marking.cpp
-@@ -2857,17 +2857,17 @@ js::gc::StoreBuffer::CellPtrEdge::trace(
- #endif
- 
-     // Bug 1376646: Make separate store buffers for strings and objects, and
-     // only check IsInsideNursery once.
- 
-     if (!IsInsideNursery(*edge))
-         return;
- 
--    if (JSString::nurseryCellIsString(*edge))
-+    if ((*edge)->nurseryCellIsString())
-         mover.traverse(reinterpret_cast<JSString**>(edge));
-     else
-         mover.traverse(reinterpret_cast<JSObject**>(edge));
- }
- 
- void
- js::gc::StoreBuffer::ValueEdge::trace(TenuringTracer& mover) const
- {
-diff --git a/js/src/gc/Nursery-inl.h b/js/src/gc/Nursery-inl.h
---- a/js/src/gc/Nursery-inl.h
-+++ b/js/src/gc/Nursery-inl.h
-@@ -23,21 +23,21 @@ bool
- js::Nursery::isInside(const SharedMem<T>& p) const
- {
-     return isInside(p.unwrap(/*safe - used for value in comparison above*/));
- }
- 
- MOZ_ALWAYS_INLINE /* static */ bool
- js::Nursery::getForwardedPointer(js::gc::Cell** ref)
- {
--    MOZ_ASSERT(ref);
--    MOZ_ASSERT(IsInsideNursery(*ref));
--    const gc::RelocationOverlay* overlay = reinterpret_cast<const gc::RelocationOverlay*>(*ref);
--    if (!overlay->isForwarded())
-+    js::gc::Cell* cell = (*ref);
-+    MOZ_ASSERT(IsInsideNursery(cell));
-+    if (!cell->isForwarded())
-         return false;
-+    const gc::RelocationOverlay* overlay = gc::RelocationOverlay::fromCell(cell);
-     *ref = overlay->forwardingAddress();
-     return true;
- }
- 
- inline void
- js::Nursery::maybeSetForwardingPointer(JSTracer* trc, void* oldData, void* newData, bool direct)
- {
-     if (trc->isTenuringTracer())
-diff --git a/js/src/gc/RelocationOverlay.h b/js/src/gc/RelocationOverlay.h
---- a/js/src/gc/RelocationOverlay.h
-+++ b/js/src/gc/RelocationOverlay.h
-@@ -11,81 +11,65 @@
- #ifndef gc_RelocationOverlay_h
- #define gc_RelocationOverlay_h
- 
- #include "mozilla/Assertions.h"
- #include "mozilla/EndianUtils.h"
- 
- #include <stdint.h>
- 
-+#include "gc/Cell.h"
- #include "js/HeapAPI.h"
- #include "vm/JSObject.h"
- #include "vm/Shape.h"
- 
- namespace js {
- namespace gc {
- 
--struct Cell;
--
- /*
-  * This structure overlays a Cell that has been moved and provides a way to find
-  * its new location. It's used during generational and compacting GC.
-  */
--class RelocationOverlay
-+class RelocationOverlay : public Cell
- {
--    /* See comment in js/public/HeapAPI.h. */
--    static const uint32_t Relocated = js::gc::Relocated;
--
--    /*
--     * Keep the low 32 bits untouched. Use them to distinguish strings from
--     * objects in the nursery.
--     */
--    uint32_t preserve_;
--
--    /* Set to Relocated when moved. */
--    uint32_t magic_;
--
--    /* The location |this| was moved to. */
--    Cell* newLocation_;
-+    // First word of a Cell has additional requirements from GC. The GC flags
-+    // determine if a Cell is a normal entry or is a RelocationOverlay.
-+    //                3         0
-+    //  -------------------------
-+    //  | NewLocation | GCFlags |
-+    //  -------------------------
-+    uintptr_t dataWithTag_;
- 
-     /* A list entry to track all relocated things. */
-     RelocationOverlay* next_;
- 
-   public:
-     static const RelocationOverlay* fromCell(const Cell* cell) {
--        return reinterpret_cast<const RelocationOverlay*>(cell);
-+        return static_cast<const RelocationOverlay*>(cell);
-     }
- 
-     static RelocationOverlay* fromCell(Cell* cell) {
--        return reinterpret_cast<RelocationOverlay*>(cell);
--    }
--
--    bool isForwarded() const {
--        (void) preserve_; // Suppress warning
--        return magic_ == Relocated;
-+        return static_cast<RelocationOverlay*>(cell);
-     }
- 
-     Cell* forwardingAddress() const {
-         MOZ_ASSERT(isForwarded());
--        return newLocation_;
-+        uintptr_t newLocation = dataWithTag_ & ~Cell::RESERVED_MASK;
-+        return reinterpret_cast<Cell*>(newLocation);
-     }
- 
-     void forwardTo(Cell* cell);
- 
-     RelocationOverlay*& nextRef() {
-         MOZ_ASSERT(isForwarded());
-         return next_;
-     }
- 
-     RelocationOverlay* next() const {
-         MOZ_ASSERT(isForwarded());
-         return next_;
-     }
--
--    static bool isCellForwarded(const Cell* cell) {
--        return fromCell(cell)->isForwarded();
--    }
- };
- 
- } // namespace gc
- } // namespace js
- 
- #endif /* gc_RelocationOverlay_h */
-diff --git a/js/src/gc/Verifier.cpp b/js/src/gc/Verifier.cpp
---- a/js/src/gc/Verifier.cpp
-+++ b/js/src/gc/Verifier.cpp
-@@ -638,18 +638,17 @@ IsValidGCThingPointer(Cell* cell)
- }
- 
- void
- CheckHeapTracer::checkCell(Cell* cell)
- {
-     // Moving
-     if (!IsValidGCThingPointer(cell) ||
-         ((gcType == GCType::Moving) && !IsGCThingValidAfterMovingGC(cell)) ||
--        ((gcType == GCType::NonMoving) &&
--            RelocationOverlay::isCellForwarded(cell)))
-+        ((gcType == GCType::NonMoving) && cell->isForwarded()))
-     {
-         failures++;
-         fprintf(stderr, "Bad pointer %p\n", cell);
-         dumpCellPath();
-     }
- }
- 
- void
-diff --git a/js/src/vm/BigIntType.h b/js/src/vm/BigIntType.h
---- a/js/src/vm/BigIntType.h
-+++ b/js/src/vm/BigIntType.h
-@@ -33,23 +33,26 @@ namespace JS {
- 
- class BigInt final : public js::gc::TenuredCell
- {
-     // StringToBigIntImpl modifies the num_ field of the res argument.
-     template <typename CharT>
-     friend bool js::StringToBigIntImpl(const mozilla::Range<const CharT>& chars,
-                                        uint8_t radix, Handle<BigInt*> res);
- 
-+  protected:
-+    // Reserved word for Cell GC invariants. This also ensures minimum
-+    // structure size.
-+    uintptr_t reserved_;
-+
-   private:
--    // The minimum allocation size is currently 16 bytes (see
--    // SortedArenaList in gc/ArenaList.h).
--    union {
--        mpz_t num_;
--        uint8_t unused_[js::gc::MinCellSize];
--    };
-+    mpz_t num_;
-+
-+  protected:
-+    BigInt() : reserved_(0) { }
- 
-   public:
-     // Allocate and initialize a BigInt value
-     static BigInt* create(JSContext* cx);
- 
-     static BigInt* createFromDouble(JSContext* cx, double d);
- 
-     static BigInt* createFromBoolean(JSContext* cx, bool b);
-diff --git a/js/src/vm/Scope.h b/js/src/vm/Scope.h
---- a/js/src/vm/Scope.h
-+++ b/js/src/vm/Scope.h
-@@ -300,44 +300,34 @@ class WrappedPtrOperations<Scope*, Wrapp
- 
- //
- // The base class of all Scopes.
- //
- class Scope : public js::gc::TenuredCell
- {
-     friend class GCMarker;
- 
--    // The kind determines data_.
--    //
--    // The memory here must be fully initialized, since otherwise the magic_
--    // value for gc::RelocationOverlay will land in the padding and may be
--    // stale.
--    union {
--        ScopeKind kind_;
--        uintptr_t paddedKind_;
--    };
--
-     // The enclosing scope or nullptr.
-     GCPtrScope enclosing_;
- 
-+    // The kind determines data_.
-+    ScopeKind kind_;
-+
-     // If there are any aliased bindings, the shape for the
-     // EnvironmentObject. Otherwise nullptr.
-     GCPtrShape environmentShape_;
- 
-   protected:
-     BaseScopeData* data_;
- 
-     Scope(ScopeKind kind, Scope* enclosing, Shape* environmentShape)
-       : enclosing_(enclosing),
-+        kind_(kind),
-         environmentShape_(environmentShape),
--        data_(nullptr)
--    {
--        paddedKind_ = 0;
--        kind_ = kind;
--    }
-+        data_(nullptr) { }
- 
-     static Scope* create(JSContext* cx, ScopeKind kind, HandleScope enclosing,
-                          HandleShape envShape);
- 
-     template <typename T, typename D>
-     static Scope* create(JSContext* cx, ScopeKind kind, HandleScope enclosing,
-                          HandleShape envShape, mozilla::UniquePtr<T, D> data);
- 
-diff --git a/js/src/vm/StringType.h b/js/src/vm/StringType.h
---- a/js/src/vm/StringType.h
-+++ b/js/src/vm/StringType.h
-@@ -160,23 +160,31 @@ class JSString : public js::gc::Cell
- {
-   protected:
-     static const size_t NUM_INLINE_CHARS_LATIN1   = 2 * sizeof(void*) / sizeof(JS::Latin1Char);
-     static const size_t NUM_INLINE_CHARS_TWO_BYTE = 2 * sizeof(void*) / sizeof(char16_t);
- 
-     /* Fields only apply to string types commented on the right. */
-     struct Data
-     {
--        union {
--            struct {
--                uint32_t           flags_;              /* JSString */
--                uint32_t           length_;             /* JSString */
--            };
--            uintptr_t              flattenData_;        /* JSRope (temporary while flattening) */
--        } u1;
-+        // First word of a Cell has additional requirements from GC and normally
-+        // would store a pointer. If a single word isn't large enough, the length
-+        // is stored separately.
-+        //          32      16       0
-+        //  --------------------------
-+        //  | Length | Index | Flags |
-+        //  --------------------------
-+        //
-+        // NOTE: This is also used for temporary storage while linearizing a Rope.
-+        uintptr_t flags_;                               /* JSString */
-+
-+#if JS_BITS_PER_WORD == 32
-+        // Additional storage for length if |flags_| is too small to fit both.
-+        uint32_t                   length_;             /* JSString */
-+#endif
-         union {
-             union {
-                 /* JS(Fat)InlineString */
-                 JS::Latin1Char     inlineStorageLatin1[NUM_INLINE_CHARS_LATIN1];
-                 char16_t           inlineStorageTwoByte[NUM_INLINE_CHARS_TWO_BYTE];
-             };
-             struct {
-                 union {
-@@ -193,19 +201,21 @@ class JSString : public js::gc::Cell
-             } s;
-         };
-     } d;
- 
-   public:
-     /* Flags exposed only for jits */
- 
-     /*
--     * The Flags Word
-+     * Flag Encoding
-      *
--     * The flags word stores both the string's type and its character encoding.
-+     * The first word of a JSString stores flags, index, and (on some
-+     * platforms) the length. The flags store both the string's type and its
-+     * character encoding.
-      *
-      * If LATIN1_CHARS_BIT is set, the string's characters are stored as Latin1
-      * instead of TwoByte. This flag can also be set for ropes, if both the
-      * left and right nodes are Latin1. Flattening will result in a Latin1
-      * string in this case.
-      *
-      * The other flags store the string's type. Instead of using a dense index
-      * to represent the most-derived type, string types are encoded to allow
-@@ -247,56 +257,55 @@ class JSString : public js::gc::Cell
-      *   Bit 3: IsInline (Inline, FatInline)
-      *
-      *  "HasBase" here refers to the two string types that have a 'base' field:
-      *  JSDependentString and JSUndependedString.
-      *  A JSUndependedString is a JSDependentString which has been 'fixed' (by ensureFixed)
-      *  to be null-terminated.  In such cases, the string must keep marking its base since
-      *  there may be any number of *other* JSDependentStrings transitively depending on it.
-      *
--     * The atom bit (NON_ATOM_BIT) is inverted so that objects and strings can
--     * be differentiated in the nursery: atoms are never in the nursery, so
--     * this bit is always 1 for a nursery string. For an object on a
--     * little-endian architecture, this is the low-order bit of the ObjectGroup
--     * pointer in a JSObject, which will always be zero. A 64-bit big-endian
--     * architecture will need to do something else (the ObjectGroup* is in the
--     * same place as a string's struct { uint32_t flags; uint32_t length; }).
-+     * The atom bit (NON_ATOM_BIT) is inverted and stored in a Cell
-+     * ReservedBit. Atoms are never stored in nursery, so the nursery can use
-+     * this bit to distinguish between JSString (1) and JSObject (0).
-      *
--     * If the INDEX_VALUE_BIT is set the upper 16 bits of the flag word hold the integer
--     * index.
-+     * If the INDEX_VALUE_BIT is set, flags will also hold an integer index.
-      */
- 
--    static const uint32_t NON_ATOM_BIT           = JS_BIT(0);
--    static const uint32_t LINEAR_BIT             = JS_BIT(1);
--    static const uint32_t HAS_BASE_BIT           = JS_BIT(2);
--    static const uint32_t INLINE_CHARS_BIT       = JS_BIT(3);
-+    // The low bits of flag word are reserved by GC.
-+    static_assert(js::gc::Cell::ReservedBits <= 3,
-+                  "JSString::flags must reserve enough bits for Cell");
-+
-+    static const uint32_t NON_ATOM_BIT           = js::gc::Cell::JSSTRING_BIT;
-+    static const uint32_t LINEAR_BIT             = JS_BIT(4);
-+    static const uint32_t HAS_BASE_BIT           = JS_BIT(5);
-+    static const uint32_t INLINE_CHARS_BIT       = JS_BIT(6);
- 
-     static const uint32_t DEPENDENT_FLAGS        = NON_ATOM_BIT | LINEAR_BIT | HAS_BASE_BIT;
--    static const uint32_t UNDEPENDED_FLAGS       = NON_ATOM_BIT | LINEAR_BIT | HAS_BASE_BIT | JS_BIT(4);
--    static const uint32_t EXTENSIBLE_FLAGS       = NON_ATOM_BIT | LINEAR_BIT | JS_BIT(4);
--    static const uint32_t EXTERNAL_FLAGS         = NON_ATOM_BIT | LINEAR_BIT | JS_BIT(5);
-+    static const uint32_t UNDEPENDED_FLAGS       = NON_ATOM_BIT | LINEAR_BIT | HAS_BASE_BIT | JS_BIT(7);
-+    static const uint32_t EXTENSIBLE_FLAGS       = NON_ATOM_BIT | LINEAR_BIT | JS_BIT(7);
-+    static const uint32_t EXTERNAL_FLAGS         = NON_ATOM_BIT | LINEAR_BIT | JS_BIT(8);
- 
--    static const uint32_t FAT_INLINE_MASK        = INLINE_CHARS_BIT | JS_BIT(4);
--    static const uint32_t PERMANENT_ATOM_MASK    = NON_ATOM_BIT | JS_BIT(5);
--    static const uint32_t PERMANENT_ATOM_FLAGS   = JS_BIT(5);
-+    static const uint32_t FAT_INLINE_MASK        = INLINE_CHARS_BIT | JS_BIT(7);
-+    static const uint32_t PERMANENT_ATOM_MASK    = NON_ATOM_BIT | JS_BIT(8);
-+    static const uint32_t PERMANENT_ATOM_FLAGS   = JS_BIT(8);
- 
-     /* Initial flags for thin inline and fat inline strings. */
-     static const uint32_t INIT_THIN_INLINE_FLAGS = NON_ATOM_BIT | LINEAR_BIT | INLINE_CHARS_BIT;
-     static const uint32_t INIT_FAT_INLINE_FLAGS  = NON_ATOM_BIT | LINEAR_BIT | FAT_INLINE_MASK;
-     static const uint32_t INIT_ROPE_FLAGS        = NON_ATOM_BIT;
-     static const uint32_t INIT_FLAT_FLAGS        = NON_ATOM_BIT | LINEAR_BIT;
- 
--    static const uint32_t TYPE_FLAGS_MASK        = JS_BIT(6) - 1;
-+    static const uint32_t TYPE_FLAGS_MASK        = JS_BITMASK(9) - JS_BITMASK(3) + js::gc::Cell::JSSTRING_BIT;
- 
--    static const uint32_t LATIN1_CHARS_BIT       = JS_BIT(6);
-+    static const uint32_t LATIN1_CHARS_BIT       = JS_BIT(9);
- 
--    static const uint32_t INDEX_VALUE_BIT        = JS_BIT(7);
-+    static const uint32_t INDEX_VALUE_BIT        = JS_BIT(10);
-     static const uint32_t INDEX_VALUE_SHIFT      = 16;
- 
--    static const uint32_t PINNED_ATOM_BIT        = JS_BIT(8);
-+    static const uint32_t PINNED_ATOM_BIT        = JS_BIT(11);
- 
-     static const uint32_t MAX_LENGTH             = js::MaxStringLength;
- 
-     static const JS::Latin1Char MAX_LATIN1_CHAR = 0xff;
- 
-     /*
-      * Helper function to validate that a string of a given length is
-      * representable by a JSString. An allocation overflow is reported if false
-@@ -312,20 +321,22 @@ class JSString : public js::gc::Cell
-                       "Inline Latin1 chars must fit in a JSString");
-         static_assert(sizeof(JSString) ==
-                       (offsetof(JSString, d.inlineStorageTwoByte) +
-                        NUM_INLINE_CHARS_TWO_BYTE * sizeof(char16_t)),
-                       "Inline char16_t chars must fit in a JSString");
- 
-         /* Ensure js::shadow::String has the same layout. */
-         using JS::shadow::String;
--        static_assert(offsetof(JSString, d.u1.length_) == offsetof(String, length_),
-+        static_assert(offsetof(JSString, d.flags_) == offsetof(String, flags_),
-+                      "shadow::String flags offset must match JSString");
-+#if JS_BITS_PER_WORD == 32
-+        static_assert(offsetof(JSString, d.length_) == offsetof(String, length_),
-                       "shadow::String length offset must match JSString");
--        static_assert(offsetof(JSString, d.u1.flags_) == offsetof(String, flags_),
--                      "shadow::String flags offset must match JSString");
-+#endif
-         static_assert(offsetof(JSString, d.s.u2.nonInlineCharsLatin1) == offsetof(String, nonInlineCharsLatin1),
-                       "shadow::String nonInlineChars offset must match JSString");
-         static_assert(offsetof(JSString, d.s.u2.nonInlineCharsTwoByte) == offsetof(String, nonInlineCharsTwoByte),
-                       "shadow::String nonInlineChars offset must match JSString");
-         static_assert(offsetof(JSString, d.s.u3.externalFinalizer) == offsetof(String, externalFinalizer),
-                       "shadow::String externalFinalizer offset must match JSString");
-         static_assert(offsetof(JSString, d.inlineStorageLatin1) == offsetof(String, inlineStorageLatin1),
-                       "shadow::String inlineStorage offset must match JSString");
-@@ -352,55 +363,63 @@ class JSString : public js::gc::Cell
- 
-   protected:
-     template <typename CharT>
-     MOZ_ALWAYS_INLINE
-     void setNonInlineChars(const CharT* chars);
- 
-     MOZ_ALWAYS_INLINE
-     uint32_t flags() const {
--        return d.u1.flags_;
-+        return uint32_t(d.flags_);
-     }
- 
-   public:
-     MOZ_ALWAYS_INLINE
-     size_t length() const {
--        return d.u1.length_;
-+#if JS_BITS_PER_WORD == 32
-+        return d.length_;
-+#else
-+        return uint32_t(d.flags_ >> 32);
-+#endif
-     }
- 
-   protected:
-     MOZ_ALWAYS_INLINE
-     void setFlagBit(uint32_t flags) {
--        d.u1.flags_ |= flags;
-+        d.flags_ |= uintptr_t(flags);
-     }
- 
-     MOZ_ALWAYS_INLINE
-     void clearFlagBit(uint32_t flags) {
--        d.u1.flags_ &= ~flags;
-+        d.flags_ &= ~uintptr_t(flags);
-     }
- 
-     MOZ_ALWAYS_INLINE
-     void setLengthAndFlags(uint32_t len, uint32_t flags) {
--        d.u1.flags_ = flags;
--        d.u1.length_ = len;
-+#if JS_BITS_PER_WORD == 32
-+        d.flags_ = flags;
-+        d.length_ = len;
-+#else
-+        d.flags_ = uint64_t(len) << 32 | uint64_t(flags);
-+#endif
-     }
- 
-     // Flatten algorithm stores a temporary word by clobbering flags. This is
-     // not GC-safe and user must ensure JSString::flags are never checked
-     // (including by asserts) while this data is stored.
-     MOZ_ALWAYS_INLINE
-     void setFlattenData(uintptr_t data) {
--        d.u1.flattenData_ = data;
-+        d.flags_ = data;
-     }
- 
-     // To get back the data, values to safely re-initialize clobbered flags
-     // must be provided.
-     MOZ_ALWAYS_INLINE
-     uintptr_t unsetFlattenData(uint32_t len, uint32_t flags) {
--        uintptr_t data = d.u1.flattenData_;
-+        uintptr_t data = d.flags_;
-         setLengthAndFlags(len, flags);
-         return data;
-     }
- 
-     // Get correct non-inline chars enum arm for given type
-     template <typename CharT> MOZ_ALWAYS_INLINE const CharT* nonInlineCharsRaw() const;
- 
-   public:
-@@ -539,24 +558,16 @@ class JSString : public js::gc::Cell
-     }
- 
-     MOZ_ALWAYS_INLINE
-     JSAtom& asAtom() const {
-         MOZ_ASSERT(isAtom());
-         return *(JSAtom*)this;
-     }
- 
--    // Used for distinguishing strings from objects in the nursery. The caller
--    // must ensure that cell is in the nursery (and not forwarded).
--    MOZ_ALWAYS_INLINE
--    static bool nurseryCellIsString(js::gc::Cell* cell) {
--        MOZ_ASSERT(!cell->isTenured());
--        return !static_cast<JSString*>(cell)->isAtom();
--    }
--
-     // Fills |array| with various strings that represent the different string
-     // kinds and character encodings.
-     static bool fillWithRepresentatives(JSContext* cx, js::HandleArrayObject array);
- 
-     /* Only called by the GC for dependent or undepended strings. */
- 
-     inline bool hasBase() const {
-         return flags() & HAS_BASE_BIT;
-@@ -569,24 +580,40 @@ class JSString : public js::gc::Cell
-     /* Only called by the GC for strings with the AllocKind::STRING kind. */
- 
-     inline void finalize(js::FreeOp* fop);
- 
-     /* Gets the number of bytes that the chars take on the heap. */
- 
-     size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf);
- 
--    /* Offsets for direct field from jit code. */
--
--    static size_t offsetOfLength() {
--        return offsetof(JSString, d.u1.length_);
-+    // Offsets for direct field from jit code. A number of places directly
-+    // access 32-bit length and flags fields so do endian trickery here.
-+#if JS_BITS_PER_WORD == 32
-+    static constexpr size_t offsetOfFlags() {
-+        return offsetof(JSString, d.flags_);
-+    }
-+    static constexpr size_t offsetOfLength() {
-+        return offsetof(JSString, d.length_);
-     }
--    static size_t offsetOfFlags() {
--        return offsetof(JSString, d.u1.flags_);
-+#elif defined(MOZ_LITTLE_ENDIAN)
-+    static constexpr size_t offsetOfFlags() {
-+        return offsetof(JSString, d.flags_);
-+    }
-+    static constexpr size_t offsetOfLength() {
-+        return offsetof(JSString, d.flags_) + sizeof(uint32_t);
-     }
-+#else
-+    static constexpr size_t offsetOfFlags() {
-+        return offsetof(JSString, d.flags_) + sizeof(uint32_t);
-+    }
-+    static constexpr size_t offsetOfLength() {
-+        return offsetof(JSString, d.flags_);
-+    }
-+#endif
- 
-   private:
-     // To help avoid writing Spectre-unsafe code, we only allow MacroAssembler
-     // to call the method below.
-     friend class js::jit::MacroAssembler;
-     static size_t offsetOfNonInlineChars() {
-         static_assert(offsetof(JSString, d.s.u2.nonInlineCharsTwoByte) ==
-                       offsetof(JSString, d.s.u2.nonInlineCharsLatin1),
-diff --git a/js/src/vm/SymbolType.h b/js/src/vm/SymbolType.h
---- a/js/src/vm/SymbolType.h
-+++ b/js/src/vm/SymbolType.h
-@@ -27,45 +27,48 @@
- namespace js {
- class AutoAccessAtomsZone;
- } // namespace js
- 
- namespace JS {
- 
- class Symbol : public js::gc::TenuredCell
- {
-+  protected:
-+    // Reserved word for Cell GC invariants. This also ensures minimum
-+    // structure size.
-+    uintptr_t reserved_;
-+
-   private:
-     SymbolCode code_;
- 
-     // Each Symbol gets its own hash code so that we don't have to use
-     // addresses as hash codes (a security hazard).
-     js::HashNumber hash_;
- 
-     JSAtom* description_;
- 
--    // The minimum allocation size is sizeof(JSString): 16 bytes on 32-bit
--    // architectures and 24 bytes on 64-bit.  A size_t of padding makes Symbol
--    // the minimum size on both.
--    size_t unused_;
--
-     Symbol(SymbolCode code, js::HashNumber hash, JSAtom* desc)
--        : code_(code), hash_(hash), description_(desc)
--    {
--        // Silence warnings about unused_ being... unused.
--        (void)unused_;
--        static_assert(uint32_t(SymbolCode::WellKnownAPILimit) == JS::shadow::Symbol::WellKnownAPILimit,
--                      "JS::shadow::Symbol::WellKnownAPILimit must match SymbolCode::WellKnownAPILimit");
--    }
-+        : reserved_(0), code_(code), hash_(hash), description_(desc) { }
- 
-     Symbol(const Symbol&) = delete;
-     void operator=(const Symbol&) = delete;
- 
-     static Symbol*
-     newInternal(JSContext* cx, SymbolCode code, js::HashNumber hash, JSAtom* description);
- 
-+    static void staticAsserts() {
-+        static_assert(uint32_t(SymbolCode::WellKnownAPILimit) == JS::shadow::Symbol::WellKnownAPILimit,
-+                      "JS::shadow::Symbol::WellKnownAPILimit must match SymbolCode::WellKnownAPILimit");
-+        static_assert(offsetof(Symbol, reserved_) == offsetof(JS::shadow::Symbol, reserved_),
-+                      "JS::shadow::Symbol::reserved_ offset must match SymbolCode::reserved_");
-+        static_assert(offsetof(Symbol, code_) == offsetof(JS::shadow::Symbol, code_),
-+                      "JS::shadow::Symbol::code_ offset must match SymbolCode::code_");
-+    }
-+
-   public:
-     static Symbol* new_(JSContext* cx, SymbolCode code, JSString* description);
-     static Symbol* for_(JSContext* cx, js::HandleString description);
- 
-     JSAtom* description() const { return description_; }
-     SymbolCode code() const { return code_; }
-     js::HashNumber hash() const { return hash_; }
- 

+ 0 - 952
frg/work-js/mozilla-release/patches/mozilla-central-push_430918.patch

@@ -1,952 +0,0 @@
-# HG changeset patch
-# User Tooru Fujisawa <arai_a@mac.com>
-# Date 1533854957 -32400
-#      Fri Aug 10 07:49:17 2018 +0900
-# Node ID e20a86a9b5756d9bf2ec3c48b1c7ddbdb95a9eba
-# Parent  60a38b319b323f9b8c44040eedecb49715a129b0
-Bug 1456404 - Part 1: Move loop related bytecode/offset handling to LoopControl. r=jwalden
-
-diff --git a/js/src/frontend/BytecodeControlStructures.cpp b/js/src/frontend/BytecodeControlStructures.cpp
---- a/js/src/frontend/BytecodeControlStructures.cpp
-+++ b/js/src/frontend/BytecodeControlStructures.cpp
-@@ -3,20 +3,23 @@
-  * This Source Code Form is subject to the terms of the Mozilla Public
-  * License, v. 2.0. If a copy of the MPL was not distributed with this
-  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- 
- #include "frontend/BytecodeControlStructures.h"
- 
- #include "frontend/BytecodeEmitter.h"
- #include "frontend/EmitterScope.h"
-+#include "vm/Opcodes.h"
- 
- using namespace js;
- using namespace js::frontend;
- 
-+using mozilla::Maybe;
-+
- NestableControl::NestableControl(BytecodeEmitter* bce, StatementKind kind)
-   : Nestable<NestableControl>(&bce->innermostNestableControl),
-     kind_(kind),
-     emitterScope_(bce->innermostEmitterScopeNoCheck())
- {}
- 
- BreakableControl::BreakableControl(BytecodeEmitter* bce, StatementKind kind)
-   : NestableControl(bce, kind)
-@@ -33,18 +36,17 @@ BreakableControl::patchBreaks(BytecodeEm
- LabelControl::LabelControl(BytecodeEmitter* bce, JSAtom* label, ptrdiff_t startOffset)
-   : BreakableControl(bce, StatementKind::Label),
-     label_(bce->cx, label),
-     startOffset_(startOffset)
- {}
- 
- LoopControl::LoopControl(BytecodeEmitter* bce, StatementKind loopKind)
-   : BreakableControl(bce, loopKind),
--    tdzCache_(bce),
--    continueTarget({ -1 })
-+    tdzCache_(bce)
- {
-     MOZ_ASSERT(is<LoopControl>());
- 
-     LoopControl* enclosingLoop = findNearest<LoopControl>(enclosing());
- 
-     stackDepth_ = bce->stackDepth;
-     loopDepth_ = enclosingLoop ? enclosingLoop->loopDepth_ + 1 : 1;
- 
-@@ -71,38 +73,102 @@ LoopControl::LoopControl(BytecodeEmitter
-         canIonOsr_ = (enclosingLoop->canIonOsr_ &&
-                       stackDepth_ == enclosingLoop->stackDepth_ + loopSlots);
-     } else {
-         canIonOsr_ = stackDepth_ == loopSlots;
-     }
- }
- 
- bool
-+LoopControl::emitContinueTarget(BytecodeEmitter* bce)
-+{
-+    if (!bce->emitJumpTarget(&continueTarget_))
-+        return false;
-+    return true;
-+}
-+
-+bool
- LoopControl::emitSpecialBreakForDone(BytecodeEmitter* bce)
- {
-     // This doesn't pop stack values, nor handle any other controls.
-     // Should be called on the toplevel of the loop.
-     MOZ_ASSERT(bce->stackDepth == stackDepth_);
-     MOZ_ASSERT(bce->innermostNestableControl == this);
- 
-     if (!bce->newSrcNote(SRC_BREAK))
-         return false;
-     if (!bce->emitJump(JSOP_GOTO, &breaks))
-         return false;
- 
-     return true;
- }
- 
- bool
-+LoopControl::emitEntryJump(BytecodeEmitter* bce)
-+{
-+    if (!bce->emitJump(JSOP_GOTO, &entryJump_))
-+        return false;
-+    return true;
-+}
-+
-+bool
-+LoopControl::emitLoopHead(BytecodeEmitter* bce, const Maybe<uint32_t>& nextPos)
-+{
-+    if (nextPos) {
-+        if (!bce->updateSourceCoordNotes(*nextPos))
-+            return false;
-+    }
-+
-+    head_ = { bce->offset() };
-+    if (!bce->emit1(JSOP_LOOPHEAD))
-+        return false;
-+
-+    return true;
-+}
-+
-+bool
-+LoopControl::emitLoopEntry(BytecodeEmitter* bce, const Maybe<uint32_t>& nextPos)
-+{
-+    if (nextPos) {
-+        if (!bce->updateSourceCoordNotes(*nextPos))
-+            return false;
-+    }
-+
-+    JumpTarget entry = { bce->offset() };
-+    bce->patchJumpsToTarget(entryJump_, entry);
-+
-+    MOZ_ASSERT(loopDepth_ > 0);
-+
-+    uint8_t loopDepthAndFlags = PackLoopEntryDepthHintAndFlags(loopDepth_,
-+                                                               canIonOsr_);
-+    if (!bce->emit2(JSOP_LOOPENTRY, loopDepthAndFlags))
-+        return false;
-+
-+    return true;
-+}
-+
-+bool
-+LoopControl::emitLoopEnd(BytecodeEmitter* bce, JSOp op)
-+{
-+    JumpList beq;
-+    if (!bce->emitBackwardJump(op, head_, &beq, &breakTarget_))
-+        return false;
-+
-+    loopEndOffset_ = beq.offset;
-+
-+    return true;
-+}
-+
-+bool
- LoopControl::patchBreaksAndContinues(BytecodeEmitter* bce)
- {
--    MOZ_ASSERT(continueTarget.offset != -1);
-+    MOZ_ASSERT(continueTarget_.offset != -1);
-     if (!patchBreaks(bce))
-         return false;
--    bce->patchJumpsToTarget(continues, continueTarget);
-+    bce->patchJumpsToTarget(continues, continueTarget_);
-     return true;
- }
- 
- TryFinallyControl::TryFinallyControl(BytecodeEmitter* bce, StatementKind kind)
-   : NestableControl(bce, kind),
-     emittingSubroutine_(false)
- {
-     MOZ_ASSERT(is<TryFinallyControl>());
-diff --git a/js/src/frontend/BytecodeControlStructures.h b/js/src/frontend/BytecodeControlStructures.h
---- a/js/src/frontend/BytecodeControlStructures.h
-+++ b/js/src/frontend/BytecodeControlStructures.h
-@@ -3,25 +3,27 @@
-  * This Source Code Form is subject to the terms of the Mozilla Public
-  * License, v. 2.0. If a copy of the MPL was not distributed with this
-  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- 
- #ifndef frontend_BytecodeControlStructures_h
- #define frontend_BytecodeControlStructures_h
- 
- #include "mozilla/Attributes.h"
-+#include "mozilla/Maybe.h"
- 
- #include <stddef.h>
- #include <stdint.h>
- 
- #include "ds/Nestable.h"
- #include "frontend/JumpList.h"
- #include "frontend/SharedContext.h"
- #include "frontend/TDZCheckCache.h"
- #include "gc/Rooting.h"
-+#include "vm/BytecodeUtil.h"
- #include "vm/StringType.h"
- 
- namespace js {
- namespace frontend {
- 
- struct BytecodeEmitter;
- class EmitterScope;
- 
-@@ -98,44 +100,127 @@ NestableControl::is<LabelControl>() cons
- }
- 
- class LoopControl : public BreakableControl
- {
-     // Loops' children are emitted in dominance order, so they can always
-     // have a TDZCheckCache.
-     TDZCheckCache tdzCache_;
- 
-+    // Here's the basic structure of a loop:
-+    //
-+    //     # Entry jump
-+    //     JSOP_GOTO entry
-+    //
-+    //   head:
-+    //     JSOP_LOOPHEAD
-+    //     {loop body after branch}
-+    //
-+    //   entry:
-+    //     JSOP_ENTRY
-+    //     {loop body before branch}
-+    //
-+    //     # Loop end, backward jump
-+    //     JSOP_GOTO/JSOP_IFNE head
-+    //
-+    //   breakTarget:
-+    //
-+    // `continueTarget` can be placed in arbitrary place by calling
-+    // `setContinueTarget` or `emitContinueTarget` (see comment above them for
-+    // more details).
-+
-+    // The offset of backward jump at the end of loop.
-+    ptrdiff_t loopEndOffset_ = -1;
-+
-+    // The jump into JSOP_LOOPENTRY.
-+    JumpList entryJump_;
-+
-+    // The bytecode offset of JSOP_LOOPHEAD.
-+    JumpTarget head_ = { -1 };
-+
-+    // The target of break statement jumps.
-+    JumpTarget breakTarget_ = { -1 };
-+
-+    // The target of continue statement jumps, e.g., the update portion of a
-+    // for(;;) loop.
-+    JumpTarget continueTarget_ = { -1 };
-+
-     // Stack depth when this loop was pushed on the control stack.
-     int32_t stackDepth_;
- 
-     // The loop nesting depth. Used as a hint to Ion.
-     uint32_t loopDepth_;
- 
-     // Can we OSR into Ion from here? True unless there is non-loop state on the stack.
-     bool canIonOsr_;
- 
-   public:
--    // The target of continue statement jumps, e.g., the update portion of a
--    // for(;;) loop.
--    JumpTarget continueTarget;
--
-     // Offset of the last continue in the loop.
-     JumpList continues;
- 
-     LoopControl(BytecodeEmitter* bce, StatementKind loopKind);
- 
--    uint32_t loopDepth() const {
--        return loopDepth_;
-+    ptrdiff_t headOffset() const {
-+        return head_.offset;
-+    }
-+    ptrdiff_t loopEndOffset() const {
-+        return loopEndOffset_;
-+    }
-+    ptrdiff_t breakTargetOffset() const {
-+        return breakTarget_.offset;
-+    }
-+    ptrdiff_t continueTargetOffset() const {
-+        return continueTarget_.offset;
-+    }
-+
-+    // The offset of the backward jump at the loop end from the loop's top, in
-+    // case there was an entry jump.
-+    ptrdiff_t loopEndOffsetFromEntryJump() const {
-+        return loopEndOffset_ - entryJump_.offset;
-+    }
-+
-+    // The offset of the backward jump at the loop end from the loop's top, in
-+    // case there was no entry jump.
-+    ptrdiff_t loopEndOffsetFromLoopHead() const {
-+        return loopEndOffset_ - head_.offset;
-     }
- 
--    bool canIonOsr() const {
--        return canIonOsr_;
-+    // The offset of the continue target from the loop's top, in case there was
-+    // no entry jump.
-+    ptrdiff_t continueTargetOffsetFromLoopHead() const {
-+        return continueTarget_.offset - head_.offset;
-     }
- 
-+    // A continue target can be specified by the following 2 ways:
-+    //   * Use the existing JUMPTARGET by calling `setContinueTarget` with
-+    //     the offset of the JUMPTARGET
-+    //   * Generate a new JUMPTARGETby calling `emitContinueTarget`
-+    void setContinueTarget(ptrdiff_t offset) {
-+        continueTarget_.offset = offset;
-+    }
-+    MOZ_MUST_USE bool emitContinueTarget(BytecodeEmitter* bce);
-+
-+    // Emit a jump to break target from the top level of the loop.
-     MOZ_MUST_USE bool emitSpecialBreakForDone(BytecodeEmitter* bce);
-+
-+    MOZ_MUST_USE bool emitEntryJump(BytecodeEmitter* bce);
-+
-+    // `nextPos` is the offset in the source code for the character that
-+    // corresponds to the next instruction after JSOP_LOOPHEAD.
-+    // Can be Nothing() if not available.
-+    MOZ_MUST_USE bool emitLoopHead(BytecodeEmitter* bce,
-+                                   const mozilla::Maybe<uint32_t>& nextPos);
-+
-+    // `nextPos` is the offset in the source code for the character that
-+    // corresponds to the next instruction after JSOP_LOOPENTRY.
-+    // Can be Nothing() if not available.
-+    MOZ_MUST_USE bool emitLoopEntry(BytecodeEmitter* bce,
-+                                    const mozilla::Maybe<uint32_t>& nextPos);
-+
-+    MOZ_MUST_USE bool emitLoopEnd(BytecodeEmitter* bce, JSOp op);
-     MOZ_MUST_USE bool patchBreaksAndContinues(BytecodeEmitter* bce);
- };
- template <>
- inline bool
- NestableControl::is<LoopControl>() const
- {
-     return StatementKindIsLoop(kind_);
- }
-diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp
---- a/js/src/frontend/BytecodeEmitter.cpp
-+++ b/js/src/frontend/BytecodeEmitter.cpp
-@@ -510,61 +510,32 @@ BytecodeEmitter::updateSourceCoordNotes(
-             return true;
-         if (!newSrcNote2(SRC_COLSPAN, SN_COLSPAN_TO_OFFSET(colspan)))
-             return false;
-         current->lastColumn = columnIndex;
-     }
-     return true;
- }
- 
--bool
--BytecodeEmitter::emitLoopHead(ParseNode* nextpn, JumpTarget* top)
--{
--    if (nextpn) {
--        /*
--         * Try to give the JSOP_LOOPHEAD the same line number as the next
--         * instruction. nextpn is often a block, in which case the next
--         * instruction typically comes from the first statement inside.
--         */
--        if (nextpn->isKind(ParseNodeKind::LexicalScope))
--            nextpn = nextpn->scopeBody();
--        MOZ_ASSERT_IF(nextpn->isKind(ParseNodeKind::StatementList), nextpn->isArity(PN_LIST));
--        if (nextpn->isKind(ParseNodeKind::StatementList) && nextpn->pn_head)
--            nextpn = nextpn->pn_head;
--        if (!updateSourceCoordNotes(nextpn->pn_pos.begin))
--            return false;
--    }
--
--    *top = { offset() };
--    return emit1(JSOP_LOOPHEAD);
--}
--
--bool
--BytecodeEmitter::emitLoopEntry(ParseNode* nextpn, JumpList entryJump)
--{
--    if (nextpn) {
--        /* Update the line number, as for LOOPHEAD. */
--        if (nextpn->isKind(ParseNodeKind::LexicalScope))
--            nextpn = nextpn->scopeBody();
--        MOZ_ASSERT_IF(nextpn->isKind(ParseNodeKind::StatementList), nextpn->isArity(PN_LIST));
--        if (nextpn->isKind(ParseNodeKind::StatementList) && nextpn->pn_head)
--            nextpn = nextpn->pn_head;
--        if (!updateSourceCoordNotes(nextpn->pn_pos.begin))
--            return false;
--    }
--
--    JumpTarget entry{ offset() };
--    patchJumpsToTarget(entryJump, entry);
--
--    LoopControl& loopInfo = innermostNestableControl->as<LoopControl>();
--    MOZ_ASSERT(loopInfo.loopDepth() > 0);
--
--    uint8_t loopDepthAndFlags = PackLoopEntryDepthHintAndFlags(loopInfo.loopDepth(),
--                                                               loopInfo.canIonOsr());
--    return emit2(JSOP_LOOPENTRY, loopDepthAndFlags);
-+Maybe<uint32_t>
-+BytecodeEmitter::getOffsetForLoop(ParseNode* nextpn)
-+{
-+    if (!nextpn)
-+        return Nothing();
-+
-+    // Try to give the JSOP_LOOPHEAD and JSOP_LOOPENTRY the same line number as
-+    // the next instruction. nextpn is often a block, in which case the next
-+    // instruction typically comes from the first statement inside.
-+    if (nextpn->isKind(ParseNodeKind::LexicalScope))
-+        nextpn = nextpn->scopeBody();
-+    MOZ_ASSERT_IF(nextpn->isKind(ParseNodeKind::StatementList), nextpn->isArity(PN_LIST));
-+    if (nextpn->isKind(ParseNodeKind::StatementList) && nextpn->pn_head)
-+        nextpn = nextpn->pn_head;
-+
-+    return Some(nextpn->pn_pos.begin);
- }
- 
- void
- BytecodeEmitter::checkTypeSet(JSOp op)
- {
-     if (CodeSpec[op].format & JOF_TYPESET) {
-         if (typesetCount < UINT16_MAX)
-             typesetCount++;
-@@ -4675,32 +4646,28 @@ BytecodeEmitter::emitSpread(bool allowSe
-     // find the loop-closing jump.
-     unsigned noteIndex;
-     if (!newSrcNote(SRC_FOR_OF, &noteIndex))
-         return false;
- 
-     // Jump down to the loop condition to minimize overhead, assuming at least
-     // one iteration.  (This is also what we do for loops; whether this
-     // assumption holds for spreads is an unanswered question.)
--    JumpList initialJump;
--    if (!emitJump(JSOP_GOTO, &initialJump))               // NEXT ITER ARR I (during the goto)
--        return false;
--
--    JumpTarget top{ -1 };
--    if (!emitLoopHead(nullptr, &top))                     // NEXT ITER ARR I
-+    if (!loopInfo.emitEntryJump(this))                    // NEXT ITER ARR I (during the goto)
-+        return false;
-+
-+    if (!loopInfo.emitLoopHead(this, Nothing()))          // NEXT ITER ARR I
-         return false;
- 
-     // When we enter the goto above, we have NEXT ITER ARR I on the stack. But
-     // when we reach this point on the loop backedge (if spreading produces at
-     // least one value), we've additionally pushed a RESULT iteration value.
-     // Increment manually to reflect this.
-     this->stackDepth++;
- 
--    JumpList beq;
--    JumpTarget breakTarget{ -1 };
-     {
- #ifdef DEBUG
-         auto loopDepth = this->stackDepth;
- #endif
- 
-         // Emit code to assign result.value to the iteration variable.
-         if (!emitAtomOp(cx->names().value, JSOP_GETPROP)) // NEXT ITER ARR I VALUE
-             return false;
-@@ -4708,46 +4675,49 @@ BytecodeEmitter::emitSpread(bool allowSe
-             return false;
- 
-         MOZ_ASSERT(this->stackDepth == loopDepth - 1);
- 
-         // Spread operations can't contain |continue|, so don't bother setting loop
-         // and enclosing "update" offsets, as we do with for-loops.
- 
-         // COME FROM the beginning of the loop to here.
--        if (!emitLoopEntry(nullptr, initialJump))         // NEXT ITER ARR I
-+        if (!loopInfo.emitLoopEntry(this, Nothing()))     // NEXT ITER ARR I
-             return false;
- 
-         if (!emitDupAt(3))                                // NEXT ITER ARR I NEXT
-             return false;
-         if (!emitDupAt(3))                                // NEXT ITER ARR I NEXT ITER
-             return false;
-         if (!emitIteratorNext(nullptr, IteratorKind::Sync, allowSelfHosted))  // ITER ARR I RESULT
-             return false;
-         if (!emit1(JSOP_DUP))                             // NEXT ITER ARR I RESULT RESULT
-             return false;
-         if (!emitAtomOp(cx->names().done, JSOP_GETPROP))  // NEXT ITER ARR I RESULT DONE
-             return false;
- 
--        if (!emitBackwardJump(JSOP_IFEQ, top, &beq, &breakTarget)) // NEXT ITER ARR I RESULT
-+        if (!loopInfo.emitLoopEnd(this, JSOP_IFEQ))       // NEXT ITER ARR I RESULT
-             return false;
- 
-         MOZ_ASSERT(this->stackDepth == loopDepth);
-     }
- 
-     // Let Ion know where the closing jump of this loop is.
--    if (!setSrcNoteOffset(noteIndex, 0, beq.offset - initialJump.offset))
-+1    if (!setSrcNoteOffset(noteIndex, 0, loopInfo.loopEndOffsetFromEntryJump()))
-         return false;
- 
-     // No breaks or continues should occur in spreads.
-     MOZ_ASSERT(loopInfo.breaks.offset == -1);
-     MOZ_ASSERT(loopInfo.continues.offset == -1);
- 
--    if (!tryNoteList.append(JSTRY_FOR_OF, stackDepth, top.offset, breakTarget.offset))
--        return false;
-+    if (!tryNoteList.append(JSTRY_FOR_OF, stackDepth, loopInfo.headOffset(),
-+                            loopInfo.breakTargetOffset()))
-+    {
-+        return false;
-+    }
- 
-     if (!emit2(JSOP_PICK, 4))                             // ITER ARR FINAL_INDEX RESULT NEXT
-         return false;
-     if (!emit2(JSOP_PICK, 4))                             // ARR FINAL_INDEX RESULT NEXT ITER
-         return false;
- 
-     return emitPopN(3);                                   // ARR FINAL_INDEX
- }
-@@ -4866,22 +4836,20 @@ BytecodeEmitter::emitForOf(ParseNode* fo
- 
-     ForOfLoopControl loopInfo(this, iterDepth, allowSelfHostedIter, iterKind);
- 
-     // Annotate so IonMonkey can find the loop-closing jump.
-     unsigned noteIndex;
-     if (!newSrcNote(SRC_FOR_OF, &noteIndex))
-         return false;
- 
--    JumpList initialJump;
--    if (!emitJump(JSOP_GOTO, &initialJump))               // NEXT ITER UNDEF
--        return false;
--
--    JumpTarget top{ -1 };
--    if (!emitLoopHead(nullptr, &top))                     // NEXT ITER UNDEF
-+    if (!loopInfo.emitEntryJump(this))                    // NEXT ITER UNDEF
-+        return false;
-+
-+    if (!loopInfo.emitLoopHead(this, Nothing()))          // NEXT ITER UNDEF
-         return false;
- 
-     // If the loop had an escaping lexical declaration, replace the current
-     // environment with an dead zoned one to implement TDZ semantics.
-     if (headLexicalEmitterScope) {
-         // The environment chain only includes an environment for the for-of
-         // loop head *if* a scope binding is captured, thereby requiring
-         // recreation each iteration. If a lexical scope exists for the head,
-@@ -4898,18 +4866,16 @@ BytecodeEmitter::emitForOf(ParseNode* fo
-                 return false;
-         }
- 
-         // For uncaptured bindings, put them back in TDZ.
-         if (!headLexicalEmitterScope->deadZoneFrameSlots(this))
-             return false;
-     }
- 
--    JumpList beq;
--    JumpTarget breakTarget{ -1 };
-     {
- #ifdef DEBUG
-         auto loopDepth = this->stackDepth;
- #endif
- 
-         // Make sure this code is attributed to the "for".
-         if (!updateSourceCoordNotes(forOfHead->pn_pos.begin))
-             return false;
-@@ -4975,39 +4941,41 @@ BytecodeEmitter::emitForOf(ParseNode* fo
-             return false;
- 
-         MOZ_ASSERT(stackDepth == loopDepth,
-                    "the stack must be balanced around the for-of body");
- 
-         if (!loopInfo.emitEndCodeNeedingIteratorClose(this))
-             return false;
- 
--        // Set offset for continues.
--        loopInfo.continueTarget = { offset() };
--
--        if (!emitLoopEntry(forHeadExpr, initialJump))     // NEXT ITER UNDEF
--            return false;
-+        loopInfo.setContinueTarget(offset());
-+
-+        if (!loopInfo.emitLoopEntry(this, getOffsetForLoop(forHeadExpr)))
-+            return false;                                 // NEXT ITER UNDEF
- 
-         if (!emit1(JSOP_FALSE))                           // NEXT ITER UNDEF FALSE
-             return false;
--        if (!emitBackwardJump(JSOP_IFEQ, top, &beq, &breakTarget))
--            return false;                                 // NEXT ITER UNDEF
-+        if (!loopInfo.emitLoopEnd(this, JSOP_IFEQ))       // NEXT ITER UNDEF
-+            return false;
- 
-         MOZ_ASSERT(this->stackDepth == loopDepth);
-     }
- 
-     // Let Ion know where the closing jump of this loop is.
--    if (!setSrcNoteOffset(noteIndex, 0, beq.offset - initialJump.offset))
-+    if (!setSrcNoteOffset(noteIndex, 0, loopInfo.loopEndOffsetFromEntryJump()))
-         return false;
- 
-     if (!loopInfo.patchBreaksAndContinues(this))
-         return false;
- 
--    if (!tryNoteList.append(JSTRY_FOR_OF, stackDepth, top.offset, breakTarget.offset))
--        return false;
-+    if (!tryNoteList.append(JSTRY_FOR_OF, stackDepth, loopInfo.headOffset(),
-+                            loopInfo.breakTargetOffset()))
-+    {
-+        return false;
-+    }
- 
-     return emitPopN(3);                                   //
- }
- 
- bool
- BytecodeEmitter::emitForIn(ParseNode* forInLoop, EmitterScope* headLexicalEmitterScope)
- {
-     MOZ_ASSERT(forInLoop->isKind(ParseNodeKind::For));
-@@ -5064,22 +5032,20 @@ BytecodeEmitter::emitForIn(ParseNode* fo
- 
-     /* Annotate so IonMonkey can find the loop-closing jump. */
-     unsigned noteIndex;
-     if (!newSrcNote(SRC_FOR_IN, &noteIndex))
-         return false;
- 
-     // Jump down to the loop condition to minimize overhead (assuming at least
-     // one iteration, just like the other loop forms).
--    JumpList initialJump;
--    if (!emitJump(JSOP_GOTO, &initialJump))               // ITER ITERVAL
--        return false;
--
--    JumpTarget top{ -1 };
--    if (!emitLoopHead(nullptr, &top))                     // ITER ITERVAL
-+    if (!loopInfo.emitEntryJump(this))                    // ITER ITERVAL
-+        return false;
-+
-+    if (!loopInfo.emitLoopHead(this, Nothing()))          // ITER ITERVAL
-         return false;
- 
-     // If the loop had an escaping lexical declaration, replace the current
-     // environment with an dead zoned one to implement TDZ semantics.
-     if (headLexicalEmitterScope) {
-         // The environment chain only includes an environment for the for-in
-         // loop head *if* a scope binding is captured, thereby requiring
-         // recreation each iteration. If a lexical scope exists for the head,
-@@ -5117,48 +5083,46 @@ BytecodeEmitter::emitForIn(ParseNode* fo
-     }
- 
-     // Perform the loop body.
-     ParseNode* forBody = forInLoop->pn_right;
-     if (!emitTree(forBody))                               // ITER ITERVAL
-         return false;
- 
-     // Set offset for continues.
--    loopInfo.continueTarget = { offset() };
-+    loopInfo.setContinueTarget(offset());
- 
-     // Make sure this code is attributed to the "for".
-     if (!updateSourceCoordNotes(forInHead->pn_pos.begin))
-         return false;
- 
--    if (!emitLoopEntry(nullptr, initialJump))             // ITER ITERVAL
-+    if (!loopInfo.emitLoopEntry(this, Nothing()))         // ITER ITERVAL
-         return false;
-     if (!emit1(JSOP_POP))                                 // ITER
-         return false;
-     if (!emit1(JSOP_MOREITER))                            // ITER NEXTITERVAL?
-         return false;
-     if (!emit1(JSOP_ISNOITER))                            // ITER NEXTITERVAL? ISNOITER
-         return false;
- 
--    JumpList beq;
--    JumpTarget breakTarget{ -1 };
--    if (!emitBackwardJump(JSOP_IFEQ, top, &beq, &breakTarget))
--        return false;                                     // ITER NEXTITERVAL
-+    if (!loopInfo.emitLoopEnd(this, JSOP_IFEQ))           // ITER NEXTITERVAL
-+        return false;
- 
-     // Set the srcnote offset so we can find the closing jump.
--    if (!setSrcNoteOffset(noteIndex, 0, beq.offset - initialJump.offset))
-+    if (!setSrcNoteOffset(noteIndex, 0, loopInfo.loopEndOffsetFromEntryJump()))
-         return false;
- 
-     if (!loopInfo.patchBreaksAndContinues(this))
-         return false;
- 
-     // Pop the enumeration value.
-     if (!emit1(JSOP_POP))                                 // ITER
-         return false;
- 
--    if (!tryNoteList.append(JSTRY_FOR_IN, this->stackDepth, top.offset, offset()))
-+    if (!tryNoteList.append(JSTRY_FOR_IN, this->stackDepth, loopInfo.headOffset(), offset()))
-         return false;
- 
-     return emit1(JSOP_ENDITER);                           //
- }
- 
- /* C-style `for (init; cond; update) ...` loop. */
- bool
- BytecodeEmitter::emitCStyleFor(ParseNode* pn, EmitterScope* headLexicalEmitterScope)
-@@ -5239,39 +5203,39 @@ BytecodeEmitter::emitCStyleFor(ParseNode
-      * from the top local variable by the length of the JSOP_GOTO
-      * emitted in between tmp and top if this loop has a condition.
-      */
-     unsigned noteIndex;
-     if (!newSrcNote(SRC_FOR, &noteIndex))
-         return false;
-     if (!emit1(JSOP_NOP))
-         return false;
--    ptrdiff_t tmp = offset();
--
--    JumpList jmp;
-+    ptrdiff_t top = offset();
-+
-     if (forHead->pn_kid2) {
-         /* Goto the loop condition, which branches back to iterate. */
--        if (!emitJump(JSOP_GOTO, &jmp))
-+        if (!loopInfo.emitEntryJump(this))
-             return false;
-     }
- 
-     /* Emit code for the loop body. */
--    JumpTarget top{ -1 };
--    if (!emitLoopHead(forBody, &top))
--        return false;
--    if (jmp.offset == -1 && !emitLoopEntry(forBody, jmp))
--        return false;
-+    if (!loopInfo.emitLoopHead(this, getOffsetForLoop(forBody)))
-+        return false;
-+    if (!forHead->pn_kid2) {
-+        if (!loopInfo.emitLoopEntry(this, getOffsetForLoop(forBody)))
-+            return false;
-+    }
- 
-     if (!emitTreeInBranch(forBody))
-         return false;
- 
-     // Set loop and enclosing "update" offsets, for continue.  Note that we
-     // continue to immediately *before* the block-freshening: continuing must
-     // refresh the block.
--    if (!emitJumpTarget(&loopInfo.continueTarget))
-+    if (!loopInfo.emitContinueTarget(this))
-         return false;
- 
-     // ES 13.7.4.8 step 3.e. The per-iteration freshening.
-     if (forLoopRequiresFreshening) {
-         MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope());
-         MOZ_ASSERT(headLexicalEmitterScope->scope(this)->kind() == ScopeKind::Lexical);
- 
-         if (headLexicalEmitterScope->hasEnvironment()) {
-@@ -5301,49 +5265,49 @@ BytecodeEmitter::emitCStyleFor(ParseNode
-             current->lastColumn = 0;
-         }
-     }
- 
-     ptrdiff_t tmp3 = offset();
- 
-     if (forHead->pn_kid2) {
-         /* Fix up the goto from top to target the loop condition. */
--        MOZ_ASSERT(jmp.offset >= 0);
--        if (!emitLoopEntry(forHead->pn_kid2, jmp))
-+        if (!loopInfo.emitLoopEntry(this, getOffsetForLoop(forHead->pn_kid2)))
-             return false;
- 
-         if (!emitTree(forHead->pn_kid2))
-             return false;
-     } else if (!forHead->pn_kid3) {
-         // If there is no condition clause and no update clause, mark
-         // the loop-ending "goto" with the location of the "for".
-         // This ensures that the debugger will stop on each loop
-         // iteration.
-         if (!updateSourceCoordNotes(pn->pn_pos.begin))
-             return false;
-     }
- 
-     /* Set the first note offset so we can find the loop condition. */
--    if (!setSrcNoteOffset(noteIndex, 0, tmp3 - tmp))
--        return false;
--    if (!setSrcNoteOffset(noteIndex, 1, loopInfo.continueTarget.offset - tmp))
-+    if (!setSrcNoteOffset(noteIndex, 0, tmp3 - top))
-+        return false;
-+    if (!setSrcNoteOffset(noteIndex, 1, loopInfo.continueTargetOffset() - top))
-         return false;
- 
-     /* If no loop condition, just emit a loop-closing jump. */
--    JumpList beq;
--    JumpTarget breakTarget{ -1 };
--    if (!emitBackwardJump(forHead->pn_kid2 ? JSOP_IFNE : JSOP_GOTO, top, &beq, &breakTarget))
-+    if (!loopInfo.emitLoopEnd(this, forHead->pn_kid2 ? JSOP_IFNE : JSOP_GOTO))
-         return false;
- 
-     /* The third note offset helps us find the loop-closing jump. */
--    if (!setSrcNoteOffset(noteIndex, 2, beq.offset - tmp))
--        return false;
--
--    if (!tryNoteList.append(JSTRY_LOOP, stackDepth, top.offset, breakTarget.offset))
--        return false;
-+    if (!setSrcNoteOffset(noteIndex, 2, loopInfo.loopEndOffset() - top))
-+        return false;
-+
-+    if (!tryNoteList.append(JSTRY_LOOP, stackDepth, loopInfo.headOffset(),
-+                            loopInfo.breakTargetOffset()))
-+    {
-+        return false;
-+    }
- 
-     if (!loopInfo.patchBreaksAndContinues(this))
-         return false;
- 
-     return true;
- }
- 
- bool
-@@ -5654,55 +5618,55 @@ BytecodeEmitter::emitDo(ParseNode* pn)
-     if (!emit1(JSOP_NOP))
-         return false;
- 
-     unsigned noteIndex2;
-     if (!newSrcNote(SRC_WHILE, &noteIndex2))
-         return false;
- 
-     /* Compile the loop body. */
--    JumpTarget top;
--    if (!emitLoopHead(pn->pn_left, &top))
--        return false;
--
-     LoopControl loopInfo(this, StatementKind::DoLoop);
- 
--    JumpList empty;
--    if (!emitLoopEntry(nullptr, empty))
-+    if (!loopInfo.emitLoopHead(this, getOffsetForLoop(pn->pn_left)))
-+        return false;
-+
-+    if (!loopInfo.emitLoopEntry(this, Nothing()))
-         return false;
- 
-     if (!emitTree(pn->pn_left))
-         return false;
- 
-     // Set the offset for continues.
--    if (!emitJumpTarget(&loopInfo.continueTarget))
-+    if (!loopInfo.emitContinueTarget(this))
-         return false;
- 
-     /* Compile the loop condition, now that continues know where to go. */
-     if (!emitTree(pn->pn_right))
-         return false;
- 
--    JumpList beq;
--    JumpTarget breakTarget{ -1 };
--    if (!emitBackwardJump(JSOP_IFNE, top, &beq, &breakTarget))
--        return false;
--
--    if (!tryNoteList.append(JSTRY_LOOP, stackDepth, top.offset, breakTarget.offset))
--        return false;
-+    if (!loopInfo.emitLoopEnd(this, JSOP_IFNE))
-+        return false;
-+
-+    if (!tryNoteList.append(JSTRY_LOOP, stackDepth, loopInfo.headOffset(),
-+                            loopInfo.breakTargetOffset()))
-+    {
-+        return false;
-+    }
- 
-     /*
-      * Update the annotations with the update and back edge positions, for
-      * IonBuilder.
-      *
-      * Be careful: We must set noteIndex2 before noteIndex in case the noteIndex
-      * note gets bigger.
-      */
--    if (!setSrcNoteOffset(noteIndex2, 0, beq.offset - top.offset))
--        return false;
--    if (!setSrcNoteOffset(noteIndex, 0, 1 + (loopInfo.continueTarget.offset - top.offset)))
-+    if (!setSrcNoteOffset(noteIndex2, 0, loopInfo.loopEndOffsetFromLoopHead()))
-+        return false;
-+    // +1 for NOP above.
-+    if (!setSrcNoteOffset(noteIndex, 0, loopInfo.continueTargetOffsetFromLoopHead() + 1))
-         return false;
- 
-     if (!loopInfo.patchBreaksAndContinues(this))
-         return false;
- 
-     return true;
- }
- 
-@@ -5738,46 +5702,46 @@ BytecodeEmitter::emitWhile(ParseNode* pn
-             return false;
-     }
- 
-     JumpTarget top{ -1 };
-     if (!emitJumpTarget(&top))
-         return false;
- 
-     LoopControl loopInfo(this, StatementKind::WhileLoop);
--    loopInfo.continueTarget = top;
-+    loopInfo.setContinueTarget(top.offset);
- 
-     unsigned noteIndex;
-     if (!newSrcNote(SRC_WHILE, &noteIndex))
-         return false;
- 
--    JumpList jmp;
--    if (!emitJump(JSOP_GOTO, &jmp))
--        return false;
--
--    if (!emitLoopHead(pn->pn_right, &top))
-+    if (!loopInfo.emitEntryJump(this))
-+        return false;
-+
-+    if (!loopInfo.emitLoopHead(this, getOffsetForLoop(pn->pn_right)))
-         return false;
- 
-     if (!emitTreeInBranch(pn->pn_right))
-         return false;
- 
--    if (!emitLoopEntry(pn->pn_left, jmp))
-+    if (!loopInfo.emitLoopEntry(this, getOffsetForLoop(pn->pn_left)))
-         return false;
-     if (!emitTree(pn->pn_left))
-         return false;
- 
--    JumpList beq;
--    JumpTarget breakTarget{ -1 };
--    if (!emitBackwardJump(JSOP_IFNE, top, &beq, &breakTarget))
--        return false;
--
--    if (!tryNoteList.append(JSTRY_LOOP, stackDepth, top.offset, breakTarget.offset))
--        return false;
--
--    if (!setSrcNoteOffset(noteIndex, 0, beq.offset - jmp.offset))
-+    if (!loopInfo.emitLoopEnd(this, JSOP_IFNE))
-+        return false;
-+
-+    if (!tryNoteList.append(JSTRY_LOOP, stackDepth, loopInfo.headOffset(),
-+                            loopInfo.breakTargetOffset()))
-+    {
-+        return false;
-+    }
-+
-+    if (!setSrcNoteOffset(noteIndex, 0, loopInfo.loopEndOffsetFromEntryJump()))
-         return false;
- 
-     if (!loopInfo.patchBreaksAndContinues(this))
-         return false;
- 
-     return true;
- }
- 
-diff --git a/js/src/frontend/BytecodeEmitter.h b/js/src/frontend/BytecodeEmitter.h
---- a/js/src/frontend/BytecodeEmitter.h
-+++ b/js/src/frontend/BytecodeEmitter.h
-@@ -547,18 +547,17 @@ struct MOZ_STACK_CLASS BytecodeEmitter
-     MOZ_MUST_USE bool emitBackwardJump(JSOp op, JumpTarget target, JumpList* jump,
-                                        JumpTarget* fallthrough);
-     void patchJumpsToTarget(JumpList jump, JumpTarget target);
-     MOZ_MUST_USE bool emitJumpTargetAndPatch(JumpList jump);
- 
-     MOZ_MUST_USE bool emitCall(JSOp op, uint16_t argc, ParseNode* pn = nullptr);
-     MOZ_MUST_USE bool emitCallIncDec(ParseNode* incDec);
- 
--    MOZ_MUST_USE bool emitLoopHead(ParseNode* nextpn, JumpTarget* top);
--    MOZ_MUST_USE bool emitLoopEntry(ParseNode* nextpn, JumpList entryJump);
-+    mozilla::Maybe<uint32_t> getOffsetForLoop(ParseNode* nextpn);
- 
-     MOZ_MUST_USE bool emitGoto(NestableControl* target, JumpList* jumplist,
-                                SrcNoteType noteType = SRC_NULL);
- 
-     MOZ_MUST_USE bool emitIndex32(JSOp op, uint32_t index);
-     MOZ_MUST_USE bool emitIndexOp(JSOp op, uint32_t index);
- 
-     MOZ_MUST_USE bool emitAtomOp(JSAtom* atom, JSOp op);

+ 0 - 1092
frg/work-js/mozilla-release/patches/mozilla-central-push_430919.patch

@@ -1,1092 +0,0 @@
-# HG changeset patch
-# User Tooru Fujisawa <arai_a@mac.com>
-# Date 1533854957 -32400
-#      Fri Aug 10 07:49:17 2018 +0900
-# Node ID 6dbce3046bd95e61ced3487cb3d6e5bf4310983f
-# Parent  e20a86a9b5756d9bf2ec3c48b1c7ddbdb95a9eba
-Bug 1456404 - Part 2: Add CForEmitter. r=jwalden
-
-diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp
---- a/js/src/frontend/BytecodeEmitter.cpp
-+++ b/js/src/frontend/BytecodeEmitter.cpp
-@@ -20,16 +20,17 @@
- 
- #include "jsapi.h"
- #include "jsnum.h"
- #include "jstypes.h"
- #include "jsutil.h"
- 
- #include "ds/Nestable.h"
- #include "frontend/BytecodeControlStructures.h"
-+#include "frontend/CForEmitter.h"
- #include "frontend/EmitterScope.h"
- #include "frontend/ForOfLoopControl.h"
- #include "frontend/IfEmitter.h"
- #include "frontend/Parser.h"
- #include "frontend/SwitchEmitter.h"
- #include "frontend/TDZCheckCache.h"
- #include "frontend/TryEmitter.h"
- #include "vm/BytecodeUtil.h"
-@@ -4780,17 +4781,17 @@ BytecodeEmitter::emitInitializeForInOrOf
-                "for-in/of loop destructuring declarations can't have initializers");
- 
-     MOZ_ASSERT(target->isKind(ParseNodeKind::Array) ||
-                target->isKind(ParseNodeKind::Object));
-     return emitDestructuringOps(target, DestructuringDeclaration);
- }
- 
- bool
--BytecodeEmitter::emitForOf(ParseNode* forOfLoop, EmitterScope* headLexicalEmitterScope)
-+BytecodeEmitter::emitForOf(ParseNode* forOfLoop, const EmitterScope* headLexicalEmitterScope)
- {
-     MOZ_ASSERT(forOfLoop->isKind(ParseNodeKind::For));
-     MOZ_ASSERT(forOfLoop->isArity(PN_BINARY));
- 
-     ParseNode* forOfHead = forOfLoop->pn_left;
-     MOZ_ASSERT(forOfHead->isKind(ParseNodeKind::ForOf));
-     MOZ_ASSERT(forOfHead->isArity(PN_TERNARY));
- 
-@@ -4971,17 +4972,17 @@ BytecodeEmitter::emitForOf(ParseNode* fo
-     {
-         return false;
-     }
- 
-     return emitPopN(3);                                   //
- }
- 
- bool
--BytecodeEmitter::emitForIn(ParseNode* forInLoop, EmitterScope* headLexicalEmitterScope)
-+BytecodeEmitter::emitForIn(ParseNode* forInLoop, const EmitterScope* headLexicalEmitterScope)
- {
-     MOZ_ASSERT(forInLoop->isKind(ParseNodeKind::For));
-     MOZ_ASSERT(forInLoop->isArity(PN_BINARY));
-     MOZ_ASSERT(forInLoop->isOp(JSOP_ITER));
- 
-     ParseNode* forInHead = forInLoop->pn_left;
-     MOZ_ASSERT(forInHead->isKind(ParseNodeKind::ForIn));
-     MOZ_ASSERT(forInHead->isArity(PN_TERNARY));
-@@ -5120,203 +5121,92 @@ BytecodeEmitter::emitForIn(ParseNode* fo
-     if (!tryNoteList.append(JSTRY_FOR_IN, this->stackDepth, loopInfo.headOffset(), offset()))
-         return false;
- 
-     return emit1(JSOP_ENDITER);                           //
- }
- 
- /* C-style `for (init; cond; update) ...` loop. */
- bool
--BytecodeEmitter::emitCStyleFor(ParseNode* pn, EmitterScope* headLexicalEmitterScope)
--{
--    LoopControl loopInfo(this, StatementKind::ForLoop);
--
-+BytecodeEmitter::emitCStyleFor(ParseNode* pn, const EmitterScope* headLexicalEmitterScope)
-+{
-     ParseNode* forHead = pn->pn_left;
-     ParseNode* forBody = pn->pn_right;
-+    ParseNode* init = forHead->pn_kid1;
-+    ParseNode* cond = forHead->pn_kid2;
-+    ParseNode* update = forHead->pn_kid3;
-+    bool isLet = init && init->isKind(ParseNodeKind::Let);
-+
-+    CForEmitter cfor(this, isLet ? headLexicalEmitterScope : nullptr);
-+
-+    if (!cfor.emitInit(init ? Some(init->pn_pos.begin) : Nothing()))
-+        return false;                                     //
- 
-     // If the head of this for-loop declared any lexical variables, the parser
-     // wrapped this ParseNodeKind::For node in a ParseNodeKind::LexicalScope
--    // representing the implicit scope of those variables. By the time we get here,
--    // we have already entered that scope. So far, so good.
--    //
--    // ### Scope freshening
--    //
--    // Each iteration of a `for (let V...)` loop creates a fresh loop variable
--    // binding for V, even if the loop is a C-style `for(;;)` loop:
--    //
--    //     var funcs = [];
--    //     for (let i = 0; i < 2; i++)
--    //         funcs.push(function() { return i; });
--    //     assertEq(funcs[0](), 0);  // the two closures capture...
--    //     assertEq(funcs[1](), 1);  // ...two different `i` bindings
--    //
--    // This is implemented by "freshening" the implicit block -- changing the
--    // scope chain to a fresh clone of the instantaneous block object -- each
--    // iteration, just before evaluating the "update" in for(;;) loops.
--    //
--    // No freshening occurs in `for (const ...;;)` as there's no point: you
--    // can't reassign consts. This is observable through the Debugger API. (The
--    // ES6 spec also skips cloning the environment in this case.)
--    bool forLoopRequiresFreshening = false;
--    if (ParseNode* init = forHead->pn_kid1) {
-+    // representing the implicit scope of those variables. By the time we get
-+    // here, we have already entered that scope. So far, so good.
-+    if (init) {
-         // Emit the `init` clause, whether it's an expression or a variable
-         // declaration. (The loop variables were hoisted into an enclosing
-         // scope, but we still need to emit code for the initializers.)
--        if (!updateSourceCoordNotes(init->pn_pos.begin))
--            return false;
-         if (init->isForLoopDeclaration()) {
--            if (!emitTree(init))
-+            if (!emitTree(init))                          //
-                 return false;
-         } else {
-             // 'init' is an expression, not a declaration. emitTree left its
-             // value on the stack.
--            if (!emitTree(init, ValueUsage::IgnoreValue))
--                return false;
--            if (!emit1(JSOP_POP))
--                return false;
--        }
--
--        // ES 13.7.4.8 step 2. The initial freshening.
--        //
--        // If an initializer let-declaration may be captured during loop iteration,
--        // the current scope has an environment.  If so, freshen the current
--        // environment to expose distinct bindings for each loop iteration.
--        forLoopRequiresFreshening = init->isKind(ParseNodeKind::Let) && headLexicalEmitterScope;
--        if (forLoopRequiresFreshening) {
--            // The environment chain only includes an environment for the for(;;)
--            // loop head's let-declaration *if* a scope binding is captured, thus
--            // requiring a fresh environment each iteration. If a lexical scope
--            // exists for the head, it must be the innermost one. If that scope
--            // has closed-over bindings inducing an environment, recreate the
--            // current environment.
--            MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope());
--            MOZ_ASSERT(headLexicalEmitterScope->scope(this)->kind() == ScopeKind::Lexical);
--
--            if (headLexicalEmitterScope->hasEnvironment()) {
--                if (!emit1(JSOP_FRESHENLEXICALENV))
--                    return false;
--            }
--        }
--    }
--
--    /*
--     * NB: the SRC_FOR note has offsetBias 1 (JSOP_NOP_LENGTH).
--     * Use tmp to hold the biased srcnote "top" offset, which differs
--     * from the top local variable by the length of the JSOP_GOTO
--     * emitted in between tmp and top if this loop has a condition.
--     */
--    unsigned noteIndex;
--    if (!newSrcNote(SRC_FOR, &noteIndex))
--        return false;
--    if (!emit1(JSOP_NOP))
--        return false;
--    ptrdiff_t top = offset();
--
--    if (forHead->pn_kid2) {
--        /* Goto the loop condition, which branches back to iterate. */
--        if (!loopInfo.emitEntryJump(this))
--            return false;
--    }
--
--    /* Emit code for the loop body. */
--    if (!loopInfo.emitLoopHead(this, getOffsetForLoop(forBody)))
--        return false;
--    if (!forHead->pn_kid2) {
--        if (!loopInfo.emitLoopEntry(this, getOffsetForLoop(forBody)))
--            return false;
--    }
--
--    if (!emitTreeInBranch(forBody))
--        return false;
--
--    // Set loop and enclosing "update" offsets, for continue.  Note that we
--    // continue to immediately *before* the block-freshening: continuing must
--    // refresh the block.
--    if (!loopInfo.emitContinueTarget(this))
--        return false;
--
--    // ES 13.7.4.8 step 3.e. The per-iteration freshening.
--    if (forLoopRequiresFreshening) {
--        MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope());
--        MOZ_ASSERT(headLexicalEmitterScope->scope(this)->kind() == ScopeKind::Lexical);
--
--        if (headLexicalEmitterScope->hasEnvironment()) {
--            if (!emit1(JSOP_FRESHENLEXICALENV))
--                return false;
--        }
-+            if (!emitTree(init, ValueUsage::IgnoreValue)) // VAL
-+                return false;
-+            if (!emit1(JSOP_POP))                         //
-+                return false;
-+        }
-+    }
-+
-+    if (!cfor.emitBody(cond ? CForEmitter::Cond::Present : CForEmitter::Cond::Missing,
-+                       getOffsetForLoop(forBody)))        //
-+    {
-+        return false;
-+    }
-+
-+    if (!emitTree(forBody))                               //
-+        return false;
-+
-+    if (!cfor.emitUpdate(update ? CForEmitter::Update::Present : CForEmitter::Update::Missing,
-+                         update ? Some(update->pn_pos.begin) : Nothing()))
-+    {                                                     //
-+        return false;
-     }
- 
-     // Check for update code to do before the condition (if any).
--    // The update code may not be executed at all; it needs its own TDZ cache.
--    if (ParseNode* update = forHead->pn_kid3) {
--        TDZCheckCache tdzCache(this);
--
--        if (!updateSourceCoordNotes(update->pn_pos.begin))
--            return false;
--        if (!emitTree(update, ValueUsage::IgnoreValue))
--            return false;
--        if (!emit1(JSOP_POP))
--            return false;
--
--        /* Restore the absolute line number for source note readers. */
--        uint32_t lineNum = parser->errorReporter().lineAt(pn->pn_pos.end);
--        if (currentLine() != lineNum) {
--            if (!newSrcNote2(SRC_SETLINE, ptrdiff_t(lineNum)))
--                return false;
--            current->currentLine = lineNum;
--            current->lastColumn = 0;
--        }
--    }
--
--    ptrdiff_t tmp3 = offset();
--
--    if (forHead->pn_kid2) {
--        /* Fix up the goto from top to target the loop condition. */
--        if (!loopInfo.emitLoopEntry(this, getOffsetForLoop(forHead->pn_kid2)))
--            return false;
--
--        if (!emitTree(forHead->pn_kid2))
--            return false;
--    } else if (!forHead->pn_kid3) {
--        // If there is no condition clause and no update clause, mark
--        // the loop-ending "goto" with the location of the "for".
--        // This ensures that the debugger will stop on each loop
--        // iteration.
--        if (!updateSourceCoordNotes(pn->pn_pos.begin))
--            return false;
--    }
--
--    /* Set the first note offset so we can find the loop condition. */
--    if (!setSrcNoteOffset(noteIndex, 0, tmp3 - top))
--        return false;
--    if (!setSrcNoteOffset(noteIndex, 1, loopInfo.continueTargetOffset() - top))
--        return false;
--
--    /* If no loop condition, just emit a loop-closing jump. */
--    if (!loopInfo.emitLoopEnd(this, forHead->pn_kid2 ? JSOP_IFNE : JSOP_GOTO))
--        return false;
--
--    /* The third note offset helps us find the loop-closing jump. */
--    if (!setSrcNoteOffset(noteIndex, 2, loopInfo.loopEndOffset() - top))
--        return false;
--
--    if (!tryNoteList.append(JSTRY_LOOP, stackDepth, loopInfo.headOffset(),
--                            loopInfo.breakTargetOffset()))
-+    if (update) {
-+        if (!emitTree(update, ValueUsage::IgnoreValue))   // VAL
-+            return false;
-+    }
-+
-+    if (!cfor.emitCond(Some(pn->pn_pos.begin),
-+                       cond ? Some(cond->pn_pos.begin) : Nothing(),
-+                       Some(pn->pn_pos.end)))             //
-     {
-         return false;
-     }
- 
--    if (!loopInfo.patchBreaksAndContinues(this))
-+    if (cond) {
-+        if (!emitTree(cond))                              // VAL
-+            return false;
-+    }
-+
-+    if (!cfor.emitEnd())                                  //
-         return false;
- 
-     return true;
- }
- 
- bool
--BytecodeEmitter::emitFor(ParseNode* pn, EmitterScope* headLexicalEmitterScope)
-+BytecodeEmitter::emitFor(ParseNode* pn, const EmitterScope* headLexicalEmitterScope)
- {
-     MOZ_ASSERT(pn->isKind(ParseNodeKind::For));
- 
-     if (pn->pn_left->isKind(ParseNodeKind::ForHead))
-         return emitCStyleFor(pn, headLexicalEmitterScope);
- 
-     if (!updateLineNumberNotes(pn->pn_pos.begin))
-         return false;
-diff --git a/js/src/frontend/BytecodeEmitter.h b/js/src/frontend/BytecodeEmitter.h
---- a/js/src/frontend/BytecodeEmitter.h
-+++ b/js/src/frontend/BytecodeEmitter.h
-@@ -812,20 +812,21 @@ struct MOZ_STACK_CLASS BytecodeEmitter
-     MOZ_MUST_USE bool emitSelfHostedAllowContentIter(ParseNode* pn);
-     MOZ_MUST_USE bool emitSelfHostedDefineDataProperty(ParseNode* pn);
-     MOZ_MUST_USE bool emitSelfHostedGetPropertySuper(ParseNode* pn);
-     MOZ_MUST_USE bool emitSelfHostedHasOwn(ParseNode* pn);
- 
-     MOZ_MUST_USE bool emitDo(ParseNode* pn);
-     MOZ_MUST_USE bool emitWhile(ParseNode* pn);
- 
--    MOZ_MUST_USE bool emitFor(ParseNode* pn, EmitterScope* headLexicalEmitterScope = nullptr);
--    MOZ_MUST_USE bool emitCStyleFor(ParseNode* pn, EmitterScope* headLexicalEmitterScope);
--    MOZ_MUST_USE bool emitForIn(ParseNode* pn, EmitterScope* headLexicalEmitterScope);
--    MOZ_MUST_USE bool emitForOf(ParseNode* pn, EmitterScope* headLexicalEmitterScope);
-+    MOZ_MUST_USE bool emitFor(ParseNode* pn,
-+                              const EmitterScope* headLexicalEmitterScope = nullptr);
-+    MOZ_MUST_USE bool emitCStyleFor(ParseNode* pn, const EmitterScope* headLexicalEmitterScope);
-+    MOZ_MUST_USE bool emitForIn(ParseNode* pn, const EmitterScope* headLexicalEmitterScope);
-+    MOZ_MUST_USE bool emitForOf(ParseNode* pn, const EmitterScope* headLexicalEmitterScope);
- 
-     MOZ_MUST_USE bool emitInitializeForInOrOfTarget(ParseNode* forHead);
- 
-     MOZ_MUST_USE bool emitBreak(PropertyName* label);
-     MOZ_MUST_USE bool emitContinue(PropertyName* label);
- 
-     MOZ_MUST_USE bool emitFunctionFormalParametersAndBody(ParseNode* pn);
-     MOZ_MUST_USE bool emitFunctionFormalParameters(ParseNode* pn);
-diff --git a/js/src/frontend/CForEmitter.cpp b/js/src/frontend/CForEmitter.cpp
-new file mode 100644
---- /dev/null
-+++ b/js/src/frontend/CForEmitter.cpp
-@@ -0,0 +1,235 @@
-+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
-+ * vim: set ts=8 sts=4 et sw=4 tw=99:
-+ * This Source Code Form is subject to the terms of the Mozilla Public
-+ * License, v. 2.0. If a copy of the MPL was not distributed with this
-+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-+
-+#include "frontend/CForEmitter.h"
-+
-+#include "frontend/BytecodeEmitter.h"
-+#include "frontend/EmitterScope.h"
-+#include "frontend/SourceNotes.h"
-+#include "vm/Opcodes.h"
-+#include "vm/Scope.h"
-+
-+using namespace js;
-+using namespace js::frontend;
-+
-+using mozilla::Maybe;
-+
-+CForEmitter::CForEmitter(BytecodeEmitter* bce,
-+                         const EmitterScope* headLexicalEmitterScopeForLet)
-+  : bce_(bce),
-+    headLexicalEmitterScopeForLet_(headLexicalEmitterScopeForLet)
-+{}
-+
-+bool
-+CForEmitter::emitInit(const Maybe<uint32_t>& initPos)
-+{
-+    MOZ_ASSERT(state_ == State::Start);
-+
-+    loopInfo_.emplace(bce_, StatementKind::ForLoop);
-+
-+    if (initPos) {
-+        if (!bce_->updateSourceCoordNotes(*initPos))
-+            return false;
-+    }
-+
-+#ifdef DEBUG
-+    state_ = State::Init;
-+#endif
-+    return true;
-+}
-+
-+bool
-+CForEmitter::emitBody(Cond cond, const Maybe<uint32_t>& bodyPos)
-+{
-+    MOZ_ASSERT(state_ == State::Init);
-+    cond_ = cond;
-+
-+    // ES 13.7.4.8 step 2. The initial freshening.
-+    //
-+    // If an initializer let-declaration may be captured during loop
-+    // iteration, the current scope has an environment.  If so, freshen the
-+    // current environment to expose distinct bindings for each loop
-+    // iteration.
-+    if (headLexicalEmitterScopeForLet_) {
-+        // The environment chain only includes an environment for the
-+        // for(;;) loop head's let-declaration *if* a scope binding is
-+        // captured, thus requiring a fresh environment each iteration. If
-+        // a lexical scope exists for the head, it must be the innermost
-+        // one. If that scope has closed-over bindings inducing an
-+        // environment, recreate the current environment.
-+        MOZ_ASSERT(headLexicalEmitterScopeForLet_ == bce_->innermostEmitterScope());
-+        MOZ_ASSERT(headLexicalEmitterScopeForLet_->scope(bce_)->kind() == ScopeKind::Lexical);
-+
-+        if (headLexicalEmitterScopeForLet_->hasEnvironment()) {
-+            if (!bce_->emit1(JSOP_FRESHENLEXICALENV))
-+                return false;
-+        }
-+    }
-+
-+    // NB: the SRC_FOR note has offsetBias 1 (JSOP_NOP_LENGTH).
-+    if (!bce_->newSrcNote(SRC_FOR, &noteIndex_))
-+        return false;
-+    if (!bce_->emit1(JSOP_NOP))
-+        return false;
-+
-+    biasedTop_ = bce_->offset();
-+
-+    if (cond_ == Cond::Present) {
-+        // Goto the loop condition, which branches back to iterate.
-+        if (!loopInfo_->emitEntryJump(bce_))
-+            return false;
-+    }
-+
-+    if (!loopInfo_->emitLoopHead(bce_, bodyPos))
-+        return false;
-+
-+    if (cond_ == Cond::Missing) {
-+        if (!loopInfo_->emitLoopEntry(bce_, bodyPos))
-+            return false;
-+    }
-+
-+    tdzCache_.emplace(bce_);
-+
-+#ifdef DEBUG
-+    state_ = State::Body;
-+#endif
-+    return true;
-+}
-+
-+bool
-+CForEmitter::emitUpdate(Update update, const Maybe<uint32_t>& updatePos)
-+{
-+    MOZ_ASSERT(state_ == State::Body);
-+    update_ = update;
-+    tdzCache_.reset();
-+
-+    // Set loop and enclosing "update" offsets, for continue.  Note that we
-+    // continue to immediately *before* the block-freshening: continuing must
-+    // refresh the block.
-+    if (!loopInfo_->emitContinueTarget(bce_))
-+        return false;
-+
-+    // ES 13.7.4.8 step 3.e. The per-iteration freshening.
-+    if (headLexicalEmitterScopeForLet_) {
-+        MOZ_ASSERT(headLexicalEmitterScopeForLet_ == bce_->innermostEmitterScope());
-+        MOZ_ASSERT(headLexicalEmitterScopeForLet_->scope(bce_)->kind() == ScopeKind::Lexical);
-+
-+        if (headLexicalEmitterScopeForLet_->hasEnvironment()) {
-+            if (!bce_->emit1(JSOP_FRESHENLEXICALENV))
-+                return false;
-+        }
-+    }
-+
-+    // The update code may not be executed at all; it needs its own TDZ
-+    // cache.
-+    if (update_ == Update::Present) {
-+        tdzCache_.emplace(bce_);
-+
-+        if (updatePos) {
-+            if (!bce_->updateSourceCoordNotes(*updatePos))
-+                return false;
-+        }
-+    }
-+
-+#ifdef DEBUG
-+    state_ = State::Update;
-+#endif
-+    return true;
-+}
-+
-+bool
-+CForEmitter::emitCond(const Maybe<uint32_t>& forPos,
-+                      const Maybe<uint32_t>& condPos,
-+                      const Maybe<uint32_t>& endPos)
-+{
-+    MOZ_ASSERT(state_ == State::Update);
-+
-+    if (update_ == Update::Present) {
-+        if (!bce_->emit1(JSOP_POP))                   //
-+            return false;
-+
-+        // Restore the absolute line number for source note readers.
-+        if (endPos) {
-+            uint32_t lineNum =
-+                bce_->parser->errorReporter().lineAt(*endPos);
-+            if (bce_->currentLine() != lineNum) {
-+                if (!bce_->newSrcNote2(SRC_SETLINE, ptrdiff_t(lineNum)))
-+                    return false;
-+                bce_->current->currentLine = lineNum;
-+                bce_->current->lastColumn = 0;
-+            }
-+        }
-+    }
-+
-+    if (update_ == Update::Present)
-+        tdzCache_.reset();
-+
-+    condOffset_ = bce_->offset();
-+
-+    if (cond_ == Cond::Present) {
-+        if (!loopInfo_->emitLoopEntry(bce_, condPos))
-+            return false;
-+    } else if (update_ == Update::Missing) {
-+        // If there is no condition clause and no update clause, mark
-+        // the loop-ending "goto" with the location of the "for".
-+        // This ensures that the debugger will stop on each loop
-+        // iteration.
-+        if (forPos) {
-+            if (!bce_->updateSourceCoordNotes(*forPos))
-+                return false;
-+        }
-+    }
-+
-+#ifdef DEBUG
-+    state_ = State::Cond;
-+#endif
-+    return true;
-+}
-+
-+bool
-+CForEmitter::emitEnd()
-+{
-+    MOZ_ASSERT(state_ == State::Cond);
-+    // Set the first note offset so we can find the loop condition.
-+    if (!bce_->setSrcNoteOffset(noteIndex_, SrcNote::For::CondOffset,
-+                                condOffset_ - biasedTop_))
-+    {
-+        return false;
-+    }
-+    if (!bce_->setSrcNoteOffset(noteIndex_, SrcNote::For::UpdateOffset,
-+                                loopInfo_->continueTargetOffset() - biasedTop_))
-+    {
-+        return false;
-+    }
-+
-+    // If no loop condition, just emit a loop-closing jump.
-+    if (!loopInfo_->emitLoopEnd(bce_, cond_ == Cond::Present ? JSOP_IFNE : JSOP_GOTO))
-+        return false;                                 //
-+
-+    // The third note offset helps us find the loop-closing jump.
-+    if (!bce_->setSrcNoteOffset(noteIndex_, SrcNote::For::BackJumpOffset,
-+                                loopInfo_->loopEndOffset() - biasedTop_))
-+
-+    {
-+        return false;
-+    }
-+
-+    if (!bce_->tryNoteList.append(JSTRY_LOOP, bce_->stackDepth, loopInfo_->headOffset(),
-+                                  loopInfo_->breakTargetOffset()))
-+    {
-+        return false;
-+    }
-+
-+    if (!loopInfo_->patchBreaksAndContinues(bce_))
-+        return false;
-+
-+    loopInfo_.reset();
-+
-+#ifdef DEBUG
-+    state_ = State::End;
-+#endif
-+    return true;
-+}
-diff --git a/js/src/frontend/CForEmitter.h b/js/src/frontend/CForEmitter.h
-new file mode 100644
---- /dev/null
-+++ b/js/src/frontend/CForEmitter.h
-@@ -0,0 +1,196 @@
-+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
-+ * vim: set ts=8 sts=4 et sw=4 tw=99:
-+ * This Source Code Form is subject to the terms of the Mozilla Public
-+ * License, v. 2.0. If a copy of the MPL was not distributed with this
-+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-+
-+#ifndef frontend_CForEmitter_h
-+#define frontend_CForEmitter_h
-+
-+#include "mozilla/Attributes.h"
-+#include "mozilla/Maybe.h"
-+
-+#include <stddef.h>
-+#include <stdint.h>
-+
-+#include "frontend/BytecodeControlStructures.h"
-+#include "frontend/TDZCheckCache.h"
-+
-+namespace js {
-+namespace frontend {
-+
-+struct BytecodeEmitter;
-+class EmitterScope;
-+
-+// Class for emitting bytecode for c-style for block.
-+//
-+// Usage: (check for the return value is omitted for simplicity)
-+//
-+//   `for (init; cond; update) body`
-+//     CForEmitter cfor(this, headLexicalEmitterScopeForLet or nullptr);
-+//     cfor.emitInit(Some(offset_of_init));
-+//     emit(init); // without pushing value
-+//     cfor.emitBody(CForEmitter::Cond::Present, Some(offset_of_body));
-+//     emit(body);
-+//     cfor.emitUpdate(CForEmitter::Update::Present, Some(offset_of_update)));
-+//     emit(update);
-+//     cfor.emitCond(Some(offset_of_for),
-+//                   Some(offset_of_cond),
-+//                   Some(offset_of_end));
-+//     emit(cond);
-+//     cfor.emitEnd();
-+//
-+//   `for (;;) body`
-+//     CForEmitter cfor(this, nullptr);
-+//     cfor.emitInit(Nothing());
-+//     cfor.emitBody(CForEmitter::Cond::Missing, Some(offset_of_body));
-+//     emit(body);
-+//     cfor.emitUpdate(CForEmitter::Update::Missing, Nothing());
-+//     cfor.emitCond(Some(offset_of_for),
-+//                   Nothing(),
-+//                   Some(offset_of_end));
-+//     cfor.emitEnd();
-+//
-+class MOZ_STACK_CLASS CForEmitter
-+{
-+    // Basic structure of the bytecode (not complete).
-+    //
-+    // If `cond` is not empty:
-+    //     {init}
-+    //     JSOP_GOTO entry
-+    //   loop:
-+    //     {body}
-+    //     {update}
-+    //   entry:
-+    //     {cond}
-+    //     JSOP_IFNE loop
-+    //
-+    // If `cond` is empty:
-+    //     {init}
-+    //   loop:
-+    //     {body}
-+    //     {update}
-+    //     JSOP_GOTO loop
-+    //
-+  public:
-+    enum class Cond {
-+        Missing,
-+        Present
-+    };
-+    enum class Update {
-+        Missing,
-+        Present
-+    };
-+
-+  private:
-+    BytecodeEmitter* bce_;
-+
-+    // The source note index for SRC_FOR.
-+    unsigned noteIndex_ = 0;
-+
-+    // The bytecode offset of loop condition.
-+    // Not the bytecode offset of loop condition expression itself.
-+    ptrdiff_t condOffset_ = 0;
-+
-+    // The base bytecode offset used by SRC_FOR.
-+    ptrdiff_t biasedTop_ = 0;
-+
-+    // Whether the c-style for loop has `cond` and `update`.
-+    Cond cond_ = Cond::Missing;
-+    Update update_ = Update::Missing;
-+
-+    mozilla::Maybe<LoopControl> loopInfo_;
-+
-+    // The lexical scope to be freshened for each iteration.
-+    // See the comment in `emitBody` for more details.
-+    //
-+    // ### Scope freshening
-+    //
-+    // Each iteration of a `for (let V...)` loop creates a fresh loop variable
-+    // binding for V, even if the loop is a C-style `for(;;)` loop:
-+    //
-+    //     var funcs = [];
-+    //     for (let i = 0; i < 2; i++)
-+    //         funcs.push(function() { return i; });
-+    //     assertEq(funcs[0](), 0);  // the two closures capture...
-+    //     assertEq(funcs[1](), 1);  // ...two different `i` bindings
-+    //
-+    // This is implemented by "freshening" the implicit block -- changing the
-+    // scope chain to a fresh clone of the instantaneous block object -- each
-+    // iteration, just before evaluating the "update" in for(;;) loops.
-+    //
-+    // ECMAScript doesn't freshen in `for (const ...;;)`.  Lack of freshening
-+    // isn't directly observable in-language because `const`s can't be mutated,
-+    // but it *can* be observed in the Debugger API.
-+    const EmitterScope* headLexicalEmitterScopeForLet_;
-+
-+    mozilla::Maybe<TDZCheckCache> tdzCache_;
-+
-+#ifdef DEBUG
-+    // The state of this emitter.
-+    //
-+    // +-------+ emitInit +------+ emitBody +------+ emitUpdate +--------+
-+    // | Start |--------->| Init |--------->| Body |----------->| Update |-+
-+    // +-------+          +------+          +------+            +--------+ |
-+    //                                                                     |
-+    //                                   +---------------------------------+
-+    //                                   |
-+    //                                   | emitCond +------+ emitEnd +-----+
-+    //                                   +--------->| Cond |-------->| End |
-+    //                                              +------+         +-----+
-+    enum class State {
-+        // The initial state.
-+        Start,
-+
-+        // After calling emitInit.
-+        Init,
-+
-+        // After calling emitBody.
-+        Body,
-+
-+        // After calling emitUpdate.
-+        Update,
-+
-+        // After calling emitCond.
-+        Cond,
-+
-+        // After calling emitEnd.
-+        End
-+    };
-+    State state_ = State::Start;
-+#endif
-+
-+  public:
-+    CForEmitter(BytecodeEmitter* bce, const EmitterScope* headLexicalEmitterScopeForLet);
-+
-+    // Parameters are the offset in the source code for each character below:
-+    //
-+    //   for ( x = 10 ; x < 20 ; x ++ ) { f(x); }
-+    //   ^     ^        ^        ^      ^       ^
-+    //   |     |        |        |      |       |
-+    //   |     |        |        |      |       endPos
-+    //   |     |        |        |      |
-+    //   |     |        |        |      bodyPos
-+    //   |     |        |        |
-+    //   |     |        |        updatePos
-+    //   |     |        |
-+    //   |     |        condPos
-+    //   |     |
-+    //   |     initPos
-+    //   |
-+    //   forPos
-+    //
-+    // Can be Nothing() if not available.
-+    MOZ_MUST_USE bool emitInit(const mozilla::Maybe<uint32_t>& initPos);
-+    MOZ_MUST_USE bool emitBody(Cond cond, const mozilla::Maybe<uint32_t>& bodyPos);
-+    MOZ_MUST_USE bool emitUpdate(Update update, const mozilla::Maybe<uint32_t>& updatePos);
-+    MOZ_MUST_USE bool emitCond(const mozilla::Maybe<uint32_t>& forPos,
-+                               const mozilla::Maybe<uint32_t>& condPos,
-+                               const mozilla::Maybe<uint32_t>& endPos);
-+    MOZ_MUST_USE bool emitEnd();
-+};
-+
-+} /* namespace frontend */
-+} /* namespace js */
-+
-+#endif /* frontend_CForEmitter_h */
-diff --git a/js/src/frontend/EmitterScope.cpp b/js/src/frontend/EmitterScope.cpp
---- a/js/src/frontend/EmitterScope.cpp
-+++ b/js/src/frontend/EmitterScope.cpp
-@@ -361,17 +361,17 @@ EmitterScope::appendScopeNote(BytecodeEm
-                "Scope notes are not needed for body-level scopes.");
-     noteIndex_ = bce->scopeNoteList.length();
-     return bce->scopeNoteList.append(index(), bce->offset(), bce->inPrologue(),
-                                      enclosingInFrame() ? enclosingInFrame()->noteIndex()
-                                                         : ScopeNote::NoScopeNoteIndex);
- }
- 
- bool
--EmitterScope::deadZoneFrameSlotRange(BytecodeEmitter* bce, uint32_t slotStart, uint32_t slotEnd)
-+EmitterScope::deadZoneFrameSlotRange(BytecodeEmitter* bce, uint32_t slotStart, uint32_t slotEnd) const
- {
-     // Lexical bindings throw ReferenceErrors if they are used before
-     // initialization. See ES6 8.1.1.1.6.
-     //
-     // For completeness, lexical bindings are initialized in ES6 by calling
-     // InitializeBinding, after which touching the binding will no longer
-     // throw reference errors. See 13.1.11, 9.2.13, 13.6.3.4, 13.6.4.6,
-     // 13.6.4.8, 13.14.5, 15.1.8, and 15.2.0.15.
-@@ -952,17 +952,17 @@ EmitterScope::enterWith(BytecodeEmitter*
- 
-     if (!appendScopeNote(bce))
-         return false;
- 
-     return checkEnvironmentChainLength(bce);
- }
- 
- bool
--EmitterScope::deadZoneFrameSlots(BytecodeEmitter* bce)
-+EmitterScope::deadZoneFrameSlots(BytecodeEmitter* bce) const
- {
-     return deadZoneFrameSlotRange(bce, frameSlotStart(), frameSlotEnd());
- }
- 
- bool
- EmitterScope::leave(BytecodeEmitter* bce, bool nonLocal)
- {
-     // If we aren't leaving the scope due to a non-local jump (e.g., break),
-diff --git a/js/src/frontend/EmitterScope.h b/js/src/frontend/EmitterScope.h
---- a/js/src/frontend/EmitterScope.h
-+++ b/js/src/frontend/EmitterScope.h
-@@ -82,34 +82,34 @@ class EmitterScope : public Nestable<Emi
- 
-     template <typename ScopeCreator>
-     MOZ_MUST_USE bool internScope(BytecodeEmitter* bce, ScopeCreator createScope);
-     template <typename ScopeCreator>
-     MOZ_MUST_USE bool internBodyScope(BytecodeEmitter* bce, ScopeCreator createScope);
-     MOZ_MUST_USE bool appendScopeNote(BytecodeEmitter* bce);
- 
-     MOZ_MUST_USE bool deadZoneFrameSlotRange(BytecodeEmitter* bce, uint32_t slotStart,
--                                             uint32_t slotEnd);
-+                                             uint32_t slotEnd) const;
- 
-   public:
-     explicit EmitterScope(BytecodeEmitter* bce);
- 
-     void dump(BytecodeEmitter* bce);
- 
-     MOZ_MUST_USE bool enterLexical(BytecodeEmitter* bce, ScopeKind kind,
-                                    Handle<LexicalScope::Data*> bindings);
-     MOZ_MUST_USE bool enterNamedLambda(BytecodeEmitter* bce, FunctionBox* funbox);
-     MOZ_MUST_USE bool enterFunction(BytecodeEmitter* bce, FunctionBox* funbox);
-     MOZ_MUST_USE bool enterFunctionExtraBodyVar(BytecodeEmitter* bce, FunctionBox* funbox);
-     MOZ_MUST_USE bool enterParameterExpressionVar(BytecodeEmitter* bce);
-     MOZ_MUST_USE bool enterGlobal(BytecodeEmitter* bce, GlobalSharedContext* globalsc);
-     MOZ_MUST_USE bool enterEval(BytecodeEmitter* bce, EvalSharedContext* evalsc);
-     MOZ_MUST_USE bool enterModule(BytecodeEmitter* module, ModuleSharedContext* modulesc);
-     MOZ_MUST_USE bool enterWith(BytecodeEmitter* bce);
--    MOZ_MUST_USE bool deadZoneFrameSlots(BytecodeEmitter* bce);
-+    MOZ_MUST_USE bool deadZoneFrameSlots(BytecodeEmitter* bce) const;
- 
-     MOZ_MUST_USE bool leave(BytecodeEmitter* bce, bool nonLocal = false);
- 
-     uint32_t index() const {
-         MOZ_ASSERT(scopeIndex_ != ScopeNote::NoScopeIndex, "Did you forget to intern a Scope?");
-         return scopeIndex_;
-     }
- 
-diff --git a/js/src/frontend/SourceNotes.h b/js/src/frontend/SourceNotes.h
---- a/js/src/frontend/SourceNotes.h
-+++ b/js/src/frontend/SourceNotes.h
-@@ -32,16 +32,33 @@ namespace js {
-  * SRC_COLSPAN, SRC_SETLINE, and SRC_XDELTA) applies to a given bytecode.
-  *
-  * NB: the js_SrcNoteSpec array in BytecodeEmitter.cpp is indexed by this
-  * enum, so its initializers need to match the order here.
-  */
- 
- class SrcNote {
-   public:
-+    // SRC_FOR: Source note for JSOP_NOP at the top of C-style for loop,
-+    //          which is placed after init expression/declaration ops.
-+    class For {
-+      public:
-+        enum Fields {
-+            // The offset of the condition expression ops from JSOP_NOP.
-+            CondOffset,
-+
-+            // The offset of the update expression ops from JSOP_NOP.
-+            UpdateOffset,
-+
-+            // The offset of JSOP_GOTO/JSOP_IFNE at the end of the loop from
-+            // JSOP_NOP.
-+            BackJumpOffset,
-+            Count,
-+        };
-+    };
-     // SRC_TABLESWITCH: Source note for JSOP_TABLESWITCH.
-     class TableSwitch {
-       public:
-         enum Fields {
-             // The offset of the end of switch (the first non-JumpTarget op
-             // after switch) from JSOP_TABLESWITCH.
-             EndOffset,
-             Count
-@@ -101,17 +118,17 @@ class SrcNote {
-     };
- };
- 
- #define FOR_EACH_SRC_NOTE_TYPE(M)                                                                  \
-     M(SRC_NULL,         "null",        0)  /* Terminates a note vector. */                         \
-     M(SRC_IF,           "if",          0)  /* JSOP_IFEQ bytecode is from an if-then. */            \
-     M(SRC_IF_ELSE,      "if-else",     0)  /* JSOP_IFEQ bytecode is from an if-then-else. */       \
-     M(SRC_COND,         "cond",        0)  /* JSOP_IFEQ is from conditional ?: operator. */        \
--    M(SRC_FOR,          "for",         3)  /* JSOP_NOP or JSOP_POP in for(;;) loop head. */        \
-+    M(SRC_FOR,          "for",         SrcNote::For::Count) \
-     M(SRC_WHILE,        "while",       1)  /* JSOP_GOTO to for or while loop condition from before \
-                                               loop, else JSOP_NOP at top of do-while loop. */      \
-     M(SRC_FOR_IN,       "for-in",      1)  /* JSOP_GOTO to for-in loop condition from before       \
-                                               loop. */                                             \
-     M(SRC_FOR_OF,       "for-of",      1)  /* JSOP_GOTO to for-of loop condition from before       \
-                                               loop. */                                             \
-     M(SRC_CONTINUE,     "continue",    0)  /* JSOP_GOTO is a continue. */                          \
-     M(SRC_BREAK,        "break",       0)  /* JSOP_GOTO is a break. */                             \
-diff --git a/js/src/jit/IonControlFlow.cpp b/js/src/jit/IonControlFlow.cpp
---- a/js/src/jit/IonControlFlow.cpp
-+++ b/js/src/jit/IonControlFlow.cpp
-@@ -1429,60 +1429,61 @@ ControlFlowGenerator::maybeLoop(JSOp op,
- 
- ControlFlowGenerator::ControlStatus
- ControlFlowGenerator::processForLoop(JSOp op, jssrcnote* sn)
- {
-     // Skip the NOP.
-     MOZ_ASSERT(op == JSOP_NOP);
-     pc = GetNextPc(pc);
- 
--    jsbytecode* condpc = pc + GetSrcNoteOffset(sn, 0);
--    jsbytecode* updatepc = pc + GetSrcNoteOffset(sn, 1);
--    jsbytecode* ifne = pc + GetSrcNoteOffset(sn, 2);
--    jsbytecode* exitpc = GetNextPc(ifne);
-+    jsbytecode* condpc = pc + GetSrcNoteOffset(sn, SrcNote::For::CondOffset);
-+    jsbytecode* updatepc = pc + GetSrcNoteOffset(sn, SrcNote::For::UpdateOffset);
-+    jsbytecode* backjumppc = pc + GetSrcNoteOffset(sn, SrcNote::For::BackJumpOffset);
-+    jsbytecode* exitpc = GetNextPc(backjumppc);
- 
-     // for loops have the following structures:
-     //
--    //   NOP or POP
--    //   [GOTO cond | NOP]
-+    //   NOP
-+    //   [GOTO cond]
-     //   LOOPHEAD
-     // body:
-     //    ; [body]
--    // [increment:]
-+    // [update:]
-     //   [FRESHENBLOCKSCOPE, if needed by a cloned block]
--    //    ; [increment]
-+    //    ; [update]
-     // [cond:]
-     //   LOOPENTRY
--    //   GOTO body
-+    //    ; [cond]
-+    //   [GOTO body | IFNE body]
-     //
--    // If there is a condition (condpc != ifne), this acts similar to a while
-+    // If there is a condition (condpc != backjumppc), this acts similar to a while
-     // loop otherwise, it acts like a do-while loop.
-     //
-     // Note that currently Ion does not compile pushblockscope/popblockscope as
-     // necessary prerequisites to freshenblockscope.  So the code below doesn't
-     // and needn't consider the implications of freshenblockscope.
-     jsbytecode* bodyStart = pc;
-     jsbytecode* bodyEnd = updatepc;
-     jsbytecode* loopEntry = condpc;
--    if (condpc != ifne) {
-+    if (condpc != backjumppc) {
-         MOZ_ASSERT(JSOp(*bodyStart) == JSOP_GOTO);
-         MOZ_ASSERT(bodyStart + GetJumpOffset(bodyStart) == condpc);
-         bodyStart = GetNextPc(bodyStart);
-     } else {
-         // No loop condition, such as for(j = 0; ; j++)
-         if (op != JSOP_NOP) {
-             // If the loop starts with POP, we have to skip a NOP.
-             MOZ_ASSERT(JSOp(*bodyStart) == JSOP_NOP);
-             bodyStart = GetNextPc(bodyStart);
-         }
-         loopEntry = GetNextPc(bodyStart);
-     }
-     jsbytecode* loopHead = bodyStart;
-     MOZ_ASSERT(JSOp(*bodyStart) == JSOP_LOOPHEAD);
--    MOZ_ASSERT(ifne + GetJumpOffset(ifne) == bodyStart);
-+    MOZ_ASSERT(backjumppc + GetJumpOffset(backjumppc) == bodyStart);
-     bodyStart = GetNextPc(bodyStart);
- 
-     MOZ_ASSERT(JSOp(*loopEntry) == JSOP_LOOPENTRY);
- 
-     CFGBlock* header = CFGBlock::New(alloc(), loopEntry);
- 
-     CFGLoopEntry* ins = CFGLoopEntry::New(alloc(), header, 0);
-     if (LoopEntryCanIonOsr(loopEntry))
-@@ -1490,34 +1491,34 @@ ControlFlowGenerator::processForLoop(JSO
- 
-     current->setStopIns(ins);
-     current->setStopPc(pc);
- 
-     // If there is no condition, we immediately parse the body. Otherwise, we
-     // parse the condition.
-     jsbytecode* stopAt;
-     CFGState::State initial;
--    if (condpc != ifne) {
-+    if (condpc != backjumppc) {
-         pc = condpc;
--        stopAt = ifne;
-+        stopAt = backjumppc;
-         initial = CFGState::FOR_LOOP_COND;
-     } else {
-         pc = bodyStart;
-         stopAt = bodyEnd;
-         initial = CFGState::FOR_LOOP_BODY;
-     }
- 
-     if (!pushLoop(initial, stopAt, current,
-                   loopHead, pc, bodyStart, bodyEnd, exitpc, updatepc))
-     {
-         return ControlStatus::Error;
-     }
- 
-     CFGState& state = cfgStack_.back();
--    state.loop.condpc = (condpc != ifne) ? condpc : nullptr;
-+    state.loop.condpc = (condpc != backjumppc) ? condpc : nullptr;
-     state.loop.updatepc = (updatepc != condpc) ? updatepc : nullptr;
-     if (state.loop.updatepc)
-         state.loop.updateEnd = condpc;
- 
-     current = header;
-     if (!addBlock(current))
-         return ControlStatus::Error;
-     return ControlStatus::Jumped;
-diff --git a/js/src/moz.build b/js/src/moz.build
---- a/js/src/moz.build
-+++ b/js/src/moz.build
-@@ -206,16 +206,17 @@ UNIFIED_SOURCES += [
-     'builtin/WeakSetObject.cpp',
-     'devtools/sharkctl.cpp',
-     'ds/Bitmap.cpp',
-     'ds/LifoAlloc.cpp',
-     'ds/MemoryProtectionExceptionHandler.cpp',
-     'frontend/BytecodeCompiler.cpp',
-     'frontend/BytecodeControlStructures.cpp',
-     'frontend/BytecodeEmitter.cpp',
-+    'frontend/CForEmitter.cpp',
-     'frontend/EmitterScope.cpp',
-     'frontend/FoldConstants.cpp',
-     'frontend/ForOfLoopControl.cpp',
-     'frontend/IfEmitter.cpp',
-     'frontend/JumpList.cpp',
-     'frontend/NameFunctions.cpp',
-     'frontend/ParseNode.cpp',
-     'frontend/SwitchEmitter.cpp',
-diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp
---- a/js/src/shell/js.cpp
-+++ b/js/src/shell/js.cpp
-@@ -2738,20 +2738,20 @@ SrcNotes(JSContext* cx, HandleScript scr
-                 return false;
-             break;
- 
-           case SRC_NEWLINE:
-             ++lineno;
-             break;
- 
-           case SRC_FOR:
--            if (!sp->jsprintf(" cond %u update %u tail %u",
--                              unsigned(GetSrcNoteOffset(sn, 0)),
--                              unsigned(GetSrcNoteOffset(sn, 1)),
--                              unsigned(GetSrcNoteOffset(sn, 2))))
-+            if (!sp->jsprintf(" cond %u update %u backjump %u",
-+                              unsigned(GetSrcNoteOffset(sn, SrcNote::For::CondOffset)),
-+                              unsigned(GetSrcNoteOffset(sn, SrcNote::For::UpdateOffset)),
-+                              unsigned(GetSrcNoteOffset(sn, SrcNote::For::BackJumpOffset))))
-             {
-                 return false;
-             }
-             break;
- 
-           case SRC_FOR_IN:
-           case SRC_FOR_OF:
-             if (!sp->jsprintf(" closingjump %u", unsigned(GetSrcNoteOffset(sn, 0))))

+ 0 - 667
frg/work-js/mozilla-release/patches/mozilla-central-push_430920.patch

@@ -1,667 +0,0 @@
-# HG changeset patch
-# User Tooru Fujisawa <arai_a@mac.com>
-# Date 1533854957 -32400
-#      Fri Aug 10 07:49:17 2018 +0900
-# Node ID b4a44d463eaaca925d705d6145f24d9f18c59a7a
-# Parent  6dbce3046bd95e61ced3487cb3d6e5bf4310983f
-Bug 1456404 - Part 3: Add ForInEmitter. r=jwalden
-
-diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp
---- a/js/src/frontend/BytecodeEmitter.cpp
-+++ b/js/src/frontend/BytecodeEmitter.cpp
-@@ -22,16 +22,17 @@
- #include "jsnum.h"
- #include "jstypes.h"
- #include "jsutil.h"
- 
- #include "ds/Nestable.h"
- #include "frontend/BytecodeControlStructures.h"
- #include "frontend/CForEmitter.h"
- #include "frontend/EmitterScope.h"
-+#include "frontend/ForInEmitter.h"
- #include "frontend/ForOfLoopControl.h"
- #include "frontend/IfEmitter.h"
- #include "frontend/Parser.h"
- #include "frontend/SwitchEmitter.h"
- #include "frontend/TDZCheckCache.h"
- #include "frontend/TryEmitter.h"
- #include "vm/BytecodeUtil.h"
- #include "vm/Debugger.h"
-@@ -4982,16 +4983,18 @@ BytecodeEmitter::emitForIn(ParseNode* fo
-     MOZ_ASSERT(forInLoop->isKind(ParseNodeKind::For));
-     MOZ_ASSERT(forInLoop->isArity(PN_BINARY));
-     MOZ_ASSERT(forInLoop->isOp(JSOP_ITER));
- 
-     ParseNode* forInHead = forInLoop->pn_left;
-     MOZ_ASSERT(forInHead->isKind(ParseNodeKind::ForIn));
-     MOZ_ASSERT(forInHead->isArity(PN_TERNARY));
- 
-+    ForInEmitter forIn(this, headLexicalEmitterScope);
-+
-     // Annex B: Evaluate the var-initializer expression if present.
-     // |for (var i = initializer in expr) { ... }|
-     ParseNode* forInTarget = forInHead->pn_kid1;
-     if (parser->astGenerator().isDeclarationList(forInTarget)) {
-         ParseNode* decl = parser->astGenerator().singleBindingFromDeclaration(forInTarget);
-         if (decl->isKind(ParseNodeKind::Name)) {
-             if (ParseNode* initializer = decl->expr()) {
-                 MOZ_ASSERT(forInTarget->isKind(ParseNodeKind::Var),
-@@ -5009,124 +5012,48 @@ BytecodeEmitter::emitForIn(ParseNode* fo
- 
-                 // Pop the initializer.
-                 if (!emit1(JSOP_POP))
-                     return false;
-             }
-         }
-     }
- 
-+    if (!forIn.emitIterated())                            //
-+        return false;
-+
-     // Evaluate the expression being iterated.
-     ParseNode* expr = forInHead->pn_kid3;
--    if (!emitTreeInBranch(expr))                          // EXPR
-+    if (!emitTree(expr))                                  // EXPR
-         return false;
- 
-     MOZ_ASSERT(forInLoop->pn_iflags == 0);
- 
--    if (!emit1(JSOP_ITER))                                // ITER
--        return false;
--
--    // For-in loops have both the iterator and the value on the stack. Push
--    // undefined to balance the stack.
--    if (!emit1(JSOP_UNDEFINED))                           // ITER ITERVAL
--        return false;
--
--    LoopControl loopInfo(this, StatementKind::ForInLoop);
--
--    /* Annotate so IonMonkey can find the loop-closing jump. */
--    unsigned noteIndex;
--    if (!newSrcNote(SRC_FOR_IN, &noteIndex))
--        return false;
--
--    // Jump down to the loop condition to minimize overhead (assuming at least
--    // one iteration, just like the other loop forms).
--    if (!loopInfo.emitEntryJump(this))                    // ITER ITERVAL
--        return false;
--
--    if (!loopInfo.emitLoopHead(this, Nothing()))          // ITER ITERVAL
--        return false;
--
--    // If the loop had an escaping lexical declaration, replace the current
--    // environment with an dead zoned one to implement TDZ semantics.
--    if (headLexicalEmitterScope) {
--        // The environment chain only includes an environment for the for-in
--        // loop head *if* a scope binding is captured, thereby requiring
--        // recreation each iteration. If a lexical scope exists for the head,
--        // it must be the innermost one. If that scope has closed-over
--        // bindings inducing an environment, recreate the current environment.
--        MOZ_ASSERT(forInTarget->isKind(ParseNodeKind::Let) ||
--                   forInTarget->isKind(ParseNodeKind::Const));
--        MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope());
--        MOZ_ASSERT(headLexicalEmitterScope->scope(this)->kind() == ScopeKind::Lexical);
--
--        if (headLexicalEmitterScope->hasEnvironment()) {
--            if (!emit1(JSOP_RECREATELEXICALENV))          // ITER ITERVAL
--                return false;
--        }
--
--        // For uncaptured bindings, put them back in TDZ.
--        if (!headLexicalEmitterScope->deadZoneFrameSlots(this))
--            return false;
--    }
--
--    {
--#ifdef DEBUG
--        auto loopDepth = this->stackDepth;
--#endif
--        MOZ_ASSERT(loopDepth >= 2);
--
--        if (!emit1(JSOP_ITERNEXT))                        // ITER ITERVAL
--            return false;
--
--        if (!emitInitializeForInOrOfTarget(forInHead))    // ITER ITERVAL
--            return false;
--
--        MOZ_ASSERT(this->stackDepth == loopDepth,
--                   "iterator and iterval must be left on the stack");
--    }
-+    MOZ_ASSERT_IF(headLexicalEmitterScope,
-+                  forInTarget->isKind(ParseNodeKind::Let) ||
-+                  forInTarget->isKind(ParseNodeKind::Const));
-+
-+    if (!forIn.emitInitialize())                          // ITER ITERVAL
-+        return false;
-+
-+    if (!emitInitializeForInOrOfTarget(forInHead))        // ITER ITERVAL
-+        return false;
-+
-+    if (!forIn.emitBody())                                // ITER ITERVAL
-+        return false;
- 
-     // Perform the loop body.
-     ParseNode* forBody = forInLoop->pn_right;
-     if (!emitTree(forBody))                               // ITER ITERVAL
-         return false;
- 
--    // Set offset for continues.
--    loopInfo.setContinueTarget(offset());
--
--    // Make sure this code is attributed to the "for".
--    if (!updateSourceCoordNotes(forInHead->pn_pos.begin))
--        return false;
--
--    if (!loopInfo.emitLoopEntry(this, Nothing()))         // ITER ITERVAL
--        return false;
--    if (!emit1(JSOP_POP))                                 // ITER
--        return false;
--    if (!emit1(JSOP_MOREITER))                            // ITER NEXTITERVAL?
--        return false;
--    if (!emit1(JSOP_ISNOITER))                            // ITER NEXTITERVAL? ISNOITER
--        return false;
--
--    if (!loopInfo.emitLoopEnd(this, JSOP_IFEQ))           // ITER NEXTITERVAL
--        return false;
--
--    // Set the srcnote offset so we can find the closing jump.
--    if (!setSrcNoteOffset(noteIndex, 0, loopInfo.loopEndOffsetFromEntryJump()))
--        return false;
--
--    if (!loopInfo.patchBreaksAndContinues(this))
--        return false;
--
--    // Pop the enumeration value.
--    if (!emit1(JSOP_POP))                                 // ITER
--        return false;
--
--    if (!tryNoteList.append(JSTRY_FOR_IN, this->stackDepth, loopInfo.headOffset(), offset()))
--        return false;
--
--    return emit1(JSOP_ENDITER);                           //
-+    if (!forIn.emitEnd(Some(forInHead->pn_pos.begin)))    //
-+        return false;
-+
-+    return true;
- }
- 
- /* C-style `for (init; cond; update) ...` loop. */
- bool
- BytecodeEmitter::emitCStyleFor(ParseNode* pn, const EmitterScope* headLexicalEmitterScope)
- {
-     ParseNode* forHead = pn->pn_left;
-     ParseNode* forBody = pn->pn_right;
-diff --git a/js/src/frontend/ForInEmitter.cpp b/js/src/frontend/ForInEmitter.cpp
-new file mode 100644
---- /dev/null
-+++ b/js/src/frontend/ForInEmitter.cpp
-@@ -0,0 +1,170 @@
-+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
-+ * vim: set ts=8 sts=4 et sw=4 tw=99:
-+ * This Source Code Form is subject to the terms of the Mozilla Public
-+ * License, v. 2.0. If a copy of the MPL was not distributed with this
-+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-+
-+#include "frontend/ForInEmitter.h"
-+
-+#include "frontend/BytecodeEmitter.h"
-+#include "frontend/EmitterScope.h"
-+#include "frontend/SourceNotes.h"
-+#include "vm/Opcodes.h"
-+#include "vm/Scope.h"
-+
-+using namespace js;
-+using namespace js::frontend;
-+
-+using mozilla::Maybe;
-+using mozilla::Nothing;
-+
-+ForInEmitter::ForInEmitter(BytecodeEmitter* bce, const EmitterScope* headLexicalEmitterScope)
-+  : bce_(bce),
-+    headLexicalEmitterScope_(headLexicalEmitterScope)
-+{}
-+
-+bool
-+ForInEmitter::emitIterated()
-+{
-+    MOZ_ASSERT(state_ == State::Start);
-+    tdzCacheForIteratedValue_.emplace(bce_);
-+
-+#ifdef DEBUG
-+    state_ = State::Iterated;
-+#endif
-+    return true;
-+}
-+
-+bool
-+ForInEmitter::emitInitialize()
-+{
-+    MOZ_ASSERT(state_ == State::Iterated);
-+    tdzCacheForIteratedValue_.reset();
-+
-+    if (!bce_->emit1(JSOP_ITER))                      // ITER
-+        return false;
-+
-+    // For-in loops have both the iterator and the value on the stack. Push
-+    // undefined to balance the stack.
-+    if (!bce_->emit1(JSOP_UNDEFINED))                 // ITER ITERVAL
-+        return false;
-+
-+    loopInfo_.emplace(bce_, StatementKind::ForInLoop);
-+
-+    // Annotate so IonMonkey can find the loop-closing jump.
-+    if (!bce_->newSrcNote(SRC_FOR_IN, &noteIndex_))
-+        return false;
-+
-+    // Jump down to the loop condition to minimize overhead (assuming at
-+    // least one iteration, just like the other loop forms).
-+    if (!loopInfo_->emitEntryJump(bce_))              // ITER ITERVAL
-+        return false;
-+
-+    if (!loopInfo_->emitLoopHead(bce_, Nothing()))    // ITER ITERVAL
-+        return false;
-+
-+    // If the loop had an escaping lexical declaration, reset the declaration's
-+    // bindings to uninitialized to implement TDZ semantics.
-+    if (headLexicalEmitterScope_) {
-+        // The environment chain only includes an environment for the
-+        // for-in loop head *if* a scope binding is captured, thereby
-+        // requiring recreation each iteration. If a lexical scope exists
-+        // for the head, it must be the innermost one. If that scope has
-+        // closed-over bindings inducing an environment, recreate the
-+        // current environment.
-+        MOZ_ASSERT(headLexicalEmitterScope_ == bce_->innermostEmitterScope());
-+        MOZ_ASSERT(headLexicalEmitterScope_->scope(bce_)->kind() == ScopeKind::Lexical);
-+
-+        if (headLexicalEmitterScope_->hasEnvironment()) {
-+            if (!bce_->emit1(JSOP_RECREATELEXICALENV))
-+                return false;                         // ITER ITERVAL
-+        }
-+
-+        // For uncaptured bindings, put them back in TDZ.
-+        if (!headLexicalEmitterScope_->deadZoneFrameSlots(bce_))
-+            return false;
-+    }
-+
-+#ifdef DEBUG
-+    loopDepth_ = bce_->stackDepth;
-+#endif
-+    MOZ_ASSERT(loopDepth_ >= 2);
-+
-+    if (!bce_->emit1(JSOP_ITERNEXT))                  // ITER ITERVAL
-+        return false;
-+
-+#ifdef DEBUG
-+    state_ = State::Initialize;
-+#endif
-+    return true;
-+}
-+
-+bool
-+ForInEmitter::emitBody()
-+{
-+    MOZ_ASSERT(state_ == State::Initialize);
-+
-+    MOZ_ASSERT(bce_->stackDepth == loopDepth_,
-+               "iterator and iterval must be left on the stack");
-+
-+#ifdef DEBUG
-+    state_ = State::Body;
-+#endif
-+    return true;
-+}
-+
-+bool
-+ForInEmitter::emitEnd(const Maybe<uint32_t>& forPos)
-+{
-+    MOZ_ASSERT(state_ == State::Body);
-+
-+    loopInfo_->setContinueTarget(bce_->offset());
-+
-+    if (forPos) {
-+        // Make sure this code is attributed to the "for".
-+        if (!bce_->updateSourceCoordNotes(*forPos))
-+            return false;
-+    }
-+
-+    if (!loopInfo_->emitLoopEntry(bce_, Nothing()))   // ITER ITERVAL
-+        return false;
-+    if (!bce_->emit1(JSOP_POP))                       // ITER
-+        return false;
-+    if (!bce_->emit1(JSOP_MOREITER))                  // ITER NEXTITERVAL?
-+        return false;
-+    if (!bce_->emit1(JSOP_ISNOITER))                  // ITER NEXTITERVAL? ISNOITER
-+        return false;
-+
-+    if (!loopInfo_->emitLoopEnd(bce_, JSOP_IFEQ))     // ITER NEXTITERVAL
-+        return false;
-+
-+    // Set the srcnote offset so we can find the closing jump.
-+    if (!bce_->setSrcNoteOffset(noteIndex_, SrcNote::ForIn::BackJumpOffset,
-+                                loopInfo_->loopEndOffsetFromEntryJump()))
-+    {
-+        return false;
-+    }
-+
-+    if (!loopInfo_->patchBreaksAndContinues(bce_))
-+        return false;
-+
-+    // Pop the enumeration value.
-+    if (!bce_->emit1(JSOP_POP))                       // ITER
-+        return false;
-+
-+    if (!bce_->tryNoteList.append(JSTRY_FOR_IN, bce_->stackDepth, loopInfo_->headOffset(),
-+                                  bce_->offset()))
-+    {
-+        return false;
-+    }
-+
-+    if (!bce_->emit1(JSOP_ENDITER))                   //
-+        return false;
-+
-+    loopInfo_.reset();
-+
-+#ifdef DEBUG
-+    state_ = State::End;
-+#endif
-+    return true;
-+}
-diff --git a/js/src/frontend/ForInEmitter.h b/js/src/frontend/ForInEmitter.h
-new file mode 100644
---- /dev/null
-+++ b/js/src/frontend/ForInEmitter.h
-@@ -0,0 +1,122 @@
-+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
-+ * vim: set ts=8 sts=4 et sw=4 tw=99:
-+ * This Source Code Form is subject to the terms of the Mozilla Public
-+ * License, v. 2.0. If a copy of the MPL was not distributed with this
-+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-+
-+#ifndef frontend_ForInEmitter_h
-+#define frontend_ForInEmitter_h
-+
-+#include "mozilla/Attributes.h"
-+#include "mozilla/Maybe.h"
-+
-+#include <stdint.h>
-+
-+#include "frontend/BytecodeControlStructures.h"
-+#include "frontend/TDZCheckCache.h"
-+
-+namespace js {
-+namespace frontend {
-+
-+struct BytecodeEmitter;
-+class EmitterScope;
-+
-+// Class for emitting bytecode for for-in loop.
-+//
-+// Usage: (check for the return value is omitted for simplicity)
-+//
-+//   `for (init in iterated) body`
-+//     // headLexicalEmitterScope: lexical scope for init
-+//     ForInEmitter forIn(this, headLexicalEmitterScope);
-+//     forIn.emitIterated();
-+//     emit(iterated);
-+//     forIn.emitInitialize();
-+//     emit(init);
-+//     forIn.emitBody();
-+//     emit(body);
-+//     forIn.emitEnd(Some(offset_of_for));
-+//
-+class MOZ_STACK_CLASS ForInEmitter
-+{
-+    BytecodeEmitter* bce_;
-+
-+    // The source note index for SRC_FOR_IN.
-+    unsigned noteIndex_ = 0;
-+
-+#ifdef DEBUG
-+    // The stack depth before emitting initialize code inside loop.
-+    int32_t loopDepth_;
-+#endif
-+
-+    mozilla::Maybe<LoopControl> loopInfo_;
-+
-+    // The lexical scope to be freshened for each iteration.  See the comment
-+    // in `emitBody` for more details.  Can be nullptr if there's no lexical
-+    // scope.
-+    const EmitterScope* headLexicalEmitterScope_;
-+
-+    // Cache for the iterated value.
-+    // (The cache for the iteration body is inside `loopInfo_`)
-+    //
-+    // The iterated value needs its own TDZCheckCache, separated from both the
-+    // enclosing block and the iteration body, in order to make the sanity check
-+    // in Ion work properly.
-+    // In term of the execution order, the TDZCheckCache for the iterated value
-+    // dominates the one for the iteration body, that means the checks in the
-+    // iteration body is dead, and we can optimize them away.  But the sanity
-+    // check in Ion doesn't know it's dead.
-+    // (see bug 1368360 for more context)
-+    mozilla::Maybe<TDZCheckCache> tdzCacheForIteratedValue_;
-+
-+#ifdef DEBUG
-+    // The state of this emitter.
-+    //
-+    // +-------+ emitIterated +----------+ emitInitialize +------------+
-+    // | Start |------------->| Iterated |--------------->| Initialize |-+
-+    // +-------+              +----------+                +------------+ |
-+    //                                                                   |
-+    //                                +----------------------------------+
-+    //                                |
-+    //                                | emitBody +------+ emitEnd  +-----+
-+    //                                +----------| Body |--------->| End |
-+    //                                           +------+          +-----+
-+    enum class State {
-+        // The initial state.
-+        Start,
-+
-+        // After calling emitIterated.
-+        Iterated,
-+
-+        // After calling emitInitialize.
-+        Initialize,
-+
-+        // After calling emitBody.
-+        Body,
-+
-+        // After calling emitEnd.
-+        End
-+    };
-+    State state_ = State::Start;
-+#endif
-+
-+  public:
-+    ForInEmitter(BytecodeEmitter* bce, const EmitterScope* headLexicalEmitterScope);
-+
-+    // Parameters are the offset in the source code for each character below:
-+    //
-+    //   for ( var x in obj ) { ... }
-+    //   ^
-+    //   |
-+    //   forPos
-+    //
-+    // Can be Nothing() if not available.
-+    MOZ_MUST_USE bool emitIterated();
-+    MOZ_MUST_USE bool emitInitialize();
-+    MOZ_MUST_USE bool emitBody();
-+    MOZ_MUST_USE bool emitEnd(const mozilla::Maybe<uint32_t>& forPos);
-+};
-+
-+} /* namespace frontend */
-+} /* namespace js */
-+
-+#endif /* frontend_ForInEmitter_h */
-diff --git a/js/src/frontend/SourceNotes.h b/js/src/frontend/SourceNotes.h
---- a/js/src/frontend/SourceNotes.h
-+++ b/js/src/frontend/SourceNotes.h
-@@ -49,16 +49,26 @@ class SrcNote {
-             UpdateOffset,
- 
-             // The offset of JSOP_GOTO/JSOP_IFNE at the end of the loop from
-             // JSOP_NOP.
-             BackJumpOffset,
-             Count,
-         };
-     };
-+    // SRC_FOR_IN: Source note for JSOP_GOTO at the top of for-in loop,
-+    //             which jumps to JSOP_LOOPENTRY.
-+    class ForIn {
-+      public:
-+        enum Fields {
-+            // The offset of JSOP_IFEQ at the end of the loop from JSOP_GOTO.
-+            BackJumpOffset,
-+            Count,
-+        };
-+    };
-     // SRC_TABLESWITCH: Source note for JSOP_TABLESWITCH.
-     class TableSwitch {
-       public:
-         enum Fields {
-             // The offset of the end of switch (the first non-JumpTarget op
-             // after switch) from JSOP_TABLESWITCH.
-             EndOffset,
-             Count
-@@ -121,18 +131,17 @@ class SrcNote {
- #define FOR_EACH_SRC_NOTE_TYPE(M)                                                                  \
-     M(SRC_NULL,         "null",        0)  /* Terminates a note vector. */                         \
-     M(SRC_IF,           "if",          0)  /* JSOP_IFEQ bytecode is from an if-then. */            \
-     M(SRC_IF_ELSE,      "if-else",     0)  /* JSOP_IFEQ bytecode is from an if-then-else. */       \
-     M(SRC_COND,         "cond",        0)  /* JSOP_IFEQ is from conditional ?: operator. */        \
-     M(SRC_FOR,          "for",         SrcNote::For::Count) \
-     M(SRC_WHILE,        "while",       1)  /* JSOP_GOTO to for or while loop condition from before \
-                                               loop, else JSOP_NOP at top of do-while loop. */      \
--    M(SRC_FOR_IN,       "for-in",      1)  /* JSOP_GOTO to for-in loop condition from before       \
--                                              loop. */                                             \
-+    M(SRC_FOR_IN,       "for-in",      SrcNote::ForIn::Count) \
-     M(SRC_FOR_OF,       "for-of",      1)  /* JSOP_GOTO to for-of loop condition from before       \
-                                               loop. */                                             \
-     M(SRC_CONTINUE,     "continue",    0)  /* JSOP_GOTO is a continue. */                          \
-     M(SRC_BREAK,        "break",       0)  /* JSOP_GOTO is a break. */                             \
-     M(SRC_BREAK2LABEL,  "break2label", 0)  /* JSOP_GOTO for 'break label'. */                      \
-     M(SRC_SWITCHBREAK,  "switchbreak", 0)  /* JSOP_GOTO is a break in a switch. */                 \
-     M(SRC_TABLESWITCH,  "tableswitch", SrcNote::TableSwitch::Count) \
-     M(SRC_CONDSWITCH,   "condswitch",  SrcNote::CondSwitch::Count) \
-diff --git a/js/src/jit/IonControlFlow.cpp b/js/src/jit/IonControlFlow.cpp
---- a/js/src/jit/IonControlFlow.cpp
-+++ b/js/src/jit/IonControlFlow.cpp
-@@ -902,56 +902,60 @@ ControlFlowGenerator::processWhileOrForI
-     // while (cond) { } loops have the following structure:
-     //    GOTO cond   ; SRC_WHILE (offset to IFNE)
-     //    LOOPHEAD
-     //    ...
-     //  cond:
-     //    LOOPENTRY
-     //    ...
-     //    IFNE        ; goes to LOOPHEAD
--    // for (x in y) { } loops are similar; the cond will be a MOREITER.
-+    // for-in/for-of loops are similar;
-+    // for-in has IFEQ as the back jump, and the cond will be a MOREITER.
-     MOZ_ASSERT(SN_TYPE(sn) == SRC_FOR_OF || SN_TYPE(sn) == SRC_FOR_IN || SN_TYPE(sn) == SRC_WHILE);
--    int ifneOffset = GetSrcNoteOffset(sn, 0);
--    jsbytecode* ifne = pc + ifneOffset;
--    MOZ_ASSERT(ifne > pc);
-+    // FIXME: Replaced in the subsequent patch.
-+    static_assert(unsigned(SrcNote::ForIn::BackJumpOffset) == 0,
-+                  "SrcNote::{While,ForIn,ForOf}::BackJumpOffset should be same");
-+    int backjumppcOffset = GetSrcNoteOffset(sn, SrcNote::ForIn::BackJumpOffset);
-+    jsbytecode* backjumppc = pc + backjumppcOffset;
-+    MOZ_ASSERT(backjumppc > pc);
- 
--    // Verify that the IFNE goes back to a loophead op.
-+    // Verify that the back jump goes back to a loophead op.
-     MOZ_ASSERT(JSOp(*GetNextPc(pc)) == JSOP_LOOPHEAD);
--    MOZ_ASSERT(GetNextPc(pc) == ifne + GetJumpOffset(ifne));
-+    MOZ_ASSERT(GetNextPc(pc) == backjumppc + GetJumpOffset(backjumppc));
- 
-     jsbytecode* loopEntry = pc + GetJumpOffset(pc);
- 
-     size_t stackPhiCount;
-     if (SN_TYPE(sn) == SRC_FOR_OF)
-         stackPhiCount = 3;
-     else if (SN_TYPE(sn) == SRC_FOR_IN)
-         stackPhiCount = 1;
-     else
-         stackPhiCount = 0;
- 
-     // Skip past the JSOP_LOOPHEAD for the body start.
-     jsbytecode* loopHead = GetNextPc(pc);
-     jsbytecode* bodyStart = GetNextPc(loopHead);
-     jsbytecode* bodyEnd = pc + GetJumpOffset(pc);
--    jsbytecode* exitpc = GetNextPc(ifne);
-+    jsbytecode* exitpc = GetNextPc(backjumppc);
-     jsbytecode* continuepc = pc;
- 
-     CFGBlock* header = CFGBlock::New(alloc(), loopEntry);
- 
-     CFGLoopEntry* ins = CFGLoopEntry::New(alloc(), header, stackPhiCount);
-     if (LoopEntryCanIonOsr(loopEntry))
-         ins->setCanOsr();
- 
-     if (SN_TYPE(sn) == SRC_FOR_IN)
-         ins->setIsForIn();
- 
-     current->setStopIns(ins);
-     current->setStopPc(pc);
- 
--    if (!pushLoop(CFGState::WHILE_LOOP_COND, ifne, current,
-+    if (!pushLoop(CFGState::WHILE_LOOP_COND, backjumppc, current,
-                   loopHead, bodyEnd, bodyStart, bodyEnd, exitpc, continuepc))
-     {
-         return ControlStatus::Error;
-     }
- 
-     // Parse the condition first.
-     current = header;
-     pc = header->startPc();
-diff --git a/js/src/moz.build b/js/src/moz.build
---- a/js/src/moz.build
-+++ b/js/src/moz.build
-@@ -209,16 +209,17 @@ UNIFIED_SOURCES += [
-     'ds/LifoAlloc.cpp',
-     'ds/MemoryProtectionExceptionHandler.cpp',
-     'frontend/BytecodeCompiler.cpp',
-     'frontend/BytecodeControlStructures.cpp',
-     'frontend/BytecodeEmitter.cpp',
-     'frontend/CForEmitter.cpp',
-     'frontend/EmitterScope.cpp',
-     'frontend/FoldConstants.cpp',
-+    'frontend/ForInEmitter.cpp',
-     'frontend/ForOfLoopControl.cpp',
-     'frontend/IfEmitter.cpp',
-     'frontend/JumpList.cpp',
-     'frontend/NameFunctions.cpp',
-     'frontend/ParseNode.cpp',
-     'frontend/SwitchEmitter.cpp',
-     'frontend/TDZCheckCache.cpp',
-     'frontend/TokenStream.cpp',
-diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp
---- a/js/src/shell/js.cpp
-+++ b/js/src/shell/js.cpp
-@@ -2749,18 +2749,24 @@ SrcNotes(JSContext* cx, HandleScript scr
-                               unsigned(GetSrcNoteOffset(sn, SrcNote::For::BackJumpOffset))))
-             {
-                 return false;
-             }
-             break;
- 
-           case SRC_FOR_IN:
-           case SRC_FOR_OF:
--            if (!sp->jsprintf(" closingjump %u", unsigned(GetSrcNoteOffset(sn, 0))))
-+            // FIXME: replaced in the subsequent patch.
-+            static_assert(unsigned(SrcNote::ForIn::BackJumpOffset) == 0,
-+                          "SrcNote::{ForIn,ForOf}::BackJumpOffset should be same");
-+            if (!sp->jsprintf(" backjump %u",
-+                              unsigned(GetSrcNoteOffset(sn, SrcNote::ForIn::BackJumpOffset))))
-+            {
-                 return false;
-+            }
-             break;
- 
-           case SRC_WHILE:
-             if (!sp->jsprintf(" offset %u", unsigned(GetSrcNoteOffset(sn, 0))))
-                 return false;
-             break;
- 
-           case SRC_NEXTCASE:

+ 0 - 940
frg/work-js/mozilla-release/patches/mozilla-central-push_430921.patch

@@ -1,940 +0,0 @@
-# HG changeset patch
-# User Tooru Fujisawa <arai_a@mac.com>
-# Date 1533854958 -32400
-#      Fri Aug 10 07:49:18 2018 +0900
-# Node ID b355131844eaba786b4c86479e17f48a96ead435
-# Parent  b4a44d463eaaca925d705d6145f24d9f18c59a7a
-Bug 1456404 - Part 4: Add ForOfEmitter. r=jwalden
-
-diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp
---- a/js/src/frontend/BytecodeEmitter.cpp
-+++ b/js/src/frontend/BytecodeEmitter.cpp
-@@ -23,16 +23,17 @@
- #include "jstypes.h"
- #include "jsutil.h"
- 
- #include "ds/Nestable.h"
- #include "frontend/BytecodeControlStructures.h"
- #include "frontend/CForEmitter.h"
- #include "frontend/EmitterScope.h"
- #include "frontend/ForInEmitter.h"
-+#include "frontend/ForOfEmitter.h"
- #include "frontend/ForOfLoopControl.h"
- #include "frontend/IfEmitter.h"
- #include "frontend/Parser.h"
- #include "frontend/SwitchEmitter.h"
- #include "frontend/TDZCheckCache.h"
- #include "frontend/TryEmitter.h"
- #include "vm/BytecodeUtil.h"
- #include "vm/Debugger.h"
-@@ -385,21 +386,29 @@ BytecodeEmitter::emitJumpTargetAndPatch(
-     JumpTarget target;
-     if (!emitJumpTarget(&target))
-         return false;
-     patchJumpsToTarget(jump, target);
-     return true;
- }
- 
- bool
-+BytecodeEmitter::emitCall(JSOp op, uint16_t argc, const Maybe<uint32_t>& sourceCoordOffset)
-+{
-+    if (sourceCoordOffset.isSome()) {
-+        if (!updateSourceCoordNotes(*sourceCoordOffset))
-+            return false;
-+    }
-+    return emit3(op, ARGC_LO(argc), ARGC_HI(argc));
-+}
-+
-+bool
- BytecodeEmitter::emitCall(JSOp op, uint16_t argc, ParseNode* pn)
- {
--    if (pn && !updateSourceCoordNotes(pn->pn_pos.begin))
--        return false;
--    return emit3(op, ARGC_LO(argc), ARGC_HI(argc));
-+    return emitCall(op, argc, pn ? Some(pn->pn_pos.begin) : Nothing());
- }
- 
- bool
- BytecodeEmitter::emitDupAt(unsigned slotFromTop)
- {
-     MOZ_ASSERT(slotFromTop < unsigned(stackDepth));
- 
-     if (slotFromTop == 0)
-@@ -2834,26 +2843,27 @@ BytecodeEmitter::emitSetOrInitializeDest
-         if (!emit1(JSOP_POP))
-             return false;
-     }
- 
-     return true;
- }
- 
- bool
--BytecodeEmitter::emitIteratorNext(ParseNode* pn, IteratorKind iterKind /* = IteratorKind::Sync */,
-+BytecodeEmitter::emitIteratorNext(const Maybe<uint32_t>& callSourceCoordOffset,
-+                                  IteratorKind iterKind /* = IteratorKind::Sync */,
-                                   bool allowSelfHosted /* = false */)
- {
-     MOZ_ASSERT(allowSelfHosted || emitterMode != BytecodeEmitter::SelfHosting,
-                ".next() iteration is prohibited in self-hosted code because it "
-                "can run user-modifiable iteration code");
- 
-     MOZ_ASSERT(this->stackDepth >= 2);                    // ... NEXT ITER
- 
--    if (!emitCall(JSOP_CALL, 0, pn))                      // ... RESULT
-+    if (!emitCall(JSOP_CALL, 0, callSourceCoordOffset))   // ... RESULT
-         return false;
- 
-     if (iterKind == IteratorKind::Async) {
-         if (!emitAwaitInInnermostScope())                 // ... RESULT
-             return false;
-     }
- 
-     if (!emitCheckIsObj(CheckIsObjectKind::IteratorNext)) // ... RESULT
-@@ -3376,17 +3386,17 @@ BytecodeEmitter::emitDestructuringOpsArr
-             if (!ifAlreadyDone.emitElse())                        // ... OBJ NEXT ITER *LREF
-                 return false;
-         }
- 
-         if (!emitDupAt(emitted + 1))                              // ... OBJ NEXT ITER *LREF NEXT
-             return false;
-         if (!emitDupAt(emitted + 1))                              // ... OBJ NEXT ITER *LREF NEXT ITER
-             return false;
--        if (!emitIteratorNext(pattern))                           // ... OBJ NEXT ITER *LREF RESULT
-+        if (!emitIteratorNext(Some(pattern->pn_pos.begin)))       // ... OBJ NEXT ITER *LREF RESULT
-             return false;
-         if (!emit1(JSOP_DUP))                                     // ... OBJ NEXT ITER *LREF RESULT RESULT
-             return false;
-         if (!emitAtomOp(cx->names().done, JSOP_GETPROP))          // ... OBJ NEXT ITER *LREF RESULT DONE
-             return false;
- 
-         if (!emit1(JSOP_DUP))                                     // ... OBJ NEXT ITER *LREF RESULT DONE DONE
-             return false;
-@@ -4684,32 +4694,35 @@ BytecodeEmitter::emitSpread(bool allowSe
-         // COME FROM the beginning of the loop to here.
-         if (!loopInfo.emitLoopEntry(this, Nothing()))     // NEXT ITER ARR I
-             return false;
- 
-         if (!emitDupAt(3))                                // NEXT ITER ARR I NEXT
-             return false;
-         if (!emitDupAt(3))                                // NEXT ITER ARR I NEXT ITER
-             return false;
--        if (!emitIteratorNext(nullptr, IteratorKind::Sync, allowSelfHosted))  // ITER ARR I RESULT
--            return false;
-+        if (!emitIteratorNext(Nothing(), IteratorKind::Sync, allowSelfHosted))
-+            return false;                                 // ITER ARR I RESULT
-         if (!emit1(JSOP_DUP))                             // NEXT ITER ARR I RESULT RESULT
-             return false;
-         if (!emitAtomOp(cx->names().done, JSOP_GETPROP))  // NEXT ITER ARR I RESULT DONE
-             return false;
- 
-         if (!loopInfo.emitLoopEnd(this, JSOP_IFEQ))       // NEXT ITER ARR I RESULT
-             return false;
- 
-         MOZ_ASSERT(this->stackDepth == loopDepth);
-     }
- 
-     // Let Ion know where the closing jump of this loop is.
--1    if (!setSrcNoteOffset(noteIndex, 0, loopInfo.loopEndOffsetFromEntryJump()))
--        return false;
-+    if (!setSrcNoteOffset(noteIndex, SrcNote::ForOf::BackJumpOffset,
-+                          loopInfo.loopEndOffsetFromEntryJump()))
-+    {
-+        return false;
-+    }
- 
-     // No breaks or continues should occur in spreads.
-     MOZ_ASSERT(loopInfo.breaks.offset == -1);
-     MOZ_ASSERT(loopInfo.continues.offset == -1);
- 
-     if (!tryNoteList.append(JSTRY_FOR_OF, stackDepth, loopInfo.headOffset(),
-                             loopInfo.breakTargetOffset()))
-     {
-@@ -4810,176 +4823,48 @@ BytecodeEmitter::emitForOf(ParseNode* fo
-     bool allowSelfHostedIter = false;
-     if (emitterMode == BytecodeEmitter::SelfHosting &&
-         forHeadExpr->isKind(ParseNodeKind::Call) &&
-         forHeadExpr->pn_head->name() == cx->names().allowContentIter)
-     {
-         allowSelfHostedIter = true;
-     }
- 
--    // Evaluate the expression being iterated. The forHeadExpr should use a
--    // distinct TDZCheckCache to evaluate since (abstractly) it runs in its own
--    // LexicalEnvironment.
--    if (!emitTreeInBranch(forHeadExpr))                   // ITERABLE
--        return false;
--    if (iterKind == IteratorKind::Async) {
--        if (!emitAsyncIterator())                         // NEXT ITER
--            return false;
--    } else {
--        if (!emitIterator())                              // NEXT ITER
--            return false;
--    }
--
--    int32_t iterDepth = stackDepth;
--
--    // For-of loops have the iterator next method, the iterator itself, and
--    // the result.value on the stack.
--    // Push an undefined to balance the stack.
--    if (!emit1(JSOP_UNDEFINED))                           // NEXT ITER UNDEF
--        return false;
--
--    ForOfLoopControl loopInfo(this, iterDepth, allowSelfHostedIter, iterKind);
--
--    // Annotate so IonMonkey can find the loop-closing jump.
--    unsigned noteIndex;
--    if (!newSrcNote(SRC_FOR_OF, &noteIndex))
--        return false;
--
--    if (!loopInfo.emitEntryJump(this))                    // NEXT ITER UNDEF
--        return false;
--
--    if (!loopInfo.emitLoopHead(this, Nothing()))          // NEXT ITER UNDEF
--        return false;
--
--    // If the loop had an escaping lexical declaration, replace the current
--    // environment with an dead zoned one to implement TDZ semantics.
-+    ForOfEmitter forOf(this, headLexicalEmitterScope, allowSelfHostedIter, iterKind);
-+
-+    if (!forOf.emitIterated())                            //
-+        return false;
-+
-+    if (!emitTree(forHeadExpr))                           // ITERABLE
-+        return false;
-+
-     if (headLexicalEmitterScope) {
--        // The environment chain only includes an environment for the for-of
--        // loop head *if* a scope binding is captured, thereby requiring
--        // recreation each iteration. If a lexical scope exists for the head,
--        // it must be the innermost one. If that scope has closed-over
--        // bindings inducing an environment, recreate the current environment.
-         DebugOnly<ParseNode*> forOfTarget = forOfHead->pn_kid1;
-         MOZ_ASSERT(forOfTarget->isKind(ParseNodeKind::Let) ||
-                    forOfTarget->isKind(ParseNodeKind::Const));
--        MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope());
--        MOZ_ASSERT(headLexicalEmitterScope->scope(this)->kind() == ScopeKind::Lexical);
--
--        if (headLexicalEmitterScope->hasEnvironment()) {
--            if (!emit1(JSOP_RECREATELEXICALENV))          // NEXT ITER UNDEF
--                return false;
--        }
--
--        // For uncaptured bindings, put them back in TDZ.
--        if (!headLexicalEmitterScope->deadZoneFrameSlots(this))
--            return false;
--    }
--
--    {
--#ifdef DEBUG
--        auto loopDepth = this->stackDepth;
--#endif
--
--        // Make sure this code is attributed to the "for".
--        if (!updateSourceCoordNotes(forOfHead->pn_pos.begin))
--            return false;
--
--        if (!emit1(JSOP_POP))                             // NEXT ITER
--            return false;
--        if (!emit1(JSOP_DUP2))                            // NEXT ITER NEXT ITER
--            return false;
--
--        if (!emitIteratorNext(forOfHead, iterKind, allowSelfHostedIter))
--            return false;                                 // NEXT ITER RESULT
--
--        if (!emit1(JSOP_DUP))                             // NEXT ITER RESULT RESULT
--            return false;
--        if (!emitAtomOp(cx->names().done, JSOP_GETPROP))  // NEXT ITER RESULT DONE
--            return false;
--
--        InternalIfEmitter ifDone(this);
--
--        if (!ifDone.emitThen())                           // NEXT ITER RESULT
--            return false;
--
--        // Remove RESULT from the stack to release it.
--        if (!emit1(JSOP_POP))                             // NEXT ITER
--            return false;
--        if (!emit1(JSOP_UNDEFINED))                       // NEXT ITER UNDEF
--            return false;
--
--        // If the iteration is done, leave loop here, instead of the branch at
--        // the end of the loop.
--        if (!loopInfo.emitSpecialBreakForDone(this))      // NEXT ITER UNDEF
--            return false;
--
--        if (!ifDone.emitEnd())                            // NEXT ITER RESULT
--            return false;
--
--        // Emit code to assign result.value to the iteration variable.
--        //
--        // Note that ES 13.7.5.13, step 5.c says getting result.value does not
--        // call IteratorClose, so start JSTRY_ITERCLOSE after the GETPROP.
--        if (!emitAtomOp(cx->names().value, JSOP_GETPROP)) // NEXT ITER VALUE
--            return false;
--
--        if (!loopInfo.emitBeginCodeNeedingIteratorClose(this))
--            return false;
--
--        if (!emitInitializeForInOrOfTarget(forOfHead))    // NEXT ITER VALUE
--            return false;
--
--        MOZ_ASSERT(stackDepth == loopDepth,
--                   "the stack must be balanced around the initializing "
--                   "operation");
--
--        // Remove VALUE from the stack to release it.
--        if (!emit1(JSOP_POP))                             // NEXT ITER
--            return false;
--        if (!emit1(JSOP_UNDEFINED))                       // NEXT ITER UNDEF
--            return false;
--
--        // Perform the loop body.
--        ParseNode* forBody = forOfLoop->pn_right;
--        if (!emitTree(forBody))                           // NEXT ITER UNDEF
--            return false;
--
--        MOZ_ASSERT(stackDepth == loopDepth,
--                   "the stack must be balanced around the for-of body");
--
--        if (!loopInfo.emitEndCodeNeedingIteratorClose(this))
--            return false;
--
--        loopInfo.setContinueTarget(offset());
--
--        if (!loopInfo.emitLoopEntry(this, getOffsetForLoop(forHeadExpr)))
--            return false;                                 // NEXT ITER UNDEF
--
--        if (!emit1(JSOP_FALSE))                           // NEXT ITER UNDEF FALSE
--            return false;
--        if (!loopInfo.emitLoopEnd(this, JSOP_IFEQ))       // NEXT ITER UNDEF
--            return false;
--
--        MOZ_ASSERT(this->stackDepth == loopDepth);
--    }
--
--    // Let Ion know where the closing jump of this loop is.
--    if (!setSrcNoteOffset(noteIndex, 0, loopInfo.loopEndOffsetFromEntryJump()))
--        return false;
--
--    if (!loopInfo.patchBreaksAndContinues(this))
--        return false;
--
--    if (!tryNoteList.append(JSTRY_FOR_OF, stackDepth, loopInfo.headOffset(),
--                            loopInfo.breakTargetOffset()))
--    {
--        return false;
--    }
--
--    return emitPopN(3);                                   //
-+    }
-+
-+    if (!forOf.emitInitialize(Some(forOfHead->pn_pos.begin)))
-+        return false;                                     // NEXT ITER VALUE
-+
-+    if (!emitInitializeForInOrOfTarget(forOfHead))        // NEXT ITER VALUE
-+        return false;
-+
-+    if (!forOf.emitBody())                                // NEXT ITER UNDEF
-+        return false;
-+
-+    // Perform the loop body.
-+    ParseNode* forBody = forOfLoop->pn_right;
-+    if (!emitTree(forBody))                               // NEXT ITER UNDEF
-+        return false;
-+
-+    if (!forOf.emitEnd(Some(forHeadExpr->pn_pos.begin)))  //
-+        return false;
-+
-+    return true;
- }
- 
- bool
- BytecodeEmitter::emitForIn(ParseNode* forInLoop, const EmitterScope* headLexicalEmitterScope)
- {
-     MOZ_ASSERT(forInLoop->isKind(ParseNodeKind::For));
-     MOZ_ASSERT(forInLoop->isArity(PN_BINARY));
-     MOZ_ASSERT(forInLoop->isOp(JSOP_ITER));
-diff --git a/js/src/frontend/BytecodeEmitter.h b/js/src/frontend/BytecodeEmitter.h
---- a/js/src/frontend/BytecodeEmitter.h
-+++ b/js/src/frontend/BytecodeEmitter.h
-@@ -544,16 +544,18 @@ struct MOZ_STACK_CLASS BytecodeEmitter
-     MOZ_MUST_USE bool emitJumpTarget(JumpTarget* target);
-     MOZ_MUST_USE bool emitJumpNoFallthrough(JSOp op, JumpList* jump);
-     MOZ_MUST_USE bool emitJump(JSOp op, JumpList* jump);
-     MOZ_MUST_USE bool emitBackwardJump(JSOp op, JumpTarget target, JumpList* jump,
-                                        JumpTarget* fallthrough);
-     void patchJumpsToTarget(JumpList jump, JumpTarget target);
-     MOZ_MUST_USE bool emitJumpTargetAndPatch(JumpList jump);
- 
-+    MOZ_MUST_USE bool emitCall(JSOp op, uint16_t argc,
-+                               const mozilla::Maybe<uint32_t>& sourceCoordOffset);
-     MOZ_MUST_USE bool emitCall(JSOp op, uint16_t argc, ParseNode* pn = nullptr);
-     MOZ_MUST_USE bool emitCallIncDec(ParseNode* incDec);
- 
-     mozilla::Maybe<uint32_t> getOffsetForLoop(ParseNode* nextpn);
- 
-     MOZ_MUST_USE bool emitGoto(NestableControl* target, JumpList* jumplist,
-                                SrcNoteType noteType = SRC_NULL);
- 
-@@ -741,17 +743,18 @@ struct MOZ_STACK_CLASS BytecodeEmitter
-     // emitIterator expects the iterable to already be on the stack.
-     // It will replace that stack value with the corresponding iterator
-     MOZ_MUST_USE bool emitIterator();
- 
-     MOZ_MUST_USE bool emitAsyncIterator();
- 
-     // Pops iterator from the top of the stack. Pushes the result of |.next()|
-     // onto the stack.
--    MOZ_MUST_USE bool emitIteratorNext(ParseNode* pn, IteratorKind kind = IteratorKind::Sync,
-+    MOZ_MUST_USE bool emitIteratorNext(const mozilla::Maybe<uint32_t>& callSourceCoordOffset,
-+                                       IteratorKind kind = IteratorKind::Sync,
-                                        bool allowSelfHosted = false);
-     MOZ_MUST_USE bool emitIteratorCloseInScope(EmitterScope& currentScope,
-                                                IteratorKind iterKind = IteratorKind::Sync,
-                                                CompletionKind completionKind = CompletionKind::Normal,
-                                                bool allowSelfHosted = false);
-     MOZ_MUST_USE bool emitIteratorCloseInInnermostScope(IteratorKind iterKind = IteratorKind::Sync,
-                                                         CompletionKind completionKind = CompletionKind::Normal,
-                                                         bool allowSelfHosted = false) {
-diff --git a/js/src/frontend/ForOfEmitter.cpp b/js/src/frontend/ForOfEmitter.cpp
-new file mode 100644
---- /dev/null
-+++ b/js/src/frontend/ForOfEmitter.cpp
-@@ -0,0 +1,233 @@
-+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
-+ * vim: set ts=8 sts=4 et sw=4 tw=99:
-+ * This Source Code Form is subject to the terms of the Mozilla Public
-+ * License, v. 2.0. If a copy of the MPL was not distributed with this
-+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-+
-+#include "frontend/ForOfEmitter.h"
-+
-+#include "frontend/BytecodeEmitter.h"
-+#include "frontend/EmitterScope.h"
-+#include "frontend/IfEmitter.h"
-+#include "frontend/SourceNotes.h"
-+#include "vm/Opcodes.h"
-+#include "vm/Scope.h"
-+
-+using namespace js;
-+using namespace js::frontend;
-+
-+using mozilla::Maybe;
-+using mozilla::Nothing;
-+
-+ForOfEmitter::ForOfEmitter(BytecodeEmitter* bce, const EmitterScope* headLexicalEmitterScope,
-+                           bool allowSelfHostedIter, IteratorKind iterKind)
-+  : bce_(bce),
-+    allowSelfHostedIter_(allowSelfHostedIter),
-+    iterKind_(iterKind),
-+    headLexicalEmitterScope_(headLexicalEmitterScope)
-+{}
-+
-+bool
-+ForOfEmitter::emitIterated()
-+{
-+    MOZ_ASSERT(state_ == State::Start);
-+
-+    // Evaluate the expression being iterated. The forHeadExpr should use a
-+    // distinct TDZCheckCache to evaluate since (abstractly) it runs in its
-+    // own LexicalEnvironment.
-+    tdzCacheForIteratedValue_.emplace(bce_);
-+
-+#ifdef DEBUG
-+    state_ = State::Iterated;
-+#endif
-+    return true;
-+}
-+
-+bool
-+ForOfEmitter::emitInitialize(const Maybe<uint32_t>& forPos)
-+{
-+    MOZ_ASSERT(state_ == State::Iterated);
-+
-+    tdzCacheForIteratedValue_.reset();
-+
-+    if (iterKind_ == IteratorKind::Async) {
-+        if (!bce_->emitAsyncIterator())               // NEXT ITER
-+            return false;
-+    } else {
-+        if (!bce_->emitIterator())                    // NEXT ITER
-+            return false;
-+    }
-+
-+    int32_t iterDepth = bce_->stackDepth;
-+
-+    // For-of loops have the iterator next method, the iterator itself, and
-+    // the result.value on the stack.
-+    // Push an undefined to balance the stack.
-+    if (!bce_->emit1(JSOP_UNDEFINED))                 // NEXT ITER UNDEF
-+        return false;
-+
-+    loopInfo_.emplace(bce_, iterDepth, allowSelfHostedIter_, iterKind_);
-+
-+    // Annotate so IonMonkey can find the loop-closing jump.
-+    if (!bce_->newSrcNote(SRC_FOR_OF, &noteIndex_))
-+        return false;
-+
-+    if (!loopInfo_->emitEntryJump(bce_))              // NEXT ITER UNDEF
-+        return false;
-+
-+    if (!loopInfo_->emitLoopHead(bce_, Nothing()))    // NEXT ITER UNDEF
-+        return false;
-+
-+    // If the loop had an escaping lexical declaration, replace the current
-+    // environment with an dead zoned one to implement TDZ semantics.
-+    if (headLexicalEmitterScope_) {
-+        // The environment chain only includes an environment for the for-of
-+        // loop head *if* a scope binding is captured, thereby requiring
-+        // recreation each iteration. If a lexical scope exists for the head,
-+        // it must be the innermost one. If that scope has closed-over
-+        // bindings inducing an environment, recreate the current environment.
-+        MOZ_ASSERT(headLexicalEmitterScope_ == bce_->innermostEmitterScope());
-+        MOZ_ASSERT(headLexicalEmitterScope_->scope(bce_)->kind() == ScopeKind::Lexical);
-+
-+        if (headLexicalEmitterScope_->hasEnvironment()) {
-+            if (!bce_->emit1(JSOP_RECREATELEXICALENV))
-+                return false;                         // NEXT ITER UNDEF
-+        }
-+
-+        // For uncaptured bindings, put them back in TDZ.
-+        if (!headLexicalEmitterScope_->deadZoneFrameSlots(bce_))
-+            return false;
-+    }
-+
-+#ifdef DEBUG
-+    loopDepth_ = bce_->stackDepth;
-+#endif
-+
-+    // Make sure this code is attributed to the "for".
-+    if (forPos) {
-+        if (!bce_->updateSourceCoordNotes(*forPos))
-+            return false;
-+    }
-+
-+    if (!bce_->emit1(JSOP_POP))                       // NEXT ITER
-+        return false;
-+    if (!bce_->emit1(JSOP_DUP2))                      // NEXT ITER NEXT ITER
-+        return false;
-+
-+    if (!bce_->emitIteratorNext(forPos, iterKind_, allowSelfHostedIter_))
-+        return false;                                 // NEXT ITER RESULT
-+
-+    if (!bce_->emit1(JSOP_DUP))                       // NEXT ITER RESULT RESULT
-+        return false;
-+    if (!bce_->emitAtomOp(bce_->cx->names().done, JSOP_GETPROP))
-+        return false;                                 // NEXT ITER RESULT DONE
-+
-+    InternalIfEmitter ifDone(bce_);
-+
-+    if (!ifDone.emitThen())                           // NEXT ITER RESULT
-+        return false;
-+
-+    // Remove RESULT from the stack to release it.
-+    if (!bce_->emit1(JSOP_POP))                       // NEXT ITER
-+        return false;
-+    if (!bce_->emit1(JSOP_UNDEFINED))                 // NEXT ITER UNDEF
-+        return false;
-+
-+    // If the iteration is done, leave loop here, instead of the branch at
-+    // the end of the loop.
-+    if (!loopInfo_->emitSpecialBreakForDone(bce_))    // NEXT ITER UNDEF
-+        return false;
-+
-+    if (!ifDone.emitEnd())                            // NEXT ITER RESULT
-+        return false;
-+
-+    // Emit code to assign result.value to the iteration variable.
-+    //
-+    // Note that ES 13.7.5.13, step 5.c says getting result.value does not
-+    // call IteratorClose, so start JSTRY_ITERCLOSE after the GETPROP.
-+    if (!bce_->emitAtomOp(bce_->cx->names().value, JSOP_GETPROP))
-+        return false;                                 // NEXT ITER VALUE
-+
-+    if (!loopInfo_->emitBeginCodeNeedingIteratorClose(bce_))
-+        return false;
-+
-+#ifdef DEBUG
-+    state_ = State::Initialize;
-+#endif
-+    return true;
-+}
-+
-+bool
-+ForOfEmitter::emitBody()
-+{
-+    MOZ_ASSERT(state_ == State::Initialize);
-+
-+    MOZ_ASSERT(bce_->stackDepth == loopDepth_,
-+               "the stack must be balanced around the initializing "
-+               "operation");
-+
-+    // Remove VALUE from the stack to release it.
-+    if (!bce_->emit1(JSOP_POP))                       // NEXT ITER
-+        return false;
-+    if (!bce_->emit1(JSOP_UNDEFINED))                 // NEXT ITER UNDEF
-+        return false;
-+
-+#ifdef DEBUG
-+    state_ = State::Body;
-+#endif
-+    return true;
-+}
-+
-+bool
-+ForOfEmitter::emitEnd(const Maybe<uint32_t>& iteratedPos)
-+{
-+    MOZ_ASSERT(state_ == State::Body);
-+
-+    MOZ_ASSERT(bce_->stackDepth == loopDepth_,
-+               "the stack must be balanced around the for-of body");
-+
-+    if (!loopInfo_->emitEndCodeNeedingIteratorClose(bce_))
-+        return false;
-+
-+    loopInfo_->setContinueTarget(bce_->offset());
-+
-+    // We use the iterated value's position to attribute JSOP_LOOPENTRY,
-+    // which corresponds to the iteration protocol.
-+    // This is a bit misleading for 2nd and later iterations and might need
-+    // some fix (bug 1482003).
-+    if (!loopInfo_->emitLoopEntry(bce_, iteratedPos))
-+        return false;
-+
-+    if (!bce_->emit1(JSOP_FALSE))                     // NEXT ITER UNDEF FALSE
-+        return false;
-+    if (!loopInfo_->emitLoopEnd(bce_, JSOP_IFEQ))     // NEXT ITER UNDEF
-+        return false;
-+
-+    MOZ_ASSERT(bce_->stackDepth == loopDepth_);
-+
-+    // Let Ion know where the closing jump of this loop is.
-+    if (!bce_->setSrcNoteOffset(noteIndex_, SrcNote::ForOf::BackJumpOffset,
-+                                loopInfo_->loopEndOffsetFromEntryJump()))
-+    {
-+        return false;
-+    }
-+
-+    if (!loopInfo_->patchBreaksAndContinues(bce_))
-+        return false;
-+
-+    if (!bce_->tryNoteList.append(JSTRY_FOR_OF, bce_->stackDepth, loopInfo_->headOffset(),
-+                                  loopInfo_->breakTargetOffset()))
-+    {
-+        return false;
-+    }
-+
-+    if (!bce_->emitPopN(3))                           //
-+        return false;
-+
-+    loopInfo_.reset();
-+
-+#ifdef DEBUG
-+    state_ = State::End;
-+#endif
-+    return true;
-+}
-diff --git a/js/src/frontend/ForOfEmitter.h b/js/src/frontend/ForOfEmitter.h
-new file mode 100644
---- /dev/null
-+++ b/js/src/frontend/ForOfEmitter.h
-@@ -0,0 +1,123 @@
-+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
-+ * vim: set ts=8 sts=4 et sw=4 tw=99:
-+ * This Source Code Form is subject to the terms of the Mozilla Public
-+ * License, v. 2.0. If a copy of the MPL was not distributed with this
-+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-+
-+#ifndef frontend_ForOfEmitter_h
-+#define frontend_ForOfEmitter_h
-+
-+#include "mozilla/Attributes.h"
-+#include "mozilla/Maybe.h"
-+
-+#include <stdint.h>
-+
-+#include "frontend/ForOfLoopControl.h"
-+#include "frontend/JumpList.h"
-+#include "frontend/TDZCheckCache.h"
-+#include "vm/Iteration.h"
-+
-+namespace js {
-+namespace frontend {
-+
-+struct BytecodeEmitter;
-+class EmitterScope;
-+
-+// Class for emitting bytecode for for-of loop.
-+//
-+// Usage: (check for the return value is omitted for simplicity)
-+//
-+//   `for (init of iterated) body`
-+//     // headLexicalEmitterScope: lexical scope for init
-+//     ForOfEmitter forOf(this, headLexicalEmitterScope);
-+//     forOf.emitIterated();
-+//     emit(iterated);
-+//     forOf.emitInitialize(Some(offset_of_for));
-+//     emit(init);
-+//     forOf.emitBody();
-+//     emit(body);
-+//     forOf.emitEnd(Some(offset_of_iterated));
-+//
-+class MOZ_STACK_CLASS ForOfEmitter
-+{
-+    BytecodeEmitter* bce_;
-+
-+    // The source note index for SRC_FOR_OF.
-+    unsigned noteIndex_ = 0;
-+
-+#ifdef DEBUG
-+    // The stack depth before emitting IteratorNext code inside loop.
-+    int32_t loopDepth_ = 0;
-+#endif
-+
-+    bool allowSelfHostedIter_;
-+    IteratorKind iterKind_;
-+
-+    // Jump from into JSOP_LOOPENTRY.
-+    JumpList initialJump_;
-+
-+    mozilla::Maybe<ForOfLoopControl> loopInfo_;
-+
-+    // The lexical scope to be freshened for each iteration.
-+    // See the comment in `emitBody` for more details.
-+    const EmitterScope* headLexicalEmitterScope_;
-+
-+    // Cache for the iterated value.
-+    // (The cache for the iteration body is inside `loopInfo_`)
-+    mozilla::Maybe<TDZCheckCache> tdzCacheForIteratedValue_;
-+
-+#ifdef DEBUG
-+    // The state of this emitter.
-+    //
-+    // +-------+ emitIterated +----------+ emitInitialize +------------+
-+    // | Start |------------->| Iterated |--------------->| Initialize |-+
-+    // +-------+              +----------+                +------------+ |
-+    //                                                                   |
-+    //                                +----------------------------------+
-+    //                                |
-+    //                                | emitBody +------+ emitEnd  +-----+
-+    //                                +----------| Body |--------->| End |
-+    //                                           +------+          +-----+
-+    enum class State {
-+        // The initial state.
-+        Start,
-+
-+        // After calling emitIterated.
-+        Iterated,
-+
-+        // After calling emitInitialize.
-+        Initialize,
-+
-+        // After calling emitBody.
-+        Body,
-+
-+        // After calling emitEnd.
-+        End
-+    };
-+    State state_ = State::Start;
-+#endif
-+
-+  public:
-+    ForOfEmitter(BytecodeEmitter* bce, const EmitterScope* headLexicalEmitterScope,
-+                 bool allowSelfHostedIter, IteratorKind iterKind);
-+
-+    // The offset in the source code for each character below:
-+    //
-+    //   for ( var x of obj ) { ... }
-+    //   ^              ^
-+    //   |              |
-+    //   |              iteratedPos
-+    //   |
-+    //   forPos
-+    //
-+    // Can be Nothing() if not available.
-+    MOZ_MUST_USE bool emitIterated();
-+    MOZ_MUST_USE bool emitInitialize(const mozilla::Maybe<uint32_t>& forPos);
-+    MOZ_MUST_USE bool emitBody();
-+    MOZ_MUST_USE bool emitEnd(const mozilla::Maybe<uint32_t>& iteratedPos);
-+};
-+
-+} /* namespace frontend */
-+} /* namespace js */
-+
-+#endif /* frontend_ForOfEmitter_h */
-diff --git a/js/src/frontend/SourceNotes.h b/js/src/frontend/SourceNotes.h
---- a/js/src/frontend/SourceNotes.h
-+++ b/js/src/frontend/SourceNotes.h
-@@ -59,16 +59,26 @@ class SrcNote {
-     class ForIn {
-       public:
-         enum Fields {
-             // The offset of JSOP_IFEQ at the end of the loop from JSOP_GOTO.
-             BackJumpOffset,
-             Count,
-         };
-     };
-+    // SRC_FOR_OF: Source note for JSOP_GOTO at the top of for-of loop,
-+    //             which jumps to JSOP_LOOPENTRY.
-+    class ForOf {
-+      public:
-+        enum Fields {
-+            // The offset of JSOP_IFEQ at the end of the loop from JSOP_GOTO.
-+            BackJumpOffset,
-+            Count,
-+        };
-+    };
-     // SRC_TABLESWITCH: Source note for JSOP_TABLESWITCH.
-     class TableSwitch {
-       public:
-         enum Fields {
-             // The offset of the end of switch (the first non-JumpTarget op
-             // after switch) from JSOP_TABLESWITCH.
-             EndOffset,
-             Count
-@@ -132,18 +142,17 @@ class SrcNote {
-     M(SRC_NULL,         "null",        0)  /* Terminates a note vector. */                         \
-     M(SRC_IF,           "if",          0)  /* JSOP_IFEQ bytecode is from an if-then. */            \
-     M(SRC_IF_ELSE,      "if-else",     0)  /* JSOP_IFEQ bytecode is from an if-then-else. */       \
-     M(SRC_COND,         "cond",        0)  /* JSOP_IFEQ is from conditional ?: operator. */        \
-     M(SRC_FOR,          "for",         SrcNote::For::Count) \
-     M(SRC_WHILE,        "while",       1)  /* JSOP_GOTO to for or while loop condition from before \
-                                               loop, else JSOP_NOP at top of do-while loop. */      \
-     M(SRC_FOR_IN,       "for-in",      SrcNote::ForIn::Count) \
--    M(SRC_FOR_OF,       "for-of",      1)  /* JSOP_GOTO to for-of loop condition from before       \
--                                              loop. */                                             \
-+    M(SRC_FOR_OF,       "for-of",      SrcNote::ForOf::Count) \
-     M(SRC_CONTINUE,     "continue",    0)  /* JSOP_GOTO is a continue. */                          \
-     M(SRC_BREAK,        "break",       0)  /* JSOP_GOTO is a break. */                             \
-     M(SRC_BREAK2LABEL,  "break2label", 0)  /* JSOP_GOTO for 'break label'. */                      \
-     M(SRC_SWITCHBREAK,  "switchbreak", 0)  /* JSOP_GOTO is a break in a switch. */                 \
-     M(SRC_TABLESWITCH,  "tableswitch", SrcNote::TableSwitch::Count) \
-     M(SRC_CONDSWITCH,   "condswitch",  SrcNote::CondSwitch::Count) \
-     M(SRC_NEXTCASE,     "nextcase",    SrcNote::NextCase::Count) \
-     M(SRC_ASSIGNOP,     "assignop",    0)  /* += or another assign-op follows. */                  \
-diff --git a/js/src/jit/IonControlFlow.cpp b/js/src/jit/IonControlFlow.cpp
---- a/js/src/jit/IonControlFlow.cpp
-+++ b/js/src/jit/IonControlFlow.cpp
-@@ -288,17 +288,17 @@ ControlFlowGenerator::snoopControlFlow(J
- 
-           case SRC_SWITCHBREAK:
-             return processSwitchBreak(op);
- 
-           case SRC_WHILE:
-           case SRC_FOR_IN:
-           case SRC_FOR_OF:
-             // while (cond) { }
--            return processWhileOrForInLoop(sn);
-+            return processWhileOrForInOrForOfLoop(sn);
- 
-           default:
-             // Hard assert for now - make an error later.
-             MOZ_CRASH("unknown goto case");
-         }
-         break;
-       }
- 
-@@ -892,32 +892,34 @@ ControlFlowGenerator::processForUpdateEn
-         // sure we capture the right stack.
-         current->setStartPc(entry->successor()->startPc());
-         current->setStopPc(entry->successor()->startPc());
-     }
-     return finishLoop(state, state.loop.successor);
- }
- 
- ControlFlowGenerator::ControlStatus
--ControlFlowGenerator::processWhileOrForInLoop(jssrcnote* sn)
-+ControlFlowGenerator::processWhileOrForInOrForOfLoop(jssrcnote* sn)
- {
-     // while (cond) { } loops have the following structure:
-     //    GOTO cond   ; SRC_WHILE (offset to IFNE)
-     //    LOOPHEAD
-     //    ...
-     //  cond:
-     //    LOOPENTRY
-     //    ...
-     //    IFNE        ; goes to LOOPHEAD
--    // for-in/for-of loops are similar;
--    // for-in has IFEQ as the back jump, and the cond will be a MOREITER.
-+    // for-in/for-of loops are similar; for-in/for-of have IFEQ as the back
-+    // jump, and the cond of for-in will be a MOREITER.
-     MOZ_ASSERT(SN_TYPE(sn) == SRC_FOR_OF || SN_TYPE(sn) == SRC_FOR_IN || SN_TYPE(sn) == SRC_WHILE);
-     // FIXME: Replaced in the subsequent patch.
-     static_assert(unsigned(SrcNote::ForIn::BackJumpOffset) == 0,
-                   "SrcNote::{While,ForIn,ForOf}::BackJumpOffset should be same");
-+    static_assert(unsigned(SrcNote::ForOf::BackJumpOffset) == 0,
-+                  "SrcNote::{While,ForIn,ForOf}::BackJumpOffset should be same");
-     int backjumppcOffset = GetSrcNoteOffset(sn, SrcNote::ForIn::BackJumpOffset);
-     jsbytecode* backjumppc = pc + backjumppcOffset;
-     MOZ_ASSERT(backjumppc > pc);
- 
-     // Verify that the back jump goes back to a loophead op.
-     MOZ_ASSERT(JSOp(*GetNextPc(pc)) == JSOP_LOOPHEAD);
-     MOZ_ASSERT(GetNextPc(pc) == backjumppc + GetJumpOffset(backjumppc));
- 
-diff --git a/js/src/jit/IonControlFlow.h b/js/src/jit/IonControlFlow.h
---- a/js/src/jit/IonControlFlow.h
-+++ b/js/src/jit/IonControlFlow.h
-@@ -849,17 +849,17 @@ class ControlFlowGenerator
-     ControlStatus processDoWhileBodyEnd(CFGState& state);
-     ControlStatus processDoWhileCondEnd(CFGState& state);
-     ControlStatus processWhileCondEnd(CFGState& state);
-     ControlStatus processWhileBodyEnd(CFGState& state);
-     ControlStatus processForLoop(JSOp op, jssrcnote* sn);
-     ControlStatus processForCondEnd(CFGState& state);
-     ControlStatus processForBodyEnd(CFGState& state);
-     ControlStatus processForUpdateEnd(CFGState& state);
--    ControlStatus processWhileOrForInLoop(jssrcnote* sn);
-+    ControlStatus processWhileOrForInOrForOfLoop(jssrcnote* sn);
-     ControlStatus processNextTableSwitchCase(CFGState& state);
-     ControlStatus processCondSwitch();
-     ControlStatus processCondSwitchCase(CFGState& state);
-     ControlStatus processCondSwitchDefault(CFGState& state);
-     ControlStatus processCondSwitchBody(CFGState& state);
-     ControlStatus processSwitchBreak(JSOp op);
-     ControlStatus processSwitchEnd(DeferredEdge* breaks, jsbytecode* exitpc);
-     ControlStatus processTry();
-diff --git a/js/src/moz.build b/js/src/moz.build
---- a/js/src/moz.build
-+++ b/js/src/moz.build
-@@ -210,16 +210,17 @@ UNIFIED_SOURCES += [
-     'ds/MemoryProtectionExceptionHandler.cpp',
-     'frontend/BytecodeCompiler.cpp',
-     'frontend/BytecodeControlStructures.cpp',
-     'frontend/BytecodeEmitter.cpp',
-     'frontend/CForEmitter.cpp',
-     'frontend/EmitterScope.cpp',
-     'frontend/FoldConstants.cpp',
-     'frontend/ForInEmitter.cpp',
-+    'frontend/ForOfEmitter.cpp',
-     'frontend/ForOfLoopControl.cpp',
-     'frontend/IfEmitter.cpp',
-     'frontend/JumpList.cpp',
-     'frontend/NameFunctions.cpp',
-     'frontend/ParseNode.cpp',
-     'frontend/SwitchEmitter.cpp',
-     'frontend/TDZCheckCache.cpp',
-     'frontend/TokenStream.cpp',
-diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp
---- a/js/src/shell/js.cpp
-+++ b/js/src/shell/js.cpp
-@@ -2749,18 +2749,17 @@ SrcNotes(JSContext* cx, HandleScript scr
-                               unsigned(GetSrcNoteOffset(sn, SrcNote::For::BackJumpOffset))))
-             {
-                 return false;
-             }
-             break;
- 
-           case SRC_FOR_IN:
-           case SRC_FOR_OF:
--            // FIXME: replaced in the subsequent patch.
--            static_assert(unsigned(SrcNote::ForIn::BackJumpOffset) == 0,
-+            static_assert(unsigned(SrcNote::ForIn::BackJumpOffset) == unsigned(SrcNote::ForOf::BackJumpOffset),
-                           "SrcNote::{ForIn,ForOf}::BackJumpOffset should be same");
-             if (!sp->jsprintf(" backjump %u",
-                               unsigned(GetSrcNoteOffset(sn, SrcNote::ForIn::BackJumpOffset))))
-             {
-                 return false;
-             }
-             break;
- 

Some files were not shown because too many files changed in this diff