📄 gen.java
字号:
do {
while (keys[i] < pivot)
i++;
while (pivot < keys[j])
j--;
if (i <= j) {
int temp1 = keys[i];
keys[i] = keys[j];
keys[j] = temp1;
int temp2 = values[i];
values[i] = values[j];
values[j] = temp2;
i++;
j--;
}
} while (i <= j)
;
if (lo < j)
qsort2(keys, values, lo, j);
if (i < hi)
qsort2(keys, values, i, hi);
}
public void visitSynchronized(Synchronized tree) {
int limit = code.nextreg;
final Item lockVar = makeTemp(syms.objectType);
genExpr(tree.lock, tree.lock.type).load().duplicate();
lockVar.store();
code.emitop(monitorenter);
final Env syncEnv = env.dup(tree, new GenContext());
((Gen.GenContext) syncEnv.info).finalize = new GenFinalizer() {
void gen() {
genLast();
assert ((Gen.GenContext) syncEnv.info).gaps.length() % 2 == 0;
((Gen.GenContext) syncEnv.info).gaps.append(
new Integer(code.curPc()));
}
void genLast() {
lockVar.load();
code.emitop(monitorexit);
}
};
((Gen.GenContext) syncEnv.info).gaps = new ListBuffer();
genTry(tree.body, Catch.emptyList, syncEnv);
code.endScopes(limit);
}
public void visitTry(final Try tree) {
final Env tryEnv = env.dup(tree, new GenContext());
final Env oldEnv = env;
final boolean useJsrLocally = jsrlimit <= 0 || jsrlimit < 100 &&
estimateCodeComplexity(tree.finalizer) > jsrlimit;
((Gen.GenContext) tryEnv.info).finalize = new GenFinalizer() {
void gen() {
if (useJsrLocally) {
if (tree.finalizer != null) {
((Gen.GenContext) tryEnv.info).cont =
new Chain(code.emitJump(jsr),
code.stacksize + 1,
((Gen.GenContext) tryEnv.info).cont,
varDebugInfo ? code.defined.dup() : null);
}
assert ((Gen.GenContext) tryEnv.info).gaps.length()
% 2 == 0;
((Gen.GenContext) tryEnv.info).gaps.append(
new Integer(code.curPc()));
} else {
assert ((Gen.GenContext) tryEnv.info).gaps.length()
% 2 == 0;
((Gen.GenContext) tryEnv.info).gaps.append(
new Integer(code.curPc()));
genLast();
}
}
void genLast() {
if (tree.finalizer != null)
genStat(tree.finalizer, oldEnv, CRT_BLOCK);
}
boolean hasFinalizer() {
return tree.finalizer != null;
}
};
((Gen.GenContext) tryEnv.info).gaps = new ListBuffer();
genTry(tree.body, tree.catchers, tryEnv);
}
/**
* Generate code for a try or synchronized statement
* @param body The body of the try or synchronized statement.
* @param catchers The lis of catch clauses.
* @param env the environment current for the body.
*/
void genTry(Tree body, List catchers, Env env) {
int limit = code.nextreg;
int startpc = code.curPc();
Bits definedTry = varDebugInfo ? code.defined.dup() : null;
genStat(body, env, CRT_BLOCK);
int endpc = code.curPc();
boolean hasFinalizer = ((Gen.GenContext) env.info).finalize != null &&
((Gen.GenContext) env.info).finalize.hasFinalizer();
if (startpc == endpc) {
if (hasFinalizer) {
code.statBegin(TreeInfo.finalizerPos(env.tree));
code.markStatBegin();
((Gen.GenContext) env.info).finalize.genLast();
}
} else {
List gaps = ((Gen.GenContext) env.info).gaps.toList();
code.statBegin(TreeInfo.endPos(body));
genFinalizer(env);
code.statBegin(TreeInfo.endPos(env.tree));
Chain exitChain = code.branch(goto_);
endFinalizerGap(env);
for (List l = catchers; l.nonEmpty(); l = l.tail) {
code.entryPoint(1);
code.setDefined(definedTry);
genCatch((Tree.Catch) l.head, env, startpc, endpc, gaps);
genFinalizer(env);
if (hasFinalizer || l.tail.nonEmpty()) {
code.statBegin(TreeInfo.endPos(env.tree));
exitChain = code.mergeChains(exitChain, code.branch(goto_));
}
endFinalizerGap(env);
}
if (hasFinalizer) {
code.newRegSegment();
int catchallpc = code.entryPoint(1);
code.setDefined(definedTry);
int startseg = startpc;
while (((Gen.GenContext) env.info).gaps.nonEmpty()) {
int endseg = ((Integer)((Gen.GenContext) env.info).gaps.next()).
intValue();
registerCatch(body.pos, startseg, endseg, catchallpc, 0);
startseg = ((Integer)((Gen.GenContext) env.info).gaps.next()).
intValue();
}
code.statBegin(TreeInfo.finalizerPos(env.tree));
code.markStatBegin();
Item excVar = makeTemp(syms.throwableType);
excVar.store();
genFinalizer(env);
excVar.load();
registerCatch(body.pos, startseg,
((Integer)((Gen.GenContext) env.info).gaps.next()).
intValue(), catchallpc, 0);
code.emitop(athrow);
code.markDead();
if (((Gen.GenContext) env.info).cont != null) {
code.resolve(((Gen.GenContext) env.info).cont);
code.statBegin(TreeInfo.finalizerPos(env.tree));
code.markStatBegin();
LocalItem retVar = makeTemp(syms.throwableType);
retVar.store();
((Gen.GenContext) env.info).finalize.genLast();
code.emitop1w(ret, retVar.reg);
code.markDead();
}
}
code.resolve(exitChain);
code.endScopes(limit);
}
}
/**
* Generate code for a catch clause.
* @param tree The catch clause.
* @param env The environment current in the enclosing try.
* @param startpc Start pc of try-block.
* @param endpc End pc of try-block.
*/
void genCatch(Catch tree, Env env, int startpc, int endpc, List gaps) {
if (startpc != endpc) {
int catchType = makeRef(tree.pos, tree.param.type);
while (gaps.nonEmpty()) {
int end = ((Integer) gaps.head).intValue();
registerCatch(tree.pos, startpc, end, code.curPc(), catchType);
gaps = gaps.tail;
startpc = ((Integer) gaps.head).intValue();
gaps = gaps.tail;
}
if (startpc < endpc)
registerCatch(tree.pos, startpc, endpc, code.curPc(), catchType);
VarSymbol exparam = tree.param.sym;
code.statBegin(tree.pos);
code.markStatBegin();
int limit = code.nextreg;
int exlocal = code.newLocal(exparam);
items.makeLocalItem(exparam).store();
code.setDefined(exlocal);
code.statBegin(TreeInfo.firstStatPos(tree.body));
genStat(tree.body, env, CRT_BLOCK);
code.endScopes(limit);
code.statBegin(TreeInfo.endPos(tree.body));
}
}
/**
* Register a catch clause in the "Exceptions" code-atttribute.
*/
void registerCatch(int pos, int startpc, int endpc, int handler_pc,
int catch_type) {
if (startpc != endpc) {
char startpc1 = (char) startpc;
char endpc1 = (char) endpc;
char handler_pc1 = (char) handler_pc;
if (startpc1 == startpc && endpc1 == endpc && handler_pc1 == handler_pc) {
code.addCatch(startpc1, endpc1, handler_pc1, (char) catch_type);
} else {
log.error(pos, "limit.code.too.large.for.try.stmt");
nerrs++;
}
}
}
/**
* Very roughly estimate the number of instructions needed for
* the given tree.
*/
int estimateCodeComplexity(Tree tree) {
if (tree == null)
return 0;
class ComplexityScanner extends TreeScanner {
ComplexityScanner() {
super();
}
int complexity = 0;
public void scan(Tree tree) {
if (complexity > jsrlimit)
return;
super.scan(tree);
}
public void visitClassDef(ClassDef tree) {
}
public void visitDoLoop(DoLoop tree) {
super.visitDoLoop(tree);
complexity++;
}
public void visitWhileLoop(WhileLoop tree) {
super.visitWhileLoop(tree);
complexity++;
}
public void visitForLoop(ForLoop tree) {
super.visitForLoop(tree);
complexity++;
}
public void visitSwitch(Switch tree) {
super.visitSwitch(tree);
complexity += 5;
}
public void visitCase(Case tree) {
super.visitCase(tree);
complexity++;
}
public void visitSynchronized(Synchronized tree) {
super.visitSynchronized(tree);
complexity += 6;
}
public void visitTry(Try tree) {
super.visitTry(tree);
if (tree.finalizer != null)
complexity += 6;
}
public void visitCatch(Catch tree) {
super.visitCatch(tree);
complexity += 2;
}
public void visitConditional(Conditional tree) {
super.visitConditional(tree);
complexity += 2;
}
public void visitIf(If tree) {
super.visitIf(tree);
complexity += 2;
}
public void visitBreak(Break tree) {
super.visitBreak(tree);
complexity += 1;
}
public void visitContinue(Continue tree) {
super.visitContinue(tree);
complexity += 1;
}
public void visitReturn(Return tree) {
super.visitReturn(tree);
complexity += 1;
}
public void visitThrow(Throw tree) {
super.visitThrow(tree);
complexity += 1;
}
public void visitAssert(Assert tree) {
super.visitAssert(tree);
complexity += 5;
}
public void visitApply(Apply tree) {
super.visitApply(tree);
complexity += 2;
}
public void visitNewClass(NewClass tree) {
scan(tree.encl);
scan(tree.args);
complexity += 2;
}
public void visitNewArray(NewArray tree) {
super.visitNewArray(tree);
complexity += 5;
}
public void visitAssign(Assign tree) {
super.visitAssign(tree);
complexity += 1;
}
public void visitAssignop(Assignop tree) {
super.visitAssignop(tree);
complexity += 2;
}
public void visitUnary(Unary tree) {
complexity += 1;
if (tree.type.constValue == null)
super.visitUnary(tree);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -