Executable* MethodTableBucket::get_method(STATE) { if(!method()->nil_p()) return as<Executable>(method()); if(method_id()->nil_p()) return nil<Executable>(); CompiledCode* code = CodeDB::load(state, as<String>(method_id())); if(ConstantScope* cs = try_as<ConstantScope>(scope())) { code->scope(state, cs); } else { code->scope(state, nil<ConstantScope>()); } code->serial(state, serial_); method(state, code); return as<Executable>(code); }
Object* rbx_create_block(STATE, CallFrame* call_frame, int index) { CPP_TRY Object* _lit = call_frame->cm->literals()->at(state, index); CompiledCode* cm = as<CompiledCode>(_lit); // TODO: We don't need to be doing this everytime. if(cm->scope()->nil_p()) { cm->scope(state, call_frame->constant_scope()); } VMMethod* vmm = call_frame->cm->backend_method(); GCTokenImpl gct; return BlockEnvironment::under_call_frame(state, gct, cm, vmm, call_frame); CPP_CATCH }
Object* rbx_create_block(STATE, CallFrame* call_frame, int index) { CPP_TRY Object* _lit = call_frame->compiled_code->literals()->at(state, index); CompiledCode* code = as<CompiledCode>(_lit); // TODO: We don't need to be doing this everytime. code->scope(state, call_frame->constant_scope()); MachineCode* mcode = call_frame->compiled_code->machine_code(); GCTokenImpl gct; return BlockEnvironment::under_call_frame(state, gct, code, mcode, call_frame); CPP_CATCH }
void CompiledCode::Info::show(STATE, Object* self, int level) { CompiledCode* code = as<CompiledCode>(self); class_header(state, self); indent_attribute(++level, "file"); code->file()->show(state, level); indent_attribute(level, "iseq"); code->iseq()->show(state, level); indent_attribute(level, "lines"); code->lines()->show_simple(state, level); indent_attribute(level, "literals"); code->literals()->show_simple(state, level); indent_attribute(level, "local_count"); code->local_count()->show(state, level); indent_attribute(level, "local_names"); code->local_names()->show_simple(state, level); indent_attribute(level, "name"); code->name()->show(state, level); indent_attribute(level, "required_args"); code->required_args()->show(state, level); indent_attribute(level, "scope"); code->scope()->show(state, level); indent_attribute(level, "splat"); code->splat()->show(state, level); indent_attribute(level, "stack_size"); code->stack_size()->show(state, level); indent_attribute(level, "total_args"); code->total_args()->show(state, level); indent_attribute(level, "internalized"); if(!code->machine_code_) { std::cout << "no\n"; } else { std::cout << "yes\n"; #ifdef ENABLE_LLVM MachineCode* v = code->machine_code(); for(int i = 0; i < MachineCode::cMaxSpecializations; i++) { if(!v->specializations[i].jit_data) continue; llvm::Function* func = v->specializations[i].jit_data->llvm_function(); llvm::outs() << "<LLVM>\n" << *func << "</LLVM>\n<MachineCode>\n"; LLVMState::show_machine_code( v->specializations[i].jit_data->native_func(), v->specializations[i].jit_data->native_size()); llvm::outs() << "</MachineCode>\n"; } #endif } close_body(level); }
ConstantScope* constant_scope() { if(custom_constant_scope_p()) return constant_scope_; return compiled_code->scope(); }
ConstantScope* constant_scope() { if(custom_constant_scope_p()) return constant_scope_; return cm->scope(); }
Object* MachineCode::execute_specialized(STATE, CallFrame* previous, Executable* exec, Module* mod, Arguments& args) { CompiledCode* code = as<CompiledCode>(exec); MachineCode* mcode = code->machine_code(); StackVariables* scope = ALLOCA_STACKVARIABLES(mcode->number_of_locals); // Originally, I tried using msg.module directly, but what happens is if // super is used, that field is read. If you combine that with the method // being called recursively, msg.module can change, causing super() to // look in the wrong place. // // Thus, we have to cache the value in the StackVariables. scope->initialize(args.recv(), args.block(), mod, mcode->number_of_locals); InterpreterCallFrame* frame = ALLOCA_CALLFRAME(mcode->stack_size); // If argument handling fails.. if(ArgumentHandler::call(state, mcode, scope, args) == false) { Exception* exc = Exception::make_argument_error(state, mcode->total_args, args.total(), args.name()); exc->locations(state, Location::from_call_stack(state, previous)); state->raise_exception(exc); return NULL; } frame->prepare(mcode->stack_size); frame->previous = previous; frame->constant_scope_ = code->scope(); frame->dispatch_data = 0; frame->compiled_code = code; frame->flags = 0; frame->optional_jit_data = 0; frame->top_scope_ = 0; frame->scope = scope; frame->arguments = &args; GCTokenImpl gct; #ifdef ENABLE_LLVM // A negative call_count means we've disabled usage based JIT // for this method. if(mcode->call_count >= 0) { if(mcode->call_count >= state->shared().config.jit_call_til_compile) { LLVMState* ls = LLVMState::get(state); OnStack<3> os(state, exec, mod, code); ls->compile_callframe(state, gct, code, frame); } else { mcode->call_count++; } } #endif #ifdef RBX_PROFILER if(unlikely(state->vm()->tooling())) { // Check the stack and interrupts here rather than in the interpreter // loop itself. OnStack<2> os(state, exec, code); if(!state->check_interrupts(gct, frame, frame)) return NULL; state->checkpoint(gct, frame); tooling::MethodEntry method(state, exec, scope->module(), args, code); RUBINIUS_METHOD_ENTRY_HOOK(state, scope->module(), args.name(), previous); Object* result = (*mcode->run)(state, mcode, frame); RUBINIUS_METHOD_RETURN_HOOK(state, scope->module(), args.name(), previous); return result; } else { if(!state->check_interrupts(gct, frame, frame)) return NULL; state->checkpoint(gct, frame); RUBINIUS_METHOD_ENTRY_HOOK(state, scope->module(), args.name(), previous); Object* result = (*mcode->run)(state, mcode, frame); RUBINIUS_METHOD_RETURN_HOOK(state, scope->module(), args.name(), previous); return result; } #else if(!state->check_interrupts(gct, frame, frame)) return NULL; state->checkpoint(gct, frame); RUBINIUS_METHOD_ENTRY_HOOK(state, scope->module(), args.name(), previous); Object* result = (*mcode->run)(state, mcode, frame); RUBINIUS_METHOD_RETURN_HOOK(state, scope->module(), args.name(), previous); return result; #endif }