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: public class TableSwitchForm extends SwitchForm {
023:
024: public TableSwitchForm(int opcode, String name) {
025: super (opcode, name);
026: }
027:
028: public TableSwitchForm(int opcode, String name, int[] rewrite) {
029: super (opcode, name, rewrite);
030: }
031:
032: /* (non-Javadoc)
033: * @see org.apache.harmony.pack200.bytecode.forms.SwitchForm#setByteCodeOperands(org.apache.harmony.pack200.bytecode.ByteCode, org.apache.harmony.pack200.bytecode.OperandManager, int)
034: */
035: public void setByteCodeOperands(ByteCode byteCode,
036: OperandManager operandManager, int codeLength) {
037: int case_count = operandManager.nextCaseCount();
038: int default_pc = operandManager.nextLabel();
039: int case_value = -1;
040: case_value = operandManager.nextCaseValues();
041:
042: int case_pcs[] = new int[case_count];
043: for (int index = 0; index < case_count; index++) {
044: case_pcs[index] = operandManager.nextLabel();
045: }
046:
047: int[] labelsArray = new int[case_count + 1];
048: labelsArray[0] = default_pc;
049: for (int index = 1; index < case_count + 1; index++) {
050: labelsArray[index] = case_pcs[index - 1];
051: }
052: byteCode.setByteCodeTargets(labelsArray);
053:
054: int lowValue = case_value;
055: int highValue = lowValue + case_count - 1;
056: // All this gets dumped into the rewrite bytes of the
057: // poor bytecode.
058:
059: // Unlike most byte codes, the TableSwitch is a
060: // variable-sized bytecode. Because of this, the
061: // rewrite array has to be defined here individually
062: // for each bytecode, rather than in the ByteCodeForm
063: // class.
064:
065: // First, there's the bytecode. Then there are 0-3
066: // bytes of padding so that the first (default)
067: // label is on a 4-byte offset.
068: int padLength = 3 - (codeLength % 4);
069: int rewriteSize = 1 + padLength + 4 // defaultbytes
070: + 4 // lowbyte
071: + 4 // highbyte
072: + (4 * case_pcs.length);
073:
074: int[] newRewrite = new int[rewriteSize];
075: int rewriteIndex = 0;
076:
077: // Fill in what we can now
078: // opcode
079: newRewrite[rewriteIndex++] = byteCode.getOpcode();
080:
081: // padding
082: for (int index = 0; index < padLength; index++) {
083: newRewrite[rewriteIndex++] = 0;
084: }
085:
086: // defaultbyte
087: // This gets overwritten by fixUpByteCodeTargets
088: newRewrite[rewriteIndex++] = -1;
089: newRewrite[rewriteIndex++] = -1;
090: newRewrite[rewriteIndex++] = -1;
091: newRewrite[rewriteIndex++] = -1;
092:
093: // lowbyte
094: int lowbyteIndex = rewriteIndex;
095: setRewrite4Bytes(lowValue, lowbyteIndex, newRewrite);
096: rewriteIndex += 4;
097:
098: // highbyte
099: int highbyteIndex = rewriteIndex;
100: setRewrite4Bytes(highValue, highbyteIndex, newRewrite);
101: rewriteIndex += 4;
102:
103: // jump offsets
104: // The case_pcs will get overwritten by fixUpByteCodeTargets
105: for (int index = 0; index < case_count; index++) {
106: // offset
107: newRewrite[rewriteIndex++] = -1;
108: newRewrite[rewriteIndex++] = -1;
109: newRewrite[rewriteIndex++] = -1;
110: newRewrite[rewriteIndex++] = -1;
111: }
112: byteCode.setRewrite(newRewrite);
113: }
114: }
|