summaryrefslogtreecommitdiffstats
path: root/src/dom/js/jsutil.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/dom/js/jsutil.c')
-rw-r--r--src/dom/js/jsutil.c213
1 files changed, 124 insertions, 89 deletions
diff --git a/src/dom/js/jsutil.c b/src/dom/js/jsutil.c
index 6e4c21cad..d7fab0f88 100644
--- a/src/dom/js/jsutil.c
+++ b/src/dom/js/jsutil.c
@@ -51,107 +51,142 @@
# include <windows.h>
#endif
-#ifdef XP_MAC
-# include <Types.h>
-# include <stdarg.h>
-# include "jsprf.h"
+JS_PUBLIC_API(void) JS_Assert(const char *s, const char *file, JSIntn ln)
+{
+ fprintf(stderr, "Assertion failure: %s, at %s:%d\n", s, file, ln);
+#if defined(WIN32)
+ DebugBreak();
+ exit(3);
#endif
+#if defined(XP_OS2)
+ asm("int $3");
+#endif
+ abort();
+}
-#ifdef XP_MAC
-/*
- * PStrFromCStr converts the source C string to a destination
- * pascal string as it copies. The dest string will
- * be truncated to fit into an Str255 if necessary.
- * If the C String pointer is NULL, the pascal string's length is
- * set to zero.
- */
-static void PStrFromCStr(const char *src, Str255 dst)
+#if defined DEBUG_notme && defined XP_UNIX
+
+#define __USE_GNU 1
+#include <dlfcn.h>
+#include <setjmp.h>
+#include <string.h>
+#include "jshash.h"
+#include "jsprf.h"
+
+JSCallsite js_calltree_root = {0, NULL, NULL, 0, NULL, NULL, NULL, NULL};
+
+static JSCallsite *
+CallTree(uint32 *bp)
{
- short length = 0;
-
- /* handle case of overlapping strings */
- if ( (void*)src == (void*)dst )
- {
- unsigned char *curdst = &dst[1];
- unsigned char thisChar;
-
- thisChar = *(const unsigned char*)src++;
- while ( thisChar != '\0' )
- {
- unsigned char nextChar;
-
- /*
- * Use nextChar so we don't overwrite what we
- * are about to read
- */
- nextChar = *(const unsigned char*)src++;
- *curdst++ = thisChar;
- thisChar = nextChar;
-
- if ( ++length >= 255 )
- break;
- }
+ uint32 *bpup, *bpdown, pc;
+ JSCallsite *parent, *site, **csp;
+ Dl_info info;
+ int ok, offset;
+ const char *symbol;
+ char *method;
+
+ /* Reverse the stack frame list to avoid recursion. */
+ bpup = NULL;
+ for (;;) {
+ bpdown = (uint32*) bp[0];
+ bp[0] = (uint32) bpup;
+ if ((uint32*) bpdown[0] < bpdown)
+ break;
+ bpup = bp;
+ bp = bpdown;
}
- else if ( src != NULL )
- {
- unsigned char *curdst = &dst[1];
- /* count down so test it loop is faster */
- short overflow = 255;
- register char temp;
- /*
- * Can't do the K&R C thing of while (*s++ = *t++)
- * because it will copy trailing zero which might
- * overrun pascal buffer. Instead we use a temp variable.
- */
- while ( (temp = *src++) != 0 )
- {
- *(char*)curdst++ = temp;
+ /* Reverse the stack again, finding and building a path in the tree. */
+ parent = &js_calltree_root;
+ do {
+ bpup = (uint32*) bp[0];
+ bp[0] = (uint32) bpdown;
+ pc = bp[1];
+
+ csp = &parent->kids;
+ while ((site = *csp) != NULL) {
+ if (site->pc == pc) {
+ /* Put the most recently used site at the front of siblings. */
+ *csp = site->siblings;
+ site->siblings = parent->kids;
+ parent->kids = site;
+
+ /* Site already built -- go up the stack. */
+ goto upward;
+ }
+ csp = &site->siblings;
+ }
- if ( --overflow <= 0 )
- break;
+ /* Check for recursion: see if pc is on our ancestor line. */
+ for (site = parent; site; site = site->parent) {
+ if (site->pc == pc)
+ goto upward;
}
- length = 255 - overflow;
- }
- dst[0] = length;
-}
-static void jsdebugstr(const char *debuggerMsg)
-{
- Str255 pStr;
+ /*
+ * Not in tree at all: let's find our symbolic callsite info.
+ * XXX static syms are masked by nearest lower global
+ */
+ info.dli_fname = info.dli_sname = NULL;
+ ok = dladdr((void*) pc, &info);
+ if (ok < 0) {
+ fprintf(stderr, "dladdr failed!\n");
+ return NULL;
+ }
- PStrFromCStr(debuggerMsg, pStr);
- DebugStr(pStr);
+/* XXXbe sub 0x08040000? or something, see dbaron bug with tenthumbs comment */
+ symbol = info.dli_sname;
+ offset = (char*)pc - (char*)info.dli_fbase;
+ method = symbol
+ ? strdup(symbol)
+ : JS_smprintf("%s+%X",
+ info.dli_fname ? info.dli_fname : "main",
+ offset);
+ if (!method)
+ return NULL;
+
+ /* Create a new callsite record. */
+ site = (JSCallsite *) malloc(sizeof(JSCallsite));
+ if (!site)
+ return NULL;
+
+ /* Insert the new site into the tree. */
+ site->pc = pc;
+ site->name = method;
+ site->library = info.dli_fname;
+ site->offset = offset;
+ site->parent = parent;
+ site->siblings = parent->kids;
+ parent->kids = site;
+ site->kids = NULL;
+
+ upward:
+ parent = site;
+ bpdown = bp;
+ bp = bpup;
+ } while (bp);
+
+ return site;
}
-static void dprintf(const char *format, ...)
+JSCallsite *
+JS_Backtrace(int skip)
{
- va_list ap;
- char *buffer;
-
- va_start(ap, format);
- buffer = (char *)JS_vsmprintf(format, ap);
- va_end(ap);
+ jmp_buf jb;
+ uint32 *bp, *bpdown;
+
+ setjmp(jb);
+
+ /* Stack walking code adapted from Kipp's "leaky". */
+ bp = (uint32*) jb[0].__jmpbuf[JB_BP];
+ while (--skip >= 0) {
+ bpdown = (uint32*) *bp++;
+ if (bpdown < bp)
+ break;
+ bp = bpdown;
+ }
- jsdebugstr(buffer);
- JS_smprintf_free(buffer);
+ return CallTree(bp);
}
-#endif /* XP_MAC */
-JS_PUBLIC_API(void) JS_Assert(const char *s, const char *file, JSIntn ln)
-{
-#ifdef XP_MAC
- dprintf("Assertion failure: %s, at %s:%d\n", s, file, ln);
-#else
- fprintf(stderr, "Assertion failure: %s, at %s:%d\n", s, file, ln);
-#endif
-#if defined(WIN32)
- DebugBreak();
-#endif
-#if defined(XP_OS2)
- asm("int $3");
-#endif
-#ifndef XP_MAC
- abort();
-#endif
-}
+#endif /* DEBUG_notme && XP_UNIX */