jsinterp.c
来自「java script test programing source code」· C语言 代码 · 共 1,863 行 · 第 1/5 页
C
1,863 行
uint32 recycled; /* LRU-recycled calls lost */ uint16 minargc; /* minimum argument count */ uint16 maxargc; /* maximum argument count */ struct ArgInfo { uint32 typeHist[NTYPEHIST]; /* histogram by type */ JSCList lruList; /* top 10 values LRU list */ struct ArgValCount { JSCList lruLink; /* LRU list linkage */ jsval value; /* recently passed value */ uint32 count; /* number of times passed */ char strbuf[112]; /* string conversion buffer */ } topValCounts[10]; /* top 10 value storage */ } argInfo[8];} CallValue;typedef struct CallEntry { JSHashEntry entry; CallKey key; CallValue value; char name[32]; /* function name copy */} CallEntry;static void *AllocCallTable(void *pool, size_t size){ return malloc(size);}static voidFreeCallTable(void *pool, void *item){ free(item);}static JSHashEntry *AllocCallEntry(void *pool, const void *key){ return (JSHashEntry*) calloc(1, sizeof(CallEntry));}static voidFreeCallEntry(void *pool, JSHashEntry *he, uintN flag){ JS_ASSERT(flag == HT_FREE_ENTRY); free(he);}static JSHashAllocOps callTableAllocOps = { AllocCallTable, FreeCallTable, AllocCallEntry, FreeCallEntry};JS_STATIC_DLL_CALLBACK(JSHashNumber)js_hash_call_key(const void *key){ CallKey *ck = (CallKey *) key; JSHashNumber hash = (jsuword)ck->callee >> 3; if (ck->filename) { hash = (hash << 4) ^ JS_HashString(ck->filename); hash = (hash << 4) ^ ck->lineno; } return hash;}JS_STATIC_DLL_CALLBACK(intN)js_compare_call_keys(const void *k1, const void *k2){ CallKey *ck1 = (CallKey *)k1, *ck2 = (CallKey *)k2; return ck1->callee == ck2->callee && ((ck1->filename && ck2->filename) ? strcmp(ck1->filename, ck2->filename) == 0 : ck1->filename == ck2->filename) && ck1->lineno == ck2->lineno;}JSHashTable *js_CallTable;size_t js_LogCallToSourceLimit;JS_STATIC_DLL_CALLBACK(intN)CallTableDumper(JSHashEntry *he, intN k, void *arg){ CallEntry *ce = (CallEntry *)he; FILE *fp = (FILE *)arg; uintN argc, i, n; struct ArgInfo *ai; JSType save, type; JSCList *cl; struct ArgValCount *avc; jsval argval; if (ce->key.filename) { /* We're called at the end of the mark phase, so mark our filenames. */ js_MarkScriptFilename(ce->key.filename); fprintf(fp, "%s:%u ", ce->key.filename, ce->key.lineno); } else { fprintf(fp, "@%p ", (void *) ce->key.callee); } if (ce->name[0]) fprintf(fp, "name %s ", ce->name); fprintf(fp, "calls %lu (%lu) argc %u/%u\n", (unsigned long) ce->value.total, (unsigned long) ce->value.recycled, ce->value.minargc, ce->value.maxargc); argc = JS_MIN(ce->value.maxargc, 8); for (i = 0; i < argc; i++) { ai = &ce->value.argInfo[i]; n = 0; save = -1; for (type = JSTYPE_VOID; type <= JSTYPE_LIMIT; type++) { if (ai->typeHist[type]) { save = type; ++n; } } if (n == 1) { fprintf(fp, " arg %u type %s: %lu\n", i, TYPENAME(save), (unsigned long) ai->typeHist[save]); } else { fprintf(fp, " arg %u type histogram:\n", i); for (type = JSTYPE_VOID; type <= JSTYPE_LIMIT; type++) { fprintf(fp, " %9s: %8lu ", TYPENAME(type), (unsigned long) ai->typeHist[type]); for (n = (uintN) JS_HOWMANY(ai->typeHist[type], 10); n > 0; --n) fputc('*', fp); fputc('\n', fp); } } fprintf(fp, " arg %u top 10 values:\n", i); n = 1; for (cl = ai->lruList.prev; cl != &ai->lruList; cl = cl->prev) { avc = (struct ArgValCount *)cl; if (!avc->count) break; argval = avc->value; fprintf(fp, " %9u: %8lu %.*s (%#lx)\n", n, (unsigned long) avc->count, sizeof avc->strbuf, avc->strbuf, argval); ++n; } } return HT_ENUMERATE_NEXT;}voidjs_DumpCallTable(JSContext *cx){ char name[24]; FILE *fp; static uintN dumpCount; if (!js_CallTable) return; JS_snprintf(name, sizeof name, "/tmp/calltable.dump.%u", dumpCount & 7); dumpCount++; fp = fopen(name, "w"); if (!fp) return; JS_HashTableEnumerateEntries(js_CallTable, CallTableDumper, fp); fclose(fp);}static voidLogCall(JSContext *cx, jsval callee, uintN argc, jsval *argv){ CallKey key; const char *name, *cstr; JSFunction *fun; JSHashNumber keyHash; JSHashEntry **hep, *he; CallEntry *ce; uintN i, j; jsval argval; JSType type; struct ArgInfo *ai; struct ArgValCount *avc; JSString *str; if (!js_CallTable) { js_CallTable = JS_NewHashTable(1024, js_hash_call_key, js_compare_call_keys, NULL, &callTableAllocOps, NULL); if (!js_CallTable) return; } key.callee = callee; key.filename = NULL; key.lineno = 0; name = ""; if (VALUE_IS_FUNCTION(cx, callee)) { fun = (JSFunction *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(callee)); if (fun->atom) name = js_AtomToPrintableString(cx, fun->atom); if (FUN_INTERPRETED(fun)) { key.filename = fun->u.i.script->filename; key.lineno = fun->u.i.script->lineno; } } keyHash = js_hash_call_key(&key); hep = JS_HashTableRawLookup(js_CallTable, keyHash, &key); he = *hep; if (he) { ce = (CallEntry *) he; JS_ASSERT(strncmp(ce->name, name, sizeof ce->name) == 0); } else { he = JS_HashTableRawAdd(js_CallTable, hep, keyHash, &key, NULL); if (!he) return; ce = (CallEntry *) he; ce->entry.key = &ce->key; ce->entry.value = &ce->value; ce->key = key; for (i = 0; i < 8; i++) { ai = &ce->value.argInfo[i]; JS_INIT_CLIST(&ai->lruList); for (j = 0; j < 10; j++) JS_APPEND_LINK(&ai->topValCounts[j].lruLink, &ai->lruList); } strncpy(ce->name, name, sizeof ce->name); } ++ce->value.total; if (ce->value.minargc < argc) ce->value.minargc = argc; if (ce->value.maxargc < argc) ce->value.maxargc = argc; if (argc > 8) argc = 8; for (i = 0; i < argc; i++) { ai = &ce->value.argInfo[i]; argval = argv[i]; type = TYPEOF(cx, argval); ++ai->typeHist[type]; for (j = 0; ; j++) { if (j == 10) { avc = (struct ArgValCount *) ai->lruList.next; ce->value.recycled += avc->count; avc->value = argval; avc->count = 1; break; } avc = &ai->topValCounts[j]; if (avc->value == argval) { ++avc->count; break; } } /* Move avc to the back of the LRU list. */ JS_REMOVE_LINK(&avc->lruLink); JS_APPEND_LINK(&avc->lruLink, &ai->lruList); str = NULL; cstr = ""; switch (TYPEOF(cx, argval)) { case JSTYPE_VOID: cstr = js_type_str[JSTYPE_VOID]; break; case JSTYPE_NULL: cstr = js_null_str; break; case JSTYPE_BOOLEAN: cstr = js_boolean_str[JSVAL_TO_BOOLEAN(argval)]; break; case JSTYPE_NUMBER: if (JSVAL_IS_INT(argval)) { JS_snprintf(avc->strbuf, sizeof avc->strbuf, "%ld", JSVAL_TO_INT(argval)); } else { JS_dtostr(avc->strbuf, sizeof avc->strbuf, DTOSTR_STANDARD, 0, *JSVAL_TO_DOUBLE(argval)); } continue; case JSTYPE_STRING: str = js_QuoteString(cx, JSVAL_TO_STRING(argval), (jschar)'"'); break; case JSTYPE_FUNCTION: if (VALUE_IS_FUNCTION(cx, argval)) { fun = (JSFunction *)JS_GetPrivate(cx, JSVAL_TO_OBJECT(argval)); if (fun && fun->atom) { str = ATOM_TO_STRING(fun->atom); break; } } /* FALL THROUGH */ case JSTYPE_OBJECT: js_LogCallToSourceLimit = sizeof avc->strbuf; cx->options |= JSOPTION_LOGCALL_TOSOURCE; str = js_ValueToSource(cx, argval); cx->options &= ~JSOPTION_LOGCALL_TOSOURCE; break; } if (str) cstr = JS_GetStringBytes(str); strncpy(avc->strbuf, cstr, sizeof avc->strbuf); }}#endif /* DUMP_CALL_TABLE *//* * Conditional assert to detect failure to clear a pending exception that is * suppressed (or unintentional suppression of a wanted exception). */#if defined DEBUG_brendan || defined DEBUG_mrbkap || defined DEBUG_shaver# define DEBUG_NOT_THROWING 1#endif#ifdef DEBUG_NOT_THROWING# define ASSERT_NOT_THROWING(cx) JS_ASSERT(!(cx)->throwing)#else# define ASSERT_NOT_THROWING(cx) /* nothing */#endif/* * Find a function reference and its 'this' object implicit first parameter * under argc arguments on cx's stack, and call the function. Push missing * required arguments, allocate declared local variables, and pop everything * when done. Then push the return value. */JS_FRIEND_API(JSBool)js_Invoke(JSContext *cx, uintN argc, uintN flags){ void *mark; JSStackFrame *fp, frame; jsval *sp, *newsp, *limit; jsval *vp, v, thisv; JSObject *funobj, *parent, *thisp; JSBool ok; JSClass *clasp; JSObjectOps *ops; JSNative native; JSFunction *fun; JSScript *script; uintN nslots, nvars, nalloc, surplus; JSInterpreterHook hook; void *hookData; /* Mark the top of stack and load frequently-used registers. */ mark = JS_ARENA_MARK(&cx->stackPool); fp = cx->fp; sp = fp->sp; /* * Set vp to the callee value's stack slot (it's where rval goes). * Once vp is set, control should flow through label out2: to return. * Set frame.rval early so native class and object ops can throw and * return false, causing a goto out2 with ok set to false. */ vp = sp - (2 + argc); v = *vp; frame.rval = JSVAL_VOID; /* * A callee must be an object reference, unless its 'this' parameter * implements the __noSuchMethod__ method, in which case that method will * be called like so: * * thisp.__noSuchMethod__(id, args) * * where id is the name of the method that this invocation attempted to * call by name, and args is an Array containing this invocation's actual
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?