Esempio n. 1
0
File: vm_exec.c Progetto: filp/slash
SLVAL
sl_vm_exec(sl_vm_exec_ctx_t* ctx, size_t ip)
{
    int line = 0;
    sl_vm_t* vm = ctx->vm;
    sl_vm_exception_handler_t* volatile exception_handler = NULL;
    sl_vm_section_t* section = ctx->section;

    sl_vm_frame_t catch_frame;
    sl_vm_frame_t call_frame;
    call_frame.prev = vm->call_stack;
    call_frame.frame_type = SL_VM_FRAME_SLASH;
    call_frame.as.call_frame.method = section->name;
    call_frame.as.call_frame.filename = (char*)section->filename;
    call_frame.as.call_frame.line = (int*)&line;
    vm->call_stack = &call_frame;

    if(ctx->section->has_try_catch) {
        catch_frame.frame_type = SL_VM_FRAME_HANDLER;
        catch_frame.as.handler_frame.value = vm->lib.nil;
    reset_exception_handler:
        catch_frame.prev = vm->call_stack;
        vm->call_stack = &catch_frame;
        
        if(sl_setjmp(catch_frame.as.handler_frame.env)) {
            vm->call_stack = catch_frame.prev;
            if(exception_handler && (catch_frame.as.handler_frame.unwind_type & SL_UNWIND_EXCEPTION)) {
                ip = exception_handler->catch_ip;
                goto reset_exception_handler;
            } else {
                vm->call_stack = call_frame.prev;
                sl_unwind(vm, catch_frame.as.handler_frame.value, catch_frame.as.handler_frame.unwind_type);
            }
        }
    }

    while(1) {
        switch(NEXT().opcode) {
            #undef INSTRUCTION
            #define INSTRUCTION(opcode, code) \
                case opcode: { \
                    code; \
                } break;
            #include "vm_defn.inc"
            
            default:
                sl_throw_message(vm, "BUG: Unknown opcode in VM"); /* never reached */
        }
    }
}
Esempio n. 2
0
static SLVAL
call_c_func(sl_vm_t* vm, SLVAL recv, sl_method_t* method, size_t argc, SLVAL* argv)
{
    if(method->arity < 0) {
        return method->as.c.func(vm, recv, argc, argv);
    } else {
        switch(method->arity) {
            case 0: return method->as.c.func(vm, recv);
            case 1: return method->as.c.func(vm, recv, argv[0]);
            case 2: return method->as.c.func(vm, recv, argv[0], argv[1]);
            case 3: return method->as.c.func(vm, recv, argv[0], argv[1], argv[2]);
            case 4: return method->as.c.func(vm, recv, argv[0], argv[1], argv[2], argv[3]);
            default:
                sl_throw_message(vm, "Too many arguments for C function");
        }
    }
    return vm->lib.nil; /* never reached */
}
Esempio n. 3
0
SLVAL
sl_imc_setup_call(sl_vm_t* vm, sl_vm_inline_method_cache_t* imc, SLVAL recv, SLVAL* argv)
{
    SLVAL klass = SL_IS_INT(recv) ? vm->lib.Int : sl_get_ptr(recv)->klass;
    sl_method_t* method = lookup_method_rec(vm, klass, imc->id);
    if(method) {
        imc->state = vm->state_method;
        imc->klass = klass;
        imc->method = method;
        if(method->base.user_flags & SL_FLAG_METHOD_IS_C_FUNC) {
            if(method->arity < 0) {
                if(sl_likely(-imc->argc - 1 <= method->arity)) {
                    imc->call = dispatch_c_call_variadic;
                } else {
                    imc->call = sl_imc_cached_call; // cop out
                }
            } else {
                if(sl_likely(imc->argc == method->arity)) {
                    switch(method->arity) {
                        case 0: imc->call = dispatch_c_call_0; break;
                        case 1: imc->call = dispatch_c_call_1; break;
                        case 2: imc->call = dispatch_c_call_2; break;
                        case 3: imc->call = dispatch_c_call_3; break;
                        case 4: imc->call = dispatch_c_call_4; break;
                        default:
                            sl_throw_message(vm, "Too many arguments for C function");
                    }
                } else {
                    imc->call = sl_imc_cached_call; // cop out
                }
            }
        } else {
            if(method->arity >= 0 && imc->argc >= method->arity && method->as.sl.section->can_stack_alloc_frame && !method->as.sl.section->opt_skip) {
                imc->call = dispatch_slash_call_stack_regs;
            } else {
                imc->call = sl_imc_cached_call; // cop out
            }
        }
        return imc->call(vm, imc, recv, argv);
    } else {
        return sl_send_missing(vm, recv, imc->id, imc->argc, argv);
    }
}