Bug 1118084 - Remove self-hosted and user-exposed PJS methods. (r=lth)
authorShu-yu Guo <shu@rfrn.org>
Fri, 09 Jan 2015 00:06:03 -0800
changeset 248701 68d1c3fd25f1fbbb5b8910a41ff0a691c0eae371
parent 248700 5f8dbb4956752d9759c92ac84b37c79d046805d2
child 248702 46c80c517631bd66053a9a84f8419329f7891935
push id4489
push userraliiev@mozilla.com
push dateMon, 23 Feb 2015 15:17:55 +0000
treeherdermozilla-beta@fd7c3dc24146 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerslth
bugs1118084
milestone37.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1118084 - Remove self-hosted and user-exposed PJS methods. (r=lth)
js/src/Makefile.in
js/src/builtin/Array.js
js/src/builtin/ParallelUtilities.js
js/src/builtin/TestingFunctions.cpp
js/src/builtin/TypedObject.cpp
js/src/builtin/TypedObject.js
js/src/builtin/Utilities.js
js/src/jit-test/tests/ion/inlining/TypedObject-TypeDescrIsSizedArrayType.js
js/src/js.msg
js/src/jsarray.cpp
js/src/tests/ecma_7/TypedObject/method_scatter.js
js/src/vm/SelfHosting.cpp
js/src/vm/Xdr.h
--- a/js/src/Makefile.in
+++ b/js/src/Makefile.in
@@ -308,17 +308,16 @@ ifdef HAVE_DTRACE
 endif
 
 # Prepare self-hosted JS code for embedding
 export:: selfhosting
 selfhosting:: selfhosted.out.h
 
 selfhosting_srcs := \
   $(srcdir)/builtin/Utilities.js \
-  $(srcdir)/builtin/ParallelUtilities.js \
   $(srcdir)/builtin/Array.js \
   $(srcdir)/builtin/Date.js \
   $(srcdir)/builtin/Error.js \
   $(srcdir)/builtin/Generator.js \
   $(srcdir)/builtin/Intl.js \
   $(srcdir)/builtin/IntlData.js \
   $(srcdir)/builtin/Iterator.js \
   $(srcdir)/builtin/Map.js \
--- a/js/src/builtin/Array.js
+++ b/js/src/builtin/Array.js
@@ -777,531 +777,8 @@ function ArrayFrom(arrayLike, mapfn=unde
             _DefineDataProperty(A, k, mappedValue, attrs);
         }
     }
 
     // Steps 8.g.iv.1-3 and 18-20 are the same.
     A.length = k;
     return A;
 }
-
-#ifdef ENABLE_PARALLEL_JS
-
-/*
- * Strawman spec:
- *   http://wiki.ecmascript.org/doku.php?id=strawman:data_parallelism
- */
-
-/**
- * Creates a new array by applying |func(e, i, self)| for each element |e|
- * with index |i|.
- */
-function ArrayMapPar(func, mode) {
-  if (!IsCallable(func))
-    ThrowError(JSMSG_NOT_FUNCTION, DecompileArg(0, func));
-
-  var self = ToObject(this);
-  var length = self.length;
-  var buffer = NewDenseArray(length);
-
-  parallel: for (;;) {
-    // Avoid parallel compilation if we are already nested in another
-    // parallel section or the user told us not to parallelize. The
-    // use of a for (;;) loop is working around some ion limitations:
-    //
-    // - Breaking out of named blocks does not currently work (bug 684384);
-    // - Unreachable Code Elim. can't properly handle if (a && b) (bug 669796)
-    if (ShouldForceSequential())
-      break parallel;
-    if (!TRY_PARALLEL(mode))
-      break parallel;
-
-    var slicesInfo = ComputeSlicesInfo(length);
-    ForkJoin(mapThread, 0, slicesInfo.count, ForkJoinMode(mode), buffer);
-    return buffer;
-  }
-
-  // Sequential fallback:
-  ASSERT_SEQUENTIAL_IS_OK(mode);
-  for (var i = 0; i < length; i++)
-    UnsafePutElements(buffer, i, func(self[i], i, self));
-  return buffer;
-
-  function mapThread(workerId, sliceStart, sliceEnd) {
-    var sliceShift = slicesInfo.shift;
-    var sliceId;
-    while (GET_SLICE(sliceStart, sliceEnd, sliceId)) {
-      var indexStart = SLICE_START_INDEX(sliceShift, sliceId);
-      var indexEnd = SLICE_END_INDEX(sliceShift, indexStart, length);
-      for (var i = indexStart; i < indexEnd; i++)
-        UnsafePutElements(buffer, i, func(self[i], i, self));
-    }
-    return sliceId;
-  }
-}
-
-/**
- * Reduces the elements in an array in parallel. Order is not fixed and |func|
- * is assumed to be associative.
- */
-function ArrayReducePar(func, mode) {
-  if (!IsCallable(func))
-    ThrowError(JSMSG_NOT_FUNCTION, DecompileArg(0, func));
-
-  var self = ToObject(this);
-  var length = self.length;
-
-  if (length === 0)
-    ThrowError(JSMSG_EMPTY_ARRAY_REDUCE);
-
-  parallel: for (;;) { // see ArrayMapPar() to explain why for(;;) etc
-    if (ShouldForceSequential())
-      break parallel;
-    if (!TRY_PARALLEL(mode))
-      break parallel;
-
-    var slicesInfo = ComputeSlicesInfo(length);
-    var numSlices = slicesInfo.count;
-    var subreductions = NewDenseArray(numSlices);
-
-    ForkJoin(reduceThread, 0, numSlices, ForkJoinMode(mode), subreductions);
-
-    var accumulator = subreductions[0];
-    for (var i = 1; i < numSlices; i++)
-      accumulator = func(accumulator, subreductions[i]);
-    return accumulator;
-  }
-
-  // Sequential fallback:
-  ASSERT_SEQUENTIAL_IS_OK(mode);
-  var accumulator = self[0];
-  for (var i = 1; i < length; i++)
-    accumulator = func(accumulator, self[i]);
-  return accumulator;
-
-  function reduceThread(workerId, sliceStart, sliceEnd) {
-    var sliceShift = slicesInfo.shift;
-    var sliceId;
-    while (GET_SLICE(sliceStart, sliceEnd, sliceId)) {
-      var indexStart = SLICE_START_INDEX(sliceShift, sliceId);
-      var indexEnd = SLICE_END_INDEX(sliceShift, indexStart, length);
-      var accumulator = self[indexStart];
-      for (var i = indexStart + 1; i < indexEnd; i++)
-        accumulator = func(accumulator, self[i]);
-      UnsafePutElements(subreductions, sliceId, accumulator);
-    }
-    return sliceId;
-  }
-}
-
-/**
- * Returns an array [s_0, ..., s_N] where |s_i| is equal to the reduction (as
- * per |reduce()|) of elements |0..i|. This is the generalization of partial
- * sum.
- */
-function ArrayScanPar(func, mode) {
-  if (!IsCallable(func))
-    ThrowError(JSMSG_NOT_FUNCTION, DecompileArg(0, func));
-
-  var self = ToObject(this);
-  var length = self.length;
-
-  if (length === 0)
-    ThrowError(JSMSG_EMPTY_ARRAY_REDUCE);
-
-  // We need two buffers because phase2() will read an intermediate result and
-  // write a final result; that is safe against bailout-and-restart only if
-  // the intermediate and final buffers are distinct.  (Bug 1023755)
-  // Obviously paying for a second buffer is undesirable.
-  var buffer = NewDenseArray(length);
-  var buffer2 = NewDenseArray(length);
-
-  parallel: for (;;) { // see ArrayMapPar() to explain why for(;;) etc
-    if (ShouldForceSequential())
-      break parallel;
-    if (!TRY_PARALLEL(mode))
-      break parallel;
-
-    var slicesInfo = ComputeSlicesInfo(length);
-    var numSlices = slicesInfo.count;
-
-    // Scan slices individually (see comment on phase1()).
-    ForkJoin(phase1, 0, numSlices, ForkJoinMode(mode), buffer);
-
-    // Compute intermediates array (see comment on phase2()).
-    var intermediates = [];
-    var accumulator = buffer[finalElement(0)];
-    ARRAY_PUSH(intermediates, accumulator);
-    for (var i = 1; i < numSlices - 1; i++) {
-      accumulator = func(accumulator, buffer[finalElement(i)]);
-      ARRAY_PUSH(intermediates, accumulator);
-    }
-
-    // Complete each slice using intermediates array (see comment on phase2()).
-    //
-    // Slice 0 must be handled specially - it's just a copy - since we don't
-    // have an identity value for the operation.
-    for ( var k=0, limit=finalElement(0) ; k <= limit ; k++ )
-      buffer2[k] = buffer[k];
-    ForkJoin(phase2, 1, numSlices, ForkJoinMode(mode), buffer2);
-    return buffer2;
-  }
-
-  // Sequential fallback:
-  ASSERT_SEQUENTIAL_IS_OK(mode);
-  scan(self[0], 0, length);
-  return buffer;
-
-  function scan(accumulator, start, end) {
-    UnsafePutElements(buffer, start, accumulator);
-    for (var i = start + 1; i < end; i++) {
-      accumulator = func(accumulator, self[i]);
-      UnsafePutElements(buffer, i, accumulator);
-    }
-    return accumulator;
-  }
-
-  /**
-   * In phase 1, we divide the source array into |numSlices| slices and
-   * compute scan on each slice sequentially as if it were the entire
-   * array. This function is responsible for computing one of those
-   * slices.
-   *
-   * So, if we have an array [A,B,C,D,E,F,G,H,I], |numSlices === 3|,
-   * and our function |func| is sum, then we would wind up computing a
-   * result array like:
-   *
-   *     [A, A+B, A+B+C, D, D+E, D+E+F, G, G+H, G+H+I]
-   *      ^~~~~~~~~~~~^  ^~~~~~~~~~~~^  ^~~~~~~~~~~~~^
-   *      Slice 0        Slice 1        Slice 2
-   *
-   * Read on in phase2 to see what we do next!
-   */
-  function phase1(workerId, sliceStart, sliceEnd) {
-    var sliceShift = slicesInfo.shift;
-    var sliceId;
-    while (GET_SLICE(sliceStart, sliceEnd, sliceId)) {
-      var indexStart = SLICE_START_INDEX(sliceShift, sliceId);
-      var indexEnd = SLICE_END_INDEX(sliceShift, indexStart, length);
-      scan(self[indexStart], indexStart, indexEnd);
-    }
-    return sliceId;
-  }
-
-  /**
-   * Computes the index of the final element computed by the slice |sliceId|.
-   */
-  function finalElement(sliceId) {
-    var sliceShift = slicesInfo.shift;
-    return SLICE_END_INDEX(sliceShift, SLICE_START_INDEX(sliceShift, sliceId), length) - 1;
-  }
-
-  /**
-   * After computing the phase1 results, we compute an
-   * |intermediates| array. |intermediates[i]| contains the result
-   * of reducing the final value from each preceding slice j<i with
-   * the final value of slice i. So, to continue our previous
-   * example, the intermediates array would contain:
-   *
-   *   [A+B+C, (A+B+C)+(D+E+F), ((A+B+C)+(D+E+F))+(G+H+I)]
-   *
-   * Here I have used parenthesization to make clear the order of
-   * evaluation in each case.
-   *
-   *   An aside: currently the intermediates array is computed
-   *   sequentially. In principle, we could compute it in parallel,
-   *   at the cost of doing duplicate work. This did not seem
-   *   particularly advantageous to me, particularly as the number
-   *   of slices is typically quite small (one per core), so I opted
-   *   to just compute it sequentially.
-   *
-   * Phase 2 combines the results of phase1 with the intermediates
-   * array to produce the final scan results. The idea is to
-   * reiterate over each element S[i] in the slice |sliceId|, which
-   * currently contains the result of reducing with S[0]...S[i]
-   * (where S0 is the first thing in the slice), and combine that
-   * with |intermediate[sliceId-1]|, which represents the result of
-   * reducing everything in the input array prior to the slice.
-   *
-   * To continue with our example, in phase 1 we computed slice 1 to
-   * be [D, D+E, D+E+F]. We will combine those results with
-   * |intermediates[1-1]|, which is |A+B+C|, so that the final
-   * result is [(A+B+C)+D, (A+B+C)+(D+E), (A+B+C)+(D+E+F)]. Again I
-   * am using parentheses to clarify how these results were reduced.
-   */
-  function phase2(workerId, sliceStart, sliceEnd) {
-    var sliceShift = slicesInfo.shift;
-    var sliceId;
-    while (GET_SLICE(sliceStart, sliceEnd, sliceId)) {
-      var indexPos = SLICE_START_INDEX(sliceShift, sliceId);
-      var indexEnd = SLICE_END_INDEX(sliceShift, indexPos, length);
-      var intermediate = intermediates[sliceId - 1];
-      for (; indexPos < indexEnd; indexPos++)
-        UnsafePutElements(buffer2, indexPos, func(intermediate, buffer[indexPos]));
-    }
-    return sliceId;
-  }
-}
-
-/**
- * |scatter()| redistributes the elements in the array into a new array.
- *
- * - targets: The index targets[i] indicates where the ith element
- *   should appear in the result.
- *
- * - defaultValue: what value to use for indices in the output array that
- *   are never targeted.
- *
- * - conflictFunc: The conflict function. Used to resolve what
- *   happens if two indices i and j in the source array are targeted
- *   as the same destination (i.e., targets[i] === targets[j]), then
- *   the final result is determined by applying func(targets[i],
- *   targets[j]). If no conflict function is provided, it is an error
- *   if targets[i] === targets[j].
- *
- * - length: length of the output array (if not specified, uses the
- *   length of the input).
- *
- * - mode: internal debugging specification.
- */
-function ArrayScatterPar(targets, defaultValue, conflictFunc, length, mode) {
-  if (conflictFunc && !IsCallable(conflictFunc))
-    ThrowError(JSMSG_NOT_FUNCTION, DecompileArg(2, conflictFunc));
-
-  var self = ToObject(this);
-
-  if (length === undefined)
-    length = self.length;
-
-  var targetsLength = std_Math_min(targets.length, self.length);
-
-  if (!IS_UINT32(targetsLength) || !IS_UINT32(length))
-    ThrowError(JSMSG_BAD_ARRAY_LENGTH);
-
-  // FIXME: Bug 965609: Find a better parallel startegy for scatter.
-
-  // Sequential fallback:
-  ASSERT_SEQUENTIAL_IS_OK(mode);
-  return seq();
-
-  function seq() {
-    var buffer = NewDenseArray(length);
-    var conflicts = NewDenseArray(length);
-
-    for (var i = 0; i < length; i++) {
-      UnsafePutElements(buffer, i, defaultValue);
-      UnsafePutElements(conflicts, i, false);
-    }
-
-    for (var i = 0; i < targetsLength; i++) {
-      var x = self[i];
-      var t = checkTarget(i, targets[i]);
-      if (conflicts[t])
-        x = collide(x, buffer[t]);
-
-      UnsafePutElements(buffer, t, x, conflicts, t, true);
-    }
-
-    return buffer;
-  }
-
-  function collide(elem1, elem2) {
-    if (conflictFunc === undefined)
-      ThrowError(JSMSG_PAR_ARRAY_SCATTER_CONFLICT);
-
-    return conflictFunc(elem1, elem2);
-  }
-
-  function checkTarget(i, t) {
-    if (TO_INT32(t) !== t)
-      ThrowError(JSMSG_PAR_ARRAY_SCATTER_BAD_TARGET, i);
-
-    if (t < 0 || t >= length)
-      ThrowError(JSMSG_PAR_ARRAY_SCATTER_BOUNDS);
-
-    // It's not enough to return t, as -0 | 0 === -0.
-    return TO_INT32(t);
-  }
-}
-
-/**
- * The filter operation applied in parallel.
- */
-function ArrayFilterPar(func, mode) {
-  if (!IsCallable(func))
-    ThrowError(JSMSG_NOT_FUNCTION, DecompileArg(0, func));
-
-  var self = ToObject(this);
-  var length = self.length;
-
-  parallel: for (;;) { // see ArrayMapPar() to explain why for(;;) etc
-    if (ShouldForceSequential())
-      break parallel;
-    if (!TRY_PARALLEL(mode))
-      break parallel;
-
-    var slicesInfo = ComputeSlicesInfo(length);
-
-    // Step 1. Compute which items from each slice of the result buffer should
-    // be preserved. When we're done, we have a uint8 array |survivors|
-    // containing 0 or 1 for each source element, indicating which members of
-    // the chunk survived. We also keep an array |counts| containing the total
-    // number of items that are being preserved from within one slice.
-    var numSlices = slicesInfo.count;
-    var counts = NewDenseArray(numSlices);
-    for (var i = 0; i < numSlices; i++)
-      UnsafePutElements(counts, i, 0);
-
-    var survivors = new Uint8Array(length);
-    ForkJoin(findSurvivorsThread, 0, numSlices, ForkJoinMode(mode), survivors);
-
-    // Step 2. Compress the slices into one contiguous set.
-    var count = 0;
-    for (var i = 0; i < numSlices; i++)
-      count += counts[i];
-    var buffer = NewDenseArray(count);
-    if (count > 0)
-      ForkJoin(copySurvivorsThread, 0, numSlices, ForkJoinMode(mode), buffer);
-
-    return buffer;
-  }
-
-  // Sequential fallback:
-  ASSERT_SEQUENTIAL_IS_OK(mode);
-  var buffer = [];
-  for (var i = 0; i < length; i++) {
-    var elem = self[i];
-    if (func(elem, i, self))
-      ARRAY_PUSH(buffer, elem);
-  }
-  return buffer;
-
-  /**
-   * As described above, our goal is to determine which items we will preserve
-   * from a given slice, storing "to-keep" bits into 32-bit chunks.
-   */
-  function findSurvivorsThread(workerId, sliceStart, sliceEnd) {
-    var sliceShift = slicesInfo.shift;
-    var sliceId;
-    while (GET_SLICE(sliceStart, sliceEnd, sliceId)) {
-      var count = 0;
-      var indexStart = SLICE_START_INDEX(sliceShift, sliceId);
-      var indexEnd = SLICE_END_INDEX(sliceShift, indexStart, length);
-      for (var indexPos = indexStart; indexPos < indexEnd; indexPos++) {
-        var keep = !!func(self[indexPos], indexPos, self);
-        UnsafePutElements(survivors, indexPos, keep);
-        count += keep;
-      }
-      UnsafePutElements(counts, sliceId, count);
-    }
-    return sliceId;
-  }
-
-  /**
-   * Copies the survivors from this slice into the correct position. Note
-   * that this is an idempotent operation that does not invoke user
-   * code. Therefore, we don't expect bailouts and make an effort to proceed
-   * chunk by chunk or avoid duplicating work.
-   */
-  function copySurvivorsThread(workerId, sliceStart, sliceEnd) {
-    var sliceShift = slicesInfo.shift;
-    var sliceId;
-    while (GET_SLICE(sliceStart, sliceEnd, sliceId)) {
-      // Total up the items preserved by previous slices.
-      var total = 0;
-      for (var i = 0; i < sliceId + 1; i++)
-        total += counts[i];
-
-      // Are we done?
-      var count = total - counts[sliceId];
-      if (count === total)
-        continue;
-
-      var indexStart = SLICE_START_INDEX(sliceShift, sliceId);
-      var indexEnd = SLICE_END_INDEX(sliceShift, indexStart, length);
-      for (var indexPos = indexStart; indexPos < indexEnd; indexPos++) {
-        if (survivors[indexPos]) {
-          UnsafePutElements(buffer, count++, self[indexPos]);
-          if (count == total)
-            break;
-        }
-      }
-    }
-
-    return sliceId;
-  }
-}
-
-/**
- * "Comprehension form": This is the function invoked for
- * |Array.{build,buildPar}(len, fn)| It creates a new array with length |len|
- * where index |i| is equal to |fn(i)|.
- *
- * The final |mode| argument is an internal argument used only during our
- * unit-testing.
- */
-function ArrayStaticBuild(length, func) {
-  if (!IS_UINT32(length))
-    ThrowError(JSMSG_BAD_ARRAY_LENGTH);
-  if (!IsCallable(func))
-    ThrowError(JSMSG_NOT_FUNCTION, DecompileArg(1, func));
-
-  var buffer = NewDenseArray(length);
-
-  for (var i = 0; i < length; i++)
-    UnsafePutElements(buffer, i, func(i));
-
-  return buffer;
-}
-
-function ArrayStaticBuildPar(length, func, mode) {
-  if (!IS_UINT32(length))
-    ThrowError(JSMSG_BAD_ARRAY_LENGTH);
-  if (!IsCallable(func))
-    ThrowError(JSMSG_NOT_FUNCTION, DecompileArg(1, func));
-
-  var buffer = NewDenseArray(length);
-
-  parallel: for (;;) {
-    if (ShouldForceSequential())
-      break parallel;
-    if (!TRY_PARALLEL(mode))
-      break parallel;
-
-    var slicesInfo = ComputeSlicesInfo(length);
-    ForkJoin(constructThread, 0, slicesInfo.count, ForkJoinMode(mode), buffer);
-    return buffer;
-  }
-
-  // Sequential fallback:
-  ASSERT_SEQUENTIAL_IS_OK(mode);
-  for (var i = 0; i < length; i++)
-    UnsafePutElements(buffer, i, func(i));
-  return buffer;
-
-  function constructThread(workerId, sliceStart, sliceEnd) {
-    var sliceShift = slicesInfo.shift;
-    var sliceId;
-    while (GET_SLICE(sliceStart, sliceEnd, sliceId)) {
-      var indexStart = SLICE_START_INDEX(sliceShift, sliceId);
-      var indexEnd = SLICE_END_INDEX(sliceShift, indexStart, length);
-      for (var i = indexStart; i < indexEnd; i++)
-        UnsafePutElements(buffer, i, func(i));
-    }
-    return sliceId;
-  }
-}
-
-/*
- * Mark the main operations as clone-at-callsite for better precision.
- * This is slightly overkill, as all that we really need is to
- * specialize to the receiver and the elemental function, but in
- * practice this is likely not so different, since element functions
- * are often used in exactly one place.
- */
-SetScriptHints(ArrayMapPar,         { cloneAtCallsite: true });
-SetScriptHints(ArrayReducePar,      { cloneAtCallsite: true });
-SetScriptHints(ArrayScanPar,        { cloneAtCallsite: true });
-SetScriptHints(ArrayScatterPar,     { cloneAtCallsite: true });
-SetScriptHints(ArrayFilterPar,      { cloneAtCallsite: true });
-SetScriptHints(ArrayStaticBuildPar, { cloneAtCallsite: true });
-
-#endif /* ENABLE_PARALLEL_JS */
deleted file mode 100644
--- a/js/src/builtin/ParallelUtilities.js
+++ /dev/null
@@ -1,72 +0,0 @@
-/* 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/. */
-
-// Shared utility functions for and macros parallel operations in `Array.js`
-// and `TypedObject.js`.
-
-#ifdef ENABLE_PARALLEL_JS
-
-/* The mode asserts options object. */
-#define TRY_PARALLEL(MODE) \
-  ((!MODE || MODE.mode !== "seq"))
-#define ASSERT_SEQUENTIAL_IS_OK(MODE) \
-  do { if (MODE) AssertSequentialIsOK(MODE) } while(false)
-
-/**
- * The ParallelSpew intrinsic is only defined in debug mode, so define a dummy
- * if debug is not on.
- */
-#ifndef DEBUG
-#define ParallelSpew(args)
-#endif
-
-#define MAX_SLICE_SHIFT 6
-#define MAX_SLICE_SIZE 64
-#define MAX_SLICES_PER_WORKER 8
-
-/**
- * Macros to help compute the start and end indices of slices based on id. Use
- * with the object returned by ComputeSliceInfo.
- */
-#define SLICE_START_INDEX(shift, id) \
-    (id << shift)
-#define SLICE_END_INDEX(shift, start, length) \
-    std_Math_min(start + (1 << shift), length)
-
-/**
- * ForkJoinGetSlice acts as identity when we are not in a parallel section, so
- * pass in the next sequential value when we are in sequential mode. The
- * reason for this odd API is because intrinsics *need* to be called during
- * ForkJoin's warmup to fill the TI info.
- */
-#define GET_SLICE(sliceStart, sliceEnd, id) \
-    ((id = ForkJoinGetSlice((InParallelSection() ? -1 : sliceStart++) | 0)) < sliceEnd)
-
-/**
- * Determine the number and size of slices. The info object has the following
- * properties:
- *
- *  - shift: amount to shift by to compute indices
- *  - count: number of slices
- */
-function ComputeSlicesInfo(length) {
-  var count = length >>> MAX_SLICE_SHIFT;
-  var numWorkers = ForkJoinNumWorkers();
-  if (count < numWorkers)
-    count = numWorkers;
-  else if (count >= numWorkers * MAX_SLICES_PER_WORKER)
-    count = numWorkers * MAX_SLICES_PER_WORKER;
-
-  // Round the slice size to be a power of 2.
-  var shift = std_Math_max(std_Math_log2(length / count) | 0, 1);
-
-  // Recompute count with the rounded size.
-  count = length >>> shift;
-  if (count << shift !== length)
-    count += 1;
-
-  return { shift: shift, count: count };
-}
-
-#endif // ENABLE_PARALLEL_JS
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -164,24 +164,16 @@ GetBuildConfiguration(JSContext *cx, uns
 #ifdef JS_OOM_DO_BACKTRACES
     value = BooleanValue(true);
 #else
     value = BooleanValue(false);
 #endif
     if (!JS_SetProperty(cx, info, "oom-backtraces", value))
         return false;
 
-#ifdef ENABLE_PARALLEL_JS
-    value = BooleanValue(true);
-#else
-    value = BooleanValue(false);
-#endif
-    if (!JS_SetProperty(cx, info, "parallelJS", value))
-        return false;
-
 #ifdef ENABLE_BINARYDATA
     value = BooleanValue(true);
 #else
     value = BooleanValue(false);
 #endif
     if (!JS_SetProperty(cx, info, "binary-data", value))
         return false;
 
--- a/js/src/builtin/TypedObject.cpp
+++ b/js/src/builtin/TypedObject.cpp
@@ -500,37 +500,30 @@ const JSPropertySpec ArrayMetaTypeDescr:
     JS_PS_END
 };
 
 const JSFunctionSpec ArrayMetaTypeDescr::typeObjectMethods[] = {
     {"array", {nullptr, nullptr}, 1, 0, "ArrayShorthand"},
     JS_SELF_HOSTED_FN("toSource", "DescrToSource", 0, 0),
     {"equivalent", {nullptr, nullptr}, 1, 0, "TypeDescrEquivalent"},
     JS_SELF_HOSTED_FN("build",    "TypedObjectArrayTypeBuild", 3, 0),
-    JS_SELF_HOSTED_FN("buildPar", "TypedObjectArrayTypeBuildPar", 3, 0),
     JS_SELF_HOSTED_FN("from",     "TypedObjectArrayTypeFrom", 3, 0),
-    JS_SELF_HOSTED_FN("fromPar",  "TypedObjectArrayTypeFromPar", 3, 0),
     JS_FS_END
 };
 
 const JSPropertySpec ArrayMetaTypeDescr::typedObjectProperties[] = {
     JS_PS_END
 };
 
 const JSFunctionSpec ArrayMetaTypeDescr::typedObjectMethods[] = {
     {"forEach", {nullptr, nullptr}, 1, 0, "ArrayForEach"},
     {"redimension", {nullptr, nullptr}, 1, 0, "TypedObjectArrayRedimension"},
     JS_SELF_HOSTED_FN("map",        "TypedObjectArrayMap",        2, 0),
-    JS_SELF_HOSTED_FN("mapPar",     "TypedObjectArrayMapPar",     2, 0),
     JS_SELF_HOSTED_FN("reduce",     "TypedObjectArrayReduce",     2, 0),
-    JS_SELF_HOSTED_FN("reducePar",  "TypedObjectArrayReducePar",  2, 0),
-    JS_SELF_HOSTED_FN("scatter",    "TypedObjectArrayScatter",    4, 0),
-    JS_SELF_HOSTED_FN("scatterPar", "TypedObjectArrayScatterPar", 4, 0),
     JS_SELF_HOSTED_FN("filter",     "TypedObjectArrayFilter",     1, 0),
-    JS_SELF_HOSTED_FN("filterPar",  "TypedObjectArrayFilterPar",  1, 0),
     JS_FS_END
 };
 
 bool
 js::CreateUserSizeAndAlignmentProperties(JSContext *cx, HandleTypeDescr descr)
 {
     // If data is transparent, also store the public slots.
     if (descr->transparent()) {
--- a/js/src/builtin/TypedObject.js
+++ b/js/src/builtin/TypedObject.js
@@ -642,124 +642,46 @@ function TypedObjectArrayMap(a, b) {
   if (typeof a === "number" && typeof b === "function")
     return MapTypedSeqImpl(this, a, thisType, b);
   else if (typeof a === "function")
     return MapTypedSeqImpl(this, 1, thisType, a);
   ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
 }
 
 // Warning: user exposed!
-function TypedObjectArrayMapPar(a, b) {
-  // Arguments: [depth], func
-
-  // Defer to the sequential variant for error cases or
-  // when not working with typed objects.
-  if (!IsObject(this) || !ObjectIsTypedObject(this))
-    return callFunction(TypedObjectArrayMap, this, a, b);
-  var thisType = TypedObjectTypeDescr(this);
-  if (!TypeDescrIsArrayType(thisType))
-    return callFunction(TypedObjectArrayMap, this, a, b);
-
-  if (typeof a === "number" && IsCallable(b))
-    return MapTypedParImpl(this, a, thisType, b);
-  else if (IsCallable(a))
-    return MapTypedParImpl(this, 1, thisType, a);
-  return callFunction(TypedObjectArrayMap, this, a, b);
-}
-
-// Warning: user exposed!
 function TypedObjectArrayReduce(a, b) {
   // Arguments: func, [initial]
   if (!IsObject(this) || !ObjectIsTypedObject(this))
     ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
   var thisType = TypedObjectTypeDescr(this);
   if (!TypeDescrIsArrayType(thisType))
     ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
 
   if (a !== undefined && typeof a !== "function")
     ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
 
   var outputType = thisType.elementType;
   return ReduceTypedSeqImpl(this, outputType, a, b);
 }
 
 // Warning: user exposed!
-function TypedObjectArrayScatter(a, b, c, d) {
-  // Arguments: outputArrayType, indices, defaultValue, conflictFunction
-  if (!IsObject(this) || !ObjectIsTypedObject(this))
-    ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
-  var thisType = TypedObjectTypeDescr(this);
-  if (!TypeDescrIsArrayType(thisType))
-    ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
-
-  if (!IsObject(a) || !ObjectIsTypeDescr(a) || !TypeDescrIsArrayType(a))
-    ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
-
-  if (d !== undefined && typeof d !== "function")
-    ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
-
-  return ScatterTypedSeqImpl(this, a, b, c, d);
-}
-
-// Warning: user exposed!
 function TypedObjectArrayFilter(func) {
   // Arguments: predicate
   if (!IsObject(this) || !ObjectIsTypedObject(this))
     ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
   var thisType = TypedObjectTypeDescr(this);
   if (!TypeDescrIsArrayType(thisType))
     ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
 
   if (typeof func !== "function")
     ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
 
   return FilterTypedSeqImpl(this, func);
 }
 
-// placeholders
-
-// Warning: user exposed!
-function TypedObjectArrayTypeBuildPar(a,b,c) {
-  return callFunction(TypedObjectArrayTypeBuild, this, a, b, c);
-}
-
-// Warning: user exposed!
-function TypedObjectArrayTypeFromPar(a,b,c) {
-  // Arguments: arrayLike, [depth], func
-
-  // Use the sequential version for error cases or when arrayLike is
-  // not a typed object.
-  if (!IsObject(this) || !ObjectIsTypeDescr(this) || !TypeDescrIsArrayType(this))
-    return callFunction(TypedObjectArrayTypeFrom, this, a, b, c);
-  if (!IsObject(a) || !ObjectIsTypedObject(a))
-    return callFunction(TypedObjectArrayTypeFrom, this, a, b, c);
-
-  // Detect whether an explicit depth is supplied.
-  if (typeof b === "number" && IsCallable(c))
-    return MapTypedParImpl(a, b, this, c);
-  if (IsCallable(b))
-    return MapTypedParImpl(a, 1, this, b);
-  return callFunction(TypedObjectArrayTypeFrom, this, a, b, c);
-}
-
-// Warning: user exposed!
-function TypedObjectArrayReducePar(a, b) {
-  return callFunction(TypedObjectArrayReduce, this, a, b);
-}
-
-// Warning: user exposed!
-function TypedObjectArrayScatterPar(a, b, c, d) {
-  return callFunction(TypedObjectArrayScatter, this, a, b, c, d);
-}
-
-// Warning: user exposed!
-function TypedObjectArrayFilterPar(func) {
-  return callFunction(TypedObjectArrayFilter, this, func);
-}
-
 // should eventually become macros
 function NUM_BYTES(bits) {
   return (bits + 7) >> 3;
 }
 function SET_BIT(data, index) {
   var word = index >> 3;
   var mask = 1 << (index & 0x7);
   data[word] |= mask;
@@ -1020,218 +942,16 @@ function MapTypedSeqImpl(inArray, depth,
     return DoMapTypedSeqDepth1Simple(inArray, totalLength, func, result);
 
   if (depth == 1)
     return DoMapTypedSeqDepth1();
 
   return DoMapTypedSeqDepthN();
 }
 
-// Implements |map| and |from| methods for typed |inArray|.
-function MapTypedParImpl(inArray, depth, outputType, func) {
-  assert(IsObject(outputType) && ObjectIsTypeDescr(outputType),
-         "Map/From called on non-type-object outputType");
-  assert(IsObject(inArray) && ObjectIsTypedObject(inArray),
-         "Map/From called on non-object or untyped input array.");
-  assert(TypeDescrIsArrayType(outputType),
-         "Map/From called on non array-type outputType");
-  assert(typeof depth === "number",
-         "Map/From called with non-numeric depth");
-  assert(IsCallable(func),
-         "Map/From called on something not callable");
-
-  var inArrayType = TypeOfTypedObject(inArray);
-
-  if (ShouldForceSequential() ||
-      depth <= 0 ||
-      TO_INT32(depth) !== depth ||
-      !TypeDescrIsArrayType(inArrayType) ||
-      !TypeDescrIsArrayType(outputType))
-  {
-    // defer error cases to seq implementation:
-    return MapTypedSeqImpl(inArray, depth, outputType, func);
-  }
-
-  switch (depth) {
-  case 1:
-    return MapTypedParImplDepth1(inArray, inArrayType, outputType, func);
-  default:
-    return MapTypedSeqImpl(inArray, depth, outputType, func);
-  }
-}
-
-function RedirectPointer(typedObj, offset, outputIsScalar) {
-  if (!outputIsScalar || !InParallelSection()) {
-    // ^ Subtle note: always check InParallelSection() last, because
-    // otherwise the other if conditions will not execute during
-    // sequential mode and we will not gather enough type
-    // information.
-
-    // Here `typedObj` represents the input or output pointer we will
-    // pass to the user function. Ideally, we will just update the
-    // offset of `typedObj` in place so that it moves along the
-    // input/output buffer without incurring any allocation costs. But
-    // we can only do this if these changes are invisible to the user.
-    //
-    // Under normal uses, such changes *should* be invisible -- the
-    // in/out pointers are only intended to be used during the
-    // callback and then discarded, but of course in the general case
-    // nothing prevents them from escaping.
-    //
-    // However, if we are in parallel mode, we know that the pointers
-    // will not escape into global state. They could still escape by
-    // being returned into the resulting array, but even that avenue
-    // is impossible if the result array cannot contain objects.
-    //
-    // Therefore, we reuse a pointer if we are both in parallel mode
-    // and we have a transparent output type.  It'd be nice to loosen
-    // this condition later by using fancy ion optimizations that
-    // assume the value won't escape and copy it if it does. But those
-    // don't exist yet. Moreover, checking if the type is transparent
-    // is an overapproximation: users can manually declare opaque
-    // types that nonetheless only contain scalar data.
-
-    typedObj = NewDerivedTypedObject(TypedObjectTypeDescr(typedObj),
-                                     typedObj, 0);
-  }
-
-  SetTypedObjectOffset(typedObj, offset);
-  return typedObj;
-}
-SetScriptHints(RedirectPointer,         { inline: true });
-
-function MapTypedParImplDepth1(inArray, inArrayType, outArrayType, func) {
-  assert(IsObject(inArrayType) && ObjectIsTypeDescr(inArrayType) &&
-         TypeDescrIsArrayType(inArrayType),
-         "DoMapTypedParDepth1: invalid inArrayType");
-  assert(IsObject(outArrayType) && ObjectIsTypeDescr(outArrayType) &&
-         TypeDescrIsArrayType(outArrayType),
-         "DoMapTypedParDepth1: invalid outArrayType");
-  assert(IsObject(inArray) && ObjectIsTypedObject(inArray),
-         "DoMapTypedParDepth1: invalid inArray");
-
-  if (!TypedObjectIsAttached(inArray))
-    ThrowError(JSMSG_TYPEDOBJECT_HANDLE_UNATTACHED);
-
-  // Determine the grain types of the input and output.
-  const inGrainType = inArrayType.elementType;
-  const outGrainType = outArrayType.elementType;
-  const inGrainTypeSize = DESCR_SIZE(inGrainType);
-  const outGrainTypeSize = DESCR_SIZE(outGrainType);
-  const inGrainTypeIsComplex = !TypeDescrIsSimpleType(inGrainType);
-  const outGrainTypeIsComplex = !TypeDescrIsSimpleType(outGrainType);
-
-  const length = inArray.length;
-  const mode = undefined;
-
-  const outArray = new outArrayType();
-  if (length === 0)
-    return outArray;
-
-  if (outArray.length != length)
-    ThrowError(JSMSG_TYPEDOBJECT_ARRAYTYPE_BAD_ARGS);
-
-  const outGrainTypeIsTransparent = ObjectIsTransparentTypedObject(outArray);
-
-  // Construct the slices and initial pointers for each worker:
-  const slicesInfo = ComputeSlicesInfo(length);
-  const numWorkers = ForkJoinNumWorkers();
-  assert(numWorkers > 0, "Should have at least the main thread");
-  const pointers = [];
-  for (var i = 0; i < numWorkers; i++) {
-    const inTypedObject = TypedObjectGetDerivedIf(inGrainType, inArray, 0,
-                                                  inGrainTypeIsComplex);
-    const outTypedObject = TypedObjectGetOpaqueIf(outGrainType, outArray, 0,
-                                                  outGrainTypeIsComplex);
-    ARRAY_PUSH(pointers, ({ inTypedObject: inTypedObject,
-                            outTypedObject: outTypedObject }));
-  }
-
-  // Below we will be adjusting offsets within the input to point at
-  // successive entries; we'll need to know the offset of inArray
-  // relative to its owner (which is often but not always 0).
-  const inBaseOffset = TypedObjectByteOffset(inArray);
-
-  ForkJoin(mapThread, 0, slicesInfo.count, ForkJoinMode(mode), outArray);
-  return outArray;
-
-  function mapThread(workerId, sliceStart, sliceEnd) {
-    assert(TO_INT32(workerId) === workerId,
-           "workerId not int: " + workerId);
-    assert(workerId < pointers.length,
-           "workerId too large: " + workerId + " >= " + pointers.length);
-
-    var pointerIndex = InParallelSection() ? workerId : 0;
-    assert(!!pointers[pointerIndex],
-          "no pointer data for workerId: " + workerId);
-
-    const { inTypedObject, outTypedObject } = pointers[pointerIndex];
-    const sliceShift = slicesInfo.shift;
-    var sliceId;
-
-    while (GET_SLICE(sliceStart, sliceEnd, sliceId)) {
-      const indexStart = SLICE_START_INDEX(sliceShift, sliceId);
-      const indexEnd = SLICE_END_INDEX(sliceShift, indexStart, length);
-
-      var inOffset = inBaseOffset + std_Math_imul(inGrainTypeSize, indexStart);
-      var outOffset = std_Math_imul(outGrainTypeSize, indexStart);
-
-      // Set the target region so that user is only permitted to write
-      // within the range set aside for this slice. This prevents user
-      // from writing to typed objects that escaped from prior slices
-      // during sequential iteration. Note that, for any particular
-      // iteration of the loop below, it's only valid to write to the
-      // memory range corresponding to the index `i` -- however, since
-      // the different iterations cannot communicate typed object
-      // pointers to one another during parallel exec, we need only
-      // fear escaped typed objects from *other* slices, so we can
-      // just set the target region once.
-      const endOffset = std_Math_imul(outGrainTypeSize, indexEnd);
-      SetForkJoinTargetRegion(outArray, outOffset, endOffset);
-
-      for (var i = indexStart; i < indexEnd; i++) {
-        var inVal = (inGrainTypeIsComplex
-                     ? RedirectPointer(inTypedObject, inOffset,
-                                       outGrainTypeIsTransparent)
-                     : inArray[i]);
-        var outVal = (outGrainTypeIsComplex
-                      ? RedirectPointer(outTypedObject, outOffset,
-                                        outGrainTypeIsTransparent)
-                      : undefined);
-        const r = func(inVal, i, inArray, outVal);
-        if (r !== undefined) {
-          if (outGrainTypeIsComplex)
-            SetTypedObjectValue(outGrainType, outArray, outOffset, r);
-          else
-            UnsafePutElements(outArray, i, r);
-        }
-        inOffset += inGrainTypeSize;
-        outOffset += outGrainTypeSize;
-
-#ifndef JSGC_FJGENERATIONAL
-        // A transparent result type cannot contain references, and
-        // hence there is no way for a pointer to a thread-local object
-        // to escape.
-        //
-        // This has been disabled for the PJS generational collector
-        // as it probably has little effect in that setting and adds
-        // per-iteration cost.
-        if (outGrainTypeIsTransparent)
-          ClearThreadLocalArenas();
-#endif
-      }
-    }
-
-    return sliceId;
-  }
-
-  return undefined;
-}
-SetScriptHints(MapTypedParImplDepth1,         { cloneAtCallsite: true });
-
 function ReduceTypedSeqImpl(array, outputType, func, initial) {
   assert(IsObject(array) && ObjectIsTypedObject(array), "Reduce called on non-object or untyped input array.");
   assert(IsObject(outputType) && ObjectIsTypeDescr(outputType), "Reduce called on non-type-object outputType");
 
   var start, value;
 
   if (initial === undefined && array.length < 1)
     // RangeError("reduce requires array of length > 0")
@@ -1263,46 +983,16 @@ function ReduceTypedSeqImpl(array, outpu
 
     for (var i = start; i < array.length; i++)
       value = func(value, array[i]);
   }
 
   return value;
 }
 
-function ScatterTypedSeqImpl(array, outputType, indices, defaultValue, conflictFunc) {
-  assert(IsObject(array) && ObjectIsTypedObject(array), "Scatter called on non-object or untyped input array.");
-  assert(IsObject(outputType) && ObjectIsTypeDescr(outputType), "Scatter called on non-type-object outputType");
-  assert(TypeDescrIsArrayType(outputType), "Scatter called on non-array type");
-  assert(conflictFunc === undefined || typeof conflictFunc === "function", "Scatter called with invalid conflictFunc");
-
-  var result = new outputType();
-  var bitvec = new Uint8Array(result.length);
-  var elemType = outputType.elementType;
-  var i, j;
-  if (defaultValue !== elemType(undefined)) {
-    for (i = 0; i < result.length; i++) {
-      result[i] = defaultValue;
-    }
-  }
-
-  for (i = 0; i < indices.length; i++) {
-    j = indices[i];
-    if (!GET_BIT(bitvec, j)) {
-      result[j] = array[i];
-      SET_BIT(bitvec, j);
-    } else if (conflictFunc === undefined) {
-      ThrowError(JSMSG_PAR_ARRAY_SCATTER_CONFLICT);
-    } else {
-      result[j] = conflictFunc(result[j], elemType(array[i]));
-    }
-  }
-  return result;
-}
-
 function FilterTypedSeqImpl(array, func) {
   assert(IsObject(array) && ObjectIsTypedObject(array), "Filter called on non-object or untyped input array.");
   assert(typeof func === "function", "Filter called with non-function predicate");
 
   var arrayType = TypeOfTypedObject(array);
   if (!TypeDescrIsArrayType(arrayType))
     ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
 
--- a/js/src/builtin/Utilities.js
+++ b/js/src/builtin/Utilities.js
@@ -102,39 +102,8 @@ function ToLength(v) {
     // Math.pow(2, 53) - 1 = 0x1fffffffffffff
     return std_Math_min(v, 0x1fffffffffffff);
 }
 
 // Spec: ECMAScript Draft, 6th edition Oct 14, 2014, 7.2.4.
 function SameValueZero(x, y) {
     return x === y || (x !== x && y !== y);
 }
-
-/********** Testing code **********/
-
-#ifdef ENABLE_PARALLEL_JS
-
-/**
- * Internal debugging tool: checks that the given `mode` permits
- * sequential execution
- */
-function AssertSequentialIsOK(mode) {
-  if (mode && mode.mode && mode.mode !== "seq" && ParallelTestsShouldPass())
-    ThrowError(JSMSG_WRONG_VALUE, "parallel execution", "sequential was forced");
-}
-
-function ForkJoinMode(mode) {
-  // WARNING: this must match the enum ForkJoinMode in ForkJoin.cpp
-  if (!mode || !mode.mode) {
-    return 0;
-  } else if (mode.mode === "compile") {
-    return 1;
-  } else if (mode.mode === "par") {
-    return 2;
-  } else if (mode.mode === "recover") {
-    return 3;
-  } else if (mode.mode === "bailout") {
-    return 4;
-  }
-  ThrowError(JSMSG_PAR_ARRAY_BAD_ARG);
-}
-
-#endif
deleted file mode 100644
--- a/js/src/jit-test/tests/ion/inlining/TypedObject-TypeDescrIsSizedArrayType.js
+++ /dev/null
@@ -1,42 +0,0 @@
-/* -*- tab-width: 8; indent-tabs-mode: nil; js-indent-level: 2 -*-
- * 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/. */
-
-/* Testing TypeDescrIsSizedArrayType() is fairly straightforward:
- * it's used early in the sequential scatter() method on TypedObject
- * arrays, and is applied to the first argument (not to "this").
- *
- * Run this with IONFLAGS=logs, generate pdfs with iongraph, and then
- * try running "pdfgrep TypeDescrIsSizedArrayType func*pass00*.pdf", this
- * might net a function that is a likely candidate for manual inspection.
- *
- * (It is sometimes useful to neuter the assert() macro in the
- * self-hosted code.)
- */
-
-if (!this.TypedObject) {
-    print("No TypedObject, skipping");
-    quit();
-}
-
-var T = TypedObject;
-var IT = new T.ArrayType(T.int32, 100);
-var ix = IT.build(x => x == 0 ? 99 : x-1);  // [99, 0, 1, ..., 98]
-
-// This is a left-rotate by one place
-function check(v) {
-    return v.scatter(IT, ix);
-}
-
-function test() {
-    var w = IT.build(x => x);
-    for ( var i=0 ; i < 77 ; i++ )
-	w = check(w);
-    return w;
-}
-
-w = test();
-assertEq(w.length, 100);
-assertEq(w[0], 77);
-print("Done");
--- a/js/src/js.msg
+++ b/js/src/js.msg
@@ -439,22 +439,16 @@ MSG_DEF(JSMSG_SHARED_ARRAY_BAD_OBJECT,  
 MSG_DEF(JSMSG_SHARED_ARRAY_BAD_LENGTH,  0, JSEXN_RANGEERR, "length argument out of range")
 
 // Shared typed array
 MSG_DEF(JSMSG_SHARED_TYPED_ARRAY_BAD_OBJECT,  0, JSEXN_TYPEERR, "invalid object argument")
 MSG_DEF(JSMSG_SHARED_TYPED_ARRAY_BAD_ARGS,    0, JSEXN_RANGEERR, "bad combination of offset, length, and element size")
 MSG_DEF(JSMSG_SHARED_TYPED_ARRAY_ARG_RANGE,   1, JSEXN_RANGEERR, "argument {0} out of range")
 MSG_DEF(JSMSG_SHARED_TYPED_ARRAY_BAD_LENGTH,  0, JSEXN_TYPEERR, "length argument must not be an object")
 
-// Parallel array
-MSG_DEF(JSMSG_PAR_ARRAY_BAD_ARG,       0, JSEXN_RANGEERR, "invalid parallel method argument")
-MSG_DEF(JSMSG_PAR_ARRAY_SCATTER_BAD_TARGET, 1, JSEXN_ERR, "target for index {0} is not an integer")
-MSG_DEF(JSMSG_PAR_ARRAY_SCATTER_BOUNDS,0, JSEXN_ERR, "index in scatter vector out of bounds")
-MSG_DEF(JSMSG_PAR_ARRAY_SCATTER_CONFLICT, 0, JSEXN_ERR, "no conflict resolution function provided")
-
 // Reflect
 MSG_DEF(JSMSG_BAD_PARSE_NODE,          0, JSEXN_INTERNALERR, "bad parse node")
 
 // Symbol
 MSG_DEF(JSMSG_BAD_SYMBOL,              1, JSEXN_TYPEERR, "{0} is not a well-known @@-symbol")
 MSG_DEF(JSMSG_SYMBOL_TO_STRING,        0, JSEXN_TYPEERR, "can't convert symbol to string")
 MSG_DEF(JSMSG_SYMBOL_TO_NUMBER,        0, JSEXN_TYPEERR, "can't convert symbol to number")
 
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -3204,25 +3204,16 @@ static const JSFunctionSpec array_method
     JS_SELF_HOSTED_FN("forEach",     "ArrayForEach",     1,0),
     JS_SELF_HOSTED_FN("map",         "ArrayMap",         1,0),
     JS_SELF_HOSTED_FN("reduce",      "ArrayReduce",      1,0),
     JS_SELF_HOSTED_FN("reduceRight", "ArrayReduceRight", 1,0),
     JS_FN("filter",             array_filter,       1,JSFUN_GENERIC_NATIVE),
     JS_SELF_HOSTED_FN("some",        "ArraySome",        1,0),
     JS_SELF_HOSTED_FN("every",       "ArrayEvery",       1,0),
 
-#ifdef ENABLE_PARALLEL_JS
-    /* Parallelizable and pure methods. */
-    JS_SELF_HOSTED_FN("mapPar",      "ArrayMapPar",      2,0),
-    JS_SELF_HOSTED_FN("reducePar",   "ArrayReducePar",   2,0),
-    JS_SELF_HOSTED_FN("scanPar",     "ArrayScanPar",     2,0),
-    JS_SELF_HOSTED_FN("scatterPar",  "ArrayScatterPar",  5,0),
-    JS_SELF_HOSTED_FN("filterPar",   "ArrayFilterPar",   2,0),
-#endif
-
     /* ES6 additions */
     JS_SELF_HOSTED_FN("find",        "ArrayFind",        1,0),
     JS_SELF_HOSTED_FN("findIndex",   "ArrayFindIndex",   1,0),
     JS_SELF_HOSTED_FN("copyWithin",  "ArrayCopyWithin",  3,0),
 
     JS_SELF_HOSTED_FN("fill",        "ArrayFill",        3,0),
 
     JS_SELF_HOSTED_SYM_FN(iterator,  "ArrayValues",      0,0),
@@ -3245,22 +3236,16 @@ static const JSFunctionSpec array_static
     JS_SELF_HOSTED_FN("map",         "ArrayStaticMap",   2,0),
     JS_SELF_HOSTED_FN("every",       "ArrayStaticEvery", 2,0),
     JS_SELF_HOSTED_FN("some",        "ArrayStaticSome",  2,0),
     JS_SELF_HOSTED_FN("reduce",      "ArrayStaticReduce", 2,0),
     JS_SELF_HOSTED_FN("reduceRight", "ArrayStaticReduceRight", 2,0),
     JS_SELF_HOSTED_FN("from",        "ArrayFrom", 3,0),
     JS_FN("of",                 array_of,           0,0),
 
-#ifdef ENABLE_PARALLEL_JS
-    JS_SELF_HOSTED_FN("build",       "ArrayStaticBuild", 2,0),
-    /* Parallelizable and pure static methods. */
-    JS_SELF_HOSTED_FN("buildPar",    "ArrayStaticBuildPar", 3,0),
-#endif
-
     JS_FS_END
 };
 
 /* ES5 15.4.2 */
 bool
 js_Array(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
deleted file mode 100644
--- a/js/src/tests/ecma_7/TypedObject/method_scatter.js
+++ /dev/null
@@ -1,95 +0,0 @@
-// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
-var BUGNUMBER = 939715;
-var summary = 'method instance.scatter';
-
-/*
- * Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/licenses/publicdomain/
- */
-
-var ArrayType = TypedObject.ArrayType;
-var StructType = TypedObject.StructType;
-var uint8 = TypedObject.uint8;
-var uint16 = TypedObject.uint16;
-var uint32 = TypedObject.uint32;
-var uint8Clamped = TypedObject.uint8Clamped;
-var int8 = TypedObject.int8;
-var int16 = TypedObject.int16;
-var int32 = TypedObject.int32;
-var float32 = TypedObject.float32;
-var float64 = TypedObject.float64;
-
-function scatterUint8sPermute() {
-  var uint8Array = uint8.array(5);
-  var array = new uint8Array([124, 120, 122, 123, 121]);
-
-  var perm = array.scatter(uint8Array, [4, 0, 2, 3, 1]);
-  assertTypedEqual(uint8Array, perm, [120, 121, 122, 123, 124]);
-}
-
-function scatterUint8sPermuteIncomplete() {
-  var uint8Array4 = uint8.array(4);
-  var uint8Array5 = uint8.array(5);
-  var array = new uint8Array4([124, 120, 122, 123]);
-
-  var perm;
-  perm = array.scatter(uint8Array5, [4, 0, 2, 3]);
-  assertTypedEqual(uint8Array5, perm, [120,  0, 122, 123, 124]);
-
-  perm = array.scatter(uint8Array5, [4, 0, 2, 3], 77);
-  assertTypedEqual(uint8Array5, perm, [120, 77, 122, 123, 124]);
-}
-
-function scatterUint8sHistogram() {
-  var uint32Array5 = uint32.array(5);
-  var uint32Array3 = uint32.array(3);
-  var array = new uint32Array5([1, 10, 100, 1000, 10000]);
-
-  var hist = array.scatter(uint32Array3, [1, 1, 2, 1, 0], 0, (a,b) => a+b);
-  assertTypedEqual(uint32Array3, hist, [10000, 1011, 100]);
-}
-
-function scatterUint8sCollisionThrows() {
-  var uint32Array5 = uint32.array(5);
-  var uint32Array3 = uint32.array(3);
-  var array = new uint32Array5([1, 10, 100, 1000, 10000]);
-
-  var unset_nonce = new Object();
-  var unset = unset_nonce;
-  try {
-    unset = array.scatter(uint32Array3, [1, 1, 2, 1, 0], 0);
-  } catch (e) {
-    assertEq(unset, unset_nonce);
-  }
-}
-
-function scatterUint8sConflictIsAssocNonCommute() {
-  var uint32Array5 = uint32.array(5);
-  var uint32Array3 = uint32.array(3);
-  var array = new uint32Array5([1, 10, 100, 1000, 10000]);
-
-  // FIXME strawman spec says conflict must be associative, but does
-  // not dictate commutative.  Yet, strawman spec does not appear to
-  // specify operation order; must address incongruence.
-
-  var lfts = array.scatter(uint32Array3, [1, 1, 2, 1, 0], 0, (a,b) => a);
-  assertTypedEqual(uint32Array3, lfts, [10000, 1, 100]);
-  var rgts = array.scatter(uint32Array3, [1, 1, 2, 1, 0], 0, (a,b) => b);
-  assertTypedEqual(uint32Array3, rgts, [10000, 1000, 100]);
-}
-
-function runTests() {
-    print(BUGNUMBER + ": " + summary);
-
-    scatterUint8sPermute();
-    scatterUint8sPermuteIncomplete();
-    scatterUint8sHistogram();
-    scatterUint8sCollisionThrows();
-    scatterUint8sConflictIsAssocNonCommute();
-
-    if (typeof reportCompare === "function")
-        reportCompare(true, true);
-    print("Tests complete");
-}
-
-runTests();
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -299,132 +299,16 @@ intrinsic_SetScriptHints(JSContext *cx, 
         return false;
     if (ToBoolean(propv))
         funScript->setShouldInline();
 
     args.rval().setUndefined();
     return true;
 }
 
-#ifdef DEBUG
-/*
- * Dump(val): Dumps a value for debugging, even in parallel mode.
- */
-bool
-intrinsic_Dump(ThreadSafeContext *cx, unsigned argc, Value *vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    js_DumpValue(args[0]);
-    if (args[0].isObject()) {
-        fprintf(stderr, "\n");
-        js_DumpObject(&args[0].toObject());
-    }
-    args.rval().setUndefined();
-    return true;
-}
-
-JS_JITINFO_NATIVE_PARALLEL_THREADSAFE(intrinsic_Dump_jitInfo, intrinsic_Dump_jitInfo,
-                                      intrinsic_Dump);
-
-bool
-intrinsic_ParallelSpew(ThreadSafeContext *cx, unsigned argc, Value *vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    MOZ_ASSERT(args.length() == 1);
-    MOZ_ASSERT(args[0].isString());
-
-    AutoCheckCannotGC nogc;
-    ScopedThreadSafeStringInspector inspector(args[0].toString());
-    if (!inspector.ensureChars(cx, nogc))
-        return false;
-
-    ScopedJSFreePtr<char> bytes;
-    if (inspector.hasLatin1Chars())
-        bytes = JS::CharsToNewUTF8CharsZ(cx, inspector.latin1Range()).c_str();
-    else
-        bytes = JS::CharsToNewUTF8CharsZ(cx, inspector.twoByteRange()).c_str();
-
-    parallel::Spew(parallel::SpewOps, bytes);
-
-    args.rval().setUndefined();
-    return true;
-}
-
-JS_JITINFO_NATIVE_PARALLEL_THREADSAFE(intrinsic_ParallelSpew_jitInfo, intrinsic_ParallelSpew_jitInfo,
-                                      intrinsic_ParallelSpew);
-#endif
-
-/*
- * ForkJoin(func, sliceStart, sliceEnd, mode, updatable): Invokes |func| many times in parallel.
- *
- * If "func" will update a pre-existing object then that object /must/ be passed
- * as the object "updatable".  It is /not/ correct to pass an object that
- * references the updatable objects indirectly.
- *
- * See ForkJoin.cpp for details and ParallelArray.js for examples.
- */
-static bool
-intrinsic_ForkJoin(JSContext *cx, unsigned argc, Value *vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    return ForkJoin(cx, args);
-}
-
-/*
- * ForkJoinWorkerNumWorkers(): Returns the number of workers in the fork join
- * thread pool, including the main thread.
- */
-static bool
-intrinsic_ForkJoinNumWorkers(JSContext *cx, unsigned argc, Value *vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    args.rval().setInt32(cx->runtime()->threadPool.numWorkers());
-    return true;
-}
-
-/*
- * ForkJoinGetSlice(id): Returns the id of the next slice to be worked
- * on.
- *
- * Acts as the identity function when called from outside of a ForkJoin
- * thread. This odd API is because intrinsics must be called during the
- * parallel warm up phase to populate observed type sets, so we must call it
- * even during sequential execution. But since there is no thread pool during
- * sequential execution, the selfhosted code is responsible for computing the
- * next sequential slice id and passing it in itself.
- */
-bool
-js::intrinsic_ForkJoinGetSlice(JSContext *cx, unsigned argc, Value *vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    MOZ_ASSERT(args.length() == 1);
-    MOZ_ASSERT(args[0].isInt32());
-    args.rval().set(args[0]);
-    return true;
-}
-
-static bool
-intrinsic_ForkJoinGetSlicePar(ForkJoinContext *cx, unsigned argc, Value *vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    MOZ_ASSERT(args.length() == 1);
-    MOZ_ASSERT(args[0].isInt32());
-
-    uint16_t sliceId;
-    if (cx->getSlice(&sliceId))
-        args.rval().setInt32(sliceId);
-    else
-        args.rval().setInt32(ThreadPool::MAX_SLICE_ID);
-
-    return true;
-}
-
-JS_JITINFO_NATIVE_PARALLEL(intrinsic_ForkJoinGetSlice_jitInfo,
-                           intrinsic_ForkJoinGetSlicePar);
-
 /*
  * NewDenseArray(length): Allocates and returns a new dense array with
  * the given length where all values are initialized to holes.
  */
 bool
 js::intrinsic_NewDenseArray(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
@@ -891,69 +775,16 @@ intrinsic_IsWeakSet(JSContext *cx, unsig
     CallArgs args = CallArgsFromVp(argc, vp);
     MOZ_ASSERT(args.length() == 1);
     MOZ_ASSERT(args[0].isObject());
 
     args.rval().setBoolean(args[0].toObject().is<WeakSetObject>());
     return true;
 }
 
-/*
- * ParallelTestsShouldPass(): Returns false if we are running in a
- * mode (such as --ion-eager) that is known to cause additional
- * bailouts or disqualifications for parallel array tests.
- *
- * This is needed because the parallel tests generally assert that,
- * under normal conditions, they will run without bailouts or
- * compilation failures, but this does not hold under "stress-testing"
- * conditions like --ion-eager or --no-ti.  However, running the tests
- * under those conditions HAS exposed bugs and thus we do not wish to
- * disable them entirely.  Instead, we simply disable the assertions
- * that state that no bailouts etc should occur.
- */
-static bool
-intrinsic_ParallelTestsShouldPass(JSContext *cx, unsigned argc, Value *vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    args.rval().setBoolean(ParallelTestsShouldPass(cx));
-    return true;
-}
-
-/*
- * ShouldForceSequential(): Returns true if parallel ops should take
- * the sequential fallback path.
- */
-bool
-js::intrinsic_ShouldForceSequential(JSContext *cx, unsigned argc, Value *vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    args.rval().setBoolean(cx->runtime()->forkJoinWarmup ||
-                           InParallelSection());
-    return true;
-}
-
-bool
-js::intrinsic_InParallelSection(JSContext *cx, unsigned argc, Value *vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    args.rval().setBoolean(false);
-    return true;
-}
-
-static bool
-intrinsic_InParallelSectionPar(ForkJoinContext *cx, unsigned argc, Value *vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    args.rval().setBoolean(true);
-    return true;
-}
-
-JS_JITINFO_NATIVE_PARALLEL(intrinsic_InParallelSection_jitInfo,
-                           intrinsic_InParallelSectionPar);
-
 /* These wrappers are needed in order to recognize the function
  * pointers within the JIT, and the raw js:: functions can't be used
  * directly because they take a ThreadSafeContext* argument.
  */
 bool
 js::intrinsic_ObjectIsTypedObject(JSContext *cx, unsigned argc, Value *vp)
 {
     return js::ObjectIsTypedObject(cx, argc, vp);
@@ -1154,33 +985,17 @@ static const JSFunctionSpec intrinsic_fu
 
     JS_FN("CallLegacyGeneratorMethodIfWrapped",
           CallNonGenericSelfhostedMethod<Is<LegacyGeneratorObject>>, 2, 0),
     JS_FN("CallStarGeneratorMethodIfWrapped",
           CallNonGenericSelfhostedMethod<Is<StarGeneratorObject>>, 2, 0),
 
     JS_FN("IsWeakSet",               intrinsic_IsWeakSet,               1,0),
 
-    JS_FN("ForkJoin",                intrinsic_ForkJoin,                5,0),
-    JS_FN("ForkJoinNumWorkers",      intrinsic_ForkJoinNumWorkers,      0,0),
     JS_FN("NewDenseArray",           intrinsic_NewDenseArray,           1,0),
-    JS_FN("ShouldForceSequential",   intrinsic_ShouldForceSequential,   0,0),
-    JS_FN("ParallelTestsShouldPass", intrinsic_ParallelTestsShouldPass, 0,0),
-    JS_FNINFO("ClearThreadLocalArenas",
-              intrinsic_ClearThreadLocalArenas,
-              &intrinsic_ClearThreadLocalArenasInfo, 0,0),
-    JS_FNINFO("SetForkJoinTargetRegion",
-              intrinsic_SetForkJoinTargetRegion,
-              &intrinsic_SetForkJoinTargetRegionInfo, 2, 0),
-    JS_FNINFO("ForkJoinGetSlice",
-              intrinsic_ForkJoinGetSlice,
-              &intrinsic_ForkJoinGetSlice_jitInfo, 1, 0),
-    JS_FNINFO("InParallelSection",
-              intrinsic_InParallelSection,
-              &intrinsic_InParallelSection_jitInfo, 0, 0),
 
     // See builtin/TypedObject.h for descriptors of the typedobj functions.
     JS_FN("NewOpaqueTypedObject",
           js::NewOpaqueTypedObject,
           1, 0),
     JS_FN("NewDerivedTypedObject",
           js::NewDerivedTypedObject,
           3, 0),
@@ -1259,26 +1074,16 @@ static const JSFunctionSpec intrinsic_fu
     JS_FN("intl_NumberFormat_availableLocales", intl_NumberFormat_availableLocales, 0,0),
     JS_FN("intl_numberingSystem", intl_numberingSystem, 1,0),
     JS_FN("intl_patternForSkeleton", intl_patternForSkeleton, 2,0),
 
     // See builtin/RegExp.h for descriptions of the regexp_* functions.
     JS_FN("regexp_exec_no_statics", regexp_exec_no_statics, 2,0),
     JS_FN("regexp_test_no_statics", regexp_test_no_statics, 2,0),
 
-#ifdef DEBUG
-    JS_FNINFO("Dump",
-              JSNativeThreadSafeWrapper<intrinsic_Dump>,
-              &intrinsic_Dump_jitInfo, 1,0),
-
-    JS_FNINFO("ParallelSpew",
-              JSNativeThreadSafeWrapper<intrinsic_ParallelSpew>,
-              &intrinsic_ParallelSpew_jitInfo, 1,0),
-#endif
-
     JS_FS_END
 };
 
 void
 js::FillSelfHostingCompileOptions(CompileOptions &options)
 {
     /*
      * In self-hosting mode, scripts use JSOP_GETINTRINSIC instead of
--- a/js/src/vm/Xdr.h
+++ b/js/src/vm/Xdr.h
@@ -30,26 +30,26 @@ namespace js {
  *  https://developer.mozilla.org/en-US/docs/SpiderMonkey/Internals/Bytecode
  *
  * === GREETINGS, FELLOW SUBTRAHEND INCREMENTER! ===
  * For the time being, please increment the subtrahend by 2 each time it
  * changes, because we have two flavors of bytecode: with JSOP_SYMBOL (in
  * Nightly) and without (all others).  FIXME: Bug 1066322 - Enable ES6 symbols
  * in all builds.
  */
-static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 224;
+static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 226;
 static_assert(XDR_BYTECODE_VERSION_SUBTRAHEND % 2 == 0, "see the comment above");
 static const uint32_t XDR_BYTECODE_VERSION =
     uint32_t(0xb973c0de - (XDR_BYTECODE_VERSION_SUBTRAHEND
 #ifdef JS_HAS_SYMBOLS
                                                            + 1
 #endif
                                                               ));
 
-static_assert(JSErr_Limit == 369,
+static_assert(JSErr_Limit == 365,
               "GREETINGS, POTENTIAL SUBTRAHEND INCREMENTER! If you added or "
               "removed MSG_DEFs from js.msg, you should increment "
               "XDR_BYTECODE_VERSION_SUBTRAHEND and update this assertion's "
               "expected JSErr_Limit value.");
 
 class XDRBuffer {
   public:
     explicit XDRBuffer(JSContext *cx)