Example usage for org.objectweb.asm Label Label

List of usage examples for org.objectweb.asm Label Label

Introduction

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

Prototype

public Label() 

Source Link

Document

Constructs a new label.

Usage

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

License:Apache License

/**
 * Returns an expression that evaluates to {@code left} if left is non null, and evaluates to
 * {@code right} otherwise. /* ww w . j a v  a 2  s.c  o  m*/
 */
static Expression firstNonNull(final Expression left, final Expression right) {
    checkArgument(left.resultType().getSort() == Type.OBJECT);
    checkArgument(right.resultType().getSort() == Type.OBJECT);
    Features features = Features.of();
    if (Expression.areAllCheap(left, right)) {
        features = features.plus(Feature.CHEAP);
    }
    if (right.isNonNullable()) {
        features = features.plus(Feature.NON_NULLABLE);
    }
    return new Expression(left.resultType(), features) {
        @Override
        void doGen(CodeBuilder cb) {
            Label leftIsNonNull = new Label();
            left.gen(cb); // Stack: L
            cb.dup(); // Stack: L, L
            cb.ifNonNull(leftIsNonNull); // Stack: L
            // pop the extra copy of left
            cb.pop(); // Stack:  
            right.gen(cb); // Stack: R
            cb.mark(leftIsNonNull); // At this point the stack has an instance of L or R
        }
    };
}

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

License:Apache License

/**
 * Returns an expression that evaluates equivalently to a java ternary expression: 
 * {@code condition ? left : right}/*w  w  w. ja  v  a 2 s.  com*/
 */
static Expression ternary(final Expression condition, final Expression trueBranch,
        final Expression falseBranch) {
    checkArgument(condition.resultType().equals(Type.BOOLEAN_TYPE));
    checkArgument(trueBranch.resultType().getSort() == falseBranch.resultType().getSort());
    Features features = Features.of();
    if (Expression.areAllCheap(condition, trueBranch, falseBranch)) {
        features = features.plus(Feature.CHEAP);
    }
    if (trueBranch.isNonNullable() && falseBranch.isNonNullable()) {
        features = features.plus(Feature.NON_NULLABLE);
    }
    return new Expression(trueBranch.resultType(), features) {
        @Override
        void doGen(CodeBuilder mv) {
            condition.gen(mv);
            Label ifFalse = new Label();
            Label end = new Label();
            mv.visitJumpInsn(Opcodes.IFEQ, ifFalse); // if 0 goto ifFalse
            trueBranch.gen(mv); // eval true branch
            mv.visitJumpInsn(Opcodes.GOTO, end); // jump to the end
            mv.visitLabel(ifFalse);
            falseBranch.gen(mv); // eval false branch
            mv.visitLabel(end);
        }
    };
}

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

License:Apache License

private static Expression doShortCircuitingLogicalOperator(
        final ImmutableList<? extends Expression> expressions, final boolean isOrOperator) {
    checkArgument(!expressions.isEmpty());
    for (Expression expr : expressions) {
        expr.checkAssignableTo(Type.BOOLEAN_TYPE);
    }/* w w  w  .ja va2  s.c  om*/
    if (expressions.size() == 1) {
        return expressions.get(0);
    }

    return new Expression(Type.BOOLEAN_TYPE,
            Expression.areAllCheap(expressions) ? Features.of(Feature.CHEAP) : Features.of()) {
        @Override
        void doGen(CodeBuilder adapter) {
            Label end = new Label();
            Label shortCircuit = new Label();
            for (int i = 0; i < expressions.size(); i++) {
                Expression expr = expressions.get(i);
                expr.gen(adapter);
                if (i == expressions.size() - 1) {
                    // if we are the last one, just goto end. Whatever the result of the last expression is
                    // determines the result of the whole expression (when all prior tests fail).
                    adapter.goTo(end);
                } else {
                    adapter.ifZCmp(isOrOperator ? Opcodes.IFNE : Opcodes.IFEQ, shortCircuit);
                }
            }
            adapter.mark(shortCircuit);
            adapter.pushBoolean(isOrOperator); // default for || is true && is false
            adapter.mark(end);
        }
    };
}

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

License:Apache License

/**
 * Returns a statement that encodes the given sequence of {@link IfBlock if blocks} as an 
 * if-elseif-else chain.//  www  . ja v  a 2s.  c o m
 */
static Statement ifElseChain(final List<IfBlock> ifs, final Optional<Statement> elseBlock) {
    checkArgument(!ifs.isEmpty());
    return new Statement() {
        @Override
        void doGen(CodeBuilder adapter) {
            Label end = new Label();
            Label next;
            for (int i = 0; i < ifs.size(); i++) {
                IfBlock curr = ifs.get(i);
                boolean isLastIfBlock = i == ifs.size() - 1;
                if (isLastIfBlock && !elseBlock.isPresent()) {
                    next = end;
                } else {
                    next = new Label();
                }
                curr.condition().gen(adapter);
                adapter.ifZCmp(Opcodes.IFEQ, next);
                curr.block().gen(adapter);
                if (end != next) {
                    adapter.goTo(end);
                }
                adapter.mark(next);
            }
            if (elseBlock.isPresent()) {
                elseBlock.get().gen(adapter);
                adapter.mark(end);
            }
        }
    };
}

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

License:Apache License

/**
 * Returns a Statement that will conditionally detach if the given {@link AdvisingAppendable} has
 * been {@link AdvisingAppendable#softLimitReached() output limited}.
 *//* ww  w. j  a  v a  2  s  .  c  om*/
Statement detachLimited(AppendableExpression appendable) {
    if (!appendable.supportsSoftLimiting()) {
        return appendable.toStatement();
    }
    final Label reattachPoint = new Label();
    final SaveRestoreState saveRestoreState = variables.saveRestoreState();

    Statement restore = saveRestoreState.restore();
    int state = addState(reattachPoint, restore);
    final Expression isSoftLimited = appendable.softLimitReached();
    final Statement returnLimited = returnExpression(MethodRef.RENDER_RESULT_LIMITED.invoke());
    final Statement saveState = stateField.putInstanceField(thisExpr, BytecodeUtils.constant(state));
    return new Statement() {
        @Override
        void doGen(CodeBuilder adapter) {
            isSoftLimited.gen(adapter);
            adapter.ifZCmp(Opcodes.IFEQ, reattachPoint); // if !softLimited
            // ok we were limited, save state and return
            saveRestoreState.save().gen(adapter); // save locals
            saveState.gen(adapter); // save the state field
            returnLimited.gen(adapter);
            // Note, the reattach point for 'limited' is _after_ the check.  That means we do not 
            // recheck the limit state.  So if a caller calls us back without freeing any buffer we
            // will print more before checking again.  This is fine, because our caller is breaking the
            // contract.
            adapter.mark(reattachPoint);
        }
    };
}

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

License:Apache License

/**
 * Generate detach logic for calls.//from ww  w  . j ava 2s. c om
 * 
 * <p>Calls are a little different due to a desire to minimize the cost of detaches. We assume 
 * that if a given call site detaches once, it is more likely to detach multiple times. So we
 * generate code that looks like:   <pre>{@code
 * 
 * RenderResult initialResult = template.render(appendable, renderContext);
 * if (!initialResult.isDone()) {
 *   // save all fields
 *   state = REATTACH_RENDER;
 *   return initialResult;
 * } else {
 *   goto END;
 * }
 * REATTACH_RENDER:
 * // restore nothing!
 * RenderResult secondResult = template.render(appendable, renderContext);
 * if (!secondResult.isDone()) {
 *   // saveFields
 *   state = REATTACH_RENDER;
 *   return secondResult;
 * } else {
 *   // restore all fields
 *   goto END;
 * }
 * END:
 * }</pre>
 * 
 * <p>With this technique we save re-running the save-restore logic for multiple detaches from
 * the same call site.  This should be especially useful for top level templates.
 * 
 * @param callRender an Expression that can generate code to call the render method, should be
 *     safe to generate more than once. 
 */
Statement detachForRender(final Expression callRender) {
    checkArgument(callRender.resultType().equals(RENDER_RESULT_TYPE));
    final Label reattachRender = new Label();
    final SaveRestoreState saveRestoreState = variables.saveRestoreState();
    // We pass NULL statement for the restore logic since we handle that ourselves below
    int state = addState(reattachRender, Statement.NULL_STATEMENT);
    final Statement saveState = stateField.putInstanceField(thisExpr, BytecodeUtils.constant(state));
    return new Statement() {
        @Override
        void doGen(CodeBuilder adapter) {
            // Legend: RR = RenderResult, Z = boolean
            callRender.gen(adapter); // Stack: RR
            adapter.dup(); // Stack: RR, RR
            MethodRef.RENDER_RESULT_IS_DONE.invokeUnchecked(adapter); // Stack: RR, Z
            // if isDone goto Done
            Label end = new Label();
            adapter.ifZCmp(Opcodes.IFNE, end); // Stack: RR

            saveRestoreState.save().gen(adapter);
            saveState.gen(adapter);
            adapter.returnValue();

            adapter.mark(reattachRender);
            callRender.gen(adapter); // Stack: RR
            adapter.dup(); // Stack: RR, RR
            MethodRef.RENDER_RESULT_IS_DONE.invokeUnchecked(adapter); // Stack: RR, Z
            // if isDone goto restore
            Label restore = new Label();
            adapter.ifZCmp(Opcodes.IFNE, restore); // Stack: RR
            // no need to save or restore anything
            adapter.returnValue();
            adapter.mark(restore); // Stack: RR
            saveRestoreState.restore().gen(adapter);
            adapter.mark(end); // Stack: RR
            adapter.pop(); // Stack:
        }
    };
}

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

License:Apache License

/**
 * Compiles the given expression tree to a sequence of bytecode in the current method visitor.
 *
 * <p>The generated bytecode expects that the evaluation stack is empty when this method is
 * called and it will generate code such that the stack contains a single SoyValue when it
 * returns.  The SoyValue object will have a runtime type equal to
 * {@code node.getType().javaType()}.// w w  w  . ja  v a  2  s  . com
 */
SoyExpression compile(ExprNode node) {
    Label reattachPoint = new Label();
    final SoyExpression exec = compile(node, reattachPoint);
    return exec.withSource(exec.labelStart(reattachPoint));
}

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

License:Apache License

private static ClassData createClass(Class<? extends Invoker> targetInterface, Expression expr) {
    java.lang.reflect.Method invokeMethod;
    try {/* w w w .  java 2 s  .com*/
        invokeMethod = targetInterface.getMethod("invoke");
    } catch (NoSuchMethodException | SecurityException e) {
        throw new RuntimeException(e);
    }
    Class<?> returnType = invokeMethod.getReturnType();
    if (!Type.getType(returnType).equals(expr.resultType())) {
        if (!returnType.equals(Object.class) || expr.resultType().getSort() != Type.OBJECT) {
            throw new IllegalArgumentException(targetInterface + " is not appropriate for this expression");
        }
    }
    TypeInfo generatedType = TypeInfo.create(
            ExpressionTester.class.getPackage().getName() + "." + targetInterface.getSimpleName() + "Impl");
    SoyClassWriter cw = SoyClassWriter.builder(generatedType)
            .setAccess(Opcodes.ACC_FINAL | Opcodes.ACC_SUPER | Opcodes.ACC_PUBLIC)
            .implementing(TypeInfo.create(targetInterface)).build();
    BytecodeUtils.defineDefaultConstructor(cw, generatedType);
    Method invoke = Method.getMethod(invokeMethod);
    Statement.returnExpression(expr).writeMethod(Opcodes.ACC_PUBLIC, invoke, cw);

    Method voidInvoke;
    try {
        voidInvoke = Method.getMethod(Invoker.class.getMethod("voidInvoke"));
    } catch (NoSuchMethodException | SecurityException e) {
        throw new RuntimeException(e); // this method definitely exists
    }
    Statement.concat(LocalVariable.createThisVar(generatedType, new Label(), new Label())
            .invoke(MethodRef.create(invokeMethod)).toStatement(), new Statement() {
                @Override
                void doGen(CodeBuilder adapter) {
                    adapter.visitInsn(Opcodes.RETURN);
                }
            }).writeMethod(Opcodes.ACC_PUBLIC, voidInvoke, cw);
    ClassData data = cw.toClassData();
    checkClassData(data);
    return data;
}

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

License:Apache License

private void putSelectPartIntoMap(Expression mapExpression, MsgNode originalMsg,
        Map<String, Statement> placeholderNameToPutStatement, SoyMsgSelectPart select) {
    MsgSelectNode repSelectNode = originalMsg.getRepSelectNode(select.getSelectVarName());
    if (!placeholderNameToPutStatement.containsKey(select.getSelectVarName())) {
        Label reattachPoint = new Label();
        Expression value = soyNodeCompiler.compileToString(repSelectNode.getExpr(), reattachPoint);
        placeholderNameToPutStatement.put(select.getSelectVarName(),
                putToMap(mapExpression, select.getSelectVarName(), value).labelStart(reattachPoint));
    }//from   w  w w.  j a v a2s .co m
    // Recursively visit select cases
    for (Case<String> caseOrDefault : select.getCases()) {
        putPlaceholdersIntoMap(mapExpression, originalMsg, caseOrDefault.parts(),
                placeholderNameToPutStatement);
    }
}

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

License:Apache License

private void putPluralPartIntoMap(Expression mapExpression, MsgNode originalMsg,
        Map<String, Statement> placeholderNameToPutStatement, SoyMsgPluralPart plural) {
    MsgPluralNode repPluralNode = originalMsg.getRepPluralNode(plural.getPluralVarName());
    if (!placeholderNameToPutStatement.containsKey(plural.getPluralVarName())) {
        Label reattachPoint = new Label();
        Expression value = soyNodeCompiler.compileToInt(repPluralNode.getExpr(), reattachPoint);
        placeholderNameToPutStatement.put(plural.getPluralVarName(),
                putToMap(mapExpression, plural.getPluralVarName(), value).labelStart(reattachPoint));
    }//ww w  .j a  v  a 2s .  com
    // Recursively visit plural cases
    for (Case<SoyMsgPluralCaseSpec> caseOrDefault : plural.getCases()) {
        putPlaceholdersIntoMap(mapExpression, originalMsg, caseOrDefault.parts(),
                placeholderNameToPutStatement);
    }
}