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.
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, 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);
43 int i = first + (variable.isCategory2() ? 2 : 1);
44 while (i < argRecordCount) {
45 variable = getVariable(argTypeRecords, i);
48 i += variable.isCategory2() ? 2 : 1;
53 public void syncWithFrameLocals(final TypeArray frameLocals) {
54 updateRecords(localTypeRecords, frameLocals);
57 public Variable setI(final int index) {
58 return setT(index, VarType.INTEGER);
61 public Variable setL(final int index) {
62 return setT(index, VarType.LONG);
65 public Variable setF(final int index) {
66 return setT(index, VarType.FLOAT);
69 public Variable setD(final int index) {
70 return setT(index, VarType.DOUBLE);
73 public Variable setA(final int index) {
74 return setT(index, VarType.REFERENCE);
77 public Variable setT(final int index, final int type) {
78 updateRecord(localTypeRecords, index, type);
79 return Variable.getLocalVariable(type, index);
82 public Variable getI(final int index) {
83 return getT(index, VarType.INTEGER);
86 public Variable getL(final int index) {
87 return getT(index, VarType.LONG);
90 public Variable getF(final int index) {
91 return getT(index, VarType.FLOAT);
94 public Variable getD(final int index) {
95 return getT(index, VarType.DOUBLE);
98 public Variable getA(final int index) {
99 return getT(index, VarType.REFERENCE);
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");
108 return Variable.getLocalVariable(type, index);
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) {
120 final int varType = VarType.fromStackMapType(smType);
121 updateRecord(typeRecords, dstIndex, varType);
122 dstIndex += VarType.isCategory2(varType) ? 2 : 1;
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);
132 final int oldRecordValue = typeRecords.get(index);
133 final int usedTypesMask =
134 (oldRecordValue >> 8) | (1 << type);
135 typeRecords.set(index, (usedTypesMask << 8) | type);
138 private static Variable getVariable(final TypeArray typeRecords,
140 return Variable.getLocalVariable(typeRecords.get(index) & 0xff, index);