michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: // Shared utility functions for and macros parallel operations in `Array.js` michael@0: // and `TypedObject.js`. michael@0: michael@0: #ifdef ENABLE_PARALLEL_JS michael@0: michael@0: /* The mode asserts options object. */ michael@0: #define TRY_PARALLEL(MODE) \ michael@0: ((!MODE || MODE.mode !== "seq")) michael@0: #define ASSERT_SEQUENTIAL_IS_OK(MODE) \ michael@0: do { if (MODE) AssertSequentialIsOK(MODE) } while(false) michael@0: michael@0: /** michael@0: * The ParallelSpew intrinsic is only defined in debug mode, so define a dummy michael@0: * if debug is not on. michael@0: */ michael@0: #ifndef DEBUG michael@0: #define ParallelSpew(args) michael@0: #endif michael@0: michael@0: #define MAX_SLICE_SHIFT 6 michael@0: #define MAX_SLICE_SIZE 64 michael@0: #define MAX_SLICES_PER_WORKER 8 michael@0: michael@0: /** michael@0: * Macros to help compute the start and end indices of slices based on id. Use michael@0: * with the object returned by ComputeSliceInfo. michael@0: */ michael@0: #define SLICE_START_INDEX(shift, id) \ michael@0: (id << shift) michael@0: #define SLICE_END_INDEX(shift, start, length) \ michael@0: std_Math_min(start + (1 << shift), length) michael@0: michael@0: /** michael@0: * ForkJoinGetSlice acts as identity when we are not in a parallel section, so michael@0: * pass in the next sequential value when we are in sequential mode. The michael@0: * reason for this odd API is because intrinsics *need* to be called during michael@0: * ForkJoin's warmup to fill the TI info. michael@0: */ michael@0: #define GET_SLICE(sliceStart, sliceEnd, id) \ michael@0: ((id = ForkJoinGetSlice((InParallelSection() ? -1 : sliceStart++) | 0)) < sliceEnd) michael@0: michael@0: /** michael@0: * Determine the number and size of slices. The info object has the following michael@0: * properties: michael@0: * michael@0: * - shift: amount to shift by to compute indices michael@0: * - count: number of slices michael@0: */ michael@0: function ComputeSlicesInfo(length) { michael@0: var count = length >>> MAX_SLICE_SHIFT; michael@0: var numWorkers = ForkJoinNumWorkers(); michael@0: if (count < numWorkers) michael@0: count = numWorkers; michael@0: else if (count >= numWorkers * MAX_SLICES_PER_WORKER) michael@0: count = numWorkers * MAX_SLICES_PER_WORKER; michael@0: michael@0: // Round the slice size to be a power of 2. michael@0: var shift = std_Math_max(std_Math_log2(length / count) | 0, 1); michael@0: michael@0: // Recompute count with the rounded size. michael@0: count = length >>> shift; michael@0: if (count << shift !== length) michael@0: count += 1; michael@0: michael@0: return { shift: shift, count: count }; michael@0: } michael@0: michael@0: #endif // ENABLE_PARALLEL_JS