vm/src/main/java/org/apidesign/vm4brwsr/LocalsMapper.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Sat, 26 Jan 2013 08:47:05 +0100
changeset 592 5e13b1ac2886
parent 319 83f638b13242
permissions -rw-r--r--
In order to support fields of the same name in subclasses we are now prefixing them with name of the class that defines them. To provide convenient way to access them from generated bytecode and also directly from JavaScript, there is a getter/setter function for each field. It starts with _ followed by the field name. If called with a parameter, it sets the field, with a parameter it just returns it.
     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 }