001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.harmony.pack200.bytecode.forms;
018:
019: import org.apache.harmony.pack200.bytecode.ByteCode;
020: import org.apache.harmony.pack200.bytecode.OperandManager;
021:
022: /**
023: * This class implements the byte code form for the
024: * wide instruction. Unlike other instructions, it
025: * can take multiple forms, depending on what is being
026: * widened.
027: */
028: public class WideForm extends VariableInstructionForm {
029:
030: public WideForm(int opcode, String name) {
031: super (opcode, name);
032: }
033:
034: public WideForm(int opcode, String name, int[] rewrite) {
035: super (opcode, name, rewrite);
036: }
037:
038: public int getOperandType() {
039: return TYPE_WIDE;
040: }
041:
042: public boolean hasWideOperand() {
043: return true;
044: }
045:
046: /* (non-Javadoc)
047: * @see org.apache.harmony.pack200.bytecode.forms.ByteCodeForm#setByteCodeOperands(org.apache.harmony.pack200.bytecode.ByteCode, org.apache.harmony.pack200.bytecode.OperandTable, org.apache.harmony.pack200.SegmentConstantPool)
048: */
049: public void setByteCodeOperands(ByteCode byteCode,
050: OperandManager operandManager, int codeLength) {
051: int instruction = operandManager.nextWideByteCode();
052: if (instruction == 132) {
053: setByteCodeOperandsFormat2(instruction, byteCode,
054: operandManager, codeLength);
055: } else {
056: setByteCodeOperandsFormat1(instruction, byteCode,
057: operandManager, codeLength);
058: }
059: }
060:
061: /**
062: * This method sets the rewrite array for the bytecode
063: * using Format 1 of the JVM spec: an opcode and two index
064: * bytes. This is used for ?load/?store/ret
065: * @param instruction should be 132
066: * @param byteCode the byte code whose rewrite array should be updated
067: * @param operandManager the source of the operands
068: * @param codeLength ignored
069: */
070: protected void setByteCodeOperandsFormat1(int instruction,
071: ByteCode byteCode, OperandManager operandManager,
072: int codeLength) {
073:
074: // Even though this code is really similar to the
075: // code for setByteCodeOperandsFormat2, I've left it
076: // distinct here. This is so changing one will
077: // not change the other - if there is a need to change,
078: // there's a good chance that the formats will
079: // differ, so an updater will not have to disentangle
080: // it.
081: int local = operandManager.nextLocal();
082:
083: // Unlike most byte codes, the wide bytecode is a
084: // variable-sized bytecode. Because of this, the
085: // rewrite array has to be defined here individually
086: // for each bytecode, rather than in the ByteCodeForm
087: // class.
088:
089: int[] newRewrite = new int[4];
090: int rewriteIndex = 0;
091:
092: // Fill in what we can now
093: // wide opcode
094: newRewrite[rewriteIndex++] = byteCode.getOpcode();
095:
096: // "real" instruction that is widened
097: newRewrite[rewriteIndex++] = instruction;
098:
099: // Index bytes
100: setRewrite2Bytes(local, rewriteIndex, newRewrite);
101: rewriteIndex += 2;
102:
103: byteCode.setRewrite(newRewrite);
104: }
105:
106: /**
107: * This method sets the rewrite array for the bytecode
108: * using Format 2 of the JVM spec: an opcode, two index
109: * bytes, and two constant bytes. This is used for iinc.
110: * @param instruction int should be 132
111: * @param byteCode ByteCode whose rewrite array should be updated
112: * @param operandManager OperandManager source of the operands
113: * @param codeLength ignored
114: */
115: protected void setByteCodeOperandsFormat2(int instruction,
116: ByteCode byteCode, OperandManager operandManager,
117: int codeLength) {
118:
119: int local = operandManager.nextLocal();
120: int constWord = operandManager.nextShort();
121:
122: // Unlike most byte codes, the wide bytecode is a
123: // variable-sized bytecode. Because of this, the
124: // rewrite array has to be defined here individually
125: // for each bytecode, rather than in the ByteCodeForm
126: // class.
127:
128: int[] newRewrite = new int[6];
129: int rewriteIndex = 0;
130:
131: // Fill in what we can now
132: // wide opcode
133: newRewrite[rewriteIndex++] = byteCode.getOpcode();
134:
135: // "real" instruction that is widened
136: newRewrite[rewriteIndex++] = instruction;
137:
138: // Index bytes
139: setRewrite2Bytes(local, rewriteIndex, newRewrite);
140: rewriteIndex += 2;
141:
142: // constant bytes
143: setRewrite2Bytes(constWord, rewriteIndex, newRewrite);
144: rewriteIndex += 2; // not strictly necessary, but just in case something comes along later
145:
146: byteCode.setRewrite(newRewrite);
147: }
148: }
|