org.formulacompiler.compiler.internal.bytecode.RootSectionCompiler.java Source code

Java tutorial

Introduction

Here is the source code for org.formulacompiler.compiler.internal.bytecode.RootSectionCompiler.java

Source

/*
 * Copyright (c) 2006-2009 by Abacus Research AG, Switzerland.
 * All rights reserved.
 *
 * This file is part of the Abacus Formula Compiler (AFC).
 *
 * For commercial licensing, please contact sales(at)formulacompiler.com.
 *
 * AFC is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * AFC is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AFC.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.formulacompiler.compiler.internal.bytecode;

import org.formulacompiler.compiler.CompilerException;
import org.formulacompiler.compiler.internal.model.SectionModel;
import org.formulacompiler.runtime.ComputationMode;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.commons.GeneratorAdapter;

import static org.formulacompiler.compiler.internal.bytecode.ByteCodeEngineCompiler.*;
import static org.formulacompiler.runtime.internal.Runtime_v2.BROKEN_REF;

final class RootSectionCompiler extends SectionCompiler {
    private static final org.objectweb.asm.commons.Method EMPTY_CONSTRUCTOR_METHOD = org.objectweb.asm.commons.Method
            .getMethod("void <init>()");
    private static final org.objectweb.asm.commons.Method RESET_METHOD = org.objectweb.asm.commons.Method
            .getMethod("void reset()");

    RootSectionCompiler(ByteCodeEngineCompiler _compiler, SectionModel _model,
            boolean _computationListenerEnabled) {
        super(_compiler, _model, GEN_ROOT_NAME, _computationListenerEnabled);
    }

    @Override
    protected SectionCompiler parentSectionCompiler() {
        return null;
    }

    @Override
    protected RootSectionCompiler rootSectionCompiler() {
        return this;
    }

    @Override
    protected void buildMembers() {
        super.buildMembers();
        buildEnvironmentMember();
    }

    private void buildEnvironmentMember() {
        // Package visible so subsections can read it.
        newField(Opcodes.ACC_FINAL, ENV_MEMBER_NAME, ENV_DESC);
    }

    private MethodCompiler constructor;

    @Override
    protected void buildConstructorWithInputs() throws CompilerException {

        this.constructor = new MethodCompiler(RootSectionCompiler.this, 0, "<init>",
                "(" + inputType().getDescriptor() + ENV_DESC + ")V") {
            @Override
            protected void compileBody() throws CompilerException {
                final GeneratorAdapter mv = mv();

                // super( _inputs ); or super();
                callInheritedConstructor(mv, 1);

                // this.environment = _environment;
                mv.loadThis();
                mv.loadArg(1);
                mv.putField(section().classType(), ENV_MEMBER_NAME, ENV_CLASS);

                // this.inputs = _inputs;
                if (hasInputs()) {
                    mv.loadThis();
                    mv.loadArg(0);
                    storeInputs(mv);
                }

                //this.sectionInfo = new SectionInfoImpl(...);
                if (isComputationListenerEnabled()) {
                    mv.loadThis();
                    mv.push(-1); //section index
                    final ExpressionCompilerForNumbers c = numericCompiler();
                    c.compile_util_createSectionInfo(model().getName(), null, BROKEN_REF, BROKEN_REF, null,
                            BROKEN_REF, BROKEN_REF);
                    mv.putField(section().classType(), SECTION_INFO_MEMBER_NAME, SECTION_INFO_CLASS);
                }

                if (RootSectionCompiler.this.computationTimeCompiled) {
                    mv.loadThis();
                    mv.newInstance(COMP_TIME_CLASS);
                    mv.dup();
                    mv.invokeConstructor(COMP_TIME_CLASS, EMPTY_CONSTRUCTOR_METHOD);
                    mv.putField(section().classType(), COMP_TIME_MEMBER_NAME, COMP_TIME_CLASS);
                }

                if (RootSectionCompiler.this.computationModeCompiled) {
                    mv.loadThis();
                    final ComputationMode computationMode = model().getEngine().getComputationMode();
                    mv.getStatic(COMP_MODE_CLASS, computationMode.name(), COMP_MODE_CLASS);
                    mv.putField(classType(), COMP_MODE_MEMBER_NAME, COMP_MODE_CLASS);
                }

                mv.visitInsn(Opcodes.RETURN);
            }
        };
    }

    @Override
    protected void finalizeConstructor() throws CompilerException {
        this.constructor.compile();
    }

    @Override
    protected void compileEnvironmentAccess(GeneratorAdapter _mv) {
        _mv.loadThis();
        _mv.getField(classType(), ENV_MEMBER_NAME, ENV_CLASS);
    }

    private boolean computationModeCompiled = false;

    private void compileComputationMode() {
        if (!this.computationModeCompiled) {
            newField(Opcodes.ACC_FINAL, COMP_MODE_MEMBER_NAME, COMP_MODE_DESC);
            this.computationModeCompiled = true;
        }
    }

    @Override
    protected void compileComputationModeAccess(GeneratorAdapter _mv) {
        _mv.loadThis();
        compileComputationModeAccessGivenThis(_mv);
    }

    void compileComputationModeAccessGivenThis(GeneratorAdapter _mv) {
        compileComputationMode();
        _mv.getField(classType(), COMP_MODE_MEMBER_NAME, COMP_MODE_CLASS);
    }

    private boolean computationTimeCompiled = false;

    private void compileComputationTime() {
        if (!this.computationTimeCompiled) {
            newField(Opcodes.ACC_FINAL, COMP_TIME_MEMBER_NAME, COMP_TIME_DESC);
            if (hasReset()) {
                final GeneratorAdapter mv = resetter();
                mv.loadThis();
                mv.getField(classType(), COMP_TIME_MEMBER_NAME, COMP_TIME_CLASS);
                mv.invokeVirtual(COMP_TIME_CLASS, RESET_METHOD);
            }
            this.computationTimeCompiled = true;
        }
    }

    @Override
    protected void compileComputationTimeAccess(GeneratorAdapter _mv) {
        _mv.loadThis();
        compileComputationTimeAccessGivenThis(_mv);
    }

    void compileComputationTimeAccessGivenThis(GeneratorAdapter _mv) {
        compileComputationTime();
        _mv.getField(classType(), COMP_TIME_MEMBER_NAME, COMP_TIME_CLASS);
    }

}