static void trace_by_addr(void *obj_addr, int distance) { // An arbitrary cut-off for a search that's too deep to be useful. if(distance > 20) { return; } Object_With_Header *obj = (Object_With_Header *) GC::pinned_objects; while(obj) { uint64 sz = get_object_size(obj); void **obj_start = (void **)obj->start(); void **obj_end = (void **)(((Byte *)obj_start) + sz); for(void **p = obj_start; p < obj_end; p++) { if(obj_addr == *p) { printf("GC TRACE: [%d] %p in obj %p(+%d): %s\n", distance, obj_addr, obj_start, (int)(((Byte *)p) - ((Byte *)obj_start)), class_get_name(obj->vt()->gcvt->ch)); if(!is_marked(obj)) { printf("GC TRACE: %p is not marked\n", obj_start); trace_by_addr(obj_start, distance + 1); } } } obj = next_object(obj); } } //trace_by_addr
MTable::MethodInfo::MethodInfo(Method_Handle _mh, size_t _num) { num = _num; mh = _mh; Class_Handle ch = method_get_class(mh); className = class_get_name(ch); methodName = method_get_name(mh); signature = method_get_descriptor(mh); assert(!className.empty() && !methodName.empty() && !signature.empty()); }
/** * Prints graph structure in stderr. */ void vf_Graph::DumpGraph() { #if _VF_DEBUG VF_DEBUG("Method: " << class_get_name(m_ctx->m_class) << "::" << m_ctx->m_name << m_ctx->m_descriptor << endl); VF_DEBUG("-- start --"); ResetNodeIterator(); while (HasMoreElements()) { DumpNode(GetNextNode()); } #endif // _VF_DEBUG } // vf_Graph::DumpGraph
static void logReadyProfile(const std::string& catName, const std::string& profilerName, EBMethodProfile* mp) { const char* methodName = method_get_name(mp->mh); Class_Handle ch = method_get_class(mp->mh); const char* className = class_get_name(ch); const char* signature = method_get_descriptor(mp->mh); std::ostringstream msg; msg <<"EM: profiler["<<profilerName.c_str()<<"] profile is ready [e:" << mp->entryCounter <<" b:"<<mp->backedgeCounter<<"] " <<className<<"::"<<methodName<<signature; INFO2(catName.c_str(), msg.str().c_str()); }
void trace_by_id() { if(GC::trace_obj == NULL) { // No tracing or the object hasn't been allocated yet. return; } if(GC::trace_collection_number >= 0) { // Object has been already traced return; } Object_With_Header *obj = GC::trace_obj; if(is_marked(obj)) { // This GC hasn't reclaimed the object return; } GC::trace_collection_number = GC::num_collections; printf("GC TRACE: Tracing unmarked object %p: %s\n", obj->start(), class_get_name(obj->vt()->gcvt->ch)); void *obj_addr = obj->start(); trace_by_addr(obj_addr, 0); } //trace_by_id
static jint skip_old_frames(VM_thread *thread) { if (NULL == getLastStackFrame(thread)) return 0; StackFrame* first_frame = (StackFrame*)(thread->firstFrame); if (first_frame) { Class *clss = method_get_class(first_frame->method); assert(clss); if (strcmp(method_get_name(first_frame->method), "runImpl") == 0 && strcmp(class_get_name(clss), "java/lang/Thread") == 0) { return 1; } } return 0; }
ClassPtr _class_define_property(ClassPtr cls, Symbol name, Value getter, Value setter) { Property* property = new Property; property->getter = getter; property->setter = setter; Method key = { .name = name, .type = MethodTypeProperty, .function = NULL, .property = property }; if (!class_define_method_or_property(cls, key)) { delete property; throw_exception_with_description("Method or property '%@' is already defined in class %@@%@.", snow::sym_to_cstr(name), class_get_name(cls), format::pointer(cls)); } return cls; }
ClassPtr _class_define_method(ClassPtr cls, Symbol name, Value function) { ASSERT(!snow::is_symbol(function)); Method key = { .name = name, .type = MethodTypeFunction, .function = function, .property = NULL }; if (!class_define_method_or_property(cls, key)) { throw_exception_with_description("Method or property '%@' is already defined in class %@@%@.", snow::sym_to_cstr(name), class_get_name(cls), format::pointer(cls)); } return cls; }
VALUE class_inspect(const CallFrame* here, VALUE self, VALUE it) { if (!is_class(self)) throw_exception_with_description("Class#inspect called for object that is not a class: %@.", value_inspect(self)); return format_string("[Class@%@ name:%@]", format::pointer(self), class_get_name(self)); }
void mark_recursive(Managed_Object_Handle ref, bool ref_is_compressed) { // If ref_is_compressed, ref is a compressed reference: the uint32 offset to an object in the heap. // ref_is_compressed => (GC::compressing_references && is_compressed_reference(ref)) assert(!ref_is_compressed || (GC::compressing_references && is_compressed_reference((COMPRESSED_REFERENCE)ref))); uint64 null_ref = (GC::compressing_references? GC::heap_base : NULL); if (ref_is_compressed) { if (ref == 0) { return; } } else { if ((uint64)ref == null_ref) { return; } } Object_With_Header *obj; if (ref_is_compressed) { Managed_Object_Handle ref2 = (Managed_Object_Handle)(GC::heap_base + (COMPRESSED_REFERENCE)ref); obj = (Object_With_Header *)(((Byte *)ref2) - sizeof(GC_Overhead)); } else { obj = (Object_With_Header *)(((Byte *)ref) - sizeof(GC_Overhead)); } unsigned space = obj->header.semispace; validate_object(obj); if(false && GC::verbosegc) { #ifdef GC_STATS printf("Marking object: %s%p [id=%I64d]\n", (ref_is_compressed? "compressed " : ""), ref, obj->header.id); #endif //GC_STATS } if(is_marked(obj)) { return; } set_marked(obj); Vtable_GC *vt = obj->vt(); if(false && GC::verbosegc) { printf("\tObject of type %s\n", class_get_name(vt->gcvt->ch)); } if(vt->gcvt->is_scannable_array) { scan_array(obj); } else { uint16 *offsets = vt->gcvt->offsets; Managed_Object_Handle ref2 = ref; if (ref_is_compressed) { ref2 = (Managed_Object_Handle)(GC::heap_base + (COMPRESSED_REFERENCE)ref); } if (GC::compressing_references) { while(*offsets) { COMPRESSED_REFERENCE *slot = (COMPRESSED_REFERENCE *)(((Byte *)ref2) + (*offsets)); COMPRESSED_REFERENCE val_offset = (COMPRESSED_REFERENCE)(*slot); assert(is_compressed_reference(val_offset)); Managed_Object_Handle val = (Managed_Object_Handle)(GC::heap_base + val_offset); push_on_mark_stack(val); offsets++; } } else { while(*offsets) { Managed_Object_Handle *slot = (Managed_Object_Handle *)(((Byte *)ref2) + *offsets); push_on_mark_stack(*slot); offsets++; } } } } //mark_recursive
/** * Dumps graph node in file in DOT format. */ void vf_Graph::DumpDotGraph() { #if _VF_DEBUG /** * Graphviz has a hardcoded label length limit. Windows has a file * name length limit as well. */ const int MAX_LABEL_LENGTH = 80; // get class and method name const char *class_name = class_get_name(m_ctx->m_class); // create file name size_t len = strlen(class_name) + strlen(m_ctx->m_name) + strlen(m_ctx->m_descriptor) + 6; char *fname = (char *) STD_ALLOCA(len); sprintf(fname, "%s_%s%s", class_name, m_ctx->m_name, m_ctx->m_descriptor); char *f_start; char *pointer; if (len > MAX_LABEL_LENGTH) { f_start = fname + len - MAX_LABEL_LENGTH; // shift to the start of the nearest lexem for (pointer = f_start;; pointer++) { if (isalnum(*pointer)) { continue; } else if (!*pointer) { // end of the string break; } else { // record the first matching position f_start = pointer; break; } } } else { f_start = fname; } for (pointer = f_start;; pointer++) { if (isalnum(*pointer)) { continue; } else if (!*pointer) { // end of the string break; } else { *pointer = '_'; } } // pointer currently points to the end of the string sprintf(pointer, ".dot"); // create .dot file ofstream fout(f_start); if (fout.fail()) { VF_DEBUG("vf_Graph::DumpDotGraph: error opening file: " << f_start); return; } // create name of graph sprintf(fname, "%s.%s%s", class_name, m_ctx->m_name, m_ctx->m_descriptor); // print graph to file DumpDotHeader(f_start, fout); ResetNodeIterator(); while (HasMoreElements()) { DumpDotNode(GetNextNode(), fout); } DumpDotEnd(fout); // close file fout.flush(); fout.close(); #endif // _VF_DEBUG } // vf_Graph::DumpDotGraph