javac: optimized for-each over RandomAccess List

Vitaly Davidovich vitalyd at gmail.com
Tue Nov 12 01:08:02 UTC 2013


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" <snazy at 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);
>         }
>
>



More information about the core-libs-dev mailing list