void CallFrame::print_backtrace(STATE) { CallFrame* cf = this; while(cf) { if(!cf->cm) { cf = static_cast<CallFrame*>(cf->previous); continue; } std::cout << static_cast<void*>(cf) << ": "; if(cf->is_block_p(state)) { std::cout << "__block__"; } else { if(MetaClass* meta = try_as<MetaClass>(cf->module())) { if(Module* mod = try_as<Module>(meta->attached_instance())) { std::cout << mod->name()->c_str(state) << "."; } else { std::cout << "#<" << meta->attached_instance()->class_object(state)->name()->c_str(state) << ":" << (void*)meta->attached_instance() << ">."; } } else { const char* mod_name; if(cf->module()->nil_p()) { mod_name = cf->cm->scope()->module()->name()->c_str(state); } else if(cf->module()->name()->nil_p()) { mod_name = cf->cm->scope()->module()->name()->c_str(state); } else { mod_name = cf->module()->name()->c_str(state); } std::cout << mod_name << "#"; } Symbol* name = try_as<Symbol>(cf->name()); if(name) { std::cout << name->c_str(state); } else { std::cout << cf->cm->name()->c_str(state); } } std::cout << " in "; if(Symbol* file_sym = try_as<Symbol>(cf->cm->file())) { std::cout << file_sym->c_str(state) << ":" << cf->line(state); } else { std::cout << "<unknown>"; } std::cout << " (+" << cf->ip(); if(cf->is_inline_frame()) { std::cout << " inline"; } std::cout << ")"; std::cout << std::endl; cf = static_cast<CallFrame*>(cf->previous); } }
Tuple* Thread::context(STATE) { utilities::thread::SpinLock::LockGuard lg(init_lock_); VM* vm = vm_; if(!vm) return nil<Tuple>(); CallFrame* cf = vm->saved_call_frame()->top_ruby_frame(); VariableScope* scope = cf->promote_scope(state); return Tuple::from(state, 3, Fixnum::from(cf->ip()), cf->compiled_code, scope); }
void SignalThread::print_backtraces() { STATE = shared_.env()->state; ThreadList* threads = shared_.thread_nexus()->threads(); for(ThreadList::iterator i = threads->begin(); i != threads->end(); ++i) { VM* vm = (*i)->as_vm(); if(!vm) continue; bool first = true; CallFrame* frame = vm->call_frame(); while(frame) { if(first) { logger::fatal("--- %s %d backtrace ---", vm->kind_name(), vm->thread_id()); first = false; } std::ostringstream stream; if(NativeMethodFrame* nmf = frame->native_method_frame()) { stream << static_cast<void*>(frame) << ": "; NativeMethod* nm = try_as<NativeMethod>(nmf->get_object(nmf->method())); if(nm && nm->name()->symbol_p()) { stream << "capi:" << nm->name()->debug_str(state) << " at "; stream << nm->file()->c_str(state); } else { stream << "unknown capi"; } } else if(frame->compiled_code) { if(frame->is_block_p(state)) { stream << "__block__"; } else { if(SingletonClass* sc = try_as<SingletonClass>(frame->module())) { Object* obj = sc->singleton(); if(Module* mod = try_as<Module>(obj)) { stream << mod->debug_str(state) << "."; } else { if(obj == G(main)) { stream << "MAIN."; } else { stream << "#<" << obj->class_object(state)->debug_str(state) << ":" << (void*)obj->id(state)->to_native() << ">."; } } } else if(IncludedModule* im = try_as<IncludedModule>(frame->module())) { stream << im->module()->debug_str(state) << "#"; } else { Symbol* name; std::string mod_name; if(frame->module()->nil_p()) { mod_name = frame->lexical_scope()->module()->debug_str(state); } else { if((name = try_as<Symbol>(frame->module()->module_name()))) { mod_name = name->debug_str(state); } else if((name = try_as<Symbol>( frame->lexical_scope()->module()->module_name()))) { mod_name = name->debug_str(state); } else { mod_name = "<anonymous module>"; } } stream << mod_name << "#"; } Symbol* name = try_as<Symbol>(frame->name()); if(name) { stream << name->debug_str(state); } else { stream << frame->compiled_code->name()->debug_str(state); } } stream << " in "; if(Symbol* file_sym = try_as<Symbol>(frame->compiled_code->file())) { stream << file_sym->debug_str(state) << ":" << frame->line(state); } else { stream << "<unknown>"; } stream << " (+" << frame->ip(); if(frame->is_inline_frame()) { stream << " inline"; } else if(frame->jitted_p()) { stream << " jit"; } stream << ")"; } logger::fatal(stream.str().c_str()); frame = frame->previous; } } }
void CallFrame::print_backtrace(STATE, std::ostream& stream, int total, bool filter) { CallFrame* cf = this; int i = -1; while(cf) { i++; if(total > 0 && i == total) return; if(NativeMethodFrame* nmf = cf->native_method_frame()) { stream << static_cast<void*>(cf) << ": "; NativeMethod* nm = try_as<NativeMethod>(nmf->get_object(nmf->method())); if(nm && nm->name()->symbol_p()) { stream << "capi:" << nm->name()->debug_str(state) << " at "; stream << nm->file()->c_str(state); } else { stream << "unknown capi"; } stream << std::endl; cf = cf->previous; continue; } if(!cf->compiled_code) { cf = cf->previous; continue; } if(filter && cf->compiled_code->kernel_method(state)) { cf = cf->previous; continue; } stream << static_cast<void*>(cf) << ": "; if(cf->is_block_p(state)) { stream << "__block__"; } else { if(SingletonClass* sc = try_as<SingletonClass>(cf->module())) { Object* obj = sc->attached_instance(); if(Module* mod = try_as<Module>(obj)) { stream << mod->debug_str(state) << "."; } else { if(obj == G(main)) { stream << "MAIN."; } else { stream << "#<" << obj->class_object(state)->debug_str(state) << ":" << (void*)obj->id(state)->to_native() << ">."; } } } else if(IncludedModule* im = try_as<IncludedModule>(cf->module())) { stream << im->module()->debug_str(state) << "#"; } else { Symbol* name; std::string mod_name; if(cf->module()->nil_p()) { mod_name = cf->constant_scope()->module()->debug_str(state); } else { if((name = try_as<Symbol>(cf->module()->module_name()))) { mod_name = name->debug_str(state); } else if((name = try_as<Symbol>( cf->constant_scope()->module()->module_name()))) { mod_name = name->debug_str(state); } else { mod_name = "<anonymous module>"; } } stream << mod_name << "#"; } Symbol* name = try_as<Symbol>(cf->name()); if(name) { stream << name->debug_str(state); } else { stream << cf->compiled_code->name()->debug_str(state); } } stream << " in "; if(Symbol* file_sym = try_as<Symbol>(cf->compiled_code->file())) { stream << file_sym->debug_str(state) << ":" << cf->line(state); } else { stream << "<unknown>"; } stream << " (+" << cf->ip(); if(cf->is_inline_frame()) { stream << " inline"; } else if(cf->jitted_p()) { stream << " jit"; } stream << ")"; stream << std::endl; cf = cf->previous; } }