Applying pteague's patch (re #685)
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / codegen / Label.java
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
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.codegen;
12
13 /**
14  * This type is a port of smalltalks JavaLabel
15  */
16 public class Label {
17         // public CodeStream codeStream;
18         final static int POS_NOT_SET = -1;
19
20         public int position = POS_NOT_SET; // position=POS_NOT_SET Then it's pos is
21                                                                                 // not set.
22
23         public int[] forwardReferences = new int[10]; // Add an overflow check
24                                                                                                         // here.
25
26         public int forwardReferenceCount = 0;
27
28         private boolean isWide = false;
29
30         public Label() {
31         }
32
33         /**
34          * @param codeStream
35          *            net.sourceforge.phpdt.internal.compiler.codegen.CodeStream
36          */
37         // public Label(CodeStream codeStream) {
38         // this.codeStream = codeStream;
39         // }
40         /**
41          * Add a forward refrence for the array.
42          */
43         void addForwardReference(int iPos) {
44                 int length;
45                 if (forwardReferenceCount >= (length = forwardReferences.length))
46                         System.arraycopy(forwardReferences, 0,
47                                         (forwardReferences = new int[2 * length]), 0, length);
48                 forwardReferences[forwardReferenceCount++] = iPos;
49         }
50
51         /**
52          * Add a forward refrence for the array.
53          */
54         public void appendForwardReferencesFrom(Label otherLabel) {
55                 int otherCount = otherLabel.forwardReferenceCount;
56                 if (otherCount == 0)
57                         return;
58                 int length = forwardReferences.length;
59                 int neededSpace = otherCount + forwardReferenceCount;
60                 if (neededSpace >= length) {
61                         System.arraycopy(forwardReferences, 0,
62                                         (forwardReferences = new int[neededSpace]), 0,
63                                         forwardReferenceCount);
64                 }
65                 // append other forward references at the end, so they will get updated
66                 // as well
67                 System.arraycopy(otherLabel.forwardReferences, 0, forwardReferences,
68                                 forwardReferenceCount, otherCount);
69                 forwardReferenceCount = neededSpace;
70         }
71
72         /*
73          * Put down a refernece to the array at the location in the codestream.
74          */
75         // void branch() {
76         // if (position == POS_NOT_SET) {
77         // addForwardReference(codeStream.position);
78         // // Leave two bytes free to generate the jump afterwards
79         // codeStream.position += 2;
80         // codeStream.classFileOffset += 2;
81         // } else {
82         // /*
83         // * Position is set. Write it if it is not a wide branch.
84         // */
85         // int offset = position - codeStream.position + 1;
86         // if (Math.abs(offset) > 0x7FFF && !this.codeStream.wideMode) {
87         // throw new AbortMethod(CodeStream.RESTART_IN_WIDE_MODE);
88         // }
89         // codeStream.writeSignedShort((short) offset);
90         // }
91         // }
92         /*
93          * No support for wide branches yet
94          */
95         // void branchWide() {
96         // if (position == POS_NOT_SET) {
97         // addForwardReference(codeStream.position);
98         // // Leave 4 bytes free to generate the jump offset afterwards
99         // isWide = true;
100         // codeStream.position += 4;
101         // codeStream.classFileOffset += 4;
102         // } else { //Position is set. Write it!
103         // codeStream.writeSignedWord(position - codeStream.position + 1);
104         // }
105         // }
106         /**
107          * @return boolean
108          */
109         public boolean hasForwardReferences() {
110                 return forwardReferenceCount != 0;
111         }
112
113         /*
114          * Some placed labels might be branching to a goto bytecode which we can
115          * optimize better.
116          */
117         // public void inlineForwardReferencesFromLabelsTargeting(int gotoLocation)
118         // {
119         // /*
120         // Code required to optimized unreachable gotos.
121         // public boolean isBranchTarget(int location) {
122         // Label[] labels = codeStream.labels;
123         // for (int i = codeStream.countLabels - 1; i >= 0; i--){
124         // Label label = labels[i];
125         // if ((label.position == location) && label.isStandardLabel()){
126         // return true;
127         // }
128         // }
129         // return false;
130         // }
131         // */
132         //      
133         // Label[] labels = codeStream.labels;
134         // for (int i = codeStream.countLabels - 1; i >= 0; i--){
135         // Label label = labels[i];
136         // if ((label.position == gotoLocation) && label.isStandardLabel()){
137         // this.appendForwardReferencesFrom(label);
138         // /*
139         // Code required to optimized unreachable gotos.
140         // label.position = POS_NOT_SET;
141         // */
142         // } else {
143         // break; // same target labels should be contiguous
144         // }
145         // }
146         // }
147         public boolean isStandardLabel() {
148                 return true;
149         }
150
151         /*
152          * Place the label. If we have forward references resolve them.
153          */
154         // public void place() { // Currently lacking wide support.
155         // if (position == POS_NOT_SET) {
156         // position = codeStream.position;
157         // codeStream.addLabel(this);
158         // int oldPosition = position;
159         // boolean optimizedBranch = false;
160         // // TURNED OFF since fail on 1F4IRD9
161         // if (forwardReferenceCount != 0) {
162         // if (optimizedBranch = (forwardReferences[forwardReferenceCount - 1] + 2
163         // == position) && (codeStream.bCodeStream[codeStream.classFileOffset - 3]
164         // == CodeStream.OPC_goto)) {
165         // codeStream.position = (position -= 3);
166         // codeStream.classFileOffset -= 3;
167         // forwardReferenceCount--;
168         // // also update the PCs in the related debug attributes
169         // /** OLD CODE
170         // int index = codeStream.pcToSourceMapSize - 1;
171         // while ((index >= 0) && (codeStream.pcToSourceMap[index][1] ==
172         // oldPosition)) {
173         // codeStream.pcToSourceMap[index--][1] = position;
174         // }
175         // */
176         // // Beginning of new code
177         // int index = codeStream.pcToSourceMapSize - 2;
178         // if (codeStream.lastEntryPC == oldPosition) {
179         // codeStream.lastEntryPC = position;
180         // }
181         // if ((index >= 0) && (codeStream.pcToSourceMap[index] == position)) {
182         // codeStream.pcToSourceMapSize-=2;
183         // }
184         // // end of new code
185         // if (codeStream.generateLocalVariableTableAttributes) {
186         // LocalVariableBinding locals[] = codeStream.locals;
187         // for (int i = 0, max = locals.length; i < max; i++) {
188         // LocalVariableBinding local = locals[i];
189         // if ((local != null) && (local.initializationCount > 0)) {
190         // if (local.initializationPCs[((local.initializationCount - 1) << 1) + 1]
191         // == oldPosition) {
192         // // we want to prevent interval of size 0 to have a negative size.
193         // // see PR 1GIRQLA: ITPJCORE:ALL - ClassFormatError for local variable
194         // attribute
195         // local.initializationPCs[((local.initializationCount - 1) << 1) + 1] =
196         // position;
197         // }
198         // if (local.initializationPCs[(local.initializationCount - 1) << 1] ==
199         // oldPosition) {
200         // local.initializationPCs[(local.initializationCount - 1) << 1] = position;
201         // }
202         // }
203         // }
204         // }
205         // }
206         // }
207         // for (int i = 0; i < forwardReferenceCount; i++) {
208         // int offset = position - forwardReferences[i] + 1;
209         // if (Math.abs(offset) > 0x7FFF && !this.codeStream.wideMode) {
210         // throw new AbortMethod(CodeStream.RESTART_IN_WIDE_MODE);
211         // }
212         // if (this.codeStream.wideMode) {
213         // if (this.isWide) {
214         // codeStream.writeSignedWord(forwardReferences[i], offset);
215         // } else {
216         // codeStream.writeSignedShort(forwardReferences[i], (short) offset);
217         // }
218         // } else {
219         // codeStream.writeSignedShort(forwardReferences[i], (short) offset);
220         // }
221         // }
222         // // For all labels placed at that position we check if we need to rewrite
223         // the jump
224         // // offset. It is the case each time a label had a forward reference to
225         // the current position.
226         // // Like we change the current position, we have to change the jump
227         // offset. See 1F4IRD9 for more details.
228         // if (optimizedBranch) {
229         // for (int i = 0; i < codeStream.countLabels; i++) {
230         // Label label = codeStream.labels[i];
231         // if (oldPosition == label.position) {
232         // label.position = position;
233         // if (label instanceof CaseLabel) {
234         // int offset = position - ((CaseLabel) label).instructionPosition;
235         // for (int j = 0; j < label.forwardReferenceCount; j++) {
236         // int forwardPosition = label.forwardReferences[j];
237         // codeStream.writeSignedWord(forwardPosition, offset);
238         // }
239         // } else {
240         // for (int j = 0; j < label.forwardReferenceCount; j++) {
241         // int forwardPosition = label.forwardReferences[j];
242         // int offset = position - forwardPosition + 1;
243         // if (Math.abs(offset) > 0x7FFF && !this.codeStream.wideMode) {
244         // throw new AbortMethod(CodeStream.RESTART_IN_WIDE_MODE);
245         // }
246         // if (this.codeStream.wideMode) {
247         // if (this.isWide) {
248         // codeStream.writeSignedWord(forwardPosition, offset);
249         // } else {
250         // codeStream.writeSignedShort(forwardPosition, (short) offset);
251         // }
252         // } else {
253         // codeStream.writeSignedShort(forwardPosition, (short) offset);
254         // }
255         // }
256         // }
257         // }
258         // }
259         // }
260         // }
261         // }
262         /**
263          * Print out the receiver
264          */
265         public String toString() {
266                 StringBuffer buffer = new StringBuffer("(position="); //$NON-NLS-1$
267                 buffer.append(position);
268                 buffer.append(", forwards = ["); //$NON-NLS-1$
269                 for (int i = 0; i < forwardReferenceCount - 1; i++)
270                         buffer.append(forwardReferences[i] + ", "); //$NON-NLS-1$
271                 if (forwardReferenceCount >= 1)
272                         buffer.append(forwardReferences[forwardReferenceCount - 1]);
273                 buffer.append("] )"); //$NON-NLS-1$
274                 return buffer.toString();
275         }
276
277         public void resetStateForCodeGeneration() {
278                 this.position = POS_NOT_SET;
279                 this.forwardReferenceCount = 0;
280         }
281 }