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