KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > compiler > codegen > StackMapFrame


1 /*******************************************************************************
2  * Copyright (c) 2005, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.compiler.codegen;
12
13 import java.text.MessageFormat JavaDoc;
14
15 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
16 import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
17
18 public class StackMapFrame implements Cloneable JavaDoc {
19     public static final int USED = 1;
20     public static final int SAME_FRAME = 0;
21     public static final int CHOP_FRAME = 1;
22     public static final int APPEND_FRAME = 2;
23     public static final int SAME_FRAME_EXTENDED = 3;
24     public static final int FULL_FRAME = 4;
25     public static final int SAME_LOCALS_1_STACK_ITEMS = 5;
26     public static final int SAME_LOCALS_1_STACK_ITEMS_EXTENDED = 6;
27
28     public int pc;
29     public int numberOfStackItems;
30     private int numberOfLocals;
31     public int localIndex;
32     public VerificationTypeInfo[] locals;
33     public VerificationTypeInfo[] stackItems;
34     private int numberOfDifferentLocals = -1;
35     public int tagBits;
36
37 public StackMapFrame() {
38     this.numberOfLocals = -1;
39     this.numberOfDifferentLocals = -1;
40 }
41 public int getFrameType(StackMapFrame prevFrame) {
42     final int offsetDelta = this.getOffsetDelta(prevFrame);
43     switch(this.numberOfStackItems) {
44         case 0 :
45             switch(this.numberOfDifferentLocals(prevFrame)) {
46                 case 0 :
47                     return offsetDelta <= 63 ? SAME_FRAME : SAME_FRAME_EXTENDED;
48                 case 1 :
49                 case 2 :
50                 case 3 :
51                     return APPEND_FRAME;
52                 case -1 :
53                 case -2 :
54                 case -3 :
55                     return CHOP_FRAME;
56             }
57             break;
58         case 1 :
59             switch(this.numberOfDifferentLocals(prevFrame)) {
60                 case 0 :
61                     return offsetDelta <= 63 ? SAME_LOCALS_1_STACK_ITEMS : SAME_LOCALS_1_STACK_ITEMS_EXTENDED;
62             }
63     }
64     return FULL_FRAME;
65 }
66 public void addLocal(int resolvedPosition, VerificationTypeInfo info) {
67     if (this.locals == null) {
68         this.locals = new VerificationTypeInfo[resolvedPosition + 1];
69         this.locals[resolvedPosition] = info;
70     } else {
71         final int length = this.locals.length;
72         if (resolvedPosition >= length) {
73             System.arraycopy(this.locals, 0, this.locals = new VerificationTypeInfo[resolvedPosition + 1], 0, length);
74         }
75         this.locals[resolvedPosition] = info;
76     }
77 }
78 public void addStackItem(VerificationTypeInfo info) {
79     if (info == null) return;
80     if (this.stackItems == null) {
81         this.stackItems = new VerificationTypeInfo[1];
82         this.stackItems[0] = info;
83         this.numberOfStackItems = 1;
84     } else {
85         final int length = this.stackItems.length;
86         if (this.numberOfStackItems == length) {
87             System.arraycopy(this.stackItems, 0, this.stackItems = new VerificationTypeInfo[length + 1], 0, length);
88         }
89         this.stackItems[this.numberOfStackItems++] = info;
90     }
91 }
92 public void addStackItem(TypeBinding binding) {
93     this.addStackItem(new VerificationTypeInfo(binding));
94 }
95 public Object JavaDoc clone() throws CloneNotSupportedException JavaDoc {
96     StackMapFrame result = (StackMapFrame) super.clone();
97     result.numberOfLocals = -1;
98     result.numberOfDifferentLocals = -1;
99     result.pc = this.pc;
100     result.numberOfStackItems = this.numberOfStackItems;
101     
102     int length = this.locals == null ? 0 : this.locals.length;
103     if (length != 0) {
104         result.locals = new VerificationTypeInfo[length];
105         for (int i = 0; i < length; i++) {
106             final VerificationTypeInfo verificationTypeInfo = this.locals[i];
107             if (verificationTypeInfo != null) {
108                 result.locals[i] = (VerificationTypeInfo) verificationTypeInfo.clone();
109             }
110         }
111     }
112     length = this.numberOfStackItems;
113     if (length != 0) {
114         result.stackItems = new VerificationTypeInfo[length];
115         for (int i = 0; i < length; i++) {
116             result.stackItems[i] = (VerificationTypeInfo) this.stackItems[i].clone();
117         }
118     }
119     return result;
120 }
121 public int numberOfDiffentStackItems(StackMapFrame prevFrame) {
122     if (prevFrame == null) {
123         return this.numberOfStackItems;
124     }
125     return this.numberOfStackItems - prevFrame.numberOfStackItems;
126 }
127 public int numberOfDifferentLocals(StackMapFrame prevFrame) {
128     if (this.numberOfDifferentLocals != -1) return this.numberOfDifferentLocals;
129     if (prevFrame == null) {
130         this.numberOfDifferentLocals = 0;
131         return 0;
132     }
133     VerificationTypeInfo[] prevLocals = prevFrame.locals;
134     VerificationTypeInfo[] currentLocals = this.locals;
135     int prevLocalsLength = prevLocals == null ? 0 : prevLocals.length;
136     int currentLocalsLength = currentLocals == null ? 0 : currentLocals.length;
137     int prevNumberOfLocals = prevFrame.getNumberOfLocals();
138     int currentNumberOfLocals = this.getNumberOfLocals();
139
140     int result = 0;
141     if (prevNumberOfLocals == 0) {
142         if (currentNumberOfLocals != 0) {
143             // need to check if there is a hole in the locals
144
result = currentNumberOfLocals; // append if no hole and currentNumberOfLocals <= 3
145
int counter = 0;
146             for(int i = 0; i < currentLocalsLength && counter < currentNumberOfLocals; i++) {
147                 if (currentLocals[i] != null) {
148                     switch(currentLocals[i].id()) {
149                         case TypeIds.T_double :
150                         case TypeIds.T_long :
151                             i++;
152                     }
153                     counter++;
154                 } else {
155                     result = Integer.MAX_VALUE;
156                     this.numberOfDifferentLocals = result;
157                     return result;
158                 }
159             }
160         }
161     } else if (currentNumberOfLocals == 0) {
162         // need to check if there is a hole in the prev locals
163
int counter = 0;
164         result = -prevNumberOfLocals; // chop frame if no hole and prevNumberOfLocals <= 3
165
for(int i = 0; i < prevLocalsLength && counter < prevNumberOfLocals; i++) {
166             if (prevLocals[i] != null) {
167                 switch(prevLocals[i].id()) {
168                     case TypeIds.T_double :
169                     case TypeIds.T_long :
170                         i++;
171                 }
172                 counter++;
173             } else {
174                 result = Integer.MAX_VALUE;
175                 this.numberOfDifferentLocals = result;
176                 return result;
177             }
178         }
179     } else {
180         // need to see if prevLocals matches with currentLocals
181
int indexInPrevLocals = 0;
182         int indexInCurrentLocals = 0;
183         int currentLocalsCounter = 0;
184         int prevLocalsCounter = 0;
185         currentLocalsLoop: for (;indexInCurrentLocals < currentLocalsLength && currentLocalsCounter < currentNumberOfLocals; indexInCurrentLocals++) {
186             VerificationTypeInfo currentLocal = currentLocals[indexInCurrentLocals];
187             if (currentLocal != null) {
188                 currentLocalsCounter++;
189                 switch(currentLocal.id()) {
190                     case TypeIds.T_double :
191                     case TypeIds.T_long :
192                         indexInCurrentLocals++; // next entry is null
193
}
194             }
195             for (;indexInPrevLocals < prevLocalsLength && prevLocalsCounter < prevNumberOfLocals; indexInPrevLocals++) {
196                 VerificationTypeInfo prevLocal = prevLocals[indexInPrevLocals];
197                 if (prevLocal != null) {
198                     prevLocalsCounter++;
199                     switch(prevLocal.id()) {
200                         case TypeIds.T_double :
201                         case TypeIds.T_long :
202                             indexInPrevLocals++; // next entry is null
203
}
204                 }
205                 // now we need to check if prevLocal matches with currentLocal
206
// the index must be the same
207
if (equals(prevLocal, currentLocal) && indexInPrevLocals == indexInCurrentLocals) {
208                     if (result != 0) {
209                         result = Integer.MAX_VALUE;
210                         this.numberOfDifferentLocals = result;
211                         return result;
212                     }
213                 } else {
214                     // locals at the same location are not equals - this has to be a full frame
215
result = Integer.MAX_VALUE;
216                     this.numberOfDifferentLocals = result;
217                     return result;
218                 }
219                 indexInPrevLocals++;
220                 continue currentLocalsLoop;
221             }
222             // process remaining current locals
223
if (currentLocal != null) {
224                 result++;
225             } else {
226                 result = Integer.MAX_VALUE;
227                 this.numberOfDifferentLocals = result;
228                 return result;
229             }
230             indexInCurrentLocals++;
231             break currentLocalsLoop;
232         }
233         if (currentLocalsCounter < currentNumberOfLocals) {
234             for(;indexInCurrentLocals < currentLocalsLength && currentLocalsCounter < currentNumberOfLocals; indexInCurrentLocals++) {
235                 VerificationTypeInfo currentLocal = currentLocals[indexInCurrentLocals];
236                 if (currentLocal == null) {
237                     result = Integer.MAX_VALUE;
238                     this.numberOfDifferentLocals = result;
239                     return result;
240                 }
241                 result++;
242                 currentLocalsCounter++;
243                 switch(currentLocal.id()) {
244                     case TypeIds.T_double :
245                     case TypeIds.T_long :
246                         indexInCurrentLocals++; // next entry is null
247
}
248             }
249         } else if (prevLocalsCounter < prevNumberOfLocals) {
250             result = -result;
251             // process possible remaining prev locals
252
for(; indexInPrevLocals < prevLocalsLength && prevLocalsCounter < prevNumberOfLocals; indexInPrevLocals++) {
253                 VerificationTypeInfo prevLocal = prevLocals[indexInPrevLocals];
254                 if (prevLocal == null) {
255                     result = Integer.MAX_VALUE;
256                     this.numberOfDifferentLocals = result;
257                     return result;
258                 }
259                 result--;
260                 prevLocalsCounter++;
261                 switch(prevLocal.id()) {
262                     case TypeIds.T_double :
263                     case TypeIds.T_long :
264                         indexInPrevLocals++; // next entry is null
265
}
266             }
267         }
268     }
269     this.numberOfDifferentLocals = result;
270     return result;
271 }
272 public int getNumberOfLocals() {
273     if (this.numberOfLocals != -1) {
274         return this.numberOfLocals;
275     }
276     int result = 0;
277     final int length = this.locals == null ? 0 : this.locals.length;
278     for(int i = 0; i < length; i++) {
279         if (this.locals[i] != null) {
280             switch(this.locals[i].id()) {
281                 case TypeIds.T_double :
282                 case TypeIds.T_long :
283                     i++;
284             }
285             result++;
286         }
287     }
288     this.numberOfLocals = result;
289     return result;
290 }
291 public int getOffsetDelta(StackMapFrame prevFrame) {
292     if (prevFrame == null) return this.pc;
293     return prevFrame.pc == -1 ? this.pc : this.pc - prevFrame.pc - 1;
294 }
295 public String JavaDoc toString() {
296     StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
297     printFrame(buffer, this);
298     return String.valueOf(buffer);
299 }
300 private void printFrame(StringBuffer JavaDoc buffer, StackMapFrame frame) {
301     String JavaDoc pattern = "[pc : {0} locals: {1} stack items: {2}\n{3}\n{4}\n]"; //$NON-NLS-1$
302
int localsLength = frame.locals == null ? 0 : frame.locals.length;
303     buffer.append(MessageFormat.format(
304         pattern,
305         new String JavaDoc[] {
306             Integer.toString(frame.pc),
307             Integer.toString(frame.getNumberOfLocals()),
308             Integer.toString(frame.numberOfStackItems),
309             print(frame.locals, localsLength),
310             print(frame.stackItems, frame.numberOfStackItems)
311         }
312     ));
313 }
314 private String JavaDoc print(VerificationTypeInfo[] infos, int length) {
315     StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
316     buffer.append('[');
317     if (infos != null) {
318         for (int i = 0; i < length; i++) {
319             if (i != 0) buffer.append(',');
320             if (infos[i] == null) {
321                 buffer.append("top"); //$NON-NLS-1$
322
continue;
323             }
324             switch(infos[i].tag) {
325                 case VerificationTypeInfo.ITEM_NULL :
326                     buffer.append("null"); //$NON-NLS-1$
327
break;
328                 case VerificationTypeInfo.ITEM_UNINITIALIZED_THIS :
329                     buffer.append("uninitialized_this"); //$NON-NLS-1$
330
break;
331                 case VerificationTypeInfo.ITEM_TOP :
332                     buffer.append("top"); //$NON-NLS-1$
333
break;
334                 case VerificationTypeInfo.ITEM_UNINITIALIZED :
335                     buffer.append("uninitialized(").append(infos[i].readableName()).append(")"); //$NON-NLS-1$ //$NON-NLS-2$
336
break;
337                 default:
338                     buffer.append(infos[i].readableName());
339             }
340         }
341     }
342     buffer.append(']');
343     return String.valueOf(buffer);
344 }
345 public void setTopOfStack(TypeBinding typeBinding) {
346     this.stackItems[this.numberOfStackItems - 1].setBinding(typeBinding);
347 }
348 public void initializeReceiver() {
349     if (this.numberOfStackItems > 0) {
350         this.stackItems[this.numberOfStackItems - 1].tag = VerificationTypeInfo.ITEM_OBJECT;
351     }
352 }
353 public void removeLocals(int resolvedPosition) {
354     if (this.locals == null || resolvedPosition < 0) return;
355     if (resolvedPosition < this.locals.length) {
356         this.locals[resolvedPosition] = null;
357     }
358 }
359 public void putLocal(int resolvedPosition, VerificationTypeInfo info) {
360     if (this.locals == null) {
361         this.locals = new VerificationTypeInfo[resolvedPosition + 1];
362         this.locals[resolvedPosition] = info;
363     } else {
364         final int length = this.locals.length;
365         if (resolvedPosition >= length) {
366             System.arraycopy(this.locals, 0, this.locals = new VerificationTypeInfo[resolvedPosition + 1], 0, length);
367         }
368         this.locals[resolvedPosition] = info;
369     }
370 }
371 public void replaceWithElementType() {
372     VerificationTypeInfo info = this.stackItems[this.numberOfStackItems - 1];
373     try {
374         VerificationTypeInfo info2 = (VerificationTypeInfo) info.clone();
375         info2.replaceWithElementType();
376         this.stackItems[this.numberOfStackItems - 1] = info2;
377     } catch (CloneNotSupportedException JavaDoc e) {
378         // ignore
379
}
380 }
381 public int getIndexOfDifferentLocals(int differentLocalsCount) {
382     for (int i = this.locals.length - 1; i >= 0; i--) {
383         VerificationTypeInfo currentLocal = this.locals[i];
384         if (currentLocal == null) {
385             // check the previous slot
386
continue;
387         } else {
388             differentLocalsCount--;
389         }
390         if (differentLocalsCount == 0) {
391             return i;
392         }
393     }
394     return 0;
395 }
396 private boolean equals(VerificationTypeInfo info, VerificationTypeInfo info2) {
397     if (info == null) {
398         return info2 == null;
399     }
400     if (info2 == null) return false;
401     return info.equals(info2);
402 }
403 public void mergeLocals(StackMapFrame currentFrame) {
404     int currentFrameLocalsLength = currentFrame.locals == null ? 0 : currentFrame.locals.length;
405     int localsLength = this.locals == null ? 0 : this.locals.length;
406     for (int i = 0, max = Math.min(currentFrameLocalsLength, localsLength); i < max; i++) {
407         VerificationTypeInfo info = this.locals[i];
408         VerificationTypeInfo info2 = currentFrame.locals[i];
409         if (info == null) {
410             if (info2 != null) {
411                 this.locals[i] = info2;
412             }
413         } else if (info2 == null) {
414             this.locals[i] = null;
415         } else {
416             int tag1 = info.tag;
417             int tag2 = info2.tag;
418             if (tag1 != tag2) {
419                 this.locals[i] = null;
420             }
421         }
422     }
423 }
424 }
425
Popular Tags