Commit 1923d116 authored by Kevin Modzelewski's avatar Kevin Modzelewski Committed by GitHub

Merge pull request #1277 from kmod/vregs_everywhere

Switch almost everything to use vregs when possible
parents 44ccbe1b a044540d
......@@ -337,7 +337,7 @@ STDOBJECT_SRCS := \
iterobject.c \
bufferobject.c \
cobject.c \
dictproxy.c \
descrobject.c \
$(EXTRA_STDOBJECT_SRCS)
STDPYTHON_SRCS := \
......
This diff is collapsed.
......@@ -21,6 +21,7 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "analysis/function_analysis.h"
#include "core/cfg.h"
#include "core/common.h"
#include "core/options.h"
......@@ -29,13 +30,12 @@ namespace pyston {
template <typename T> class BBAnalyzer {
public:
typedef llvm::DenseMap<InternedString, T> Map;
typedef VRegMap<T> Map;
typedef llvm::DenseMap<CFGBlock*, Map> AllMap;
virtual ~BBAnalyzer() {}
virtual T merge(T from, T into) const = 0;
virtual T mergeBlank(T into) const = 0;
virtual void processBB(Map& starting, CFGBlock* block) const = 0;
};
......@@ -56,10 +56,12 @@ void computeFixedPoint(typename BBAnalyzer<T>::Map&& initial_map, CFGBlock* init
assert(!starting_states.size());
assert(!ending_states.size());
int num_vregs = initial_map.numVregs();
llvm::SmallPtrSet<CFGBlock*, 32> in_queue;
std::priority_queue<CFGBlock*, llvm::SmallVector<CFGBlock*, 32>, CFGBlockMinIndex> q;
starting_states.insert(make_pair(initial_block, std::move(initial_map)));
starting_states.insert(std::make_pair(initial_block, std::move(initial_map)));
q.push(initial_block);
in_queue.insert(initial_block);
......@@ -70,9 +72,10 @@ void computeFixedPoint(typename BBAnalyzer<T>::Map&& initial_map, CFGBlock* init
q.pop();
in_queue.erase(block);
Map& initial = starting_states[block];
assert(starting_states.count(block));
Map& initial = starting_states.find(block)->second;
if (VERBOSITY("analysis") >= 2)
printf("fpc on block %d - %d entries\n", block->idx, initial.size());
printf("fpc on block %d - %d entries\n", block->idx, initial.numVregs());
Map ending = Map(initial);
......@@ -87,43 +90,34 @@ void computeFixedPoint(typename BBAnalyzer<T>::Map&& initial_map, CFGBlock* init
initial = true;
}
Map& next = starting_states[next_block];
for (const auto& p : ending) {
if (next.count(p.first) == 0) {
changed = true;
if (initial) {
next[p.first] = p.second;
} else {
next[p.first] = analyzer.mergeBlank(p.second);
}
} else {
T& next_elt = next[p.first];
T new_elt = analyzer.merge(p.second, next_elt);
if (next_elt != new_elt) {
next_elt = new_elt;
changed = true;
}
}
}
auto it = starting_states.find(next_block);
if (it == starting_states.end())
it = starting_states.insert(std::make_pair(next_block, Map(num_vregs))).first;
for (const auto& p : next) {
if (ending.count(p.first))
continue;
Map& next = it->second;
// merge ending->next
for (int vreg = 0; vreg < num_vregs; vreg++) {
T& next_elt = next[vreg];
T next_elt = analyzer.mergeBlank(p.second);
if (next_elt != p.second) {
next[p.first] = next_elt;
T new_elt = analyzer.merge(ending[vreg], next_elt);
if (next_elt != new_elt) {
next_elt = new_elt;
changed = true;
}
}
#ifndef NDEBUG
assert(next.numVregs() == ending.numVregs());
#endif
if (changed && in_queue.insert(next_block).second) {
q.push(next_block);
}
}
ending_states[block] = std::move(ending);
ending_states.erase(block);
ending_states.insert(std::make_pair(block, std::move(ending)));
}
if (VERBOSITY("analysis")) {
......
This diff is collapsed.
......@@ -20,6 +20,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "core/cfg.h"
#include "core/stringpool.h"
#include "core/types.h"
......@@ -41,7 +42,7 @@ private:
typedef llvm::DenseMap<CFGBlock*, std::unique_ptr<LivenessBBVisitor>> LivenessCacheMap;
LivenessCacheMap liveness_cache;
llvm::DenseMap<InternedString, llvm::DenseMap<CFGBlock*, bool>> result_cache;
VRegMap<llvm::DenseMap<CFGBlock*, bool>> result_cache;
public:
LivenessAnalysis(CFG* cfg);
......@@ -50,60 +51,59 @@ public:
// we don't keep track of node->parent_block relationships, so you have to pass both:
bool isKill(AST_Name* node, CFGBlock* parent_block);
bool isLiveAtEnd(InternedString name, CFGBlock* block);
bool isLiveAtEnd(int vreg, CFGBlock* block);
};
class PhiAnalysis;
class DefinednessAnalysis {
public:
enum DefinitionLevel {
enum DefinitionLevel : char {
Unknown,
Undefined,
PotentiallyDefined,
Defined,
};
typedef llvm::DenseSet<InternedString> RequiredSet;
private:
llvm::DenseMap<CFGBlock*, llvm::DenseMap<InternedString, DefinitionLevel>> defined_at_beginning, defined_at_end;
llvm::DenseMap<CFGBlock*, RequiredSet> defined_at_end_sets;
llvm::DenseMap<CFGBlock*, VRegMap<DefinitionLevel>> defined_at_beginning, defined_at_end;
llvm::DenseMap<CFGBlock*, VRegSet> defined_at_end_sets;
public:
DefinednessAnalysis() {}
void run(llvm::DenseMap<InternedString, DefinitionLevel> initial_map, CFGBlock* initial_block,
ScopeInfo* scope_info);
void run(VRegMap<DefinitionLevel> initial_map, CFGBlock* initial_block, ScopeInfo* scope_info);
DefinitionLevel isDefinedAtEnd(InternedString name, CFGBlock* block);
const RequiredSet& getDefinedNamesAtEnd(CFGBlock* block);
DefinitionLevel isDefinedAtEnd(int vreg, CFGBlock* block);
const VRegSet& getDefinedVregsAtEnd(CFGBlock* block);
friend class PhiAnalysis;
};
class PhiAnalysis {
public:
typedef llvm::DenseSet<InternedString> RequiredSet;
DefinednessAnalysis definedness;
VRegSet empty_set;
private:
LivenessAnalysis* liveness;
llvm::DenseMap<CFGBlock*, RequiredSet> required_phis;
llvm::DenseMap<CFGBlock*, VRegSet> required_phis;
public:
// Initials_need_phis specifies that initial_map should count as an additional entry point
// that may require phis.
PhiAnalysis(llvm::DenseMap<InternedString, DefinednessAnalysis::DefinitionLevel> initial_map,
CFGBlock* initial_block, bool initials_need_phis, LivenessAnalysis* liveness, ScopeInfo* scope_info);
PhiAnalysis(VRegMap<DefinednessAnalysis::DefinitionLevel> initial_map, CFGBlock* initial_block,
bool initials_need_phis, LivenessAnalysis* liveness, ScopeInfo* scope_info);
bool isRequired(InternedString name, CFGBlock* block);
bool isRequiredAfter(InternedString name, CFGBlock* block);
const RequiredSet& getAllRequiredAfter(CFGBlock* block);
const RequiredSet& getAllRequiredFor(CFGBlock* block);
bool isRequired(int vreg, CFGBlock* block);
bool isRequiredAfter(int vreg, CFGBlock* block);
const VRegSet& getAllRequiredAfter(CFGBlock* block);
const VRegSet& getAllRequiredFor(CFGBlock* block);
// If "name" may be undefined at the beginning of any immediate successor block of "block":
bool isPotentiallyUndefinedAfter(InternedString name, CFGBlock* block);
bool isPotentiallyUndefinedAfter(int vreg, CFGBlock* block);
// If "name" may be undefined at the beginning of "block"
bool isPotentiallyUndefinedAt(InternedString name, CFGBlock* block);
bool isPotentiallyUndefinedAt(int vreg, CFGBlock* block);
};
std::unique_ptr<LivenessAnalysis> computeLivenessInfo(CFG*);
......
......@@ -587,29 +587,33 @@ public:
}
}
bool visit_functiondef(AST_FunctionDef* node) override {
if (node == orig_node) {
this->currently_visiting_functiondef_args = true;
void visitOrignodeArgs(AST_arguments* args) {
this->currently_visiting_functiondef_args = true;
int counter = 0;
for (AST_expr* e : node->args->args) {
if (e->type == AST_TYPE::Tuple) {
doWrite(scoping->getInternedStrings().get("." + std::to_string(counter)));
}
counter++;
e->accept(this);
int counter = 0;
for (AST_expr* e : args->args) {
if (e->type == AST_TYPE::Tuple) {
doWrite(scoping->getInternedStrings().get("." + std::to_string(counter)));
}
counter++;
e->accept(this);
}
if (node->args->vararg.s().size()) {
mangleNameInPlace(node->args->vararg, cur->private_name, scoping->getInternedStrings());
doWrite(node->args->vararg);
}
if (node->args->kwarg.s().size()) {
mangleNameInPlace(node->args->kwarg, cur->private_name, scoping->getInternedStrings());
doWrite(node->args->kwarg);
}
if (args->vararg) {
mangleNameInPlace(args->vararg->id, cur->private_name, scoping->getInternedStrings());
doWrite(args->vararg->id);
}
if (args->kwarg) {
mangleNameInPlace(args->kwarg->id, cur->private_name, scoping->getInternedStrings());
doWrite(args->kwarg->id);
}
this->currently_visiting_functiondef_args = false;
}
this->currently_visiting_functiondef_args = false;
bool visit_functiondef(AST_FunctionDef* node) override {
if (node == orig_node) {
visitOrignodeArgs(node->args);
for (AST_stmt* s : node->body)
s->accept(this);
......@@ -666,16 +670,7 @@ public:
bool visit_lambda(AST_Lambda* node) override {
if (node == orig_node) {
for (AST_expr* e : node->args->args)
e->accept(this);
if (node->args->vararg.s().size()) {
mangleNameInPlace(node->args->vararg, cur->private_name, scoping->getInternedStrings());
doWrite(node->args->vararg);
}
if (node->args->kwarg.s().size()) {
mangleNameInPlace(node->args->kwarg, cur->private_name, scoping->getInternedStrings());
doWrite(node->args->kwarg);
}
visitOrignodeArgs(node->args);
node->body->accept(this);
} else {
for (auto* e : node->args->defaults)
......
This diff is collapsed.
......@@ -39,8 +39,8 @@ public:
virtual ~TypeAnalysis() {}
virtual ConcreteCompilerType* getTypeAtBlockStart(InternedString name, CFGBlock* block) = 0;
virtual ConcreteCompilerType* getTypeAtBlockEnd(InternedString name, CFGBlock* block) = 0;
virtual ConcreteCompilerType* getTypeAtBlockStart(int vreg, CFGBlock* block) = 0;
virtual ConcreteCompilerType* getTypeAtBlockEnd(int vreg, CFGBlock* block) = 0;
virtual BoxedClass* speculatedExprClass(AST_expr*) = 0;
virtual BoxedClass* speculatedExprClass(AST_slice*) = 0;
};
......
This diff is collapsed.
......@@ -76,9 +76,8 @@ BORROWED(BoxedCode*) FunctionMetadata::getCode() {
void FunctionMetadata::addVersion(CompiledFunction* compiled) {
assert(compiled);
assert((compiled->spec != NULL) + (compiled->entry_descriptor != NULL) == 1);
assert(compiled->md == NULL);
assert(compiled->md);
assert(compiled->code);
compiled->md = this;
if (compiled->entry_descriptor == NULL) {
bool could_have_speculations = (source.get() != NULL);
......
......@@ -821,19 +821,15 @@ ConcreteCompilerVariable* UnknownType::hasnext(IREmitter& emitter, const OpInfo&
return boolFromI1(emitter, rtn_val);
}
CompilerVariable* makeFunction(IREmitter& emitter, FunctionMetadata* f, CompilerVariable* closure, llvm::Value* globals,
CompilerVariable* makeFunction(IREmitter& emitter, FunctionMetadata* f, llvm::Value* closure, llvm::Value* globals,
const std::vector<ConcreteCompilerVariable*>& defaults) {
// Unlike the FunctionMetadata*, which can be shared between recompilations, the Box* around it
// should be created anew every time the functiondef is encountered
llvm::Value* closure_v;
ConcreteCompilerVariable* convertedClosure = NULL;
if (closure) {
convertedClosure = closure->makeConverted(emitter, closure->getConcreteType());
closure_v = convertedClosure->getValue();
} else {
closure_v = getNullPtr(g.llvm_closure_type_ptr);
emitter.setType(closure_v, RefType::BORROWED);
if (!closure) {
closure = getNullPtr(g.llvm_closure_type_ptr);
emitter.setType(closure, RefType::BORROWED);
}
llvm::SmallVector<llvm::Value*, 4> array_passed_args;
......@@ -860,8 +856,8 @@ CompilerVariable* makeFunction(IREmitter& emitter, FunctionMetadata* f, Compiler
// emitter.createCall().
llvm::Instruction* boxed = emitter.getBuilder()->CreateCall(
g.funcs.createFunctionFromMetadata,
std::vector<llvm::Value*>{ embedRelocatablePtr(f, g.llvm_functionmetadata_type_ptr), closure_v, globals,
scratch, getConstantInt(defaults.size(), g.i64) });
std::vector<llvm::Value*>{ embedRelocatablePtr(f, g.llvm_functionmetadata_type_ptr), closure, globals, scratch,
getConstantInt(defaults.size(), g.i64) });
emitter.setType(boxed, RefType::OWNED);
// The refcounter needs to know that this call "uses" the arguments that got passed via scratch.
......@@ -2433,8 +2429,11 @@ public:
}
};
ConcreteCompilerType* BOOL = new BoolType();
llvm::Value* makeLLVMBool(bool b) {
return llvm::ConstantInt::get(BOOL->llvmType(), b, false);
}
ConcreteCompilerVariable* makeBool(bool b) {
return new ConcreteCompilerVariable(BOOL, llvm::ConstantInt::get(BOOL->llvmType(), b, false));
return new ConcreteCompilerVariable(BOOL, makeLLVMBool(b));
}
ConcreteCompilerVariable* doIs(IREmitter& emitter, CompilerVariable* lhs, CompilerVariable* rhs, bool negate) {
......@@ -2862,6 +2861,17 @@ llvm::Value* i1FromBool(IREmitter& emitter, ConcreteCompilerVariable* v) {
}
}
llvm::Value* i1FromLLVMBool(IREmitter& emitter, llvm::Value* v) {
if (BOOLS_AS_I64) {
assert(v->getType() == BOOL->llvmType());
assert(BOOL->llvmType() == g.i64);
llvm::Value* v2 = emitter.getBuilder()->CreateTrunc(v, g.i1);
return v2;
} else {
return v;
}
}
ConcreteCompilerType* LIST, *SLICE, *MODULE, *DICT, *SET, *FROZENSET, *LONG, *BOXED_COMPLEX;
......
......@@ -346,6 +346,7 @@ CompilerVariable* makeFloat(double);
CompilerVariable* makeUnboxedFloat(IREmitter&, ConcreteCompilerVariable*);
CompilerVariable* makeUnboxedFloat(IREmitter&, llvm::Value*);
llvm::Value* makeLLVMBool(bool b);
ConcreteCompilerVariable* makeBool(bool);
ConcreteCompilerVariable* makeLong(IREmitter&, Box*);
ConcreteCompilerVariable* makePureImaginary(IREmitter&, Box*);
......@@ -361,7 +362,7 @@ UnboxedSlice extractSlice(CompilerVariable* slice);
#if 0
CompilerVariable* makeUnicode(IREmitter& emitter, llvm::StringRef);
#endif
CompilerVariable* makeFunction(IREmitter& emitter, FunctionMetadata*, CompilerVariable* closure, llvm::Value* globals,
CompilerVariable* makeFunction(IREmitter& emitter, FunctionMetadata*, llvm::Value* closure, llvm::Value* globals,
const std::vector<ConcreteCompilerVariable*>& defaults);
ConcreteCompilerVariable* undefVariable();
CompilerVariable* makeTuple(const std::vector<CompilerVariable*>& elts);
......@@ -372,6 +373,7 @@ CompilerType* makeFuncType(ConcreteCompilerType* rtn_type, const std::vector<Con
ConcreteCompilerVariable* boolFromI1(IREmitter&, llvm::Value*);
llvm::Value* i1FromBool(IREmitter&, ConcreteCompilerVariable*);
llvm::Value* i1FromLLVMBool(IREmitter&, llvm::Value*);
template <typename V>
CompilerVariable* _ValuedCompilerType<V>::getPystonIter(IREmitter& emitter, const OpInfo& info, VAR* var) {
......
......@@ -97,26 +97,32 @@ public:
return pool->get(static_cast<BoxedString*>(ident)->s());
}
AST_Name* convertToName(identifier ident) {
if (!ident)
return NULL;
return new AST_Name(convert(ident), AST_TYPE::Store, -1, -1);
}
AST_arguments* convert(arguments_ty ident, AST* parent) {
auto r = new AST_arguments();
convertAll<expr_ty>(ident->args, r->args);
convertAll<expr_ty>(ident->defaults, r->defaults);
r->vararg = convert(ident->vararg);
r->kwarg = convert(ident->kwarg);
r->vararg = convertToName(ident->vararg);
r->kwarg = convertToName(ident->kwarg);
if ((!r->vararg.s().empty()) && (!r->kwarg.s().empty()) && (r->vararg == r->kwarg)) {
if (r->vararg && r->kwarg && (r->vararg->id == r->kwarg->id)) {
char buf[1024];
snprintf(buf, sizeof(buf), "duplicate argument '%s' in function definition", r->vararg.c_str());
snprintf(buf, sizeof(buf), "duplicate argument '%s' in function definition", r->vararg->id.c_str());
raiseSyntaxError(buf, parent->lineno, parent->col_offset, fn, "", true);
}
std::set<InternedString> seen;
if (!r->vararg.s().empty()) {
seen.insert(r->vararg);
if (r->vararg) {
seen.insert(r->vararg->id);
}
if (!r->kwarg.s().empty()) {
seen.insert(r->kwarg);
if (r->kwarg) {
seen.insert(r->kwarg->id);
}
checkDuplicateArgs(parent, r->args, &seen);
......
This diff is collapsed.
......@@ -77,13 +77,13 @@ ParamNames::ParamNames(AST* ast, InternedStringPool& pool)
}
}
vararg = arguments->vararg.s();
if (vararg.size())
vararg_name = new AST_Name(pool.get(vararg), AST_TYPE::Param, arguments->lineno, arguments->col_offset);
vararg_name = arguments->vararg;
if (vararg_name)
vararg = vararg_name->id.s();
kwarg = arguments->kwarg.s();
if (kwarg.size())
kwarg_name = new AST_Name(pool.get(kwarg), AST_TYPE::Param, arguments->lineno, arguments->col_offset);
kwarg_name = arguments->kwarg;
if (kwarg_name)
kwarg = kwarg_name->id.s();
} else {
RELEASE_ASSERT(0, "%d", ast->type);
}
......@@ -261,7 +261,7 @@ CompiledFunction* compileFunction(FunctionMetadata* f, FunctionSpecialization* s
if (entry_descriptor && VERBOSITY("irgen") >= 2) {
for (const auto& p : entry_descriptor->args) {
ss << p.first.s() << ": " << p.second->debugName() << '\n';
ss << p.first << ": " << p.second->debugName() << '\n';
}
}
......@@ -680,10 +680,10 @@ void CompiledFunction::speculationFailed() {
}
std::unordered_set<CompiledFunction*> all_compiled_functions;
CompiledFunction::CompiledFunction(llvm::Function* func, FunctionSpecialization* spec, void* code, EffortLevel effort,
CompiledFunction::CompiledFunction(FunctionMetadata* md, FunctionSpecialization* spec, void* code, EffortLevel effort,
ExceptionStyle exception_style, const OSREntryDescriptor* entry_descriptor)
: md(NULL),
func(func),
: md(md),
func(NULL),
effort(effort),
exception_style(exception_style),
spec(spec),
......@@ -827,6 +827,6 @@ void FunctionMetadata::addVersion(void* f, ConcreteCompilerType* rtn_type,
#endif
FunctionSpecialization* spec = new FunctionSpecialization(processType(rtn_type), arg_types);
addVersion(new CompiledFunction(NULL, spec, f, EffortLevel::MAXIMAL, exception_style, NULL));
addVersion(new CompiledFunction(this, spec, f, EffortLevel::MAXIMAL, exception_style, NULL));
}
}
This diff is collapsed.
......@@ -21,6 +21,7 @@
#include "llvm/ADT/iterator_range.h"
#include "llvm/IR/Instructions.h"
#include "core/cfg.h"
#include "core/stringpool.h"
#include "core/types.h"
......@@ -43,9 +44,9 @@ class TypeAnalysis;
class RefcountTracker;
class UnwindInfo;
typedef std::unordered_map<InternedString, CompilerVariable*> SymbolTable;
typedef std::map<InternedString, CompilerVariable*> SortedSymbolTable;
typedef std::unordered_map<InternedString, ConcreteCompilerVariable*> ConcreteSymbolTable;
typedef VRegMap<CompilerVariable*> SymbolTable;
typedef VRegMap<llvm::Value*> DefinednessTable;
typedef VRegMap<ConcreteCompilerVariable*> ConcreteSymbolTable;
extern const std::string CREATED_CLOSURE_NAME;
extern const std::string PASSED_CLOSURE_NAME;
......@@ -75,6 +76,9 @@ private:
llvm::Value* globals;
llvm::Value* vregs;
llvm::Value* stmt;
llvm::Value* passed_closure = NULL, * created_closure = NULL, * passed_generator = NULL;
int scratch_size;
public:
......@@ -82,6 +86,8 @@ public:
ParamNames* param_names, GCBuilder* gc, llvm::MDNode* func_dbg_info, RefcountTracker* refcount_tracker);
~IRGenState();
CFG* getCFG() { return getSourceInfo()->cfg; }
CompiledFunction* getCurFunction() { return cf; }
FunctionMetadata* getMD() { return md; }
......@@ -119,6 +125,14 @@ public:
ParamNames* getParamNames() { return param_names; }
llvm::Value* getPassedClosure();
llvm::Value* getCreatedClosure();
llvm::Value* getPassedGenerator();
void setPassedClosure(llvm::Value*);
void setCreatedClosure(llvm::Value*);
void setPassedGenerator(llvm::Value*);
// Returns the custom globals, or the module if the globals come from the module.
llvm::Value* getGlobals();
// Returns the custom globals, or null if the globals come from the module.
......@@ -140,15 +154,20 @@ public:
// symbol_table records which Python variables are bound to what CompilerVariables at the end of this block.
// phi_symbol_table records the ones that will need to be `phi'd.
// both only record non-globals.
// TODO: switch these to unique_ptr's
SymbolTable* symbol_table;
ConcreteSymbolTable* phi_symbol_table;
DefinednessTable* definedness_vars;
llvm::BasicBlock* ending_block;
llvm::SmallVector<ExceptionState, 2> exception_state;
EndingState(SymbolTable* symbol_table, ConcreteSymbolTable* phi_symbol_table, llvm::BasicBlock* ending_block,
EndingState(SymbolTable* symbol_table, ConcreteSymbolTable* phi_symbol_table,
DefinednessTable* definedness_vars, llvm::BasicBlock* ending_block,
llvm::ArrayRef<ExceptionState> exception_state)
: symbol_table(symbol_table),
phi_symbol_table(phi_symbol_table),
definedness_vars(definedness_vars),
ending_block(ending_block),
exception_state(exception_state.begin(), exception_state.end()) {}
};
......@@ -159,6 +178,8 @@ public:
= 0;
virtual void giveLocalSymbol(InternedString name, CompilerVariable* var) = 0;
virtual void giveLocalSymbol(int vreg, CompilerVariable* var) = 0;
virtual void giveDefinednessVar(int vreg, llvm::Value* val) = 0;
virtual void copySymbolsFrom(SymbolTable* st) = 0;
virtual void run(const CFGBlock* block) = 0; // primary entry point
virtual EndingState getEndingSymbolTable() = 0;
......
......@@ -18,6 +18,7 @@
#include <map>
#include <vector>
#include "core/cfg.h"
#include "core/stringpool.h"
namespace llvm {
......@@ -32,7 +33,11 @@ struct StackMap;
class OSREntryDescriptor {
private:
OSREntryDescriptor(FunctionMetadata* md, AST_Jump* backedge, ExceptionStyle exception_style)
: md(md), backedge(backedge), exception_style(exception_style) {
: md(md),
backedge(backedge),
exception_style(exception_style),
args(md->source->cfg->getVRegInfo().getTotalNumOfVRegs()),
potentially_undefined(md->source->cfg->getVRegInfo().getTotalNumOfVRegs()) {
assert(md);
}
......@@ -40,8 +45,9 @@ public:
FunctionMetadata* md;
AST_Jump* const backedge;
ExceptionStyle exception_style;
typedef std::map<InternedString, ConcreteCompilerType*> ArgMap;
typedef VRegMap<ConcreteCompilerType*> ArgMap;
ArgMap args;
VRegSet potentially_undefined;
static OSREntryDescriptor* create(FunctionMetadata* md, AST_Jump* backedge, ExceptionStyle exception_style) {
return new OSREntryDescriptor(md, backedge, exception_style);
......
......@@ -218,9 +218,9 @@ AST_arguments* read_arguments(BufferedReader* reader) {
readExprVector(rtn->args, reader);
rtn->col_offset = -1;
readExprVector(rtn->defaults, reader);
rtn->kwarg = reader->readAndInternString();
rtn->kwarg = ast_cast<AST_Name>(readASTExpr(reader));
rtn->lineno = -1;
rtn->vararg = reader->readAndInternString();
rtn->vararg = ast_cast<AST_Name>(readASTExpr(reader));
return rtn;
}
......@@ -1042,9 +1042,9 @@ AST_Module* parse_file(const char* fn, FutureFlags inherited_flags) {
const char* getMagic() {
if (ENABLE_PYPA_PARSER)
return "a\ncQ";
return "a\ncR";
else
return "a\nCQ";
return "a\nCR";
}
#define MAGIC_STRING_LENGTH 4
......
......@@ -30,10 +30,6 @@
namespace pyston {
void PatchpointInfo::addFrameVar(llvm::StringRef name, CompilerType* type) {
frame_vars.push_back(FrameVarInfo({.name = name, .type = type }));
}
int ICSetupInfo::totalSize() const {
if (isDeopt())
return DEOPT_CALL_ONLY_SIZE;
......@@ -74,30 +70,46 @@ bool StackMap::Record::Location::operator==(const StackMap::Record::Location& rh
}
void PatchpointInfo::parseLocationMap(StackMap::Record* r, LocationMap* map) {
if (!this->isDeopt())
return;
assert(r->locations.size() == totalStackmapArgs());
int cur_arg = frameStackmapArgsStart();
// printf("parsing pp %ld:\n", reinterpret_cast<int64_t>(this));
for (FrameVarInfo& frame_var : frame_vars) {
int num_args = frame_var.type->numFrameArgs();
auto parse_type = [&](CompilerType* type) {
int num_args = type->numFrameArgs();
llvm::SmallVector<StackMap::Record::Location, 1> locations;
locations.append(r->locations.data() + cur_arg, r->locations.data() + cur_arg + num_args);
// printf("%s %d %d\n", frame_var.name.c_str(), r->locations[cur_arg].type, r->locations[cur_arg].regnum);
map->names[frame_var.name].locations.push_back(
LocationMap::LocationTable::LocationEntry({._debug_pp_id = (uint64_t) this,
.offset = r->offset,
.length = patchpointSize(),
.type = frame_var.type,
.locations = std::move(locations) }));
cur_arg += num_args;
return LocationMap::LocationTable::LocationEntry({._debug_pp_id = (uint64_t) this,
.offset = r->offset,
.length = patchpointSize(),
.type = type,
.locations = std::move(locations) });
};
auto&& source = parentFunction()->md->source;
if (source->is_generator)
map->generator.locations.push_back(parse_type(GENERATOR));
if (source->getScopeInfo()->takesClosure())
map->passed_closure.locations.push_back(parse_type(CLOSURE));
if (source->getScopeInfo()->createsClosure())
map->created_closure.locations.push_back(parse_type(CLOSURE));
for (FrameVarInfo& frame_var : frame_info_desc.vars) {
map->vars[frame_var.vreg].locations.push_back(parse_type(frame_var.type));
}
assert(cur_arg - frameStackmapArgsStart() == numFrameStackmapArgs());
for (int vreg : frame_info_desc.potentially_undefined) {
map->definedness_vars[vreg].locations.push_back(parse_type(BOOL));
}
ASSERT(cur_arg - frameStackmapArgsStart() == numFrameStackmapArgs(), "%d %d %d", cur_arg, frameStackmapArgsStart(),
numFrameStackmapArgs());
}
static int extractScratchOffset(PatchpointInfo* pp, StackMap::Record* r) {
......
......@@ -96,9 +96,13 @@ public:
struct PatchpointInfo {
public:
struct FrameVarInfo {
llvm::StringRef name;
int vreg;
CompilerType* type;
};
struct FrameInfoDesc {
std::vector<FrameVarInfo> vars;
llvm::SmallVector<int, 2> potentially_undefined;
};
private:
CompiledFunction* const parent_cf;
......@@ -106,10 +110,10 @@ private:
int num_ic_stackmap_args;
int num_frame_stackmap_args;
bool is_frame_info_stackmap;
std::vector<FrameVarInfo> frame_vars;
unsigned int id;
FrameInfoDesc frame_info_desc;
PatchpointInfo(CompiledFunction* parent_cf, const ICSetupInfo* icinfo, int num_ic_stackmap_args)
: parent_cf(parent_cf),
icinfo(icinfo),
......@@ -125,7 +129,7 @@ public:
int patchpointSize();
CompiledFunction* parentFunction() { return parent_cf; }
const std::vector<FrameVarInfo>& getFrameVars() { return frame_vars; }
FrameInfoDesc& getFrameDesc() { return frame_info_desc; }
int scratchStackmapArg() { return 0; }
int scratchSize() { return isDeopt() ? MAX_FRAME_SPILLS * sizeof(void*) : 96; }
......@@ -133,7 +137,11 @@ public:
bool isFrameInfoStackmap() const { return is_frame_info_stackmap; }
int numFrameSpillsSupported() const { return isDeopt() ? MAX_FRAME_SPILLS : 0; }
void addFrameVar(llvm::StringRef name, CompilerType* type);
void addFrameVar(int vreg, CompilerType* type) {
frame_info_desc.vars.push_back(FrameVarInfo({.vreg = vreg, .type = type }));
}
void addPotentiallyUndefined(int vreg) { frame_info_desc.potentially_undefined.push_back(vreg); }
void setNumFrameArgs(int num_frame_args) {
assert(num_frame_stackmap_args == -1);
num_frame_stackmap_args = num_frame_args;
......
......@@ -301,8 +301,12 @@ AST_arguments* readItem(pypa::AstArguments& a, InternedStringPool& interned_stri
readVector(ptr->defaults, a.defaults, interned_strings);
ptr->defaults.erase(std::remove(ptr->defaults.begin(), ptr->defaults.end(), nullptr), ptr->defaults.end());
readVector(ptr->args, a.arguments, interned_strings);
ptr->kwarg = readName(a.kwargs, interned_strings);
ptr->vararg = readName(a.args, interned_strings);
InternedString kwarg_name = readName(a.kwargs, interned_strings);
if (kwarg_name.s().size())
ptr->kwarg = new AST_Name(kwarg_name, AST_TYPE::Store, -1, -1);
InternedString vararg_name = readName(a.args, interned_strings);
if (vararg_name.s().size())
ptr->vararg = new AST_Name(vararg_name, AST_TYPE::Store, -1, -1);
return ptr;
}
......
......@@ -176,8 +176,8 @@ private:
virtual bool visit_arguments(AST_arguments* node) {
writeExprVector(node->args);
writeExprVector(node->defaults);
writeString(node->kwarg);
writeString(node->vararg);
writeExpr(node->kwarg);
writeExpr(node->vararg);
return true;
}
virtual bool visit_assert(AST_Assert* node) {
......
......@@ -19,6 +19,7 @@
#include <unordered_map>
#include <vector>
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
......@@ -101,7 +102,9 @@ public:
}
};
llvm::StringMap<LocationTable> names;
llvm::DenseMap<int, LocationTable> vars;
LocationTable generator, passed_closure, created_closure;
llvm::DenseMap<int, LocationTable> definedness_vars;
};
StackMap* parseStackMap();
......
......@@ -329,25 +329,6 @@ public:
}
}
llvm::ArrayRef<StackMap::Record::Location> findLocations(llvm::StringRef name) {
assert(id.type == PythonFrameId::COMPILED);
CompiledFunction* cf = getCF();
uint64_t ip = getId().ip;
assert(ip > cf->code_start);
unsigned offset = ip - cf->code_start;
assert(cf->location_map);
const LocationMap::LocationTable& table = cf->location_map->names[name];
auto entry = table.findEntry(offset);
if (!entry)
return {};
assert(entry->locations.size());
return entry->locations;
}
AST_stmt* getCurrentStatement() {
assert(getFrameInfo()->stmt);
return getFrameInfo()->stmt;
......@@ -870,20 +851,37 @@ DeoptState getDeoptState() {
// We have to detect + ignore any entries for variables that
// could have been defined (so they have entries) but aren't (so the
// entries point to uninitialized memory).
std::unordered_set<std::string> is_undefined;
std::unordered_set<int> is_undefined;
for (const auto& p : cf->location_map->names) {
if (!startswith(p.first(), "!is_defined_"))
continue;
auto readEntry = [&](const LocationMap::LocationTable::LocationEntry* e) {
auto locs = e->locations;
llvm::SmallVector<uint64_t, 1> vals;
// printf("%s: %s\n", p.first().c_str(), e.type->debugName().c_str());
for (auto& loc : locs) {
vals.push_back(frame_iter->readLocation(loc));
}
// this returns an owned reference so we don't incref it
Box* v = e->type->deserializeFromFrame(vals);
return v;
};
if (auto e = cf->location_map->generator.findEntry(offset))
d->d[boxString(PASSED_GENERATOR_NAME)] = readEntry(e);
if (auto e = cf->location_map->passed_closure.findEntry(offset))
d->d[boxString(PASSED_CLOSURE_NAME)] = readEntry(e);
if (auto e = cf->location_map->created_closure.findEntry(offset))
d->d[boxString(CREATED_CLOSURE_NAME)] = readEntry(e);
for (const auto& p : cf->location_map->definedness_vars) {
auto e = p.second.findEntry(offset);
if (e) {
auto locs = e->locations;
assert(locs.size() == 1);
uint64_t v = frame_iter->readLocation(locs[0]);
if ((v & 1) == 0)
is_undefined.insert(p.first().substr(12));
Box* b = readEntry(e);
AUTO_DECREF(b);
if (b == Py_False)
is_undefined.insert(p.first);
}
}
......@@ -893,40 +891,23 @@ DeoptState getDeoptState() {
// But deopts are so rare it's not really worth it.
Box** vregs = frame_iter->getFrameInfo()->vregs;
for (const auto& p : cf->md->source->cfg->getVRegInfo().getUserVisibleSymVRegMap()) {
if (is_undefined.count(p.first.s()))
continue;
if (is_undefined.count(p.second))
assert(0);
Box* v = vregs[p.second];
if (!v)
continue;
assert(!d->d.count(p.first.getBox()));
d->d[incref(p.first.getBox())] = incref(v);
d->d[boxInt(p.second)] = incref(v);
}
for (const auto& p : cf->location_map->names) {
if (p.first()[0] == '!')
continue;
if (is_undefined.count(p.first()))
for (const auto& p : cf->location_map->vars) {
if (is_undefined.count(p.first))
continue;
auto e = p.second.findEntry(offset);
if (e) {
auto locs = e->locations;
llvm::SmallVector<uint64_t, 1> vals;
// printf("%s: %s\n", p.first().c_str(), e.type->debugName().c_str());
for (auto& loc : locs) {
vals.push_back(frame_iter->readLocation(loc));
}
// this returns an owned reference so we don't incref it
Box* v = e->type->deserializeFromFrame(vals);
// printf("%s: (pp id %ld) %p\n", p.first().c_str(), e._debug_pp_id, v);
d->d[boxString(p.first())] = v;
}
if (e)
d->d[boxInt(p.first)] = readEntry(e);
}
} else {
abort();
......@@ -1093,6 +1074,10 @@ extern "C" void abort() {
// In case displaying the traceback recursively calls abort:
static bool recursive = false;
if (recursive) {
fprintf(stderr, "Recursively called abort! Make sure to check the stack trace\n");
}
if (!recursive && !IN_SHUTDOWN) {
recursive = true;
Stats::dump();
......
......@@ -256,6 +256,10 @@ void AST_arguments::accept(ASTVisitor* v) {
visitVector(defaults, v);
visitVector(args, v);
if (kwarg)
kwarg->accept(v);
if (vararg)
vararg->accept(v);
}
void AST_Assert::accept(ASTVisitor* v) {
......
......@@ -217,6 +217,7 @@ public:
class AST_alias : public AST {
public:
InternedString name, asname;
int name_vreg = -1, asname_vreg = -1;
virtual void accept(ASTVisitor* v);
......@@ -225,14 +226,14 @@ public:
static const AST_TYPE::AST_TYPE TYPE = AST_TYPE::alias;
};
class AST_Name;
class AST_arguments : public AST {
public:
// no lineno, col_offset attributes
std::vector<AST_expr*> args, defaults;
// These are represented as strings, not names; not sure why.
// If they don't exist, the string is empty.
InternedString kwarg, vararg;
AST_Name* kwarg = NULL, * vararg = NULL;
virtual void accept(ASTVisitor* v);
......@@ -1116,7 +1117,7 @@ public:
};
template <typename T> T* ast_cast(AST* node) {
assert(node->type == T::TYPE);
assert(!node || node->type == T::TYPE);
return static_cast<T*>(node);
}
......
......@@ -232,6 +232,9 @@ private:
CFGBlock* exc_dest;
// variable names to store the exception (type, value, traceback) in
InternedString exc_type_name, exc_value_name, exc_traceback_name;
// Similar to did_why: says whether the block might have been jumped-to
bool maybe_taken;
};
// ---------- Member fields ----------
......@@ -517,9 +520,11 @@ private:
return node;
}
void pushJump(CFGBlock* target, bool allow_backedge = false) {
void pushJump(CFGBlock* target, bool allow_backedge = false, int lineno = 0) {
AST_Jump* rtn = new AST_Jump();
rtn->target = target;
rtn->lineno = lineno;
push_back(rtn);
curblock->connectTo(target, allow_backedge);
curblock = nullptr;
......@@ -1007,8 +1012,8 @@ private:
InternedString func_name = internString("<comprehension>");
func->name = func_name;
func->args = new AST_arguments();
func->args->vararg = internString("");
func->args->kwarg = internString("");
func->args->vararg = NULL;
func->args->kwarg = NULL;
scoping_analysis->registerScopeReplacement(node, func); // critical bit
return new AST_MakeFunction(func);
}
......@@ -1574,6 +1579,7 @@ public:
curblock->connectTo(exc_dest);
ExcBlockInfo& exc_info = exc_handlers.back();
exc_info.maybe_taken = true;
curblock = exc_dest;
// TODO: need to clear some temporaries here
......@@ -1613,7 +1619,6 @@ public:
auto tmp = nodeName();
pushAssign(tmp, new AST_MakeClass(def));
// is this name mangling correct?
pushAssign(source->mangleName(def->name), makeName(tmp, AST_TYPE::Load, node->lineno, 0, true));
return true;
......@@ -1635,7 +1640,6 @@ public:
auto tmp = nodeName();
pushAssign(tmp, new AST_MakeFunction(def));
// is this name mangling correct?
pushAssign(source->mangleName(def->name), makeName(tmp, AST_TYPE::Load, node->lineno, node->col_offset, true));
return true;
......@@ -2266,7 +2270,7 @@ public:
curblock->connectTo(end_false);
curblock = end_true;
pushJump(loop_block, true);
pushJump(loop_block, true, getLastLinenoSub(node->body.back()));
curblock = end_false;
pushJump(else_block);
......@@ -2341,7 +2345,7 @@ public:
InternedString exc_type_name = nodeName("type");
InternedString exc_value_name = nodeName("value");
InternedString exc_traceback_name = nodeName("traceback");
exc_handlers.push_back({ exc_handler_block, exc_type_name, exc_value_name, exc_traceback_name });
exc_handlers.push_back({ exc_handler_block, exc_type_name, exc_value_name, exc_traceback_name, false });
for (AST_stmt* subnode : node->body) {
subnode->accept(this);
......@@ -2464,7 +2468,7 @@ public:
InternedString exc_value_name = nodeName("value");
InternedString exc_traceback_name = nodeName("traceback");
InternedString exc_why_name = nodeName("why");
exc_handlers.push_back({ exc_handler_block, exc_type_name, exc_value_name, exc_traceback_name });
exc_handlers.push_back({ exc_handler_block, exc_type_name, exc_value_name, exc_traceback_name, false });
CFGBlock* finally_block = cfg->addDeferredBlock();
pushFinallyContinuation(finally_block, exc_why_name);
......@@ -2475,6 +2479,7 @@ public:
break;
}
bool maybe_exception = exc_handlers.back().maybe_taken;
exc_handlers.pop_back();
int did_why = continuations.back().did_why; // bad to just reach in like this
......@@ -2512,15 +2517,17 @@ public:
exitFinallyIf(node, Why::BREAK, exc_why_name);
if (did_why & (1 << Why::CONTINUE))
exitFinallyIf(node, Why::CONTINUE, exc_why_name);
if (maybe_exception) {
CFGBlock* reraise = cfg->addDeferredBlock();
CFGBlock* noexc = makeFinallyCont(Why::EXCEPTION, makeLoad(exc_why_name, node, true), reraise);
CFGBlock* reraise = cfg->addDeferredBlock();
CFGBlock* noexc = makeFinallyCont(Why::EXCEPTION, makeLoad(exc_why_name, node, true), reraise);
cfg->placeBlock(reraise);
curblock = reraise;
pushReraise(getLastLinenoSub(node->finalbody.back()), exc_type_name, exc_value_name, exc_traceback_name);
cfg->placeBlock(reraise);
curblock = reraise;
pushReraise(getLastLinenoSub(node->finalbody.back()), exc_type_name, exc_value_name,
exc_traceback_name);
curblock = noexc;
curblock = noexc;
}
}
return true;
......@@ -2585,7 +2592,7 @@ public:
CFGBlock* exc_block = cfg->addDeferredBlock();
exc_block->info = "with_exc";
exc_handlers.push_back({ exc_block, exc_type_name, exc_value_name, exc_traceback_name });
exc_handlers.push_back({ exc_block, exc_type_name, exc_value_name, exc_traceback_name, false });
for (int i = 0; i < node->body.size(); i++) {
node->body[i]->accept(this);
......@@ -2679,13 +2686,16 @@ public:
ScopeInfo* scope_info;
CFGBlock* current_block;
int next_vreg;
llvm::DenseMap<InternedString, int> sym_vreg_map;
llvm::DenseMap<InternedString, DefaultedInt<-1>> sym_vreg_map;
llvm::DenseMap<InternedString, std::unordered_set<CFGBlock*>> sym_blocks_map;
std::vector<InternedString> vreg_sym_map;
enum Step { TrackBlockUsage = 0, UserVisible, CrossBlock, SingleBlockUse } step;
AssignVRegsVisitor(ScopeInfo* scope_info) : scope_info(scope_info), current_block(0), next_vreg(0) {}
bool visit_alias(AST_alias* node) override { RELEASE_ASSERT(0, "these should be removed by the cfg"); }
bool visit_arguments(AST_arguments* node) override {
for (AST_expr* d : node->defaults)
d->accept(this);
......@@ -2748,9 +2758,16 @@ public:
}
int assignVReg(InternedString id) {
assert(id.s().size());
auto it = sym_vreg_map.find(id);
if (sym_vreg_map.end() == it) {
sym_vreg_map[id] = next_vreg;
if (!REUSE_VREGS || step == UserVisible || step == CrossBlock) {
assert(next_vreg == vreg_sym_map.size());
vreg_sym_map.push_back(id);
}
return next_vreg++;
}
return it->second;
......@@ -2768,8 +2785,10 @@ void VRegInfo::assignVRegs(CFG* cfg, const ParamNames& param_names, ScopeInfo* s
for (CFGBlock* b : cfg->blocks) {
visitor.current_block = b;
#if REUSE_VREGS
if (step == AssignVRegsVisitor::SingleBlockUse)
visitor.next_vreg = num_vregs_cross_block;
#endif
if (b == cfg->getStartingBlock()) {
for (auto* name : param_names.arg_names) {
......@@ -2796,7 +2815,13 @@ void VRegInfo::assignVRegs(CFG* cfg, const ParamNames& param_names, ScopeInfo* s
num_vregs = num_vregs_cross_block = visitor.next_vreg;
}
sym_vreg_map = std::move(visitor.sym_vreg_map);
vreg_sym_map = std::move(visitor.vreg_sym_map);
assert(hasVRegsAssigned());
#if REUSE_VREGS
assert(vreg_sym_map.size() == num_vregs_cross_block);
#else
assert(vreg_sym_map.size() == num_vregs);
#endif
}
CFG* computeCFG(SourceInfo* source, std::vector<AST_stmt*> body, const ParamNames& param_names) {
......
This diff is collapsed.
......@@ -316,6 +316,7 @@ class BoxedGenerator;
class ICInfo;
class LocationMap;
class JitCodeBlock;
class FrameInfo;
extern std::vector<Box*> constants;
extern std::vector<Box*> late_constants; // constants that should be freed after normal constants
......@@ -346,6 +347,8 @@ public:
// The function pointer to the generated code. For convenience, it can be accessed
// as one of many different types.
// TODO: we instead make these accessor-functions that make sure that the code actually
// matches the C signature that we would return.
union {
Box* (*call)(Box*, Box*, Box*, Box**);
Box* (*closure_call)(BoxedClosure*, Box*, Box*, Box*, Box**);
......@@ -354,6 +357,7 @@ public:
Box* (*call1)(Box*, Box*, Box*, Box*, Box**);
Box* (*call2)(Box*, Box*, Box*, Box*, Box*, Box**);
Box* (*call3)(Box*, Box*, Box*, Box*, Box*, Box*, Box**);
Box* (*call_osr)(BoxedGenerator*, BoxedClosure*, FrameInfo*, Box**);
void* code;
uintptr_t code_start;
};
......@@ -375,7 +379,7 @@ public:
// List of metadata objects for ICs inside this compilation
std::vector<ICInfo*> ics;
CompiledFunction(llvm::Function* func, FunctionSpecialization* spec, void* code, EffortLevel effort,
CompiledFunction(FunctionMetadata* func, FunctionSpecialization* spec, void* code, EffortLevel effort,
ExceptionStyle exception_style, const OSREntryDescriptor* entry_descriptor);
ConcreteCompilerType* getReturnType();
......
......@@ -95,19 +95,19 @@ void removeDirectoryIfExists(const std::string& path);
// Checks that lhs and rhs, which are iterables of InternedStrings, have the
// same set of names in them.
template <class T1, class T2> bool sameKeyset(T1* lhs, T2* rhs) {
std::vector<InternedString> lv, rv;
for (typename T1::iterator it = lhs->begin(); it != lhs->end(); it++) {
lv.push_back(it->first);
std::vector<int> lv, rv;
for (typename T1::iterator it = lhs->begin(); it != lhs->end(); ++it) {
lv.push_back((*it).first);
}
for (typename T2::iterator it = rhs->begin(); it != rhs->end(); it++) {
rv.push_back(it->first);
for (typename T2::iterator it = rhs->begin(); it != rhs->end(); ++it) {
rv.push_back((*it).first);
}
std::sort(lv.begin(), lv.end());
std::sort(rv.begin(), rv.end());
std::vector<InternedString> lextra(lv.size());
std::vector<InternedString>::iterator diffend
std::vector<int> lextra(lv.size());
std::vector<int>::iterator diffend
= std::set_difference(lv.begin(), lv.end(), rv.begin(), rv.end(), lextra.begin());
lextra.resize(diffend - lextra.begin());
......@@ -115,19 +115,19 @@ template <class T1, class T2> bool sameKeyset(T1* lhs, T2* rhs) {
if (lextra.size()) {
printf("Only in lhs:\n");
for (int i = 0; i < lextra.size(); i++) {
printf("%s\n", lextra[i].c_str());
printf("%d\n", lextra[i]);
}
good = false;
}
std::vector<InternedString> rextra(rv.size());
std::vector<int> rextra(rv.size());
diffend = std::set_difference(rv.begin(), rv.end(), lv.begin(), lv.end(), rextra.begin());
rextra.resize(diffend - rextra.begin());
if (rextra.size()) {
printf("Only in rhs:\n");
for (int i = 0; i < rextra.size(); i++) {
printf("%s\n", rextra[i].c_str());
printf("%d\n", rextra[i]);
}
good = false;
}
......
......@@ -137,6 +137,8 @@ extern "C" void xdecrefAndRethrow(void* cxa_ptr, int num, ...) {
}
extern "C" Box* deopt(AST_expr* expr, Box* value) {
ASSERT(ENABLE_FRAME_INTROSPECTION, "deopt will not work with frame introspection turned off");
STAT_TIMER(t0, "us_timer_deopt", 10);
static StatCounter num_deopt("num_deopt");
......
......@@ -10,12 +10,18 @@ PYOPENSSL_DIR = os.path.abspath(os.path.join(ENV_NAME, "site-packages", "OpenSSL
packages = ["nose==1.3.7", "pycparser==2.13", "cryptography==1.0.1", "pyopenssl==0.15.1", "pyasn1==0.1.7", "idna==2.0", "six==1.9.0", "enum34==1.0.4", "ipaddress==1.0.14", "cffi==1.1.0"]
create_virtenv(ENV_NAME, packages, force_create = True)
import subprocess
# This particular test is bad; it depends on certain implementation details of the openssl library
# it's linked against. It fails in cpython and for other people as well
# https://www.mail-archive.com/ports@openbsd.org/msg52063.html
import subprocess
subprocess.check_call(["sed", "-i", 's/\\(def test_digest.*\\)/\\1\\n return/',
os.path.join(PYOPENSSL_DIR, "test", "test_crypto.py")])
# This particular test is bad; it fails if run close to a second-boundary
# https://github.com/pyca/pyopenssl/issues/266
subprocess.check_call(["sed", "-i", 's/\\(def test_export_test.*\\)/\\1\\n return/',
os.path.join(PYOPENSSL_DIR, "test", "test_crypto.py")])
expected = [{'ran': 438}]
run_test([NOSETESTS_EXE], cwd=PYOPENSSL_DIR, expected=expected)
# skip-if: '-O' in EXTRA_JIT_ARGS or '-n' in EXTRA_JIT_ARGS
# statcheck: noninit_count('num_deopt') == 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 triggers_deopt(x):
if x < 90:
return ""
return unicode("")
class C():
def f(self, x, b):
if b and x < 90:
y = 1
triggers_deopt(x).isalnum
try:
print y
assert b
except UnboundLocalError as e:
print e
c = C()
for i in range(91):
c.f(i, True)
c = C()
for i in range(91):
c.f(i, False)
# Some corner cases around name scopes
def f1():
exec ""
from sys import version as sys_version
f1()
def f2():
exec ""
def f3(*args, **kw):
exec ""
print args, kw
f3(*[1, 2], **dict(a=1, b=2))
f2()
import sys
import os.path
print sys.excepthook, sys.displayhook
assert callable(sys.excepthook)
print sys.displayhook
print sys.version[:3]
print os.path.exists(sys.executable)
print sys.copyright[-200:]
......
This diff is collapsed.
This diff is collapsed.
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