Skip to content

Instantly share code, notes, and snippets.

@nikomatsakis
Created July 16, 2012 23:42
Show Gist options
  • Save nikomatsakis/3125873 to your computer and use it in GitHub Desktop.
Save nikomatsakis/3125873 to your computer and use it in GitHub Desktop.
diff --git a/js/src/builtin/ParallelArray.cpp b/js/src/builtin/ParallelArray.cpp
--- a/js/src/builtin/ParallelArray.cpp
+++ b/js/src/builtin/ParallelArray.cpp
@@ -18,16 +18,18 @@
*
* The Initial Developer of the Original Code is
* Intel Corporation
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Stephan Herhut <[email protected]>
+ * Niko Matsakis <[email protected]>
+ * Shu-yu Guo <[email protected]>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
@@ -170,45 +172,82 @@ SequentialBuild(JSContext *cx, uint32_t
static bool
ParallelBuild(JSContext *cx, uint32_t length, const Value &thisv, JSObject *elementalFun,
bool passElement, unsigned numExtras, Value *extras,
HandleObject srcBuffer, HandleObject buffer)
{
if (!ion::IsEnabled(cx))
return false;
- // The array needs to be homogeneous on a numeric type.
- AutoEnterTypeInference enter(cx);
- JSValueType type = ElementTypeTag(cx, &thisv.toObject());
- if (type != JSVAL_TYPE_INT32 && type != JSVAL_TYPE_DOUBLE)
- return false;
+ ion::MethodStatus status;
- // The kernel should be a function.
- if (!elementalFun->isFunction())
- return false;
+ {
+ // The array needs to be homogeneous on a numeric type.
+ AutoEnterTypeInference enter(cx);
+ JSValueType type = ElementTypeTag(cx, &thisv.toObject());
+ if (type != JSVAL_TYPE_INT32 && type != JSVAL_TYPE_DOUBLE)
+ return false;
- RootedFunction fun(cx, elementalFun->toFunction());
- if (!fun->isInterpreted())
- return false;
+ // The kernel should be a function.
+ if (!elementalFun->isFunction())
+ return false;
- // Ensure that the function is analyzed by TI.
- JSScript *script = fun->script();
+ RootedFunction fun(cx, elementalFun->toFunction());
+ if (!fun->isInterpreted())
+ return false;
- if (!script->ensureRanAnalysis(cx, fun->environment()))
- return false;
+ // Ensure that the function is analyzed by TI.
+ JSScript *script = fun->script();
- TypeScript::SetThis(cx, script, thisv);
- TypeScript::SetArgument(cx, script, 0, passElement ? srcBuffer->getDenseArrayElement(0) : Int32Value(0));
- for (unsigned i = 0; i < numExtras; i++)
- TypeScript::SetArgument(cx, script, i + 1, extras[i]);
+ if (!script->ensureRanAnalysis(cx, fun->environment()))
+ return false;
- // Try to compile the kernel.
- ion::MethodStatus status = ion::CanEnterParallelArrayKernel(cx, fun, numExtras + 1);
+ TypeScript::SetThis(cx, script, thisv);
+ TypeScript::SetArgument(cx, script, 0, passElement ? srcBuffer->getDenseArrayElement(0) : Int32Value(0));
+ for (unsigned i = 0; i < numExtras; i++)
+ TypeScript::SetArgument(cx, script, i + 1, extras[i]);
+
+ // Try to compile the kernel.
+ status = ion::CanEnterParallelArrayKernel(cx, fun, numExtras + 1);
+ }
+
if (status == ion::Method_Compiled) {
- // TODO: Spawn threads or something.
+ /* prepare call frame on stack */
+ InvokeArgsGuard args;
+ if (!cx->stack.pushInvokeArgs(cx, numExtras + 1, &args))
+ return false;
+
+ for (uint32_t i = 0; i < length; i++) {
+ /* set callee */
+ args.setCallee(ObjectValue(*elementalFun));
+
+ /* set value of this */
+ args.thisv() = thisv;
+
+ if (passElement)
+ args[0] = srcBuffer->getDenseArrayElement(i);
+ else
+ args[0].setNumber(i);
+
+ /* set extra arguments */
+ for (unsigned j = 0; j < numExtras; j++) {
+ args[j + 1] = extras[j];
+ }
+
+ /* call */
+ InvokeFrameGuard ifg;
+ if (!cx->stack.pushInvokeFrame(cx, args, (InitialFrameFlags)NO_CONSTRUCT, &ifg))
+ return false;
+ if (ion::Cannon(cx, ifg.fp()) != ion::IonExec_Ok)
+ return false;
+
+ /* set result element */
+ buffer->setDenseArrayElementWithType(cx, i, args.rval());
+ }
+
return true;
}
return false;
}
static JSBool
ParallelArray_build(JSContext *cx, uint32_t length, const Value &thisv, JSObject *elementalFun,
diff --git a/js/src/ion/Ion.cpp b/js/src/ion/Ion.cpp
--- a/js/src/ion/Ion.cpp
+++ b/js/src/ion/Ion.cpp
@@ -885,17 +885,17 @@ ParallelArrayKernelCompiler(IonBuilder &
if (!CanCompileParallelArrayKernel(graph))
return false;
if (!GenerateCode(builder, graph))
return false;
IonSpewEndFunction();
- return false;
+ return true;
}
template <bool Compiler(IonBuilder &, MIRGraph &)>
static bool
IonCompile(JSContext *cx, JSScript *script, JSFunction *fun, jsbytecode *osrPc)
{
TempAllocator temp(&cx->tempLifoAlloc());
IonContext ictx(cx, &temp);
diff --git a/js/src/ion/ParallelArrayAnalysis.cpp b/js/src/ion/ParallelArrayAnalysis.cpp
--- a/js/src/ion/ParallelArrayAnalysis.cpp
+++ b/js/src/ion/ParallelArrayAnalysis.cpp
@@ -77,29 +77,29 @@ class ParallelArrayVisitor : public MIns
SAFE_OP(Mul)
SAFE_OP(Div)
SAFE_OP(Mod)
SAFE_OP(Concat)
SAFE_OP(CharCodeAt)
SAFE_OP(FromCharCode)
SAFE_OP(Return)
UNSAFE_OP(Throw)
- UNSAFE_OP(Box)
- UNSAFE_OP(Unbox)
+ SAFE_OP(Box) // Boxing just creates a JSVal, doesn't alloc.
+ SAFE_OP(Unbox)
UNSAFE_OP(GuardObject)
SAFE_OP(ToDouble)
SAFE_OP(ToInt32)
SAFE_OP(TruncateToInt32)
UNSAFE_OP(ToString)
UNSAFE_OP(NewSlots)
UNSAFE_OP(NewArray)
UNSAFE_OP(NewObject)
UNSAFE_OP(NewCallObject)
UNSAFE_OP(InitProp)
- UNSAFE_OP(Start)
+ SAFE_OP(Start)
UNSAFE_OP(OsrEntry)
UNSAFE_OP(RegExp)
UNSAFE_OP(Lambda)
UNSAFE_OP(ImplicitThis)
UNSAFE_OP(Slots)
UNSAFE_OP(Elements)
UNSAFE_OP(ConstantElements)
SAFE_OP(LoadSlot)
@@ -160,21 +160,21 @@ ion::CanCompileParallelArrayKernel(MIRGr
for (MBasicBlockIterator block(graph.begin()); block != graph.end(); block++) {
for (MInstructionIterator instr(block->begin()); instr != block->end(); instr++) {
instr->accept(&visitor);
}
}
if (!visitor.IsSafe()) {
IonSpew(IonSpew_ParallelArray, "ParallelArray invoked with unsafe fn!\n");
+ return false;
} else {
IonSpew(IonSpew_ParallelArray, "ParallelArray invoked with safe fn\n");
+ return true;
}
-
- return false;
}
bool
ParallelArrayVisitor::visitTest(MTest *) {
return true;
}
bool
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment