📄 jsemit.c
字号:
}typedef struct AddJumpTargetArgs { JSContext *cx; JSCodeGenerator *cg; ptrdiff_t offset; JSJumpTarget *node;} AddJumpTargetArgs;static intAddJumpTarget(AddJumpTargetArgs *args, JSJumpTarget **jtp){ JSJumpTarget *jt; int balanceDelta; jt = *jtp; if (!jt) { JSCodeGenerator *cg = args->cg; jt = cg->jtFreeList; if (jt) { cg->jtFreeList = jt->kids[JT_LEFT]; } else { JS_ARENA_ALLOCATE_CAST(jt, JSJumpTarget *, &args->cx->tempPool, sizeof *jt); if (!jt) { JS_ReportOutOfMemory(args->cx); return 0; } } jt->offset = args->offset; jt->balance = 0; jt->kids[JT_LEFT] = jt->kids[JT_RIGHT] = NULL; cg->numJumpTargets++; args->node = jt; *jtp = jt; return 1; } if (jt->offset == args->offset) { args->node = jt; return 0; } if (args->offset < jt->offset) balanceDelta = -AddJumpTarget(args, &jt->kids[JT_LEFT]); else balanceDelta = AddJumpTarget(args, &jt->kids[JT_RIGHT]); if (!args->node) return 0; jt->balance += balanceDelta; return (balanceDelta && jt->balance) ? 1 - BalanceJumpTargets(jtp) : 0;}#ifdef DEBUG_brendanstatic int AVLCheck(JSJumpTarget *jt){ int lh, rh; if (!jt) return 0; JS_ASSERT(-1 <= jt->balance && jt->balance <= 1); lh = AVLCheck(jt->kids[JT_LEFT]); rh = AVLCheck(jt->kids[JT_RIGHT]); JS_ASSERT(jt->balance == rh - lh); return 1 + JS_MAX(lh, rh);}#endifstatic JSBoolSetSpanDepTarget(JSContext *cx, JSCodeGenerator *cg, JSSpanDep *sd, ptrdiff_t off){ AddJumpTargetArgs args; if (off < JUMPX_OFFSET_MIN || JUMPX_OFFSET_MAX < off) { ReportStatementTooLarge(cx, cg); return JS_FALSE; } args.cx = cx; args.cg = cg; args.offset = sd->top + off; args.node = NULL; AddJumpTarget(&args, &cg->jumpTargets); if (!args.node) return JS_FALSE;#ifdef DEBUG_brendan AVLCheck(cg->jumpTargets);#endif SD_SET_TARGET(sd, args.node); return JS_TRUE;}#define SPANDEPS_MIN 256#define SPANDEPS_SIZE(n) ((n) * sizeof(JSSpanDep))#define SPANDEPS_SIZE_MIN SPANDEPS_SIZE(SPANDEPS_MIN)static JSBoolAddSpanDep(JSContext *cx, JSCodeGenerator *cg, jsbytecode *pc, jsbytecode *pc2, ptrdiff_t off){ uintN index; JSSpanDep *sdbase, *sd; size_t size; index = cg->numSpanDeps; if (index + 1 == 0) { ReportStatementTooLarge(cx, cg); return JS_FALSE; } if ((index & (index - 1)) == 0 && (!(sdbase = cg->spanDeps) || index >= SPANDEPS_MIN)) { if (!sdbase) { size = SPANDEPS_SIZE_MIN; JS_ARENA_ALLOCATE_CAST(sdbase, JSSpanDep *, &cx->tempPool, size); } else { size = SPANDEPS_SIZE(index); JS_ARENA_GROW_CAST(sdbase, JSSpanDep *, &cx->tempPool, size, size); } if (!sdbase) return JS_FALSE; cg->spanDeps = sdbase; } cg->numSpanDeps = index + 1; sd = cg->spanDeps + index; sd->top = PTRDIFF(pc, CG_BASE(cg), jsbytecode); sd->offset = sd->before = PTRDIFF(pc2, CG_BASE(cg), jsbytecode); if (js_CodeSpec[*pc].format & JOF_BACKPATCH) { /* Jump offset will be backpatched if off is a non-zero "bpdelta". */ if (off != 0) { JS_ASSERT(off >= 1 + JUMP_OFFSET_LEN); if (off > BPDELTA_MAX) { ReportStatementTooLarge(cx, cg); return JS_FALSE; } } SD_SET_BPDELTA(sd, off); } else if (off == 0) { /* Jump offset will be patched directly, without backpatch chaining. */ SD_SET_TARGET(sd, NULL); } else { /* The jump offset in off is non-zero, therefore it's already known. */ if (!SetSpanDepTarget(cx, cg, sd, off)) return JS_FALSE; } if (index > SPANDEP_INDEX_MAX) index = SPANDEP_INDEX_HUGE; SET_SPANDEP_INDEX(pc2, index); return JS_TRUE;}static JSBoolBuildSpanDepTable(JSContext *cx, JSCodeGenerator *cg){ jsbytecode *pc, *end; JSOp op; const JSCodeSpec *cs; ptrdiff_t len, off; pc = CG_BASE(cg) + cg->spanDepTodo; end = CG_NEXT(cg); while (pc < end) { op = (JSOp)*pc; cs = &js_CodeSpec[op]; len = (ptrdiff_t)cs->length; switch (cs->format & JOF_TYPEMASK) { case JOF_JUMP: off = GET_JUMP_OFFSET(pc); if (!AddSpanDep(cx, cg, pc, pc, off)) return JS_FALSE; break; case JOF_TABLESWITCH: { jsbytecode *pc2; jsint i, low, high; pc2 = pc; off = GET_JUMP_OFFSET(pc2); if (!AddSpanDep(cx, cg, pc, pc2, off)) return JS_FALSE; pc2 += JUMP_OFFSET_LEN; low = GET_JUMP_OFFSET(pc2); pc2 += JUMP_OFFSET_LEN; high = GET_JUMP_OFFSET(pc2); pc2 += JUMP_OFFSET_LEN; for (i = low; i <= high; i++) { off = GET_JUMP_OFFSET(pc2); if (!AddSpanDep(cx, cg, pc, pc2, off)) return JS_FALSE; pc2 += JUMP_OFFSET_LEN; } len = 1 + pc2 - pc; break; } case JOF_LOOKUPSWITCH: { jsbytecode *pc2; jsint npairs; pc2 = pc; off = GET_JUMP_OFFSET(pc2); if (!AddSpanDep(cx, cg, pc, pc2, off)) return JS_FALSE; pc2 += JUMP_OFFSET_LEN; npairs = (jsint) GET_ATOM_INDEX(pc2); pc2 += ATOM_INDEX_LEN; while (npairs) { pc2 += ATOM_INDEX_LEN; off = GET_JUMP_OFFSET(pc2); if (!AddSpanDep(cx, cg, pc, pc2, off)) return JS_FALSE; pc2 += JUMP_OFFSET_LEN; npairs--; } len = 1 + pc2 - pc; break; } } JS_ASSERT(len > 0); pc += len; } return JS_TRUE;}static JSSpanDep *GetSpanDep(JSCodeGenerator *cg, jsbytecode *pc){ uintN index; ptrdiff_t offset; int lo, hi, mid; JSSpanDep *sd; index = GET_SPANDEP_INDEX(pc); if (index != SPANDEP_INDEX_HUGE) return cg->spanDeps + index; offset = PTRDIFF(pc, CG_BASE(cg), jsbytecode); lo = 0; hi = cg->numSpanDeps - 1; while (lo <= hi) { mid = (lo + hi) / 2; sd = cg->spanDeps + mid; if (sd->before == offset) return sd; if (sd->before < offset) lo = mid + 1; else hi = mid - 1; } JS_ASSERT(0); return NULL;}static JSBoolSetBackPatchDelta(JSContext *cx, JSCodeGenerator *cg, jsbytecode *pc, ptrdiff_t delta){ JSSpanDep *sd; JS_ASSERT(delta >= 1 + JUMP_OFFSET_LEN); if (!cg->spanDeps && delta < JUMP_OFFSET_MAX) { SET_JUMP_OFFSET(pc, delta); return JS_TRUE; } if (delta > BPDELTA_MAX) { ReportStatementTooLarge(cx, cg); return JS_FALSE; } if (!cg->spanDeps && !BuildSpanDepTable(cx, cg)) return JS_FALSE; sd = GetSpanDep(cg, pc); JS_ASSERT(SD_GET_BPDELTA(sd) == 0); SD_SET_BPDELTA(sd, delta); return JS_TRUE;}static voidUpdateJumpTargets(JSJumpTarget *jt, ptrdiff_t pivot, ptrdiff_t delta){ if (jt->offset > pivot) { jt->offset += delta; if (jt->kids[JT_LEFT]) UpdateJumpTargets(jt->kids[JT_LEFT], pivot, delta); } if (jt->kids[JT_RIGHT]) UpdateJumpTargets(jt->kids[JT_RIGHT], pivot, delta);}static JSSpanDep *FindNearestSpanDep(JSCodeGenerator *cg, ptrdiff_t offset, int lo, JSSpanDep *guard){ int num, hi, mid; JSSpanDep *sdbase, *sd; num = cg->numSpanDeps; JS_ASSERT(num > 0); hi = num - 1; sdbase = cg->spanDeps; while (lo <= hi) { mid = (lo + hi) / 2; sd = sdbase + mid; if (sd->before == offset) return sd; if (sd->before < offset) lo = mid + 1; else hi = mid - 1; } if (lo == num) return guard; sd = sdbase + lo; JS_ASSERT(sd->before >= offset && (lo == 0 || sd[-1].before < offset)); return sd;}static voidFreeJumpTargets(JSCodeGenerator *cg, JSJumpTarget *jt){ if (jt->kids[JT_LEFT]) FreeJumpTargets(cg, jt->kids[JT_LEFT]); if (jt->kids[JT_RIGHT]) FreeJumpTargets(cg, jt->kids[JT_RIGHT]); jt->kids[JT_LEFT] = cg->jtFreeList; cg->jtFreeList = jt;}static JSBoolOptimizeSpanDeps(JSContext *cx, JSCodeGenerator *cg){ jsbytecode *pc, *oldpc, *base, *limit, *next; JSSpanDep *sd, *sd2, *sdbase, *sdlimit, *sdtop, guard; ptrdiff_t offset, growth, delta, top, pivot, span, length, target; JSBool done; JSOp op; uint32 type; size_t size, incr; jssrcnote *sn, *snlimit; JSSrcNoteSpec *spec; uintN i, n, noteIndex; JSTryNote *tn, *tnlimit;#ifdef DEBUG_brendan int passes = 0;#endif base = CG_BASE(cg); sdbase = cg->spanDeps; sdlimit = sdbase + cg->numSpanDeps; offset = CG_OFFSET(cg); growth = 0; do { done = JS_TRUE; delta = 0; top = pivot = -1; sdtop = NULL; pc = NULL; op = JSOP_NOP; type = 0;#ifdef DEBUG_brendan passes++;#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -