Example usage for org.objectweb.asm Opcodes ISTORE

List of usage examples for org.objectweb.asm Opcodes ISTORE

Introduction

In this page you can find the example usage for org.objectweb.asm Opcodes ISTORE.

Prototype

int ISTORE

To view the source code for org.objectweb.asm Opcodes ISTORE.

Click Source Link

Usage

From source file:com.google.code.jconts.instrument.gen.AsyncMethodAdapter.java

License:Apache License

private void checkProlog() {
    // Generate only once (at the beginning)
    if (prologGenerated) {
        return;//from  ww  w  . j  a  va2 s.c om
    }
    prologGenerated = true;

    // try...catch around the whole body. Should be added last (after all
    // other try..catch blocks).
    // Actually, we are making an assumption that reader will emit
    // visitTryCatchBlock BEFORE generating any bytecode.
    // We cannot call visitTryCatchBlock at the end since it should
    // be called before all its labels are visited (which we generate
    // in this block).
    mv.visitTryCatchBlock(tryLabel, dispatchLabel, catchLabel, null);

    // Goto to table switch dispatcher
    mv.visitJumpInsn(Opcodes.GOTO, dispatchLabel);

    // Wrap the whole original body with try...catch that will invoke
    // cont.setException(Throwable t)
    mv.visitLabel(tryLabel);

    // Restore the frame as it was before changing method arguments
    Type[] locs = info.entryLocals;
    Object[] frame = new Object[info.isStatic() ? locs.length : locs.length + 1];

    // Frame
    if (!info.isStatic()) {
        frame[0] = info.owner;
    }

    int off = info.isStatic() ? 0 : 1;
    for (int i = 0; i < locs.length; ++i) {
        frame[off + i] = Frames.toFrameType(locs[i]);
    }

    mv.visitFrame(Opcodes.F_FULL, frame.length, frame, 0, new Object[0]);
    Label label = new Label();
    dispatchTable.add(label);
    mv.visitLabel(label);

    if (!info.isStatic()) {
        locals.add(Type.getObjectType(info.owner));
    }
    Collections.addAll(locals, locs);

    // Restore the original method arguments
    // argX = state.varX
    String[] names = info.entryLocalsVars;
    for (int i = 0; i < info.entryLocals.length; ++i) {
        // We go directly to target, introduced var used
        target.visitVarInsn(Opcodes.ALOAD, info.isStatic() ? 0 : 1);
        mv.visitFieldInsn(Opcodes.GETFIELD, info.stateClassName, names[i], info.entryLocals[i].getDescriptor());
        mv.visitVarInsn(info.entryLocals[i].getOpcode(Opcodes.ISTORE), info.isStatic() ? i : i + 1);

    }
}

From source file:com.google.code.jconts.instrument.gen.AsyncMethodAdapter.java

License:Apache License

@Override
public void visitMethodInsn(int opcode, String owner, String name, String desc) {
    checkProlog();//from w  w  w . j  av a2 s . c om

    if (opcode == Opcodes.INVOKESTATIC && ASYNC_NAME.equals(owner) && ARETURN_NAME.equals(name)) {

        if (ARETURN_VOID_DESC.equals(desc)) {
            mv.visitInsn(Opcodes.ACONST_NULL);
        }

        // state variable
        target.visitVarInsn(Opcodes.ALOAD, info.isStatic() ? 0 : 1);
        mv.visitFieldInsn(Opcodes.GETFIELD, info.stateClassName, CONTINUATION_FIELD, CONTINUATION_DESC);
        mv.visitInsn(Opcodes.SWAP);
        mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, CONTINUATION_NAME, CONTINUATION_INVOKE_NAME,
                CONTINUATION_INVOKE_DESC);

        // Will be dropped while replacing ARETURN with RETURN.
        // FIXME: Should verify this value is NOT used.
        mv.visitInsn(Opcodes.ACONST_NULL);
        return;
    }
    if (opcode == Opcodes.INVOKESTATIC && ASYNC_NAME.equals(owner) && AWAIT_NAME.equals(name)
            && AWAIT_DESC.equals(desc)) {

        // Computation<T> is on stack

        // FIXME: ...
        // if (stack.size() != 1) {
        // throw new IllegalStateException(
        // "Stack preserving is not supported!");
        // }

        int index = dispatchTable.size();

        // Save state
        List<Type> l = new ArrayList<Type>(locals);
        if (!info.isStatic()) {
            l.remove(0);
        }

        // state.varX = locX
        String[] vars = info.tracker.stateFields(l.toArray(new Type[0]));
        for (int i = 0; i < vars.length; ++i) {
            // state variable
            target.visitVarInsn(Opcodes.ALOAD, info.isStatic() ? 0 : 1);
            mv.visitVarInsn(l.get(i).getOpcode(Opcodes.ILOAD), i + info.thisOffset);
            mv.visitFieldInsn(Opcodes.PUTFIELD, info.stateClassName, vars[i], l.get(i).getDescriptor());
        }

        // Create instance of continuation
        // new Continuation([this, ]state, index);
        mv.visitTypeInsn(Opcodes.NEW, info.continuationClassName);
        mv.visitInsn(Opcodes.DUP);

        // "this' for new Continuation([this, ]state, index)
        if (!info.isStatic()) {
            mv.visitVarInsn(Opcodes.ALOAD, 0);
        }

        // state and index
        target.visitVarInsn(Opcodes.ALOAD, 0 + info.thisOffset);
        mv.visitIntInsn(Opcodes.BIPUSH, index);

        String ctorDesc;
        if (info.isStatic()) {
            ctorDesc = Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] { info.stateType, Type.INT_TYPE });
        } else {
            ctorDesc = Type.getMethodDescriptor(Type.VOID_TYPE,
                    new Type[] { Type.getObjectType(info.owner), info.stateType, Type.INT_TYPE });
        }
        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, info.continuationClassName, CTOR_NAME, ctorDesc);

        mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, COMPUTATION_NAME, COMPUTATION_EXECUTE_NAME,
                COMPUTATION_EXECUTE_DESC);
        super.visitInsn(Opcodes.RETURN);

        // Restore state
        // mv.visitFrame(Opcodes.F_SAME, 0, new Object[0], 0, new
        // Object[0]);
        Label label = new Label();

        int invokeIndex = dispatchTable.size();
        dispatchTable.add(label); // for invoke
        dispatchTable.add(label); // for setException
        mv.visitLabel(label);
        for (int i = 0; i < vars.length; ++i) {
            // state variable
            target.visitVarInsn(Opcodes.ALOAD, info.isStatic() ? 0 : 1);
            mv.visitFieldInsn(Opcodes.GETFIELD, info.stateClassName, vars[i], l.get(i).getDescriptor());
            mv.visitVarInsn(l.get(i).getOpcode(Opcodes.ISTORE), i + info.thisOffset);
        }

        // if (index == invokeIndex) goto invokeLabel;
        Label invokeLabel = new Label();
        target.visitVarInsn(Opcodes.ILOAD, 1 + info.thisOffset);
        mv.visitIntInsn(Opcodes.BIPUSH, invokeIndex);
        mv.visitJumpInsn(Opcodes.IF_ICMPEQ, invokeLabel);

        // Throw exception
        target.visitVarInsn(Opcodes.ALOAD, info.isStatic() ? 0 : 1);
        mv.visitFieldInsn(Opcodes.GETFIELD, info.stateClassName, "exception", THROWABLE_DESC);
        mv.visitInsn(Opcodes.ATHROW);

        // Push result value
        // invokeLabel:
        mv.visitLabel(invokeLabel);
        target.visitVarInsn(Opcodes.ALOAD, info.isStatic() ? 0 : 1);
        mv.visitFieldInsn(Opcodes.GETFIELD, info.stateClassName, "result", OBJECT_DESC);
        return;
    }
    super.visitMethodInsn(opcode, owner, name, desc);
}

From source file:com.google.devtools.build.android.desugar.BytecodeTypeInference.java

License:Open Source License

@Override
public void visitVarInsn(int opcode, int var) {
    switch (opcode) {
    case Opcodes.ILOAD:
        push(InferredType.INT);/*from w  w w  .  j  av a  2  s.  co  m*/
        break;
    case Opcodes.LLOAD:
        push(InferredType.LONG);
        push(InferredType.TOP);
        break;
    case Opcodes.FLOAD:
        push(InferredType.FLOAT);
        break;
    case Opcodes.DLOAD:
        push(InferredType.DOUBLE);
        push(InferredType.TOP);
        break;
    case Opcodes.ALOAD:
        push(getLocalVariableType(var));
        break;
    case Opcodes.ISTORE:
    case Opcodes.FSTORE:
    case Opcodes.ASTORE: {
        InferredType type = pop();
        setLocalVariableTypes(var, type);
        break;
    }
    case Opcodes.LSTORE:
    case Opcodes.DSTORE: {
        InferredType type = pop(2);
        setLocalVariableTypes(var, type);
        setLocalVariableTypes(var + 1, InferredType.TOP);
        break;
    }
    case Opcodes.RET:
        throw new RuntimeException("The instruction RET is not supported");
    default:
        throw new RuntimeException("Unhandled opcode " + opcode);
    }
    super.visitVarInsn(opcode, var);
}

From source file:com.google.devtools.build.wireless.testing.java.injector.TypeDescriptorTest.java

License:Apache License

/**
 * Test method for {@link TypeDescriptor#getStoreOpcode()}.
 *///from w w w  . ja va  2s.co  m
public void testGetStoreOpcode() {
    try {
        TypeDescriptor.VOID.getStoreOpcode();
        fail("Void should have thrown an exception!");
    } catch (IllegalStateException e) {
        // OK!
    }
    assertEquals("Wrong STORE instruction", Opcodes.ISTORE, TypeDescriptor.BOOLEAN.getStoreOpcode());
    assertEquals("Wrong STORE instruction", Opcodes.ISTORE, TypeDescriptor.BYTE.getStoreOpcode());
    assertEquals("Wrong STORE instruction", Opcodes.ISTORE, TypeDescriptor.CHAR.getStoreOpcode());
    assertEquals("Wrong STORE instruction", Opcodes.ISTORE, TypeDescriptor.SHORT.getStoreOpcode());
    assertEquals("Wrong STORE instruction", Opcodes.ISTORE, TypeDescriptor.INTEGER.getStoreOpcode());
    assertEquals("Wrong STORE instruction", Opcodes.LSTORE, TypeDescriptor.LONG.getStoreOpcode());
    assertEquals("Wrong STORE instruction", Opcodes.FSTORE, TypeDescriptor.FLOAT.getStoreOpcode());
    assertEquals("Wrong STORE instruction", Opcodes.DSTORE, TypeDescriptor.DOUBLE.getStoreOpcode());
    assertEquals("Wrong STORE instruction", Opcodes.ASTORE, TypeDescriptor.CLASS.getStoreOpcode());
    assertEquals("Wrong STORE instruction", Opcodes.ASTORE, TypeDescriptor.ARRAY.getStoreOpcode());
}

From source file:com.google.monitoring.runtime.instrumentation.adapters.AllocationMethodAdapter.java

License:Apache License

private void pushProductOfIntArrayOnStack() {
    final Label beginScopeLabel = new Label();
    final Label endScopeLabel = new Label();

    final int dimsArrayIndex = newLocal("[I", beginScopeLabel, endScopeLabel);
    final int counterIndex = newLocal("I", beginScopeLabel, endScopeLabel);
    final int productIndex = newLocal("I", beginScopeLabel, endScopeLabel);
    final Label loopLabel = new Label();
    final Label endLabel = new Label();

    super.visitLabel(beginScopeLabel);

    // stack: ... intArray
    super.visitVarInsn(Opcodes.ASTORE, dimsArrayIndex);
    // -> stack: ...

    // counter = 0
    super.visitInsn(Opcodes.ICONST_0);
    super.visitVarInsn(Opcodes.ISTORE, counterIndex);
    // product = 1
    super.visitInsn(Opcodes.ICONST_1);
    super.visitVarInsn(Opcodes.ISTORE, productIndex);
    // loop:/*from   w  w w.j a v  a2  s  .c  o  m*/
    super.visitLabel(loopLabel);
    // if index >= arraylength goto end:
    super.visitVarInsn(Opcodes.ILOAD, counterIndex);
    super.visitVarInsn(Opcodes.ALOAD, dimsArrayIndex);
    super.visitInsn(Opcodes.ARRAYLENGTH);
    super.visitJumpInsn(Opcodes.IF_ICMPGE, endLabel);
    // product = product * max(array[counter],1)
    super.visitVarInsn(Opcodes.ALOAD, dimsArrayIndex);
    super.visitVarInsn(Opcodes.ILOAD, counterIndex);
    super.visitInsn(Opcodes.IALOAD);
    super.visitInsn(Opcodes.DUP);
    final Label nonZeroDimension = new Label();
    super.visitJumpInsn(Opcodes.IFNE, nonZeroDimension);
    super.visitInsn(Opcodes.POP);
    super.visitInsn(Opcodes.ICONST_1);
    super.visitLabel(nonZeroDimension);
    super.visitVarInsn(Opcodes.ILOAD, productIndex);
    super.visitInsn(Opcodes.IMUL); // if overflow happens it happens.
    super.visitVarInsn(Opcodes.ISTORE, productIndex);
    // iinc counter 1
    super.visitIincInsn(counterIndex, 1);
    // goto loop
    super.visitJumpInsn(Opcodes.GOTO, loopLabel);
    // end:
    super.visitLabel(endLabel);
    // re-push dimensions array
    super.visitVarInsn(Opcodes.ALOAD, dimsArrayIndex);
    // push product
    super.visitVarInsn(Opcodes.ILOAD, productIndex);

    super.visitLabel(endScopeLabel);
}

From source file:com.google.monitoring.runtime.instrumentation.adapters.AllocationMethodAdapter.java

License:Apache License

/**
 * Reflection-based allocation (@see java.lang.reflect.Array#newInstance) is
 * triggered with a static method call (INVOKESTATIC), so we hook it here.
 * Class initialization is triggered with a constructor call (INVOKESPECIAL)
 * so we hook that here too as a proxy for the new bytecode which leaves an
 * uninitialized object on the stack that we're not allowed to touch.
 * {@link java.lang.Object#clone} is also a call to INVOKESPECIAL,
 * and is hooked here.  {@link java.lang.Class#newInstance} and
 * {@link java.lang.reflect.Constructor#newInstance} are both
 * INVOKEVIRTUAL calls, so they are hooked here, as well.
 *///from   www  .  j a  v a  2 s .  c  o  m
@Override
public void visitMethodInsn(final int opcode, final String owner, final String name, final String signature,
        final boolean itf) {
    if (opcode == Opcodes.INVOKESTATIC &&
    // Array does its own native allocation.  Grr.
            owner.equals("java/lang/reflect/Array") && name.equals("newInstance")) {
        if (signature.equals("(Ljava/lang/Class;I)Ljava/lang/Object;")) {

            final Label beginScopeLabel = new Label();
            final Label endScopeLabel = new Label();
            super.visitLabel(beginScopeLabel);

            // stack: ... class count
            final int countIndex = newLocal("I", beginScopeLabel, endScopeLabel);
            super.visitVarInsn(Opcodes.ISTORE, countIndex);
            // -> stack: ... class
            pushClassNameOnStack();
            // -> stack: ... class className
            final int typeNameIndex = newLocal("Ljava/lang/String;", beginScopeLabel, endScopeLabel);
            super.visitVarInsn(Opcodes.ASTORE, typeNameIndex);
            // -> stack: ... class
            super.visitVarInsn(Opcodes.ILOAD, countIndex);
            // -> stack: ... class count
            super.visitMethodInsn(opcode, owner, name, signature, itf);
            // -> stack: ... newobj
            super.visitInsn(Opcodes.DUP);
            // -> stack: ... newobj newobj
            super.visitVarInsn(Opcodes.ILOAD, countIndex);
            // -> stack: ... newobj newobj count
            super.visitInsn(Opcodes.SWAP);
            // -> stack: ... newobj count newobj
            super.visitVarInsn(Opcodes.ALOAD, typeNameIndex);
            super.visitLabel(endScopeLabel);
            // -> stack: ... newobj count newobj className
            super.visitInsn(Opcodes.SWAP);
            // -> stack: ... newobj count className newobj
            super.visitMethodInsn(Opcodes.INVOKESTATIC, recorderClass, recorderMethod, RECORDER_SIGNATURE,
                    false);
            // -> stack: ... newobj
            return;
        } else if (signature.equals("(Ljava/lang/Class;[I)Ljava/lang/Object;")) {
            final Label beginScopeLabel = new Label();
            final Label endScopeLabel = new Label();
            super.visitLabel(beginScopeLabel);

            final int dimsArrayIndex = newLocal("[I", beginScopeLabel, endScopeLabel);
            // stack: ... class dimsArray
            pushProductOfIntArrayOnStack();
            // -> stack: ... class dimsArray product
            final int productIndex = newLocal("I", beginScopeLabel, endScopeLabel);
            super.visitVarInsn(Opcodes.ISTORE, productIndex);
            // -> stack: ... class dimsArray

            super.visitVarInsn(Opcodes.ASTORE, dimsArrayIndex);
            // -> stack: ... class
            pushClassNameOnStack();
            // -> stack: ... class className
            final int typeNameIndex = newLocal("Ljava/lang/String;", beginScopeLabel, endScopeLabel);
            super.visitVarInsn(Opcodes.ASTORE, typeNameIndex);
            // -> stack: ... class
            super.visitVarInsn(Opcodes.ALOAD, dimsArrayIndex);
            // -> stack: ... class dimsArray
            super.visitMethodInsn(opcode, owner, name, signature, itf);
            // -> stack: ... newobj

            super.visitInsn(Opcodes.DUP);
            // -> stack: ... newobj newobj
            super.visitVarInsn(Opcodes.ILOAD, productIndex);
            // -> stack: ... newobj newobj product
            super.visitInsn(Opcodes.SWAP);
            // -> stack: ... newobj product newobj
            super.visitVarInsn(Opcodes.ALOAD, typeNameIndex);
            super.visitLabel(endScopeLabel);
            // -> stack: ... newobj product newobj className
            super.visitInsn(Opcodes.SWAP);
            // -> stack: ... newobj product className newobj
            super.visitMethodInsn(Opcodes.INVOKESTATIC, recorderClass, recorderMethod, RECORDER_SIGNATURE,
                    false);
            // -> stack: ... newobj
            return;
        }
    }

    if (opcode == Opcodes.INVOKEVIRTUAL) {
        if ("clone".equals(name) && owner.startsWith("[")) {
            super.visitMethodInsn(opcode, owner, name, signature, itf);

            int i = 0;
            while (i < owner.length()) {
                if (owner.charAt(i) != '[') {
                    break;
                }
                i++;
            }
            if (i > 1) {
                // -> stack: ... newobj
                super.visitTypeInsn(Opcodes.CHECKCAST, owner);
                // -> stack: ... arrayref
                calculateArrayLengthAndDispatch(owner.substring(i), i);
            } else {
                // -> stack: ... newobj
                super.visitInsn(Opcodes.DUP);
                // -> stack: ... newobj newobj
                super.visitTypeInsn(Opcodes.CHECKCAST, owner);
                // -> stack: ... newobj arrayref
                super.visitInsn(Opcodes.ARRAYLENGTH);
                // -> stack: ... newobj length
                super.visitInsn(Opcodes.SWAP);
                // -> stack: ... length newobj
                invokeRecordAllocation(owner.substring(i));
            }
            return;
        } else if ("newInstance".equals(name)) {
            if ("java/lang/Class".equals(owner) && "()Ljava/lang/Object;".equals(signature)) {
                super.visitInsn(Opcodes.DUP);
                // -> stack: ... Class Class
                super.visitMethodInsn(opcode, owner, name, signature, itf);
                // -> stack: ... Class newobj
                super.visitInsn(Opcodes.DUP_X1);
                // -> stack: ... newobj Class newobj
                super.visitMethodInsn(Opcodes.INVOKESTATIC, recorderClass, recorderMethod, CLASS_RECORDER_SIG,
                        false);
                // -> stack: ... newobj
                return;
            } else if ("java/lang/reflect/Constructor".equals(owner)
                    && "([Ljava/lang/Object;)Ljava/lang/Object;".equals(signature)) {
                buildRecorderFromObject(opcode, owner, name, signature, itf);
                return;
            }
        }
    }

    if (opcode == Opcodes.INVOKESPECIAL) {
        if ("clone".equals(name) && "java/lang/Object".equals(owner)) {
            buildRecorderFromObject(opcode, owner, name, signature, itf);
            return;
        } else if ("<init>".equals(name) && outstandingAllocs > 0) {
            // Tricky because superclass initializers mean there can be more calls
            // to <init> than calls to NEW; hence outstandingAllocs.
            --outstandingAllocs;

            // Most of the time (i.e. in bytecode generated by javac) it is the case
            // that following an <init> call the top of the stack has a reference ot
            // the newly-initialized object.  But nothing in the JVM Spec requires
            // this, so we need to play games with the stack to make an explicit
            // extra copy (and then discard it).

            dupStackElementBeforeSignatureArgs(signature);
            super.visitMethodInsn(opcode, owner, name, signature, itf);
            super.visitLdcInsn(-1);
            super.visitInsn(Opcodes.SWAP);
            invokeRecordAllocation(owner);
            super.visitInsn(Opcodes.POP);
            return;
        }
    }

    super.visitMethodInsn(opcode, owner, name, signature, itf);
}

From source file:com.google.monitoring.runtime.instrumentation.adapters.AllocationMethodAdapter.java

License:Apache License

private void dupStackElementBeforeSignatureArgs(final String sig) {
    final Label beginScopeLabel = new Label();
    final Label endScopeLabel = new Label();
    super.visitLabel(beginScopeLabel);

    final Type[] argTypes = Type.getArgumentTypes(sig);
    final int[] args = new int[argTypes.length];

    for (int i = argTypes.length - 1; i >= 0; --i) {
        args[i] = newLocal(argTypes[i], beginScopeLabel, endScopeLabel);
        super.visitVarInsn(argTypes[i].getOpcode(Opcodes.ISTORE), args[i]);
    }//www.  j av a  2 s .  c  o m
    super.visitInsn(Opcodes.DUP);
    for (int i = 0; i < argTypes.length; ++i) {
        final int op = argTypes[i].getOpcode(Opcodes.ILOAD);
        super.visitVarInsn(op, args[i]);
        if (op == Opcodes.ALOAD) {
            super.visitInsn(Opcodes.ACONST_NULL);
            super.visitVarInsn(Opcodes.ASTORE, args[i]);
        }
    }
    super.visitLabel(endScopeLabel);
}

From source file:com.google.template.soy.jbcsrc.LocalVariable.java

License:Apache License

/** Writes the value at the top of the stack to the local variable. */
private Statement store(final Expression expr, final Optional<Label> firstVarInstruction) {
    expr.checkAssignableTo(resultType());
    return new Statement() {
        @Override/*w  w w.  j  a  v  a  2 s  . c o m*/
        void doGen(CodeBuilder adapter) {
            expr.gen(adapter);
            if (firstVarInstruction.isPresent()) {
                adapter.mark(firstVarInstruction.get());
            }
            adapter.visitVarInsn(resultType().getOpcode(Opcodes.ISTORE), index());
        }
    };
}

From source file:com.google.template.soy.jbcsrc.restricted.LocalVariable.java

License:Apache License

/** Writes the value at the top of the stack to the local variable. */
private Statement store(final Expression expr, final Optional<Label> firstVarInstruction) {
    expr.checkAssignableTo(resultType());
    return new Statement() {
        @Override/*from   w  ww  . j  av a2s .c  om*/
        protected void doGen(CodeBuilder adapter) {
            expr.gen(adapter);
            if (firstVarInstruction.isPresent()) {
                adapter.mark(firstVarInstruction.get());
            }
            adapter.visitVarInsn(resultType().getOpcode(Opcodes.ISTORE), index());
        }
    };
}

From source file:com.google.template.soy.jbcsrc.SoyNodeCompiler.java

License:Apache License

/**
 * Interprets the given expressions as the arguments of a {@code range(...)} expression in a
 * {@code for} loop./*from  ww w. ja  va 2 s.  c o  m*/
 */
private CompiledRangeArgs calculateRangeArgs(ForNode forNode, Scope scope) {
    RangeArgs rangeArgs = forNode.getRangeArgs();

    final ImmutableList.Builder<Statement> initStatements = ImmutableList.builder();
    final Variable currentIndex;
    if (rangeArgs.start().isPresent()) {
        Label startDetachPoint = new Label();
        Expression startIndex = MethodRef.INTS_CHECKED_CAST
                .invoke(exprCompiler.compile(rangeArgs.start().get(), startDetachPoint).unboxAs(long.class));
        currentIndex = scope.create(forNode.getVarName(), startIndex, STORE);
        initStatements.add(currentIndex.initializer().labelStart(startDetachPoint));
    } else {
        currentIndex = scope.create(forNode.getVarName(), constant(0), STORE);
        initStatements.add(currentIndex.initializer());
    }

    final Statement incrementCurrentIndex;
    if (rangeArgs.increment().isPresent()) {
        Label detachPoint = new Label();
        Expression increment = MethodRef.INTS_CHECKED_CAST
                .invoke(exprCompiler.compile(rangeArgs.increment().get(), detachPoint).unboxAs(long.class));
        // If the expression is non-trivial, make sure to save it to a field.
        final Variable incrementVariable = scope.createSynthetic(SyntheticVarName.forLoopIncrement(forNode),
                increment, increment.isCheap() ? DERIVED : STORE);
        initStatements.add(incrementVariable.initializer().labelStart(detachPoint));
        incrementVariable.local();
        incrementCurrentIndex = new Statement() {
            @Override
            void doGen(CodeBuilder adapter) {
                currentIndex.local().gen(adapter);
                incrementVariable.local().gen(adapter);
                adapter.visitInsn(Opcodes.IADD);
                adapter.visitVarInsn(Opcodes.ISTORE, currentIndex.local().index());
            }
        };
    } else {
        incrementCurrentIndex = new Statement() {
            @Override
            void doGen(CodeBuilder adapter) {
                adapter.iinc(currentIndex.local().index(), 1);
            }
        };
    }

    Label detachPoint = new Label();
    Expression limit = MethodRef.INTS_CHECKED_CAST
            .invoke(exprCompiler.compile(rangeArgs.limit(), detachPoint).unboxAs(long.class));
    // If the expression is non-trivial we should cache it in a local variable
    Variable variable = scope.createSynthetic(SyntheticVarName.forLoopLimit(forNode), limit,
            limit.isCheap() ? DERIVED : STORE);
    initStatements.add(variable.initializer().labelStart(detachPoint));
    limit = variable.local();

    return new AutoValue_SoyNodeCompiler_CompiledRangeArgs(currentIndex.local(), limit, incrementCurrentIndex,
            initStatements.build());
}