1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 package org.apache.commons.compress.harmony.unpack200.bytecode.forms; 18 19 import org.apache.commons.compress.harmony.unpack200.bytecode.ByteCode; 20 import org.apache.commons.compress.harmony.unpack200.bytecode.OperandManager; 21 22 /** 23 * This class implements the byte code form for the wide instruction. Unlike other instructions, it can take multiple forms, depending on what is being widened. 24 */ 25 public class WideForm extends VariableInstructionForm { 26 27 public WideForm(final int opcode, final String name) { 28 super(opcode, name); 29 } 30 31 /* 32 * (non-Javadoc) 33 * 34 * @see org.apache.commons.compress.harmony.unpack200.bytecode.forms.ByteCodeForm#setByteCodeOperands(org.apache.commons. 35 * compress.harmony.unpack200.bytecode.ByteCode, org.apache.commons.compress.harmony.unpack200.bytecode.OperandTable, 36 * org.apache.commons.compress.harmony.unpack200.SegmentConstantPool) 37 */ 38 @Override 39 public void setByteCodeOperands(final ByteCode byteCode, final OperandManager operandManager, final int codeLength) { 40 final int instruction = operandManager.nextWideByteCode(); 41 if (instruction == 132) { 42 setByteCodeOperandsFormat2(instruction, byteCode, operandManager, codeLength); 43 } else { 44 setByteCodeOperandsFormat1(instruction, byteCode, operandManager, codeLength); 45 } 46 } 47 48 /** 49 * This method sets the rewrite array for the bytecode using Format 1 of the JVM spec: an opcode and two index bytes. This is used for ?load/?store/ret 50 * 51 * @param instruction should be 132 52 * @param byteCode the byte code whose rewrite array should be updated 53 * @param operandManager the source of the operands 54 * @param codeLength ignored 55 */ 56 protected void setByteCodeOperandsFormat1(final int instruction, final ByteCode byteCode, final OperandManager operandManager, final int codeLength) { 57 58 // Even though this code is really similar to the 59 // code for setByteCodeOperandsFormat2, I've left it 60 // distinct here. This is so changing one will 61 // not change the other - if there is a need to change, 62 // there's a good chance that the formats will 63 // differ, so an updater will not have to disentangle 64 // it. 65 final int local = operandManager.nextLocal(); 66 67 // Unlike most byte codes, the wide bytecode is a 68 // variable-sized bytecode. Because of this, the 69 // rewrite array has to be defined here individually 70 // for each bytecode, rather than in the ByteCodeForm 71 // class. 72 73 final int[] newRewrite = new int[4]; 74 int rewriteIndex = 0; 75 76 // Fill in what we can now 77 // wide opcode 78 newRewrite[rewriteIndex++] = byteCode.getOpcode(); 79 80 // "real" instruction that is widened 81 newRewrite[rewriteIndex++] = instruction; 82 83 // Index bytes 84 setRewrite2Bytes(local, rewriteIndex, newRewrite); 85 rewriteIndex += 2; 86 87 byteCode.setRewrite(newRewrite); 88 } 89 90 /** 91 * This method sets the rewrite array for the bytecode using Format 2 of the JVM spec: an opcode, two index bytes, and two constant bytes. This is used for 92 * iinc. 93 * 94 * @param instruction int should be 132 95 * @param byteCode ByteCode whose rewrite array should be updated 96 * @param operandManager OperandManager source of the operands 97 * @param codeLength ignored 98 */ 99 protected void setByteCodeOperandsFormat2(final int instruction, final ByteCode byteCode, final OperandManager operandManager, final int codeLength) { 100 101 final int local = operandManager.nextLocal(); 102 final int constWord = operandManager.nextShort(); 103 104 // Unlike most byte codes, the wide bytecode is a 105 // variable-sized bytecode. Because of this, the 106 // rewrite array has to be defined here individually 107 // for each bytecode, rather than in the ByteCodeForm 108 // class. 109 110 final int[] newRewrite = new int[6]; 111 int rewriteIndex = 0; 112 113 // Fill in what we can now 114 // wide opcode 115 newRewrite[rewriteIndex++] = byteCode.getOpcode(); 116 117 // "real" instruction that is widened 118 newRewrite[rewriteIndex++] = instruction; 119 120 // Index bytes 121 setRewrite2Bytes(local, rewriteIndex, newRewrite); 122 rewriteIndex += 2; 123 124 // constant bytes 125 setRewrite2Bytes(constWord, rewriteIndex, newRewrite); 126 rewriteIndex += 2; // not strictly necessary, but just in case 127 // something comes along later 128 129 byteCode.setRewrite(newRewrite); 130 } 131 }