mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Backed out changeset eef5f845fb75 (bug 829602) for intermittent jit-test failures.
This commit is contained in:
parent
a933a9f63f
commit
c42dcf36fd
@ -958,7 +958,6 @@ selfhosting_srcs := \
|
||||
$(srcdir)/builtin/Array.js \
|
||||
$(srcdir)/builtin/Intl.js \
|
||||
$(srcdir)/builtin/IntlData.js \
|
||||
$(srcdir)/builtin/ParallelArray.js \
|
||||
$(NULL)
|
||||
|
||||
selfhosted_out_h_deps := \
|
||||
|
211
js/src/builtin/ParallelArray-inl.h
Normal file
211
js/src/builtin/ParallelArray-inl.h
Normal file
@ -0,0 +1,211 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* 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 ParallelArray_inl_h__
|
||||
#define ParallelArray_inl_h__
|
||||
|
||||
#include "builtin/ParallelArray.h"
|
||||
|
||||
#include "jsobjinlines.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
inline bool
|
||||
ParallelArrayObject::IndexInfo::inBounds() const
|
||||
{
|
||||
JS_ASSERT(isInitialized());
|
||||
JS_ASSERT(indices.length() <= dimensions.length());
|
||||
|
||||
for (uint32_t d = 0; d < indices.length(); d++) {
|
||||
if (indices[d] >= dimensions[d])
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ParallelArrayObject::IndexInfo::bump()
|
||||
{
|
||||
JS_ASSERT(isInitialized());
|
||||
JS_ASSERT(indices.length() > 0);
|
||||
|
||||
uint32_t d = indices.length() - 1;
|
||||
while (++indices[d] == dimensions[d]) {
|
||||
if (d == 0)
|
||||
return false;
|
||||
indices[d--] = 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline uint32_t
|
||||
ParallelArrayObject::IndexInfo::scalarLengthOfDimensions()
|
||||
{
|
||||
JS_ASSERT(isInitialized());
|
||||
return dimensions[0] * partialProducts[0];
|
||||
}
|
||||
|
||||
inline uint32_t
|
||||
ParallelArrayObject::IndexInfo::toScalar()
|
||||
{
|
||||
JS_ASSERT(isInitialized());
|
||||
JS_ASSERT(indices.length() <= partialProducts.length());
|
||||
|
||||
if (indices.length() == 0)
|
||||
return 0;
|
||||
if (dimensions.length() == 1)
|
||||
return indices[0];
|
||||
|
||||
uint32_t index = indices[0] * partialProducts[0];
|
||||
for (uint32_t i = 1; i < indices.length(); i++)
|
||||
index += indices[i] * partialProducts[i];
|
||||
return index;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ParallelArrayObject::IndexInfo::fromScalar(uint32_t index)
|
||||
{
|
||||
JS_ASSERT(isInitialized());
|
||||
if (!indices.resize(partialProducts.length()))
|
||||
return false;
|
||||
|
||||
if (dimensions.length() == 1) {
|
||||
indices[0] = index;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t prev = index;
|
||||
uint32_t d;
|
||||
for (d = 0; d < partialProducts.length() - 1; d++) {
|
||||
indices[d] = prev / partialProducts[d];
|
||||
prev = prev % partialProducts[d];
|
||||
}
|
||||
indices[d] = prev;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ParallelArrayObject::IndexInfo::initialize(uint32_t space)
|
||||
{
|
||||
// Initialize using a manually set dimension vector.
|
||||
JS_ASSERT(dimensions.length() > 0);
|
||||
JS_ASSERT(space <= dimensions.length());
|
||||
|
||||
// Compute the partial products of the dimensions.
|
||||
//
|
||||
// NB: partialProducts[i] is the scalar length of dimension i. The scalar
|
||||
// length of the entire space is thus dimensions[0] * partialProducts[0].
|
||||
uint32_t ndims = dimensions.length();
|
||||
if (!partialProducts.resize(ndims))
|
||||
return false;
|
||||
partialProducts[ndims - 1] = 1;
|
||||
for (uint32_t i = ndims - 1; i > 0; i--)
|
||||
partialProducts[i - 1] = dimensions[i] * partialProducts[i];
|
||||
|
||||
// Reserve indices.
|
||||
return indices.reserve(ndims) && indices.resize(space);
|
||||
}
|
||||
|
||||
inline bool
|
||||
ParallelArrayObject::IndexInfo::initialize(JSContext *cx, HandleParallelArrayObject source,
|
||||
uint32_t space)
|
||||
{
|
||||
// Initialize using a dimension vector gotten from a parallel array
|
||||
// source.
|
||||
if (!source->getDimensions(cx, dimensions))
|
||||
return false;
|
||||
|
||||
return initialize(space);
|
||||
}
|
||||
|
||||
inline bool
|
||||
ParallelArrayObject::DenseArrayToIndexVector(JSContext *cx, HandleObject obj,
|
||||
IndexVector &indices)
|
||||
{
|
||||
uint32_t length = obj->getDenseInitializedLength();
|
||||
if (!indices.resize(length))
|
||||
return false;
|
||||
|
||||
// Read the index vector out of the dense array into an actual Vector for
|
||||
// ease of access. We're guaranteed that the elements of the dense array
|
||||
// are uint32s, so just cast.
|
||||
const Value *src = obj->getDenseElements();
|
||||
const Value *end = src + length;
|
||||
for (uint32_t *dst = indices.begin(); src < end; dst++, src++)
|
||||
*dst = static_cast<uint32_t>(src->toInt32());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ParallelArrayObject::is(const Value &v)
|
||||
{
|
||||
return v.isObject() && is(&v.toObject());
|
||||
}
|
||||
|
||||
inline bool
|
||||
ParallelArrayObject::is(JSObject *obj)
|
||||
{
|
||||
return obj->hasClass(&class_);
|
||||
}
|
||||
|
||||
inline ParallelArrayObject *
|
||||
ParallelArrayObject::as(JSObject *obj)
|
||||
{
|
||||
JS_ASSERT(is(obj));
|
||||
return static_cast<ParallelArrayObject *>(obj);
|
||||
}
|
||||
|
||||
inline JSObject *
|
||||
ParallelArrayObject::dimensionArray()
|
||||
{
|
||||
JSObject &dimObj = getSlot(SLOT_DIMENSIONS).toObject();
|
||||
JS_ASSERT(dimObj.isArray());
|
||||
return &dimObj;
|
||||
}
|
||||
|
||||
inline JSObject *
|
||||
ParallelArrayObject::buffer()
|
||||
{
|
||||
JSObject &buf = getSlot(SLOT_BUFFER).toObject();
|
||||
JS_ASSERT(buf.isArray());
|
||||
return &buf;
|
||||
}
|
||||
|
||||
inline uint32_t
|
||||
ParallelArrayObject::bufferOffset()
|
||||
{
|
||||
return static_cast<uint32_t>(getSlot(SLOT_BUFFER_OFFSET).toInt32());
|
||||
}
|
||||
|
||||
inline uint32_t
|
||||
ParallelArrayObject::outermostDimension()
|
||||
{
|
||||
return static_cast<uint32_t>(dimensionArray()->getDenseElement(0).toInt32());
|
||||
}
|
||||
|
||||
inline bool
|
||||
ParallelArrayObject::isOneDimensional()
|
||||
{
|
||||
return dimensionArray()->getDenseInitializedLength() == 1;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ParallelArrayObject::getDimensions(JSContext *cx, IndexVector &dims)
|
||||
{
|
||||
RootedObject obj(cx, dimensionArray());
|
||||
if (!obj)
|
||||
return false;
|
||||
return DenseArrayToIndexVector(cx, obj, dims);
|
||||
}
|
||||
|
||||
} // namespace js
|
||||
|
||||
#endif // ParallelArray_inl_h__
|
File diff suppressed because it is too large
Load Diff
@ -12,45 +12,402 @@
|
||||
#include "jscntxt.h"
|
||||
#include "jsobj.h"
|
||||
|
||||
#include "ion/Ion.h"
|
||||
#include "vm/ForkJoin.h"
|
||||
#include "vm/ThreadPool.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
class ParallelArrayObject : public JSObject
|
||||
{
|
||||
static Class protoClass;
|
||||
static JSFunctionSpec methods[];
|
||||
static const uint32_t NumFixedSlots = 4;
|
||||
static const uint32_t NumCtors = 4;
|
||||
static FixedHeapPtr<PropertyName> ctorNames[NumCtors];
|
||||
class ParallelArrayObject;
|
||||
typedef Rooted<ParallelArrayObject *> RootedParallelArrayObject;
|
||||
typedef Handle<ParallelArrayObject *> HandleParallelArrayObject;
|
||||
|
||||
static bool initProps(JSContext *cx, HandleObject obj);
|
||||
//
|
||||
// ParallelArray Overview
|
||||
//
|
||||
// Parallel arrays are immutable, possibly multi-dimensional arrays which
|
||||
// enable parallel computation based on a few base operations. The execution
|
||||
// model is one of fallback: try to execute operations in parallel, falling
|
||||
// back to sequential implementation if (for whatever reason) the operation
|
||||
// could not be executed in paralle. The API allows leeway to implementers to
|
||||
// decide both representation and what is considered parallelizable.
|
||||
//
|
||||
// Currently ParallelArray objects are backed by dense arrays for ease of
|
||||
// GC. For the higher-dimensional case, data is stored in a packed, row-major
|
||||
// order representation in the backing dense array. See notes below about
|
||||
// IndexInfo in how to convert between scalar offsets into the backing array
|
||||
// and a vector of indices.
|
||||
//
|
||||
// ParallelArray objects are always dense. That is, all holes are eagerly
|
||||
// filled in with undefined instead of being JS_ARRAY_HOLE. This results in a
|
||||
// break from the behavior of normal JavaScript arrays: if a ParallelArray p
|
||||
// is missing an indexed property i, p[i] is _always_ undefined and will never
|
||||
// walk up the prototype chain in search of i.
|
||||
//
|
||||
// Except for the comprehension form, all operations (e.g. map, filter,
|
||||
// reduce) operate on the outermost dimension only. That is, those operations
|
||||
// only operate on the "rows" of the array. "Element" is used in context of
|
||||
// ParallelArray objects to mean any indexable value of a ParallelArray
|
||||
// object. For a one dimensional array, elements are always scalar values. For
|
||||
// a higher dimensional array, elements could either be scalar values
|
||||
// (i.e. leaves) or ParallelArray objects of lesser dimensions
|
||||
// (i.e. subarrays).
|
||||
//
|
||||
|
||||
class ParallelArrayObject : public JSObject {
|
||||
public:
|
||||
typedef Vector<uint32_t, 4> IndexVector;
|
||||
|
||||
//
|
||||
// Helper structure to help index higher-dimensional arrays to convert
|
||||
// between a vector of indices and scalar offsets for use in the flat
|
||||
// backing dense array.
|
||||
//
|
||||
// IndexInfo instances _must_ be initialized using one of the initialize
|
||||
// methods before use.
|
||||
//
|
||||
// Typical usage is stack allocating an IndexInfo, initializing it with a
|
||||
// particular source ParallelArray object's dimensionality, and mutating
|
||||
// the indices member vector. For instance, to iterate through everything
|
||||
// in the first 2 dimensions of an array of > 2 dimensions:
|
||||
//
|
||||
// IndexInfo iv(cx);
|
||||
// if (!iv.initialize(cx, source, 2))
|
||||
// return false;
|
||||
// for (uint32_t i = 0; i < iv.dimensions[0]; i++) {
|
||||
// for (uint32_t j = 0; j < iv.dimensions[1]; j++) {
|
||||
// iv.indices[0] = i;
|
||||
// iv.indices[1] = j;
|
||||
// if (source->getParallelArrayElement(cx, iv, &elem))
|
||||
// ...
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Note from the above that it is not required to fill out the indices
|
||||
// vector up to the full dimensionality. For an N-dimensional array,
|
||||
// having an indices vector of length D < N indexes a subarray.
|
||||
//
|
||||
|
||||
struct IndexInfo {
|
||||
// Vector of indices. Should be large enough to hold up to
|
||||
// dimensions.length indices.
|
||||
IndexVector indices;
|
||||
|
||||
// Vector of dimensions of the ParallelArray object that the indices
|
||||
// are meant to index into.
|
||||
IndexVector dimensions;
|
||||
|
||||
// Cached partial products of the dimensions defined by the following
|
||||
// recurrence:
|
||||
//
|
||||
// partialProducts[n] =
|
||||
// 1 if n == |dimensions|
|
||||
// dimensions[n+1] * partialProducts[n+1] otherwise
|
||||
//
|
||||
// These are used for computing scalar offsets.
|
||||
IndexVector partialProducts;
|
||||
|
||||
IndexInfo(JSContext *cx)
|
||||
: indices(cx), dimensions(cx), partialProducts(cx)
|
||||
{}
|
||||
|
||||
// Prepares indices and computes partial products. The space argument
|
||||
// is the index space. The indices vector is resized to be of length
|
||||
// space.
|
||||
//
|
||||
// The dimensions vector must be filled already, and space must be <=
|
||||
// dimensions.length().
|
||||
inline bool initialize(uint32_t space);
|
||||
|
||||
// Load dimensions from a source, then initialize as above.
|
||||
inline bool initialize(JSContext *cx, HandleParallelArrayObject source,
|
||||
uint32_t space);
|
||||
|
||||
// Bump the index by 1, wrapping over if necessary. Returns false when
|
||||
// the increment would go out of bounds.
|
||||
inline bool bump();
|
||||
|
||||
// Get the scalar length according to the dimensions vector, i.e. the
|
||||
// product of the dimensions vector.
|
||||
inline uint32_t scalarLengthOfDimensions();
|
||||
|
||||
// Compute the scalar index from the current index vector.
|
||||
inline uint32_t toScalar();
|
||||
|
||||
// Set the index vector according to a scalar index.
|
||||
inline bool fromScalar(uint32_t index);
|
||||
|
||||
inline bool inBounds() const;
|
||||
bool isInitialized() const;
|
||||
};
|
||||
|
||||
static JSObject *initClass(JSContext *cx, JSObject *obj);
|
||||
static Class class_;
|
||||
|
||||
static JSBool construct(JSContext *cx, unsigned argc, Value *vp);
|
||||
static JSBool constructHelper(JSContext *cx, MutableHandleFunction ctor, CallArgs &args);
|
||||
static inline bool is(const Value &v);
|
||||
static inline bool is(JSObject *obj);
|
||||
static inline ParallelArrayObject *as(JSObject *obj);
|
||||
|
||||
// Creates a new ParallelArray instance with the correct number of slots
|
||||
// and so forth.
|
||||
inline JSObject *dimensionArray();
|
||||
inline JSObject *buffer();
|
||||
inline uint32_t bufferOffset();
|
||||
inline uint32_t outermostDimension();
|
||||
inline bool isOneDimensional();
|
||||
inline bool getDimensions(JSContext *cx, IndexVector &dims);
|
||||
|
||||
// The general case; requires an initialized IndexInfo.
|
||||
bool getParallelArrayElement(JSContext *cx, IndexInfo &iv, MutableHandleValue vp);
|
||||
|
||||
// Get the element at index in the outermost dimension. This is a
|
||||
// convenience function designed to require an IndexInfo only if it is
|
||||
// actually needed.
|
||||
//
|
||||
// NOTE: This object will NOT have the correct type object! It is
|
||||
// up to the caller to adjust the type object appropriately
|
||||
// before releasing the object into the wild. You probably want
|
||||
// to be calling construct() above, which will adjust the type
|
||||
// object for you, since ParallelArray type objects must be setup
|
||||
// in a rather particular way to interact well with the
|
||||
// self-hosted code. See constructHelper() for details.
|
||||
static JSObject *newInstance(JSContext *cx);
|
||||
// If the parallel array is multidimensional, then the caller must provide
|
||||
// an IndexInfo initialized to length 1, which is used to access the
|
||||
// array. This argument is modified. If the parallel array is
|
||||
// one-dimensional, then maybeIV may be null.
|
||||
bool getParallelArrayElement(JSContext *cx, uint32_t index, IndexInfo *maybeIV,
|
||||
MutableHandleValue vp);
|
||||
|
||||
// Get the constructor function for argc number of arguments.
|
||||
static JSFunction *getConstructor(JSContext *cx, unsigned argc);
|
||||
// Get the element at index in the outermost dimension. This is a
|
||||
// convenience function that initializes a temporary
|
||||
// IndexInfo if the parallel array is multidimensional.
|
||||
bool getParallelArrayElement(JSContext *cx, uint32_t index, MutableHandleValue vp);
|
||||
|
||||
static JSObject *initClass(JSContext *cx, HandleObject obj);
|
||||
static bool is(const Value &v);
|
||||
bool toStringBuffer(JSContext *cx, bool useLocale, StringBuffer &sb);
|
||||
|
||||
// Note that this is not an object op but called directly from the
|
||||
// iteration code, as we enumerate prototypes ourselves.
|
||||
static bool enumerate(JSContext *cx, HandleObject obj, unsigned flags,
|
||||
AutoIdVector *props);
|
||||
|
||||
private:
|
||||
enum {
|
||||
// The ParallelArray API refers to dimensions as "shape", but to avoid
|
||||
// confusion with the internal engine notion of a shape we call it
|
||||
// "dimensions" here.
|
||||
SLOT_DIMENSIONS = 0,
|
||||
|
||||
// Underlying dense array.
|
||||
SLOT_BUFFER,
|
||||
|
||||
// First index of the underlying buffer to be considered in bounds.
|
||||
SLOT_BUFFER_OFFSET,
|
||||
|
||||
RESERVED_SLOTS
|
||||
};
|
||||
|
||||
enum ExecutionStatus {
|
||||
ExecutionFailed = 0,
|
||||
ExecutionCompiled,
|
||||
ExecutionSucceeded
|
||||
};
|
||||
|
||||
// Execution modes are kept as static instances of structs that implement
|
||||
// a signature that comprises of build, map, fold, scatter, and filter,
|
||||
// whose argument lists are defined in the macros below.
|
||||
//
|
||||
// Even though the base class |ExecutionMode| is purely abstract, we only
|
||||
// use dynamic dispatch when using the debug options. Almost always we
|
||||
// directly call the member function on one of the statics.
|
||||
|
||||
#define JS_PA_build_ARGS \
|
||||
JSContext *cx, \
|
||||
IndexInfo &iv, \
|
||||
HandleObject elementalFun, \
|
||||
HandleObject buffer
|
||||
|
||||
#define JS_PA_map_ARGS \
|
||||
JSContext *cx, \
|
||||
HandleParallelArrayObject source, \
|
||||
HandleObject elementalFun, \
|
||||
HandleObject buffer
|
||||
|
||||
#define JS_PA_reduce_ARGS \
|
||||
JSContext *cx, \
|
||||
HandleParallelArrayObject source, \
|
||||
HandleObject elementalFun, \
|
||||
HandleObject buffer, \
|
||||
MutableHandleValue vp
|
||||
|
||||
#define JS_PA_scatter_ARGS \
|
||||
JSContext *cx, \
|
||||
HandleParallelArrayObject source, \
|
||||
HandleObject targets, \
|
||||
const Value &defaultValue, \
|
||||
HandleObject conflictFun, \
|
||||
HandleObject buffer
|
||||
|
||||
#define JS_PA_filter_ARGS \
|
||||
JSContext *cx, \
|
||||
HandleParallelArrayObject source, \
|
||||
HandleObject filters, \
|
||||
HandleObject buffer
|
||||
|
||||
#define JS_PA_DECLARE_OP(NAME) \
|
||||
ExecutionStatus NAME(JS_PA_ ## NAME ## _ARGS)
|
||||
|
||||
#define JS_PA_DECLARE_ALL_OPS \
|
||||
JS_PA_DECLARE_OP(build); \
|
||||
JS_PA_DECLARE_OP(map); \
|
||||
JS_PA_DECLARE_OP(reduce); \
|
||||
JS_PA_DECLARE_OP(scatter); \
|
||||
JS_PA_DECLARE_OP(filter);
|
||||
|
||||
class ExecutionMode {
|
||||
public:
|
||||
// The comprehension form. Builds a higher-dimensional array using a
|
||||
// kernel function.
|
||||
virtual JS_PA_DECLARE_OP(build) = 0;
|
||||
|
||||
// Maps a kernel function over the outermost dimension of the array.
|
||||
virtual JS_PA_DECLARE_OP(map) = 0;
|
||||
|
||||
// Reduce to a value using a kernel function. Scan is like reduce, but
|
||||
// keeps the intermediate results in an array.
|
||||
virtual JS_PA_DECLARE_OP(reduce) = 0;
|
||||
|
||||
// Scatter elements according to an index map.
|
||||
virtual JS_PA_DECLARE_OP(scatter) = 0;
|
||||
|
||||
// Filter elements according to a truthy array.
|
||||
virtual JS_PA_DECLARE_OP(filter) = 0;
|
||||
|
||||
virtual const char *toString() = 0;
|
||||
};
|
||||
|
||||
// Fallback means try parallel first, and if unable to execute in
|
||||
// parallel, execute sequentially.
|
||||
class FallbackMode : public ExecutionMode {
|
||||
public:
|
||||
JS_PA_DECLARE_ALL_OPS
|
||||
const char *toString() { return "fallback"; }
|
||||
};
|
||||
|
||||
class ParallelMode : public ExecutionMode {
|
||||
public:
|
||||
JS_PA_DECLARE_ALL_OPS
|
||||
const char *toString() { return "parallel"; }
|
||||
};
|
||||
|
||||
class SequentialMode : public ExecutionMode {
|
||||
public:
|
||||
JS_PA_DECLARE_ALL_OPS
|
||||
const char *toString() { return "sequential"; }
|
||||
};
|
||||
|
||||
static SequentialMode sequential;
|
||||
static ParallelMode parallel;
|
||||
static FallbackMode fallback;
|
||||
|
||||
#undef JS_PA_build_ARGS
|
||||
#undef JS_PA_map_ARGS
|
||||
#undef JS_PA_reduce_ARGS
|
||||
#undef JS_PA_scatter_ARGS
|
||||
#undef JS_PA_filter_ARGS
|
||||
#undef JS_PA_DECLARE_OP
|
||||
#undef JS_PA_DECLARE_ALL_OPS
|
||||
|
||||
#ifdef DEBUG
|
||||
// Debug options can be passed in as an extra argument to the
|
||||
// operations. The grammar is:
|
||||
//
|
||||
// options ::= { mode: "par" | "seq",
|
||||
// expect: "fail" | "bail" | "success" }
|
||||
struct DebugOptions {
|
||||
ExecutionMode *mode;
|
||||
ExecutionStatus expect;
|
||||
bool init(JSContext *cx, const Value &v);
|
||||
bool check(JSContext *cx, ExecutionStatus actual);
|
||||
};
|
||||
|
||||
static const char *ExecutionStatusToString(ExecutionStatus ss);
|
||||
#endif
|
||||
|
||||
static JSFunctionSpec methods[];
|
||||
static Class protoClass;
|
||||
|
||||
static inline bool DenseArrayToIndexVector(JSContext *cx, HandleObject obj,
|
||||
IndexVector &indices);
|
||||
|
||||
static bool create(JSContext *cx, MutableHandleValue vp);
|
||||
static bool create(JSContext *cx, HandleObject buffer, MutableHandleValue vp);
|
||||
static bool create(JSContext *cx, HandleObject buffer, uint32_t offset,
|
||||
const IndexVector &dims, MutableHandleValue vp);
|
||||
static JSBool construct(JSContext *cx, unsigned argc, Value *vp);
|
||||
|
||||
static bool map(JSContext *cx, CallArgs args);
|
||||
static bool reduce(JSContext *cx, CallArgs args);
|
||||
static bool scan(JSContext *cx, CallArgs args);
|
||||
static bool scatter(JSContext *cx, CallArgs args);
|
||||
static bool filter(JSContext *cx, CallArgs args);
|
||||
static bool flatten(JSContext *cx, CallArgs args);
|
||||
static bool partition(JSContext *cx, CallArgs args);
|
||||
static bool get(JSContext *cx, CallArgs args);
|
||||
static bool dimensionsGetter(JSContext *cx, CallArgs args);
|
||||
static bool lengthGetter(JSContext *cx, CallArgs args);
|
||||
static bool toString(JSContext *cx, CallArgs args);
|
||||
static bool toLocaleString(JSContext *cx, CallArgs args);
|
||||
static bool toSource(JSContext *cx, CallArgs args);
|
||||
|
||||
static void mark(JSTracer *trc, RawObject obj);
|
||||
static JSBool lookupGeneric(JSContext *cx, HandleObject obj, HandleId id,
|
||||
MutableHandleObject objp, MutableHandleShape propp);
|
||||
static JSBool lookupProperty(JSContext *cx, HandleObject obj, HandlePropertyName name,
|
||||
MutableHandleObject objp, MutableHandleShape propp);
|
||||
static JSBool lookupElement(JSContext *cx, HandleObject obj, uint32_t index,
|
||||
MutableHandleObject objp, MutableHandleShape propp);
|
||||
static JSBool lookupSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid,
|
||||
MutableHandleObject objp, MutableHandleShape propp);
|
||||
static JSBool defineGeneric(JSContext *cx, HandleObject obj, HandleId id, HandleValue value,
|
||||
JSPropertyOp getter, StrictPropertyOp setter, unsigned attrs);
|
||||
static JSBool defineProperty(JSContext *cx, HandleObject obj,
|
||||
HandlePropertyName name, HandleValue value,
|
||||
JSPropertyOp getter, StrictPropertyOp setter, unsigned attrs);
|
||||
static JSBool defineElement(JSContext *cx, HandleObject obj,
|
||||
uint32_t index, HandleValue value,
|
||||
PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
|
||||
static JSBool defineSpecial(JSContext *cx, HandleObject obj,
|
||||
HandleSpecialId sid, HandleValue value,
|
||||
PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
|
||||
static JSBool getGeneric(JSContext *cx, HandleObject obj, HandleObject receiver,
|
||||
HandleId id, MutableHandleValue vp);
|
||||
static JSBool getProperty(JSContext *cx, HandleObject obj, HandleObject receiver,
|
||||
HandlePropertyName name, MutableHandleValue vp);
|
||||
static JSBool getElement(JSContext *cx, HandleObject obj, HandleObject receiver,
|
||||
uint32_t index, MutableHandleValue vp);
|
||||
static JSBool getSpecial(JSContext *cx, HandleObject obj, HandleObject receiver,
|
||||
HandleSpecialId sid, MutableHandleValue vp);
|
||||
static JSBool setGeneric(JSContext *cx, HandleObject obj, HandleId id,
|
||||
MutableHandleValue vp, JSBool strict);
|
||||
static JSBool setProperty(JSContext *cx, HandleObject obj, HandlePropertyName name,
|
||||
MutableHandleValue vp, JSBool strict);
|
||||
static JSBool setElement(JSContext *cx, HandleObject obj, uint32_t index,
|
||||
MutableHandleValue vp, JSBool strict);
|
||||
static JSBool getElementIfPresent(JSContext *cx, HandleObject obj, HandleObject receiver,
|
||||
uint32_t index, MutableHandleValue vp, bool *present);
|
||||
static JSBool setSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid,
|
||||
MutableHandleValue vp, JSBool strict);
|
||||
static JSBool getGenericAttributes(JSContext *cx, HandleObject obj, HandleId id,
|
||||
unsigned *attrsp);
|
||||
static JSBool getPropertyAttributes(JSContext *cx, HandleObject obj, HandlePropertyName name,
|
||||
unsigned *attrsp);
|
||||
static JSBool getElementAttributes(JSContext *cx, HandleObject obj, uint32_t index,
|
||||
unsigned *attrsp);
|
||||
static JSBool getSpecialAttributes(JSContext *cx, HandleObject obj, HandleSpecialId sid,
|
||||
unsigned *attrsp);
|
||||
static JSBool setGenericAttributes(JSContext *cx, HandleObject obj, HandleId id,
|
||||
unsigned *attrsp);
|
||||
static JSBool setPropertyAttributes(JSContext *cx, HandleObject obj, HandlePropertyName name,
|
||||
unsigned *attrsp);
|
||||
static JSBool setElementAttributes(JSContext *cx, HandleObject obj, uint32_t index,
|
||||
unsigned *attrsp);
|
||||
static JSBool setSpecialAttributes(JSContext *cx, HandleObject obj, HandleSpecialId sid,
|
||||
unsigned *attrsp);
|
||||
static JSBool deleteGeneric(JSContext *cx, HandleObject obj, HandleId id,
|
||||
MutableHandleValue rval, JSBool strict);
|
||||
static JSBool deleteProperty(JSContext *cx, HandleObject obj, HandlePropertyName name,
|
||||
MutableHandleValue rval, JSBool strict);
|
||||
static JSBool deleteElement(JSContext *cx, HandleObject obj, uint32_t index,
|
||||
MutableHandleValue rval, JSBool strict);
|
||||
static JSBool deleteSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid,
|
||||
MutableHandleValue rval, JSBool strict);
|
||||
};
|
||||
|
||||
} // namespace js
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -32,7 +32,6 @@ var std_Boolean_toString = Boolean.prototype.toString;
|
||||
var Std_Date = Date;
|
||||
var std_Date_now = Date.now;
|
||||
var std_Function_bind = Function.prototype.bind;
|
||||
var std_Function_apply = Function.prototype.apply;
|
||||
var std_Math_floor = Math.floor;
|
||||
var std_Math_max = Math.max;
|
||||
var std_Math_min = Math.min;
|
||||
|
@ -278,9 +278,8 @@ def JS2C(source, target, env):
|
||||
lines = ExpandConstants(lines, consts)
|
||||
lines = ExpandMacros(lines, macros)
|
||||
Validate(lines, filename)
|
||||
# FIXME #824112
|
||||
#if not env['DEBUG']:
|
||||
# lines = minifier.JSMinify(lines)
|
||||
if not env['DEBUG']:
|
||||
lines = minifier.JSMinify(lines)
|
||||
id = (os.path.split(filename)[1])[:-3]
|
||||
if debugger: id = id[:-9]
|
||||
raw_length = len(lines)
|
||||
|
@ -214,26 +214,6 @@ macro OVERRIDE_SUBJECT(override) = ((override)[(override).length - 1]);
|
||||
# 1-based so index of 1 returns the first capture
|
||||
macro OVERRIDE_CAPTURE(override, index) = ((override)[(index)]);
|
||||
|
||||
# The mode asserts options object for ParallelArray
|
||||
macro TRY_PARALLEL(MODE) = ((!MODE || MODE.mode === "par"));
|
||||
macro ASSERT_SEQUENTIAL_IS_OK(MODE) = do { if (MODE) AssertSequentialIsOK(MODE) } while(false);
|
||||
|
||||
# How many items at a time do we do recomp. for parallel execution.
|
||||
# Note that filter currently assumes that this is no greater than 32
|
||||
# in order to make use of a bitset.
|
||||
const CHUNK_SHIFT = 5;
|
||||
const CHUNK_SIZE = 32;
|
||||
|
||||
# Slice array: see ComputeAllSliceBounds() in ParallelArray.js
|
||||
macro SLICE_INFO(START, END) = START, END, START, 0;
|
||||
macro SLICE_START(ID) = ((ID << 2) + 0);
|
||||
macro SLICE_END(ID) = ((ID << 2) + 1);
|
||||
macro SLICE_POS(ID) = ((ID << 2) + 2);
|
||||
|
||||
# Safe version of ARRAY.push(ELEMENT)
|
||||
macro ARRAY_PUSH(ARRAY, ELEMENT) = callFunction(std_Array_push, ARRAY, ELEMENT);
|
||||
macro ARRAY_SLICE(ARRAY, ELEMENT) = callFunction(std_Array_slice, ARRAY, ELEMENT);
|
||||
|
||||
# PropertyDescriptor return value indices - must match
|
||||
# PropertyDescriptorIndices in runtime.cc.
|
||||
const IS_ACCESSOR_INDEX = 0;
|
||||
|
@ -2209,50 +2209,6 @@ CodeGenerator::generateBody()
|
||||
return true;
|
||||
}
|
||||
|
||||
// Out-of-line object allocation for LNewParallelArray.
|
||||
class OutOfLineNewParallelArray : public OutOfLineCodeBase<CodeGenerator>
|
||||
{
|
||||
LNewParallelArray *lir_;
|
||||
|
||||
public:
|
||||
OutOfLineNewParallelArray(LNewParallelArray *lir)
|
||||
: lir_(lir)
|
||||
{ }
|
||||
|
||||
bool accept(CodeGenerator *codegen) {
|
||||
return codegen->visitOutOfLineNewParallelArray(this);
|
||||
}
|
||||
|
||||
LNewParallelArray *lir() const {
|
||||
return lir_;
|
||||
}
|
||||
};
|
||||
|
||||
typedef JSObject *(*NewInitParallelArrayFn)(JSContext *, HandleObject);
|
||||
static const VMFunction NewInitParallelArrayInfo =
|
||||
FunctionInfo<NewInitParallelArrayFn>(NewInitParallelArray);
|
||||
|
||||
bool
|
||||
CodeGenerator::visitNewParallelArrayVMCall(LNewParallelArray *lir)
|
||||
{
|
||||
JS_ASSERT(gen->info().executionMode() == SequentialExecution);
|
||||
|
||||
Register objReg = ToRegister(lir->output());
|
||||
|
||||
JS_ASSERT(!lir->isCall());
|
||||
saveLive(lir);
|
||||
|
||||
pushArg(ImmGCPtr(lir->mir()->templateObject()));
|
||||
if (!callVM(NewInitParallelArrayInfo, lir))
|
||||
return false;
|
||||
|
||||
if (ReturnReg != objReg)
|
||||
masm.movePtr(ReturnReg, objReg);
|
||||
|
||||
restoreLive(lir);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Out-of-line object allocation for LNewArray.
|
||||
class OutOfLineNewArray : public OutOfLineCodeBase<CodeGenerator>
|
||||
{
|
||||
@ -2326,32 +2282,6 @@ CodeGenerator::visitNewSlots(LNewSlots *lir)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGenerator::visitNewParallelArray(LNewParallelArray *lir)
|
||||
{
|
||||
Register objReg = ToRegister(lir->output());
|
||||
JSObject *templateObject = lir->mir()->templateObject();
|
||||
|
||||
OutOfLineNewParallelArray *ool = new OutOfLineNewParallelArray(lir);
|
||||
if (!addOutOfLineCode(ool))
|
||||
return false;
|
||||
|
||||
masm.newGCThing(objReg, templateObject, ool->entry());
|
||||
masm.initGCThing(objReg, templateObject);
|
||||
|
||||
masm.bind(ool->rejoin());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGenerator::visitOutOfLineNewParallelArray(OutOfLineNewParallelArray *ool)
|
||||
{
|
||||
if (!visitNewParallelArrayVMCall(ool->lir()))
|
||||
return false;
|
||||
masm.jump(ool->rejoin());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGenerator::visitNewArray(LNewArray *lir)
|
||||
{
|
||||
|
@ -99,8 +99,6 @@ class CodeGenerator : public CodeGeneratorSpecific
|
||||
bool visitCallDirectEval(LCallDirectEval *lir);
|
||||
bool visitDoubleToInt32(LDoubleToInt32 *lir);
|
||||
bool visitNewSlots(LNewSlots *lir);
|
||||
bool visitNewParallelArrayVMCall(LNewParallelArray *lir);
|
||||
bool visitNewParallelArray(LNewParallelArray *lir);
|
||||
bool visitOutOfLineNewParallelArray(OutOfLineNewParallelArray *ool);
|
||||
bool visitNewArrayCallVM(LNewArray *lir);
|
||||
bool visitNewArray(LNewArray *lir);
|
||||
|
@ -445,13 +445,6 @@ class IonBuilder : public MIRGenerator
|
||||
InliningStatus inlineNewDenseArray(CallInfo &callInfo);
|
||||
InliningStatus inlineNewDenseArrayForSequentialExecution(CallInfo &callInfo);
|
||||
InliningStatus inlineNewDenseArrayForParallelExecution(CallInfo &callInfo);
|
||||
InliningStatus inlineNewParallelArray(CallInfo &callInfo);
|
||||
InliningStatus inlineParallelArray(CallInfo &callInfo);
|
||||
InliningStatus inlineParallelArrayTail(CallInfo &callInfo,
|
||||
HandleFunction target,
|
||||
MDefinition *ctor,
|
||||
types::StackTypeSet *ctorTypes,
|
||||
uint32_t discards);
|
||||
|
||||
InliningStatus inlineThrowError(CallInfo &callInfo);
|
||||
InliningStatus inlineDump(CallInfo &callInfo);
|
||||
|
@ -109,10 +109,6 @@ IonBuilder::inlineNativeCall(CallInfo &callInfo, JSNative native)
|
||||
return inlineShouldForceSequentialOrInParallelSection(callInfo);
|
||||
if (native == testingFunc_inParallelSection)
|
||||
return inlineShouldForceSequentialOrInParallelSection(callInfo);
|
||||
if (native == intrinsic_NewParallelArray)
|
||||
return inlineNewParallelArray(callInfo);
|
||||
if (native == ParallelArrayObject::construct)
|
||||
return inlineParallelArray(callInfo);
|
||||
if (native == intrinsic_NewDenseArray)
|
||||
return inlineNewDenseArray(callInfo);
|
||||
|
||||
@ -1070,152 +1066,6 @@ IonBuilder::inlineShouldForceSequentialOrInParallelSection(CallInfo &callInfo)
|
||||
JS_NOT_REACHED("Invalid execution mode");
|
||||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineNewParallelArray(CallInfo &callInfo)
|
||||
{
|
||||
// Rewrites a call like
|
||||
//
|
||||
// NewParallelArray(ParallelArrayView, arg0, ..., argN)
|
||||
//
|
||||
// to
|
||||
//
|
||||
// x = MNewParallelArray()
|
||||
// ParallelArrayView(x, arg0, ..., argN)
|
||||
|
||||
uint32_t argc = callInfo.argc();
|
||||
if (argc < 1 || callInfo.constructing())
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
types::StackTypeSet *ctorTypes = getInlineArgTypeSet(callInfo, 0);
|
||||
RawObject targetObj = ctorTypes->getSingleton();
|
||||
RootedFunction target(cx);
|
||||
if (targetObj && targetObj->isFunction())
|
||||
target = targetObj->toFunction();
|
||||
if (target && target->isInterpreted() && target->nonLazyScript()->shouldCloneAtCallsite) {
|
||||
RootedScript scriptRoot(cx, script());
|
||||
target = CloneFunctionAtCallsite(cx, target, scriptRoot, pc);
|
||||
if (!target)
|
||||
return InliningStatus_Error;
|
||||
}
|
||||
MDefinition *ctor = makeCallsiteClone(
|
||||
target,
|
||||
callInfo.getArg(0)->toPassArg()->getArgument());
|
||||
|
||||
// Discard the function.
|
||||
return inlineParallelArrayTail(callInfo, target, ctor,
|
||||
target ? NULL : ctorTypes, 1);
|
||||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineParallelArray(CallInfo &callInfo)
|
||||
{
|
||||
if (!callInfo.constructing())
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
uint32_t argc = callInfo.argc();
|
||||
RootedFunction target(cx, ParallelArrayObject::getConstructor(cx, argc));
|
||||
if (!target)
|
||||
return InliningStatus_Error;
|
||||
|
||||
JS_ASSERT(target->nonLazyScript()->shouldCloneAtCallsite);
|
||||
RootedScript script(cx, script_);
|
||||
target = CloneFunctionAtCallsite(cx, target, script, pc);
|
||||
if (!target)
|
||||
return InliningStatus_Error;
|
||||
|
||||
MConstant *ctor = MConstant::New(ObjectValue(*target));
|
||||
current->add(ctor);
|
||||
|
||||
return inlineParallelArrayTail(callInfo, target, ctor, NULL, 0);
|
||||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineParallelArrayTail(CallInfo &callInfo,
|
||||
HandleFunction target,
|
||||
MDefinition *ctor,
|
||||
types::StackTypeSet *ctorTypes,
|
||||
uint32_t discards)
|
||||
{
|
||||
// Rewrites either NewParallelArray(...) or new ParallelArray(...) from a
|
||||
// call to a native ctor into a call to the relevant function in the
|
||||
// self-hosted code.
|
||||
|
||||
uint32_t argc = callInfo.argc() - discards;
|
||||
|
||||
// Create the new parallel array object. Parallel arrays have specially
|
||||
// constructed type objects, so we can only perform the inlining if we
|
||||
// already have one of these type objects.
|
||||
types::StackTypeSet *returnTypes = getInlineReturnTypeSet();
|
||||
if (returnTypes->getKnownTypeTag() != JSVAL_TYPE_OBJECT)
|
||||
return InliningStatus_NotInlined;
|
||||
if (returnTypes->getObjectCount() != 1)
|
||||
return InliningStatus_NotInlined;
|
||||
types::TypeObject *typeObject = returnTypes->getTypeObject(0);
|
||||
|
||||
// Create the call and add in the non-this arguments.
|
||||
uint32_t targetArgs = argc;
|
||||
if (target && !target->isNative())
|
||||
targetArgs = Max<uint32_t>(target->nargs, argc);
|
||||
|
||||
MCall *call = MCall::New(target, targetArgs + 1, argc, false, ctorTypes);
|
||||
if (!call)
|
||||
return InliningStatus_Error;
|
||||
|
||||
callInfo.unwrapArgs();
|
||||
|
||||
// Explicitly pad any missing arguments with |undefined|.
|
||||
// This permits skipping the argumentsRectifier.
|
||||
for (int32_t i = targetArgs; i > (int)argc; i--) {
|
||||
JS_ASSERT_IF(target, !target->isNative());
|
||||
MConstant *undef = MConstant::New(UndefinedValue());
|
||||
current->add(undef);
|
||||
MPassArg *pass = MPassArg::New(undef);
|
||||
current->add(pass);
|
||||
call->addArg(i, pass);
|
||||
}
|
||||
|
||||
MPassArg *oldThis = MPassArg::New(callInfo.thisArg());
|
||||
current->add(oldThis);
|
||||
|
||||
// Add explicit arguments.
|
||||
// Skip addArg(0) because it is reserved for this
|
||||
for (int32_t i = 0; i < argc; i++) {
|
||||
MDefinition *arg = callInfo.getArg(i + discards);
|
||||
MPassArg *passArg = MPassArg::New(arg);
|
||||
current->add(passArg);
|
||||
call->addArg(i + 1, passArg);
|
||||
}
|
||||
|
||||
// Place an MPrepareCall before the first passed argument, before we
|
||||
// potentially perform rearrangement.
|
||||
MPrepareCall *start = new MPrepareCall;
|
||||
oldThis->block()->insertBefore(oldThis, start);
|
||||
call->initPrepareCall(start);
|
||||
|
||||
// Create the MIR to allocate the new parallel array. Take the type
|
||||
// object is taken from the prediction set.
|
||||
RootedObject templateObject(cx, ParallelArrayObject::newInstance(cx));
|
||||
if (!templateObject)
|
||||
return InliningStatus_Error;
|
||||
templateObject->setType(typeObject);
|
||||
MNewParallelArray *newObject = MNewParallelArray::New(templateObject);
|
||||
current->add(newObject);
|
||||
MPassArg *newThis = MPassArg::New(newObject);
|
||||
current->add(newThis);
|
||||
call->addArg(0, newThis);
|
||||
|
||||
// Set the new callee.
|
||||
call->initFunction(ctor);
|
||||
|
||||
current->add(call);
|
||||
current->push(newObject);
|
||||
|
||||
if (!resumeAfter(call))
|
||||
return InliningStatus_Error;
|
||||
|
||||
return InliningStatus_Inlined;
|
||||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineNewDenseArray(CallInfo &callInfo)
|
||||
{
|
||||
|
@ -1077,10 +1077,6 @@ class MNewParallelArray : public MNullaryInstruction
|
||||
return new MNewParallelArray(templateObject);
|
||||
}
|
||||
|
||||
AliasSet getAliasSet() const {
|
||||
return AliasSet::None();
|
||||
}
|
||||
|
||||
JSObject *templateObject() const {
|
||||
return templateObject_;
|
||||
}
|
||||
|
@ -269,21 +269,6 @@ IteratorMore(JSContext *cx, HandleObject obj, JSBool *res)
|
||||
return true;
|
||||
}
|
||||
|
||||
JSObject *
|
||||
NewInitParallelArray(JSContext *cx, HandleObject templateObject)
|
||||
{
|
||||
JS_ASSERT(templateObject->getClass() == &ParallelArrayObject::class_);
|
||||
JS_ASSERT(!templateObject->hasSingletonType());
|
||||
|
||||
RootedObject obj(cx, ParallelArrayObject::newInstance(cx));
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
obj->setType(templateObject->type());
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
JSObject*
|
||||
NewInitArray(JSContext *cx, uint32_t count, types::TypeObject *typeArg)
|
||||
{
|
||||
|
@ -436,8 +436,7 @@ JSBool ObjectEmulatesUndefined(RawObject obj);
|
||||
|
||||
bool IteratorMore(JSContext *cx, HandleObject obj, JSBool *res);
|
||||
|
||||
// Allocation functions for JSOP_NEWARRAY and JSOP_NEWOBJECT and parallel array inlining
|
||||
JSObject *NewInitParallelArray(JSContext *cx, HandleObject templateObj);
|
||||
// Allocation functions for JSOP_NEWARRAY and JSOP_NEWOBJECT
|
||||
JSObject *NewInitArray(JSContext *cx, uint32_t count, types::TypeObject *type);
|
||||
JSObject *NewInitObject(JSContext *cx, HandleObject templateObject);
|
||||
|
||||
|
@ -2,118 +2,7 @@
|
||||
* 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/. */
|
||||
|
||||
// Explanation of minItemsTestingThreshold:
|
||||
//
|
||||
// If the volume of input items in a test is small, then all of them
|
||||
// may be processed during warmup alone, and the parallel-invocation
|
||||
// will trivially succeed even if we are intentionally trying to
|
||||
// detect a failure.
|
||||
//
|
||||
// The maximum number of items processed by sequential warmups for
|
||||
// ParallelArrayBuild is:
|
||||
// maxSeqItems = maxBailouts * numSlices * CHUNK_SIZE
|
||||
//
|
||||
// For maxBailouts = 3, maxSeqItems == 3 * 8 * 32 == 768
|
||||
// For maxBailouts = 5, maxSeqItems == 5 * 8 * 32 == 1280
|
||||
//
|
||||
// Our test code does not have access to the values of these constants
|
||||
// (maxBailouts, numSlices, CHUNK_SIZE). Therefore, the value of
|
||||
// minItemsTestingThreshold should be kept in sync with some value
|
||||
// greater than maxSeqItems as calculated above.
|
||||
//
|
||||
// This is still imperfect since it assumes numSlices <= 8, but
|
||||
// numSlices is machine-dependent.
|
||||
// (TODO: consider exposing numSlices via builtin/TestingFunctions.cpp)
|
||||
|
||||
var minItemsTestingThreshold = 1024;
|
||||
|
||||
function build(n, f) {
|
||||
var result = [];
|
||||
for (var i = 0; i < n; i++)
|
||||
result.push(f(i));
|
||||
return result;
|
||||
}
|
||||
|
||||
function range(n, m) {
|
||||
// Returns an array with [n..m] (include on n, exclusive on m)
|
||||
|
||||
var result = [];
|
||||
for (var i = n; i < m; i++)
|
||||
result.push(i);
|
||||
return result;
|
||||
}
|
||||
|
||||
function seq_scan(array, f) {
|
||||
// Simple sequential version of scan() that operates over an array
|
||||
|
||||
var result = [];
|
||||
result[0] = array[0];
|
||||
for (var i = 1; i < array.length; i++) {
|
||||
result[i] = f(result[i-1], array[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function assertAlmostEq(v1, v2) {
|
||||
if (v1 === v2)
|
||||
return true;
|
||||
// + and other fp ops can vary somewhat when run in parallel!
|
||||
assertEq(typeof v1, "number");
|
||||
assertEq(typeof v2, "number");
|
||||
var diff = Math.abs(v1 - v2);
|
||||
var percent = diff / v1 * 100.0;
|
||||
print("v1 = " + v1);
|
||||
print("v2 = " + v2);
|
||||
print("% diff = " + percent);
|
||||
assertEq(percent < 1e-10, true); // off by an less than 1e-10%...good enough.
|
||||
}
|
||||
|
||||
function assertStructuralEq(e1, e2) {
|
||||
if (e1 instanceof ParallelArray && e2 instanceof ParallelArray) {
|
||||
assertEqParallelArray(e1, e2);
|
||||
} else if (e1 instanceof Array && e2 instanceof ParallelArray) {
|
||||
assertEqParallelArrayArray(e2, e1);
|
||||
} else if (e1 instanceof ParallelArray && e2 instanceof Array) {
|
||||
assertEqParallelArrayArray(e1, e2);
|
||||
} else if (e1 instanceof Array && e2 instanceof Array) {
|
||||
assertEqArray(e1, e2);
|
||||
} else if (e1 instanceof Object && e2 instanceof Object) {
|
||||
assertEq(e1.__proto__, e2.__proto__);
|
||||
for (prop in e1) {
|
||||
if (e1.hasOwnProperty(prop)) {
|
||||
assertEq(e2.hasOwnProperty(prop), true);
|
||||
assertStructuralEq(e1[prop], e2[prop]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
assertEq(e1, e2);
|
||||
}
|
||||
}
|
||||
|
||||
function assertEqParallelArrayArray(a, b) {
|
||||
assertEq(a.shape.length, 1);
|
||||
assertEq(a.length, b.length);
|
||||
for (var i = 0, l = a.length; i < l; i++) {
|
||||
try {
|
||||
assertStructuralEq(a.get(i), b[i]);
|
||||
} catch (e) {
|
||||
print("...in index ", i, " of ", l);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function assertEqArray(a, b) {
|
||||
assertEq(a.length, b.length);
|
||||
for (var i = 0, l = a.length; i < l; i++) {
|
||||
try {
|
||||
assertStructuralEq(a[i], b[i]);
|
||||
} catch (e) {
|
||||
print("...in index ", i, " of ", l);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
load(libdir + "eqArrayHelper.js");
|
||||
|
||||
function assertEqParallelArray(a, b) {
|
||||
assertEq(a instanceof ParallelArray, true);
|
||||
@ -135,89 +24,29 @@ function assertEqParallelArray(a, b) {
|
||||
|
||||
var iv = shape.map(function () { return 0; });
|
||||
do {
|
||||
try {
|
||||
var e1 = a.get.apply(a, iv);
|
||||
var e2 = b.get.apply(b, iv);
|
||||
assertStructuralEq(e1, e2);
|
||||
} catch (e) {
|
||||
print("...in indices ", iv, " of ", shape);
|
||||
throw e;
|
||||
}
|
||||
var e1 = a.get(iv);
|
||||
var e2 = b.get(iv);
|
||||
if (e1 instanceof ParallelArray && e2 instanceof ParallelArray)
|
||||
assertEqParallelArray(e1, e2);
|
||||
else if (e1 instanceof Array && e2 instanceof Array)
|
||||
assertEqArray(e1, e2);
|
||||
else
|
||||
assertEq(e1, e2);
|
||||
} while (bump(iv));
|
||||
}
|
||||
|
||||
function assertParallelArrayModesEq(modes, acc, opFunction, cmpFunction) {
|
||||
if (!cmpFunction) { cmpFunction = assertStructuralEq; }
|
||||
function assertParallelArrayModesCommute(modes, pa, op) {
|
||||
var args = Array.slice(arguments, 3);
|
||||
var acc;
|
||||
modes.forEach(function (mode) {
|
||||
var result = opFunction({ mode: mode, expect: "success" });
|
||||
cmpFunction(acc, result);
|
||||
var result = op.apply(pa, args.concat([{ mode: mode, expect: "success" }]));
|
||||
if (acc) {
|
||||
if (acc instanceof ParallelArray)
|
||||
assertEqParallelArray(acc, result);
|
||||
else
|
||||
assertEq(acc, result);
|
||||
} else {
|
||||
acc = result;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function assertParallelArrayModesCommute(modes, opFunction) {
|
||||
var acc = opFunction({ mode: modes[0], expect: "success" });
|
||||
assertParallelArrayModesEq(modes.slice(1), acc, opFunction);
|
||||
}
|
||||
|
||||
function comparePerformance(opts) {
|
||||
var measurements = [];
|
||||
for (var i = 0; i < opts.length; i++) {
|
||||
var start = new Date();
|
||||
opts[i].func();
|
||||
var end = new Date();
|
||||
var diff = (end.getTime() - start.getTime());
|
||||
measurements.push(diff);
|
||||
print("Option " + opts[i].name + " took " + diff + "ms");
|
||||
}
|
||||
|
||||
for (var i = 1; i < opts.length; i++) {
|
||||
var rel = (measurements[i] - measurements[0]) * 100 / measurements[0];
|
||||
print("Option " + opts[i].name + " relative to option " +
|
||||
opts[0].name + ": " + (rel|0) + "%");
|
||||
}
|
||||
}
|
||||
|
||||
function compareAgainstArray(jsarray, opname, func, cmpFunction) {
|
||||
var expected = jsarray[opname].apply(jsarray, [func]);
|
||||
var parray = new ParallelArray(jsarray);
|
||||
|
||||
// Unfortunately, it sometimes happens that running 'par' twice in a
|
||||
// row causes bailouts and other unfortunate things!
|
||||
|
||||
assertParallelArrayModesEq(["seq", "par", "par"], expected, function(m) {
|
||||
print(m.mode + " " + m.expect);
|
||||
var result = parray[opname].apply(parray, [func, m]);
|
||||
// print(result.toString());
|
||||
return result;
|
||||
}, cmpFunction);
|
||||
}
|
||||
|
||||
function testFilter(jsarray, func, cmpFunction) {
|
||||
compareAgainstArray(jsarray, "filter", func, cmpFunction);
|
||||
|
||||
// var expected = jsarray.filter(func);
|
||||
// var filters = jsarray.map(func);
|
||||
// var parray = new ParallelArray(jsarray);
|
||||
//
|
||||
// // Unfortunately, it sometimes happens that running 'par' twice in a
|
||||
// // row causes bailouts and other unfortunate things!
|
||||
//
|
||||
// assertParallelArrayModesEq(["seq", "par", "par"], expected, function(m) {
|
||||
// print(m.mode + " " + m.expect);
|
||||
// return parray.filter(filters, m);
|
||||
// }, cmpFunction);
|
||||
}
|
||||
|
||||
function testScan(jsarray, func, cmpFunction) {
|
||||
var expected = seq_scan(jsarray, func);
|
||||
var parray = new ParallelArray(jsarray);
|
||||
|
||||
// Unfortunately, it sometimes happens that running 'par' twice in a
|
||||
// row causes bailouts and other unfortunate things!
|
||||
|
||||
assertParallelArrayModesEq(["seq", "par", "par"], expected, function(m) {
|
||||
print(m.mode + " " + m.expect);
|
||||
var p = parray.scan(func, m);
|
||||
return p;
|
||||
}, cmpFunction);
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
// |jit-test| error:Error
|
||||
|
||||
// Binary: cache/js-dbg-64-50177d59c0e1-linux
|
||||
// Flags:
|
||||
//
|
||||
|
@ -1,3 +1,5 @@
|
||||
// |jit-test| error:TypeError
|
||||
|
||||
// Binary: cache/js-dbg-64-c676b554c7bb-linux
|
||||
// Flags:
|
||||
//
|
||||
|
@ -1,3 +1,5 @@
|
||||
// |jit-test| error:TypeError
|
||||
|
||||
// Binary: cache/js-dbg-64-5d63594c05a9-linux
|
||||
// Flags:
|
||||
//
|
||||
|
@ -1,32 +0,0 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function buildSimple() {
|
||||
|
||||
assertParallelArrayModesCommute(["seq", "par"], function(m) {
|
||||
return new ParallelArray([256], function(i) {
|
||||
return [i, i+1, i+2, i+3];
|
||||
}, m);
|
||||
});
|
||||
|
||||
assertParallelArrayModesCommute(["seq", "par"], function(m) {
|
||||
return new ParallelArray([256], function(i) {
|
||||
var x = [];
|
||||
for (var i = 0; i < 4; i++) {
|
||||
x[i] = i;
|
||||
}
|
||||
return x;
|
||||
}, m);
|
||||
});
|
||||
|
||||
assertParallelArrayModesCommute(["seq", "par"], function(m) {
|
||||
return new ParallelArray([256], function(i) {
|
||||
var x = [];
|
||||
for (var i = 0; i < 99; i++) {
|
||||
x[i] = i;
|
||||
}
|
||||
return x;
|
||||
}, m);
|
||||
});
|
||||
}
|
||||
|
||||
buildSimple();
|
@ -1,21 +0,0 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function testMap() {
|
||||
compareAgainstArray(range(0, 64), "map", function (v) {
|
||||
var x = [];
|
||||
var N = 2;
|
||||
for (var i = 0; i < 10; i++) {
|
||||
if ((i % N) == 0) {
|
||||
x[i] = {f1: v};
|
||||
} else if ((i % N) == 1) {
|
||||
x[i] = {f1: v, f2: v, f3: v,
|
||||
f4: v, f5: v, f6: v,
|
||||
f7: v, f8: v, f9: v};
|
||||
}
|
||||
}
|
||||
return x;
|
||||
});
|
||||
}
|
||||
|
||||
testMap();
|
||||
|
@ -1,23 +0,0 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function testMap() {
|
||||
// At least on my machine, this test is successful, whereas
|
||||
// `alloc-too-many-objs.js` fails to run in parallel because of
|
||||
// issues around GC.
|
||||
|
||||
var nums = new ParallelArray(range(0, 10));
|
||||
|
||||
assertParallelArrayModesCommute(["seq", "par"], function(m) {
|
||||
print(m.mode+" "+m.expect);
|
||||
nums.map(function (v) {
|
||||
var x = [];
|
||||
for (var i = 0; i < 45000; i++) {
|
||||
x[i] = {from: v};
|
||||
}
|
||||
return x;
|
||||
}, m)
|
||||
});
|
||||
}
|
||||
|
||||
testMap();
|
||||
|
@ -1,13 +0,0 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function buildSimple() {
|
||||
|
||||
assertParallelArrayModesCommute(["seq", "par"], function(m) {
|
||||
return new ParallelArray([256], function(i) {
|
||||
return { x: i, y: i + 1, z: i + 2 };
|
||||
}, m);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
buildSimple();
|
@ -1,35 +0,0 @@
|
||||
// |jit-test| slow;
|
||||
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function testMap() {
|
||||
|
||||
// Note: This is the same kernel function as `alloc-many-objs`, but
|
||||
// with a larger bound. This often fails par. exec. because it
|
||||
// triggers GC at inconvenient times. But let's just test that it
|
||||
// doesn't crash or something!
|
||||
|
||||
var ints = range(0, 100000);
|
||||
var pints = new ParallelArray(ints);
|
||||
|
||||
// The bailout occurs because at some point during execution we will
|
||||
// request a GC. The GC is actually deferred until after execution
|
||||
// fails.
|
||||
pints.map(kernel, {mode: "par", expect: "bailout"});
|
||||
|
||||
function kernel(v) {
|
||||
var x = [];
|
||||
|
||||
for (var i = 0; i < 50; i++) {
|
||||
x[i] = [];
|
||||
for (var j = 0; j < 1024; j++) {
|
||||
x[i][j] = j;
|
||||
}
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
}
|
||||
|
||||
testMap();
|
||||
|
@ -1,22 +0,0 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function makeObject(e, i, c) {
|
||||
var v = {element: e, index: i, collection: c};
|
||||
|
||||
if (e == 512) // note: happens once
|
||||
delete v.i;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
function test() {
|
||||
var array = range(0, 768);
|
||||
var array1 = array.map(makeObject);
|
||||
|
||||
var pa = new ParallelArray(array);
|
||||
var pa1 = pa.map(makeObject, {mode: "par", expect: "mixed"});
|
||||
|
||||
assertStructuralEq(pa1, array1);
|
||||
}
|
||||
|
||||
test();
|
@ -1,16 +0,0 @@
|
||||
// |jit-test| slow;
|
||||
// ^^ This test is slow when --no-ion is used, specifically,
|
||||
// as part of TBPL.
|
||||
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function makeObject(e, i, c) {
|
||||
var v = {element: e, index: i, collection: c};
|
||||
|
||||
if (e == 512) // note: never happens
|
||||
delete v.i;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
compareAgainstArray(range(0, 512), "map", makeObject);
|
@ -1,12 +0,0 @@
|
||||
function testClosureCreation() {
|
||||
var a = [ 1, 2, 3, 4, 5, 6, 7, 8, 9,10,
|
||||
11,12,13,14,15,16,17,18,19,20,
|
||||
21,22,23,24,25,26,27,28,29,30,
|
||||
31,32,33,34,35,36,27,38,39,40];
|
||||
var p = new ParallelArray(a);
|
||||
var makeadd1 = function (v) { return function (x) { return x+1; }; };
|
||||
var m = p.map(makeadd1, {mode: "par", expect: "success"});
|
||||
assertEq(m.get(1)(2), 3); // (\x.x+1) 2 == 3
|
||||
}
|
||||
|
||||
testClosureCreation();
|
@ -1,11 +0,0 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function testClosureCreation() {
|
||||
var a = range(0, 64);
|
||||
var p = new ParallelArray(a);
|
||||
var makeadd1 = function (v) { return function (x) { return x+1; }; };
|
||||
var m = p.map(makeadd1, {mode: "par", expect: "success"});
|
||||
assertEq(m.get(1)(2), 3); // (\x.x+1) 2 == 3
|
||||
}
|
||||
|
||||
testClosureCreation();
|
@ -1,12 +0,0 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function testClosureCreationAndInvocation() {
|
||||
var a = range(1, 65);
|
||||
var p = new ParallelArray(a);
|
||||
function etaadd1(v) { return (function (x) { return x+1; })(v); };
|
||||
// eta-expansion is (or at least can be) treated as call with unknown target
|
||||
var m = p.map(etaadd1, {mode: "par", expect: "success"});
|
||||
assertEq(m.get(1), 3); // (\x.x+1) 2 == 3
|
||||
}
|
||||
|
||||
testClosureCreationAndInvocation();
|
@ -1,12 +0,0 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function testClosureCreationAndInvocation() {
|
||||
var a = range(1, 65);
|
||||
var p = new ParallelArray(a);
|
||||
function makeaddv(v) { return function (x) { return x+v; }; };
|
||||
var m = p.map(makeaddv, {mode: "par", expect: "success"});
|
||||
assertEq(m.get(1)(1), 3); // (\x.x+v){v=2} 1 == 3
|
||||
assertEq(m.get(2)(2), 5); // (\x.x+v){v=3} 2 == 5
|
||||
}
|
||||
|
||||
testClosureCreationAndInvocation();
|
@ -1,37 +0,0 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function testClosureCreationAndInvocation() {
|
||||
var a = range(1, 65);
|
||||
var p = new ParallelArray(a);
|
||||
function makeaddv(v) {
|
||||
var u = v - 1;
|
||||
var t = v - 2;
|
||||
var s = v - 3;
|
||||
var r = v - 4;
|
||||
var q = v - 5;
|
||||
var p = v - 6;
|
||||
var o = v - 7;
|
||||
var n = v - 8;
|
||||
var m = v - 9;
|
||||
var l = v - 10;
|
||||
var k = v - 11;
|
||||
var j = v - 12;
|
||||
var i = v - 13;
|
||||
var h = v - 14;
|
||||
var g = v - 15;
|
||||
var f = v - 16;
|
||||
var e = v - 17;
|
||||
var d = v - 18;
|
||||
var c = v - 19;
|
||||
var b = v - 20;
|
||||
var a = v - 21;
|
||||
return function (x) { return [x,v,u,t,v,s,r,q,
|
||||
p,o,m,n,l,k,j,i,
|
||||
h,g,f,e,d,c,b,a]; };
|
||||
};
|
||||
var m = p.map(makeaddv);
|
||||
print(m.get(20)(1)[2]);
|
||||
assertEq(m.get(20)(1)[2], 20);
|
||||
}
|
||||
|
||||
testClosureCreationAndInvocation();
|
@ -1,48 +0,0 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function testClosureCreationAndInvocation() {
|
||||
var a = range(0, 64);
|
||||
var p = new ParallelArray(a);
|
||||
function makeaddv(v) {
|
||||
var u = v - 1;
|
||||
var t = v - 2;
|
||||
var s = v - 3;
|
||||
var r = v - 4;
|
||||
var q = v - 5;
|
||||
var p = v - 6;
|
||||
var o = v - 7;
|
||||
var n = v - 8;
|
||||
var m = v - 9;
|
||||
var l = v - 10;
|
||||
var k = v - 11;
|
||||
var j = v - 12;
|
||||
var i = v - 13;
|
||||
var h = v - 14;
|
||||
var g = v - 15;
|
||||
var f = v - 16;
|
||||
var e = v - 17;
|
||||
var d = v - 18;
|
||||
var c = v - 19;
|
||||
var b = v - 20;
|
||||
var a = v - 21;
|
||||
return function (x) {
|
||||
switch (x) {
|
||||
case 0: return a; case 1: return b;
|
||||
case 2: return c; case 3: return d;
|
||||
case 4: return e; case 5: return f;
|
||||
case 6: return g; case 7: return h;
|
||||
case 8: return i; case 9: return j;
|
||||
case 10: return k; case 11: return l;
|
||||
case 12: return m; case 13: return n;
|
||||
case 14: return o; case 15: return p;
|
||||
case 16: return q; case 17: return r;
|
||||
case 18: return s; case 19: return t;
|
||||
case 20: return u;
|
||||
}
|
||||
};
|
||||
};
|
||||
var m = p.map(makeaddv);
|
||||
assertEq(m.get(21)(1), 1); // v == 21; x == 1 ==> inner function returns b == 1
|
||||
}
|
||||
|
||||
testClosureCreationAndInvocation();
|
@ -1,48 +0,0 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function testClosureCreationAndInvocation() {
|
||||
var a = range(0, 64);
|
||||
var p = new ParallelArray(a);
|
||||
function makeaddv(v) {
|
||||
var u = 1;
|
||||
var t = 2;
|
||||
var s = 3;
|
||||
var r = 4;
|
||||
var q = 5;
|
||||
var p = 6;
|
||||
var o = 7;
|
||||
var n = 8;
|
||||
var m = 9;
|
||||
var l = 10;
|
||||
var k = 11;
|
||||
var j = 12;
|
||||
var i = 13;
|
||||
var h = 14;
|
||||
var g = 15;
|
||||
var f = 16;
|
||||
var e = 17;
|
||||
var d = 18;
|
||||
var c = 19;
|
||||
var b = 20;
|
||||
var a = 21;
|
||||
return function (x) {
|
||||
switch (x) {
|
||||
case 0: return a; case 1: return b;
|
||||
case 2: return c; case 3: return d;
|
||||
case 4: return e; case 5: return f;
|
||||
case 6: return g; case 7: return h;
|
||||
case 8: return i; case 9: return j;
|
||||
case 10: return k; case 11: return l;
|
||||
case 12: return m; case 13: return n;
|
||||
case 14: return o; case 15: return p;
|
||||
case 16: return q; case 17: return r;
|
||||
case 18: return s; case 19: return t;
|
||||
case 20: return u;
|
||||
}
|
||||
};
|
||||
};
|
||||
var m = p.map(makeaddv, {mode: "par", expect: "success"});
|
||||
assertEq(m.get(21)(1), 20); // v == 21; x == 1 ==> inner function returns b == 20
|
||||
}
|
||||
|
||||
testClosureCreationAndInvocation();
|
@ -1,53 +0,0 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function testClosureCreationAndInvocation() {
|
||||
var a = range(0, 64);
|
||||
var p = new ParallelArray(a);
|
||||
function makeaddv(v) {
|
||||
var u = 1;
|
||||
var t = 2;
|
||||
var s = 3;
|
||||
var r = 4;
|
||||
var q = 5;
|
||||
var p = 6;
|
||||
var o = 7;
|
||||
var n = 8;
|
||||
var m = 9;
|
||||
var l = 10;
|
||||
var k = 11;
|
||||
var j = 12;
|
||||
var i = 13;
|
||||
var h = 14;
|
||||
var g = 15;
|
||||
var f = 16;
|
||||
var e = 17;
|
||||
var d = 18;
|
||||
var c = 19;
|
||||
var b = 20;
|
||||
var a = 21;
|
||||
return ((v % 2 == 0)
|
||||
? function (x) { return a; }
|
||||
: function (x) {
|
||||
switch (x) {
|
||||
case 0: return a; case 1: return b;
|
||||
case 2: return c; case 3: return d;
|
||||
case 4: return e; case 5: return f;
|
||||
case 6: return g; case 7: return h;
|
||||
case 8: return i; case 9: return j;
|
||||
case 10: return k; case 11: return l;
|
||||
case 12: return m; case 13: return n;
|
||||
case 14: return o; case 15: return p;
|
||||
case 16: return q; case 17: return r;
|
||||
case 18: return s; case 19: return t;
|
||||
case 20: return u;
|
||||
}
|
||||
});
|
||||
}
|
||||
var m = p.map(makeaddv, {mode: "par", expect: "success"});
|
||||
assertEq(m.get(21)(1), 20); // v == 21; x == 1 ==> inner function returns b == 20
|
||||
|
||||
var n = p.map(function (v) { return function (x) { return v; }});
|
||||
assertEq(n.get(21)(1), 21); // v == 21
|
||||
}
|
||||
|
||||
testClosureCreationAndInvocation();
|
@ -1,6 +0,0 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
compareAgainstArray(["a", "b", "c", "d", "e", "f", "g", "h",
|
||||
"i", "j", "k", "l", "m", "n", "o", "p",
|
||||
"q", "r", "s", "t", "u", "v", "w", "x",
|
||||
"y", "z"], "map", function(e) { return e == "u" || e == "x"; });
|
@ -1,6 +0,0 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
compareAgainstArray(["a", "b", "c", "d", "e", "f", "g", "h",
|
||||
"i", "j", "k", "l", "m", "n", "o", "p",
|
||||
"q", "r", "s", "t", "u", "v", "w", "x",
|
||||
"y", "z"], "map", function(e) { return e != "u" && e != "x"; });
|
@ -1,19 +0,0 @@
|
||||
// |jit-test| slow;
|
||||
|
||||
load(libdir + "parallelarray-helpers.js")
|
||||
|
||||
function buildComprehension() {
|
||||
var pa1 = new ParallelArray(256, function (idx) { return idx; });
|
||||
for (var i = 0; i < 20000; i++) {
|
||||
print(i);
|
||||
buildAndCompare();
|
||||
}
|
||||
|
||||
function buildAndCompare() {
|
||||
// this will be ion-generated:
|
||||
var pa2 = new ParallelArray(256, function (idx) { return idx; });
|
||||
assertStructuralEq(pa1, pa2);
|
||||
}
|
||||
}
|
||||
|
||||
buildComprehension();
|
@ -1,16 +0,0 @@
|
||||
load(libdir + "parallelarray-helpers.js")
|
||||
|
||||
function test() {
|
||||
var pa1 = new ParallelArray(256, function (x) {
|
||||
return new ParallelArray(256, function(y) { return x*1000 + y; });
|
||||
});
|
||||
|
||||
for (var x = 0; x < 256; x++) {
|
||||
var pax = pa1.get(x);
|
||||
for (var y = 0; y < 256; y++) {
|
||||
assertEq(pax.get(y), x * 1000 + y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
test();
|
@ -14,7 +14,7 @@ function buildComprehension() {
|
||||
}
|
||||
}
|
||||
}
|
||||
var p2 = new ParallelArray(a).partition(d).partition(W);
|
||||
var p2 = new ParallelArray(a).partition(d).partition(H);
|
||||
assertEqParallelArray(p, p2);
|
||||
}
|
||||
|
||||
|
@ -22,5 +22,4 @@ function buildComprehension() {
|
||||
}, RangeError);
|
||||
}
|
||||
|
||||
// FIXME(bug 844887) throw correct exception
|
||||
// buildComprehension();
|
||||
buildComprehension();
|
||||
|
@ -1,14 +1,14 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
load(libdir + "eqArrayHelper.js");
|
||||
|
||||
function buildSimple() {
|
||||
// Simple constructor
|
||||
var a = [1,2,3,4,5];
|
||||
var p = new ParallelArray(a);
|
||||
assertEqParallelArrayArray(p, a);
|
||||
assertEqArray(p, a);
|
||||
var a2 = a.slice();
|
||||
a[0] = 9;
|
||||
// No sharing
|
||||
assertEqParallelArrayArray(p, a2);
|
||||
assertEqArray(p, a2);
|
||||
}
|
||||
|
||||
buildSimple();
|
||||
|
@ -10,5 +10,4 @@ function buildWithHoles() {
|
||||
assertEq(Object.keys(p).join(","), Object.keys(b).join(","));
|
||||
}
|
||||
|
||||
// FIXME(bug 844882) self-hosted object not array-like, exposes internal properties
|
||||
// buildWithHoles();
|
||||
buildWithHoles();
|
||||
|
@ -7,7 +7,7 @@ function buildArrayLike() {
|
||||
var a = { 0: 1, 1: 2, 2: 3, 3: 4, length: 4 };
|
||||
var p = new ParallelArray(a);
|
||||
var e = Array.prototype.join.call(a, ",");
|
||||
assertEq(p.toString(), e);
|
||||
assertEq(p.toString(), bracket(e));
|
||||
}
|
||||
|
||||
buildArrayLike();
|
||||
|
@ -5,11 +5,9 @@ function buildPA() {
|
||||
var p1 = new ParallelArray([1,2,3,4]);
|
||||
var p2 = new ParallelArray(p1);
|
||||
assertEqParallelArray(p1, p2);
|
||||
|
||||
var p1d = new ParallelArray([2,2], function(i,j) { return i + j; });
|
||||
var p2d = new ParallelArray(p1d);
|
||||
assertEq(p1d.toString(), p2d.toString());
|
||||
}
|
||||
|
||||
// FIXME(bug 844882) self-hosted object not array-like, exposes internal properties
|
||||
// buildPA();
|
||||
buildPA();
|
||||
|
@ -1,7 +1,3 @@
|
||||
// |jit-test| slow;
|
||||
// ^^ This test is slow when --no-ion is used, specifically,
|
||||
// as part of TBPL.
|
||||
|
||||
function testCopyBigArray() {
|
||||
// Don't crash
|
||||
var a = new Array(1000 * 1000);
|
||||
|
@ -3,11 +3,11 @@ function testElement() {
|
||||
var a = [1,{},"a",false]
|
||||
var p = new ParallelArray(a);
|
||||
for (var i = 0; i < a.length; i++) {
|
||||
assertEq(p.get(i), p.get(i));
|
||||
assertEq(p.get(i), a[i]);
|
||||
assertEq(p[i], p[i]);
|
||||
assertEq(p[i], a[i]);
|
||||
}
|
||||
// Test out of bounds
|
||||
assertEq(p.get(42), undefined);
|
||||
assertEq(p[42], undefined);
|
||||
}
|
||||
|
||||
testElement();
|
||||
|
@ -4,22 +4,16 @@ function testElement() {
|
||||
// Test getting element from higher dimension
|
||||
var p = new ParallelArray([2,2,2], function () { return 0; });
|
||||
var p0 = new ParallelArray([2,2], function () { return 0; });
|
||||
print("0");
|
||||
assertEqParallelArray(p.get(0), p0);
|
||||
|
||||
assertEqParallelArray(p[0], p0);
|
||||
// Should create new wrapper
|
||||
print("1");
|
||||
assertEq(p.get(0) !== p.get(0), true);
|
||||
|
||||
assertEq(p[0] !== p[0], true);
|
||||
// Test out of bounds
|
||||
print("2");
|
||||
assertEq(p.get(42), undefined);
|
||||
|
||||
assertEq(p[42], undefined);
|
||||
// Test getting element from 0-lengthed higher dimension
|
||||
var pp = new ParallelArray([0,0], function() { return 0; });
|
||||
assertEq(pp.get(2), undefined);
|
||||
assertEq(pp[2], undefined);
|
||||
var pp2 = new ParallelArray([2,0], function() { return 0; });
|
||||
assertEqParallelArray(pp2.get(0), new ParallelArray());
|
||||
assertEqParallelArray(pp2[0], new ParallelArray());
|
||||
}
|
||||
|
||||
testElement();
|
||||
|
@ -7,5 +7,4 @@ function testElement() {
|
||||
assertEq(desc.value, 9);
|
||||
}
|
||||
|
||||
// FIXME(bug 844882) self-hosted object not array-like, exposes internal properties
|
||||
// testElement();
|
||||
testElement();
|
||||
|
@ -4,5 +4,4 @@ function testEnumerate() {
|
||||
assertEq(i >= 0 && i < p.length, true);
|
||||
}
|
||||
|
||||
// FIXME(bug 844882) self-hosted object not array-like, exposes internal properties
|
||||
// testEnumerate();
|
||||
testEnumerate();
|
||||
|
14
js/src/jit-test/tests/parallelarray/filter-1.js
Normal file
14
js/src/jit-test/tests/parallelarray/filter-1.js
Normal file
@ -0,0 +1,14 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function testFilterAll() {
|
||||
// Test filtering everything (leaving everything in)
|
||||
var p = new ParallelArray([0,1,2,3,4]);
|
||||
var all = p.map(function (i) { return true; });
|
||||
var r = p.filter(all);
|
||||
assertEqParallelArray(r, p);
|
||||
var p = new ParallelArray([5,2], function(i,j) { return i+j; });
|
||||
var r = p.filter(all);
|
||||
assertEqParallelArray(r, new ParallelArray(p));
|
||||
}
|
||||
|
||||
testFilterAll();
|
14
js/src/jit-test/tests/parallelarray/filter-2.js
Normal file
14
js/src/jit-test/tests/parallelarray/filter-2.js
Normal file
@ -0,0 +1,14 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function testFilterNone() {
|
||||
// Test filtering (removing everything)
|
||||
var p = new ParallelArray([0,1,2,3,4]);
|
||||
var none = p.map(function () { return false; });
|
||||
var r = p.filter(none);
|
||||
assertEqParallelArray(r, new ParallelArray);
|
||||
var p = new ParallelArray([5,2], function(i,j) { return i+j; });
|
||||
var r = p.filter(none);
|
||||
assertEqParallelArray(r, new ParallelArray);
|
||||
}
|
||||
|
||||
testFilterNone();
|
14
js/src/jit-test/tests/parallelarray/filter-3.js
Normal file
14
js/src/jit-test/tests/parallelarray/filter-3.js
Normal file
@ -0,0 +1,14 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function testFilterSome() {
|
||||
var p = new ParallelArray([0,1,2,3,4]);
|
||||
var evenBelowThree = p.map(function (i) { return ((i%2) === 0) && (i < 3); });
|
||||
var r = p.filter(evenBelowThree);
|
||||
assertEqParallelArray(r, new ParallelArray([0,2]));
|
||||
var p = new ParallelArray([5,2], function (i,j) { return i; });
|
||||
var evenBelowThree = p.map(function (i) { return ((i[0]%2) === 0) && (i[0] < 3); });
|
||||
var r = p.filter(evenBelowThree);
|
||||
assertEqParallelArray(r, new ParallelArray([p[0], p[2]]));
|
||||
}
|
||||
|
||||
testFilterSome();
|
16
js/src/jit-test/tests/parallelarray/filter-4.js
Normal file
16
js/src/jit-test/tests/parallelarray/filter-4.js
Normal file
@ -0,0 +1,16 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function testFilterMisc() {
|
||||
var p = new ParallelArray([0,1,2]);
|
||||
// Test array
|
||||
var r = p.filter([true, false, true]);
|
||||
assertEqParallelArray(r, new ParallelArray([p[0], p[2]]));
|
||||
// Test array-like
|
||||
var r = p.filter({ 0: true, 1: false, 2: true, length: 3 });
|
||||
assertEqParallelArray(r, new ParallelArray([p[0], p[2]]));
|
||||
// Test truthy
|
||||
var r = p.filter([1, "", {}]);
|
||||
assertEqParallelArray(r, new ParallelArray([p[0], p[2]]));
|
||||
}
|
||||
|
||||
testFilterMisc();
|
@ -1,2 +0,0 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
testFilter(range(0, 1024), function() { return true; });
|
@ -1,5 +0,0 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
testFilter(range(0, 1024), function(e, i) {
|
||||
return (i % 3) != 0;
|
||||
});
|
||||
|
@ -1,6 +0,0 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
// since we divide things into chunks of 32, and filter uses some
|
||||
// bitsets, test that all that logic works fine if the number of items
|
||||
// is not evenly divisible by 32:
|
||||
testFilter(range(0, 617), function(i) { return (i % 2) == 0; });
|
@ -1,2 +0,0 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
testFilter(range(0, 1024), function() { return false; });
|
11
js/src/jit-test/tests/parallelarray/filter-throws.js
Normal file
11
js/src/jit-test/tests/parallelarray/filter-throws.js
Normal file
@ -0,0 +1,11 @@
|
||||
load(libdir + "asserts.js");
|
||||
|
||||
function testFilterThrows() {
|
||||
var p = new ParallelArray([1,2,3,4,5]);
|
||||
|
||||
assertThrowsInstanceOf(function () {
|
||||
p.filter({ length: 0xffffffff + 1 });
|
||||
}, RangeError);
|
||||
}
|
||||
|
||||
testFilterThrows();
|
@ -1,18 +0,0 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function testFilterMisc() {
|
||||
function truthy(e, i, c) {
|
||||
switch (i % 6) {
|
||||
case 0: return 1;
|
||||
case 1: return "";
|
||||
case 2: return {};
|
||||
case 3: return [];
|
||||
case 4: return false;
|
||||
case 5: return true;
|
||||
}
|
||||
}
|
||||
|
||||
testFilter(range(0, 1024), truthy);
|
||||
}
|
||||
|
||||
testFilterMisc();
|
@ -1,2 +0,0 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
testFilter(range(0, 1024), function(i) { return i <= 1 || i >= 1022; });
|
@ -1,24 +0,0 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function testFlatten() {
|
||||
var p0 = new ParallelArray([0,1]);
|
||||
var p1 = new ParallelArray([2,3]);
|
||||
var p = new ParallelArray([p0, p1]);
|
||||
var p2 = new ParallelArray([0,1,2,3]);
|
||||
assertEqParallelArray(p.flatten(), p2);
|
||||
|
||||
// Test flatten crossing packed boundary with non-shape uniform elements
|
||||
var blah = new ParallelArray([2,2], function() { return 0; });
|
||||
var pp = new ParallelArray([p0, p1, blah]);
|
||||
var p2 = new ParallelArray([0,1,2,3,blah[0],blah[1]]);
|
||||
assertEqParallelArray(pp.flatten(), p2);
|
||||
|
||||
var p0 = new ParallelArray([2,2], function() { return 1; });
|
||||
var p1 = new ParallelArray([2,2], function() { return 2; });
|
||||
var p = new ParallelArray([p0, p1]);
|
||||
var p2 = new ParallelArray([p0[0],p0[1],p1[0],p1[1]]);
|
||||
assertEqParallelArray(p.flatten(), p2);
|
||||
}
|
||||
|
||||
// FIXME(bug 844991) logical shape not implemented
|
||||
// testFlatten();
|
@ -2,7 +2,7 @@ function testGet() {
|
||||
var a = [1,2,3,4,5];
|
||||
var p = new ParallelArray(a);
|
||||
for (var i = 0; i < a.length; i++)
|
||||
assertEq(p.get(i), a[i]);
|
||||
assertEq(p.get([i]), a[i]);
|
||||
}
|
||||
|
||||
testGet();
|
||||
|
@ -2,12 +2,12 @@ load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function testGet() {
|
||||
var p = new ParallelArray([2,2,2], function(i,j,k) { return i+j+k; });
|
||||
assertEq(p.get(1,1,1), 1+1+1);
|
||||
assertEq(p.get([1,1,1]), 1+1+1);
|
||||
var p2 = new ParallelArray([2], function(i) { return 1+1+i; });
|
||||
assertEqParallelArray(p.get(1,1), p2);
|
||||
assertEqParallelArray(p.get([1,1]), p2);
|
||||
var p3 = new ParallelArray([2,2], function(i,j) { return 1+i+j; });
|
||||
assertEqParallelArray(p.get(1), p3);
|
||||
assertEq(p.get(5,5), undefined);
|
||||
assertEqParallelArray(p.get([1]), p3);
|
||||
assertEq(p.get([5,5]), undefined);
|
||||
}
|
||||
|
||||
testGet();
|
||||
|
@ -2,7 +2,7 @@ function testGetNoCraziness() {
|
||||
// .get shouldn't do prototype walks
|
||||
ParallelArray.prototype[42] = "foo";
|
||||
var p = new ParallelArray([1,2,3,4]);
|
||||
assertEq(p.get(42), undefined);
|
||||
assertEq(p.get([42]), undefined);
|
||||
}
|
||||
|
||||
testGetNoCraziness();
|
||||
|
@ -1,6 +1,6 @@
|
||||
function testGetBounds() {
|
||||
var p = new ParallelArray([1,2,3,4]);
|
||||
assertEq(p.get(42), undefined);
|
||||
assertEq(p.get([42]), undefined);
|
||||
}
|
||||
|
||||
testGetBounds();
|
||||
|
9
js/src/jit-test/tests/parallelarray/get-5.js
Normal file
9
js/src/jit-test/tests/parallelarray/get-5.js
Normal file
@ -0,0 +1,9 @@
|
||||
function testGet() {
|
||||
// Test .get on array-like
|
||||
var p = new ParallelArray([1,2,3,4]);
|
||||
assertEq(p.get({ 0: 1, length: 1 }), 2);
|
||||
var p2 = new ParallelArray([2,2], function(i,j) { return i+j; });
|
||||
assertEq(p2.get({ 0: 1, 1: 0, length: 2 }), 1);
|
||||
}
|
||||
|
||||
testGet();
|
@ -1,13 +0,0 @@
|
||||
function testGet() {
|
||||
// Test getting higher dimension inferred shape
|
||||
var p0 = new ParallelArray([0,1]);
|
||||
var p1 = new ParallelArray([2,3]);
|
||||
var p = new ParallelArray([p0, p1]);
|
||||
assertEq(p.get(0,0), 0);
|
||||
assertEq(p.get(0,1), 1);
|
||||
assertEq(p.get(1,0), 2);
|
||||
assertEq(p.get(1,1), 3);
|
||||
}
|
||||
|
||||
// FIXME(bug 844991) logical shape not implemented
|
||||
// testGet();
|
14
js/src/jit-test/tests/parallelarray/get-throws.js
Normal file
14
js/src/jit-test/tests/parallelarray/get-throws.js
Normal file
@ -0,0 +1,14 @@
|
||||
load(libdir + "asserts.js");
|
||||
|
||||
function testGetThrows() {
|
||||
// Throw if argument not object
|
||||
var p = new ParallelArray([1,2,3,4]);
|
||||
assertThrowsInstanceOf(function () { p.get(42); }, TypeError);
|
||||
assertThrowsInstanceOf(function () { p.get(.42); }, TypeError);
|
||||
var p = new ParallelArray([2,2], function (i,j) { return i+j; });
|
||||
assertThrowsInstanceOf(function () {
|
||||
p.get({ 0: 1, 1: 0, testGet: 2 });
|
||||
}, TypeError);
|
||||
}
|
||||
|
||||
testGetThrows();
|
@ -7,23 +7,23 @@ function testHoles() {
|
||||
// force the VM to call a conversion function, which will crash if the value
|
||||
// we got out is a JS_ARRAY_HOLE.
|
||||
var p = new ParallelArray([,1]);
|
||||
assertEq(p.get(0) * 42, NaN);
|
||||
assertEq(p[0] * 42, NaN);
|
||||
var m = p.map(f1);
|
||||
assertEq(m.get(0), NaN);
|
||||
assertEq(m.get(1), 42);
|
||||
assertEq(m[0], NaN);
|
||||
assertEq(m[1], 42);
|
||||
var r = p.reduce(f2);
|
||||
assertEq(r, NaN);
|
||||
var s = p.scan(f2);
|
||||
assertEq(s.get(0) * 42, NaN);
|
||||
assertEq(s.get(1), NaN);
|
||||
assertEq(s[0] * 42, NaN);
|
||||
assertEq(s[1], NaN);
|
||||
var k = p.scatter([1,0]);
|
||||
assertEq(k.get(0), 1);
|
||||
assertEq(k[0], 1);
|
||||
assertEq(k[1] * 42, NaN);
|
||||
var l = p.filter(function (e, i) { return i == 0; });
|
||||
assertEq(l.get(0) * 42, NaN);
|
||||
var l = p.filter([1,0]);
|
||||
assertEq(l[0] * 42, NaN);
|
||||
var p2 = p.partition(1);
|
||||
assertEq(p2.get(0).get(0) * 42, NaN);
|
||||
var g = p.get(0);
|
||||
assertEq(p2[0][0] * 42, NaN);
|
||||
var g = p.get([0]);
|
||||
assertEq(g * 42, NaN);
|
||||
}
|
||||
|
||||
|
@ -20,5 +20,4 @@ function testElement() {
|
||||
assertEq(p2[0], undefined);
|
||||
}
|
||||
|
||||
// FIXME(bug 844882) self-hosted object not array-like, exposes internal properties
|
||||
// testElement();
|
||||
testElement();
|
||||
|
@ -1,8 +0,0 @@
|
||||
function test() {
|
||||
var N = 22;
|
||||
var p = new ParallelArray([N], function(i) { return i; });
|
||||
for (var i = 0; i < N; i++)
|
||||
assertEq(p.get(i), i);
|
||||
}
|
||||
|
||||
test();
|
@ -1,17 +0,0 @@
|
||||
function test() {
|
||||
function mk(i, j) { return i*100+j; }
|
||||
|
||||
var N = 22;
|
||||
var M = 44;
|
||||
|
||||
var p = new ParallelArray([N,M], mk);
|
||||
for (var i = 0; i < N; i++) {
|
||||
for (var j = 0; j < M; j++) {
|
||||
print([i, j]);
|
||||
assertEq(p.get(i, j), mk(i, j));
|
||||
assertEq(p.get(i).get(j), mk(i, j));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
test();
|
@ -1,24 +0,0 @@
|
||||
function test() {
|
||||
function mk(i, j, k) { return i*10000+j*100+k; }
|
||||
|
||||
var N = 10;
|
||||
var M = 20;
|
||||
var O = 30;
|
||||
|
||||
print("Computing");
|
||||
var p = new ParallelArray([N,M,O], mk);
|
||||
|
||||
print("Checking");
|
||||
for (var i = 0; i < N; i++) {
|
||||
for (var j = 0; j < M; j++) {
|
||||
for (var k = 0; k < O; k++) {
|
||||
assertEq(p.get(i, j, k), mk(i, j, k));
|
||||
assertEq(p.get(i, j).get(k), mk(i, j, k));
|
||||
assertEq(p.get(i).get(j).get(k), mk(i, j, k));
|
||||
assertEq(p.get(i).get(j, k), mk(i, j, k));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
test();
|
@ -1,26 +0,0 @@
|
||||
function test() {
|
||||
function mk(i, j, k, l) { return i*1000000+j*10000+k*100+l; }
|
||||
|
||||
var N = 2;
|
||||
var M = 4;
|
||||
var O = 6;
|
||||
var P = 8;
|
||||
|
||||
print("Computing");
|
||||
var p = new ParallelArray([N,M,O,P], mk);
|
||||
|
||||
print("Checking");
|
||||
for (var i = 0; i < N; i++) {
|
||||
for (var j = 0; j < M; j++) {
|
||||
for (var k = 0; k < O; k++) {
|
||||
for (var l = 0; l < P; l++) {
|
||||
assertEq(p.get(i, j, k, l), mk(i, j, k, l));
|
||||
assertEq(p.get(i, j).get(k, l), mk(i, j, k, l));
|
||||
assertEq(p.get(i).get(j).get(k).get(l), mk(i, j, k, l));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
test();
|
@ -6,5 +6,4 @@ function testLength() {
|
||||
assertEq(p.length, 4);
|
||||
}
|
||||
|
||||
// FIXME(bug 844988) immutability not enforced
|
||||
// testLength();
|
||||
testLength();
|
||||
|
@ -1,49 +0,0 @@
|
||||
// Adapted from
|
||||
//
|
||||
// https://github.com/RiverTrail/RiverTrail/blob/master/examples/mandelbrot/mandelbrot.js
|
||||
//
|
||||
// which in turn is adapted from a WebCL implementation available at
|
||||
//
|
||||
// http://www.ibiblio.org/e-notes/webcl/mandelbrot.html
|
||||
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
var nc = 30, maxCol = nc*3;
|
||||
|
||||
// this is the actual mandelbrot computation, ported to JavaScript
|
||||
// from the WebCL / OpenCL example at
|
||||
// http://www.ibiblio.org/e-notes/webcl/mandelbrot.html
|
||||
function computeSetByRow(x, y) {
|
||||
var Cr = (x - 256) / scale + 0.407476;
|
||||
var Ci = (y - 256) / scale + 0.234204;
|
||||
var I = 0, R = 0, I2 = 0, R2 = 0;
|
||||
var n = 0;
|
||||
while ((R2+I2 < 2.0) && (n < 512)) {
|
||||
I = (R+R)*I+Ci;
|
||||
R = R2-I2+Cr;
|
||||
R2 = R*R;
|
||||
I2 = I*I;
|
||||
n++;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
function computeSequentially() {
|
||||
result = [];
|
||||
for (var r = 0; r < rows; r++) {
|
||||
for (var c = 0; c < cols; c++) {
|
||||
result.push(computeSetByRow(r, c));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
var scale = 10000*300;
|
||||
var rows = 4;
|
||||
var cols = 4;
|
||||
|
||||
// check that we get correct result
|
||||
assertParallelArrayModesEq(["seq", "par"], computeSequentially(), function(m) {
|
||||
r = new ParallelArray([rows, cols], computeSetByRow);
|
||||
return r.flatten();
|
||||
});
|
10
js/src/jit-test/tests/parallelarray/map-1.js
Normal file
10
js/src/jit-test/tests/parallelarray/map-1.js
Normal file
@ -0,0 +1,10 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function testMap() {
|
||||
var p = new ParallelArray([0,1,2,3,4]);
|
||||
var m = p.map(function (v) { return v+1; });
|
||||
var p2 = new ParallelArray([1,2,3,4,5]);
|
||||
assertEqParallelArray(m, p2);
|
||||
}
|
||||
|
||||
testMap();
|
@ -2,7 +2,7 @@ function testMap() {
|
||||
// Test overflow
|
||||
var p = new ParallelArray([1 << 30]);
|
||||
var m = p.map(function(x) { return x * 4; });
|
||||
assertEq(m.get(0), (1 << 30) * 4);
|
||||
assertEq(m[0], (1 << 30) * 4);
|
||||
}
|
||||
|
||||
testMap();
|
||||
|
@ -4,7 +4,7 @@ function testMap() {
|
||||
// Test mapping higher dimensional
|
||||
var p = new ParallelArray([2,2], function (i,j) { return i+j; });
|
||||
var m = p.map(function(x) { return x; });
|
||||
var p2 = new ParallelArray(p.shape[0], function (i) { return p.get(i); });
|
||||
var p2 = new ParallelArray(p);
|
||||
assertEqParallelArray(m, p2);
|
||||
}
|
||||
|
||||
|
@ -1,12 +0,0 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
var SIZE = 4096;
|
||||
|
||||
function testMap() {
|
||||
var q = {f: 22};
|
||||
compareAgainstArray(range(0, SIZE), "map", function(e) {
|
||||
return e + q.f;
|
||||
});
|
||||
}
|
||||
|
||||
testMap();
|
@ -1,9 +0,0 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function factorial(n) {
|
||||
if (n == 0)
|
||||
return 1;
|
||||
return n * factorial(n - 1);
|
||||
}
|
||||
|
||||
compareAgainstArray(range(0, 64), "map", factorial);
|
@ -1,3 +0,0 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
compareAgainstArray(range(0, 512), "map", function(e) { return e+1; });
|
@ -1,16 +0,0 @@
|
||||
// |jit-test| error: Error;
|
||||
|
||||
// This test tests the mode assertions. It provides a function which
|
||||
// should successfully execute and specifies that it should fail. We
|
||||
// expect an exception to result.
|
||||
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function testMap() {
|
||||
var p = new ParallelArray(range(0, 64));
|
||||
var m = p.map(function (v) { return v+1; }, { mode: "par", expect: "fail" });
|
||||
assertEqParallelArray(m, new ParallelArray(range(1, 64)));
|
||||
}
|
||||
|
||||
testMap();
|
||||
|
@ -1,17 +0,0 @@
|
||||
load(libdir + "parallelarray-helpers.js")
|
||||
|
||||
function test() {
|
||||
var pa0 = new ParallelArray(range(0, 256));
|
||||
var pa1 = new ParallelArray(256, function (x) {
|
||||
return pa0.map(function(y) { return x * 1000 + y; });
|
||||
}, {mode: "par", expect: "success"});
|
||||
|
||||
for (var x = 0; x < 256; x++) {
|
||||
var pax = pa1.get(x);
|
||||
for (var y = 0; y < 256; y++) {
|
||||
assertEq(pax.get(y), x * 1000 + y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
test();
|
@ -1,9 +0,0 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function wrapInObject(v) {
|
||||
var obj = {f: 2};
|
||||
obj.f += v;
|
||||
return obj;
|
||||
}
|
||||
|
||||
compareAgainstArray(range(0, 64), "map", wrapInObject);
|
@ -1,11 +0,0 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function test() {
|
||||
// Test what happens if the length of the array is very short (i.e.,
|
||||
// less than the number of cores). There used to be a bug in this
|
||||
// case that led to crashes or other undefined behavior.
|
||||
var makeadd1 = function (v) { return [v]; }
|
||||
compareAgainstArray(range(1, 3), "map", makeadd1);
|
||||
}
|
||||
|
||||
test();
|
@ -1,20 +0,0 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function test() {
|
||||
var array1 = range(0, 512);
|
||||
var array2 = build(512, function(i) {
|
||||
return i*1000000 + array1.reduce(sum);
|
||||
});
|
||||
|
||||
|
||||
var parray1 = new ParallelArray(array1);
|
||||
var parray2 = new ParallelArray(512, function(i) {
|
||||
return i*1000000 + parray1.reduce(sum);
|
||||
});
|
||||
|
||||
assertStructuralEq(array2, parray2);
|
||||
|
||||
function sum(a, b) { return a+b; }
|
||||
}
|
||||
|
||||
test();
|
@ -7,9 +7,9 @@ function testPartition() {
|
||||
var ppShape = [p.shape[0] / 2, 2].concat(p.shape.slice(1));
|
||||
var pppShape = [pp.shape[0] / 2, 2].concat(pp.shape.slice(1));
|
||||
assertEqArray(pp.shape, ppShape);
|
||||
assertEq(pp.toString(), "<1,2>,<3,4>,<5,6>,<7,8>");
|
||||
assertEq(pp.toString(), "<<1,2>,<3,4>,<5,6>,<7,8>>");
|
||||
assertEqArray(ppp.shape, pppShape);
|
||||
assertEq(ppp.toString(), "<<1,2>,<3,4>>,<<5,6>,<7,8>>");
|
||||
assertEq(ppp.toString(), "<<<1,2>,<3,4>>,<<5,6>,<7,8>>>");
|
||||
}
|
||||
|
||||
testPartition();
|
||||
|
8
js/src/jit-test/tests/parallelarray/reduce-1.js
Normal file
8
js/src/jit-test/tests/parallelarray/reduce-1.js
Normal file
@ -0,0 +1,8 @@
|
||||
|
||||
function testReduce() {
|
||||
var p = new ParallelArray([1,2,3,4,5]);
|
||||
var r = p.reduce(function (v, p) { return v*p; });
|
||||
assertEq(r, 120);
|
||||
}
|
||||
|
||||
testReduce();
|
8
js/src/jit-test/tests/parallelarray/reduce-2.js
Normal file
8
js/src/jit-test/tests/parallelarray/reduce-2.js
Normal file
@ -0,0 +1,8 @@
|
||||
|
||||
function testReduceOne() {
|
||||
var p = new ParallelArray([1]);
|
||||
var r = p.reduce(function (v, p) { return v*p; });
|
||||
assertEq(r, 1);
|
||||
}
|
||||
|
||||
testReduceOne();
|
@ -1,31 +0,0 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
// Tests that reduce saves its intermediate state correctly by
|
||||
// inducing a bailout in the middle of the reduction. This test may
|
||||
// fail to test what it is intended to test if the wrong number of
|
||||
// worker threads etc are present. It reproduced an existing bug when
|
||||
// used with 8 worker threads.
|
||||
|
||||
function testReduce() {
|
||||
var aCounter = 0;
|
||||
function sum(a, b) {
|
||||
var r = a + b;
|
||||
if (r == 234) // occurs once per slice
|
||||
aCounter++;
|
||||
return r;
|
||||
}
|
||||
|
||||
var array = build(4096, function() { return 1; });
|
||||
var seqResult = array.reduce(sum);
|
||||
var seqCounter = aCounter;
|
||||
|
||||
aCounter = 0;
|
||||
var parray = new ParallelArray(array);
|
||||
var parResult = parray.reduce(sum);
|
||||
var parCounter = aCounter;
|
||||
|
||||
assertEq(true, parCounter >= seqCounter);
|
||||
assertStructuralEq(parResult, seqResult);
|
||||
}
|
||||
|
||||
testReduce();
|
@ -1,15 +1,13 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function testReduce() {
|
||||
// Test reduce elemental fun args
|
||||
var N = 64;
|
||||
var p = new ParallelArray(range(1, N+1));
|
||||
var p = new ParallelArray([1,2,3,4]);
|
||||
var r = p.reduce(function (a, b) {
|
||||
assertEq(a >= 1 && a <= N, true);
|
||||
assertEq(b >= 1 && b <= N, true);
|
||||
assertEq(a >= 1 && a <= 4, true);
|
||||
assertEq(b >= 1 && b <= 4, true);
|
||||
return a;
|
||||
});
|
||||
assertEq(r >= 1 && r <= N, true);
|
||||
assertEq(r >= 1 && r <= 4, true);
|
||||
}
|
||||
|
||||
testReduce();
|
||||
|
@ -1,9 +0,0 @@
|
||||
function testReduceOne() {
|
||||
// Note: parallel execution with only 1 element will generally
|
||||
// bailout, so don't use assertParallelArrayModesEq() here.
|
||||
var p = new ParallelArray([1]);
|
||||
var r = p.reduce(function (v, p) { return v*p; });
|
||||
assertEq(r, 1);
|
||||
}
|
||||
|
||||
testReduceOne();
|
@ -1,26 +0,0 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function testReduce() {
|
||||
// This test is interesting because during warmup v*p remains an
|
||||
// integer but this ceases to be true once real execution proceeds.
|
||||
// By the end, it will just be some double value.
|
||||
|
||||
function mul(v, p) { return v*p; }
|
||||
|
||||
// Ensure that the array only contains values between 1 and 4.
|
||||
var array = range(1, 513).map(function(v) { return (v % 4) + 1; });
|
||||
var expected = array.reduce(mul);
|
||||
print(expected);
|
||||
|
||||
var parray = new ParallelArray(array);
|
||||
var results = ["success", "mixed", "success", "success"];
|
||||
var actual;
|
||||
for (var i = 0; i < results.length; i++) {
|
||||
print("Iteration ", i, " expects ", results[i]);
|
||||
actual = parray.reduce(mul, {mode: "par", expect: results[i]});
|
||||
}
|
||||
|
||||
assertAlmostEq(actual, expected);
|
||||
}
|
||||
|
||||
testReduce();
|
@ -1,22 +0,0 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function testReduce() {
|
||||
// This test is interesting because during warmup v*p remains an
|
||||
// integer but this ceases to be true once real execution proceeds.
|
||||
// By the end, it will just be infinity.
|
||||
function mul(v, p) { return v*p; }
|
||||
|
||||
var array = range(1, 513);
|
||||
var expected = array.reduce(mul);
|
||||
var parray = new ParallelArray(array);
|
||||
var modes = ["seq", "par"];
|
||||
for (var i = 0; i < 2; i++) {
|
||||
assertAlmostEq(expected, parray.reduce(mul, {mode: modes[i], expect: "success"}));
|
||||
}
|
||||
// assertParallelArrayModesEq(["seq", "par"], expected, function(m) {
|
||||
// d = parray.reduce(sum, m);
|
||||
// return d;
|
||||
// });
|
||||
}
|
||||
|
||||
testReduce();
|
@ -1,8 +0,0 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
|
||||
function testReduce() {
|
||||
function sum(v, p) { return v+p; }
|
||||
compareAgainstArray(range(1, 513), "reduce", sum);
|
||||
}
|
||||
|
||||
testReduce();
|
@ -13,5 +13,4 @@ function testReduceThrows() {
|
||||
}, TypeError);
|
||||
}
|
||||
|
||||
// FIXME(bug 844886) sanity check argument types
|
||||
// testReduceThrows();
|
||||
testReduceThrows();
|
||||
|
@ -1,3 +1,13 @@
|
||||
load(libdir + "parallelarray-helpers.js");
|
||||
function sum(a, b) { return a+b; }
|
||||
testScan(range(1, 1024), sum);
|
||||
|
||||
function testScan() {
|
||||
function f(v, p) { return v*p; }
|
||||
var a = [1,2,3,4,5];
|
||||
var p = new ParallelArray(a);
|
||||
var s = p.scan(f);
|
||||
for (var i = 0; i < p.length; i++) {
|
||||
var p2 = new ParallelArray(a.slice(0, i+1));
|
||||
assertEq(s[i], p2.reduce(f));
|
||||
}
|
||||
}
|
||||
|
||||
testScan();
|
||||
|
@ -1,9 +1,9 @@
|
||||
|
||||
function testScanOne() {
|
||||
function f(v, p) { throw "This should never be called."; }
|
||||
function f(v, p) { return v*p; }
|
||||
var p = new ParallelArray([1]);
|
||||
var s = p.scan(f);
|
||||
assertEq(s.get(0), 1);
|
||||
assertEq(s.get(0), p.reduce(f));
|
||||
assertEq(s[0], p.reduce(f));
|
||||
}
|
||||
|
||||
testScanOne();
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user