1 /*******************************************************************************
 
   2  * Copyright (c) 2000, 2003 IBM Corporation and others.
 
   3  * All rights reserved. This program and the accompanying materials 
 
   4  * are made available under the terms of the Common Public License v1.0
 
   5  * which accompanies this distribution, and is available at
 
   6  * http://www.eclipse.org/legal/cpl-v10.html
 
   9  *     IBM Corporation - initial API and implementation
 
  10  *******************************************************************************/
 
  11 package net.sourceforge.phpdt.internal.compiler.codegen;
 
  13 import net.sourceforge.phpdt.internal.compiler.lookup.LocalVariableBinding;
 
  14 import net.sourceforge.phpdt.internal.compiler.problem.AbortMethod;
 
  17  * This type is a port of smalltalks JavaLabel
 
  20 //      public CodeStream codeStream;
 
  21         final static int POS_NOT_SET = -1;
 
  22         public int position = POS_NOT_SET; // position=POS_NOT_SET Then it's pos is not set.
 
  23         public int[] forwardReferences = new int[10]; // Add an overflow check here.
 
  24         public int forwardReferenceCount = 0;
 
  25         private boolean isWide = false;
 
  29  * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
 
  31 //public Label(CodeStream codeStream) {
 
  32 //      this.codeStream = codeStream;
 
  35  * Add a forward refrence for the array.
 
  37 void addForwardReference(int iPos) {
 
  39         if (forwardReferenceCount >= (length = forwardReferences.length))
 
  40                 System.arraycopy(forwardReferences, 0, (forwardReferences = new int[2*length]), 0, length);
 
  41         forwardReferences[forwardReferenceCount++] = iPos;
 
  44  * Add a forward refrence for the array.
 
  46 public void appendForwardReferencesFrom(Label otherLabel) {
 
  47         int otherCount = otherLabel.forwardReferenceCount;
 
  48         if (otherCount == 0) return;
 
  49         int length = forwardReferences.length;
 
  50         int neededSpace = otherCount + forwardReferenceCount;
 
  51         if (neededSpace >= length){
 
  52                 System.arraycopy(forwardReferences, 0, (forwardReferences = new int[neededSpace]), 0, forwardReferenceCount);
 
  54         // append other forward references at the end, so they will get updated as well
 
  55         System.arraycopy(otherLabel.forwardReferences, 0, forwardReferences, forwardReferenceCount, otherCount);
 
  56         forwardReferenceCount = neededSpace;
 
  59 * Put down  a refernece to the array at the location in the codestream.
 
  62 //      if (position == POS_NOT_SET) {
 
  63 //              addForwardReference(codeStream.position);
 
  64 //              // Leave two bytes free to generate the jump afterwards
 
  65 //              codeStream.position += 2;
 
  66 //              codeStream.classFileOffset += 2;
 
  69 //               * Position is set. Write it if it is not a wide branch.
 
  71 //              int offset = position - codeStream.position + 1;
 
  72 //              if (Math.abs(offset) > 0x7FFF && !this.codeStream.wideMode) {
 
  73 //                      throw new AbortMethod(CodeStream.RESTART_IN_WIDE_MODE);
 
  75 //              codeStream.writeSignedShort((short) offset);
 
  79 * No support for wide branches yet
 
  82 //      if (position == POS_NOT_SET) {
 
  83 //              addForwardReference(codeStream.position);
 
  84 //              // Leave 4 bytes free to generate the jump offset afterwards
 
  86 //              codeStream.position += 4;
 
  87 //              codeStream.classFileOffset += 4;
 
  88 //      } else { //Position is set. Write it!
 
  89 //              codeStream.writeSignedWord(position - codeStream.position + 1);
 
  95 public boolean hasForwardReferences() {
 
  96         return forwardReferenceCount != 0;
 
  99  * Some placed labels might be branching to a goto bytecode which we can optimize better.
 
 101 //public void inlineForwardReferencesFromLabelsTargeting(int gotoLocation) {
 
 103 // Code required to optimized unreachable gotos.
 
 104 //      public boolean isBranchTarget(int location) {
 
 105 //              Label[] labels = codeStream.labels;
 
 106 //              for (int i = codeStream.countLabels - 1; i >= 0; i--){
 
 107 //                      Label label = labels[i];
 
 108 //                      if ((label.position == location) && label.isStandardLabel()){
 
 116 //      Label[] labels = codeStream.labels;
 
 117 //      for (int i = codeStream.countLabels - 1; i >= 0; i--){
 
 118 //              Label label = labels[i];
 
 119 //              if ((label.position == gotoLocation) && label.isStandardLabel()){
 
 120 //                      this.appendForwardReferencesFrom(label);
 
 122 //                       Code required to optimized unreachable gotos.
 
 123 //                              label.position = POS_NOT_SET;
 
 126 //                      break; // same target labels should be contiguous
 
 130 public boolean isStandardLabel(){
 
 134 * Place the label. If we have forward references resolve them.
 
 136 //public void place() { // Currently lacking wide support.
 
 137 //      if (position == POS_NOT_SET) {
 
 138 //              position = codeStream.position;
 
 139 //              codeStream.addLabel(this);
 
 140 //              int oldPosition = position;
 
 141 //              boolean optimizedBranch = false;
 
 142 //              // TURNED OFF since fail on 1F4IRD9
 
 143 //              if (forwardReferenceCount != 0) {
 
 144 //                      if (optimizedBranch = (forwardReferences[forwardReferenceCount - 1] + 2 == position) && (codeStream.bCodeStream[codeStream.classFileOffset - 3] == CodeStream.OPC_goto)) {
 
 145 //                              codeStream.position = (position -= 3);
 
 146 //                              codeStream.classFileOffset -= 3;
 
 147 //                              forwardReferenceCount--;
 
 148 //                              // also update the PCs in the related debug attributes
 
 150 //                                      int index = codeStream.pcToSourceMapSize - 1;
 
 151 //                                              while ((index >= 0) && (codeStream.pcToSourceMap[index][1] == oldPosition)) {
 
 152 //                                                      codeStream.pcToSourceMap[index--][1] = position;
 
 155 //                              // Beginning of new code
 
 156 //                              int index = codeStream.pcToSourceMapSize - 2;
 
 157 //                              if (codeStream.lastEntryPC == oldPosition) {
 
 158 //                                      codeStream.lastEntryPC = position;
 
 160 //                              if ((index >= 0) && (codeStream.pcToSourceMap[index] == position)) {
 
 161 //                                      codeStream.pcToSourceMapSize-=2;
 
 163 //                              // end of new code
 
 164 //                              if (codeStream.generateLocalVariableTableAttributes) {
 
 165 //                                      LocalVariableBinding locals[] = codeStream.locals;
 
 166 //                                      for (int i = 0, max = locals.length; i < max; i++) {
 
 167 //                                              LocalVariableBinding local = locals[i];
 
 168 //                                              if ((local != null) && (local.initializationCount > 0)) {
 
 169 //                                                      if (local.initializationPCs[((local.initializationCount - 1) << 1) + 1] == oldPosition) {
 
 170 //                                                              // we want to prevent interval of size 0 to have a negative size.
 
 171 //                                                              // see PR 1GIRQLA: ITPJCORE:ALL - ClassFormatError for local variable attribute
 
 172 //                                                              local.initializationPCs[((local.initializationCount - 1) << 1) + 1] = position;
 
 174 //                                                      if (local.initializationPCs[(local.initializationCount - 1) << 1] == oldPosition) {
 
 175 //                                                              local.initializationPCs[(local.initializationCount - 1) << 1] = position;
 
 182 //              for (int i = 0; i < forwardReferenceCount; i++) {
 
 183 //                      int offset = position - forwardReferences[i] + 1;
 
 184 //                      if (Math.abs(offset) > 0x7FFF && !this.codeStream.wideMode) {
 
 185 //                              throw new AbortMethod(CodeStream.RESTART_IN_WIDE_MODE);
 
 187 //                      if (this.codeStream.wideMode) {
 
 188 //                              if (this.isWide) {
 
 189 //                                      codeStream.writeSignedWord(forwardReferences[i], offset);
 
 191 //                                      codeStream.writeSignedShort(forwardReferences[i], (short) offset);
 
 194 //                              codeStream.writeSignedShort(forwardReferences[i], (short) offset);
 
 197 //              // For all labels placed at that position we check if we need to rewrite the jump
 
 198 //              // offset. It is the case each time a label had a forward reference to the current position.
 
 199 //              // Like we change the current position, we have to change the jump offset. See 1F4IRD9 for more details.
 
 200 //              if (optimizedBranch) {
 
 201 //                      for (int i = 0; i < codeStream.countLabels; i++) {
 
 202 //                              Label label = codeStream.labels[i];
 
 203 //                              if (oldPosition == label.position) {
 
 204 //                                      label.position = position;
 
 205 //                                      if (label instanceof CaseLabel) {
 
 206 //                                              int offset = position - ((CaseLabel) label).instructionPosition;
 
 207 //                                              for (int j = 0; j < label.forwardReferenceCount; j++) {
 
 208 //                                                      int forwardPosition = label.forwardReferences[j];
 
 209 //                                                      codeStream.writeSignedWord(forwardPosition, offset);
 
 212 //                                              for (int j = 0; j < label.forwardReferenceCount; j++) {
 
 213 //                                                      int forwardPosition = label.forwardReferences[j];
 
 214 //                                                      int offset = position - forwardPosition + 1;
 
 215 //                                                      if (Math.abs(offset) > 0x7FFF && !this.codeStream.wideMode) {
 
 216 //                                                              throw new AbortMethod(CodeStream.RESTART_IN_WIDE_MODE);
 
 218 //                                                      if (this.codeStream.wideMode) {
 
 219 //                                                              if (this.isWide) {
 
 220 //                                                                      codeStream.writeSignedWord(forwardPosition, offset);
 
 222 //                                                                      codeStream.writeSignedShort(forwardPosition, (short) offset);
 
 225 //                                                              codeStream.writeSignedShort(forwardPosition, (short) offset);
 
 235  * Print out the receiver
 
 237 public String toString() {
 
 238         StringBuffer buffer = new StringBuffer("(position="); //$NON-NLS-1$
 
 239         buffer.append(position);
 
 240         buffer.append(", forwards = ["); //$NON-NLS-1$
 
 241         for (int i = 0; i < forwardReferenceCount - 1; i++)
 
 242                 buffer.append(forwardReferences[i] + ", "); //$NON-NLS-1$
 
 243         if (forwardReferenceCount >= 1)
 
 244                 buffer.append(forwardReferences[forwardReferenceCount-1]);
 
 245         buffer.append("] )"); //$NON-NLS-1$
 
 246         return buffer.toString();
 
 249 public void resetStateForCodeGeneration() {
 
 250         this.position = POS_NOT_SET;
 
 251         this.forwardReferenceCount = 0;