Support for reflection on primitive types. All tests finish in the browser.
2 * Back 2 Browser Bytecode Translator
3 * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
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.
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.
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.
18 package org.apidesign.vm4brwsr;
20 import java.io.IOException;
21 import org.apidesign.javap.RuntimeConstants;
22 import org.apidesign.javap.TypeArray;
24 final class LocalsMapper {
25 private final TypeArray argTypeRecords;
26 private final TypeArray localTypeRecords;
28 public LocalsMapper(final TypeArray stackMapArgs) {
29 final TypeArray initTypeRecords = new TypeArray();
30 updateRecords(initTypeRecords, stackMapArgs);
32 argTypeRecords = initTypeRecords;
33 localTypeRecords = new TypeArray(initTypeRecords);
36 public void outputArguments(final Appendable out) throws IOException {
37 final int argRecordCount = argTypeRecords.getSize();
38 if (argRecordCount > 0) {
39 Variable variable = getVariable(argTypeRecords, 0);
42 int i = variable.isCategory2() ? 2 : 1;
43 while (i < argRecordCount) {
44 variable = getVariable(argTypeRecords, i);
47 i += variable.isCategory2() ? 2 : 1;
52 public void syncWithFrameLocals(final TypeArray frameLocals) {
53 updateRecords(localTypeRecords, frameLocals);
56 public Variable setI(final int index) {
57 return setT(index, VarType.INTEGER);
60 public Variable setL(final int index) {
61 return setT(index, VarType.LONG);
64 public Variable setF(final int index) {
65 return setT(index, VarType.FLOAT);
68 public Variable setD(final int index) {
69 return setT(index, VarType.DOUBLE);
72 public Variable setA(final int index) {
73 return setT(index, VarType.REFERENCE);
76 public Variable setT(final int index, final int type) {
77 updateRecord(localTypeRecords, index, type);
78 return Variable.getLocalVariable(type, index);
81 public Variable getI(final int index) {
82 return getT(index, VarType.INTEGER);
85 public Variable getL(final int index) {
86 return getT(index, VarType.LONG);
89 public Variable getF(final int index) {
90 return getT(index, VarType.FLOAT);
93 public Variable getD(final int index) {
94 return getT(index, VarType.DOUBLE);
97 public Variable getA(final int index) {
98 return getT(index, VarType.REFERENCE);
101 public Variable getT(final int index, final int type) {
102 final int oldRecordValue = localTypeRecords.get(index);
103 if ((oldRecordValue & 0xff) != type) {
104 throw new IllegalStateException("Type mismatch");
107 return Variable.getLocalVariable(type, index);
110 private static void updateRecords(final TypeArray typeRecords,
111 final TypeArray stackMapTypes) {
112 final int srcSize = stackMapTypes.getSize();
113 for (int i = 0, dstIndex = 0; i < srcSize; ++i) {
114 final int smType = stackMapTypes.get(i);
115 if (smType == RuntimeConstants.ITEM_Bogus) {
119 final int varType = VarType.fromStackMapType(smType);
120 updateRecord(typeRecords, dstIndex, varType);
121 dstIndex += VarType.isCategory2(varType) ? 2 : 1;
125 private static void updateRecord(final TypeArray typeRecords,
126 final int index, final int type) {
127 if (typeRecords.getSize() < (index + 1)) {
128 typeRecords.setSize(index + 1);
131 final int oldRecordValue = typeRecords.get(index);
132 final int usedTypesMask =
133 (oldRecordValue >> 8) | (1 << type);
134 typeRecords.set(index, (usedTypesMask << 8) | type);
137 private static Variable getVariable(final TypeArray typeRecords,
139 return Variable.getLocalVariable(typeRecords.get(index) & 0xff, index);