Search in sources :

Example 1 with LocalVariable

use of com.google.template.soy.jbcsrc.restricted.LocalVariable in project closure-templates by google.

the class PrintDirectives method applyStreamingPrintDirectivesTo.

private static AppendableAndOptions applyStreamingPrintDirectivesTo(List<DirectiveWithArgs> directivesToApply, Expression appendable, JbcSrcPluginContext context, TemplateVariableManager variableManager) {
    final List<LocalVariable> closeables = new ArrayList<>();
    final List<Variable> appendableVars = new ArrayList<>();
    Scope scope = variableManager.enterScope();
    AppendableAndOptions prev = AppendableAndOptions.create(appendable);
    Variable prevVar = scope.createTemporary("tmp_appendable", appendable);
    appendableVars.add(prevVar);
    // appendable with the last directive first. so iterate in reverse order.
    for (DirectiveWithArgs directiveToApply : Lists.reverse(directivesToApply)) {
        AppendableAndOptions curr = directiveToApply.apply(context, prevVar.local());
        Variable currVar = scope.createTemporary("tmp_appendable", curr.appendable());
        appendableVars.add(currVar);
        if (curr.closeable()) {
            closeables.add(currVar.local());
        }
        prev = curr;
        prevVar = currVar;
    }
    // Check if we need to apply a wrapper to make sure close propagates to all the right places
    // this is necessary if there are multiple closeable wrappers.
    final Expression appendableExpression;
    final boolean closeable;
    if (closeables.isEmpty()) {
        appendableExpression = prev.appendable();
        closeable = false;
    } else if (closeables.size() == 1 && prev.closeable()) {
        // there is exactly one closeable and it is first, we don't need a wrapper
        appendableExpression = prev.appendable();
        closeable = true;
    } else {
        // there is either more than one closeable, or it is not the first one, so we need a wrapper
        // We need to reverse the list of closeables so that we close them in the correct order. for
        // example, given '|foo|bar' we will first wrap the delegate with bar and then with foo but we
        // need to close foo first.
        appendableExpression = RUNTIME_PROPAGATE_CLOSE.invoke(Iterables.getLast(appendableVars).local(), BytecodeUtils.asImmutableList(Lists.reverse(closeables)));
        closeable = true;
    }
    final Statement exitScope = scope.exitScope();
    Expression result = new Expression(appendableExpression.resultType()) {

        @Override
        protected void doGen(CodeBuilder adapter) {
            for (Variable var : appendableVars) {
                var.initializer().gen(adapter);
            }
            appendableExpression.gen(adapter);
            exitScope.gen(adapter);
        }
    };
    if (closeable) {
        return AppendableAndOptions.createCloseable(result);
    } else {
        return AppendableAndOptions.create(result);
    }
}
Also used : Variable(com.google.template.soy.jbcsrc.TemplateVariableManager.Variable) LocalVariable(com.google.template.soy.jbcsrc.restricted.LocalVariable) Scope(com.google.template.soy.jbcsrc.TemplateVariableManager.Scope) SoyExpression(com.google.template.soy.jbcsrc.restricted.SoyExpression) Expression(com.google.template.soy.jbcsrc.restricted.Expression) Statement(com.google.template.soy.jbcsrc.restricted.Statement) AppendableAndOptions(com.google.template.soy.jbcsrc.restricted.SoyJbcSrcPrintDirective.Streamable.AppendableAndOptions) LocalVariable(com.google.template.soy.jbcsrc.restricted.LocalVariable) ArrayList(java.util.ArrayList) CodeBuilder(com.google.template.soy.jbcsrc.restricted.CodeBuilder)

Example 2 with LocalVariable

use of com.google.template.soy.jbcsrc.restricted.LocalVariable in project closure-templates by google.

the class TemplateCompiler method generateConstructor.

/**
 * Generate a public constructor that assigns our final field and checks for missing required
 * params.
 *
 * <p>This constructor is called by the generate factory classes.
 *
 * @param fieldInitializers additional statements to initialize fields (other than params)
 */
private void generateConstructor(Statement fieldInitializers) {
    final Label start = new Label();
    final Label end = new Label();
    final LocalVariable thisVar = createThisVar(template.typeInfo(), start, end);
    final LocalVariable paramsVar = createLocal("params", 1, SOY_RECORD_TYPE, start, end);
    final LocalVariable ijVar = createLocal("ij", 2, SOY_RECORD_TYPE, start, end);
    final List<Statement> assignments = new ArrayList<>();
    // for other fields needed by the compiler.
    assignments.add(fieldInitializers);
    assignments.add(paramsField.putInstanceField(thisVar, paramsVar));
    assignments.add(ijField.putInstanceField(thisVar, ijVar));
    for (TemplateParam param : template.node().getAllParams()) {
        Expression paramProvider = getParam(paramsVar, ijVar, param);
        assignments.add(paramFields.get(param.name()).putInstanceField(thisVar, paramProvider));
    }
    Statement constructorBody = new Statement() {

        @Override
        protected void doGen(CodeBuilder ga) {
            ga.mark(start);
            // call super()
            thisVar.gen(ga);
            ga.invokeConstructor(OBJECT.type(), NULLARY_INIT);
            for (Statement assignment : assignments) {
                assignment.gen(ga);
            }
            ga.visitInsn(Opcodes.RETURN);
            ga.visitLabel(end);
            thisVar.tableEntry(ga);
            paramsVar.tableEntry(ga);
            ijVar.tableEntry(ga);
        }
    };
    constructorBody.writeMethod(Opcodes.ACC_PUBLIC, template.constructor().method(), writer);
}
Also used : Expression(com.google.template.soy.jbcsrc.restricted.Expression) Statement(com.google.template.soy.jbcsrc.restricted.Statement) Label(org.objectweb.asm.Label) LocalVariable(com.google.template.soy.jbcsrc.restricted.LocalVariable) ArrayList(java.util.ArrayList) TemplateParam(com.google.template.soy.soytree.defn.TemplateParam) CodeBuilder(com.google.template.soy.jbcsrc.restricted.CodeBuilder)

Example 3 with LocalVariable

use of com.google.template.soy.jbcsrc.restricted.LocalVariable in project closure-templates by google.

the class TemplateCompiler method generateRenderMethod.

private Statement generateRenderMethod() {
    final Label start = new Label();
    final Label end = new Label();
    final LocalVariable thisVar = createThisVar(template.typeInfo(), start, end);
    final LocalVariable appendableVar = createLocal("appendable", 1, LOGGING_ADVISING_APPENDABLE_TYPE, start, end).asNonNullable();
    final LocalVariable contextVar = createLocal("context", 2, RENDER_CONTEXT_TYPE, start, end).asNonNullable();
    final TemplateVariableManager variableSet = new TemplateVariableManager(fieldNames, template.typeInfo(), thisVar, template.renderMethod().method());
    TemplateNode node = template.node();
    TemplateVariables variables = new TemplateVariables(variableSet, thisVar, new RenderContextExpression(contextVar));
    final CompiledMethodBody methodBody = SoyNodeCompiler.create(registry, innerClasses, stateField, thisVar, AppendableExpression.forLocal(appendableVar), variableSet, variables).compile(node);
    final Statement returnDone = Statement.returnExpression(MethodRef.RENDER_RESULT_DONE.invoke());
    new Statement() {

        @Override
        protected void doGen(CodeBuilder adapter) {
            adapter.mark(start);
            methodBody.body().gen(adapter);
            adapter.mark(end);
            returnDone.gen(adapter);
            thisVar.tableEntry(adapter);
            appendableVar.tableEntry(adapter);
            contextVar.tableEntry(adapter);
            variableSet.generateTableEntries(adapter);
        }
    }.writeIOExceptionMethod(Opcodes.ACC_PUBLIC, template.renderMethod().method(), writer);
    writer.setNumDetachStates(methodBody.numberOfDetachStates());
    variableSet.defineStaticFields(writer);
    return variableSet.defineFields(writer);
}
Also used : TemplateNode(com.google.template.soy.soytree.TemplateNode) Statement(com.google.template.soy.jbcsrc.restricted.Statement) Label(org.objectweb.asm.Label) LocalVariable(com.google.template.soy.jbcsrc.restricted.LocalVariable) CompiledMethodBody(com.google.template.soy.jbcsrc.SoyNodeCompiler.CompiledMethodBody) CodeBuilder(com.google.template.soy.jbcsrc.restricted.CodeBuilder)

Example 4 with LocalVariable

use of com.google.template.soy.jbcsrc.restricted.LocalVariable in project closure-templates by google.

the class TemplateFactoryCompiler method generateCreateMethod.

/**
 * Writes the {@link CompiledTemplate.Factory#create} method, which directly delegates to the
 * constructor of the {@link #template}.
 */
private void generateCreateMethod(ClassVisitor cv, TypeInfo factoryType) {
    final Label start = new Label();
    final Label end = new Label();
    final LocalVariable thisVar = createThisVar(factoryType, start, end);
    final LocalVariable paramsVar = createLocal("params", 1, SOY_RECORD_TYPE, start, end);
    final LocalVariable ijVar = createLocal("ij", 2, SOY_RECORD_TYPE, start, end);
    final Statement returnTemplate = Statement.returnExpression(template.constructor().construct(paramsVar, ijVar));
    new Statement() {

        @Override
        protected void doGen(CodeBuilder ga) {
            ga.mark(start);
            returnTemplate.gen(ga);
            ga.mark(end);
            thisVar.tableEntry(ga);
            paramsVar.tableEntry(ga);
            ijVar.tableEntry(ga);
        }
    }.writeMethod(Opcodes.ACC_PUBLIC, CREATE_METHOD, cv);
}
Also used : Statement(com.google.template.soy.jbcsrc.restricted.Statement) Label(org.objectweb.asm.Label) LocalVariable(com.google.template.soy.jbcsrc.restricted.LocalVariable) CodeBuilder(com.google.template.soy.jbcsrc.restricted.CodeBuilder)

Example 5 with LocalVariable

use of com.google.template.soy.jbcsrc.restricted.LocalVariable in project closure-templates by google.

the class TemplateVariableManager method enterScope.

/**
 * Enters a new scope. Variables may only be defined within a scope.
 */
Scope enterScope() {
    final Map<VarKey, Variable> currentFrame = new LinkedHashMap<>();
    final Label scopeExit = new Label();
    frames.push(currentFrame);
    return new Scope() {

        boolean exited;

        @Override
        Variable createSynthetic(SyntheticVarName varName, Expression initExpr, SaveStrategy strategy) {
            checkState(!exited, "Scope already exited");
            VarKey key = VarKey.create(Kind.SYNTHETIC, varName.name());
            // synthetics are prefixed by $ by convention
            String name = fieldNames.generateName("$" + varName.name());
            return doCreate(name, new Label(), scopeExit, initExpr, key, strategy);
        }

        @Override
        Variable createTemporary(String name, Expression initExpr) {
            checkState(!exited, "Scope already exited");
            VarKey key = VarKey.create(Kind.TEMPORARY, name);
            name = fieldNames.generateName("$$" + name);
            return doCreate(name, new Label(), scopeExit, initExpr, key, SaveStrategy.NEVER);
        }

        @Override
        Variable create(String name, Expression initExpr, SaveStrategy strategy) {
            checkState(!exited, "Scope already exited");
            VarKey key = VarKey.create(Kind.USER_DEFINED, name);
            name = fieldNames.generateName(name);
            return doCreate(name, new Label(), scopeExit, initExpr, key, strategy);
        }

        @Override
        Statement exitScope() {
            checkState(!exited, "Scope already exited");
            exited = true;
            frames.pop();
            // Use identity semantics to make sure we visit each label at most once.  visiting a label
            // more than once tends to corrupt internal asm state.
            final Set<Label> endLabels = Sets.newIdentityHashSet();
            for (Variable var : currentFrame.values()) {
                endLabels.add(var.local.end());
                availableSlots.clear(var.local.index(), var.local.index() + var.local.resultType().getSize());
            }
            return new Statement() {

                // TODO(lukes): we could generate null writes for when object typed fields go out of
                // scope.  This would potentially allow intermediate results to be collected sooner.
                @Override
                protected void doGen(CodeBuilder adapter) {
                    for (Label label : endLabels) {
                        adapter.visitLabel(label);
                    }
                }
            };
        }

        private Variable doCreate(String name, Label start, Label end, Expression initExpr, VarKey key, SaveStrategy strategy) {
            int index = reserveSlotFor(initExpr.resultType());
            LocalVariable local = LocalVariable.createLocal(name, index, initExpr.resultType(), start, end);
            Variable var;
            switch(strategy) {
                case DERIVED:
                    var = new DerivedVariable(initExpr, local);
                    break;
                case NEVER:
                    var = new TemporaryVariable(initExpr, local);
                    break;
                case STORE:
                    var = new FieldSavedVariable(initExpr, local);
                    break;
                default:
                    throw new AssertionError();
            }
            currentFrame.put(key, var);
            allVariables.add(var);
            return var;
        }
    };
}
Also used : LocalVariable(com.google.template.soy.jbcsrc.restricted.LocalVariable) Statement(com.google.template.soy.jbcsrc.restricted.Statement) Label(org.objectweb.asm.Label) LocalVariable(com.google.template.soy.jbcsrc.restricted.LocalVariable) LinkedHashMap(java.util.LinkedHashMap) CodeBuilder(com.google.template.soy.jbcsrc.restricted.CodeBuilder) Expression(com.google.template.soy.jbcsrc.restricted.Expression)

Aggregations

CodeBuilder (com.google.template.soy.jbcsrc.restricted.CodeBuilder)5 LocalVariable (com.google.template.soy.jbcsrc.restricted.LocalVariable)5 Statement (com.google.template.soy.jbcsrc.restricted.Statement)5 Label (org.objectweb.asm.Label)4 Expression (com.google.template.soy.jbcsrc.restricted.Expression)3 ArrayList (java.util.ArrayList)2 CompiledMethodBody (com.google.template.soy.jbcsrc.SoyNodeCompiler.CompiledMethodBody)1 Scope (com.google.template.soy.jbcsrc.TemplateVariableManager.Scope)1 Variable (com.google.template.soy.jbcsrc.TemplateVariableManager.Variable)1 SoyExpression (com.google.template.soy.jbcsrc.restricted.SoyExpression)1 AppendableAndOptions (com.google.template.soy.jbcsrc.restricted.SoyJbcSrcPrintDirective.Streamable.AppendableAndOptions)1 TemplateNode (com.google.template.soy.soytree.TemplateNode)1 TemplateParam (com.google.template.soy.soytree.defn.TemplateParam)1 LinkedHashMap (java.util.LinkedHashMap)1