Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
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
}
Exemplo n.º 3
0
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;
}
Exemplo n.º 4
0
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);
}
Exemplo n.º 5
0
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
}