rt/vm/src/main/java/org/apidesign/vm4brwsr/LocalsMapper.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Tue, 26 Feb 2013 16:54:16 +0100
changeset 772 d382dacfd73f
parent 442 vm/src/main/java/org/apidesign/vm4brwsr/LocalsMapper.java@b107ed66f2e7
child 810 9eb750594b15
permissions -rw-r--r--
Moving modules around so the runtime is under one master pom and can be built without building other modules that are in the repository
     1 /**
     2  * Back 2 Browser Bytecode Translator
     3  * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     4  *
     5  * This program is free software: you can redistribute it and/or modify
     6  * it under the terms of the GNU General Public License as published by
     7  * the Free Software Foundation, version 2 of the License.
     8  *
     9  * This program is distributed in the hope that it will be useful,
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  * GNU General Public License for more details.
    13  *
    14  * You should have received a copy of the GNU General Public License
    15  * along with this program. Look for COPYING file in the top folder.
    16  * If not, see http://opensource.org/licenses/GPL-2.0.
    17  */
    18 package org.apidesign.vm4brwsr;
    19 
    20 import java.io.IOException;
    21 import org.apidesign.javap.RuntimeConstants;
    22 import org.apidesign.javap.TypeArray;
    23 
    24 final class LocalsMapper {
    25     private final TypeArray argTypeRecords;
    26     private final TypeArray localTypeRecords;
    27 
    28     public LocalsMapper(final TypeArray stackMapArgs) {
    29         final TypeArray initTypeRecords = new TypeArray();
    30         updateRecords(initTypeRecords, stackMapArgs);
    31 
    32         argTypeRecords = initTypeRecords;
    33         localTypeRecords = new TypeArray(initTypeRecords);
    34     }
    35 
    36     public void outputArguments(final Appendable out, boolean isStatic) throws IOException {
    37         final int argRecordCount = argTypeRecords.getSize();
    38         int first = isStatic ? 0 : 1;
    39         if (argRecordCount > first) {
    40             Variable variable = getVariable(argTypeRecords, first);
    41             out.append(variable);
    42 
    43             int i = first + (variable.isCategory2() ? 2 : 1);
    44             while (i < argRecordCount) {
    45                 variable = getVariable(argTypeRecords, i);
    46                 out.append(", ");
    47                 out.append(variable);
    48                 i += variable.isCategory2() ? 2 : 1;
    49             }
    50         }
    51     }
    52 
    53     public void syncWithFrameLocals(final TypeArray frameLocals) {
    54         updateRecords(localTypeRecords, frameLocals);
    55     }
    56 
    57     public Variable setI(final int index) {
    58         return setT(index, VarType.INTEGER);
    59     }
    60 
    61     public Variable setL(final int index) {
    62         return setT(index, VarType.LONG);
    63     }
    64 
    65     public Variable setF(final int index) {
    66         return setT(index, VarType.FLOAT);
    67     }
    68 
    69     public Variable setD(final int index) {
    70         return setT(index, VarType.DOUBLE);
    71     }
    72 
    73     public Variable setA(final int index) {
    74         return setT(index, VarType.REFERENCE);
    75     }
    76 
    77     public Variable setT(final int index, final int type) {
    78         updateRecord(localTypeRecords, index, type);
    79         return Variable.getLocalVariable(type, index);
    80     }
    81 
    82     public Variable getI(final int index) {
    83         return getT(index, VarType.INTEGER);
    84     }
    85 
    86     public Variable getL(final int index) {
    87         return getT(index, VarType.LONG);
    88     }
    89 
    90     public Variable getF(final int index) {
    91         return getT(index, VarType.FLOAT);
    92     }
    93 
    94     public Variable getD(final int index) {
    95         return getT(index, VarType.DOUBLE);
    96     }
    97 
    98     public Variable getA(final int index) {
    99         return getT(index, VarType.REFERENCE);
   100     }
   101 
   102     public Variable getT(final int index, final int type) {
   103         final int oldRecordValue = localTypeRecords.get(index);
   104         if ((oldRecordValue & 0xff) != type) {
   105             throw new IllegalStateException("Type mismatch");
   106         }
   107 
   108         return Variable.getLocalVariable(type, index);
   109     }
   110 
   111     private static void updateRecords(final TypeArray typeRecords,
   112                                       final TypeArray stackMapTypes) {
   113         final int srcSize = stackMapTypes.getSize();
   114         for (int i = 0, dstIndex = 0; i < srcSize; ++i) {
   115             final int smType = stackMapTypes.get(i);
   116             if (smType == RuntimeConstants.ITEM_Bogus) {
   117                 ++dstIndex;
   118                 continue;
   119             }
   120             final int varType = VarType.fromStackMapType(smType);
   121             updateRecord(typeRecords, dstIndex, varType);
   122             dstIndex += VarType.isCategory2(varType) ? 2 : 1;
   123         }
   124     }
   125 
   126     private static void updateRecord(final TypeArray typeRecords,
   127                                      final int index, final int type) {
   128         if (typeRecords.getSize() < (index + 1)) {
   129             typeRecords.setSize(index + 1);
   130         }
   131 
   132         final int oldRecordValue = typeRecords.get(index);
   133         final int usedTypesMask =
   134                 (oldRecordValue >> 8) | (1 << type);
   135         typeRecords.set(index, (usedTypesMask << 8) | type);
   136     }
   137 
   138     private static Variable getVariable(final TypeArray typeRecords,
   139                                         final int index) {
   140         return Variable.getLocalVariable(typeRecords.get(index) & 0xff, index);
   141     }
   142 }