Backed out changeset e7f298d7b17b (bug 829602) for frequent B2G mochitest crashes on a CLOSED TREE.

This commit is contained in:
Ryan VanderMeulen 2013-03-11 17:24:31 -04:00
parent f735930263
commit 100806930b
140 changed files with 2900 additions and 3632 deletions

View File

@ -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 := \

View 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

View File

@ -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

View File

@ -37,7 +37,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;

View File

@ -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)

View File

@ -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;

View File

@ -2195,50 +2195,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>
{
@ -2312,32 +2268,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)
{

View File

@ -98,8 +98,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);

View File

@ -2099,17 +2099,8 @@ ion::Invalidate(types::TypeCompartment &types, FreeOp *fop,
co.invalidate();
// Wait for the scripts to get warm again before doing another
// compile, unless either:
// (1) we are recompiling *because* a script got hot;
// (resetUses is false); or,
// (2) we are invalidating a parallel script. This is because
// the useCount only applies to sequential uses. Parallel
// execution *requires* ion, and so we don't limit it to
// methods with a high usage count (though we do check that
// the useCount is at least 1 when compiling the transitive
// closure of potential callees, to avoid compiling things
// that are never run at all).
if (resetUses && executionMode != ParallelExecution)
// compile, unless we are recompiling *because* a script got hot.
if (resetUses)
script->resetUseCount();
}
}

View File

@ -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);

View File

@ -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)
{

View File

@ -1077,10 +1077,6 @@ class MNewParallelArray : public MNullaryInstruction
return new MNewParallelArray(templateObject);
}
AliasSet getAliasSet() const {
return AliasSet::None();
}
JSObject *templateObject() const {
return templateObject_;
}

View File

@ -266,21 +266,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)
{

View File

@ -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);

View File

@ -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);
}

View File

@ -1,3 +1,5 @@
// |jit-test| error:Error
// Binary: cache/js-dbg-64-50177d59c0e1-linux
// Flags:
//

View File

@ -1,3 +1,5 @@
// |jit-test| error:TypeError
// Binary: cache/js-dbg-64-c676b554c7bb-linux
// Flags:
//

View File

@ -1,3 +1,5 @@
// |jit-test| error:TypeError
// Binary: cache/js-dbg-64-5d63594c05a9-linux
// Flags:
//

View File

@ -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();

View File

@ -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();

View File

@ -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();

View File

@ -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();

View File

@ -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();

View File

@ -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.index;
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();

View File

@ -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);

View File

@ -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();

View File

@ -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();

View File

@ -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();

View File

@ -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();

View File

@ -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();

View File

@ -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();

View File

@ -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();

View File

@ -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();

View File

@ -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"; });

View File

@ -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"; });

View File

@ -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();

View File

@ -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();

View File

@ -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);
}

View File

@ -22,5 +22,4 @@ function buildComprehension() {
}, RangeError);
}
// FIXME(bug 844887) throw correct exception
// buildComprehension();
buildComprehension();

View File

@ -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();

View File

@ -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();

View File

@ -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();

View File

@ -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();

View File

@ -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);

View File

@ -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();

View File

@ -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();

View File

@ -7,5 +7,4 @@ function testElement() {
assertEq(desc.value, 9);
}
// FIXME(bug 844882) self-hosted object not array-like, exposes internal properties
// testElement();
testElement();

View File

@ -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();

View 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();

View 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();

View 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();

View 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();

View File

@ -1,2 +0,0 @@
load(libdir + "parallelarray-helpers.js");
testFilter(range(0, 1024), function() { return true; });

View File

@ -1,5 +0,0 @@
load(libdir + "parallelarray-helpers.js");
testFilter(range(0, 1024), function(e, i) {
return (i % 3) != 0;
});

View File

@ -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; });

View File

@ -1,2 +0,0 @@
load(libdir + "parallelarray-helpers.js");
testFilter(range(0, 1024), function() { return false; });

View 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();

View File

@ -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();

View File

@ -1,2 +0,0 @@
load(libdir + "parallelarray-helpers.js");
testFilter(range(0, 1024), function(i) { return i <= 1 || i >= 1022; });

View File

@ -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();

View File

@ -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();

View File

@ -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();

View File

@ -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();

View File

@ -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();

View 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();

View File

@ -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();

View 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();

View File

@ -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);
}

View File

@ -20,5 +20,4 @@ function testElement() {
assertEq(p2[0], undefined);
}
// FIXME(bug 844882) self-hosted object not array-like, exposes internal properties
// testElement();
testElement();

View File

@ -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();

View File

@ -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();

View File

@ -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();

View File

@ -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();

View File

@ -6,5 +6,4 @@ function testLength() {
assertEq(p.length, 4);
}
// FIXME(bug 844988) immutability not enforced
// testLength();
testLength();

View File

@ -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();
});

View 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();

View File

@ -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();

View File

@ -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);
}

View File

@ -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();

View File

@ -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);

View File

@ -1,3 +0,0 @@
load(libdir + "parallelarray-helpers.js");
compareAgainstArray(range(0, 512), "map", function(e) { return e+1; });

View File

@ -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();

View File

@ -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();

View File

@ -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);

View File

@ -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();

View File

@ -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();

View File

@ -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();

View 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();

View 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();

View File

@ -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();

View File

@ -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();

View File

@ -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();

View File

@ -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();

View File

@ -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();

View File

@ -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();

View File

@ -13,5 +13,4 @@ function testReduceThrows() {
}, TypeError);
}
// FIXME(bug 844886) sanity check argument types
// testReduceThrows();
testReduceThrows();

View File

@ -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();

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