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