KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > debugger > jpda > projects > AST2Bytecode


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.debugger.jpda.projects;
21
22 import com.sun.corba.se.impl.protocol.InfoOnlyServantCacheLocalCRDImpl;
23 import com.sun.source.tree.ArrayAccessTree;
24 import com.sun.source.tree.AssignmentTree;
25 import com.sun.source.tree.BinaryTree;
26 import com.sun.source.tree.CompilationUnitTree;
27 import com.sun.source.tree.CompoundAssignmentTree;
28 import com.sun.source.tree.ConditionalExpressionTree;
29 import com.sun.source.tree.ExpressionTree;
30 import com.sun.source.tree.IdentifierTree;
31 import com.sun.source.tree.InstanceOfTree;
32 import com.sun.source.tree.LineMap;
33 import com.sun.source.tree.LiteralTree;
34 import com.sun.source.tree.MemberSelectTree;
35 import com.sun.source.tree.MethodInvocationTree;
36 import com.sun.source.tree.NewArrayTree;
37 import com.sun.source.tree.NewClassTree;
38 import com.sun.source.tree.ParenthesizedTree;
39 import com.sun.source.tree.Tree;
40 import com.sun.source.tree.TypeCastTree;
41 import com.sun.source.tree.UnaryTree;
42 import com.sun.source.util.SourcePositions;
43 import com.sun.source.util.TreePath;
44 import com.sun.source.util.Trees;
45 import java.util.ArrayList JavaDoc;
46 import java.util.HashMap JavaDoc;
47 import java.util.List JavaDoc;
48 import java.util.Map JavaDoc;
49 import java.util.Set JavaDoc;
50 import javax.lang.model.element.TypeElement;
51 import javax.lang.model.type.TypeKind;
52 import javax.lang.model.type.TypeMirror;
53 import javax.lang.model.util.Types;
54 import org.netbeans.api.java.source.CompilationController;
55 import org.netbeans.api.java.source.ElementUtilities;
56
57 import org.netbeans.spi.debugger.jpda.EditorContext;
58
59 /**
60  * This class tries to match the AST expression to bytecode. The result
61  * of this match is provided as an
62  * {@link org.netbeans.spi.debugger.jpda.EditorContext.ExpressionTree} object.
63  *
64  * @author Martin Entlicher
65  */

66 class AST2Bytecode {
67     
68     /** Creates a new instance of AST2Bytecode */
69     private AST2Bytecode() {
70     }
71     
72     static EditorContext.Operation[] matchSourceTree2Bytecode(
73             CompilationUnitTree cu, CompilationController ci,
74             List JavaDoc<Tree> treeNodes, ExpressionScanner.ExpressionsInfo info,
75             byte[] bytecodes, int[] indexes, byte[] constantPool,
76             OperationCreationDelegate opCreationDelegate,
77             Map<Tree, EditorContext.Operation> nodeOperations) {
78         
79         Trees trees = ci.getTrees();
80         Types types = ci.getTypes();
81         SourcePositions sp = trees.getSourcePositions();
82         //List<Tree> treeNodes = linearizeTree(expTrees);
83
if (treeNodes == null) return null;
84         int length = treeNodes.size();
85         List JavaDoc<EditorContext.Operation> operations = new ArrayList JavaDoc<EditorContext.Operation>(length);
86         LineMap lineMap = cu.getLineMap();
87         int indexesIndex = 0;
88         int from = indexes[indexesIndex];
89         int to = indexes[indexesIndex + 1];
90         for (int treeIndex = 0; treeIndex < length; treeIndex++) {
91             Tree node = treeNodes.get(treeIndex);
92             Tree.Kind kind = node.getKind();
93             EditorContext.Operation op = null;
94             if (kind.equals(Tree.Kind.METHOD_INVOCATION) ||
95                 kind.equals(Tree.Kind.NEW_CLASS)) {
96                 
97                 int opcode;
98                 do {
99                     do {
100                         opcode = bytecodes[from] & 0xFF;
101                         if (isMethodCall(opcode)) {
102                             break;
103                         }
104                         from += getInstrSize(opcode, bytecodes, from);
105                     } while (from < to);
106                     if (from < to) {
107                         break;
108                     }
109                     if ((indexesIndex + 2) < indexes.length) {
110                         indexesIndex += 2;
111                         from = indexes[indexesIndex];
112                         to = indexes[indexesIndex + 1];
113                     } else {
114                         break;
115                     }
116                 } while (true);
117                 if (from < to) { // We have the method call
118
int pos = (int) sp.getStartPosition(cu, node);
119                     EditorContext.Position startPosition =
120                             opCreationDelegate.createPosition(
121                                     pos,
122                                     (int) lineMap.getLineNumber(pos),
123                                     (int) lineMap.getColumnNumber(pos)
124                             );
125                     pos = (int) sp.getEndPosition(cu, node);
126                     EditorContext.Position endPosition =
127                             opCreationDelegate.createPosition(
128                                     pos,
129                                     (int) lineMap.getLineNumber(pos),
130                                     (int) lineMap.getColumnNumber(pos)
131                             );
132                     Tree identifier;
133                     String JavaDoc methodName;
134                     String JavaDoc methodClassType;
135                     if (kind.equals(Tree.Kind.NEW_CLASS)) {
136                         identifier = ((NewClassTree) node).getIdentifier();
137                         methodName = "<init>";
138                         TreePath iPath = TreePath.getPath(cu, identifier);
139                         TypeMirror type = trees.getTypeMirror(iPath);
140                         assert type.getKind() == TypeKind.DECLARED;
141                         TypeElement te = (TypeElement) types.asElement(type);
142                         methodClassType = ElementUtilities.getBinaryName(te);
143                     } else {
144                         //identifier = ((MemberSelectTree) ((MethodInvocationTree) node).getMethodSelect()).getIdentifier();
145
identifier = ((MethodInvocationTree) node).getMethodSelect();
146                         if (identifier.getKind() == Tree.Kind.IDENTIFIER) {
147                             methodName = ((IdentifierTree) identifier).getName().toString();
148                             TreePath iPath = TreePath.getPath(cu, identifier);
149                             TypeElement te = trees.getScope(iPath).getEnclosingClass();
150                             methodClassType = ElementUtilities.getBinaryName(te);
151                         } else {
152                             methodName = ((MemberSelectTree) identifier).getIdentifier().toString();
153                             ExpressionTree exp = ((MemberSelectTree) identifier).getExpression();
154                             TreePath expPath = TreePath.getPath(cu, exp);
155                             TypeMirror type = trees.getTypeMirror(expPath);
156                             assert type.getKind() == TypeKind.DECLARED;
157                             TypeElement te = (TypeElement) types.asElement(type);
158                             methodClassType = ElementUtilities.getBinaryName(te);
159                         }
160                     }
161                     pos = (int) sp.getStartPosition(cu, identifier);
162                     EditorContext.Position methodStartPosition =
163                             opCreationDelegate.createPosition(
164                                     pos,
165                                     (int) lineMap.getLineNumber(pos),
166                                     (int) lineMap.getColumnNumber(pos)
167                             );
168                     pos = (int) sp.getEndPosition(cu, identifier);
169                     EditorContext.Position methodEndPosition =
170                             opCreationDelegate.createPosition(
171                                     pos,
172                                     (int) lineMap.getLineNumber(pos),
173                                     (int) lineMap.getColumnNumber(pos)
174                             );
175                     /*
176                     EditorContext.Operation op =
177                             opCreationDelegate.createOperation(
178                                     startPosition,
179                                     endPosition,
180                                     from
181                             );
182                      */

183                     op = opCreationDelegate.createMethodOperation(
184                                     startPosition,
185                                     endPosition,
186                                     methodStartPosition,
187                                     methodEndPosition,
188                                     methodName,
189                                     methodClassType,
190                                     from
191                             );
192                     //treeNodes.get(treeIndex).setCodeIndex(from);
193
from += getInstrSize(opcode, bytecodes, from);
194                     operations.add(op);
195                 } else {
196                     return null; // Mismatch
197
}
198             }
199             if (op != null) {
200                 nodeOperations.put(node, op);
201             }
202         }
203         // Check the rest of the bytecode for method calls:
204
do {
205             while (from < to) {
206                 int opcode = bytecodes[(int) from] & 0xFF;
207                 if (isMethodCall(opcode)) {
208                     return null; // Mismatch
209
}
210                 from += getInstrSize(opcode, bytecodes, from);
211             }
212             if ((indexesIndex + 2) < indexes.length) {
213                 indexesIndex += 2;
214                 from = indexes[indexesIndex];
215                 to = indexes[indexesIndex + 1];
216             } else {
217                 break;
218             }
219         } while (true);
220         /*
221         // Assign next operations:
222         for (int treeIndex = 0; treeIndex < length; treeIndex++) {
223             Tree node = treeNodes.get(treeIndex);
224             Set<Tree> nextNodes = info.getNextExpressions(node);
225             if (nextNodes != null) {
226                 EditorContext.Operation op = nodeOperations.get(node);
227                 if (op == null) {
228                     for (int backIndex = treeIndex - 1; backIndex >= 0; backIndex--) {
229                         node = treeNodes.get(backIndex);
230                         op = nodeOperations.get(node);
231                         if (op != null) break;
232                     }
233                 }
234                 if (op != null) {
235                     assignNext(op, opCreationDelegate, info, nodeOperations,
236                                nextNodes, treeNodes);
237                 }
238             }
239         }
240          */

241         return operations.toArray(new EditorContext.Operation[] {});
242     }
243     
244     /*private static void assignNext(EditorContext.Operation op,
245                                    OperationCreationDelegate opCreationDelegate,
246                                    ExpressionScanner.ExpressionsInfo info,
247                                    Map<Tree, EditorContext.Operation> nodeOperations,
248                                    Set<Tree> nextNodes,
249                                    List<Tree> allNodes) {
250         for (Tree t : nextNodes) {
251             EditorContext.Operation nextOp = nodeOperations.get(t);
252             if (nextOp != null) {
253                 opCreationDelegate.addNextOperationTo(op, nextOp);
254             } else {
255                 Set<Tree> nextNextNodes = info.getNextExpressions(t);
256                 if (nextNextNodes == null) {
257                     boolean check = false;
258                     for (int treeIndex = 0; treeIndex < allNodes.size(); treeIndex++) {
259                         Tree node = allNodes.get(treeIndex);
260                         if (check) {
261                             nextNextNodes = info.getNextExpressions(node);
262                             if (nextNextNodes != null) break;
263                         } else {
264                             if (t == node) {
265                                 check = true;
266                             }
267                         }
268                     }
269                 } else {
270                     assignNext(op, opCreationDelegate, info, nodeOperations, nextNextNodes, allNodes);
271                 }
272             }
273         }
274     }*/

275     
276     private static boolean isMethodCall(int opcode) {
277         return opcode >= 182 && opcode <= 185;
278     }
279     
280     private static int getInstrSize(int opcode, byte[] bytecodes, long codeIndex) {
281         if (opcode <= 15) return 1; // nop - dconst_1
282
if (opcode == 16) return 2; // bipush <byte>
283
if (opcode == 17) return 3; // sipush <byte1> <byte2>
284
if (opcode == 18) return 2; // ldc <index>
285
if (opcode <= 20) return 3; // ldc_w <byte1> <byte2>, ldc2_w <byte1> <byte2>
286
if (opcode <= 25) return 2; // iload <index>, lload <index>, fload <index>, dload <index>, aload <index>
287
if (opcode <= 53) return 1; // <x>load_<n>, <x>aload
288
if (opcode <= 58) return 2; // <x>store <index>
289
if (opcode <= 86) return 1; // <x>store_<n>, <x>astore
290
if (opcode <= 94) return 1; // pop*, dup*
291
if (opcode <= 131) return 1; // swap, <x>add, <x>sub, <x>mul, <x>div, <x>rem, <x>neg, *sh*, <x>and, <x>or, <x>xor
292
if (opcode <= 132) return 3; // iinc <index> <const>
293
if (opcode <= 147) return 1; // <x>2<x>
294
if (opcode <= 152) return 1; // <x>cmp<x>
295
if (opcode <= 168) return 3; // if<cond> <branchbyte1> <branchbyte2>, goto <branchbyte1> <branchbyte2>, jsr <branchbyte1> <branchbyte2>
296
if (opcode <= 169) return 2; // ret <index>
297
if (opcode == 170) return tableswitchSize(bytecodes, codeIndex);
298         if (opcode == 171) return lookupswitchSize(bytecodes, codeIndex);
299         if (opcode <= 177) return 1; // <x>return
300
if (opcode <= 184) return 3; // <get/put><static/field> <byte1> <byte2>, invokevirtual, invokespecial, invokestatic
301
if (opcode == 185) return 5; // invokeinterface
302
// 186 not used
303
if (opcode == 187) return 3; // new <byte1> <byte2>
304
if (opcode == 188) return 2; // newarray <atype>
305
if (opcode == 189) return 3; // anewarray <byte1> <byte2>
306
if (opcode <= 191) return 1; // arraylength, athrow
307
if (opcode <= 193) return 3; // checkcast <byte1> <byte2>, instanceof <byte1> <byte2>
308
if (opcode <= 195) return 1; // monitorenter, monitorexit
309
if (opcode == 196) return wideSize(bytecodes, codeIndex);
310         if (opcode == 197) return 4; // multianewarray
311
if (opcode <= 199) return 3; // ifnull/ifnonnull <byte1> <byte2>
312
if (opcode <= 201) return 5; // goto_w/jsr_w 4x<byte>
313
return 1; // reserved opcodes
314
}
315     
316     private static int tableswitchSize(byte[] bytecodes, long codeIndex) {
317         int padding = 4 - ((int) codeIndex % 4); // Following byte begins at an address that is a multiple of 4
318
int pos = (int) codeIndex + padding;
319         pos += 4; // default
320
int low = readInt(bytecodes, pos);
321         pos += 4; // low
322
int high = readInt(bytecodes, pos);
323         pos += 4; // high
324
pos += (high - low + 1) << 2; // high - low + 1 32-bit offsets
325
return pos - (int) codeIndex;
326     }
327     
328     private static int lookupswitchSize(byte[] bytecodes, long codeIndex) {
329         int padding = 4 - ((int) codeIndex % 4); // Following byte begins at an address that is a multiple of 4
330
int pos = (int) codeIndex + padding;
331         pos += 4; // default
332
int npairs = readInt(bytecodes, pos);
333         pos += 4; // npairs
334
pos += npairs << 3; // npairs 2x32-bit numbers (pairs)
335
return pos - (int) codeIndex;
336     }
337     
338     private static int wideSize(byte[] bytecodes, long codeIndex) {
339         int opcode = bytecodes[(int) codeIndex + 1] & 0xFF;
340         if (opcode == 132) { // iinc
341
return 6;
342         } else {
343             return 4;
344         }
345     }
346     
347     private static int readUnsignedShort(byte[] bytecodes, int pos) {
348         return ((bytecodes[pos] & 0xFF) << 8) | (bytecodes[pos + 1] & 0xFF);
349     }
350     
351     private static int readInt(byte[] bytecodes, int pos) {
352         return (bytecodes[pos ] & 0xFF) << 24 |
353                 (bytecodes[pos + 1] & 0xFF) << 16 |
354                 (bytecodes[pos + 2] & 0xFF) << 8 |
355                 (bytecodes[pos + 3] & 0xFF);
356     }
357
358     
359     static interface OperationCreationDelegate {
360         
361         /*
362             EditorContext.Operation createOperation(
363                     EditorContext.Position startPosition,
364                     EditorContext.Position endPosition,
365                     int bytecodeIndex);
366          */

367             
368             EditorContext.Operation createMethodOperation(
369                     EditorContext.Position startPosition,
370                     EditorContext.Position endPosition,
371                     EditorContext.Position methodStartPosition,
372                     EditorContext.Position methodEndPosition,
373                     String JavaDoc methodName, String JavaDoc methodClassType,
374                     int bytecodeIndex);
375             
376             EditorContext.Position createPosition(int offset, int line, int column);
377             
378             void addNextOperationTo(EditorContext.Operation operation,
379                                     EditorContext.Operation next);
380
381     }
382 }
383
Popular Tags