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;