Commit a2560414 authored by Marius Wachtler's avatar Marius Wachtler

move constants from the module into CodeConstants (=code object)

parent 7f52a9ad
...@@ -69,6 +69,10 @@ IRGenState::IRGenState(BoxedCode* code, CompiledFunction* cf, llvm::Function* fu ...@@ -69,6 +69,10 @@ IRGenState::IRGenState(BoxedCode* code, CompiledFunction* cf, llvm::Function* fu
IRGenState::~IRGenState() { IRGenState::~IRGenState() {
} }
const CodeConstants& IRGenState::getCodeConstants() {
return code->code_constants;
}
llvm::Value* IRGenState::getPassedClosure() { llvm::Value* IRGenState::getPassedClosure() {
assert(getScopeInfo().takesClosure()); assert(getScopeInfo().takesClosure());
assert(passed_closure); assert(passed_closure);
...@@ -721,9 +725,9 @@ public: ...@@ -721,9 +725,9 @@ public:
return rtn; return rtn;
} }
Box* getIntConstant(int64_t n) override { return irstate->getSourceInfo()->parent_module->getIntConstant(n); } Box* getIntConstant(int64_t n) override { return irstate->getCodeConstants().getIntConstant(n); }
Box* getFloatConstant(double d) override { return irstate->getSourceInfo()->parent_module->getFloatConstant(d); } Box* getFloatConstant(double d) override { return irstate->getCodeConstants().getFloatConstant(d); }
void refConsumed(llvm::Value* v, llvm::Instruction* inst) override { void refConsumed(llvm::Value* v, llvm::Instruction* inst) override {
irstate->getRefcounts()->refConsumed(v, inst); irstate->getRefcounts()->refConsumed(v, inst);
......
...@@ -92,6 +92,7 @@ public: ...@@ -92,6 +92,7 @@ public:
CompiledFunction* getCurFunction() { return cf; } CompiledFunction* getCurFunction() { return cf; }
BoxedCode* getCode() { return code; } BoxedCode* getCode() { return code; }
const CodeConstants& getCodeConstants();
ExceptionStyle getExceptionStyle() { return cf->exception_style; } ExceptionStyle getExceptionStyle() { return cf->exception_style; }
......
...@@ -27,6 +27,8 @@ ...@@ -27,6 +27,8 @@
#include "core/bst.h" #include "core/bst.h"
#include "core/options.h" #include "core/options.h"
#include "core/types.h" #include "core/types.h"
#include "runtime/complex.h"
#include "runtime/long.h"
#include "runtime/objmodel.h" #include "runtime/objmodel.h"
#include "runtime/types.h" #include "runtime/types.h"
...@@ -362,9 +364,19 @@ private: ...@@ -362,9 +364,19 @@ private:
CFGBlock* curblock; CFGBlock* curblock;
std::vector<ContInfo> continuations; std::vector<ContInfo> continuations;
std::vector<ExcBlockInfo> exc_handlers; std::vector<ExcBlockInfo> exc_handlers;
// maps constants to their vreg number
llvm::DenseMap<Box*, int> consts; llvm::DenseMap<Box*, int> consts;
CodeConstants code_constants; CodeConstants code_constants;
llvm::StringMap<BoxedString*> str_constants;
llvm::StringMap<Box*> unicode_constants;
// I'm not sure how well it works to use doubles as hashtable keys; thankfully
// it's not a big deal if we get misses.
std::unordered_map<int64_t, Box*> imaginary_constants;
llvm::StringMap<Box*> long_constants;
llvm::DenseMap<InternedString, int> interned_string_constants;
unsigned int next_var_index = 0; unsigned int next_var_index = 0;
friend std::pair<CFG*, CodeConstants> computeCFG(llvm::ArrayRef<AST_stmt*> body, AST_TYPE::AST_TYPE ast_type, friend std::pair<CFG*, CodeConstants> computeCFG(llvm::ArrayRef<AST_stmt*> body, AST_TYPE::AST_TYPE ast_type,
...@@ -518,16 +530,39 @@ private: ...@@ -518,16 +530,39 @@ private:
return vreg; return vreg;
} }
static int64_t getDoubleBits(double d) {
int64_t rtn;
static_assert(sizeof(rtn) == sizeof(d), "");
memcpy(&rtn, &d, sizeof(d));
return rtn;
}
TmpValue makeNum(int64_t n, int lineno) {
Box* o = code_constants.getIntConstant(n);
int vreg_const = addConst(o);
return TmpValue(vreg_const, lineno);
}
TmpValue remapNum(AST_Num* num) { TmpValue remapNum(AST_Num* num) {
Box* o = NULL; Box* o = NULL;
if (num->num_type == AST_Num::INT) { if (num->num_type == AST_Num::INT) {
o = source->parent_module->getIntConstant(num->n_int); o = code_constants.getIntConstant(num->n_int);
} else if (num->num_type == AST_Num::FLOAT) { } else if (num->num_type == AST_Num::FLOAT) {
o = source->parent_module->getFloatConstant(num->n_float); o = code_constants.getFloatConstant(num->n_float);
} else if (num->num_type == AST_Num::LONG) { } else if (num->num_type == AST_Num::LONG) {
o = source->parent_module->getLongConstant(num->n_long); Box*& r = long_constants[num->n_long];
if (!r) {
r = createLong(num->n_long);
code_constants.addOwnedRef(r);
}
o = r;
} else if (num->num_type == AST_Num::COMPLEX) { } else if (num->num_type == AST_Num::COMPLEX) {
o = source->parent_module->getPureImaginaryConstant(num->n_float); Box*& r = imaginary_constants[getDoubleBits(num->n_float)];
if (!r) {
r = createPureImaginary(num->n_float);
code_constants.addOwnedRef(r);
}
o = r;
} else } else
RELEASE_ASSERT(0, "not implemented"); RELEASE_ASSERT(0, "not implemented");
...@@ -535,23 +570,34 @@ private: ...@@ -535,23 +570,34 @@ private:
return TmpValue(vreg_const, num->lineno); return TmpValue(vreg_const, num->lineno);
} }
TmpValue makeStr(llvm::StringRef str, int lineno = 0) {
BoxedString*& o = str_constants[str];
// we always intern the string
if (!o) {
o = internStringMortal(str);
code_constants.addOwnedRef(o);
}
int vreg_const = addConst(o);
return TmpValue(vreg_const, lineno);
}
TmpValue remapStr(AST_Str* str) { TmpValue remapStr(AST_Str* str) {
// TODO make this serializable // TODO make this serializable
Box* o = NULL;
if (str->str_type == AST_Str::STR) { if (str->str_type == AST_Str::STR) {
o = source->parent_module->getStringConstant(str->str_data, true); return makeStr(str->str_data, str->lineno);
} else if (str->str_type == AST_Str::UNICODE) { } else if (str->str_type == AST_Str::UNICODE) {
o = source->parent_module->getUnicodeConstant(str->str_data); Box*& r = unicode_constants[str->str_data];
} else { if (!r) {
RELEASE_ASSERT(0, "%d", str->str_type); r = decodeUTF8StringPtr(str->str_data);
code_constants.addOwnedRef(r);
}
return TmpValue(addConst(r), str->lineno);
} }
RELEASE_ASSERT(0, "%d", str->str_type);
int vreg_const = addConst(o);
return TmpValue(vreg_const, str->lineno);
} }
TmpValue makeNum(int n, int lineno) { TmpValue makeNum(int n, int lineno) {
Box* o = source->parent_module->getIntConstant(n); Box* o = code_constants.getIntConstant(n);
int vreg_const = addConst(o); int vreg_const = addConst(o);
return TmpValue(vreg_const, lineno); return TmpValue(vreg_const, lineno);
} }
...@@ -561,12 +607,6 @@ private: ...@@ -561,12 +607,6 @@ private:
return TmpValue(vreg_const, lineno); return TmpValue(vreg_const, lineno);
} }
TmpValue makeStr(llvm::StringRef str, int lineno = 0) {
Box* o = source->parent_module->getStringConstant(str, true);
int vreg_const = addConst(o);
return TmpValue(vreg_const, lineno);
}
TmpValue applyComprehensionCall(AST_ListComp* node, TmpValue name) { TmpValue applyComprehensionCall(AST_ListComp* node, TmpValue name) {
TmpValue elt = remapExpr(node->elt); TmpValue elt = remapExpr(node->elt);
return makeCallAttr(name, internString("append"), true, { elt }); return makeCallAttr(name, internString("append"), true, { elt });
...@@ -3334,7 +3374,7 @@ static std::pair<CFG*, CodeConstants> computeCFG(llvm::ArrayRef<AST_stmt*> body, ...@@ -3334,7 +3374,7 @@ static std::pair<CFG*, CodeConstants> computeCFG(llvm::ArrayRef<AST_stmt*> body,
rtn->print(visitor.code_constants, llvm::outs()); rtn->print(visitor.code_constants, llvm::outs());
} }
return std::make_pair(rtn, visitor.code_constants); return std::make_pair(rtn, std::move(visitor.code_constants));
} }
......
...@@ -480,68 +480,6 @@ std::string BoxedModule::name() { ...@@ -480,68 +480,6 @@ std::string BoxedModule::name() {
} }
} }
BORROWED(BoxedString*) BoxedModule::getStringConstant(llvm::StringRef ast_str, bool intern) {
BoxedString*& r = str_constants[ast_str];
if (intern) {
// If we had previously created a box for this string, we have to create a new
// string (or at least, be prepared to return a different value that we had already
// interned). This is fine, except we have to be careful because we promised
// that we would keep the previously-created string alive.
// So, make sure to put it onto the keep_alive list.
if (r && !PyString_CHECK_INTERNED(r)) {
RELEASE_ASSERT(0, "this codepath has been dead for a little while, make sure it still works");
keep_alive.push_back(r);
r = NULL;
}
if (!r)
r = internStringMortal(ast_str);
} else if (!r)
r = boxString(ast_str);
return r;
}
BORROWED(Box*) BoxedModule::getUnicodeConstant(llvm::StringRef ast_str) {
Box*& r = unicode_constants[ast_str];
if (!r)
r = decodeUTF8StringPtr(ast_str);
return r;
}
BORROWED(BoxedInt*) BoxedModule::getIntConstant(int64_t n) {
BoxedInt*& r = int_constants[n];
if (!r)
r = (BoxedInt*)boxInt(n);
return r;
}
static int64_t getDoubleBits(double d) {
int64_t rtn;
static_assert(sizeof(rtn) == sizeof(d), "");
memcpy(&rtn, &d, sizeof(d));
return rtn;
}
BORROWED(BoxedFloat*) BoxedModule::getFloatConstant(double d) {
BoxedFloat*& r = float_constants[getDoubleBits(d)];
if (!r)
r = static_cast<BoxedFloat*>(boxFloat(d));
return r;
}
BORROWED(Box*) BoxedModule::getPureImaginaryConstant(double d) {
Box*& r = imaginary_constants[getDoubleBits(d)];
if (!r)
r = createPureImaginary(d);
return r;
}
BORROWED(Box*) BoxedModule::getLongConstant(llvm::StringRef ast_str) {
Box*& r = long_constants[ast_str];
if (!r)
r = createLong(ast_str);
return r;
}
// This mustn't throw; our IR generator generates calls to it without "invoke" even when there are exception handlers / // This mustn't throw; our IR generator generates calls to it without "invoke" even when there are exception handlers /
// finally-blocks in scope. // finally-blocks in scope.
extern "C" Box* createFunctionFromMetadata(BoxedCode* code, BoxedClosure* closure, Box* globals, extern "C" Box* createFunctionFromMetadata(BoxedCode* code, BoxedClosure* closure, Box* globals,
...@@ -3817,21 +3755,12 @@ void BoxedModule::dealloc(Box* b) noexcept { ...@@ -3817,21 +3755,12 @@ void BoxedModule::dealloc(Box* b) noexcept {
BoxedModule::clear(self); BoxedModule::clear(self);
self->str_constants.~ContiguousMap();
self->unicode_constants.~ContiguousMap();
self->int_constants.~ContiguousMap();
self->float_constants.~ContiguousMap();
self->imaginary_constants.~ContiguousMap();
self->long_constants.~ContiguousMap();
assert(!self->keep_alive.size());
b->cls->tp_free(self); b->cls->tp_free(self);
} }
int BoxedModule::traverse(Box* _m, visitproc visit, void* arg) noexcept { int BoxedModule::traverse(Box* _m, visitproc visit, void* arg) noexcept {
BoxedModule* m = static_cast<BoxedModule*>(_m); BoxedModule* m = static_cast<BoxedModule*>(_m);
Py_TRAVERSE(m->attrs); Py_TRAVERSE(m->attrs);
assert(!m->keep_alive.size());
return 0; return 0;
} }
...@@ -3849,15 +3778,6 @@ extern "C" void _PyModule_Clear(PyObject* b) noexcept { ...@@ -3849,15 +3778,6 @@ extern "C" void _PyModule_Clear(PyObject* b) noexcept {
HCAttrs* attrs = self->getHCAttrsPtr(); HCAttrs* attrs = self->getHCAttrsPtr();
attrs->moduleClear(); attrs->moduleClear();
clearContiguousMap(self->str_constants);
clearContiguousMap(self->unicode_constants);
clearContiguousMap(self->int_constants);
clearContiguousMap(self->float_constants);
clearContiguousMap(self->imaginary_constants);
clearContiguousMap(self->long_constants);
assert(!self->keep_alive.size());
} }
int BoxedModule::clear(Box* b) noexcept { int BoxedModule::clear(Box* b) noexcept {
...@@ -4102,6 +4022,33 @@ int BoxedClosure::clear(Box* _o) noexcept { ...@@ -4102,6 +4022,33 @@ int BoxedClosure::clear(Box* _o) noexcept {
return 0; return 0;
} }
BORROWED(BoxedInt*) CodeConstants::getIntConstant(int64_t n) const {
BoxedInt*& r = int_constants[n];
if (!r) {
r = (BoxedInt*)boxInt(n);
addOwnedRef(r);
}
return r;
}
BORROWED(BoxedFloat*) CodeConstants::getFloatConstant(double d) const {
int64_t double_as_int64;
static_assert(sizeof(double_as_int64) == sizeof(d), "");
memcpy(&double_as_int64, &d, sizeof(d));
BoxedFloat*& r = float_constants[double_as_int64];
if (!r) {
r = (BoxedFloat*)boxFloat(d);
addOwnedRef(r);
}
return r;
}
void CodeConstants::dealloc() const {
decrefArray(owned_refs.data(), owned_refs.size());
owned_refs.clear();
}
#ifndef Py_REF_DEBUG #ifndef Py_REF_DEBUG
#define PRINT_TOTAL_REFS() #define PRINT_TOTAL_REFS()
#else /* Py_REF_DEBUG */ #else /* Py_REF_DEBUG */
......
...@@ -1072,18 +1072,40 @@ static_assert(sizeof(BoxedDict) == sizeof(PyDictObject), ""); ...@@ -1072,18 +1072,40 @@ static_assert(sizeof(BoxedDict) == sizeof(PyDictObject), "");
class CodeConstants { class CodeConstants {
private: private:
// stores all constants accessible by vregs in the corrext order
// constants[-(vreg + 1)] will allow one to retrieve the constant for a vreg
std::vector<Box*> constants; std::vector<Box*> constants;
// all objects we need to decref when the code object dies
mutable std::vector<Box*> owned_refs;
// Note: DenseMap doesn't work here since we don't prevent the tombstone/empty
// keys from reaching it.
mutable std::unordered_map<int64_t, BoxedInt*> int_constants;
// I'm not sure how well it works to use doubles as hashtable keys; thankfully
// it's not a big deal if we get misses.
mutable std::unordered_map<int64_t, BoxedFloat*> float_constants;
public: public:
CodeConstants() {} CodeConstants() {}
CodeConstants(CodeConstants&&) = default;
CodeConstants& operator=(CodeConstants&&) = default;
~CodeConstants() { dealloc(); }
Box* getConstant(int vreg) const { return constants[-(vreg + 1)]; } BORROWED(Box*) getConstant(int vreg) const { return constants[-(vreg + 1)]; }
// returns the vreg num for the constant (which is a negative number) // returns the vreg num for the constant (which is a negative number)
int createVRegEntryForConstant(Box* o) { int createVRegEntryForConstant(Box* o) {
constants.push_back(o); constants.push_back(o);
return -constants.size(); return -constants.size();
} }
void addOwnedRef(Box* o) const { owned_refs.emplace_back(o); }
BORROWED(BoxedInt*) getIntConstant(int64_t n) const;
BORROWED(BoxedFloat*) getFloatConstant(double d) const;
void dealloc() const;
}; };
......
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