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 LookupSwitchForm extends SwitchForm {
023:
024: public LookupSwitchForm(int opcode, String name) {
025: super (opcode, name);
026: }
027:
028: public LookupSwitchForm(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_values[] = new int[case_count];
040: for (int index = 0; index < case_count; index++) {
041: case_values[index] = operandManager.nextCaseValues();
042: }
043: int case_pcs[] = new int[case_count];
044: for (int index = 0; index < case_count; index++) {
045: case_pcs[index] = operandManager.nextLabel();
046: }
047:
048: int[] labelsArray = new int[case_count + 1];
049: labelsArray[0] = default_pc;
050: for (int index = 1; index < case_count + 1; index++) {
051: labelsArray[index] = case_pcs[index - 1];
052: }
053: byteCode.setByteCodeTargets(labelsArray);
054:
055: // All this gets dumped into the rewrite bytes of the
056: // poor bytecode.
057:
058: // Unlike most byte codes, the LookupSwitch is a
059: // variable-sized bytecode. Because of this, the
060: // rewrite array has to be defined here individually
061: // for each bytecode, rather than in the ByteCodeForm
062: // class.
063:
064: // First, there's the bytecode. Then there are 0-3
065: // bytes of padding so that the first (default)
066: // label is on a 4-byte offset.
067: int padLength = 3 - (codeLength % 4);
068: int rewriteSize = 1 + padLength + 4 // defaultbytes
069: + 4 // npairs
070: + (4 * case_values.length) + (4 * case_pcs.length);
071:
072: int[] newRewrite = new int[rewriteSize];
073: int rewriteIndex = 0;
074:
075: // Fill in what we can now
076: // opcode
077: newRewrite[rewriteIndex++] = byteCode.getOpcode();
078:
079: // padding
080: for (int index = 0; index < padLength; index++) {
081: newRewrite[rewriteIndex++] = 0;
082: }
083:
084: // defaultbyte
085: // This gets overwritten by fixUpByteCodeTargets
086: newRewrite[rewriteIndex++] = -1;
087: newRewrite[rewriteIndex++] = -1;
088: newRewrite[rewriteIndex++] = -1;
089: newRewrite[rewriteIndex++] = -1;
090:
091: // npairs
092: int npairsIndex = rewriteIndex;
093: setRewrite4Bytes(case_values.length, npairsIndex, newRewrite);
094: rewriteIndex += 4;
095:
096: // match-offset pairs
097: // The case_values aren't overwritten, but the
098: // case_pcs will get overwritten by fixUpByteCodeTargets
099: for (int index = 0; index < case_values.length; index++) {
100: // match
101: setRewrite4Bytes(case_values[index], rewriteIndex,
102: newRewrite);
103: rewriteIndex += 4;
104: // offset
105: newRewrite[rewriteIndex++] = -1;
106: newRewrite[rewriteIndex++] = -1;
107: newRewrite[rewriteIndex++] = -1;
108: newRewrite[rewriteIndex++] = -1;
109: }
110: byteCode.setRewrite(newRewrite);
111: }
112: }
|