Commit 7cf92757 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Cleanup: add settable OSR/reopt thresholds, and get rid of tier 2

Previously it was:
tier 0: ast interpreter
tier 1: llvm, no speculations, no llvm opts
tier 2: llvm, w/ speculations, no llvm opts
tier 3: llvm, w/ speculations, w/ llvm opts

tier 2 seemed pretty useless, and very little would stay in it.  Also,
OSR would always skip from tier 1 to tier 3.

Separately, add configurable OSR/reopt thresholds.  This is mostly for the
sake of tests, where we can set lower limits and force OSR/reopts to happen.
parent b8a00bf1
......@@ -783,8 +783,7 @@ public:
// public entry point:
TypeAnalysis* doTypeAnalysis(CFG* cfg, const ParamNames& arg_names, const std::vector<ConcreteCompilerType*>& arg_types,
EffortLevel::EffortLevel effort, TypeAnalysis::SpeculationLevel speculation,
ScopeInfo* scope_info) {
EffortLevel effort, TypeAnalysis::SpeculationLevel speculation, ScopeInfo* scope_info) {
// if (effort == EffortLevel::INTERPRETED) {
// return new NullTypeAnalysis();
//}
......
......@@ -43,7 +43,7 @@ public:
};
TypeAnalysis* doTypeAnalysis(CFG* cfg, const ParamNames& param_names,
const std::vector<ConcreteCompilerType*>& arg_types, EffortLevel::EffortLevel effort,
const std::vector<ConcreteCompilerType*>& arg_types, EffortLevel effort,
TypeAnalysis::SpeculationLevel speculation, ScopeInfo* scope_info);
}
......
......@@ -45,9 +45,6 @@ namespace pyston {
namespace {
#define OSR_THRESHOLD 200
#define REOPT_THRESHOLD 100
union Value {
bool b;
int64_t n;
......@@ -379,7 +376,7 @@ Value ASTInterpreter::visit_jump(AST_Jump* node) {
if (ENABLE_OSR && backedge) {
++edgecount;
if (edgecount > OSR_THRESHOLD && !FORCE_INTERPRETER) {
if (edgecount > OSR_THRESHOLD_INTERPRETER && !FORCE_INTERPRETER) {
eraseDeadSymbols();
const OSREntryDescriptor* found_entry = nullptr;
......@@ -1083,7 +1080,7 @@ const void* interpreter_instr_addr = (void*)&ASTInterpreter::execute;
Box* astInterpretFunction(CompiledFunction* cf, int nargs, Box* closure, Box* generator, Box* arg1, Box* arg2,
Box* arg3, Box** args) {
if (unlikely(cf->times_called > REOPT_THRESHOLD && ENABLE_REOPT && !FORCE_INTERPRETER)) {
if (unlikely(cf->times_called > REOPT_THRESHOLD_INTERPRETER && ENABLE_REOPT && !FORCE_INTERPRETER)) {
CompiledFunction* optimized = reoptCompiledFuncInternal(cf);
if (closure && generator)
return optimized->closure_generator_call((BoxedClosure*)closure, (BoxedGenerator*)generator, arg1, arg2,
......
......@@ -63,7 +63,7 @@ void MyInserter::InsertHelper(llvm::Instruction* I, const llvm::Twine& Name, llv
llvm::IRBuilderDefaultInserter<true>::InsertHelper(I, Name, BB, InsertPt);
}
static void optimizeIR(llvm::Function* f, EffortLevel::EffortLevel effort) {
static void optimizeIR(llvm::Function* f, EffortLevel effort) {
// TODO maybe should do some simple passes (ex: gvn?) if effort level isn't maximal?
// In general, this function needs a lot of tuning.
if (effort < EffortLevel::MAXIMAL)
......@@ -334,7 +334,7 @@ static void emitBBs(IRGenState* irstate, const char* bb_type, GuardList& out_gua
TypeAnalysis* types, const OSREntryDescriptor* entry_descriptor, const BlockSet& full_blocks,
const BlockSet& partial_blocks) {
SourceInfo* source = irstate->getSourceInfo();
EffortLevel::EffortLevel effort = irstate->getEffortLevel();
EffortLevel effort = irstate->getEffortLevel();
CompiledFunction* cf = irstate->getCurFunction();
ConcreteCompilerType* rtn_type = irstate->getReturnType();
// llvm::MDNode* func_info = irstate->getFuncDbgInfo();
......@@ -614,13 +614,6 @@ static void emitBBs(IRGenState* irstate, const char* bb_type, GuardList& out_gua
// pass
} else if (block == source->cfg->getStartingBlock()) {
assert(entry_descriptor == NULL);
// number of times a function needs to be called to be reoptimized:
static const int REOPT_THRESHOLDS[] = {
10, // INTERPRETED->MINIMAL
250, // MINIMAL->MODERATE
10000, // MODERATE->MAXIMAL
};
assert(strcmp("opt", bb_type) == 0);
if (ENABLE_REOPT && effort < EffortLevel::MAXIMAL && source->ast != NULL
......@@ -636,8 +629,11 @@ static void emitBBs(IRGenState* irstate, const char* bb_type, GuardList& out_gua
llvm::Value* new_call_count
= emitter->getBuilder()->CreateAdd(cur_call_count, getConstantInt(1, g.i64));
emitter->getBuilder()->CreateStore(new_call_count, call_count_ptr);
llvm::Value* reopt_test = emitter->getBuilder()->CreateICmpSGT(
new_call_count, getConstantInt(REOPT_THRESHOLDS[effort], g.i64));
assert(effort == EffortLevel::MINIMAL);
int reopt_threshold = REOPT_THRESHOLD_BASELINE;
llvm::Value* reopt_test
= emitter->getBuilder()->CreateICmpSGT(new_call_count, getConstantInt(reopt_threshold, g.i64));
llvm::Metadata* md_vals[] = { llvm::MDString::get(g.context, "branch_weights"),
llvm::ConstantAsMetadata::get(getConstantInt(1)),
......@@ -1085,13 +1081,12 @@ static llvm::MDNode* setupDebugInfo(SourceInfo* source, llvm::Function* f, std::
return func_info;
}
static std::string getUniqueFunctionName(std::string nameprefix, EffortLevel::EffortLevel effort,
const OSREntryDescriptor* entry) {
static std::string getUniqueFunctionName(std::string nameprefix, EffortLevel effort, const OSREntryDescriptor* entry) {
static int num_functions = 0;
std::ostringstream os;
os << nameprefix;
os << "_e" << effort;
os << "_e" << (int)effort;
if (entry) {
os << "_osr" << entry->backedge->target->idx;
if (entry->cf->func)
......@@ -1103,7 +1098,7 @@ static std::string getUniqueFunctionName(std::string nameprefix, EffortLevel::Ef
}
CompiledFunction* doCompile(SourceInfo* source, ParamNames* param_names, const OSREntryDescriptor* entry_descriptor,
EffortLevel::EffortLevel effort, FunctionSpecialization* spec, std::string nameprefix) {
EffortLevel effort, FunctionSpecialization* spec, std::string nameprefix) {
Timer _t("in doCompile");
Timer _t2;
long irgen_us = 0;
......@@ -1170,7 +1165,8 @@ CompiledFunction* doCompile(SourceInfo* source, ParamNames* param_names, const O
irgen_us += _t2.split();
TypeAnalysis::SpeculationLevel speculation_level = TypeAnalysis::NONE;
if (ENABLE_SPECULATION && effort >= EffortLevel::MODERATE)
EffortLevel min_speculation_level = EffortLevel::MAXIMAL;
if (ENABLE_SPECULATION && effort >= min_speculation_level)
speculation_level = TypeAnalysis::SOME;
TypeAnalysis* types
= doTypeAnalysis(source->cfg, *param_names, spec->arg_types, effort, speculation_level, source->getScopeInfo());
......
......@@ -95,7 +95,7 @@ InternedString getIsDefinedName(InternedString name, InternedStringPool& interne
bool isIsDefinedName(const std::string& name);
CompiledFunction* doCompile(SourceInfo* source, ParamNames* param_names, const OSREntryDescriptor* entry_descriptor,
EffortLevel::EffortLevel effort, FunctionSpecialization* spec, std::string nameprefix);
EffortLevel effort, FunctionSpecialization* spec, std::string nameprefix);
// A common pattern is to branch based off whether a variable is defined but only if it is
// potentially-undefined. If it is potentially-undefined, we have to generate control-flow
......@@ -119,13 +119,13 @@ llvm::Value* handlePotentiallyUndefined(ConcreteCompilerVariable* is_defined_var
class TypeRecorder;
class OpInfo {
private:
const EffortLevel::EffortLevel effort;
const EffortLevel effort;
TypeRecorder* const type_recorder;
public:
const UnwindInfo unw_info;
OpInfo(EffortLevel::EffortLevel effort, TypeRecorder* type_recorder, UnwindInfo unw_info)
OpInfo(EffortLevel effort, TypeRecorder* type_recorder, UnwindInfo unw_info)
: effort(effort), type_recorder(type_recorder), unw_info(unw_info) {}
bool isInterpreted() const { return effort == EffortLevel::INTERPRETED; }
......
......@@ -103,7 +103,7 @@ ScopeInfo* SourceInfo::getScopeInfo() {
return scoping->getScopeInfoForNode(ast);
}
EffortLevel::EffortLevel initialEffort() {
EffortLevel initialEffort() {
if (FORCE_INTERPRETER)
return EffortLevel::INTERPRETED;
if (FORCE_OPTIMIZE)
......@@ -113,7 +113,7 @@ EffortLevel::EffortLevel initialEffort() {
return EffortLevel::MINIMAL;
}
static void compileIR(CompiledFunction* cf, EffortLevel::EffortLevel effort) {
static void compileIR(CompiledFunction* cf, EffortLevel effort) {
assert(cf);
assert(cf->func);
......@@ -165,7 +165,7 @@ static void compileIR(CompiledFunction* cf, EffortLevel::EffortLevel effort) {
// Compiles a new version of the function with the given signature and adds it to the list;
// should only be called after checking to see if the other versions would work.
// The codegen_lock needs to be held in W mode before calling this function:
CompiledFunction* compileFunction(CLFunction* f, FunctionSpecialization* spec, EffortLevel::EffortLevel effort,
CompiledFunction* compileFunction(CLFunction* f, FunctionSpecialization* spec, EffortLevel effort,
const OSREntryDescriptor* entry) {
Timer _t("for compileFunction()");
assert(spec);
......@@ -190,7 +190,7 @@ CompiledFunction* compileFunction(CLFunction* f, FunctionSpecialization* spec, E
ss << ") -> ";
ss << spec->rtn_type->debugName();
// spec->rtn_type->llvmType()->print(ss);
ss << " at effort level " << effort;
ss << " at effort level " << (int)effort;
if (entry != NULL) {
ss << "\nDoing OSR-entry partial compile, starting with backedge to block " << entry->backedge->target->idx
<< '\n';
......@@ -250,13 +250,6 @@ CompiledFunction* compileFunction(CLFunction* f, FunctionSpecialization* spec, E
num_compiles.log();
break;
}
case EffortLevel::MODERATE: {
static StatCounter us_compiling("us_compiling_2_moderate");
us_compiling.log(us);
static StatCounter num_compiles("num_compiles_2_moderate");
num_compiles.log();
break;
}
case EffortLevel::MAXIMAL: {
static StatCounter us_compiling("us_compiling_3_maximal");
us_compiling.log(us);
......@@ -264,6 +257,8 @@ CompiledFunction* compileFunction(CLFunction* f, FunctionSpecialization* spec, E
num_compiles.log();
break;
}
default:
RELEASE_ASSERT(0, "%d", effort);
}
return cf;
......@@ -284,7 +279,7 @@ void compileAndRunModule(AST_Module* m, BoxedModule* bm) {
SourceInfo* si = new SourceInfo(bm, scoping, m, m->body);
CLFunction* cl_f = new CLFunction(0, 0, false, false, si);
EffortLevel::EffortLevel effort = initialEffort();
EffortLevel effort = initialEffort();
cf = compileFunction(cl_f, new FunctionSpecialization(VOID), effort, NULL);
assert(cf->clfunc->versions.size());
......@@ -335,7 +330,7 @@ void CompiledFunction::speculationFailed() {
/// Reoptimizes the given function version at the new effort level.
/// The cf must be an active version in its parents CLFunction; the given
/// version will be replaced by the new version, which will be returned.
static CompiledFunction* _doReopt(CompiledFunction* cf, EffortLevel::EffortLevel new_effort) {
static CompiledFunction* _doReopt(CompiledFunction* cf, EffortLevel new_effort) {
LOCK_REGION(codegen_rwlock.asWrite());
assert(cf->clfunc->versions.size());
......@@ -372,7 +367,8 @@ static CompiledFunction* _doReopt(CompiledFunction* cf, EffortLevel::EffortLevel
abort();
}
static StatCounter stat_osrexits("OSR exits");
static StatCounter stat_osrexits("num_osr_exits");
static StatCounter stat_osr_compiles("num_osr_compiles");
CompiledFunction* compilePartialFuncInternal(OSRExit* exit) {
LOCK_REGION(codegen_rwlock.asWrite());
......@@ -386,14 +382,14 @@ CompiledFunction* compilePartialFuncInternal(OSRExit* exit) {
assert(exit->parent_cf->clfunc);
CompiledFunction*& new_cf = exit->parent_cf->clfunc->osr_versions[exit->entry];
if (new_cf == NULL) {
EffortLevel::EffortLevel new_effort = EffortLevel::MAXIMAL;
EffortLevel new_effort = EffortLevel::MAXIMAL;
if (exit->parent_cf->effort == EffortLevel::INTERPRETED)
new_effort = EffortLevel::MINIMAL;
// EffortLevel::EffortLevel new_effort = (EffortLevel::EffortLevel)(exit->parent_cf->effort + 1);
// new_effort = EffortLevel::MAXIMAL;
CompiledFunction* compiled
= compileFunction(exit->parent_cf->clfunc, exit->parent_cf->spec, new_effort, exit->entry);
assert(compiled == new_cf);
stat_osr_compiles.log();
}
return new_cf;
......@@ -412,7 +408,16 @@ extern "C" CompiledFunction* reoptCompiledFuncInternal(CompiledFunction* cf) {
assert(cf->effort < EffortLevel::MAXIMAL);
assert(cf->clfunc->versions.size());
CompiledFunction* new_cf = _doReopt(cf, (EffortLevel::EffortLevel(cf->effort + 1)));
EffortLevel new_effort;
if (cf->effort == EffortLevel::INTERPRETED)
new_effort = EffortLevel::MINIMAL;
else if (cf->effort == EffortLevel::MINIMAL)
new_effort = EffortLevel::MAXIMAL;
else
RELEASE_ASSERT(0, "unknown effort: %d", cf->effort);
CompiledFunction* new_cf = _doReopt(cf, new_effort);
assert(!new_cf->is_interpreted);
return new_cf;
}
......
......@@ -332,7 +332,7 @@ private:
OpInfo getOpInfoForNode(AST* ast, UnwindInfo unw_info) {
assert(ast);
EffortLevel::EffortLevel effort = irstate->getEffortLevel();
EffortLevel effort = irstate->getEffortLevel();
bool record_types = (effort != EffortLevel::INTERPRETED && effort != EffortLevel::MAXIMAL);
TypeRecorder* type_recorder;
......@@ -1945,10 +1945,8 @@ private:
llvm::Value* newcount = emitter.getBuilder()->CreateAdd(curcount, getConstantInt(1, g.i64));
emitter.getBuilder()->CreateStore(newcount, edgecount_ptr);
int OSR_THRESHOLD = 10000;
if (irstate->getEffortLevel() == EffortLevel::INTERPRETED)
OSR_THRESHOLD = 100;
llvm::Value* osr_test = emitter.getBuilder()->CreateICmpSGT(newcount, getConstantInt(OSR_THRESHOLD));
assert(irstate->getEffortLevel() == EffortLevel::MINIMAL);
llvm::Value* osr_test = emitter.getBuilder()->CreateICmpSGT(newcount, getConstantInt(OSR_THRESHOLD_BASELINE));
llvm::Metadata* md_vals[]
= { llvm::MDString::get(g.context, "branch_weights"), llvm::ConstantAsMetadata::get(getConstantInt(1)),
......
......@@ -76,7 +76,7 @@ public:
llvm::Function* getLLVMFunction() { return cf->func; }
EffortLevel::EffortLevel getEffortLevel() { return cf->effort; }
EffortLevel getEffortLevel() { return cf->effort; }
GCBuilder* getGC() { return gc; }
......
......@@ -56,7 +56,7 @@ BoxedClass* TypeRecorder::predict() {
if (!ENABLE_TYPE_FEEDBACK)
return NULL;
if (last_count > 100)
if (last_count > SPECULATION_THRESHOLD)
return last_seen;
return NULL;
......
......@@ -40,6 +40,12 @@ bool ENABLE_INTERPRETER = true;
bool ENABLE_PYPA_PARSER = false;
bool USE_REGALLOC_BASIC = true;
int OSR_THRESHOLD_INTERPRETER = 200;
int REOPT_THRESHOLD_INTERPRETER = 100;
int OSR_THRESHOLD_BASELINE = 10000;
int REOPT_THRESHOLD_BASELINE = 500;
int SPECULATION_THRESHOLD = 100;
static bool _GLOBAL_ENABLE = 1;
bool ENABLE_ICS = 1 && _GLOBAL_ENABLE;
bool ENABLE_ICGENERICS = 1 && ENABLE_ICS;
......
......@@ -31,6 +31,10 @@ inline int version_hex(int major, int minor, int micro, int level = 0, int seria
extern int MAX_OPT_ITERATIONS;
extern int OSR_THRESHOLD_INTERPRETER, REOPT_THRESHOLD_INTERPRETER;
extern int OSR_THRESHOLD_BASELINE, REOPT_THRESHOLD_BASELINE;
extern int SPECULATION_THRESHOLD;
extern bool SHOW_DISASM, FORCE_INTERPRETER, FORCE_OPTIMIZE, PROFILE, DUMPJIT, TRAP, USE_STRIPPED_STDLIB,
ENABLE_INTERPRETER, ENABLE_PYPA_PARSER, USE_REGALLOC_BASIC;
......
......@@ -96,14 +96,11 @@ public:
} // namespace gc
using gc::GCVisitor;
namespace EffortLevel {
enum EffortLevel {
enum class EffortLevel {
INTERPRETED = 0,
MINIMAL,
MODERATE,
MAXIMAL,
MINIMAL = 1,
MAXIMAL = 3, // keep the old tier numbering for familiarity
};
}
class CompilerType;
template <class V> class ValuedCompilerType;
......@@ -193,7 +190,7 @@ public:
int code_size;
llvm::Value* llvm_code; // the llvm callable.
EffortLevel::EffortLevel effort;
EffortLevel effort;
int64_t times_called, times_speculation_failed;
ICInvalidator dependent_callsites;
......@@ -203,8 +200,7 @@ public:
std::vector<ICInfo*> ics;
CompiledFunction(llvm::Function* func, FunctionSpecialization* spec, bool is_interpreted, void* code,
llvm::Value* llvm_code, EffortLevel::EffortLevel effort,
const OSREntryDescriptor* entry_descriptor)
llvm::Value* llvm_code, EffortLevel effort, const OSREntryDescriptor* entry_descriptor)
: clfunc(NULL), func(func), spec(spec), entry_descriptor(entry_descriptor), is_interpreted(is_interpreted),
code(code), llvm_code(llvm_code), effort(effort), times_called(0), times_speculation_failed(0),
location_map(nullptr) {}
......@@ -327,9 +323,9 @@ CLFunction* unboxRTFunction(Box*);
// Compiles a new version of the function with the given signature and adds it to the list;
// should only be called after checking to see if the other versions would work.
CompiledFunction* compileFunction(CLFunction* f, FunctionSpecialization* spec, EffortLevel::EffortLevel effort,
CompiledFunction* compileFunction(CLFunction* f, FunctionSpecialization* spec, EffortLevel effort,
const OSREntryDescriptor* entry);
EffortLevel::EffortLevel initialEffort();
EffortLevel initialEffort();
typedef bool i1;
typedef int64_t i64;
......
......@@ -27,18 +27,24 @@ static Box* setOption(Box* option, Box* value) {
if (value->cls != int_cls)
raiseExcHelper(TypeError, "value must be a 'int' object but received a '%s'", getTypeName(value));
bool enable = ((BoxedInt*)value)->n;
if (option_string->s == "ENABLE_INTERPRETER")
ENABLE_INTERPRETER = enable;
else if (option_string->s == "ENABLE_OSR")
ENABLE_OSR = enable;
else if (option_string->s == "ENABLE_REOPT")
ENABLE_REOPT = enable;
else if (option_string->s == "FORCE_INTERPRETER")
FORCE_INTERPRETER = enable;
else
raiseExcHelper(ValueError, "unknown option name '%s", option_string->s.c_str());
int n = ((BoxedInt*)value)->n;
#define CHECK(_s) \
if (option_string->s == STRINGIFY(_s)) \
_s = n
// :)
CHECK(ENABLE_INTERPRETER);
else CHECK(ENABLE_OSR);
else CHECK(ENABLE_REOPT);
else CHECK(FORCE_INTERPRETER);
else CHECK(REOPT_THRESHOLD_INTERPRETER);
else CHECK(OSR_THRESHOLD_INTERPRETER);
else CHECK(REOPT_THRESHOLD_BASELINE);
else CHECK(OSR_THRESHOLD_BASELINE);
else CHECK(SPECULATION_THRESHOLD);
else raiseExcHelper(ValueError, "unknown option name '%s", option_string->s.c_str());
return None;
}
......
......@@ -2293,7 +2293,7 @@ static CompiledFunction* pickVersion(CLFunction* f, int num_output_args, Box* oa
}
FunctionSpecialization* spec = new FunctionSpecialization(UNKNOWN, arg_types);
EffortLevel::EffortLevel new_effort = initialEffort();
EffortLevel new_effort = initialEffort();
// this also pushes the new CompiledVersion to the back of the version list:
chosen_cf = compileFunction(f, spec, new_effort, NULL);
......
# run_args: -n
# statcheck: ("-O" in EXTRA_JIT_ARGS) or (1 <= stats["OSR exits"] <= 2)
# statcheck: ("-O" in EXTRA_JIT_ARGS) or (1 <= stats["num_osr_exits"] <= 2)
# statcheck: stats['slowpath_binop'] <= 10
x = 100000
......
# This test could really benefit from defined/settable OSR limits
# statcheck: '-O' in EXTRA_JIT_ARGS or 1 <= stats['num_osr_exits'] <= 5
def f(x):
def inner():
......
# skip-if: '-O' in EXTRA_JIT_ARGS
# statcheck: 4 <= noninit_count('num_deopt') < 50
# statcheck: 1 <= stats["num_osr_exits"] <= 2
try:
import __pyston__
__pyston__.setOption("OSR_THRESHOLD_BASELINE", 50)
__pyston__.setOption("REOPT_THRESHOLD_BASELINE", 50)
__pyston__.setOption("SPECULATION_THRESHOLD", 10)
except ImportError:
pass
def f(o):
def main():
def f(o):
print "starting"
try:
......@@ -16,31 +26,29 @@ def f(o):
print "Done"
class C(object):
class C(object):
def __repr__(self):
return "<C>"
c = C()
c.a = 1
c.b = 0
c.c = 3
c.d = 4
c = C()
c.a = 1
c.b = 0
c.c = 3
c.d = 4
# These limits are high to try to trigger OSR.
# TODO we should have some way to lower the OSR thresholds
for i in xrange(20000):
for i in xrange(2000):
print i
if i == 5000:
if i == 500:
c.a = []
if i == 6000:
if i == 600:
c.b = 1
if i == 7000:
if i == 700:
c.c = []
if i == 8000:
if i == 800:
c.b = 0
c.d = 1.0
......@@ -48,9 +56,9 @@ for i in xrange(20000):
# Regression test reduced from subprocess.py:
import types
def f2(self, args):
# Regression test reduced from subprocess.py:
import types
def f2(self, args):
if isinstance(args, types.StringTypes):
pass
......@@ -59,10 +67,11 @@ def f2(self, args):
except:
pass
c = C()
c.pid = 1
for i in xrange(20000):
c = C()
c.pid = 1
for i in xrange(2000):
f2(c, None)
if i == 15000:
if i == 1500:
c.pid = 1.0
main()
# statcheck: ("-O" in EXTRA_JIT_ARGS) or (1 <= stats["num_osr_exits"] <= 2)
# While perhaps not required in practice, we should have the ability to
# OSR from inside a list comprehension.
# statcheck: ("-O" in EXTRA_JIT_ARGS) or (1 <= stats["OSR exits"] <= 2)
def p(i):
print i
for i in xrange(100000):
pass
# [i for i in xrange(100000) if i % 100 == 0]
print len([i for i in xrange(100000) if i % 100 == 0])
# statcheck: '-O' in EXTRA_JIT_ARGS or 1 <= stats['num_osr_exits'] <= 5
# "big osr" in terms of lots of live variables needing to be passed through:
try:
import __pyston__
__pyston__.setOption("OSR_THRESHOLD_INTERPRETER", 5)
__pyston__.setOption("OSR_THRESHOLD_BASELINE", 5)
except ImportError:
pass
def outer(quit):
if quit:
return
......@@ -15,7 +24,7 @@ def outer(quit):
i = 9
l = []
n = 100000
n = 10000
while n:
n = n - 1
a = a + 1
......
# statcheck: '-O' in EXTRA_JIT_ARGS or 1 <= stats['num_osr_exits'] <= 5
# Try to trick the JIT into OSR'ing into an optimized version with a speculation
# that has already failed.
# In the f() function, y will have type int, but when we OSR from the while loop,
......@@ -10,7 +12,7 @@ def xrange(n):
def f(x):
y = xrange(x)
n = 100000
n = 10000
while n:
n -= 1
......
# statcheck: '-O' in EXTRA_JIT_ARGS or 1 <= stats['num_osr_exits'] <= 5
# Regression test to make sure we can do an OSR if one of the live variables
# is potentially-undefined.
......@@ -5,10 +7,13 @@ def f(x):
if x % 2:
y = x
for i in xrange(1000000):
for i in xrange(10000):
pass
try:
print y
except NameError, e:
print e
f(11)
f(10)
# statcheck: '-O' in EXTRA_JIT_ARGS or 1 <= stats['num_osr_exits'] <= 5
# Regression test to make sure we can do an OSR if one of the live variables
# is potentially-undefined.
......@@ -7,10 +9,13 @@ def f(x):
xrange(0)
for i in xrange(1000000):
for i in xrange(10000):
xrange(0)
try:
print y
except NameError, e:
print e
xrange(0)
f(11)
......
......@@ -2,6 +2,7 @@
# of stacks that we have:
def recurse(n):
print n
if n > 0:
return recurse(n - 1)
return n
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment