WideForm.java

  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. import org.apache.commons.compress.harmony.unpack200.bytecode.ByteCode;
  19. import org.apache.commons.compress.harmony.unpack200.bytecode.OperandManager;

  20. /**
  21.  * 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.
  22.  */
  23. public class WideForm extends VariableInstructionForm {

  24.     public WideForm(final int opcode, final String name) {
  25.         super(opcode, name);
  26.     }

  27.     /*
  28.      * (non-Javadoc)
  29.      *
  30.      * @see org.apache.commons.compress.harmony.unpack200.bytecode.forms.ByteCodeForm#setByteCodeOperands(org.apache.commons.
  31.      * compress.harmony.unpack200.bytecode.ByteCode, org.apache.commons.compress.harmony.unpack200.bytecode.OperandTable,
  32.      * org.apache.commons.compress.harmony.unpack200.SegmentConstantPool)
  33.      */
  34.     @Override
  35.     public void setByteCodeOperands(final ByteCode byteCode, final OperandManager operandManager, final int codeLength) {
  36.         final int instruction = operandManager.nextWideByteCode();
  37.         if (instruction == 132) {
  38.             setByteCodeOperandsFormat2(instruction, byteCode, operandManager, codeLength);
  39.         } else {
  40.             setByteCodeOperandsFormat1(instruction, byteCode, operandManager, codeLength);
  41.         }
  42.     }

  43.     /**
  44.      * 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
  45.      *
  46.      * @param instruction    should be 132
  47.      * @param byteCode       the byte code whose rewrite array should be updated
  48.      * @param operandManager the source of the operands
  49.      * @param codeLength     ignored
  50.      */
  51.     protected void setByteCodeOperandsFormat1(final int instruction, final ByteCode byteCode, final OperandManager operandManager, final int codeLength) {

  52.         // Even though this code is really similar to the
  53.         // code for setByteCodeOperandsFormat2, I've left it
  54.         // distinct here. This is so changing one will
  55.         // not change the other - if there is a need to change,
  56.         // there's a good chance that the formats will
  57.         // differ, so an updater will not have to disentangle
  58.         // it.
  59.         final int local = operandManager.nextLocal();

  60.         // Unlike most byte codes, the wide bytecode is a
  61.         // variable-sized bytecode. Because of this, the
  62.         // rewrite array has to be defined here individually
  63.         // for each bytecode, rather than in the ByteCodeForm
  64.         // class.

  65.         final int[] newRewrite = new int[4];
  66.         int rewriteIndex = 0;

  67.         // Fill in what we can now
  68.         // wide opcode
  69.         newRewrite[rewriteIndex++] = byteCode.getOpcode();

  70.         // "real" instruction that is widened
  71.         newRewrite[rewriteIndex++] = instruction;

  72.         // Index bytes
  73.         setRewrite2Bytes(local, rewriteIndex, newRewrite);
  74.         rewriteIndex += 2;

  75.         byteCode.setRewrite(newRewrite);
  76.     }

  77.     /**
  78.      * 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
  79.      * iinc.
  80.      *
  81.      * @param instruction    int should be 132
  82.      * @param byteCode       ByteCode whose rewrite array should be updated
  83.      * @param operandManager OperandManager source of the operands
  84.      * @param codeLength     ignored
  85.      */
  86.     protected void setByteCodeOperandsFormat2(final int instruction, final ByteCode byteCode, final OperandManager operandManager, final int codeLength) {

  87.         final int local = operandManager.nextLocal();
  88.         final int constWord = operandManager.nextShort();

  89.         // Unlike most byte codes, the wide bytecode is a
  90.         // variable-sized bytecode. Because of this, the
  91.         // rewrite array has to be defined here individually
  92.         // for each bytecode, rather than in the ByteCodeForm
  93.         // class.

  94.         final int[] newRewrite = new int[6];
  95.         int rewriteIndex = 0;

  96.         // Fill in what we can now
  97.         // wide opcode
  98.         newRewrite[rewriteIndex++] = byteCode.getOpcode();

  99.         // "real" instruction that is widened
  100.         newRewrite[rewriteIndex++] = instruction;

  101.         // Index bytes
  102.         setRewrite2Bytes(local, rewriteIndex, newRewrite);
  103.         rewriteIndex += 2;

  104.         // constant bytes
  105.         setRewrite2Bytes(constWord, rewriteIndex, newRewrite);
  106.         rewriteIndex += 2; // not strictly necessary, but just in case
  107.         // something comes along later

  108.         byteCode.setRewrite(newRewrite);
  109.     }
  110. }