Created
August 8, 2012 01:31
-
-
Save nikomatsakis/3291232 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/ion/Bailouts.h b/js/src/ion/Bailouts.h | |
--- a/js/src/ion/Bailouts.h | |
+++ b/js/src/ion/Bailouts.h | |
@@ -102,16 +102,17 @@ static const uint32 BAILOUT_TABLE_SIZE = | |
static const uint32 BAILOUT_RETURN_OK = 0; | |
static const uint32 BAILOUT_RETURN_FATAL_ERROR = 1; | |
static const uint32 BAILOUT_RETURN_ARGUMENT_CHECK = 2; | |
static const uint32 BAILOUT_RETURN_TYPE_BARRIER = 3; | |
static const uint32 BAILOUT_RETURN_MONITOR = 4; | |
static const uint32 BAILOUT_RETURN_RECOMPILE_CHECK = 5; | |
static const uint32 BAILOUT_RETURN_BOUNDS_CHECK = 6; | |
static const uint32 BAILOUT_RETURN_INVALIDATE = 7; | |
+static const uint32 BAILOUT_RETURN_PARALLEL = 8; | |
// Attached to the compartment for easy passing through from ::Bailout to | |
// ::ThunkToInterpreter. | |
class BailoutClosure | |
{ | |
// These class are used to control the stack usage and the order of | |
// declaration is used by the destructor to restore the stack in the | |
// expected order when classes are created. This class is only created | |
diff --git a/js/src/ion/CompileInfo.h b/js/src/ion/CompileInfo.h | |
--- a/js/src/ion/CompileInfo.h | |
+++ b/js/src/ion/CompileInfo.h | |
@@ -16,18 +16,29 @@ CountArgSlots(JSFunction *fun) | |
{ | |
return fun ? fun->nargs + 2 : 1; // +2 for |scopeChain| and |this|, or +1 for |scopeChain| | |
} | |
// Contains information about the compilation source for IR being generated. | |
class CompileInfo | |
{ | |
public: | |
- CompileInfo(JSScript *script, JSFunction *fun, jsbytecode *osrPc, bool constructing) | |
- : script_(script), fun_(fun), osrPc_(osrPc), constructing_(constructing) | |
+ enum CompileMode { | |
+ // Normal compilation: code will always execute sequentially | |
+ COMPILE_SEQ, | |
+ | |
+ // Parallel compilation: code will execute in parallel | |
+ // e.g., Rivertrail | |
+ COMPILE_PAR | |
+ }; | |
+ | |
+ CompileInfo(JSScript *script, JSFunction *fun, jsbytecode *osrPc, bool constructing, | |
+ CompileMode compileMode) | |
+ : script_(script), fun_(fun), osrPc_(osrPc), constructing_(constructing), | |
+ compileMode_(compileMode) | |
{ | |
JS_ASSERT_IF(osrPc, JSOp(*osrPc) == JSOP_LOOPENTRY); | |
nslots_ = script->nslots + CountArgSlots(fun); | |
} | |
JSScript *script() const { | |
return script_; | |
} | |
@@ -128,20 +139,29 @@ class CompileInfo | |
uint32 stackSlot(uint32 i) const { | |
return firstStackSlot() + i; | |
} | |
bool hasArguments() { | |
return script()->argumentsHasVarBinding(); | |
} | |
+ CompileMode compileMode() const { | |
+ return compileMode_; | |
+ } | |
+ | |
+ bool isParallelCompilation() const { | |
+ return compileMode_ == COMPILE_PAR; | |
+ } | |
+ | |
private: | |
JSScript *script_; | |
JSFunction *fun_; | |
unsigned nslots_; | |
jsbytecode *osrPc_; | |
bool constructing_; | |
+ CompileMode compileMode_; | |
}; | |
} // namespace ion | |
} // namespace js | |
#endif | |
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 | |
@@ -858,26 +858,28 @@ ParallelArrayKernelCompiler(IonBuilder & | |
IonSpewEndFunction(); | |
return true; | |
} | |
template <bool Compiler(IonBuilder &, MIRGraph &)> | |
static bool | |
-IonCompile(JSContext *cx, JSScript *script, JSFunction *fun, jsbytecode *osrPc, bool constructing) | |
+IonCompile(JSContext *cx, JSScript *script, JSFunction *fun, jsbytecode *osrPc, | |
+ bool constructing, CompileInfo::CompileMode compileMode) | |
{ | |
TempAllocator temp(&cx->tempLifoAlloc()); | |
IonContext ictx(cx, cx->compartment, &temp); | |
if (!cx->compartment->ensureIonCompartmentExists(cx)) | |
return false; | |
MIRGraph graph(&temp); | |
- CompileInfo *info = cx->tempLifoAlloc().new_<CompileInfo>(script, fun, osrPc, constructing); | |
+ CompileInfo *info = cx->tempLifoAlloc().new_<CompileInfo>(script, fun, osrPc, constructing, | |
+ compileMode); | |
if (!info) | |
return false; | |
types::AutoEnterTypeInference enter(cx, true); | |
TypeInferenceOracle oracle; | |
if (!oracle.init(cx, script)) | |
return false; | |
@@ -967,17 +969,18 @@ CheckScriptSize(JSScript *script) | |
return false; | |
} | |
return true; | |
} | |
template <bool Compiler(IonBuilder &, MIRGraph &)> | |
static MethodStatus | |
-Compile(JSContext *cx, JSScript *script, JSFunction *fun, jsbytecode *osrPc, bool constructing) | |
+Compile(JSContext *cx, JSScript *script, JSFunction *fun, jsbytecode *osrPc, bool constructing, | |
+ CompileInfo::CompileMode compileMode) | |
{ | |
JS_ASSERT(ion::IsEnabled(cx)); | |
JS_ASSERT_IF(osrPc != NULL, (JSOp)*osrPc == JSOP_LOOPENTRY); | |
if (cx->compartment->debugMode()) { | |
IonSpew(IonSpew_Abort, "debugging"); | |
return Method_CantCompile; | |
} | |
@@ -1001,17 +1004,17 @@ Compile(JSContext *cx, JSScript *script, | |
//NDM | |
//NDM if (script->getUseCount() < js_IonOptions.usesBeforeCompile) | |
//NDM return Method_Skipped; | |
} else { | |
if (script->incUseCount() < js_IonOptions.usesBeforeCompileNoJaeger) | |
return Method_Skipped; | |
} | |
- if (!IonCompile<Compiler>(cx, script, fun, osrPc, constructing)) | |
+ if (!IonCompile<Compiler>(cx, script, fun, osrPc, constructing, compileMode)) | |
return Method_CantCompile; | |
// Compilation succeeded, but we invalidated right away. | |
return script->hasIonScript() ? Method_Compiled : Method_Skipped; | |
} | |
} // namespace ion | |
} // namespace js | |
@@ -1039,17 +1042,18 @@ ion::CanEnterAtBranch(JSContext *cx, JSS | |
// Mark as forbidden if frame can't be handled. | |
if (!CheckFrame(fp)) { | |
ForbidCompilation(script); | |
return Method_CantCompile; | |
} | |
// Attempt compilation. Returns Method_Compiled if already compiled. | |
JSFunction *fun = fp->isFunctionFrame() ? fp->fun() : NULL; | |
- MethodStatus status = Compile<TestCompiler>(cx, script, fun, pc, false); | |
+ MethodStatus status = Compile<TestCompiler>(cx, script, fun, pc, false, | |
+ CompileInfo::COMPILE_SEQ); | |
if (status != Method_Compiled) { | |
if (status == Method_CantCompile) | |
ForbidCompilation(script); | |
return status; | |
} | |
if (script->ion->osrPc() != pc) | |
return Method_Skipped; | |
@@ -1091,17 +1095,18 @@ ion::CanEnter(JSContext *cx, JSScript *s | |
// Mark as forbidden if frame can't be handled. | |
if (!CheckFrame(fp)) { | |
ForbidCompilation(script); | |
return Method_CantCompile; | |
} | |
// Attempt compilation. Returns Method_Compiled if already compiled. | |
JSFunction *fun = fp->isFunctionFrame() ? fp->fun() : NULL; | |
- MethodStatus status = Compile<TestCompiler>(cx, script, fun, NULL, fp->isConstructing()); | |
+ MethodStatus status = Compile<TestCompiler>(cx, script, fun, NULL, fp->isConstructing(), | |
+ CompileInfo::COMPILE_SEQ); | |
if (status != Method_Compiled) { | |
if (status == Method_CantCompile) | |
ForbidCompilation(script); | |
return status; | |
} | |
// This can GC, so afterward, script->ion is not guaranteed to be valid. | |
if (!cx->compartment->ionCompartment()->enterJIT(cx)) | |
@@ -1132,17 +1137,18 @@ ion::CanEnterParallelArrayKernel(JSConte | |
if (script->ion == ION_DISABLED_SCRIPT) | |
return Method_Skipped; | |
// Skip if the code is expected to result in a bailout. | |
if (script->ion && script->ion->bailoutExpected()) | |
return Method_Skipped; | |
// Attempt compilation. Returns Method_Compiled if already compiled. | |
- MethodStatus status = Compile<ParallelArrayKernelCompiler>(cx, script, fun, NULL, false); | |
+ MethodStatus status = Compile<ParallelArrayKernelCompiler>(cx, script, fun, NULL, false, | |
+ CompileInfo::COMPILE_PAR); | |
if (status != Method_Compiled) { | |
if (status == Method_CantCompile) | |
ForbidCompilation(script); | |
return status; | |
} | |
// This can GC, so afterward, script->ion is not guaranteed to be valid. | |
if (!cx->compartment->ionCompartment()->enterJIT(cx)) | |
diff --git a/js/src/ion/IonBuilder.cpp b/js/src/ion/IonBuilder.cpp | |
--- a/js/src/ion/IonBuilder.cpp | |
+++ b/js/src/ion/IonBuilder.cpp | |
@@ -2807,17 +2807,18 @@ IonBuilder::jsop_call_inline(HandleFunct | |
if (!argv.resizeUninitialized(argc + 1)) | |
return false; | |
for (int32 i = argc; i >= 0; i--) | |
argv[i] = current->pop(); | |
// Compilation information is allocated for the duration of the current tempLifoAlloc | |
// lifetime. | |
CompileInfo *info = cx->tempLifoAlloc().new_<CompileInfo>(callee->script(), callee, | |
- (jsbytecode *)NULL, constructing); | |
+ (jsbytecode *)NULL, constructing, | |
+ CompileInfo::COMPILE_SEQ); | |
if (!info) | |
return false; | |
MIRGraphExits saveExits; | |
AutoAccumulateExits aae(graph(), saveExits); | |
TypeInferenceOracle oracle; | |
if (!oracle.init(cx, callee->script())) | |
diff --git a/js/src/ion/shared/CodeGenerator-x86-shared.cpp b/js/src/ion/shared/CodeGenerator-x86-shared.cpp | |
--- a/js/src/ion/shared/CodeGenerator-x86-shared.cpp | |
+++ b/js/src/ion/shared/CodeGenerator-x86-shared.cpp | |
@@ -335,16 +335,33 @@ class BailoutLabel { | |
void operator()(MacroAssembler &masm, Label *label) const { | |
masm.retarget(label_, label); | |
} | |
}; | |
template <typename T> bool | |
CodeGeneratorX86Shared::bailout(const T &binder, LSnapshot *snapshot) | |
{ | |
+ // There has got to be an easier way! | |
+ CompileInfo &info = snapshot->mir()->block()->info(); | |
+ switch (info.compileMode()) { | |
+ case CompileInfo::COMPILE_PAR: { | |
+ // in parallel mode, make no attempt to recover, just signal an error. | |
+ OutOfLineParallelAbort *ool = new OutOfLineParallelAbort(); | |
+ if (!addOutOfLineCode(ool)) | |
+ return false; | |
+ binder(masm, ool->entry()); | |
+ return true; | |
+ } | |
+ | |
+ case CompileInfo::COMPILE_SEQ: { | |
+ break; | |
+ } | |
+ } | |
+ | |
if (!encode(snapshot)) | |
return false; | |
// Though the assembler doesn't track all frame pushes, at least make sure | |
// the known value makes sense. We can't use bailout tables if the stack | |
// isn't properly aligned to the static frame size. | |
JS_ASSERT_IF(frameClass_ != FrameSizeClass::None() && deoptTable_, | |
frameClass_.frameSize() == masm.framePushed()); | |
@@ -1225,16 +1242,30 @@ CodeGeneratorX86Shared::visitOutOfLineTr | |
restoreVolatile(output); | |
} | |
masm.jump(ool->rejoin()); | |
return true; | |
} | |
+bool | |
+CodeGeneratorX86Shared::visitOutOfLineParallelAbort() | |
+{ | |
+ masm.moveValue(MagicValue(JS_ION_ERROR), JSReturnOperand); | |
+ masm.jump(returnLabel_); | |
+ return true; | |
+} | |
+ | |
+bool | |
+OutOfLineParallelAbort::accept(CodeGeneratorX86Shared *codegen) | |
+{ | |
+ return codegen->visitOutOfLineParallelAbort(); | |
+} | |
+ | |
Operand | |
CodeGeneratorX86Shared::createArrayElementOperand(Register elements, const LAllocation *index) | |
{ | |
if (index->isConstant()) | |
return Operand(elements, ToInt32(index) * sizeof(js::Value)); | |
return Operand(elements, ToRegister(index), TimesEight); | |
} | |
diff --git a/js/src/ion/shared/CodeGenerator-x86-shared.h b/js/src/ion/shared/CodeGenerator-x86-shared.h | |
--- a/js/src/ion/shared/CodeGenerator-x86-shared.h | |
+++ b/js/src/ion/shared/CodeGenerator-x86-shared.h | |
@@ -113,16 +113,17 @@ class CodeGeneratorX86Shared : public Co | |
virtual bool visitGuardShape(LGuardShape *guard); | |
virtual bool visitGuardClass(LGuardClass *guard); | |
virtual bool visitTruncateDToInt32(LTruncateDToInt32 *ins); | |
// Out of line visitors. | |
bool visitOutOfLineBailout(OutOfLineBailout *ool); | |
bool visitMulNegativeZeroCheck(MulNegativeZeroCheck *ool); | |
bool visitOutOfLineTruncate(OutOfLineTruncate *ool); | |
+ bool visitOutOfLineParallelAbort(); | |
bool generateInvalidateEpilogue(); | |
}; | |
// An out-of-line bailout thunk. | |
class OutOfLineBailout : public OutOfLineCodeBase<CodeGeneratorX86Shared> | |
{ | |
LSnapshot *snapshot_; | |
@@ -133,13 +134,24 @@ class OutOfLineBailout : public OutOfLin | |
bool accept(CodeGeneratorX86Shared *codegen); | |
LSnapshot *snapshot() const { | |
return snapshot_; | |
} | |
}; | |
+ | |
+// An out-of-line parallel abort thunk. | |
+class OutOfLineParallelAbort : public OutOfLineCodeBase<CodeGeneratorX86Shared> | |
+{ | |
+ public: | |
+ OutOfLineParallelAbort() | |
+ { } | |
+ | |
+ bool accept(CodeGeneratorX86Shared *codegen); | |
+}; | |
+ | |
} // namespace ion | |
} // namespace js | |
#endif // jsion_codegen_x86_shared_h__ | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment