Commit cd11e1d5 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Make the GC-header managed by the GC

Previously the gc header had to be set and managed by the user of the GC,
which didn't make much sense.

Also took this opportunity to clean up a bunch of old cruft.

Also got rid of ObjectFlavors and AllocationKinds, in preference for
a GCKind which I think makes more sense.  Right now there are only three
different GCKinds, but I'm not sure if the previous AllocationKinds
should each get their own GCKind.
parent e891c285
...@@ -105,7 +105,9 @@ void Assembler::emitByte(uint8_t b) { ...@@ -105,7 +105,9 @@ void Assembler::emitByte(uint8_t b) {
void Assembler::emitInt(int64_t n, int bytes) { void Assembler::emitInt(int64_t n, int bytes) {
assert(bytes > 0 && bytes <= 8); assert(bytes > 0 && bytes <= 8);
assert((-1L << (8 * bytes - 1)) <= n && n <= ((1L << (8 * bytes - 1)) - 1)); if (bytes < 8)
assert((-1L << (8 * bytes - 1)) <= n && n <= ((1L << (8 * bytes - 1)) - 1));
for (int i = 0; i < bytes; i++) { for (int i = 0; i < bytes; i++) {
emitByte(n & 0xff); emitByte(n & 0xff);
n >>= 8; n >>= 8;
......
...@@ -67,7 +67,6 @@ struct GlobalState { ...@@ -67,7 +67,6 @@ struct GlobalState {
FunctionAddressRegistry func_addr_registry; FunctionAddressRegistry func_addr_registry;
llvm::Type* llvm_value_type, *llvm_value_type_ptr, *llvm_value_type_ptr_ptr; llvm::Type* llvm_value_type, *llvm_value_type_ptr, *llvm_value_type_ptr_ptr;
llvm::Type* llvm_class_type, *llvm_class_type_ptr; llvm::Type* llvm_class_type, *llvm_class_type_ptr;
llvm::Type* llvm_flavor_type, *llvm_flavor_type_ptr;
llvm::Type* llvm_opaque_type; llvm::Type* llvm_opaque_type;
llvm::Type* llvm_str_type_ptr; llvm::Type* llvm_str_type_ptr;
llvm::Type* llvm_clfunction_type_ptr, *llvm_closure_type_ptr, *llvm_generator_type_ptr; llvm::Type* llvm_clfunction_type_ptr, *llvm_closure_type_ptr, *llvm_generator_type_ptr;
......
...@@ -242,8 +242,11 @@ public: ...@@ -242,8 +242,11 @@ public:
virtual llvm::Value* makeClassCheck(IREmitter& emitter, ConcreteCompilerVariable* var, BoxedClass* cls) { virtual llvm::Value* makeClassCheck(IREmitter& emitter, ConcreteCompilerVariable* var, BoxedClass* cls) {
assert(var->getValue()->getType() == g.llvm_value_type_ptr); assert(var->getValue()->getType() == g.llvm_value_type_ptr);
// TODO this is brittle: directly embeds the position of the class object:
llvm::Value* cls_ptr = emitter.getBuilder()->CreateConstInBoundsGEP2_32(var->getValue(), 0, 1); static_assert(offsetof(Box, cls) % sizeof(void*) == 0, "");
llvm::Value* cls_ptr
= emitter.getBuilder()->CreateConstInBoundsGEP2_32(var->getValue(), 0, offsetof(Box, cls) / sizeof(void*));
llvm::Value* cls_value = emitter.getBuilder()->CreateLoad(cls_ptr); llvm::Value* cls_value = emitter.getBuilder()->CreateLoad(cls_ptr);
assert(cls_value->getType() == g.llvm_class_type_ptr); assert(cls_value->getType() == g.llvm_class_type_ptr);
llvm::Value* rtn = emitter.getBuilder()->CreateICmpEQ(cls_value, embedConstantPtr(cls, g.llvm_class_type_ptr)); llvm::Value* rtn = emitter.getBuilder()->CreateICmpEQ(cls_value, embedConstantPtr(cls, g.llvm_class_type_ptr));
......
...@@ -35,7 +35,6 @@ ...@@ -35,7 +35,6 @@
#include "core/stats.h" #include "core/stats.h"
#include "core/types.h" #include "core/types.h"
#include "core/util.h" #include "core/util.h"
#include "runtime/gc_runtime.h"
#include "runtime/objmodel.h" #include "runtime/objmodel.h"
#include "runtime/types.h" #include "runtime/types.h"
......
...@@ -49,8 +49,6 @@ private: ...@@ -49,8 +49,6 @@ private:
} }
BoxedClass* getClassFromGV(GlobalVariable* gv) { return *(BoxedClass**)getGVAddr(gv); } BoxedClass* getClassFromGV(GlobalVariable* gv) { return *(BoxedClass**)getGVAddr(gv); }
ObjectFlavor* getFlavorFromGV(GlobalVariable* gv) { return (ObjectFlavor*)getGVAddr(gv); }
void replaceUsesWithConstant(llvm::Value* v, uintptr_t val) { void replaceUsesWithConstant(llvm::Value* v, uintptr_t val) {
if (isa<PointerType>(v->getType())) if (isa<PointerType>(v->getType()))
v->replaceAllUsesWith(embedConstantPtr((void*)val, v->getType())); v->replaceAllUsesWith(embedConstantPtr((void*)val, v->getType()));
...@@ -69,31 +67,6 @@ private: ...@@ -69,31 +67,6 @@ private:
return true; return true;
} }
bool handleFlavor(LoadInst* li, ConstantExpr* gepce) {
if (VERBOSITY("opt") >= 1) {
errs() << "\nFound this load of a flavor attr:\n" << *li << '\n';
}
GetElementPtrInst* gep = cast<GetElementPtrInst>(gepce->getAsInstruction());
APInt ap_offset(64, 0, true);
bool success = gep->accumulateConstantOffset(*g.tm->getDataLayout(), ap_offset);
delete gep;
assert(success);
int64_t offset = ap_offset.getSExtValue();
if (offset == offsetof(ObjectFlavor, kind_id)) {
ObjectFlavor* flavor = getFlavorFromGV(cast<GlobalVariable>(gepce->getOperand(0)));
replaceUsesWithConstant(li, flavor->kind_id);
return true;
} else {
ASSERT(0, "%ld", offset);
return false;
}
assert(0);
return false;
}
bool handleCls(LoadInst* li, GlobalVariable* gv) { bool handleCls(LoadInst* li, GlobalVariable* gv) {
bool changed = true; bool changed = true;
...@@ -190,9 +163,6 @@ public: ...@@ -190,9 +163,6 @@ public:
ConstantExpr* ce = dyn_cast<ConstantExpr>(li->getOperand(0)); ConstantExpr* ce = dyn_cast<ConstantExpr>(li->getOperand(0));
// Not 100% sure what the isGEPWithNoNotionalOverIndexing() means, but // Not 100% sure what the isGEPWithNoNotionalOverIndexing() means, but
// at least it checks if it's a gep: // at least it checks if it's a gep:
if (ce && ce->isGEPWithNoNotionalOverIndexing() && ce->getOperand(0)->getType() == g.llvm_flavor_type_ptr) {
changed = handleFlavor(li, ce);
}
GlobalVariable* gv = dyn_cast<GlobalVariable>(li->getOperand(0)); GlobalVariable* gv = dyn_cast<GlobalVariable>(li->getOperand(0));
if (!gv) if (!gv)
......
...@@ -33,7 +33,6 @@ ...@@ -33,7 +33,6 @@
#include "core/threading.h" #include "core/threading.h"
#include "core/types.h" #include "core/types.h"
#include "runtime/float.h" #include "runtime/float.h"
#include "runtime/gc_runtime.h"
#include "runtime/generator.h" #include "runtime/generator.h"
#include "runtime/inline/boxing.h" #include "runtime/inline/boxing.h"
#include "runtime/int.h" #include "runtime/int.h"
...@@ -129,10 +128,6 @@ void initGlobalFuncs(GlobalState& g) { ...@@ -129,10 +128,6 @@ void initGlobalFuncs(GlobalState& g) {
assert(g.llvm_class_type); assert(g.llvm_class_type);
g.llvm_class_type_ptr = g.llvm_class_type->getPointerTo(); g.llvm_class_type_ptr = g.llvm_class_type->getPointerTo();
g.llvm_flavor_type = g.stdlib_module->getTypeByName("class.pyston::ObjectFlavor");
assert(g.llvm_flavor_type);
g.llvm_flavor_type_ptr = g.llvm_flavor_type->getPointerTo();
g.llvm_str_type_ptr = lookupFunction("boxStringPtr")->arg_begin()->getType(); g.llvm_str_type_ptr = lookupFunction("boxStringPtr")->arg_begin()->getType();
// The LLVM vector type for the arguments that we pass to runtimeCall and related functions. // The LLVM vector type for the arguments that we pass to runtimeCall and related functions.
......
...@@ -71,37 +71,6 @@ public: ...@@ -71,37 +71,6 @@ public:
virtual void visitPotentialRange(void* const* start, void* const* end) = 0; virtual void visitPotentialRange(void* const* start, void* const* end) = 0;
}; };
typedef int kindid_t;
class AllocationKind;
extern "C" kindid_t registerKind(const AllocationKind*);
class AllocationKind {
public:
#ifndef NDEBUG
static const int64_t COOKIE = 0x1234abcd0c00c1e;
const int64_t _cookie = COOKIE;
#endif
typedef void (*GCHandler)(GCVisitor*, void*);
GCHandler gc_handler;
typedef void (*FinalizationFunc)(void*);
FinalizationFunc finalizer;
const kindid_t kind_id;
public:
AllocationKind(GCHandler gc_handler, FinalizationFunc finalizer) __attribute__((visibility("default")))
: gc_handler(gc_handler), finalizer(finalizer), kind_id(registerKind(this)) {}
};
extern "C" const AllocationKind untracked_kind, conservative_kind;
class ObjectFlavor;
class ObjectFlavor : public AllocationKind {
public:
ObjectFlavor(GCHandler gc_handler, FinalizationFunc finalizer) __attribute__((visibility("default")))
: AllocationKind(gc_handler, finalizer) {}
};
namespace EffortLevel { namespace EffortLevel {
...@@ -302,56 +271,11 @@ EffortLevel::EffortLevel initialEffort(); ...@@ -302,56 +271,11 @@ EffortLevel::EffortLevel initialEffort();
typedef bool i1; typedef bool i1;
typedef int64_t i64; typedef int64_t i64;
extern "C" void* rt_alloc(size_t);
extern "C" void rt_free(void*);
extern "C" void* rt_realloc(void* ptr, size_t new_size);
extern "C" const std::string* getNameOfClass(BoxedClass* cls); extern "C" const std::string* getNameOfClass(BoxedClass* cls);
class Rewriter; class Rewriter;
class RewriterVar; class RewriterVar;
struct GCObjectHeader {
kindid_t kind_id;
uint16_t kind_data; // this part of the header is free for the kind to set as it wishes.
uint8_t gc_flags;
constexpr GCObjectHeader(const AllocationKind* kind) : kind_id(kind->kind_id), kind_data(0), gc_flags(0) {}
};
static_assert(sizeof(GCObjectHeader) <= sizeof(void*), "");
class GCObject {
public:
GCObjectHeader gc_header;
constexpr GCObject(const AllocationKind* kind) : gc_header(kind) {}
void* operator new(size_t size) __attribute__((visibility("default"))) { return rt_alloc(size); }
void operator delete(void* ptr) __attribute__((visibility("default"))) { rt_free(ptr); }
};
extern "C" const AllocationKind hc_kind;
class HiddenClass : public GCObject {
private:
HiddenClass() : GCObject(&hc_kind) {}
HiddenClass(const HiddenClass* parent) : GCObject(&hc_kind), attr_offsets(parent->attr_offsets) {}
public:
static HiddenClass* getRoot();
std::unordered_map<std::string, int> attr_offsets;
std::unordered_map<std::string, HiddenClass*> children;
HiddenClass* getOrMakeChild(const std::string& attr);
int getOffset(const std::string& attr) {
std::unordered_map<std::string, int>::iterator it = attr_offsets.find(attr);
if (it == attr_offsets.end())
return -1;
return it->second;
}
HiddenClass* delAttrToMakeHC(const std::string& attr);
};
class Box; class Box;
class BoxIterator { class BoxIterator {
public: public:
...@@ -375,6 +299,43 @@ private: ...@@ -375,6 +299,43 @@ private:
Box* value; Box* value;
}; };
namespace gc {
enum class GCKind : uint8_t {
PYTHON = 1,
CONSERVATIVE = 2,
UNTRACKED = 3,
};
void* gc_alloc(size_t nbytes, GCKind kind);
}
class PythonGCObject {
public:
void* operator new(size_t size) __attribute__((visibility("default"))) {
return gc_alloc(size, gc::GCKind::PYTHON);
}
void operator delete(void* ptr) __attribute__((visibility("default"))) { abort(); }
};
class ConservativeGCObject {
public:
void* operator new(size_t size) __attribute__((visibility("default"))) {
return gc_alloc(size, gc::GCKind::CONSERVATIVE);
}
void operator delete(void* ptr) __attribute__((visibility("default"))) { abort(); }
};
class UntrackedGCObject {
public:
void* operator new(size_t size) __attribute__((visibility("default"))) {
return gc_alloc(size, gc::GCKind::UNTRACKED);
}
void operator delete(void* ptr) __attribute__((visibility("default"))) { abort(); }
};
class HiddenClass;
extern HiddenClass* root_hcls;
class SetattrRewriteArgs; class SetattrRewriteArgs;
class GetattrRewriteArgs; class GetattrRewriteArgs;
...@@ -382,23 +343,23 @@ class DelattrRewriteArgs; ...@@ -382,23 +343,23 @@ class DelattrRewriteArgs;
struct HCAttrs { struct HCAttrs {
public: public:
struct AttrList : GCObject { struct AttrList : ConservativeGCObject {
Box* attrs[0]; Box* attrs[0];
}; };
HiddenClass* hcls; HiddenClass* hcls;
AttrList* attr_list; AttrList* attr_list;
HCAttrs() : hcls(HiddenClass::getRoot()), attr_list(nullptr) {} HCAttrs() : hcls(root_hcls), attr_list(nullptr) {}
}; };
class Box : public GCObject { class Box : public PythonGCObject {
public: public:
BoxedClass* cls; BoxedClass* cls;
llvm::iterator_range<BoxIterator> pyElements(); llvm::iterator_range<BoxIterator> pyElements();
Box(const ObjectFlavor* flavor, BoxedClass* cls); Box(BoxedClass* cls);
HCAttrs* getAttrsPtr(); HCAttrs* getAttrsPtr();
...@@ -412,6 +373,7 @@ public: ...@@ -412,6 +373,7 @@ public:
Box* getattr(const std::string& attr) { return getattr(attr, NULL); } Box* getattr(const std::string& attr) { return getattr(attr, NULL); }
void delattr(const std::string& attr, DelattrRewriteArgs* rewrite_args); void delattr(const std::string& attr, DelattrRewriteArgs* rewrite_args);
}; };
extern "C" const std::string* getTypeName(Box* o);
...@@ -429,6 +391,9 @@ public: ...@@ -429,6 +391,9 @@ public:
// Is NULL iff this is object_cls // Is NULL iff this is object_cls
BoxedClass* const base; BoxedClass* const base;
typedef void (*gcvisit_func)(GCVisitor*, Box*);
gcvisit_func gc_visit;
// Offset of the HCAttrs object or 0 if there are no hcattrs. // Offset of the HCAttrs object or 0 if there are no hcattrs.
// Analogous to tp_dictoffset // Analogous to tp_dictoffset
const int attrs_offset; const int attrs_offset;
...@@ -450,7 +415,7 @@ public: ...@@ -450,7 +415,7 @@ public:
// will need to update this once we support tp_getattr-style overriding: // will need to update this once we support tp_getattr-style overriding:
bool hasGenericGetattr() { return true; } bool hasGenericGetattr() { return true; }
BoxedClass(BoxedClass* base, int attrs_offset, int instance_size, bool is_user_defined); BoxedClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset, int instance_size, bool is_user_defined);
void freeze() { void freeze() {
assert(!is_constant); assert(!is_constant);
is_constant = true; is_constant = true;
......
...@@ -54,17 +54,15 @@ StaticRootHandle::~StaticRootHandle() { ...@@ -54,17 +54,15 @@ StaticRootHandle::~StaticRootHandle() {
getRootHandles()->erase(this); getRootHandles()->erase(this);
} }
bool TraceStackGCVisitor::isValid(void* p) {
return global_heap.getAllocationFromInteriorPointer(p);
}
inline void TraceStackGCVisitor::_visit(void* p) {
assert(isValid(p)); bool TraceStackGCVisitor::isValid(void* p) {
stack->push(p); return global_heap.getAllocationFromInteriorPointer(p) != NULL;
} }
void TraceStackGCVisitor::visit(void* p) { void TraceStackGCVisitor::visit(void* p) {
_visit(p); assert(global_heap.getAllocationFromInteriorPointer(p)->user_data == p);
stack->push(p);
} }
void TraceStackGCVisitor::visitRange(void* const* start, void* const* end) { void TraceStackGCVisitor::visitRange(void* const* start, void* const* end) {
...@@ -79,9 +77,9 @@ void TraceStackGCVisitor::visitRange(void* const* start, void* const* end) { ...@@ -79,9 +77,9 @@ void TraceStackGCVisitor::visitRange(void* const* start, void* const* end) {
} }
void TraceStackGCVisitor::visitPotential(void* p) { void TraceStackGCVisitor::visitPotential(void* p) {
void* a = global_heap.getAllocationFromInteriorPointer(p); GCAllocation* a = global_heap.getAllocationFromInteriorPointer(p);
if (a) { if (a) {
visit(a); visit(a->user_data);
} }
} }
...@@ -92,19 +90,6 @@ void TraceStackGCVisitor::visitPotentialRange(void* const* start, void* const* e ...@@ -92,19 +90,6 @@ void TraceStackGCVisitor::visitPotentialRange(void* const* start, void* const* e
} }
} }
#define MAX_KINDS 1024
#define KIND_OFFSET 0x111
static kindid_t num_kinds = 0;
static AllocationKind::GCHandler handlers[MAX_KINDS];
extern "C" kindid_t registerKind(const AllocationKind* kind) {
assert(kind == &untracked_kind || kind->gc_handler);
assert(num_kinds < MAX_KINDS);
assert(handlers[num_kinds] == NULL);
handlers[num_kinds] = kind->gc_handler;
return KIND_OFFSET + num_kinds++;
}
static void markPhase() { static void markPhase() {
#ifndef NVALGRIND #ifndef NVALGRIND
// Have valgrind close its eyes while we do the conservative stack and data scanning, // Have valgrind close its eyes while we do the conservative stack and data scanning,
...@@ -124,37 +109,37 @@ static void markPhase() { ...@@ -124,37 +109,37 @@ static void markPhase() {
// if (VERBOSITY()) printf("Found %d roots\n", stack.size()); // if (VERBOSITY()) printf("Found %d roots\n", stack.size());
while (void* p = stack.pop()) { while (void* p = stack.pop()) {
assert(((intptr_t)p) % 8 == 0); assert(((intptr_t)p) % 8 == 0);
GCObjectHeader* header = headerFromObject(p); GCAllocation* al = GCAllocation::fromUserData(p);
if (isMarked(header)) { if (isMarked(al)) {
continue; continue;
} }
// printf("Marking + scanning %p\n", p); // printf("Marking + scanning %p\n", p);
setMark(header); setMark(al);
// is being made GCKind kind_id = al->kind_id;
if (header->kind_id == 0) if (kind_id == GCKind::UNTRACKED) {
continue; continue;
} else if (kind_id == GCKind::CONSERVATIVE) {
ASSERT(KIND_OFFSET <= header->kind_id && header->kind_id < KIND_OFFSET + num_kinds, "%p %d", header, uint32_t bytes = al->kind_data;
header->kind_id); visitor.visitPotentialRange((void**)p, (void**)((char*)p + bytes));
} else if (kind_id == GCKind::PYTHON) {
if (header->kind_id == untracked_kind.kind_id) Box* b = reinterpret_cast<Box*>(p);
continue; BoxedClass* cls = b->cls;
// ASSERT(kind->_cookie == AllocationKind::COOKIE, "%lx %lx", kind->_cookie, AllocationKind::COOKIE); if (cls) {
// AllocationKind::GCHandler gcf = kind->gc_handler; // The cls can be NULL since we use 'new' to construct them.
AllocationKind::GCHandler gcf = handlers[header->kind_id - KIND_OFFSET]; // An arbitrary amount of stuff can happen between the 'new' and
// the call to the constructor (ie the args get evaluated), which
assert(gcf); // can trigger a collection.
// if (!gcf) { ASSERT(cls->gc_visit, "%s", getTypeName(b)->c_str());
// std::string name = g.func_addr_registry.getFuncNameAtAddress((void*)kind, true); cls->gc_visit(&visitor, b);
// ASSERT(gcf, "%p %s", kind, name.c_str()); }
//} } else {
RELEASE_ASSERT(0, "Unhandled kind: %d", (int)kind_id);
gcf(&visitor, p); }
} }
#ifndef NVALGRIND #ifndef NVALGRIND
......
...@@ -22,22 +22,6 @@ ...@@ -22,22 +22,6 @@
namespace pyston { namespace pyston {
namespace gc { namespace gc {
#define MARK_BIT 0x1
inline void setMark(GCObjectHeader* header) {
header->gc_flags |= MARK_BIT;
}
inline void clearMark(GCObjectHeader* header) {
header->gc_flags &= ~MARK_BIT;
}
inline bool isMarked(GCObjectHeader* header) {
return (header->gc_flags & MARK_BIT) != 0;
}
#undef MARK_BIT
class TraceStack { class TraceStack {
private: private:
std::vector<void*> v; std::vector<void*> v;
...@@ -65,12 +49,11 @@ class TraceStackGCVisitor : public GCVisitor { ...@@ -65,12 +49,11 @@ class TraceStackGCVisitor : public GCVisitor {
private: private:
bool isValid(void* p); bool isValid(void* p);
void _visit(void* p);
public: public:
TraceStack* stack; TraceStack* stack;
TraceStackGCVisitor(TraceStack* stack) : stack(stack) {} TraceStackGCVisitor(TraceStack* stack) : stack(stack) {}
// These all work on *user* pointers, ie pointers to the user_data section of GCAllocations
void visit(void* p) override; void visit(void* p) override;
void visitRange(void* const* start, void* const* end) override; void visitRange(void* const* start, void* const* end) override;
void visitPotential(void* p) override; void visitPotential(void* p) override;
......
...@@ -27,8 +27,9 @@ ...@@ -27,8 +27,9 @@
namespace pyston { namespace pyston {
namespace gc { namespace gc {
inline void* gc_alloc(size_t bytes) __attribute__((visibility("default"))); inline void* gc_alloc(size_t bytes, GCKind kind_id) __attribute__((visibility("default")));
inline void* gc_alloc(size_t bytes) { inline void* gc_alloc(size_t bytes, GCKind kind_id) {
bytes += sizeof(GCAllocation);
#ifndef NVALGRIND #ifndef NVALGRIND
// Adding a redzone will confuse the allocator, so disable it for now. // Adding a redzone will confuse the allocator, so disable it for now.
...@@ -37,19 +38,33 @@ inline void* gc_alloc(size_t bytes) { ...@@ -37,19 +38,33 @@ inline void* gc_alloc(size_t bytes) {
// valgrind is actively running, but I think it's better to just always turn them on. // valgrind is actively running, but I think it's better to just always turn them on.
// They're broken and have 0 size anyway. // They're broken and have 0 size anyway.
#define ENABLE_REDZONES 1 #define ENABLE_REDZONES 1
void* r;
if (ENABLE_REDZONES)
bytes += REDZONE_SIZE * 2;
#endif
GCAllocation* alloc = global_heap.alloc(bytes);
alloc->kind_id = kind_id;
alloc->gc_flags = 0;
if (kind_id == GCKind::CONSERVATIVE) {
assert(bytes < (1 << 31));
alloc->kind_data = bytes;
}
void* r = alloc->user_data;
#ifndef NVALGRIND
if (ENABLE_REDZONES) { if (ENABLE_REDZONES) {
void* base = global_heap.alloc(bytes + REDZONE_SIZE * 2); r = ((char*)r) + REDZONE_SIZE;
r = ((char*)base) + REDZONE_SIZE;
// printf("alloc base = %p\n", base);
} else {
r = global_heap.alloc(bytes);
} }
VALGRIND_MALLOCLIKE_BLOCK(r, bytes, REDZONE_SIZE, false); VALGRIND_MALLOCLIKE_BLOCK(r, bytes, REDZONE_SIZE, false);
#else
void* r = global_heap.alloc(bytes);
#endif #endif
// TODO This doesn't belong here (probably in PythonGCObject?)...
if (kind_id == GCKind::PYTHON) {
((Box*)r)->cls = NULL;
}
#ifndef NDEBUG #ifndef NDEBUG
// I think I have a suspicion: the gc will see the constant and treat it as a // I think I have a suspicion: the gc will see the constant and treat it as a
// root. So instead, shift to hide the pointer // root. So instead, shift to hide the pointer
...@@ -68,21 +83,23 @@ inline void* gc_alloc(size_t bytes) { ...@@ -68,21 +83,23 @@ inline void* gc_alloc(size_t bytes) {
inline void* gc_realloc(void* ptr, size_t bytes) __attribute__((visibility("default"))); inline void* gc_realloc(void* ptr, size_t bytes) __attribute__((visibility("default")));
inline void* gc_realloc(void* ptr, size_t bytes) { inline void* gc_realloc(void* ptr, size_t bytes) {
bytes += sizeof(GCAllocation);
#ifndef NVALGRIND #ifndef NVALGRIND
void* rtn; void* rtn;
if (ENABLE_REDZONES) { if (ENABLE_REDZONES) {
void* base = (char*)ptr - REDZONE_SIZE; void* base = (char*)ptr - REDZONE_SIZE;
void* rtn_base = global_heap.realloc(base, bytes + 2 * REDZONE_SIZE); void* rtn_base = global_heap.realloc(GCAllocation::fromUserData(base), bytes + 2 * REDZONE_SIZE)->user_data;
rtn = (char*)rtn_base + REDZONE_SIZE; rtn = (char*)rtn_base + REDZONE_SIZE;
} else { } else {
rtn = global_heap.realloc(ptr, bytes); rtn = global_heap.realloc(GCAllocation::fromUserData(ptr), bytes)->user_data;
} }
VALGRIND_FREELIKE_BLOCK(ptr, REDZONE_SIZE); VALGRIND_FREELIKE_BLOCK(ptr, REDZONE_SIZE);
VALGRIND_MALLOCLIKE_BLOCK(rtn, bytes, REDZONE_SIZE, true); VALGRIND_MALLOCLIKE_BLOCK(rtn, bytes, REDZONE_SIZE, true);
return rtn; return rtn;
#else #else
return global_heap.realloc(ptr, bytes); return global_heap.realloc(GCAllocation::fromUserData(ptr), bytes)->user_data;
#endif #endif
} }
...@@ -91,13 +108,13 @@ inline void gc_free(void* ptr) { ...@@ -91,13 +108,13 @@ inline void gc_free(void* ptr) {
#ifndef NVALGRIND #ifndef NVALGRIND
if (ENABLE_REDZONES) { if (ENABLE_REDZONES) {
void* base = (char*)ptr - REDZONE_SIZE; void* base = (char*)ptr - REDZONE_SIZE;
global_heap.free(base); global_heap.free(GCAllocation::fromUserData(base));
} else { } else {
global_heap.free(ptr); global_heap.free(GCAllocation::fromUserData(ptr));
} }
VALGRIND_FREELIKE_BLOCK(ptr, REDZONE_SIZE); VALGRIND_FREELIKE_BLOCK(ptr, REDZONE_SIZE);
#else #else
global_heap.free(ptr); global_heap.free(GCAllocation::fromUserData(ptr));
#endif #endif
} }
} }
......
...@@ -83,13 +83,13 @@ public: ...@@ -83,13 +83,13 @@ public:
bool contains(void* addr) { return start <= addr && addr < cur; } bool contains(void* addr) { return start <= addr && addr < cur; }
}; };
Arena small_arena((void*)0x1270000000L); static Arena small_arena((void*)0x1270000000L);
Arena large_arena((void*)0x2270000000L); static Arena large_arena((void*)0x2270000000L);
struct LargeObj { struct LargeObj {
LargeObj* next, **prev; LargeObj* next, **prev;
size_t obj_size; size_t obj_size;
char data[0]; GCAllocation data[0];
int mmap_size() { int mmap_size() {
size_t total_size = obj_size + sizeof(LargeObj); size_t total_size = obj_size + sizeof(LargeObj);
...@@ -99,14 +99,14 @@ struct LargeObj { ...@@ -99,14 +99,14 @@ struct LargeObj {
int capacity() { return mmap_size() - sizeof(LargeObj); } int capacity() { return mmap_size() - sizeof(LargeObj); }
static LargeObj* fromPointer(void* ptr) { static LargeObj* fromAllocation(GCAllocation* alloc) {
char* rtn = (char*)ptr + ((char*)NULL - ((LargeObj*)(NULL))->data); char* rtn = (char*)alloc - offsetof(LargeObj, data);
assert((uintptr_t)rtn % PAGE_SIZE == 0); assert((uintptr_t)rtn % PAGE_SIZE == 0);
return reinterpret_cast<LargeObj*>(rtn); return reinterpret_cast<LargeObj*>(rtn);
} }
}; };
void* Heap::allocLarge(size_t size) { GCAllocation* Heap::allocLarge(size_t size) {
_collectIfNeeded(size); _collectIfNeeded(size);
LOCK_REGION(lock); LOCK_REGION(lock);
...@@ -122,7 +122,7 @@ void* Heap::allocLarge(size_t size) { ...@@ -122,7 +122,7 @@ void* Heap::allocLarge(size_t size) {
rtn->prev = &large_head; rtn->prev = &large_head;
large_head = rtn; large_head = rtn;
return &rtn->data; return rtn->data;
} }
static Block* alloc_block(uint64_t size, Block** prev) { static Block* alloc_block(uint64_t size, Block** prev) {
...@@ -197,7 +197,7 @@ Heap::ThreadBlockCache::~ThreadBlockCache() { ...@@ -197,7 +197,7 @@ Heap::ThreadBlockCache::~ThreadBlockCache() {
} }
} }
static void* allocFromBlock(Block* b) { static GCAllocation* allocFromBlock(Block* b) {
int i = 0; int i = 0;
uint64_t mask = 0; uint64_t mask = 0;
for (; i < BITFIELD_ELTS; i++) { for (; i < BITFIELD_ELTS; i++) {
...@@ -220,7 +220,7 @@ static void* allocFromBlock(Block* b) { ...@@ -220,7 +220,7 @@ static void* allocFromBlock(Block* b) {
int idx = first + i * 64; int idx = first + i * 64;
void* rtn = &b->atoms[idx]; void* rtn = &b->atoms[idx];
return rtn; return reinterpret_cast<GCAllocation*>(rtn);
} }
static Block* claimBlock(size_t rounded_size, Block** free_head) { static Block* claimBlock(size_t rounded_size, Block** free_head) {
...@@ -233,7 +233,7 @@ static Block* claimBlock(size_t rounded_size, Block** free_head) { ...@@ -233,7 +233,7 @@ static Block* claimBlock(size_t rounded_size, Block** free_head) {
return alloc_block(rounded_size, NULL); return alloc_block(rounded_size, NULL);
} }
void* Heap::allocSmall(size_t rounded_size, int bucket_idx) { GCAllocation* Heap::allocSmall(size_t rounded_size, int bucket_idx) {
_collectIfNeeded(rounded_size); _collectIfNeeded(rounded_size);
Block** free_head = &heads[bucket_idx]; Block** free_head = &heads[bucket_idx];
...@@ -252,7 +252,7 @@ void* Heap::allocSmall(size_t rounded_size, int bucket_idx) { ...@@ -252,7 +252,7 @@ void* Heap::allocSmall(size_t rounded_size, int bucket_idx) {
while (true) { while (true) {
while (Block* cache_block = *cache_head) { while (Block* cache_block = *cache_head) {
void* rtn = allocFromBlock(cache_block); GCAllocation* rtn = allocFromBlock(cache_block);
if (rtn) if (rtn)
return rtn; return rtn;
...@@ -280,11 +280,11 @@ void* Heap::allocSmall(size_t rounded_size, int bucket_idx) { ...@@ -280,11 +280,11 @@ void* Heap::allocSmall(size_t rounded_size, int bucket_idx) {
} }
} }
void _freeFrom(void* ptr, Block* b) { void _freeFrom(GCAllocation* alloc, Block* b) {
assert(b == Block::forPointer(ptr)); assert(b == Block::forPointer(alloc));
size_t size = b->size; size_t size = b->size;
int offset = (char*)ptr - (char*)b; int offset = (char*)alloc - (char*)b;
assert(offset % size == 0); assert(offset % size == 0);
int atom_idx = offset / ATOM_SIZE; int atom_idx = offset / ATOM_SIZE;
...@@ -308,56 +308,56 @@ static void _freeLargeObj(LargeObj* lobj) { ...@@ -308,56 +308,56 @@ static void _freeLargeObj(LargeObj* lobj) {
assert(r == 0); assert(r == 0);
} }
void Heap::free(void* ptr) { void Heap::free(GCAllocation* al) {
if (large_arena.contains(ptr)) { if (large_arena.contains(al)) {
LargeObj* lobj = LargeObj::fromPointer(ptr); LargeObj* lobj = LargeObj::fromAllocation(al);
_freeLargeObj(lobj); _freeLargeObj(lobj);
return; return;
} }
assert(small_arena.contains(ptr)); assert(small_arena.contains(al));
Block* b = Block::forPointer(ptr); Block* b = Block::forPointer(al);
_freeFrom(ptr, b); _freeFrom(al, b);
} }
void* Heap::realloc(void* ptr, size_t bytes) { GCAllocation* Heap::realloc(GCAllocation* al, size_t bytes) {
if (large_arena.contains(ptr)) { if (large_arena.contains(al)) {
LargeObj* lobj = LargeObj::fromPointer(ptr); LargeObj* lobj = LargeObj::fromAllocation(al);
int capacity = lobj->capacity(); int capacity = lobj->capacity();
if (capacity >= bytes && capacity < bytes * 2) if (capacity >= bytes && capacity < bytes * 2)
return ptr; return al;
void* rtn = alloc(bytes); GCAllocation* rtn = alloc(bytes);
memcpy(rtn, ptr, std::min(bytes, lobj->obj_size)); memcpy(rtn, al, std::min(bytes, lobj->obj_size));
_freeLargeObj(lobj); _freeLargeObj(lobj);
return rtn; return rtn;
} }
assert(small_arena.contains(ptr)); assert(small_arena.contains(al));
Block* b = Block::forPointer(ptr); Block* b = Block::forPointer(al);
size_t size = b->size; size_t size = b->size;
if (size >= bytes && size < bytes * 2) if (size >= bytes && size < bytes * 2)
return ptr; return al;
void* rtn = alloc(bytes); GCAllocation* rtn = alloc(bytes);
#ifndef NVALGRIND #ifndef NVALGRIND
VALGRIND_DISABLE_ERROR_REPORTING; VALGRIND_DISABLE_ERROR_REPORTING;
memcpy(rtn, ptr, std::min(bytes, size)); memcpy(rtn, al, std::min(bytes, size));
VALGRIND_ENABLE_ERROR_REPORTING; VALGRIND_ENABLE_ERROR_REPORTING;
#else #else
memcpy(rtn, ptr, std::min(bytes, size)); memcpy(rtn, al, std::min(bytes, size));
#endif #endif
_freeFrom(ptr, b); _freeFrom(al, b);
return rtn; return rtn;
} }
void* Heap::getAllocationFromInteriorPointer(void* ptr) { GCAllocation* Heap::getAllocationFromInteriorPointer(void* ptr) {
if (large_arena.contains(ptr)) { if (large_arena.contains(ptr)) {
LargeObj* cur = large_head; LargeObj* cur = large_head;
while (cur) { while (cur) {
...@@ -387,7 +387,7 @@ void* Heap::getAllocationFromInteriorPointer(void* ptr) { ...@@ -387,7 +387,7 @@ void* Heap::getAllocationFromInteriorPointer(void* ptr) {
if (b->isfree[bitmap_idx] & mask) if (b->isfree[bitmap_idx] & mask)
return NULL; return NULL;
return &b->atoms[atom_idx]; return reinterpret_cast<GCAllocation*>(&b->atoms[atom_idx]);
} }
static Block** freeChain(Block** head) { static Block** freeChain(Block** head) {
...@@ -406,11 +406,14 @@ static Block** freeChain(Block** head) { ...@@ -406,11 +406,14 @@ static Block** freeChain(Block** head) {
continue; continue;
void* p = &b->atoms[atom_idx]; void* p = &b->atoms[atom_idx];
GCObjectHeader* header = headerFromObject(p); GCAllocation* al = reinterpret_cast<GCAllocation*>(p);
if (isMarked(header)) { if (isMarked(al)) {
clearMark(header); clearMark(al);
} else { } else {
if (VERBOSITY() >= 2)
printf("Freeing %p\n", al->user_data);
// assert(p != (void*)0x127000d960); // the main module // assert(p != (void*)0x127000d960); // the main module
b->isfree[bitmap_idx] |= mask; b->isfree[bitmap_idx] |= mask;
} }
...@@ -464,13 +467,12 @@ void Heap::freeUnmarked() { ...@@ -464,13 +467,12 @@ void Heap::freeUnmarked() {
LargeObj* cur = large_head; LargeObj* cur = large_head;
while (cur) { while (cur) {
void* p = cur->data; GCAllocation* al = cur->data;
GCObjectHeader* header = headerFromObject(p); if (isMarked(al)) {
if (isMarked(header)) { clearMark(al);
clearMark(header);
} else { } else {
if (VERBOSITY() >= 2) if (VERBOSITY() >= 2)
printf("Freeing %p\n", p); printf("Freeing %p\n", al->user_data);
*cur->prev = cur->next; *cur->prev = cur->next;
if (cur->next) if (cur->next)
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#ifndef PYSTON_GC_HEAP_H #ifndef PYSTON_GC_HEAP_H
#define PYSTON_GC_HEAP_H #define PYSTON_GC_HEAP_H
#include <cstddef>
#include <cstdint> #include <cstdint>
#include "core/common.h" #include "core/common.h"
...@@ -23,14 +24,41 @@ ...@@ -23,14 +24,41 @@
namespace pyston { namespace pyston {
namespace gc { namespace gc {
inline GCObjectHeader* headerFromObject(void* obj) { typedef uint8_t kindid_t;
#ifndef NVALGRIND struct GCAllocation {
return static_cast<GCObjectHeader*>((void*)((char*)obj + 0)); unsigned int gc_flags : 8;
#else GCKind kind_id : 8;
return static_cast<GCObjectHeader*>(obj); unsigned int _reserved1 : 16;
#endif unsigned int kind_data : 32;
char user_data[0];
static GCAllocation* fromUserData(void* user_data) {
char* d = reinterpret_cast<char*>(user_data);
return reinterpret_cast<GCAllocation*>(d - offsetof(GCAllocation, user_data));
}
};
static_assert(sizeof(GCAllocation) <= sizeof(void*),
"we should try to make sure the gc header is word-sized or smaller");
#define MARK_BIT 0x1
inline void setMark(GCAllocation* header) {
header->gc_flags |= MARK_BIT;
} }
inline void clearMark(GCAllocation* header) {
header->gc_flags &= ~MARK_BIT;
}
inline bool isMarked(GCAllocation* header) {
return (header->gc_flags & MARK_BIT) != 0;
}
#undef MARK_BIT
#define BLOCK_SIZE (4 * 4096) #define BLOCK_SIZE (4 * 4096)
#define ATOM_SIZE 16 #define ATOM_SIZE 16
static_assert(BLOCK_SIZE % ATOM_SIZE == 0, ""); static_assert(BLOCK_SIZE % ATOM_SIZE == 0, "");
...@@ -80,8 +108,8 @@ private: ...@@ -80,8 +108,8 @@ private:
Block* full_heads[NUM_BUCKETS]; Block* full_heads[NUM_BUCKETS];
LargeObj* large_head = NULL; LargeObj* large_head = NULL;
void* allocSmall(size_t rounded_size, int bucket_idx); GCAllocation* allocSmall(size_t rounded_size, int bucket_idx);
void* allocLarge(size_t bytes); GCAllocation* allocLarge(size_t bytes);
// DS_DEFINE_MUTEX(lock); // DS_DEFINE_MUTEX(lock);
DS_DEFINE_SPINLOCK(lock); DS_DEFINE_SPINLOCK(lock);
...@@ -104,10 +132,10 @@ private: ...@@ -104,10 +132,10 @@ private:
public: public:
Heap() : thread_caches(this) {} Heap() : thread_caches(this) {}
void* realloc(void* ptr, size_t bytes); GCAllocation* realloc(GCAllocation* alloc, size_t bytes);
void* alloc(size_t bytes) { GCAllocation* alloc(size_t bytes) {
void* rtn; GCAllocation* rtn;
// assert(bytes >= 16); // assert(bytes >= 16);
if (bytes <= 16) if (bytes <= 16)
rtn = allocSmall(16, 0); rtn = allocSmall(16, 0);
...@@ -125,16 +153,13 @@ public: ...@@ -125,16 +153,13 @@ public:
} }
} }
// assert(rtn);
GCObjectHeader* header = headerFromObject(rtn);
*reinterpret_cast<intptr_t*>(header) = 0;
return rtn; return rtn;
} }
void free(void* ptr); void free(GCAllocation* alloc);
// not thread safe: // not thread safe:
void* getAllocationFromInteriorPointer(void* ptr); GCAllocation* getAllocationFromInteriorPointer(void* ptr);
// not thread safe: // not thread safe:
void freeUnmarked(); void freeUnmarked();
}; };
......
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
#include "core/common.h" #include "core/common.h"
#include "core/types.h" #include "core/types.h"
#include "gc/collector.h" #include "gc/collector.h"
#include "runtime/gc_runtime.h"
#include "runtime/objmodel.h" #include "runtime/objmodel.h"
#include "runtime/types.h" #include "runtime/types.h"
......
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
#include "core/types.h" #include "core/types.h"
#include "gc/collector.h" #include "gc/collector.h"
#include "runtime/gc_runtime.h"
#include "runtime/inline/boxing.h" #include "runtime/inline/boxing.h"
#include "runtime/types.h" #include "runtime/types.h"
#include "runtime/util.h" #include "runtime/util.h"
......
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
#include "core/ast.h" #include "core/ast.h"
#include "core/types.h" #include "core/types.h"
#include "gc/collector.h" #include "gc/collector.h"
#include "runtime/gc_runtime.h"
#include "runtime/inline/xrange.h" #include "runtime/inline/xrange.h"
#include "runtime/list.h" #include "runtime/list.h"
#include "runtime/long.h" #include "runtime/long.h"
...@@ -392,7 +391,6 @@ Box* zip2(Box* container1, Box* container2) { ...@@ -392,7 +391,6 @@ Box* zip2(Box* container1, Box* container2) {
return rtn; return rtn;
} }
extern "C" const ObjectFlavor notimplemented_flavor(&boxGCHandler, NULL);
BoxedClass* notimplemented_cls; BoxedClass* notimplemented_cls;
BoxedModule* builtins_module; BoxedModule* builtins_module;
...@@ -401,7 +399,6 @@ BoxedClass* Exception, *AssertionError, *AttributeError, *GeneratorExit, *TypeEr ...@@ -401,7 +399,6 @@ BoxedClass* Exception, *AssertionError, *AttributeError, *GeneratorExit, *TypeEr
*IOError, *OSError, *ZeroDivisionError, *ValueError, *UnboundLocalError, *RuntimeError, *ImportError, *IOError, *OSError, *ZeroDivisionError, *ValueError, *UnboundLocalError, *RuntimeError, *ImportError,
*StopIteration, *Warning, *SyntaxError; *StopIteration, *Warning, *SyntaxError;
const ObjectFlavor exception_flavor(&boxGCHandler, NULL);
Box* exceptionNew1(BoxedClass* cls) { Box* exceptionNew1(BoxedClass* cls) {
return exceptionNew2(cls, boxStrConstant("")); return exceptionNew2(cls, boxStrConstant(""));
} }
...@@ -409,7 +406,7 @@ Box* exceptionNew1(BoxedClass* cls) { ...@@ -409,7 +406,7 @@ Box* exceptionNew1(BoxedClass* cls) {
class BoxedException : public Box { class BoxedException : public Box {
public: public:
HCAttrs attrs; HCAttrs attrs;
BoxedException(BoxedClass* cls) : Box(&exception_flavor, cls) {} BoxedException(BoxedClass* cls) : Box(cls) {}
}; };
Box* exceptionNew2(BoxedClass* cls, Box* message) { Box* exceptionNew2(BoxedClass* cls, Box* message) {
...@@ -441,7 +438,7 @@ Box* exceptionRepr(Box* b) { ...@@ -441,7 +438,7 @@ Box* exceptionRepr(Box* b) {
} }
static BoxedClass* makeBuiltinException(BoxedClass* base, const char* name) { static BoxedClass* makeBuiltinException(BoxedClass* base, const char* name) {
BoxedClass* cls = new BoxedClass(base, offsetof(BoxedException, attrs), sizeof(BoxedException), false); BoxedClass* cls = new BoxedClass(base, NULL, offsetof(BoxedException, attrs), sizeof(BoxedException), false);
cls->giveAttr("__name__", boxStrConstant(name)); cls->giveAttr("__name__", boxStrConstant(name));
// TODO these should be on the base Exception class: // TODO these should be on the base Exception class:
...@@ -455,14 +452,13 @@ static BoxedClass* makeBuiltinException(BoxedClass* base, const char* name) { ...@@ -455,14 +452,13 @@ static BoxedClass* makeBuiltinException(BoxedClass* base, const char* name) {
} }
BoxedClass* enumerate_cls; BoxedClass* enumerate_cls;
extern const ObjectFlavor enumerate_flavor;
class BoxedEnumerate : public Box { class BoxedEnumerate : public Box {
private: private:
Box* iterator; Box* iterator;
int64_t idx; int64_t idx;
public: public:
BoxedEnumerate(Box* iterator, int64_t idx) : Box(&enumerate_flavor, enumerate_cls), iterator(iterator), idx(idx) {} BoxedEnumerate(Box* iterator, int64_t idx) : Box(enumerate_cls), iterator(iterator), idx(idx) {}
static Box* new_(Box* cls, Box* obj, Box* start) { static Box* new_(Box* cls, Box* obj, Box* start) {
RELEASE_ASSERT(cls == enumerate_cls, ""); RELEASE_ASSERT(cls == enumerate_cls, "");
...@@ -508,25 +504,24 @@ public: ...@@ -508,25 +504,24 @@ public:
return r; return r;
} }
static void gcHandler(GCVisitor* v, void* p) { static void gcHandler(GCVisitor* v, Box* b) {
boxGCHandler(v, p); boxGCHandler(v, b);
BoxedEnumerate* it = (BoxedEnumerate*)p; BoxedEnumerate* it = (BoxedEnumerate*)b;
v->visit(it->iterator); v->visit(it->iterator);
} }
}; };
const ObjectFlavor enumerate_flavor(&BoxedEnumerate::gcHandler, NULL);
void setupBuiltins() { void setupBuiltins() {
builtins_module = createModule("__builtin__", "__builtin__"); builtins_module = createModule("__builtin__", "__builtin__");
builtins_module->giveAttr("None", None); builtins_module->giveAttr("None", None);
notimplemented_cls = new BoxedClass(object_cls, 0, sizeof(Box), false); notimplemented_cls = new BoxedClass(object_cls, NULL, 0, sizeof(Box), false);
notimplemented_cls->giveAttr("__name__", boxStrConstant("NotImplementedType")); notimplemented_cls->giveAttr("__name__", boxStrConstant("NotImplementedType"));
notimplemented_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)notimplementedRepr, STR, 1))); notimplemented_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)notimplementedRepr, STR, 1)));
notimplemented_cls->freeze(); notimplemented_cls->freeze();
NotImplemented = new Box(&notimplemented_flavor, notimplemented_cls); NotImplemented = new Box(notimplemented_cls);
gc::registerStaticRootObj(NotImplemented); gc::registerStaticRootObj(NotImplemented);
builtins_module->giveAttr("NotImplemented", NotImplemented); builtins_module->giveAttr("NotImplemented", NotImplemented);
...@@ -598,7 +593,7 @@ void setupBuiltins() { ...@@ -598,7 +593,7 @@ void setupBuiltins() {
builtins_module->giveAttr("issubclass", issubclass_obj); builtins_module->giveAttr("issubclass", issubclass_obj);
enumerate_cls = new BoxedClass(object_cls, 0, sizeof(BoxedEnumerate), false); enumerate_cls = new BoxedClass(object_cls, &BoxedEnumerate::gcHandler, 0, sizeof(BoxedEnumerate), false);
enumerate_cls->giveAttr("__name__", boxStrConstant("enumerate")); enumerate_cls->giveAttr("__name__", boxStrConstant("enumerate"));
enumerate_cls->giveAttr( enumerate_cls->giveAttr(
"__new__", "__new__",
......
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
#include "core/types.h" #include "core/types.h"
#include "gc/collector.h" #include "gc/collector.h"
#include "runtime/gc_runtime.h"
#include "runtime/inline/boxing.h" #include "runtime/inline/boxing.h"
#include "runtime/types.h" #include "runtime/types.h"
#include "runtime/util.h" #include "runtime/util.h"
......
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
#include "codegen/compvars.h" #include "codegen/compvars.h"
#include "core/types.h" #include "core/types.h"
#include "runtime/gc_runtime.h"
#include "runtime/inline/boxing.h" #include "runtime/inline/boxing.h"
#include "runtime/types.h" #include "runtime/types.h"
#include "runtime/util.h" #include "runtime/util.h"
......
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
#include "core/types.h" #include "core/types.h"
#include "gc/collector.h" #include "gc/collector.h"
#include "runtime/gc_runtime.h"
#include "runtime/inline/boxing.h" #include "runtime/inline/boxing.h"
#include "runtime/types.h" #include "runtime/types.h"
#include "runtime/util.h" #include "runtime/util.h"
......
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
#include "core/types.h" #include "core/types.h"
#include "gc/collector.h" #include "gc/collector.h"
#include "runtime/gc_runtime.h"
#include "runtime/inline/boxing.h" #include "runtime/inline/boxing.h"
#include "runtime/int.h" #include "runtime/int.h"
#include "runtime/types.h" #include "runtime/types.h"
......
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
#include "codegen/compvars.h" #include "codegen/compvars.h"
#include "core/threading.h" #include "core/threading.h"
#include "core/types.h" #include "core/types.h"
#include "runtime/gc_runtime.h"
#include "runtime/objmodel.h" #include "runtime/objmodel.h"
#include "runtime/types.h" #include "runtime/types.h"
......
...@@ -27,7 +27,6 @@ namespace pyston { ...@@ -27,7 +27,6 @@ namespace pyston {
static BoxedModule* test_module = NULL; static BoxedModule* test_module = NULL;
extern "C" const ObjectFlavor capifunc_flavor(&boxGCHandler, NULL);
BoxedClass* capifunc_cls; BoxedClass* capifunc_cls;
class BoxedCApiFunction : public Box { class BoxedCApiFunction : public Box {
private: private:
...@@ -35,8 +34,7 @@ private: ...@@ -35,8 +34,7 @@ private:
PyCFunction func; PyCFunction func;
public: public:
BoxedCApiFunction(const char* name, PyCFunction func) BoxedCApiFunction(const char* name, PyCFunction func) : Box(capifunc_cls), name(name), func(func) {}
: Box(&capifunc_flavor, capifunc_cls), name(name), func(func) {}
static BoxedString* __repr__(BoxedCApiFunction* self) { static BoxedString* __repr__(BoxedCApiFunction* self) {
assert(self->cls == capifunc_cls); assert(self->cls == capifunc_cls);
...@@ -124,7 +122,7 @@ BoxedModule* getTestModule() { ...@@ -124,7 +122,7 @@ BoxedModule* getTestModule() {
} }
void setupCAPI() { void setupCAPI() {
capifunc_cls = new BoxedClass(object_cls, 0, sizeof(BoxedCApiFunction), false); capifunc_cls = new BoxedClass(object_cls, NULL, 0, sizeof(BoxedCApiFunction), false);
capifunc_cls->giveAttr("__name__", boxStrConstant("capifunc")); capifunc_cls->giveAttr("__name__", boxStrConstant("capifunc"));
capifunc_cls->giveAttr("__repr__", capifunc_cls->giveAttr("__repr__",
......
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
#include "core/stats.h" #include "core/stats.h"
#include "core/types.h" #include "core/types.h"
#include "gc/collector.h" #include "gc/collector.h"
#include "runtime/gc_runtime.h"
#include "runtime/objmodel.h" #include "runtime/objmodel.h"
#include "runtime/types.h" #include "runtime/types.h"
#include "runtime/util.h" #include "runtime/util.h"
...@@ -165,16 +164,15 @@ extern "C" Box* dictNew(Box* _cls) { ...@@ -165,16 +164,15 @@ extern "C" Box* dictNew(Box* _cls) {
} }
BoxedClass* dict_iterator_cls = NULL; BoxedClass* dict_iterator_cls = NULL;
extern "C" void dictIteratorGCHandler(GCVisitor* v, void* p) { extern "C" void dictIteratorGCHandler(GCVisitor* v, Box* b) {
boxGCHandler(v, p); boxGCHandler(v, b);
BoxedDictIterator* it = (BoxedDictIterator*)p;
BoxedDictIterator* it = static_cast<BoxedDictIterator*>(b);
v->visit(it->d); v->visit(it->d);
} }
extern "C" const ObjectFlavor dict_iterator_flavor(&dictIteratorGCHandler, NULL);
void setupDict() { void setupDict() {
dict_iterator_cls = new BoxedClass(object_cls, 0, sizeof(BoxedDict), false); dict_iterator_cls = new BoxedClass(object_cls, &dictIteratorGCHandler, 0, sizeof(BoxedDict), false);
dict_cls->giveAttr("__name__", boxStrConstant("dict")); dict_cls->giveAttr("__name__", boxStrConstant("dict"));
// dict_cls->giveAttr("__len__", new BoxedFunction(boxRTFunction((void*)dictLen, NULL, 1))); // dict_cls->giveAttr("__len__", new BoxedFunction(boxRTFunction((void*)dictLen, NULL, 1)));
......
...@@ -33,7 +33,6 @@ public: ...@@ -33,7 +33,6 @@ public:
BoxedDictIterator(BoxedDict* d, IteratorType type); BoxedDictIterator(BoxedDict* d, IteratorType type);
}; };
extern "C" const ObjectFlavor dict_iterator_flavor;
Box* dictIterKeys(Box* self); Box* dictIterKeys(Box* self);
Box* dictIterValues(Box* self); Box* dictIterValues(Box* self);
Box* dictIterItems(Box* self); Box* dictIterItems(Box* self);
......
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
#include "core/common.h" #include "core/common.h"
#include "core/stats.h" #include "core/stats.h"
#include "core/types.h" #include "core/types.h"
#include "runtime/gc_runtime.h"
#include "runtime/objmodel.h" #include "runtime/objmodel.h"
#include "runtime/types.h" #include "runtime/types.h"
#include "runtime/util.h" #include "runtime/util.h"
......
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
#include "codegen/compvars.h" #include "codegen/compvars.h"
#include "core/types.h" #include "core/types.h"
#include "runtime/gc_runtime.h"
#include "runtime/inline/boxing.h" #include "runtime/inline/boxing.h"
#include "runtime/objmodel.h" #include "runtime/objmodel.h"
#include "runtime/types.h" #include "runtime/types.h"
......
// Copyright (c) 2014 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PYSTON_RUNTIME_GCRUNTIME_H
#define PYSTON_RUNTIME_GCRUNTIME_H
#include "core/common.h"
#include "core/options.h"
#include "core/types.h"
namespace pyston {
class Box;
void gc_teardown();
extern "C" void* rt_alloc(size_t size);
extern "C" void* rt_realloc(void* ptr, size_t new_size);
extern "C" void rt_free(void* ptr);
}
#endif
...@@ -26,7 +26,6 @@ ...@@ -26,7 +26,6 @@
#include "core/stats.h" #include "core/stats.h"
#include "core/types.h" #include "core/types.h"
#include "gc/collector.h" #include "gc/collector.h"
#include "runtime/gc_runtime.h"
#include "runtime/objmodel.h" #include "runtime/objmodel.h"
#include "runtime/types.h" #include "runtime/types.h"
#include "runtime/util.h" #include "runtime/util.h"
...@@ -128,8 +127,8 @@ extern "C" BoxedGenerator* createGenerator(BoxedFunction* function, Box* arg1, B ...@@ -128,8 +127,8 @@ extern "C" BoxedGenerator* createGenerator(BoxedFunction* function, Box* arg1, B
extern "C" BoxedGenerator::BoxedGenerator(BoxedFunction* function, Box* arg1, Box* arg2, Box* arg3, Box** args) extern "C" BoxedGenerator::BoxedGenerator(BoxedFunction* function, Box* arg1, Box* arg2, Box* arg3, Box** args)
: Box(&generator_flavor, generator_cls), function(function), arg1(arg1), arg2(arg2), arg3(arg3), args(nullptr), : Box(generator_cls), function(function), arg1(arg1), arg2(arg2), arg3(arg3), args(nullptr), entryExited(false),
entryExited(false), returnValue(nullptr), exception(nullptr) { returnValue(nullptr), exception(nullptr) {
giveAttr("__name__", boxString(function->f->source->getName())); giveAttr("__name__", boxString(function->f->source->getName()));
...@@ -147,9 +146,37 @@ extern "C" BoxedGenerator::BoxedGenerator(BoxedFunction* function, Box* arg1, Bo ...@@ -147,9 +146,37 @@ extern "C" BoxedGenerator::BoxedGenerator(BoxedFunction* function, Box* arg1, Bo
makecontext(&context, (void (*)(void))generatorEntry, 1, this); makecontext(&context, (void (*)(void))generatorEntry, 1, this);
} }
extern "C" void generatorGCHandler(GCVisitor* v, Box* b) {
boxGCHandler(v, b);
BoxedGenerator* g = (BoxedGenerator*)b;
v->visit(g->function);
int num_args = g->function->f->num_args;
if (num_args >= 1)
v->visit(g->arg1);
if (num_args >= 2)
v->visit(g->arg2);
if (num_args >= 3)
v->visit(g->arg3);
if (num_args > 3)
v->visitPotentialRange(reinterpret_cast<void* const*>(&g->args->elts[0]),
reinterpret_cast<void* const*>(&g->args->elts[num_args - 3]));
if (g->returnValue)
v->visit(g->returnValue);
if (g->exception)
v->visit(g->exception);
v->visitPotentialRange((void**)&g->context, ((void**)&g->context) + sizeof(g->context) / sizeof(void*));
v->visitPotentialRange((void**)&g->returnContext,
((void**)&g->returnContext) + sizeof(g->returnContext) / sizeof(void*));
v->visitPotentialRange((void**)&g->stack[0], (void**)&g->stack[BoxedGenerator::STACK_SIZE]);
}
void setupGenerator() { void setupGenerator() {
generator_cls = new BoxedClass(object_cls, offsetof(BoxedGenerator, attrs), sizeof(BoxedGenerator), false); generator_cls = new BoxedClass(object_cls, &generatorGCHandler, offsetof(BoxedGenerator, attrs),
sizeof(BoxedGenerator), false);
generator_cls->giveAttr("__name__", boxStrConstant("generator")); generator_cls->giveAttr("__name__", boxStrConstant("generator"));
generator_cls->giveAttr("__iter__", generator_cls->giveAttr("__iter__",
new BoxedFunction(boxRTFunction((void*)generatorIter, typeFromClass(generator_cls), 1))); new BoxedFunction(boxRTFunction((void*)generatorIter, typeFromClass(generator_cls), 1)));
......
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
namespace pyston { namespace pyston {
extern BoxedClass* generator_cls; extern BoxedClass* generator_cls;
extern "C" const ObjectFlavor generator_flavor;
void setupGenerator(); void setupGenerator();
......
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
#include "runtime/inline/boxing.h" #include "runtime/inline/boxing.h"
#include "runtime/gc_runtime.h"
#include "runtime/int.h" #include "runtime/int.h"
#include "runtime/objmodel.h" #include "runtime/objmodel.h"
#include "runtime/types.h" #include "runtime/types.h"
......
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
#ifndef PYSTON_RUNTIME_INLINE_BOXING_H #ifndef PYSTON_RUNTIME_INLINE_BOXING_H
#define PYSTON_RUNTIME_INLINE_BOXING_H #define PYSTON_RUNTIME_INLINE_BOXING_H
#include "runtime/gc_runtime.h"
#include "runtime/int.h" #include "runtime/int.h"
#include "runtime/objmodel.h" #include "runtime/objmodel.h"
#include "runtime/types.h" #include "runtime/types.h"
......
...@@ -15,12 +15,11 @@ ...@@ -15,12 +15,11 @@
#include <cstring> #include <cstring>
#include "runtime/dict.h" #include "runtime/dict.h"
#include "runtime/gc_runtime.h"
namespace pyston { namespace pyston {
BoxedDictIterator::BoxedDictIterator(BoxedDict* d, IteratorType type) BoxedDictIterator::BoxedDictIterator(BoxedDict* d, IteratorType type)
: Box(&dict_iterator_flavor, dict_iterator_cls), d(d), it(d->d.begin()), itEnd(d->d.end()), type(type) { : Box(dict_iterator_cls), d(d), it(d->d.begin()), itEnd(d->d.end()), type(type) {
} }
Box* dictIterKeys(Box* s) { Box* dictIterKeys(Box* s) {
......
// Copyright (c) 2014 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <cstdio>
#include <cstdlib>
#include "core/common.h"
#include "core/options.h"
#include "core/types.h"
#include "gc/gc_alloc.h"
#include "runtime/gc_runtime.h"
#include "runtime/objmodel.h"
#include "runtime/types.h"
#define USE_CUSTOM_ALLOC
namespace pyston {
//#define DEBUG_GC
#ifdef DEBUG_GC
typedef std::unordered_set<void*> AliveSet;
static AliveSet* getAlive() {
static AliveSet* alive = new AliveSet();
return alive;
}
#endif
void* rt_alloc(size_t size) {
#ifdef USE_CUSTOM_ALLOC
void* ptr = gc::gc_alloc(size);
#else
void* ptr = malloc(size);
#endif
#ifndef NDEBUG
// nallocs++;
#endif
#ifdef DEBUG_GC
getAlive()->insert(ptr);
#endif
return ptr;
}
void* rt_realloc(void* ptr, size_t new_size) {
#ifdef USE_CUSTOM_ALLOC
void* rtn = gc::gc_realloc(ptr, new_size);
#else
void* rtn = realloc(ptr, new_size);
#endif
#ifdef DEBUG_GC
getAlive()->erase(ptr);
getAlive()->insert(rtn);
#endif
return rtn;
}
void rt_free(void* ptr) {
#ifndef NDEBUG
// nallocs--;
#endif
#ifdef DEBUG_GC
getAlive()->erase(ptr);
#endif
#ifdef USE_CUSTOM_ALLOC
gc::gc_free(ptr);
#else
free(ptr);
#endif
// assert(nallocs >= 0);
}
void gc_teardown() {
/*
if (nallocs != 0) {
printf("Error: %d alloc's not freed\n", nallocs);
#ifdef DEBUG_GC
AliveSet *alive = getAlive();
assert(nallocs == alive->size());
for (void* p : alive) {
printf("%p\n", p);
}
#endif
// This will scan through the heap and alert us about things that
// aren't marked (which should be all alive objects):
gc::global_heap.freeUnmarked();
abort();
}
*/
}
}
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
#include "core/types.h" #include "core/types.h"
#include "gc/heap.h" #include "gc/heap.h"
#include "runtime/float.h" #include "runtime/float.h"
#include "runtime/gc_runtime.h"
#include "runtime/generator.h" #include "runtime/generator.h"
#include "runtime/inline/boxing.h" #include "runtime/inline/boxing.h"
#include "runtime/int.h" #include "runtime/int.h"
......
...@@ -15,13 +15,12 @@ ...@@ -15,13 +15,12 @@
#include <cstring> #include <cstring>
#include "runtime/gc_runtime.h"
#include "runtime/list.h" #include "runtime/list.h"
#include "runtime/objmodel.h" #include "runtime/objmodel.h"
namespace pyston { namespace pyston {
BoxedListIterator::BoxedListIterator(BoxedList* l) : Box(&list_iterator_flavor, list_iterator_cls), l(l), pos(0) { BoxedListIterator::BoxedListIterator(BoxedList* l) : Box(list_iterator_cls), l(l), pos(0) {
} }
...@@ -72,7 +71,7 @@ void BoxedList::shrink() { ...@@ -72,7 +71,7 @@ void BoxedList::shrink() {
elts = GCdArray::realloc(elts, new_capacity); elts = GCdArray::realloc(elts, new_capacity);
capacity = new_capacity; capacity = new_capacity;
} else if (size == 0) { } else if (size == 0) {
rt_free(elts); delete elts;
capacity = 0; capacity = 0;
} }
} }
......
...@@ -14,13 +14,12 @@ ...@@ -14,13 +14,12 @@
#include <cstring> #include <cstring>
#include "runtime/gc_runtime.h"
#include "runtime/objmodel.h" #include "runtime/objmodel.h"
#include "runtime/tuple.h" #include "runtime/tuple.h"
namespace pyston { namespace pyston {
BoxedTupleIterator::BoxedTupleIterator(BoxedTuple* t) : Box(&tuple_iterator_flavor, tuple_iterator_cls), t(t), pos(0) { BoxedTupleIterator::BoxedTupleIterator(BoxedTuple* t) : Box(tuple_iterator_cls), t(t), pos(0) {
} }
Box* tupleIterIter(Box* s) { Box* tupleIterIter(Box* s) {
......
...@@ -14,15 +14,11 @@ ...@@ -14,15 +14,11 @@
#include "codegen/compvars.h" #include "codegen/compvars.h"
#include "core/types.h" #include "core/types.h"
#include "runtime/gc_runtime.h"
#include "runtime/objmodel.h" #include "runtime/objmodel.h"
#include "runtime/types.h" #include "runtime/types.h"
namespace pyston { namespace pyston {
extern "C" const ObjectFlavor xrange_flavor(&boxGCHandler, NULL);
extern "C" const ObjectFlavor xrange_iterator_flavor;
BoxedClass* xrange_cls, *xrange_iterator_cls; BoxedClass* xrange_cls, *xrange_iterator_cls;
class BoxedXrangeIterator; class BoxedXrangeIterator;
...@@ -31,8 +27,7 @@ private: ...@@ -31,8 +27,7 @@ private:
const int64_t start, stop, step; const int64_t start, stop, step;
public: public:
BoxedXrange(i64 start, i64 stop, i64 step) BoxedXrange(i64 start, i64 stop, i64 step) : Box(xrange_cls), start(start), stop(stop), step(step) {}
: Box(&xrange_flavor, xrange_cls), start(start), stop(stop), step(step) {}
friend class BoxedXrangeIterator; friend class BoxedXrangeIterator;
}; };
...@@ -43,8 +38,7 @@ private: ...@@ -43,8 +38,7 @@ private:
int64_t cur; int64_t cur;
public: public:
BoxedXrangeIterator(BoxedXrange* xrange) BoxedXrangeIterator(BoxedXrange* xrange) : Box(xrange_iterator_cls), xrange(xrange), cur(xrange->start) {}
: Box(&xrange_iterator_flavor, xrange_iterator_cls), xrange(xrange), cur(xrange->start) {}
static bool xrangeIteratorHasnextUnboxed(Box* s) __attribute__((visibility("default"))) { static bool xrangeIteratorHasnextUnboxed(Box* s) __attribute__((visibility("default"))) {
assert(s->cls == xrange_iterator_cls); assert(s->cls == xrange_iterator_cls);
...@@ -70,14 +64,13 @@ public: ...@@ -70,14 +64,13 @@ public:
return boxInt(xrangeIteratorNextUnboxed(s)); return boxInt(xrangeIteratorNextUnboxed(s));
} }
static void xrangeIteratorGCHandler(GCVisitor* v, void* p) { static void xrangeIteratorGCHandler(GCVisitor* v, Box* b) {
boxGCHandler(v, p); boxGCHandler(v, b);
BoxedXrangeIterator* it = (BoxedXrangeIterator*)p; BoxedXrangeIterator* it = (BoxedXrangeIterator*)b;
v->visit(it->xrange); v->visit(it->xrange);
} }
}; };
extern "C" const ObjectFlavor xrange_iterator_flavor(&BoxedXrangeIterator::xrangeIteratorGCHandler, NULL);
Box* xrange(Box* cls, Box* start, Box* stop, Box** args) { Box* xrange(Box* cls, Box* start, Box* stop, Box** args) {
assert(cls == xrange_cls); assert(cls == xrange_cls);
...@@ -117,9 +110,10 @@ Box* xrangeIter(Box* self) { ...@@ -117,9 +110,10 @@ Box* xrangeIter(Box* self) {
} }
void setupXrange() { void setupXrange() {
xrange_cls = new BoxedClass(object_cls, 0, sizeof(BoxedXrange), false); xrange_cls = new BoxedClass(object_cls, NULL, 0, sizeof(BoxedXrange), false);
xrange_cls->giveAttr("__name__", boxStrConstant("xrange")); xrange_cls->giveAttr("__name__", boxStrConstant("xrange"));
xrange_iterator_cls = new BoxedClass(object_cls, 0, sizeof(BoxedXrangeIterator), false); xrange_iterator_cls = new BoxedClass(object_cls, &BoxedXrangeIterator::xrangeIteratorGCHandler, 0,
sizeof(BoxedXrangeIterator), false);
xrange_iterator_cls->giveAttr("__name__", boxStrConstant("rangeiterator")); xrange_iterator_cls->giveAttr("__name__", boxStrConstant("rangeiterator"));
xrange_cls->giveAttr( xrange_cls->giveAttr(
......
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
#include "core/stats.h" #include "core/stats.h"
#include "core/types.h" #include "core/types.h"
#include "gc/collector.h" #include "gc/collector.h"
#include "runtime/gc_runtime.h"
#include "runtime/inline/boxing.h" #include "runtime/inline/boxing.h"
#include "runtime/long.h" #include "runtime/long.h"
#include "runtime/objmodel.h" #include "runtime/objmodel.h"
...@@ -590,7 +589,7 @@ extern "C" Box* intNew(Box* _cls, Box* val) { ...@@ -590,7 +589,7 @@ extern "C" Box* intNew(Box* _cls, Box* val) {
getNameOfClass(cls)->c_str()); getNameOfClass(cls)->c_str());
assert(cls->instance_size >= sizeof(BoxedInt)); assert(cls->instance_size >= sizeof(BoxedInt));
void* mem = rt_alloc(cls->instance_size); void* mem = gc_alloc(cls->instance_size, gc::GCKind::PYTHON);
BoxedInt* rtn = ::new (mem) BoxedInt(cls, 0); BoxedInt* rtn = ::new (mem) BoxedInt(cls, 0);
initUserAttrs(rtn, cls); initUserAttrs(rtn, cls);
......
...@@ -24,7 +24,6 @@ ...@@ -24,7 +24,6 @@
#include "core/stats.h" #include "core/stats.h"
#include "core/types.h" #include "core/types.h"
#include "gc/collector.h" #include "gc/collector.h"
#include "runtime/gc_runtime.h"
#include "runtime/objmodel.h" #include "runtime/objmodel.h"
#include "runtime/types.h" #include "runtime/types.h"
#include "runtime/util.h" #include "runtime/util.h"
...@@ -448,14 +447,12 @@ Box* listReverse(BoxedList* self) { ...@@ -448,14 +447,12 @@ Box* listReverse(BoxedList* self) {
} }
BoxedClass* list_iterator_cls = NULL; BoxedClass* list_iterator_cls = NULL;
extern "C" void listIteratorGCHandler(GCVisitor* v, void* p) { extern "C" void listIteratorGCHandler(GCVisitor* v, Box* b) {
boxGCHandler(v, p); boxGCHandler(v, b);
BoxedListIterator* it = (BoxedListIterator*)p; BoxedListIterator* it = (BoxedListIterator*)b;
v->visit(it->l); v->visit(it->l);
} }
extern "C" const ObjectFlavor list_iterator_flavor(&listIteratorGCHandler, NULL);
extern "C" Box* listNew(Box* cls, Box* container) { extern "C" Box* listNew(Box* cls, Box* container) {
assert(cls == list_cls); assert(cls == list_cls);
...@@ -521,7 +518,7 @@ Box* listEq(BoxedList* self, Box* rhs) { ...@@ -521,7 +518,7 @@ Box* listEq(BoxedList* self, Box* rhs) {
} }
void setupList() { void setupList() {
list_iterator_cls = new BoxedClass(object_cls, 0, sizeof(BoxedList), false); list_iterator_cls = new BoxedClass(object_cls, &listIteratorGCHandler, 0, sizeof(BoxedList), false);
list_cls->giveAttr("__name__", boxStrConstant("list")); list_cls->giveAttr("__name__", boxStrConstant("list"));
......
...@@ -28,7 +28,6 @@ public: ...@@ -28,7 +28,6 @@ public:
BoxedListIterator(BoxedList* l); BoxedListIterator(BoxedList* l);
}; };
extern "C" const ObjectFlavor list_iterator_flavor;
Box* listIter(Box* self); Box* listIter(Box* self);
Box* listIterIter(Box* self); Box* listIterIter(Box* self);
Box* listiterHasnext(Box* self); Box* listiterHasnext(Box* self);
......
...@@ -24,7 +24,6 @@ ...@@ -24,7 +24,6 @@
#include "core/stats.h" #include "core/stats.h"
#include "core/types.h" #include "core/types.h"
#include "gc/collector.h" #include "gc/collector.h"
#include "runtime/gc_runtime.h"
#include "runtime/inline/boxing.h" #include "runtime/inline/boxing.h"
#include "runtime/objmodel.h" #include "runtime/objmodel.h"
#include "runtime/types.h" #include "runtime/types.h"
...@@ -33,7 +32,6 @@ ...@@ -33,7 +32,6 @@
namespace pyston { namespace pyston {
BoxedClass* long_cls; BoxedClass* long_cls;
const ObjectFlavor long_flavor(&boxGCHandler, NULL);
extern "C" Box* createLong(const std::string* s) { extern "C" Box* createLong(const std::string* s) {
BoxedLong* rtn = new BoxedLong(long_cls); BoxedLong* rtn = new BoxedLong(long_cls);
...@@ -58,7 +56,7 @@ extern "C" Box* longNew(Box* _cls, Box* val) { ...@@ -58,7 +56,7 @@ extern "C" Box* longNew(Box* _cls, Box* val) {
getNameOfClass(cls)->c_str()); getNameOfClass(cls)->c_str());
assert(cls->instance_size >= sizeof(BoxedInt)); assert(cls->instance_size >= sizeof(BoxedInt));
void* mem = rt_alloc(cls->instance_size); void* mem = gc_alloc(cls->instance_size, gc::GCKind::PYTHON);
BoxedLong* rtn = ::new (mem) BoxedLong(cls); BoxedLong* rtn = ::new (mem) BoxedLong(cls);
initUserAttrs(rtn, cls); initUserAttrs(rtn, cls);
......
...@@ -25,13 +25,12 @@ namespace pyston { ...@@ -25,13 +25,12 @@ namespace pyston {
void setupLong(); void setupLong();
extern BoxedClass* long_cls; extern BoxedClass* long_cls;
extern const ObjectFlavor long_flavor;
class BoxedLong : public Box { class BoxedLong : public Box {
public: public:
mpz_t n; mpz_t n;
BoxedLong(BoxedClass* cls) __attribute__((visibility("default"))) : Box(&long_flavor, cls) {} BoxedLong(BoxedClass* cls) __attribute__((visibility("default"))) : Box(cls) {}
}; };
extern "C" Box* createLong(const std::string* s); extern "C" Box* createLong(const std::string* s);
......
...@@ -39,7 +39,6 @@ ...@@ -39,7 +39,6 @@
#include "gc/heap.h" #include "gc/heap.h"
#include "runtime/capi.h" #include "runtime/capi.h"
#include "runtime/float.h" #include "runtime/float.h"
#include "runtime/gc_runtime.h"
#include "runtime/generator.h" #include "runtime/generator.h"
#include "runtime/types.h" #include "runtime/types.h"
#include "runtime/util.h" #include "runtime/util.h"
...@@ -360,10 +359,17 @@ extern "C" void checkUnpackingLength(i64 expected, i64 given) { ...@@ -360,10 +359,17 @@ extern "C" void checkUnpackingLength(i64 expected, i64 given) {
} }
} }
BoxedClass::BoxedClass(BoxedClass* base, int attrs_offset, int instance_size, bool is_user_defined) BoxedClass::BoxedClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset, int instance_size,
: Box(&type_flavor, type_cls), base(base), attrs_offset(attrs_offset), instance_size(instance_size), bool is_user_defined)
: Box(type_cls), base(base), gc_visit(gc_visit), attrs_offset(attrs_offset), instance_size(instance_size),
is_constant(false), is_user_defined(is_user_defined) { is_constant(false), is_user_defined(is_user_defined) {
if (gc_visit == NULL) {
assert(base);
this->gc_visit = base->gc_visit;
}
assert(this->gc_visit);
if (!base) { if (!base) {
assert(object_cls == nullptr); assert(object_cls == nullptr);
// we're constructing 'object' // we're constructing 'object'
...@@ -432,19 +438,14 @@ HiddenClass* HiddenClass::delAttrToMakeHC(const std::string& attr) { ...@@ -432,19 +438,14 @@ HiddenClass* HiddenClass::delAttrToMakeHC(const std::string& attr) {
// TODO we can first locate the parent HiddenClass of the deleted // TODO we can first locate the parent HiddenClass of the deleted
// attribute and hence avoid creation of its ancestors. // attribute and hence avoid creation of its ancestors.
HiddenClass* cur = getRoot(); HiddenClass* cur = root_hcls;
for (const auto& attr : new_attrs) { for (const auto& attr : new_attrs) {
cur = cur->getOrMakeChild(attr); cur = cur->getOrMakeChild(attr);
} }
return cur; return cur;
} }
HiddenClass* HiddenClass::getRoot() { Box::Box(BoxedClass* cls) : cls(cls) {
static HiddenClass* root = new HiddenClass();
return root;
}
Box::Box(const ObjectFlavor* flavor, BoxedClass* cls) : GCObject(flavor), cls(cls) {
// if (TRACK_ALLOCATIONS) { // if (TRACK_ALLOCATIONS) {
// int id = Stats::getStatId("allocated_" + *getNameOfClass(c)); // int id = Stats::getStatId("allocated_" + *getNameOfClass(c));
// Stats::log(id); // Stats::log(id);
...@@ -613,22 +614,22 @@ void Box::setattr(const std::string& attr, Box* val, SetattrRewriteArgs* rewrite ...@@ -613,22 +614,22 @@ void Box::setattr(const std::string& attr, Box* val, SetattrRewriteArgs* rewrite
RewriterVarUsage r_new_array2(RewriterVarUsage::empty()); RewriterVarUsage r_new_array2(RewriterVarUsage::empty());
int new_size = sizeof(HCAttrs::AttrList) + sizeof(Box*) * (numattrs + 1); int new_size = sizeof(HCAttrs::AttrList) + sizeof(Box*) * (numattrs + 1);
if (numattrs == 0) { if (numattrs == 0) {
attrs->attr_list = (HCAttrs::AttrList*)rt_alloc(new_size); attrs->attr_list = (HCAttrs::AttrList*)gc_alloc(new_size, gc::GCKind::UNTRACKED);
attrs->attr_list->gc_header.kind_id = untracked_kind.kind_id;
if (rewrite_args) { if (rewrite_args) {
RewriterVarUsage r_newsize = rewrite_args->rewriter->loadConst(new_size, Location::forArg(0)); RewriterVarUsage r_newsize = rewrite_args->rewriter->loadConst(new_size, Location::forArg(0));
r_new_array2 = rewrite_args->rewriter->call(false, (void*)rt_alloc, std::move(r_newsize)); RewriterVarUsage r_kind
RewriterVarUsage r_flavor = rewrite_args->rewriter->loadConst((int64_t)untracked_kind.kind_id); = rewrite_args->rewriter->loadConst((int)gc::GCKind::UNTRACKED, Location::forArg(1));
r_new_array2.setAttr(ATTRLIST_KIND_OFFSET, std::move(r_flavor)); r_new_array2
= rewrite_args->rewriter->call(false, (void*)gc::gc_alloc, std::move(r_newsize), std::move(r_kind));
} }
} else { } else {
attrs->attr_list = (HCAttrs::AttrList*)rt_realloc(attrs->attr_list, new_size); attrs->attr_list = (HCAttrs::AttrList*)gc::gc_realloc(attrs->attr_list, new_size);
if (rewrite_args) { if (rewrite_args) {
RewriterVarUsage r_oldarray = rewrite_args->obj.getAttr(cls->attrs_offset + HCATTRS_ATTRS_OFFSET, RewriterVarUsage r_oldarray = rewrite_args->obj.getAttr(cls->attrs_offset + HCATTRS_ATTRS_OFFSET,
RewriterVarUsage::NoKill, Location::forArg(0)); RewriterVarUsage::NoKill, Location::forArg(0));
RewriterVarUsage r_newsize = rewrite_args->rewriter->loadConst(new_size, Location::forArg(1)); RewriterVarUsage r_newsize = rewrite_args->rewriter->loadConst(new_size, Location::forArg(1));
r_new_array2 r_new_array2 = rewrite_args->rewriter->call(false, (void*)gc::gc_realloc, std::move(r_oldarray),
= rewrite_args->rewriter->call(false, (void*)rt_realloc, std::move(r_oldarray), std::move(r_newsize)); std::move(r_newsize));
} }
} }
// Don't set the new hcls until after we do the allocation for the new attr_list; // Don't set the new hcls until after we do the allocation for the new attr_list;
...@@ -1273,28 +1274,28 @@ extern "C" void dump(void* p) { ...@@ -1273,28 +1274,28 @@ extern "C" void dump(void* p) {
return; return;
} }
GCObjectHeader* header = gc::headerFromObject(p); gc::GCAllocation* al = gc::GCAllocation::fromUserData(p);
if (header->kind_id == hc_kind.kind_id) { if (al->kind_id == gc::GCKind::UNTRACKED) {
printf("hcls object\n"); printf("gc-untracked object\n");
return; return;
} }
if (header->kind_id == untracked_kind.kind_id) { if (al->kind_id == gc::GCKind::CONSERVATIVE) {
printf("untracked object\n"); printf("conservatively-scanned object object\n");
return; return;
} }
if (header->kind_id == conservative_kind.kind_id) { if (al->kind_id == gc::GCKind::PYTHON) {
printf("untracked object\n"); printf("Python object\n");
Box* b = (Box*)p;
printf("Class: %s\n", getTypeName(b)->c_str());
if (isSubclass(b->cls, type_cls)) {
printf("Type name: %s\n", getNameOfClass(static_cast<BoxedClass*>(b))->c_str());
}
return; return;
} }
printf("Assuming it's a Box*\n"); RELEASE_ASSERT(0, "%d", (int)al->kind_id);
Box* b = (Box*)p;
printf("Class: %s\n", getTypeName(b)->c_str());
if (isSubclass(b->cls, type_cls)) {
printf("Type name: %s\n", getNameOfClass(static_cast<BoxedClass*>(b))->c_str());
}
} }
// For rewriting purposes, this function assumes that nargs will be constant. // For rewriting purposes, this function assumes that nargs will be constant.
...@@ -2745,7 +2746,7 @@ void Box::delattr(const std::string& attr, DelattrRewriteArgs* rewrite_args) { ...@@ -2745,7 +2746,7 @@ void Box::delattr(const std::string& attr, DelattrRewriteArgs* rewrite_args) {
// guarantee the size of the attr_list equals the number of attrs // guarantee the size of the attr_list equals the number of attrs
int new_size = sizeof(HCAttrs::AttrList) + sizeof(Box*) * (num_attrs - 1); int new_size = sizeof(HCAttrs::AttrList) + sizeof(Box*) * (num_attrs - 1);
attrs->attr_list = (HCAttrs::AttrList*)rt_realloc(attrs->attr_list, new_size); attrs->attr_list = (HCAttrs::AttrList*)gc::gc_realloc(attrs->attr_list, new_size);
} }
extern "C" void delattr_internal(Box* obj, const std::string& attr, bool allow_custom, extern "C" void delattr_internal(Box* obj, const std::string& attr, bool allow_custom,
......
...@@ -37,7 +37,6 @@ void raiseExc(Box* exc_obj) __attribute__((__noreturn__)); ...@@ -37,7 +37,6 @@ void raiseExc(Box* exc_obj) __attribute__((__noreturn__));
// helper function for raising from the runtime: // helper function for raising from the runtime:
void raiseExcHelper(BoxedClass*, const char* fmt, ...) __attribute__((__noreturn__)); void raiseExcHelper(BoxedClass*, const char* fmt, ...) __attribute__((__noreturn__));
extern "C" const std::string* getTypeName(Box* o);
extern "C" const std::string* getNameOfClass(BoxedClass* cls); extern "C" const std::string* getNameOfClass(BoxedClass* cls);
// TODO sort this // TODO sort this
......
...@@ -25,12 +25,6 @@ namespace pyston { ...@@ -25,12 +25,6 @@ namespace pyston {
BoxedClass* set_cls, *set_iterator_cls; BoxedClass* set_cls, *set_iterator_cls;
BoxedClass* frozenset_cls; BoxedClass* frozenset_cls;
extern "C" void setGCHandler(GCVisitor* v, void* p);
extern "C" void setIteratorGCHandler(GCVisitor* v, void* p);
const ObjectFlavor set_flavor(&setGCHandler, NULL);
const ObjectFlavor set_iterator_flavor(&setIteratorGCHandler, NULL);
extern "C" Box* createSet() { extern "C" Box* createSet() {
return new BoxedSet(set_cls); return new BoxedSet(set_cls);
} }
...@@ -42,7 +36,7 @@ public: ...@@ -42,7 +36,7 @@ public:
BoxedSet* s; BoxedSet* s;
decltype(BoxedSet::s)::iterator it; decltype(BoxedSet::s)::iterator it;
BoxedSetIterator(BoxedSet* s) : Box(&set_iterator_flavor, set_iterator_cls), s(s), it(s->s.begin()) {} BoxedSetIterator(BoxedSet* s) : Box(set_iterator_cls), s(s), it(s->s.begin()) {}
bool hasNext() { return it != s->s.end(); } bool hasNext() { return it != s->s.end(); }
...@@ -53,25 +47,10 @@ public: ...@@ -53,25 +47,10 @@ public:
} }
}; };
extern "C" void setGCHandler(GCVisitor* v, void* p) { extern "C" void setIteratorGCHandler(GCVisitor* v, Box* b) {
boxGCHandler(v, p); boxGCHandler(v, b);
BoxedSet* s = (BoxedSet*)p;
// This feels like a cludge, but we need to find anything that
// the unordered_map might have allocated.
// Another way to handle this would be to rt_alloc the unordered_map
// as well, though that incurs extra memory dereferences which would
// be nice to avoid.
void** start = (void**)&s->s;
void** end = start + (sizeof(s->s) / 8);
v->visitPotentialRange(start, end);
}
extern "C" void setIteratorGCHandler(GCVisitor* v, void* p) {
boxGCHandler(v, p);
BoxedSetIterator* it = (BoxedSetIterator*)p; BoxedSetIterator* it = (BoxedSetIterator*)b;
v->visit(it->s); v->visit(it->s);
} }
...@@ -228,7 +207,7 @@ void setupSet() { ...@@ -228,7 +207,7 @@ void setupSet() {
set_cls->giveAttr("__name__", boxStrConstant("set")); set_cls->giveAttr("__name__", boxStrConstant("set"));
frozenset_cls->giveAttr("__name__", boxStrConstant("frozenset")); frozenset_cls->giveAttr("__name__", boxStrConstant("frozenset"));
set_iterator_cls = new BoxedClass(object_cls, 0, sizeof(BoxedSet), false); set_iterator_cls = new BoxedClass(object_cls, &setIteratorGCHandler, 0, sizeof(BoxedSet), false);
set_iterator_cls->giveAttr("__name__", boxStrConstant("setiterator")); set_iterator_cls->giveAttr("__name__", boxStrConstant("setiterator"));
set_iterator_cls->giveAttr("__hasnext__", set_iterator_cls->giveAttr("__hasnext__",
new BoxedFunction(boxRTFunction((void*)setiteratorHasnext, BOXED_BOOL, 1))); new BoxedFunction(boxRTFunction((void*)setiteratorHasnext, BOXED_BOOL, 1)));
......
...@@ -26,7 +26,6 @@ void setupSet(); ...@@ -26,7 +26,6 @@ void setupSet();
void teardownSet(); void teardownSet();
extern BoxedClass* set_cls, *frozenset_cls; extern BoxedClass* set_cls, *frozenset_cls;
extern const ObjectFlavor set_flavor, frozenset_flavor;
extern "C" Box* createSet(); extern "C" Box* createSet();
...@@ -34,7 +33,7 @@ class BoxedSet : public Box { ...@@ -34,7 +33,7 @@ class BoxedSet : public Box {
public: public:
std::unordered_set<Box*, PyHasher, PyEq, StlCompatAllocator<Box*> > s; std::unordered_set<Box*, PyHasher, PyEq, StlCompatAllocator<Box*> > s;
BoxedSet(BoxedClass* cls) __attribute__((visibility("default"))) : Box(&set_flavor, cls) {} BoxedSet(BoxedClass* cls) __attribute__((visibility("default"))) : Box(cls) {}
}; };
} }
......
...@@ -24,7 +24,6 @@ ...@@ -24,7 +24,6 @@
#include "core/common.h" #include "core/common.h"
#include "core/types.h" #include "core/types.h"
#include "gc/collector.h" #include "gc/collector.h"
#include "runtime/gc_runtime.h"
#include "runtime/objmodel.h" #include "runtime/objmodel.h"
#include "runtime/types.h" #include "runtime/types.h"
#include "runtime/util.h" #include "runtime/util.h"
...@@ -579,16 +578,13 @@ extern "C" Box* strGetitem(BoxedString* self, Box* slice) { ...@@ -579,16 +578,13 @@ extern "C" Box* strGetitem(BoxedString* self, Box* slice) {
// Should probably implement that, and maybe once that's implemented get // Should probably implement that, and maybe once that's implemented get
// rid of the striterator class? // rid of the striterator class?
BoxedClass* str_iterator_cls = NULL; BoxedClass* str_iterator_cls = NULL;
extern "C" void strIteratorGCHandler(GCVisitor* v, void* p);
extern "C" const ObjectFlavor str_iterator_flavor(&strIteratorGCHandler, NULL);
class BoxedStringIterator : public Box { class BoxedStringIterator : public Box {
public: public:
BoxedString* s; BoxedString* s;
std::string::const_iterator it, end; std::string::const_iterator it, end;
BoxedStringIterator(BoxedString* s) BoxedStringIterator(BoxedString* s) : Box(str_iterator_cls), s(s), it(s->s.begin()), end(s->s.end()) {}
: Box(&str_iterator_flavor, str_iterator_cls), s(s), it(s->s.begin()), end(s->s.end()) {}
static bool hasnextUnboxed(BoxedStringIterator* self) { static bool hasnextUnboxed(BoxedStringIterator* self) {
assert(self->cls == str_iterator_cls); assert(self->cls == str_iterator_cls);
...@@ -610,9 +606,9 @@ public: ...@@ -610,9 +606,9 @@ public:
} }
}; };
extern "C" void strIteratorGCHandler(GCVisitor* v, void* p) { extern "C" void strIteratorGCHandler(GCVisitor* v, Box* b) {
boxGCHandler(v, p); boxGCHandler(v, b);
BoxedStringIterator* it = (BoxedStringIterator*)p; BoxedStringIterator* it = (BoxedStringIterator*)b;
v->visit(it->s); v->visit(it->s);
} }
...@@ -648,7 +644,7 @@ Box* strCount2(BoxedString* self, Box* elt) { ...@@ -648,7 +644,7 @@ Box* strCount2(BoxedString* self, Box* elt) {
} }
void setupStr() { void setupStr() {
str_iterator_cls = new BoxedClass(object_cls, 0, sizeof(BoxedString), false); str_iterator_cls = new BoxedClass(object_cls, &strIteratorGCHandler, 0, sizeof(BoxedString), false);
gc::registerStaticRootObj(str_iterator_cls); gc::registerStaticRootObj(str_iterator_cls);
str_iterator_cls->giveAttr("__name__", boxStrConstant("striterator")); str_iterator_cls->giveAttr("__name__", boxStrConstant("striterator"));
str_iterator_cls->giveAttr("__hasnext__", str_iterator_cls->giveAttr("__hasnext__",
......
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
#include "core/stats.h" #include "core/stats.h"
#include "core/types.h" #include "core/types.h"
#include "gc/collector.h" #include "gc/collector.h"
#include "runtime/gc_runtime.h"
#include "runtime/objmodel.h" #include "runtime/objmodel.h"
#include "runtime/types.h" #include "runtime/types.h"
#include "runtime/util.h" #include "runtime/util.h"
...@@ -203,17 +202,15 @@ Box* tupleHash(BoxedTuple* self) { ...@@ -203,17 +202,15 @@ Box* tupleHash(BoxedTuple* self) {
} }
BoxedClass* tuple_iterator_cls = NULL; BoxedClass* tuple_iterator_cls = NULL;
extern "C" void tupleIteratorGCHandler(GCVisitor* v, void* p) { extern "C" void tupleIteratorGCHandler(GCVisitor* v, Box* b) {
boxGCHandler(v, p); boxGCHandler(v, b);
BoxedTupleIterator* it = (BoxedTupleIterator*)p; BoxedTupleIterator* it = (BoxedTupleIterator*)b;
v->visit(it->t); v->visit(it->t);
} }
extern "C" const ObjectFlavor tuple_iterator_flavor(&tupleIteratorGCHandler, NULL);
void setupTuple() { void setupTuple() {
tuple_iterator_cls = new BoxedClass(object_cls, 0, sizeof(BoxedTuple), false); tuple_iterator_cls = new BoxedClass(object_cls, &tupleIteratorGCHandler, 0, sizeof(BoxedTuple), false);
tuple_cls->giveAttr("__name__", boxStrConstant("tuple")); tuple_cls->giveAttr("__name__", boxStrConstant("tuple"));
......
...@@ -28,7 +28,6 @@ public: ...@@ -28,7 +28,6 @@ public:
BoxedTupleIterator(BoxedTuple* t); BoxedTupleIterator(BoxedTuple* t);
}; };
extern "C" const ObjectFlavor tuple_iterator_flavor;
Box* tupleIter(Box* self); Box* tupleIter(Box* self);
Box* tupleIterIter(Box* self); Box* tupleIterIter(Box* self);
Box* tupleiterHasnext(Box* self); Box* tupleiterHasnext(Box* self);
......
This diff is collapsed.
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "core/threading.h" #include "core/threading.h"
#include "core/types.h" #include "core/types.h"
#include "gc/gc_alloc.h"
namespace pyston { namespace pyston {
...@@ -74,11 +75,6 @@ extern BoxedClass* object_cls, *type_cls, *bool_cls, *int_cls, *float_cls, *str_ ...@@ -74,11 +75,6 @@ extern BoxedClass* object_cls, *type_cls, *bool_cls, *int_cls, *float_cls, *str_
*instancemethod_cls, *list_cls, *slice_cls, *module_cls, *dict_cls, *tuple_cls, *file_cls, *xrange_cls, *member_cls, *instancemethod_cls, *list_cls, *slice_cls, *module_cls, *dict_cls, *tuple_cls, *file_cls, *xrange_cls, *member_cls,
*closure_cls, *generator_cls; *closure_cls, *generator_cls;
} }
extern "C" {
extern const ObjectFlavor object_flavor, type_flavor, bool_flavor, int_flavor, float_flavor, str_flavor,
function_flavor, none_flavor, instancemethod_flavor, list_flavor, slice_flavor, module_flavor, dict_flavor,
tuple_flavor, file_flavor, xrange_flavor, member_flavor, closure_flavor, generator_flavor;
}
extern "C" { extern Box* None, *NotImplemented, *True, *False; } extern "C" { extern Box* None, *NotImplemented, *True, *False; }
extern "C" { extern "C" {
extern Box* repr_obj, *len_obj, *hash_obj, *range_obj, *abs_obj, *min_obj, *max_obj, *open_obj, *id_obj, *chr_obj, extern Box* repr_obj, *len_obj, *hash_obj, *range_obj, *abs_obj, *min_obj, *max_obj, *open_obj, *id_obj, *chr_obj,
...@@ -108,27 +104,6 @@ extern "C" Box* createTuple(int64_t nelts, Box** elts); ...@@ -108,27 +104,6 @@ extern "C" Box* createTuple(int64_t nelts, Box** elts);
extern "C" void printFloat(double d); extern "C" void printFloat(double d);
class ConservativeWrapper : public GCObject {
public:
void* data[0];
ConservativeWrapper(size_t data_size) : GCObject(&conservative_kind), data() {
assert(data_size % sizeof(void*) == 0);
gc_header.kind_data = data_size;
}
void* operator new(size_t size, size_t data_size) {
assert(size == sizeof(ConservativeWrapper));
return rt_alloc(data_size + size);
}
static ConservativeWrapper* fromPointer(void* p) {
ConservativeWrapper* o = (ConservativeWrapper*)((void**)p - 1);
assert(&o->data == p);
return o;
}
};
template <class T> class StlCompatAllocator { template <class T> class StlCompatAllocator {
public: public:
typedef size_t size_type; typedef size_t size_type;
...@@ -148,14 +123,10 @@ public: ...@@ -148,14 +123,10 @@ public:
size_t to_allocate = n * sizeof(value_type); size_t to_allocate = n * sizeof(value_type);
// assert(to_allocate < (1<<16)); // assert(to_allocate < (1<<16));
ConservativeWrapper* rtn = new (to_allocate) ConservativeWrapper(to_allocate); return reinterpret_cast<pointer>(gc_alloc(to_allocate, gc::GCKind::CONSERVATIVE));
return (pointer)&rtn->data[0];
} }
void deallocate(pointer p, size_t n) { void deallocate(pointer p, size_t n) { gc::gc_free(p); }
ConservativeWrapper* o = ConservativeWrapper::fromPointer(p);
rt_free(o);
}
// I would never be able to come up with this on my own: // I would never be able to come up with this on my own:
// http://en.cppreference.com/w/cpp/memory/allocator/construct // http://en.cppreference.com/w/cpp/memory/allocator/construct
...@@ -169,26 +140,59 @@ public: ...@@ -169,26 +140,59 @@ public:
bool operator!=(const StlCompatAllocator<T>& rhs) const { return false; } bool operator!=(const StlCompatAllocator<T>& rhs) const { return false; }
}; };
template <typename K, typename V, typename Hash = std::hash<K>, typename KeyEqual = std::equal_to<K> >
class conservative_unordered_map
: public std::unordered_map<K, V, Hash, KeyEqual, StlCompatAllocator<std::pair<const K, V> > > {};
class HiddenClass : public ConservativeGCObject {
private:
HiddenClass() {}
HiddenClass(const HiddenClass* parent) : attr_offsets(parent->attr_offsets) {}
public:
static HiddenClass* makeRoot() {
#ifndef NDEBUG
static bool made = false;
assert(!made);
made = true;
#endif
return new HiddenClass();
}
conservative_unordered_map<std::string, int> attr_offsets;
conservative_unordered_map<std::string, HiddenClass*> children;
HiddenClass* getOrMakeChild(const std::string& attr);
int getOffset(const std::string& attr) {
auto it = attr_offsets.find(attr);
if (it == attr_offsets.end())
return -1;
return it->second;
}
HiddenClass* delAttrToMakeHC(const std::string& attr);
};
class BoxedInt : public Box { class BoxedInt : public Box {
public: public:
int64_t n; int64_t n;
BoxedInt(BoxedClass* cls, int64_t n) __attribute__((visibility("default"))) : Box(&int_flavor, cls), n(n) {} BoxedInt(BoxedClass* cls, int64_t n) __attribute__((visibility("default"))) : Box(cls), n(n) {}
}; };
class BoxedFloat : public Box { class BoxedFloat : public Box {
public: public:
double d; double d;
BoxedFloat(double d) __attribute__((visibility("default"))) : Box(&float_flavor, float_cls), d(d) {} BoxedFloat(double d) __attribute__((visibility("default"))) : Box(float_cls), d(d) {}
}; };
class BoxedBool : public Box { class BoxedBool : public Box {
public: public:
bool b; bool b;
BoxedBool(bool b) __attribute__((visibility("default"))) : Box(&bool_flavor, bool_cls), b(b) {} BoxedBool(bool b) __attribute__((visibility("default"))) : Box(bool_cls), b(b) {}
}; };
class BoxedString : public Box { class BoxedString : public Box {
...@@ -196,9 +200,8 @@ public: ...@@ -196,9 +200,8 @@ public:
// const std::basic_string<char, std::char_traits<char>, StlCompatAllocator<char> > s; // const std::basic_string<char, std::char_traits<char>, StlCompatAllocator<char> > s;
const std::string s; const std::string s;
BoxedString(const std::string&& s) __attribute__((visibility("default"))) BoxedString(const std::string&& s) __attribute__((visibility("default"))) : Box(str_cls), s(std::move(s)) {}
: Box(&str_flavor, str_cls), s(std::move(s)) {} BoxedString(const std::string& s) __attribute__((visibility("default"))) : Box(str_cls), s(s) {}
BoxedString(const std::string& s) __attribute__((visibility("default"))) : Box(&str_flavor, str_cls), s(s) {}
}; };
class BoxedInstanceMethod : public Box { class BoxedInstanceMethod : public Box {
...@@ -206,22 +209,22 @@ public: ...@@ -206,22 +209,22 @@ public:
Box* obj, *func; Box* obj, *func;
BoxedInstanceMethod(Box* obj, Box* func) __attribute__((visibility("default"))) BoxedInstanceMethod(Box* obj, Box* func) __attribute__((visibility("default")))
: Box(&instancemethod_flavor, instancemethod_cls), obj(obj), func(func) {} : Box(instancemethod_cls), obj(obj), func(func) {}
}; };
class GCdArray : public GCObject { class GCdArray {
public: public:
Box* elts[0]; Box* elts[0];
GCdArray() : GCObject(&untracked_kind) {}
void* operator new(size_t size, int capacity) { void* operator new(size_t size, int capacity) {
assert(size == sizeof(GCdArray)); assert(size == sizeof(GCdArray));
return rt_alloc(capacity * sizeof(Box*) + size); return gc_alloc(capacity * sizeof(Box*) + size, gc::GCKind::UNTRACKED);
} }
void operator delete(void* p) { gc::gc_free(p); }
static GCdArray* realloc(GCdArray* array, int capacity) { static GCdArray* realloc(GCdArray* array, int capacity) {
return (GCdArray*)rt_realloc(array, capacity * sizeof(Box*) + sizeof(GCdArray)); return (GCdArray*)gc::gc_realloc(array, capacity * sizeof(Box*) + sizeof(GCdArray));
} }
}; };
...@@ -232,7 +235,7 @@ public: ...@@ -232,7 +235,7 @@ public:
DS_DEFINE_MUTEX(lock); DS_DEFINE_MUTEX(lock);
BoxedList() __attribute__((visibility("default"))) : Box(&list_flavor, list_cls), size(0), capacity(0) {} BoxedList() __attribute__((visibility("default"))) : Box(list_cls), size(0), capacity(0) {}
void ensure(int space); void ensure(int space);
void shrink(); void shrink();
...@@ -245,9 +248,9 @@ public: ...@@ -245,9 +248,9 @@ public:
const GCVector elts; const GCVector elts;
BoxedTuple(std::vector<Box*, StlCompatAllocator<Box*> >& elts) __attribute__((visibility("default"))) BoxedTuple(std::vector<Box*, StlCompatAllocator<Box*> >& elts) __attribute__((visibility("default")))
: Box(&tuple_flavor, tuple_cls), elts(elts) {} : Box(tuple_cls), elts(elts) {}
BoxedTuple(std::vector<Box*, StlCompatAllocator<Box*> >&& elts) __attribute__((visibility("default"))) BoxedTuple(std::vector<Box*, StlCompatAllocator<Box*> >&& elts) __attribute__((visibility("default")))
: Box(&tuple_flavor, tuple_cls), elts(std::move(elts)) {} : Box(tuple_cls), elts(std::move(elts)) {}
}; };
extern "C" BoxedTuple* EmptyTuple; extern "C" BoxedTuple* EmptyTuple;
...@@ -255,7 +258,7 @@ class BoxedFile : public Box { ...@@ -255,7 +258,7 @@ class BoxedFile : public Box {
public: public:
FILE* f; FILE* f;
bool closed; bool closed;
BoxedFile(FILE* f) __attribute__((visibility("default"))) : Box(&file_flavor, file_cls), f(f), closed(false) {} BoxedFile(FILE* f) __attribute__((visibility("default"))) : Box(file_cls), f(f), closed(false) {}
}; };
struct PyHasher { struct PyHasher {
...@@ -276,7 +279,7 @@ public: ...@@ -276,7 +279,7 @@ public:
DictMap d; DictMap d;
BoxedDict() __attribute__((visibility("default"))) : Box(&dict_flavor, dict_cls) {} BoxedDict() __attribute__((visibility("default"))) : Box(dict_cls) {}
}; };
class BoxedFunction : public Box { class BoxedFunction : public Box {
...@@ -306,8 +309,7 @@ public: ...@@ -306,8 +309,7 @@ public:
class BoxedSlice : public Box { class BoxedSlice : public Box {
public: public:
Box* start, *stop, *step; Box* start, *stop, *step;
BoxedSlice(Box* lower, Box* upper, Box* step) BoxedSlice(Box* lower, Box* upper, Box* step) : Box(slice_cls), start(lower), stop(upper), step(step) {}
: Box(&slice_flavor, slice_cls), start(lower), stop(upper), step(step) {}
}; };
class BoxedMemberDescriptor : public Box { class BoxedMemberDescriptor : public Box {
...@@ -318,7 +320,7 @@ public: ...@@ -318,7 +320,7 @@ public:
int offset; int offset;
BoxedMemberDescriptor(MemberType type, int offset) : Box(&member_flavor, member_cls), type(type), offset(offset) {} BoxedMemberDescriptor(MemberType type, int offset) : Box(member_cls), type(type), offset(offset) {}
}; };
// TODO is there any particular reason to make this a Box, ie a python-level object? // TODO is there any particular reason to make this a Box, ie a python-level object?
...@@ -327,7 +329,7 @@ public: ...@@ -327,7 +329,7 @@ public:
HCAttrs attrs; HCAttrs attrs;
BoxedClosure* parent; BoxedClosure* parent;
BoxedClosure(BoxedClosure* parent) : Box(&closure_flavor, closure_cls), parent(parent) {} BoxedClosure(BoxedClosure* parent) : Box(closure_cls), parent(parent) {}
}; };
class BoxedGenerator : public Box { class BoxedGenerator : public Box {
...@@ -349,7 +351,7 @@ public: ...@@ -349,7 +351,7 @@ public:
BoxedGenerator(BoxedFunction* function, Box* arg1, Box* arg2, Box* arg3, Box** args); BoxedGenerator(BoxedFunction* function, Box* arg1, Box* arg2, Box* arg3, Box** args);
}; };
extern "C" void boxGCHandler(GCVisitor* v, void* p); extern "C" void boxGCHandler(GCVisitor* v, Box* b);
Box* exceptionNew1(BoxedClass* cls); Box* exceptionNew1(BoxedClass* cls);
Box* exceptionNew2(BoxedClass* cls, Box* message); Box* exceptionNew2(BoxedClass* cls, Box* message);
......
...@@ -2,22 +2,22 @@ ...@@ -2,22 +2,22 @@
#include <cstdio> #include <cstdio>
#include "stdint.h" #include "stdint.h"
void set64(int64_t* ptr) { class C {
*ptr = 0x1234; public:
} C(int i) {
printf("ctor\n");
}
void* operator new(size_t bytes) {
printf("operator new\n");
return NULL;
}
};
void set64full(int64_t* ptr) { int f() {
*ptr = 0x1234567890; printf("f()");
return 1;
} }
namespace pyston { extern "C" C* c() {
class Box {}; return new C(f());
int throw_catch(Box* b) {
try {
throw b;
} catch (int e) {
return e;
}
}
} }
# expected: fail
# - the GC will crash if any thread is inside a generator during a collection
# Allocate a few-dozen megabytes of memory inside a generator,
# to try to force a collection.
def f():
l = range(1000)
for i in xrange(10000):
l = list(l)
yield 0
print list(f())
...@@ -13,10 +13,16 @@ using namespace pyston; ...@@ -13,10 +13,16 @@ using namespace pyston;
using namespace pyston::gc; using namespace pyston::gc;
struct S { struct S {
GCObjectHeader header;
int data[0]; int data[0];
}; };
TEST(alloc, basic) {
void* p1 = gc_alloc(16, GCKind::UNTRACKED);
void* p2 = gc_alloc(16, GCKind::UNTRACKED);
ASSERT_TRUE(p1 != p2);
}
void testAlloc(int B) { void testAlloc(int B) {
std::unique_ptr<int> masks(new int[B/4]); std::unique_ptr<int> masks(new int[B/4]);
masks.get()[0] = 0; masks.get()[0] = 0;
...@@ -32,8 +38,7 @@ void testAlloc(int B) { ...@@ -32,8 +38,7 @@ void testAlloc(int B) {
if (B > 1024) if (B > 1024)
N /= 10; N /= 10;
for (int i = 0; i < N; i++) { for (int i = 0; i < N; i++) {
S* t = static_cast<S*>(gc_alloc(B)); S* t = static_cast<S*>(gc_alloc(B, GCKind::UNTRACKED));
t->header.kind_id = untracked_kind.kind_id;
ASSERT_TRUE(t != NULL); ASSERT_TRUE(t != NULL);
ASSERT_EQ(0, seen.count(t)); ASSERT_EQ(0, seen.count(t));
...@@ -66,18 +71,15 @@ TEST(alloc, alloc3584) { testAlloc(3584); } ...@@ -66,18 +71,15 @@ TEST(alloc, alloc3584) { testAlloc(3584); }
TEST(alloc, largeallocs) { TEST(alloc, largeallocs) {
int s1 = 1 << 20; int s1 = 1 << 20;
S* d1 = (S*)gc_alloc(s1); S* d1 = (S*)gc_alloc(s1, GCKind::UNTRACKED);
d1->header.kind_id = untracked_kind.kind_id;
memset(d1->data, 1, s1 - sizeof(S)); memset(d1->data, 1, s1 - sizeof(S));
int s2 = 2 << 20; int s2 = 2 << 20;
S* d2 = (S*)gc_alloc(s2); S* d2 = (S*)gc_alloc(s2, GCKind::UNTRACKED);
d2->header.kind_id = untracked_kind.kind_id;
memset(d2->data, 2, s2 - sizeof(S)); memset(d2->data, 2, s2 - sizeof(S));
int s3 = 4 << 20; int s3 = 4 << 20;
S* d3 = (S*)gc_alloc(s3); S* d3 = (S*)gc_alloc(s3, GCKind::UNTRACKED);
d3->header.kind_id = untracked_kind.kind_id;
memset(d3->data, 3, s3 - sizeof(S)); memset(d3->data, 3, s3 - sizeof(S));
for (int i = sizeof(S); i < s1; i++) { for (int i = sizeof(S); i < s1; i++) {
...@@ -96,14 +98,14 @@ TEST(alloc, largeallocs) { ...@@ -96,14 +98,14 @@ TEST(alloc, largeallocs) {
TEST(alloc, freeing) { TEST(alloc, freeing) {
// Not sure this is enough to crash if it doesn't get freed: // Not sure this is enough to crash if it doesn't get freed:
for (int i = 0; i < 100000; i++) { for (int i = 0; i < 100000; i++) {
void* a = gc_alloc(1024); void* a = gc_alloc(1024, GCKind::UNTRACKED);
gc_free(a); gc_free(a);
} }
} }
TEST(alloc, freeingLarge) { TEST(alloc, freeingLarge) {
for (int i = 0; i < 200; i++) { for (int i = 0; i < 200; i++) {
void* a = gc_alloc(1<<26); void* a = gc_alloc(1<<26, GCKind::UNTRACKED);
gc_free(a); gc_free(a);
} }
} }
......
...@@ -100,6 +100,9 @@ bool makeVisible(llvm::GlobalValue* gv) { ...@@ -100,6 +100,9 @@ bool makeVisible(llvm::GlobalValue* gv) {
bool isConstant(MDNode* parent_type, int offset) { bool isConstant(MDNode* parent_type, int offset) {
MDString *s = cast<MDString>(parent_type->getOperand(0)); MDString *s = cast<MDString>(parent_type->getOperand(0));
// TODO: these were somewhat helpful, but this code is broken since
// it hard-codes the attribute offsets.
/*
if (s->getString() == "_ZTSN6pyston19BoxedXrangeIteratorE") { if (s->getString() == "_ZTSN6pyston19BoxedXrangeIteratorE") {
return (offset == 16); return (offset == 16);
} }
...@@ -115,6 +118,7 @@ bool isConstant(MDNode* parent_type, int offset) { ...@@ -115,6 +118,7 @@ bool isConstant(MDNode* parent_type, int offset) {
if (s->getString() == "_ZTSN6pyston11BoxedXrangeE") { if (s->getString() == "_ZTSN6pyston11BoxedXrangeE") {
return offset == 16 || offset == 24 || offset == 32; return offset == 16 || offset == 24 || offset == 32;
} }
*/
return false; return false;
} }
......
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