[macruby-changes] [2562] MacRuby/trunk

source_changes at macosforge.org source_changes at macosforge.org
Fri Sep 18 01:30:16 PDT 2009


Revision: 2562
          http://trac.macosforge.org/projects/ruby/changeset/2562
Author:   lsansonetti at apple.com
Date:     2009-09-18 01:30:15 -0700 (Fri, 18 Sep 2009)
Log Message:
-----------
added preliminary support for backtracing/symbolication

Modified Paths:
--------------
    MacRuby/trunk/compiler.cpp
    MacRuby/trunk/compiler.h
    MacRuby/trunk/vm.cpp
    MacRuby/trunk/vm.h

Modified: MacRuby/trunk/compiler.cpp
===================================================================
--- MacRuby/trunk/compiler.cpp	2009-09-18 08:29:05 UTC (rev 2561)
+++ MacRuby/trunk/compiler.cpp	2009-09-18 08:30:15 UTC (rev 2562)
@@ -20,9 +20,13 @@
 
 extern "C" const char *ruby_node_name(int node);
 
+// Will be set later, in vm.cpp.
 llvm::Module *RoxorCompiler::module = NULL;
 RoxorCompiler *RoxorCompiler::shared = NULL;
 
+AnnotationID RoxorFunctionAnnotation::id =
+	AnnotationManager::getID("RoxorFunction");
+
 RoxorCompiler::RoxorCompiler(void)
 {
     fname = NULL;
@@ -128,6 +132,8 @@
     setCurrentClassFunc = NULL;
     getCacheFunc = NULL;
 
+    func_annotation = NULL;
+
 #if __LP64__
     RubyObjTy = IntTy = Type::Int64Ty;
 #else
@@ -730,6 +736,9 @@
 	    (module->getOrInsertFunction("rb_vm_dispatch", ft));
     }
 
+    assert(func_annotation != NULL);
+    func_annotation->dispatch_lines.push_back(current_line);
+
     return compile_protected_call(dispatcherFunc, params);
 }
 
@@ -2944,6 +2953,7 @@
     }
     printf("... %s\n", ruby_node_name(nd_type(node)));
 #endif
+    current_line = nd_line(node);
 
     switch (nd_type(node)) {
 	case NODE_SCOPE:
@@ -2985,6 +2995,9 @@
 		Function *f = Function::Create(ft, GlobalValue::PrivateLinkage,
 			"", module);
 
+		RoxorFunctionAnnotation *old_func_annotation = func_annotation;
+		func_annotation = new RoxorFunctionAnnotation(f, fname);
+
 		BasicBlock *old_rescue_bb = rescue_bb;
 		BasicBlock *old_entry_bb = entry_bb;
 		BasicBlock *old_bb = bb;
@@ -3205,6 +3218,7 @@
 		    rescue_bb->eraseFromParent();
 		}
 
+		func_annotation = old_func_annotation;
 		bb = old_bb;
 		entry_bb = old_entry_bb;
 		lvars = old_lvars;

Modified: MacRuby/trunk/compiler.h
===================================================================
--- MacRuby/trunk/compiler.h	2009-09-18 08:29:05 UTC (rev 2561)
+++ MacRuby/trunk/compiler.h	2009-09-18 08:30:15 UTC (rev 2562)
@@ -27,6 +27,23 @@
 #define DEFINED_SUPER	6
 #define DEFINED_METHOD	7
 
+class RoxorFunctionAnnotation : public Annotation {
+    public:
+	static AnnotationID id;
+	std::string path;
+	std::vector<unsigned int> dispatch_lines;
+
+	RoxorFunctionAnnotation(Function *function, const char *_path)
+	    : Annotation(RoxorFunctionAnnotation::id), path(_path) {
+		function->addAnnotation(this);
+	    }
+
+	static RoxorFunctionAnnotation *from_function(Function *function) {
+	    return (RoxorFunctionAnnotation *)
+		function->getAnnotation(RoxorFunctionAnnotation::id);
+	}
+};
+
 class RoxorCompiler {
     public:
 	static llvm::Module *module;
@@ -81,6 +98,7 @@
 # define DEBUG_LEVEL_DEC()
 #endif
 
+	unsigned int current_line;
 	BasicBlock *bb;
 	BasicBlock *entry_bb;
 	ID current_mid;
@@ -108,6 +126,7 @@
 	int return_from_block;
 	int return_from_block_ids;
 	PHINode *ensure_pn;
+	RoxorFunctionAnnotation *func_annotation;
 
 	Function *dispatcherFunc;
 	Function *fastPlusFunc;

Modified: MacRuby/trunk/vm.cpp
===================================================================
--- MacRuby/trunk/vm.cpp	2009-09-18 08:29:05 UTC (rev 2561)
+++ MacRuby/trunk/vm.cpp	2009-09-18 08:30:15 UTC (rev 2562)
@@ -406,8 +406,8 @@
 }
 
 bool
-RoxorCore::symbolize_call_address(void *addr, void **startp, unsigned long *ln,
-	char *name, size_t name_len)
+RoxorCore::symbolize_call_address(void *addr, void **startp, char *path,
+	size_t path_len, unsigned long *ln, char *name, size_t name_len)
 {
     void *start = NULL;
 
@@ -429,7 +429,7 @@
 	*startp = start;
     }
 
-    if (name != NULL || ln != NULL) {
+    if (name != NULL || path != NULL || ln != NULL) {
 	std::map<IMP, rb_vm_method_node_t *>::iterator iter = 
 	    ruby_imps.find((IMP)start);
 	if (iter == ruby_imps.end()) {
@@ -438,11 +438,56 @@
 	}
 
 	rb_vm_method_node_t *node = iter->second;
-#if 0 // TODO
+
+	RoxorFunctionAnnotation *annotation = f == NULL
+	    ? NULL
+	    : RoxorFunctionAnnotation::from_function(f->f);
 	if (ln != NULL) {
-	    *ln = nd_line(node->node);
+	    if (annotation != NULL) {
+#if __LP64__
+		// So, we need to determine here which call to the dispatcher
+		// we are exactly, so that we can retrieve the appropriate
+		// line number from the annotation.
+		// Unfortunately, the only way to achieve that seems to scan
+		// the current function's machine code.
+		// This code has only been tested on x86_64 but could be
+		// easily ported to i386.
+		const uint32_t sym = *(uint32_t *)((unsigned char *)addr - 8);
+		const int sentinel = sym & 0xff;
+
+		unsigned char *p = f->start;
+		unsigned int i = 0;
+		while ((p = (unsigned char *)memchr(p, sentinel,
+				(unsigned char *)addr - p)) != NULL) {
+		    if (*(uint32_t *)p == sym) {
+			i++;
+		    }
+		    p++;
+		}
+
+		if (i > 0 && i - 1 < annotation->dispatch_lines.size()) {
+		    *ln = annotation->dispatch_lines[i - 1];
+		}
+		else {
+		    *ln = 0;
+		}
+#else
+		// TODO 32-bit hack...
+		*ln = 0;
+#endif
+	    }
+	    else {
+		*ln = 0;
+	    }
 	}
-#endif
+	if (path != NULL) {
+	    if (annotation != NULL) {
+		strncpy(path, annotation->path.c_str(), path_len);
+	    }
+	    else {
+		strncpy(path, "core", path_len);
+	    }
+	}
 	if (name != NULL) {
 	    strncpy(name, sel_getName(node->sel), name_len);
 	}
@@ -2329,7 +2374,7 @@
     for (int i = callstack_n - 1; i >= 0; i--) {
 	void *start = NULL;
 	if (GET_CORE()->symbolize_call_address(callstack[i],
-		    &start, NULL, NULL, 0)) {
+		    &start, NULL, 0, NULL, NULL, 0)) {
 	    start = (void *)objc_imp((IMP)start);
 	    if (start == (void *)self) {
 		skip = false;
@@ -4507,13 +4552,14 @@
     VALUE ary = rb_ary_new();
 
     for (int i = 0; i < callstack_n; i++) {
+	char path[PATH_MAX];
 	char name[100];
 	unsigned long ln = 0;
 
-	if (GET_CORE()->symbolize_call_address(callstack[i], NULL, &ln, name,
-		    sizeof name)) {
-	    char entry[100];
-	    snprintf(entry, sizeof entry, "%ld:in `%s'", ln, name);
+	if (GET_CORE()->symbolize_call_address(callstack[i], NULL,
+		    path, sizeof path, &ln, name, sizeof name)) {
+	    char entry[PATH_MAX];
+	    snprintf(entry, sizeof entry, "%s:%ld:in `%s'", path, ln, name);
 	    rb_ary_push(ary, rb_str_new2(entry));
 	}
     }

Modified: MacRuby/trunk/vm.h
===================================================================
--- MacRuby/trunk/vm.h	2009-09-18 08:29:05 UTC (rev 2561)
+++ MacRuby/trunk/vm.h	2009-09-18 08:30:15 UTC (rev 2562)
@@ -670,7 +670,8 @@
 	}
 
 	bool symbolize_call_address(void *addr, void **startp,
-		unsigned long *ln, char *name, size_t name_len);
+		char *path, size_t path_len, unsigned long *ln,
+		char *name, size_t name_len);
 
 	struct mcache *method_cache_get(SEL sel, bool super);
 	rb_vm_method_node_t *method_node_get(IMP imp);
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090918/852c87a3/attachment.html>


More information about the macruby-changes mailing list