You'd lose the concurrent mod checking that the iterator may do, which would change behavior.
Vitaly Sent from my phone On Nov 11, 2013 1:12 PM, "Robert Stupp" <sn...@gmx.de> wrote: > Hi, > > is it ok to optimize for-each-loop code generation for instances of > java.util.List that also implement java.util.RandomAccess by expanding to > List lst$ = listexpr; > int len$ = lst$.size(); > for (int i$ = 0 ; i$ < len$ ; i$++) { > T loopvar = lst$.get(i$); > <LOOOP-BODY> > } > > I am not sure whether this would break existing code, that relies on > Iterator. RandomAccess declares that access using size()+get(int) are > faster than using an iterator. > > The necessary modifications to > com.sun.tools.javac.comp.Lower#visitForeachLoop may look like this: > > /** Translate away the foreach loop. */ > public void visitForeachLoop(JCEnhancedForLoop tree) { > if (types.elemtype(tree.expr.type) == null) { > if (tree.var.vartype.type.contains(syms.listType) && > tree.var.vartype.type.contains(syms.randomAccessType)) > visitRandomAccessListLoop(tree); > else > visitIterableForeachLoop(tree); > } > else > visitArrayForeachLoop(tree); > } > // where > /** > * A statement of the form > * > * <pre> > * for ( T v : listexpr ) stmt; > * </pre> > * > * (where listexpr is of an randomaccess-list type) gets > translated to > * > * <pre>{@code > * for ( { listtype #lst = listexpr; > * int #len = lst.size(); > * int #i = 0; }; > * #i < #len; i$++ ) { > * T v = lst$.get(#i); > * stmt; > * } > * }</pre> > * > * where #arr, #len, and #i are freshly named synthetic local > variables. > */ > private void visitRandomAccessListLoop(JCEnhancedForLoop tree) { > make_at(tree.expr.pos()); > VarSymbol listcache = new VarSymbol(SYNTHETIC, > names.fromString("lst" + target.syntheticNameChar()), > tree.expr.type, > currentMethodSym); > JCStatement listcachedef = make.VarDef(listcache, tree.expr); > VarSymbol lencache = new VarSymbol(SYNTHETIC, > names.fromString("len" + target.syntheticNameChar()), > syms.intType, > currentMethodSym); > Symbol size = lookupMethod(tree.expr.pos(), > names.size, > tree.expr.type, > List.<Type>nil()); > Symbol get = lookupMethod(tree.expr.pos(), > names.get, > tree.expr.type, > List.<Type>nil()); > JCStatement lencachedef = make. > VarDef(lencache, > make.App(make.Select(make.Ident(listcache), > size))); > VarSymbol index = new VarSymbol(SYNTHETIC, > names.fromString("i" + target.syntheticNameChar()), > syms.intType, > currentMethodSym); > > JCVariableDecl indexdef = make.VarDef(index, make.Literal(INT, > 0)); > indexdef.init.type = indexdef.type = syms.intType.constType(0); > > List<JCStatement> loopinit = List.of(listcachedef, > lencachedef, indexdef); > JCBinary cond = makeBinary(LT, make.Ident(index), > make.Ident(lencache)); > > JCExpressionStatement step = make.Exec(makeUnary(PREINC, > make.Ident(index))); > > Type elemtype = types.elemtype(tree.expr.type); > JCExpression loopvarinit = > make.App(make.Select(make.Ident(listcache), get), > List.of(make.Ident(indexdef))); > JCVariableDecl loopvardef = > (JCVariableDecl)make.VarDef(tree.var.mods, > tree.var.name, > tree.var.vartype, > loopvarinit).setType(tree.var.type); > loopvardef.sym = tree.var.sym; > JCBlock body = make. > Block(0, List.of(loopvardef, tree.body)); > > result = translate(make. > ForLoop(loopinit, > cond, > List.of(step), > body)); > patchTargets(body, tree, result); > } > >