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.restricted.SoyExpression.java

License:Apache License

/** Returns a SoyExpression that evaluates to a subtype of {@link SoyValue}. */
public SoyExpression box() {
    if (isBoxed()) {
        return this;
    }/*from   www. j a  va 2  s .  c  o  m*/
    if (soyType().equals(NullType.getInstance())) {
        if (delegate == NULL) {
            return NULL_BOXED;
        }
        return asBoxed(toStatement().then(NULL_BOXED));
    }
    // since we aren't boxed and these must be primitives so we don't need to worry about
    // nullability
    if (soyRuntimeType.isKnownBool()) {
        return asBoxed(MethodRef.BOOLEAN_DATA_FOR_VALUE.invoke(delegate));
    }
    if (soyRuntimeType.isKnownInt()) {
        return asBoxed(MethodRef.INTEGER_DATA_FOR_VALUE.invoke(delegate));
    }
    if (soyRuntimeType.isKnownFloat()) {
        return asBoxed(MethodRef.FLOAT_DATA_FOR_VALUE.invoke(delegate));
    }
    // If null is expected and it is a reference type we want to propagate null through the boxing
    // operation
    final boolean isNonNullable = delegate.isNonNullable();
    return asBoxed(new Expression(soyRuntimeType.box().runtimeType(), features()) {
        @Override
        protected void doGen(CodeBuilder adapter) {
            Label end = null;
            delegate.gen(adapter);
            if (!isNonNullable) {
                end = new Label();
                BytecodeUtils.nullCoalesce(adapter, end);
            }
            doBox(adapter, soyRuntimeType.asNonNullable());
            if (end != null) {
                adapter.mark(end);
            }
        }
    });
}

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

License:Apache License

/** Coerce this expression to a boolean value. */
public SoyExpression coerceToBoolean() {
    // First deal with primitives which don't have to care about null.
    if (BytecodeUtils.isPrimitive(resultType())) {
        return coercePrimitiveToBoolean();
    }/*from w  w  w .jav  a 2  s .  c o  m*/
    if (soyType().equals(NullType.getInstance())) {
        return FALSE;
    }
    if (delegate.isNonNullable()) {
        return coerceNonNullableReferenceTypeToBoolean();
    } else {
        // If we are potentially nullable, then map null to false and run the normal logic recursively
        // for the non-nullable branch.
        final Label end = new Label();
        return withSource(new Expression(delegate.resultType(), delegate.features()) {
            @Override
            protected void doGen(CodeBuilder adapter) {
                delegate.gen(adapter);
                adapter.dup();
                Label nonNull = new Label();
                adapter.ifNonNull(nonNull);
                adapter.pop();
                adapter.pushBoolean(false);
                adapter.goTo(end);
                adapter.mark(nonNull);
            }
        }).asNonNullable().coerceToBoolean().labelEnd(end);
    }
}

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

License:Apache License

/**
 * Unboxes this to a {@link SoyExpression} with a runtime type of {@code asType}.
 *
 * <p>This method is appropriate when you know (likely via inspection of the {@link #soyType()},
 * or other means) that the value does have the appropriate type but you prefer to interact with
 * it as its unboxed representation. If you simply want to 'coerce' the given value to a new type
 * consider {@link #coerceToBoolean()} {@link #coerceToDouble()} or {@link #coerceToString()}
 * which are designed for that use case.
 *//*from   w  w  w  . j  a v  a2s  . co  m*/
public SoyExpression unboxAs(Class<?> asType) {
    checkArgument(!SoyValue.class.isAssignableFrom(asType),
            "Cannot use unboxAs() to convert to a SoyValue: %s, use .box() instead", asType);

    // No-op conversion, always allow.
    // SoyExpressions that are already unboxed fall into this case.
    if (BytecodeUtils.isDefinitelyAssignableFrom(Type.getType(asType), soyRuntimeType.runtimeType())) {
        return this;
    }

    // Attempting to unbox an unboxed proto
    if (asType.equals(Message.class) && soyRuntimeType.isKnownProtoOrUnionOfProtos() && !isBoxed()) {
        return this;
    }

    if (!isBoxed()) {
        throw new IllegalStateException("Trying to unbox an unboxed value (" + soyRuntimeType + ") into "
                + asType + " doesn't make sense. Should you be using a type coercion? e.g. coerceToBoolean()");
    }

    if (asType.equals(boolean.class)) {
        return forBool(delegate.invoke(MethodRef.SOY_VALUE_BOOLEAN_VALUE));
    }
    if (asType.equals(long.class)) {
        return forInt(delegate.invoke(MethodRef.SOY_VALUE_LONG_VALUE));
    }
    if (asType.equals(double.class)) {
        return forFloat(delegate.invoke(MethodRef.SOY_VALUE_FLOAT_VALUE));
    }

    if (delegate.isNonNullable()) {
        if (asType.equals(String.class)) {
            Expression unboxedString = delegate.invoke(MethodRef.SOY_VALUE_STRING_VALUE);
            // We need to ensure that santized types don't lose their content kinds
            return soyRuntimeType.isKnownSanitizedContent()
                    ? forSanitizedString(unboxedString, ((SanitizedType) soyType()).getContentKind())
                    : forString(unboxedString);
        }
        if (asType.equals(List.class)) {
            return unboxAsList();
        }
        if (asType.equals(Message.class)) {
            SoyRuntimeType runtimeType = getUnboxedType(soyType());
            return forProto(runtimeType, delegate.invoke(MethodRef.SOY_PROTO_VALUE_GET_PROTO)
                    .checkedCast(runtimeType.runtimeType()));
        }
    } else {
        // else it must be a List/Proto/String all of which must preserve null through the unboxing
        // operation
        // TODO(lukes): this violates the expression contract since we jump to a label outside the
        // scope of the expression
        final Label end = new Label();
        Expression nonNullDelegate = new Expression(resultType(), features()) {
            @Override
            protected void doGen(CodeBuilder adapter) {
                delegate.gen(adapter);
                BytecodeUtils.nullCoalesce(adapter, end);
            }
        };
        return withSource(nonNullDelegate).asNonNullable().unboxAs(asType).asNullable().labelEnd(end);
    }
    throw new UnsupportedOperationException("Can't unbox " + soyRuntimeType + " as " + asType);
}

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

License:Apache License

public static ClassData createClass(Class<? extends Invoker> targetInterface, Expression expr) {
    java.lang.reflect.Method invokeMethod;
    try {/*from  w  w  w  .  j  a  v  a2 s .c  o  m*/
        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(Names.CLASS_PREFIX + 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
                protected 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.SoyExpression.java

License:Apache License

/** Returns a SoyExpression that evaluates to a subtype of {@link SoyValue}. */
SoyExpression box() {/*from w w w.  j ava2 s  .  c o  m*/
    if (isBoxed()) {
        return this;
    }
    if (soyType.equals(NullType.getInstance())) {
        return this;
    }
    // If null is expected and it is a reference type we want to propagate null through the boxing
    // operation
    if (!delegate.isNonNullable()) {
        // now prefix with a null check and then box so null is preserved via 'boxing'
        final Label end = new Label();
        return withSource(new Expression(resultType(), features()) {
            @Override
            void doGen(CodeBuilder adapter) {
                delegate.gen(adapter);
                adapter.dup();
                adapter.ifNull(end);
            }
        }).asNonNullable().box().asNullable().labelEnd(end);
    }
    if (isKnownBool()) {
        return asBoxed(MethodRef.BOOLEAN_DATA_FOR_VALUE.invoke(delegate));
    }
    if (isKnownInt()) {
        return asBoxed(MethodRef.INTEGER_DATA_FOR_VALUE.invoke(delegate));
    }
    if (isKnownFloat()) {
        return asBoxed(MethodRef.FLOAT_DATA_FOR_VALUE.invoke(delegate));
    }
    if (isKnownSanitizedContent()) {
        return asBoxed(MethodRef.ORDAIN_AS_SAFE.invoke(delegate,
                FieldRef.enumReference(((SanitizedType) soyType).getContentKind()).accessor()));
    }
    if (isKnownString()) {
        return asBoxed(MethodRef.STRING_DATA_FOR_VALUE.invoke(delegate));
    }
    if (isKnownList()) {
        return asBoxed(MethodRef.LIST_IMPL_FOR_PROVIDER_LIST.invoke(delegate));
    }
    throw new IllegalStateException(
            "cannot box soy expression of type " + soyType + " with runtime type " + clazz);
}

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

License:Apache License

/** Coerce this expression to a boolean value. */
SoyExpression coerceToBoolean() {//from   www  . ja va2  s.  co  m
    // First deal with primitives which don't have to care about null.
    if (BytecodeUtils.isPrimitive(resultType())) {
        return coercePrimitiveToBoolean();
    }
    if (soyType.equals(NullType.getInstance())) {
        return FALSE;
    }
    if (delegate.isNonNullable()) {
        return coerceNonNullableReferenceTypeToBoolean();
    } else {
        // If we are potentially nullable, then map null to false and run the normal logic recursively
        // for the non-nullable branch.
        final Label end = new Label();
        return withSource(new Expression(delegate.resultType(), delegate.features()) {
            @Override
            void doGen(CodeBuilder adapter) {
                delegate.gen(adapter);
                adapter.dup();
                Label nonNull = new Label();
                adapter.ifNonNull(nonNull);
                adapter.pop();
                adapter.pushBoolean(false);
                adapter.goTo(end);
                adapter.mark(nonNull);
            }
        }).asNonNullable().coerceToBoolean().labelEnd(end);
    }
}

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

License:Apache License

/**
 * Unboxes this to a {@link SoyExpression} with a runtime type of {@code asType}.
 *
 * <p>This method is appropriate when you know (likely via inspection of the {@link #soyType()},
 * or other means) that the value does have the appropriate type but you prefer to interact with
 * it as its unboxed representation.  If you simply want to 'coerce' the given value to a new type
 * consider {@link #coerceToBoolean()} {@link #coerceToDouble()} or {@link #coerceToString()}
 * which are designed for that use case.
 *///from   www  .  j  a  va2  s  .com
SoyExpression unboxAs(Class<?> asType) {
    checkArgument(!SoyValue.class.isAssignableFrom(asType),
            "Cannot use convert() to convert to a  SoyValue: %s, use .box() instead", asType);
    // no op conversion, always allow.
    if (asType.equals(clazz)) {
        return this;
    }
    if (!isBoxed()) {
        throw new IllegalStateException("Trying to unbox an unboxed value (" + clazz + ") doesn't make sense, "
                + "should you be using a type coercion? e.g. .coerceToBoolean()");
    }
    if (asType.equals(boolean.class)) {
        return forBool(delegate.invoke(MethodRef.SOY_VALUE_BOOLEAN_VALUE));
    }
    if (asType.equals(long.class)) {
        return forInt(delegate.invoke(MethodRef.SOY_VALUE_LONG_VALUE));
    }
    if (asType.equals(double.class)) {
        return forFloat(delegate.invoke(MethodRef.SOY_VALUE_FLOAT_VALUE));
    }
    if (delegate.isNonNullable()) {
        if (asType.equals(String.class)) {
            Expression unboxedString = delegate.invoke(MethodRef.SOY_VALUE_STRING_VALUE);
            // We need to ensure that santized types don't lose their content kinds
            return isKnownSanitizedContent()
                    ? forSanitizedString(unboxedString, ((SanitizedType) soyType).getContentKind())
                    : forString(unboxedString);
        }
        if (asType.equals(List.class)) {
            return unboxAsList();
        }
    } else {
        // else it must be a List/Proto/String all of which must preserve null through the unboxing
        // operation
        final Label ifNull = new Label();
        Expression nonNullDelegate = new Expression(resultType(), features()) {
            @Override
            void doGen(CodeBuilder adapter) {
                delegate.gen(adapter);
                adapter.dup();
                adapter.ifNull(ifNull);
            }
        };
        final SoyExpression unboxAs = withSource(nonNullDelegate).asNonNullable().unboxAs(asType);
        return unboxAs.withSource(new Expression(unboxAs.resultType(), features()) {
            @Override
            void doGen(CodeBuilder adapter) {
                unboxAs.gen(adapter);
                adapter.mark(ifNull);
                adapter.checkCast(unboxAs.resultType()); // insert a cast to force type agreement
            }
        });
    }
    throw new UnsupportedOperationException("Can't unbox " + clazz + " as " + asType);
}

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

License:Apache License

@Override
protected Statement visitSwitchNode(SwitchNode node) {
    // A few special cases:
    // 1. only a {default} block.  In this case we can skip all the switch logic and temporaries
    // 2. no children.  Just return the empty statement
    // Note that in both of these cases we do not evalutate (or generate code) for the switch
    // expression.
    List<SoyNode> children = node.getChildren();
    if (children.isEmpty()) {
        return Statement.NULL_STATEMENT;
    }/*from  w ww  .j a  v  a 2 s  .c  o  m*/
    if (children.size() == 1 && children.get(0) instanceof SwitchDefaultNode) {
        return visitChildrenInNewScope((SwitchDefaultNode) children.get(0));
    }
    // otherwise we need to evaluate the predicate and generate dispatching logic.
    SoyExpression expression = exprCompiler.compile(node.getExpr());
    Statement init;
    List<IfBlock> cases = new ArrayList<>();
    Optional<Statement> defaultBlock = Optional.absent();
    Scope scope = variables.enterScope();
    Variable variable = scope.createSynthetic(SyntheticVarName.forSwitch(node), expression, STORE);
    init = variable.initializer();
    expression = expression.withSource(variable.local());

    for (SoyNode child : children) {
        if (child instanceof SwitchCaseNode) {
            SwitchCaseNode caseNode = (SwitchCaseNode) child;
            Label reattachPoint = new Label();
            List<Expression> comparisons = new ArrayList<>();
            for (ExprRootNode caseExpr : caseNode.getExprList()) {
                comparisons.add(compareSoyEquals(expression, exprCompiler.compile(caseExpr, reattachPoint)));
            }
            Expression condition = BytecodeUtils.logicalOr(comparisons).labelStart(reattachPoint);
            Statement block = visitChildrenInNewScope(caseNode);
            cases.add(IfBlock.create(condition, block));
        } else {
            SwitchDefaultNode defaultNode = (SwitchDefaultNode) child;
            defaultBlock = Optional.of(visitChildrenInNewScope(defaultNode));
        }
    }
    Statement exitScope = scope.exitScope();

    // Soy allows arbitrary expressions to appear in {case} statements within a {switch}.
    // Java/C, by contrast, only allow some constant expressions in cases.
    // TODO(lukes): in practice the case statements are often constant strings/ints.  If everything
    // is typed to int/string we should consider implementing via the tableswitch/lookupswitch
    // instruction which would be way way way faster.  cglib has some helpers for string switch
    // generation that we could maybe use
    return Statement.concat(init, ControlFlow.ifElseChain(cases, defaultBlock), exitScope)
            .withSourceLocation(node.getSourceLocation());
}

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

License:Apache License

@Override
protected Statement visitForNode(ForNode node) {
    // Despite appearances, range() is not a soy function, it is essentially a keyword that only
    // works in for loops, there are 3 forms.
    // {for $i in range(3)}{$i}{/for} -> 0 1 2
    // {for $i in range(2, 5)} ... {/for} -> 2 3 4
    // {for $i in range(2, 8, 2)} ... {/for} -> 2 4 6

    Scope scope = variables.enterScope();
    final CompiledRangeArgs rangeArgs = calculateRangeArgs(node, scope);

    final Statement loopBody = visitChildrenInNewScope(node);

    // Note it is important that exitScope is called _after_ the children are visited.
    // TODO(lukes): this is somewhat error-prone... we could maybe manage it by have the scope
    // maintain a sequence of statements and then all statements would be added to Scope which would
    // return a statement for the whole thing at the end... would that be clearer?
    final Statement exitScope = scope.exitScope();
    return new Statement(node.getSourceLocation()) {
        @Override// ww  w .java  2s .  c o m
        void doGen(CodeBuilder adapter) {
            for (Statement initializer : rangeArgs.initStatements()) {
                initializer.gen(adapter);
            }
            // We need to check for an empty loop by doing an entry test
            Label loopStart = adapter.mark();

            // If current >= limit we are done
            rangeArgs.currentIndex().gen(adapter);
            rangeArgs.limit().gen(adapter);
            Label end = new Label();
            adapter.ifCmp(Type.INT_TYPE, Opcodes.IFGE, end);

            loopBody.gen(adapter);

            // at the end of the loop we need to increment and jump back.
            rangeArgs.increment().gen(adapter);
            adapter.goTo(loopStart);
            adapter.mark(end);
            exitScope.gen(adapter);
        }
    };
}

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  www. j a  va2s.  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());
}