extern "C" Box* createClass(std::string *name, BoxedModule *parent_module) { BoxedClass* rtn = new BoxedClass(true, NULL); rtn->giveAttr("__name__", boxString(*name)); Box* modname = parent_module->getattr("__name__", NULL, NULL); rtn->giveAttr("__module__", modname); return rtn; }
static void markPhase() { #ifndef NVALGRIND // Have valgrind close its eyes while we do the conservative stack and data scanning, // since we'll be looking at potentially-uninitialized values: VALGRIND_DISABLE_ERROR_REPORTING; #endif TraceStack stack(roots); collectStackRoots(&stack); TraceStackGCVisitor visitor(&stack); for (auto h : *getRootHandles()) { visitor.visitPotential(h->value); } // if (VERBOSITY()) printf("Found %d roots\n", stack.size()); while (void* p = stack.pop()) { assert(((intptr_t)p) % 8 == 0); GCAllocation* al = GCAllocation::fromUserData(p); if (isMarked(al)) { continue; } // printf("Marking + scanning %p\n", p); setMark(al); GCKind kind_id = al->kind_id; if (kind_id == GCKind::UNTRACKED) { continue; } else if (kind_id == GCKind::CONSERVATIVE) { uint32_t bytes = al->kind_data; visitor.visitPotentialRange((void**)p, (void**)((char*)p + bytes)); } else if (kind_id == GCKind::PYTHON) { Box* b = reinterpret_cast<Box*>(p); BoxedClass* cls = b->cls; if (cls) { // The cls can be NULL since we use 'new' to construct them. // An arbitrary amount of stuff can happen between the 'new' and // the call to the constructor (ie the args get evaluated), which // can trigger a collection. ASSERT(cls->gc_visit, "%s", getTypeName(b)->c_str()); cls->gc_visit(&visitor, b); } } else { RELEASE_ASSERT(0, "Unhandled kind: %d", (int)kind_id); } } #ifndef NVALGRIND VALGRIND_ENABLE_ERROR_REPORTING; #endif }
extern "C" Box* createUserClass(std::string* name, Box* _base, BoxedModule* parent_module) { assert(_base); assert(isSubclass(_base->cls, type_cls)); BoxedClass* base = static_cast<BoxedClass*>(_base); BoxedClass* made; if (base->instancesHaveAttrs()) { made = new BoxedClass(base, base->attrs_offset, base->instance_size, true); } else { assert(base->instance_size % sizeof(void*) == 0); made = new BoxedClass(base, base->instance_size, base->instance_size + sizeof(HCAttrs), true); } made->giveAttr("__name__", boxString(*name)); Box* modname = parent_module->getattr("__name__", NULL, NULL); made->giveAttr("__module__", modname); return made; }
void setupThread() { // Hacky: we want to use some of CPython's implementation of the thread module (the threading local stuff), // and some of ours (thread handling). Start off by calling a cut-down version of initthread, and then // add our own attributes to the module it creates. initthread(); RELEASE_ASSERT(!PyErr_Occurred(), ""); Box* thread_module = getSysModulesDict()->getOrNull(boxString("thread")); assert(thread_module); thread_module->giveAttr("start_new_thread", new BoxedBuiltinFunctionOrMethod( boxRTFunction((void*)startNewThread, BOXED_INT, 3, 1, false, false), "start_new_thread", { NULL })); thread_module->giveAttr("allocate_lock", new BoxedBuiltinFunctionOrMethod( boxRTFunction((void*)allocateLock, UNKNOWN, 0), "allocate_lock")); thread_module->giveAttr( "get_ident", new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)getIdent, BOXED_INT, 0), "get_ident")); thread_module->giveAttr( "stack_size", new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)stackSize, BOXED_INT, 0), "stack_size")); thread_lock_cls = BoxedHeapClass::create(type_cls, object_cls, NULL, 0, 0, sizeof(BoxedThreadLock), false, "lock"); thread_lock_cls->giveAttr("__module__", boxString("thread")); thread_lock_cls->giveAttr( "acquire", new BoxedFunction(boxRTFunction((void*)BoxedThreadLock::acquire, BOXED_BOOL, 2, 1, false, false), { boxInt(1) })); thread_lock_cls->giveAttr("release", new BoxedFunction(boxRTFunction((void*)BoxedThreadLock::release, NONE, 1))); thread_lock_cls->giveAttr("acquire_lock", thread_lock_cls->getattr("acquire")); thread_lock_cls->giveAttr("release_lock", thread_lock_cls->getattr("release")); thread_lock_cls->giveAttr("__enter__", thread_lock_cls->getattr("acquire")); thread_lock_cls->giveAttr("__exit__", new BoxedFunction(boxRTFunction((void*)BoxedThreadLock::exit, NONE, 4))); thread_lock_cls->freeze(); BoxedClass* ThreadError = BoxedHeapClass::create(type_cls, Exception, NULL, Exception->attrs_offset, Exception->tp_weaklistoffset, Exception->tp_basicsize, false, "error"); ThreadError->giveAttr("__module__", boxString("thread")); ThreadError->freeze(); thread_module->giveAttr("error", ThreadError); }
void markPhase() { #ifndef NVALGRIND // Have valgrind close its eyes while we do the conservative stack and data scanning, // since we'll be looking at potentially-uninitialized values: VALGRIND_DISABLE_ERROR_REPORTING; #endif TraceStack stack(roots); GCVisitor visitor(&stack); threading::visitAllStacks(&visitor); gatherInterpreterRoots(&visitor); for (void* p : nonheap_roots) { Box* b = reinterpret_cast<Box*>(p); BoxedClass* cls = b->cls; if (cls) { ASSERT(cls->gc_visit, "%s", getTypeName(b)); cls->gc_visit(&visitor, b); } } for (auto h : *getRootHandles()) { visitor.visit(h->value); } // if (VERBOSITY()) printf("Found %d roots\n", stack.size()); while (void* p = stack.pop()) { assert(((intptr_t)p) % 8 == 0); GCAllocation* al = GCAllocation::fromUserData(p); assert(isMarked(al)); // printf("Marking + scanning %p\n", p); GCKind kind_id = al->kind_id; if (kind_id == GCKind::UNTRACKED) { continue; } else if (kind_id == GCKind::CONSERVATIVE) { uint32_t bytes = al->kind_data; if (DEBUG >= 2) { if (global_heap.small_arena.contains(p)) { SmallArena::Block* b = SmallArena::Block::forPointer(p); assert(b->size >= bytes + sizeof(GCAllocation)); } } visitor.visitPotentialRange((void**)p, (void**)((char*)p + bytes)); } else if (kind_id == GCKind::PRECISE) { uint32_t bytes = al->kind_data; if (DEBUG >= 2) { if (global_heap.small_arena.contains(p)) { SmallArena::Block* b = SmallArena::Block::forPointer(p); assert(b->size >= bytes + sizeof(GCAllocation)); } } visitor.visitRange((void**)p, (void**)((char*)p + bytes)); } else if (kind_id == GCKind::PYTHON) { Box* b = reinterpret_cast<Box*>(p); BoxedClass* cls = b->cls; if (cls) { // The cls can be NULL since we use 'new' to construct them. // An arbitrary amount of stuff can happen between the 'new' and // the call to the constructor (ie the args get evaluated), which // can trigger a collection. ASSERT(cls->gc_visit, "%s", getTypeName(b)); cls->gc_visit(&visitor, b); } } else if (kind_id == GCKind::HIDDEN_CLASS) { HiddenClass* hcls = reinterpret_cast<HiddenClass*>(p); hcls->gc_visit(&visitor); } else { RELEASE_ASSERT(0, "Unhandled kind: %d", (int)kind_id); } } #ifndef NVALGRIND VALGRIND_ENABLE_ERROR_REPORTING; #endif }