Commit 9030ec59 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge pull request #499 from kmod/sqlalchemy

import with globals
parents 801dec8c bd33badc
...@@ -23,6 +23,7 @@ addons: ...@@ -23,6 +23,7 @@ addons:
- clang-3.5 - clang-3.5
- cmake - cmake
- g++-4.8 - g++-4.8
- gdb
- libgmp3-dev - libgmp3-dev
- liblzma-dev - liblzma-dev
- libncurses5-dev - libncurses5-dev
...@@ -51,7 +52,7 @@ script: ...@@ -51,7 +52,7 @@ script:
- ccache -z - ccache -z
- ninja -j4 pyston - ninja -j4 pyston
- ccache -s - ccache -s
- ninja check-pyston - PYSTON_RUN_ARGS=G ninja check-pyston
os: os:
- linux - linux
......
...@@ -342,12 +342,7 @@ Value ASTInterpreter::doBinOp(Box* left, Box* right, int op, BinExpType exp_type ...@@ -342,12 +342,7 @@ Value ASTInterpreter::doBinOp(Box* left, Box* right, int op, BinExpType exp_type
void ASTInterpreter::doStore(InternedString name, Value value) { void ASTInterpreter::doStore(InternedString name, Value value) {
ScopeInfo::VarScopeType vst = scope_info->getScopeTypeOfName(name); ScopeInfo::VarScopeType vst = scope_info->getScopeTypeOfName(name);
if (vst == ScopeInfo::VarScopeType::GLOBAL) { if (vst == ScopeInfo::VarScopeType::GLOBAL) {
if (globals->cls == module_cls) { setGlobal(globals, name, value.o);
setattr(static_cast<BoxedModule*>(globals), name.c_str(), value.o);
} else {
assert(globals->cls == dict_cls);
static_cast<BoxedDict*>(globals)->d[boxString(name.str())] = value.o;
}
} else if (vst == ScopeInfo::VarScopeType::NAME) { } else if (vst == ScopeInfo::VarScopeType::NAME) {
assert(frame_info.boxedLocals != NULL); assert(frame_info.boxedLocals != NULL);
// TODO should probably pre-box the names when it's a scope that usesNameLookup // TODO should probably pre-box the names when it's a scope that usesNameLookup
...@@ -879,7 +874,6 @@ Value ASTInterpreter::visit_delete(AST_Delete* node) { ...@@ -879,7 +874,6 @@ Value ASTInterpreter::visit_delete(AST_Delete* node) {
ScopeInfo::VarScopeType vst = scope_info->getScopeTypeOfName(target->id); ScopeInfo::VarScopeType vst = scope_info->getScopeTypeOfName(target->id);
if (vst == ScopeInfo::VarScopeType::GLOBAL) { if (vst == ScopeInfo::VarScopeType::GLOBAL) {
// Can't use delattr since the errors are different:
delGlobal(globals, &target->id.str()); delGlobal(globals, &target->id.str());
continue; continue;
} else if (vst == ScopeInfo::VarScopeType::NAME) { } else if (vst == ScopeInfo::VarScopeType::NAME) {
......
...@@ -599,6 +599,8 @@ CompiledFunction* getTopCompiledFunction() { ...@@ -599,6 +599,8 @@ CompiledFunction* getTopCompiledFunction() {
Box* getGlobals() { Box* getGlobals() {
auto it = getTopPythonFrame(); auto it = getTopPythonFrame();
if (!it)
return NULL;
return it->getGlobals(); return it->getGlobals();
} }
......
...@@ -38,7 +38,6 @@ extern "C" const char* getStatTimerName() { ...@@ -38,7 +38,6 @@ extern "C" const char* getStatTimerName() {
__thread StatTimer* StatTimer::stack; __thread StatTimer* StatTimer::stack;
StatTimer::StatTimer(int statid, bool push) { StatTimer::StatTimer(int statid, bool push) {
uint64_t at_time = getCPUTicks(); uint64_t at_time = getCPUTicks();
_duration = 0;
_start_time = 0; _start_time = 0;
_statid = statid; _statid = statid;
...@@ -56,7 +55,6 @@ StatTimer::StatTimer(int statid, bool push) { ...@@ -56,7 +55,6 @@ StatTimer::StatTimer(int statid, bool push) {
} }
StatTimer::StatTimer(int statid, uint64_t at_time) { StatTimer::StatTimer(int statid, uint64_t at_time) {
_duration = 0;
_start_time = 0; _start_time = 0;
_statid = statid; _statid = statid;
_prev = stack; _prev = stack;
...@@ -88,13 +86,10 @@ StatTimer::~StatTimer() { ...@@ -88,13 +86,10 @@ StatTimer::~StatTimer() {
void StatTimer::pause(uint64_t at_time) { void StatTimer::pause(uint64_t at_time) {
assert(!isPaused()); assert(!isPaused());
assert(at_time > _start_time); assert(at_time > _start_time);
auto cur_duration = _duration;
_duration = at_time - _start_time;
assert(_duration > cur_duration);
uint64_t _duration = at_time - _start_time;
Stats::log(_statid, _duration); Stats::log(_statid, _duration);
_duration = 0;
_start_time = 0; _start_time = 0;
_last_pause_time = at_time; _last_pause_time = at_time;
// fprintf (stderr, "paused %d at %lu\n", _statid, at_time); // fprintf (stderr, "paused %d at %lu\n", _statid, at_time);
......
...@@ -116,9 +116,6 @@ class StatTimer { ...@@ -116,9 +116,6 @@ class StatTimer {
private: private:
static __thread StatTimer* stack; static __thread StatTimer* stack;
// the accumulated active duration of this timer
uint64_t _duration;
// the start time of the current active segment (0 == paused) // the start time of the current active segment (0 == paused)
uint64_t _start_time; uint64_t _start_time;
......
...@@ -80,6 +80,8 @@ public: ...@@ -80,6 +80,8 @@ public:
return *this->_str < *rhs._str; return *this->_str < *rhs._str;
} }
operator llvm::StringRef() { return llvm::StringRef(*_str); }
friend class InternedStringPool; friend class InternedStringPool;
friend struct std::hash<InternedString>; friend struct std::hash<InternedString>;
friend struct std::less<InternedString>; friend struct std::less<InternedString>;
......
...@@ -16,10 +16,12 @@ ...@@ -16,10 +16,12 @@
#include <csignal> #include <csignal>
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
#include <fcntl.h>
#include <readline/history.h> #include <readline/history.h>
#include <readline/readline.h> #include <readline/readline.h>
#include <stdint.h> #include <stdint.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/wait.h>
#include <unistd.h> #include <unistd.h>
#include "llvm/Support/FileSystem.h" #include "llvm/Support/FileSystem.h"
...@@ -90,6 +92,86 @@ static bool handle_toplevel_exn(const ExcInfo& e, int* retcode) { ...@@ -90,6 +92,86 @@ static bool handle_toplevel_exn(const ExcInfo& e, int* retcode) {
static bool force_repl = false; static bool force_repl = false;
static bool unbuffered = false; static bool unbuffered = false;
static const char* argv0;
static int pipefds[2];
static void handle_sigsegv(int signum) {
assert(signum == SIGSEGV);
// TODO: this should set a flag saying a KeyboardInterrupt is pending.
// For now, just call abort(), so that we get a traceback at least.
fprintf(stderr, "child encountered segfault! signalling parent watcher to backtrace.\n");
char buf[1];
int r = write(pipefds[1], buf, 1);
RELEASE_ASSERT(r == 1, "");
while (true) {
sleep(1);
}
}
static int gdb_child_pid;
static void propagate_sig(int signum) {
// fprintf(stderr, "parent received signal %d, passing to child and then ignoring\n", signum);
assert(gdb_child_pid);
int r = kill(gdb_child_pid, signum);
assert(!r);
}
static void enableGdbSegfaultWatcher() {
int r = pipe2(pipefds, 0);
RELEASE_ASSERT(r == 0, "");
gdb_child_pid = fork();
if (gdb_child_pid) {
// parent watcher process
close(pipefds[1]);
for (int i = 0; i < _NSIG; i++) {
if (i == SIGCHLD)
continue;
signal(i, &propagate_sig);
}
while (true) {
char buf[1];
int r = read(pipefds[0], buf, 1);
if (r == 1) {
fprintf(stderr, "Parent process woken up by child; collecting backtrace and killing child\n");
char pidbuf[20];
snprintf(pidbuf, sizeof(pidbuf), "%d", gdb_child_pid);
close(STDOUT_FILENO);
dup2(STDERR_FILENO, STDOUT_FILENO);
r = execlp("gdb", "gdb", "-p", pidbuf, argv0, "-batch", "-ex", "set pagination 0", "-ex",
"thread apply all bt", "-ex", "kill", "-ex", "quit -11", NULL);
RELEASE_ASSERT(0, "%d %d %s", r, errno, strerror(errno));
}
if (r == 0) {
int status;
r = waitpid(gdb_child_pid, &status, 0);
RELEASE_ASSERT(r == gdb_child_pid, "%d %d %s", r, errno, strerror(errno));
int rtncode = 0;
if (WIFEXITED(status))
rtncode = WEXITSTATUS(status);
else
rtncode = 128 + WTERMSIG(status);
exit(rtncode);
}
RELEASE_ASSERT(0, "%d %d %s", r, errno, strerror(errno));
}
RELEASE_ASSERT(0, "");
}
close(pipefds[0]);
signal(SIGSEGV, &handle_sigsegv);
}
int handleArg(char code) { int handleArg(char code) {
if (code == 'O') if (code == 'O')
FORCE_OPTIMIZE = true; FORCE_OPTIMIZE = true;
...@@ -131,6 +213,8 @@ int handleArg(char code) { ...@@ -131,6 +213,8 @@ int handleArg(char code) {
CONTINUE_AFTER_FATAL = true; CONTINUE_AFTER_FATAL = true;
} else if (code == 'T') { } else if (code == 'T') {
ENABLE_TRACEBACKS = false; ENABLE_TRACEBACKS = false;
} else if (code == 'G') {
enableGdbSegfaultWatcher();
} else { } else {
fprintf(stderr, "Unknown option: -%c\n", code); fprintf(stderr, "Unknown option: -%c\n", code);
return 2; return 2;
...@@ -139,6 +223,7 @@ int handleArg(char code) { ...@@ -139,6 +223,7 @@ int handleArg(char code) {
} }
static int main(int argc, char** argv) { static int main(int argc, char** argv) {
argv0 = argv[0];
Timer _t("for jit startup"); Timer _t("for jit startup");
// llvm::sys::PrintStackTraceOnErrorSignal(); // llvm::sys::PrintStackTraceOnErrorSignal();
...@@ -168,7 +253,7 @@ static int main(int argc, char** argv) { ...@@ -168,7 +253,7 @@ static int main(int argc, char** argv) {
// Suppress getopt errors so we can throw them ourselves // Suppress getopt errors so we can throw them ourselves
opterr = 0; opterr = 0;
while ((code = getopt(argc, argv, "+:OqdIibpjtrsSvnxEc:FuPT")) != -1) { while ((code = getopt(argc, argv, "+:OqdIibpjtrsSvnxEc:FuPTG")) != -1) {
if (code == 'c') { if (code == 'c') {
assert(optarg); assert(optarg);
command = optarg; command = optarg;
...@@ -286,7 +371,10 @@ static int main(int argc, char** argv) { ...@@ -286,7 +371,10 @@ static int main(int argc, char** argv) {
llvm::sys::path::append(path, fn); llvm::sys::path::append(path, fn);
llvm::sys::path::remove_filename(path); llvm::sys::path::remove_filename(path);
prependToSysPath(path.str()); char* real_path
= realpath(path.str().str().c_str(), NULL); // inefficient way of null-terminating the string
prependToSysPath(real_path);
free(real_path);
main_module = createModule("__main__", fn); main_module = createModule("__main__", fn);
try { try {
......
...@@ -388,6 +388,10 @@ Box* bltinImport(Box* name, Box* globals, Box* locals, Box** args) { ...@@ -388,6 +388,10 @@ Box* bltinImport(Box* name, Box* globals, Box* locals, Box** args) {
Box* fromlist = args[0]; Box* fromlist = args[0];
Box* level = args[1]; Box* level = args[1];
// __import__ takes a 'locals' argument, but it doesn't get used in CPython.
// Well, it gets passed to PyImport_ImportModuleLevel() and then import_module_level(),
// which ignores it. So we don't even pass it through.
name = coerceUnicodeToStr(name); name = coerceUnicodeToStr(name);
if (name->cls != str_cls) { if (name->cls != str_cls) {
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "codegen/irgen/hooks.h" #include "codegen/irgen/hooks.h"
#include "codegen/parser.h" #include "codegen/parser.h"
#include "codegen/unwinding.h"
#include "runtime/capi.h" #include "runtime/capi.h"
#include "runtime/objmodel.h" #include "runtime/objmodel.h"
...@@ -267,7 +268,7 @@ static Box* getParent(Box* globals, int level, std::string& buf) { ...@@ -267,7 +268,7 @@ static Box* getParent(Box* globals, int level, std::string& buf) {
if (globals == NULL || globals == None || level == 0) if (globals == NULL || globals == None || level == 0)
return None; return None;
BoxedString* pkgname = static_cast<BoxedString*>(getattrInternal(globals, package_str, NULL)); BoxedString* pkgname = static_cast<BoxedString*>(getFromGlobals(globals, package_str));
if (pkgname != NULL && pkgname != None) { if (pkgname != NULL && pkgname != None) {
/* __package__ is set, so use it */ /* __package__ is set, so use it */
if (pkgname->cls != str_cls) { if (pkgname->cls != str_cls) {
...@@ -286,17 +287,11 @@ static Box* getParent(Box* globals, int level, std::string& buf) { ...@@ -286,17 +287,11 @@ static Box* getParent(Box* globals, int level, std::string& buf) {
buf += pkgname->s; buf += pkgname->s;
} else { } else {
/* __package__ not set, so figure it out and set it */ /* __package__ not set, so figure it out and set it */
BoxedString* modname = static_cast<BoxedString*>(getattrInternal(globals, name_str, NULL)); BoxedString* modname = static_cast<BoxedString*>(getFromGlobals(globals, name_str));
if (modname == NULL || modname->cls != str_cls) if (modname == NULL || modname->cls != str_cls)
return None; return None;
Box* modpath = NULL; Box* modpath = getFromGlobals(globals, path_str);
try {
modpath = getattrInternal(globals, path_str, NULL);
} catch (ExcInfo e) {
if (!e.matches(AttributeError))
raiseRaw(e);
}
if (modpath != NULL) { if (modpath != NULL) {
/* __path__ is set, so modname is already the package name */ /* __path__ is set, so modname is already the package name */
...@@ -304,7 +299,7 @@ static Box* getParent(Box* globals, int level, std::string& buf) { ...@@ -304,7 +299,7 @@ static Box* getParent(Box* globals, int level, std::string& buf) {
raiseExcHelper(ValueError, "Module name too long"); raiseExcHelper(ValueError, "Module name too long");
} }
buf += modname->s; buf += modname->s;
globals->setattr(package_str, modname, NULL); setGlobal(globals, package_str, modname);
} else { } else {
/* Normal module, so work out the package name if any */ /* Normal module, so work out the package name if any */
size_t lastdot = modname->s.rfind('.'); size_t lastdot = modname->s.rfind('.');
...@@ -312,7 +307,7 @@ static Box* getParent(Box* globals, int level, std::string& buf) { ...@@ -312,7 +307,7 @@ static Box* getParent(Box* globals, int level, std::string& buf) {
raiseExcHelper(ValueError, "Attempted relative import in non-package"); raiseExcHelper(ValueError, "Attempted relative import in non-package");
} }
if (lastdot == std::string::npos) { if (lastdot == std::string::npos) {
globals->setattr(package_str, None, NULL); setGlobal(globals, package_str, None);
return None; return None;
} }
if (lastdot >= PATH_MAX) { if (lastdot >= PATH_MAX) {
...@@ -320,7 +315,7 @@ static Box* getParent(Box* globals, int level, std::string& buf) { ...@@ -320,7 +315,7 @@ static Box* getParent(Box* globals, int level, std::string& buf) {
} }
buf = std::string(modname->s, 0, lastdot); buf = std::string(modname->s, 0, lastdot);
globals->setattr(package_str, boxStringPtr(&buf), NULL); setGlobal(globals, package_str, boxStringPtr(&buf));
} }
} }
...@@ -471,7 +466,6 @@ static bool loadNext(Box* mod, Box* altmod, std::string& name, std::string& buf, ...@@ -471,7 +466,6 @@ static bool loadNext(Box* mod, Box* altmod, std::string& name, std::string& buf,
static void ensureFromlist(Box* module, Box* fromlist, std::string& buf, bool recursive); static void ensureFromlist(Box* module, Box* fromlist, std::string& buf, bool recursive);
Box* importModuleLevel(const std::string& name, Box* globals, Box* from_imports, int level) { Box* importModuleLevel(const std::string& name, Box* globals, Box* from_imports, int level) {
RELEASE_ASSERT(!globals || globals == None || isSubclass(globals->cls, module_cls), "");
bool return_first = from_imports == None; bool return_first = from_imports == None;
static StatCounter slowpath_import("slowpath_import"); static StatCounter slowpath_import("slowpath_import");
...@@ -665,7 +659,7 @@ Box* nullImporterFindModule(Box* self, Box* fullname, Box* path) { ...@@ -665,7 +659,7 @@ Box* nullImporterFindModule(Box* self, Box* fullname, Box* path) {
extern "C" Box* import(int level, Box* from_imports, const std::string* module_name) { extern "C" Box* import(int level, Box* from_imports, const std::string* module_name) {
std::string _module_name(*module_name); std::string _module_name(*module_name);
return importModuleLevel(_module_name, getCurrentModule(), from_imports, level); return importModuleLevel(_module_name, getGlobals(), from_imports, level);
} }
Box* impFindModule(Box* _name, BoxedList* path) { Box* impFindModule(Box* _name, BoxedList* path) {
......
...@@ -4562,6 +4562,40 @@ extern "C" Box* getGlobal(Box* globals, const std::string* name) { ...@@ -4562,6 +4562,40 @@ extern "C" Box* getGlobal(Box* globals, const std::string* name) {
raiseExcHelper(NameError, "global name '%s' is not defined", name->c_str()); raiseExcHelper(NameError, "global name '%s' is not defined", name->c_str());
} }
Box* getFromGlobals(Box* globals, llvm::StringRef name) {
if (globals->cls == attrwrapper_cls) {
globals = unwrapAttrWrapper(globals);
RELEASE_ASSERT(globals->cls == module_cls, "%s", globals->cls->tp_name);
}
if (globals->cls == module_cls) {
return globals->getattr(name);
} else if (globals->cls == dict_cls) {
auto d = static_cast<BoxedDict*>(globals)->d;
auto name_str = boxString(name.str());
auto it = d.find(name_str);
if (it != d.end())
return it->second;
return NULL;
} else {
RELEASE_ASSERT(0, "%s", globals->cls->tp_name);
}
}
void setGlobal(Box* globals, llvm::StringRef name, Box* value) {
if (globals->cls == attrwrapper_cls) {
globals = unwrapAttrWrapper(globals);
RELEASE_ASSERT(globals->cls == module_cls, "%s", globals->cls->tp_name);
}
if (globals->cls == module_cls) {
setattr(static_cast<BoxedModule*>(globals), name.data(), value);
} else {
RELEASE_ASSERT(globals->cls == dict_cls, "%s", globals->cls->tp_name);
static_cast<BoxedDict*>(globals)->d[boxString(name)] = value;
}
}
extern "C" Box* importFrom(Box* _m, const std::string* name) { extern "C" Box* importFrom(Box* _m, const std::string* name) {
STAT_TIMER(t0, "us_timer_importFrom"); STAT_TIMER(t0, "us_timer_importFrom");
......
...@@ -183,7 +183,13 @@ inline std::tuple<Box*, Box*, Box*, Box**> getTupleFromArgsArray(Box** args, int ...@@ -183,7 +183,13 @@ inline std::tuple<Box*, Box*, Box*, Box**> getTupleFromArgsArray(Box** args, int
// The `globals` argument can be either a BoxedModule or a BoxedDict // The `globals` argument can be either a BoxedModule or a BoxedDict
// Corresponds to a name lookup with GLOBAL scope. Checks the passed globals object, then the builtins,
// and if not found raises an exception.
extern "C" Box* getGlobal(Box* globals, const std::string* name); extern "C" Box* getGlobal(Box* globals, const std::string* name);
// Checks for the name just in the passed globals object, and returns NULL if it is not found.
// This includes if the globals object defined a custom __getattr__ method that threw an AttributeError.
Box* getFromGlobals(Box* globals, llvm::StringRef name);
void setGlobal(Box* globals, llvm::StringRef name, Box* value);
extern "C" void delGlobal(Box* globals, const std::string* name); extern "C" void delGlobal(Box* globals, const std::string* name);
extern "C" void boxedLocalsSet(Box* boxedLocals, const char* attr, Box* val); extern "C" void boxedLocalsSet(Box* boxedLocals, const char* attr, Box* val);
......
...@@ -198,6 +198,7 @@ extern "C" void abort() { ...@@ -198,6 +198,7 @@ extern "C" void abort() {
__builtin_unreachable(); __builtin_unreachable();
} }
#if 0
extern "C" void exit(int code) { extern "C" void exit(int code) {
static void (*libc_exit)(int) = (void (*)(int))dlsym(RTLD_NEXT, "exit"); static void (*libc_exit)(int) = (void (*)(int))dlsym(RTLD_NEXT, "exit");
...@@ -219,6 +220,7 @@ extern "C" void exit(int code) { ...@@ -219,6 +220,7 @@ extern "C" void exit(int code) {
libc_exit(code); libc_exit(code);
__builtin_unreachable(); __builtin_unreachable();
} }
#endif
extern "C" void raise0() { extern "C" void raise0() {
ExcInfo* exc_info = getFrameExcInfo(); ExcInfo* exc_info = getFrameExcInfo();
......
...@@ -21,9 +21,10 @@ set -e ...@@ -21,9 +21,10 @@ set -e
set -ux set -ux
python -c 'import __future__' python -c 'import __future__'
python -c 'import sys; print sys.executable' python -c 'import sys; print sys.executable'
pip install bcrypt==1.1.0 python-gflags==2.0 pip install bcrypt==1.1.0 python-gflags==2.0 sqlalchemy==1.0.0
python -c 'import bcrypt; assert bcrypt.__version__ == "1.1.0"; assert bcrypt.hashpw("password1", "$2a$12$0123456789012345678901").endswith("I1hdtg4K"); print "bcrypt seems to work"' python -c 'import bcrypt; assert bcrypt.__version__ == "1.1.0"; assert bcrypt.hashpw("password1", "$2a$12$0123456789012345678901").endswith("I1hdtg4K"); print "bcrypt seems to work"'
python -c 'import gflags; print "gflags imports"' python -c 'import gflags; print "gflags imports"'
python -c 'import sqlalchemy; print "sqlalchemy imports"'
""".strip() """.strip()
# print sh_script # print sh_script
......
import test_package.import_target
import import_target
print
s = """
import import_target
print import_target.__file__.replace(".pyc", ".py")
"""
def test(g):
print "Testing with globals:", "None" if g is None else ("globals" if g is globals() else sorted(g.items()))
print __import__("import_target", g).__file__.replace(".pyc", ".py")
exec s in g
print "Resulting globals:", "None" if g is None else ("globals" if g is globals() else sorted(g.keys()))
print
test(None)
test(globals())
test({"__package__":"test_package"})
test({"__name__":"test_package.foo"})
test({"__name__":"test_package"})
test({"__name__":"test_package", "__path__":"foo"})
...@@ -157,6 +157,9 @@ def run_test(fn, check_stats, run_memcheck): ...@@ -157,6 +157,9 @@ def run_test(fn, check_stats, run_memcheck):
code = p.wait() code = p.wait()
elapsed = time.time() - start elapsed = time.time() - start
if code >= 128:
code -= 256
return determine_test_result(fn, opts, code, out, stderr, elapsed) return determine_test_result(fn, opts, code, out, stderr, elapsed)
def get_test_options(fn, check_stats, run_memcheck): def get_test_options(fn, check_stats, run_memcheck):
......
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