Commit 06ffe979 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Add a bunch of misc debugging helpers

parent d4df5d7e
......@@ -2,6 +2,12 @@
# This module should be kept compatible with Python 2.2, see PEP 291.
from __future__ import generators
# Pyston change:
import sys
del sys.modules['modulefinder']
raise ImportError("This isn't really supported in Pyston yet")
import dis
import imp
import marshal
......
......@@ -64,7 +64,7 @@ union Value {
Value(double d) : d(d) {}
Value(Box* o) : o(o) {
if (DEBUG >= 2)
assert(gc::isValidGCObject(o));
ASSERT(gc::isValidGCObject(o), "%p", o);
}
};
......@@ -532,8 +532,15 @@ Value ASTInterpreter::visit_jump(AST_Jump* node) {
CompiledFunction* partial_func = compilePartialFuncInternal(&exit);
auto arg_tuple = getTupleFromArgsArray(&arg_array[0], arg_array.size());
return partial_func->call(std::get<0>(arg_tuple), std::get<1>(arg_tuple), std::get<2>(arg_tuple),
Box* r = partial_func->call(std::get<0>(arg_tuple), std::get<1>(arg_tuple), std::get<2>(arg_tuple),
std::get<3>(arg_tuple));
// This is one of the few times that we are allowed to have an invalid value in a Box* Value.
// Check for it, and return as an int so that we don't trigger a potential assert when
// creating the Value.
if (compiled_func->getReturnType() != VOID)
assert(r);
return (intptr_t)r;
}
}
......
......@@ -985,7 +985,9 @@ AST_Module* parse_file(const char* fn) {
Timer _t("parsing");
if (ENABLE_PYPA_PARSER) {
return pypa_parse(fn);
AST_Module* rtn = pypa_parse(fn);
assert(rtn);
return rtn;
}
FILE* fp = popen(getParserCommandLine(fn).c_str(), "r");
......
......@@ -699,7 +699,7 @@ FrameStackState getFrameStackState() {
Box* v = e.type->deserializeFromFrame(vals);
// printf("%s: (pp id %ld) %p\n", p.first.c_str(), e._debug_pp_id, v);
assert(gc::isValidGCObject(v));
ASSERT(gc::isValidGCObject(v), "%p", v);
d->d[boxString(p.first)] = v;
}
}
......
......@@ -82,7 +82,10 @@ static int main(int argc, char** argv) {
bool stats = false;
bool unbuffered = false;
const char* command = NULL;
while ((code = getopt(argc, argv, "+OqdIibpjtrsSvnxc:FuP")) != -1) {
// Suppress getopt errors so we can throw them ourselves
opterr = 0;
while ((code = getopt(argc, argv, "+:OqdIibpjtrsSvnxc:FuP")) != -1) {
if (code == 'O')
FORCE_OPTIMIZE = true;
else if (code == 't')
......@@ -120,12 +123,25 @@ static int main(int argc, char** argv) {
} else if (code == 'F') {
CONTINUE_AFTER_FATAL = true;
} else if (code == 'c') {
assert(optarg);
command = optarg;
// no more option parsing; the rest of our arguments go into sys.argv.
break;
} else
} else {
if (code == ':') {
fprintf(stderr, "Argument expected for the -%c option\n", optopt);
return 2;
}
if (code == '?') {
fprintf(stderr, "Unknown option: -%c\n", optopt);
return 2;
}
fprintf(stderr, "Unknown getopt() error. '%c' '%c'\n", code, optopt);
abort();
}
}
const char* fn = NULL;
......
......@@ -1579,7 +1579,6 @@ Box* getattrInternalGeneric(Box* obj, const std::string& attr, GetattrRewriteArg
return getattrInternalEx(static_cast<BoxedInstanceMethod*>(obj)->func, attr, NULL, cls_only, for_call,
bind_obj_out, NULL);
}
// Finally, check __getattr__
if (rewrite_args) {
rewrite_args->out_success = true;
......@@ -2160,7 +2159,7 @@ extern "C" i64 unboxedLen(Box* obj) {
return rtn;
}
extern "C" void dump(void* p) {
extern "C" void dumpEx(void* p, int levels) {
printf("\n");
printf("Raw address: %p\n", p);
......@@ -2233,7 +2232,32 @@ extern "C" void dump(void* p) {
}
if (isSubclass(b->cls, tuple_cls)) {
printf("%ld elements\n", static_cast<BoxedTuple*>(b)->size());
BoxedTuple* t = static_cast<BoxedTuple*>(b);
printf("%ld elements\n", t->size());
if (levels > 0) {
int i = 0;
for (auto e : *t) {
printf("\nElement %d:", i);
i++;
dumpEx(e, levels - 1);
}
}
}
if (isSubclass(b->cls, dict_cls)) {
BoxedDict* d = static_cast<BoxedDict*>(b);
printf("%ld elements\n", d->d.size());
if (levels > 0) {
int i = 0;
for (auto t : d->d) {
printf("\nKey:");
dumpEx(t.first, levels - 1);
printf("Value:");
dumpEx(t.second, levels - 1);
}
}
}
if (isSubclass(b->cls, int_cls)) {
......@@ -2269,6 +2293,10 @@ extern "C" void dump(void* p) {
RELEASE_ASSERT(0, "%d", (int)al->kind_id);
}
extern "C" void dump(void* p) {
dumpEx(p, 0);
}
// For rewriting purposes, this function assumes that nargs will be constant.
// That's probably fine for some uses (ex binops), but otherwise it should be guarded on beforehand.
extern "C" Box* callattrInternal(Box* obj, const std::string* attr, LookupScope scope, CallRewriteArgs* rewrite_args,
......@@ -2441,7 +2469,7 @@ extern "C" Box* callattrInternal(Box* obj, const std::string* attr, LookupScope
extern "C" Box* callattr(Box* obj, const std::string* attr, CallattrFlags flags, ArgPassSpec argspec, Box* arg1,
Box* arg2, Box* arg3, Box** args, const std::vector<const std::string*>* keyword_names) {
assert(gc::isValidGCObject(obj));
ASSERT(gc::isValidGCObject(obj), "%p", obj);
int npassed_args = argspec.totalPassed();
......
......@@ -94,6 +94,7 @@ extern "C" Box* createBoxedIterWrapperIfNeeded(Box* o);
extern "C" bool hasnext(Box* o);
extern "C" void dump(void* p);
extern "C" void dumpEx(void* p, int levels = 0);
struct SetattrRewriteArgs;
void setattrGeneric(Box* obj, const std::string& attr, Box* val, SetattrRewriteArgs* rewrite_args);
......
......@@ -159,7 +159,8 @@ extern "C" void abort() {
// In case something calls abort down the line:
static bool recursive = false;
if (!recursive) {
// If object_cls is NULL, then we somehow died early on, and won't be able to display a traceback.
if (!recursive && object_cls) {
recursive = true;
fprintf(stderr, "Someone called abort!\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