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 + -
显示快捷键?