Commit fe668bcf authored by Michael Arntzenius's avatar Michael Arntzenius

add some coments, TODOs, and FIXMEs

parent 42021be6
...@@ -90,6 +90,7 @@ private: ...@@ -90,6 +90,7 @@ private:
// This is probably a bunch worse than LRU, but it's also // This is probably a bunch worse than LRU, but it's also
// probably a bunch better than the "always evict slot #0" policy // probably a bunch better than the "always evict slot #0" policy
// that it's replacing. // that it's replacing.
// TODO: experiment with different IC eviction strategies.
int next_slot_to_try; int next_slot_to_try;
const StackInfo stack_info; const StackInfo stack_info;
......
...@@ -274,6 +274,9 @@ void ASTInterpreter::initArguments(int nargs, BoxedClosure* _closure, BoxedGener ...@@ -274,6 +274,9 @@ void ASTInterpreter::initArguments(int nargs, BoxedClosure* _closure, BoxedGener
} }
} }
// Map from stack frame pointers for frames corresponding to ASTInterpreter::execute() to the ASTInterpreter handling
// them. Used to look up information about that frame. This is used for getting tracebacks, for CPython introspection
// (sys._getframe & co), and for GC scanning.
static std::unordered_map<void*, ASTInterpreter*> s_interpreterMap; static std::unordered_map<void*, ASTInterpreter*> s_interpreterMap;
static_assert(THREADING_USE_GIL, "have to make the interpreter map thread safe!"); static_assert(THREADING_USE_GIL, "have to make the interpreter map thread safe!");
......
...@@ -1855,6 +1855,7 @@ private: ...@@ -1855,6 +1855,7 @@ private:
static const std::string newline_str("\n"); static const std::string newline_str("\n");
static const std::string space_str(" "); static const std::string space_str(" ");
// TODO: why are we inline-generating all this code instead of just emitting a call to some runtime function?
int nvals = node->values.size(); int nvals = node->values.size();
for (int i = 0; i < nvals; i++) { for (int i = 0; i < nvals; i++) {
CompilerVariable* var = evalExpr(node->values[i], unw_info); CompilerVariable* var = evalExpr(node->values[i], unw_info);
......
...@@ -530,6 +530,36 @@ static const LineInfo* lineInfoForFrame(PythonFrameIteratorImpl& frame_it) { ...@@ -530,6 +530,36 @@ static const LineInfo* lineInfoForFrame(PythonFrameIteratorImpl& frame_it) {
return new LineInfo(current_stmt->lineno, current_stmt->col_offset, source->fn, source->getName()); return new LineInfo(current_stmt->lineno, current_stmt->col_offset, source->fn, source->getName());
} }
// To produce a traceback, we:
//
// 1. Use libunwind to produce a cursor into our stack.
//
// 2. Grab the next frame in the stack and check what function it is from. There are four options:
//
// (a) A JIT-compiled Python function.
// (b) ASTInterpreter::execute() in codegen/ast_interpreter.cpp.
// (c) generatorEntry() in runtime/generator.cpp.
// (d) Something else.
//
// By cases:
//
// (2a, 2b) If the previous frame we visited was an OSR frame (which we know from its CompiledFunction*), then we
// skip this frame (it's the frame we replaced on-stack) and keep unwinding. (FIXME: Why are we guaranteed that we
// on-stack-replaced at most one frame?) Otherwise, we found a frame for our traceback! Proceed to step 3.
//
// (2c) Continue unwinding in the stack of whatever called the generator. This involves some hairy munging of
// undocumented fields in libunwind structs to swap the context.
//
// (2d) Ignore it and keep unwinding. It's some C or C++ function that we don't want in our traceback.
//
// 3. We've found a frame for our traceback, along with a CompiledFunction* and some other information about it.
//
// We grab the current statement it is in (as an AST_stmt*) and use it and the CompiledFunction*'s source info to
// produce the line information for the traceback. For JIT-compiled functions, getting the statement involves the
// CF's location_map.
//
// 4. Unless we've hit the end of the stack, go to 2 and keep unwinding.
//
static StatCounter us_gettraceback("us_gettraceback"); static StatCounter us_gettraceback("us_gettraceback");
BoxedTraceback* getTraceback() { BoxedTraceback* getTraceback() {
STAT_TIMER(t0, "us_timer_gettraceback"); STAT_TIMER(t0, "us_timer_gettraceback");
......
...@@ -489,6 +489,13 @@ extern "C" void PyEval_ReInitThreads() noexcept { ...@@ -489,6 +489,13 @@ extern "C" void PyEval_ReInitThreads() noexcept {
} }
} }
// We need to make sure the threading lock is released, so we unconditionally unlock it. After a fork, we are the
// only thread, so this won't race; and since it's a "fast" mutex (see `man pthread_mutex_lock`), this works even
// if it isn't locked. If we needed to avoid unlocking a non-locked mutex, though, we could trylock it first:
//
// int err = pthread_mutex_trylock(&threading_lock.mutex);
// ASSERT(!err || err == EBUSY, "pthread_mutex_trylock failed, but not with EBUSY");
//
threading_lock.unlock(); threading_lock.unlock();
num_starting_threads = 0; num_starting_threads = 0;
......
...@@ -689,6 +689,8 @@ struct FrameInfo { ...@@ -689,6 +689,8 @@ struct FrameInfo {
// In Pyston, exc is the frame-local value of sys.exc_info. // In Pyston, exc is the frame-local value of sys.exc_info.
// - This makes frame entering+leaving faster at the expense of slower exceptions. // - This makes frame entering+leaving faster at the expense of slower exceptions.
// //
// TODO: do we want exceptions to be slower? benchmark this!
//
// exc.type is initialized to NULL at function entry, and exc.value and exc.tb are left // exc.type is initialized to NULL at function entry, and exc.value and exc.tb are left
// uninitialized. When one wants to access any of the values, you need to check if exc.type // uninitialized. When one wants to access any of the values, you need to check if exc.type
// is NULL, and if so crawl up the stack looking for the first frame with a non-null exc.type // is NULL, and if so crawl up the stack looking for the first frame with a non-null exc.type
......
...@@ -877,6 +877,7 @@ Box* print(BoxedTuple* args, BoxedDict* kwargs) { ...@@ -877,6 +877,7 @@ Box* print(BoxedTuple* args, BoxedDict* kwargs) {
Box* space_box = boxStrConstant(" "); Box* space_box = boxStrConstant(" ");
// TODO softspace handling? // TODO softspace handling?
// TODO: duplicates code with ASTInterpreter::visit_print()
bool first = true; bool first = true;
for (auto e : *args) { for (auto e : *args) {
BoxedString* s = str(e); BoxedString* s = str(e);
......
...@@ -88,6 +88,9 @@ Box* startNewThread(Box* target, Box* args, Box* kw) { ...@@ -88,6 +88,9 @@ Box* startNewThread(Box* target, Box* args, Box* kw) {
* codes in the return value of the sem_ calls (like the pthread_ functions). * codes in the return value of the sem_ calls (like the pthread_ functions).
* Correct implementations return -1 and put the code in errno. This supports * Correct implementations return -1 and put the code in errno. This supports
* either. * either.
*
* NOTE (2015-05-14): According to `man pthread_mutex_lock` on my system (Ubuntu
* 14.10), returning the error code is expected behavior. - rntz
*/ */
static int fix_status(int status) { static int fix_status(int status) {
return (status == -1) ? errno : status; return (status == -1) ? errno : status;
......
...@@ -48,7 +48,7 @@ void showBacktrace() { ...@@ -48,7 +48,7 @@ void showBacktrace() {
void raiseRaw(const ExcInfo& e) __attribute__((__noreturn__)); void raiseRaw(const ExcInfo& e) __attribute__((__noreturn__));
void raiseRaw(const ExcInfo& e) { void raiseRaw(const ExcInfo& e) {
STAT_TIMER(t0, "us_timer_raiseraw"); STAT_TIMER(t0, "us_timer_raiseraw");
// Should set these to None before getting here: // Should set these to None rather than null before getting here:
assert(e.type); assert(e.type);
assert(e.value); assert(e.value);
assert(e.traceback); assert(e.traceback);
......
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