Created
July 16, 2012 23:42
-
-
Save nikomatsakis/3125873 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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