Skip to content

Instantly share code, notes, and snippets.

@nikomatsakis
Created August 8, 2012 01:31
Show Gist options
  • Save nikomatsakis/3291232 to your computer and use it in GitHub Desktop.
Save nikomatsakis/3291232 to your computer and use it in GitHub Desktop.
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