Exemple #1
0
// @args finalizer allows NULL.
pone_val* pone_opaque_new(pone_world* world, pone_val* klass, void* ptr, pone_finalizer_t finalizer) {
    struct pone_opaque_body* body = pone_malloc(world, sizeof(struct pone_opaque_body));
    body->ptr = ptr;
    body->finalizer = finalizer;
    body->refcnt = 1;
    body->klass = klass;

    pone_val* opaque = pone_obj_alloc(world, PONE_OPAQUE);
    opaque->as.opaque.body = body;
    return opaque;
}
Exemple #2
0
// Caller must get GC_RD_LOCK.
pone_val* pone_obj_alloc(pone_world* world, pone_t type) {
    pone_universe* universe = world->universe;

    assert(universe);
    assert(world->arena_last != NULL);
    pone_val* val;

#ifdef STRESS_GC
    // pone_gc_log(world->universe, "stress gc\n");
    world->gc_requested = true;
#endif

    // check free-ed values
    if (world->freelist) {
        // reuse it.
        val = world->freelist;
        world->freelist = world->freelist->as.free.next;
    } else {
        // there is no free-ed value.
        // then, use value from arena.
        if (world->arena_last->idx == PONE_ARENA_SIZE) {
            // arena doesn't have an empty slot

            // Run GC.
            pone_gc_log(world->universe, "there's no empty slot in the arena %p\n", world->arena_last);
            world->gc_requested = true;

            // alloc new arena
            pone_arena* arena = pone_malloc(world, sizeof(pone_arena));
            arena->next = NULL;
            arena->idx = 0;
            world->arena_last->next = arena;
            world->arena_last = arena;
            val = &(arena->values[arena->idx]);
            arena->idx++;
        } else {
            // use last arena entry
            val = &(world->arena_last->values[world->arena_last->idx++]);
        }
    }

    val->as.basic.flags = 0;
    val->as.basic.type = type;

    pone_save_tmp(world, val);

    return val;
}
Exemple #3
0
pone_val* pone_regex_new(pone_world* world, const char* str, size_t len) {
    pone_universe* universe = world->universe;
    pone_val* obj = pone_obj_new(world, universe->class_regex);
    OnigErrorInfo errinfo;
    regex_t* re = pone_malloc(world, sizeof(regex_t));
    int err_code;
    if ((err_code = onig_new_without_alloc(re, (const OnigUChar*)str, (const OnigUChar*)str + len, ONIG_OPTION_NONE, ONIG_ENCODING_UTF8, ONIG_SYNTAX_PERL, &errinfo)) != ONIG_NORMAL) {
        char buf[ONIG_MAX_ERROR_MESSAGE_LEN];
        int errsize = onig_error_code_to_str((OnigUChar*)buf, err_code, errinfo);
        pone_throw(world, pone_str_new_strdup(world, buf, errsize));
        // TODO create X::Regexp
    }
    pone_obj_set_ivar(world, obj, "$!re", pone_opaque_new(world, universe->class_onig, re, re_finalizer));
    pone_obj_set_ivar(world, obj, "$!str", pone_str_new_strdup(world, str, len));
    return obj;
}
Exemple #4
0
pone_val* pone_new_hash(pone_world* world, int n, ...) {
    va_list list;

    pone_hash* hv = (pone_hash*)pone_malloc(world, sizeof(pone_hash));
    hv->refcnt = 1;
    hv->type   = PONE_HASH;

    hv->h = kh_init(str);

    va_start(list, n);
    // we can optimize in case of `{a => 3}`. we can omit mortalize.
    for (int i=0; i<n; i+=2) {
        pone_val* k = va_arg(list, pone_val*);
        pone_val* v = va_arg(list, pone_val*);
        pone_hash_put(world, (pone_val*)hv, k, v);
    }
    va_end(list);

    return (pone_val*)hv;
}