001 /*
002 * This file is part of the Jikes RVM project (http://jikesrvm.org).
003 *
004 * This file is licensed to You under the Eclipse Public License (EPL);
005 * You may not use this file except in compliance with the License. You
006 * may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/eclipse-1.0.php
009 *
010 * See the COPYRIGHT.txt file distributed with this work for information
011 * regarding copyright ownership.
012 */
013 package org.jikesrvm.compilers.baseline;
014
015 import org.jikesrvm.ArchitectureSpecific.BaselineCompilerImpl;
016 import org.jikesrvm.VM;
017 import org.jikesrvm.classloader.BytecodeConstants;
018 import org.jikesrvm.classloader.BytecodeStream;
019 import org.jikesrvm.classloader.ClassLoaderConstants;
020 import org.jikesrvm.classloader.ExceptionHandlerMap;
021 import org.jikesrvm.classloader.MethodReference;
022 import org.jikesrvm.classloader.NormalMethod;
023 import org.jikesrvm.classloader.TypeReference;
024
025 /**
026 * This class builds the reference and non-reference maps for a given method.
027 * The maps are recorded with ReferenceMaps. This class works with the baseline
028 * compiler, calculating the maps for local variables (including parameters),
029 * and the java operand stack. Given the basic blocks mapped out by BuildBB
030 * determine for each GC point (call sites and new's, etc) what the stack and
031 * variable maps are. Note that this class deals with reference maps (the term
032 * "stack maps" was not used as it is too ambiguous - does "stack" refer to the
033 * java operand stack or a C-like stack?; when processing java bytecodes it
034 * seemed best to use "stack" for java operand stack.)
035 */
036 final class BuildReferenceMaps implements BytecodeConstants, ClassLoaderConstants, BBConstants {
037
038 /**
039 * The entry in the reference map contains a value that is not a reference.
040 */
041 static final byte NON_REFERENCE = 0;
042 /**
043 * The entry in the reference map contains a value that is a reference.
044 */
045 static final byte REFERENCE = 1;
046 /**
047 * The entry in the reference map contains a JSR return address.
048 */
049 static final byte RETURN_ADDRESS = 2;
050 /**
051 * The entry in the reference map is not set in a JSR body.
052 */
053 static final byte NOT_SET = 0;
054 /**
055 * The entry in the reference map is set to a value that is a reference within a JSR body.
056 */
057 static final byte SET_TO_REFERENCE = 1;
058 /**
059 * The entry in the reference map is set to a value that is not a reference within a JSR body.
060 */
061 static final byte SET_TO_NONREFERENCE = 3;
062
063 private static enum PrimitiveSize {
064 ONEWORD, DOUBLEWORD
065 };
066
067 // These two variables are used and updated by more than one method in this class,
068 // therefore they need to be instance variables;
069 int workStkTop;
070 int JSRSubNext;
071
072 /**
073 * After the analysis of the blocks of a method, examine the byte codes again, to
074 * determine the reference maps for the gc points. Record the maps with
075 * referenceMaps.
076 */
077 public void buildReferenceMaps(NormalMethod method, int[] stackHeights, byte[] localTypes,
078 ReferenceMaps referenceMaps, BuildBB buildBB) {
079 //****************************************************************//
080 // These were calculated by BuildBB.determineTheBasicBlocks //
081 //****************************************************************//
082 int gcPointCount = buildBB.gcPointCount;
083 short[] byteToBlockMap = buildBB.byteToBlockMap;
084 BasicBlock[] basicBlocks = buildBB.basicBlocks;
085 int jsrCount = buildBB.numJsrs;
086
087 byte[][] bbMaps; // The starting map for each block, a block is not
088 // processed until it has a starting map.
089 int[] blockStkTop; // For each block, track where its current stack top is.
090
091 int currBBNum; // Block number of block currently being processed
092 byte[] currBBMap; // The current map, used during processing thru a block
093 int currBBStkTop; // Stack top for the current map
094
095 int currBBStkEmpty; // Level when stack is empty - value depends on number of locals
096 int paramCount; // Number of parameters to the method being processed
097
098 // Variables for processing JSR instructions, RET instructions and JSR subroutines
099 PendingRETInfo[] bbPendingRETs = null;
100 PendingRETInfo currPendingRET;
101 JSRSubroutineInfo[] JSRSubs = null;
102
103 // Blocks that need to be processed are put on the workStk
104 short[] workStk;
105
106 // Track whether a block has already been seen once. Any recording of maps done
107 // within such a block will be processed as a "rerecording" instead of a new map.
108 //
109 boolean[] blockSeen;
110
111 // blocks that represent "catch" blocks need special processing. Catch blocks
112 // also referred to as handlers
113 //
114 ExceptionHandlerMap exceptions; // exception table class for method being processed
115 int[] tryStartPC; // array of try start indicesinto byte code table
116 int[] tryEndPC; // array of try end indices into byte code table
117 int[] tryHandlerPC; // array of try handlers start indices into bytecode
118 int tryHandlerLength; // length of try handlers array
119 int[] reachableHandlerBBNums; // array of reachable handlers from a given try block
120 int reachableHandlersCount; // Number of reachable handlers
121 boolean[] handlerProcessed; // Handler blocks are processed after the normal flow. As
122 // they may be nested, they need to be handled
123 // individually. This array is used to track which
124 // have been processed.
125 boolean handlersAllDone;
126
127 // Other local variables
128 //
129 BytecodeStream bcodes; // byte codes for the method
130 short brBBNum; // For processing branches, need block number of target
131
132 final boolean debug = false;
133
134 // Note that the mapping done here is "double mapping" of parameters.
135 // Double mapping is when the parameters for a method are included in the map of
136 // the method as well as in the map of the caller of the method. The original
137 // intent was that with double mapping call sites that are tricks
138 // (eg Magic.callFunctionReturnVoid ) would at least be correctly mapped on one
139 // of the two sides. However with more recent changes to the runtime stack frame
140 // layout, the parameters specified on the caller side occupy different
141 // locations than the parameters on the callee side for the baseline compiler.
142 // Thus both need to be described.
143
144 //
145 // Initialization
146 //
147
148 // Determine what stack empty looks like
149 paramCount = method.getParameterWords();
150 if (!method.isStatic()) paramCount++;
151
152 currBBStkEmpty = method.getLocalWords() - 1; // -1 to locate the last "local" index
153
154 if (debug) VM.sysWrite("getLocalWords() : " + method.getLocalWords() + "\n");
155
156 // Get information from the method being processed
157 bcodes = method.getBytecodes();
158
159 // Set up the array of maps per block; block 0 is not used
160 int numBB = buildBB.bbf.getNumberofBlocks();
161 bbMaps = new byte[numBB + 1][];
162 blockStkTop = new int[bbMaps.length];
163 blockSeen = new boolean[bbMaps.length];
164
165 // Try Handler processing initialization
166
167 exceptions = method.getExceptionHandlerMap();
168 if (exceptions != null) {
169 tryStartPC = exceptions.getStartPC();
170 tryEndPC = exceptions.getEndPC();
171 tryHandlerPC = exceptions.getHandlerPC();
172 tryHandlerLength = tryHandlerPC.length;
173
174 reachableHandlerBBNums = new int[tryStartPC.length];
175 handlerProcessed = new boolean[tryStartPC.length];
176 if (jsrCount > 0) {
177 JSRSubs = new JSRSubroutineInfo[jsrCount];
178 JSRSubNext = 0;
179 bbPendingRETs = new PendingRETInfo[bbMaps.length];
180 }
181 handlersAllDone = (tryHandlerLength == 0);
182
183 // write poison values to help distinguish different errors
184 for (int ii = 0; ii < reachableHandlerBBNums.length; ii++) {
185 reachableHandlerBBNums[ii] = -1;
186 }
187 } else {
188 tryHandlerLength = 0;
189 handlersAllDone = true;
190 tryStartPC = null;
191 tryEndPC = null;
192 tryHandlerPC = null;
193 reachableHandlerBBNums = null;
194 handlerProcessed = null;
195 }
196 reachableHandlersCount = 0;
197
198 // Start a new set of maps with the reference Map class.
199 // 3rd argument is parameter count included with the maps
200 referenceMaps.startNewMaps(gcPointCount, jsrCount, paramCount);
201
202 // Set up the Work stack
203 workStk = new short[10 + tryHandlerLength];
204
205 // Start by putting the first block on the work stack
206 workStkTop = 0;
207 workStk[workStkTop] = byteToBlockMap[0];
208 currBBMap = new byte[method.getOperandWords() + currBBStkEmpty + 1];
209
210 //
211 // Need to include the parameters of this method in the map
212 //
213 TypeReference[] parameterTypes = method.getParameterTypes();
214 int paramStart;
215 if (!method.isStatic()) {
216 currBBMap[0] = REFERENCE; // implicit "this" object
217 localTypes[0] = ADDRESS_TYPE;
218 paramStart = 1;
219 } else {
220 paramStart = 0;
221 }
222
223 for (int i = 0; i < parameterTypes.length; i++, paramStart++) {
224 TypeReference parameterType = parameterTypes[i];
225 if (parameterType.isReferenceType()) {
226 localTypes[paramStart] = ADDRESS_TYPE;
227 currBBMap[paramStart] = REFERENCE;
228 } else {
229 currBBMap[paramStart] = NON_REFERENCE;
230
231 if (parameterType.getStackWords() == 2) {
232 if (parameterType.isLongType()) {
233 localTypes[paramStart] = LONG_TYPE;
234 } else {
235 localTypes[paramStart] = DOUBLE_TYPE;
236 }
237 paramStart++;
238 } else if (parameterType.isFloatType()) {
239 localTypes[paramStart] = FLOAT_TYPE;
240 } else if (parameterType.isIntLikeType()) {
241 localTypes[paramStart] = INT_TYPE;
242 } else {
243 localTypes[paramStart] = ADDRESS_TYPE;
244 }
245 }
246 }
247
248 // The map for the start of the first block, is stack empty, with none
249 // of the locals set yet
250 //
251 currBBStkTop = currBBStkEmpty;
252 bbMaps[byteToBlockMap[0]] = currBBMap;
253 blockStkTop[byteToBlockMap[0]] = currBBStkTop;
254
255 // For all methods, record a map at the start of the method for the corresponding
256 // conditional call to "yield".
257
258 referenceMaps.recordStkMap(0, currBBMap, currBBStkTop, false);
259
260 currBBMap = new byte[currBBMap.length];
261
262 //----------------------------------------------------------
263 //
264 // Keep looping until the Work Stack is empty
265 //
266 //----------------------------------------------------------
267 while (workStkTop > -1) {
268
269 // Get the next item off the work stack
270 currBBNum = workStk[workStkTop];
271 workStkTop--;
272
273 boolean inJSRSub = false;
274 if (bbMaps[currBBNum] != null) {
275 currBBStkTop = blockStkTop[currBBNum];
276 for (int k = 0; k <= currBBStkTop; k++) {
277 currBBMap[k] = bbMaps[currBBNum][k];
278 }
279
280 if (jsrCount > 0 && basicBlocks[currBBNum].isInJSR()) {
281 inJSRSub = true;
282 }
283 } else {
284 VM.sysWrite("BuildReferenceMaps, error: found a block on work stack with");
285 VM.sysWrite(" no starting map. The block number is ");
286 VM.sysWrite(basicBlocks[currBBNum].getBlockNumber());
287 VM.sysWrite("\n");
288 VM.sysFail("BuildReferenceMaps work stack failure");
289 }
290
291 int start = basicBlocks[currBBNum].getStart();
292 int end = basicBlocks[currBBNum].getEnd();
293
294 if (jsrCount > 0 && inJSRSub) {
295 currPendingRET = bbPendingRETs[currBBNum];
296 if (basicBlocks[currBBNum].isTryStart()) {
297 for (int k = 0; k < tryHandlerLength; k++) {
298 if (tryStartPC[k] == start) {
299 int handlerBBNum = byteToBlockMap[tryHandlerPC[k]];
300 bbPendingRETs[handlerBBNum] = new PendingRETInfo(currPendingRET);
301 }
302 }
303 }
304 } else {
305 currPendingRET = null;
306 }
307
308 boolean inTryBlock;
309 if (basicBlocks[currBBNum].isTryBlock()) {
310 inTryBlock = true;
311 reachableHandlersCount = 0;
312 for (int i = 0; i < tryHandlerLength; i++) {
313 if (start <= tryEndPC[i] && end >= tryStartPC[i]) {
314 reachableHandlerBBNums[reachableHandlersCount] = byteToBlockMap[tryHandlerPC[i]];
315 reachableHandlersCount++;
316 int handlerBBNum = byteToBlockMap[tryHandlerPC[i]];
317 if (bbMaps[handlerBBNum] == null) {
318 bbMaps[handlerBBNum] = new byte[currBBMap.length];
319 for (int k = 0; k <= currBBStkEmpty; k++) {
320 bbMaps[handlerBBNum][k] = currBBMap[k];
321 }
322 bbMaps[handlerBBNum][currBBStkEmpty + 1] = REFERENCE;
323 blockStkTop[handlerBBNum] = currBBStkEmpty + 1;
324 } else {
325 if (inJSRSub && basicBlocks[handlerBBNum].isInJSR()) {
326 // In JSR and handler within the same JSR.
327 // Ensure SET_TO_NONREFERENCE is carried across
328 for (int k = 0; k <= currBBStkEmpty; k++) {
329 if (currBBMap[k] == SET_TO_NONREFERENCE && bbMaps[handlerBBNum][k] != SET_TO_NONREFERENCE) {
330 handlerProcessed[i] = false;
331 bbMaps[handlerBBNum][k] = SET_TO_NONREFERENCE;
332 }
333 }
334 } else if (inJSRSub) {
335 // In JSR but handler is shared by JSR and non JSR
336 // realise JSR and SET_TO_NONREFERENCE becomes NON_REFERENCE
337 for (int k = 0; k <= currBBStkEmpty; k++) {
338 if (currBBMap[k] == SET_TO_NONREFERENCE && bbMaps[handlerBBNum][k] != NON_REFERENCE) {
339 handlerProcessed[i] = false;
340 bbMaps[handlerBBNum][k] = NON_REFERENCE;
341 }
342 }
343 } else {
344 // No JSRs involved, simply ensure NON_REFERENCE is carried over
345 for (int k = 0; k <= currBBStkEmpty; k++) {
346 if (currBBMap[k] == NON_REFERENCE && bbMaps[handlerBBNum][k] != NON_REFERENCE) {
347 handlerProcessed[i] = false;
348 bbMaps[handlerBBNum][k] = NON_REFERENCE;
349 }
350 }
351 }
352 }
353 }
354 }
355 } else {
356 inTryBlock = false;
357 }
358
359 boolean processNextBlock = true;
360
361 bcodes.reset(start);
362 while (bcodes.index() <= end) {
363 int biStart = bcodes.index();
364 int opcode = bcodes.nextInstruction();
365 if (stackHeights != null) {
366 stackHeights[biStart] = currBBStkTop;
367 }
368
369 if (debug) {
370 VM.sysWrite("opcode : " + opcode + "\n");
371 VM.sysWrite("current map: ");
372 for (int j = 0; j <= currBBStkTop; j++) {
373 VM.sysWrite(currBBMap[j]);
374 }
375 VM.sysWrite("\n");
376 }
377
378 switch (opcode) {
379 case JBC_nop: {
380 break;
381 }
382 case JBC_aconst_null: {
383 currBBStkTop++;
384 currBBMap[currBBStkTop] = REFERENCE;
385 break;
386 }
387 case JBC_aload_0: {
388 int localNumber = 0;
389 currBBStkTop++;
390 currBBMap[currBBStkTop] = inJSRSub ? REFERENCE : currBBMap[localNumber];
391 break;
392 }
393 case JBC_aload_1: {
394 int localNumber = 1;
395 currBBStkTop++;
396 currBBMap[currBBStkTop] = inJSRSub ? REFERENCE : currBBMap[localNumber];
397 break;
398 }
399 case JBC_aload_2: {
400 int localNumber = 2;
401 currBBStkTop++;
402 currBBMap[currBBStkTop] = inJSRSub ? REFERENCE : currBBMap[localNumber];
403 break;
404 }
405 case JBC_aload_3: {
406 int localNumber = 3;
407 currBBStkTop++;
408 currBBMap[currBBStkTop] = inJSRSub ? REFERENCE : currBBMap[localNumber];
409 break;
410 }
411 case JBC_aload: {
412 int localNumber = bcodes.getLocalNumber();
413 currBBStkTop++;
414 currBBMap[currBBStkTop] = inJSRSub ? REFERENCE : currBBMap[localNumber];
415 break;
416 }
417
418 case JBC_iconst_m1:
419 case JBC_iconst_0:
420 case JBC_iconst_1:
421 case JBC_iconst_2:
422 case JBC_iconst_3:
423 case JBC_iconst_4:
424 case JBC_iconst_5:
425 case JBC_fconst_0:
426 case JBC_fconst_1:
427 case JBC_fconst_2:
428 case JBC_iload_0:
429 case JBC_iload_1:
430 case JBC_iload_2:
431 case JBC_iload_3:
432 case JBC_fload_0:
433 case JBC_fload_1:
434 case JBC_fload_2:
435 case JBC_fload_3:
436 case JBC_bipush:
437 case JBC_iload:
438 case JBC_fload:
439 case JBC_sipush:
440 case JBC_i2l:
441 case JBC_i2d:
442 case JBC_f2l:
443 case JBC_f2d: {
444 currBBStkTop++;
445 currBBMap[currBBStkTop] = NON_REFERENCE;
446 bcodes.skipInstruction(); // contains mix of 1,2,3 byte bytecodes
447 break;
448 }
449
450 case JBC_lconst_0:
451 case JBC_lconst_1:
452 case JBC_dconst_0:
453 case JBC_dconst_1:
454 case JBC_lload_0:
455 case JBC_lload_1:
456 case JBC_lload_2:
457 case JBC_lload_3:
458 case JBC_dload_0:
459 case JBC_dload_1:
460 case JBC_dload_2:
461 case JBC_dload_3:
462 case JBC_ldc2_w:
463 case JBC_lload:
464 case JBC_dload: {
465 currBBStkTop++;
466 currBBMap[currBBStkTop] = NON_REFERENCE;
467 currBBStkTop++;
468 currBBMap[currBBStkTop] = NON_REFERENCE;
469 bcodes.skipInstruction(); // mix of 1, 2, and 3 byte bytecodes
470 break;
471 }
472
473 case JBC_ldc: {
474 currBBStkTop++;
475 int cpi = bcodes.getConstantIndex();
476 int type = bcodes.getConstantType(cpi);
477 if (type == CP_STRING || type == CP_CLASS) {
478 currBBMap[currBBStkTop] = REFERENCE;
479 } else {
480 currBBMap[currBBStkTop] = NON_REFERENCE;
481 }
482 break;
483 }
484 case JBC_ldc_w: {
485 currBBStkTop++;
486 int cpi = bcodes.getWideConstantIndex();
487 int type = bcodes.getConstantType(cpi);
488 if (type == CP_STRING || type == CP_CLASS) {
489 currBBMap[currBBStkTop] = REFERENCE;
490 } else {
491 currBBMap[currBBStkTop] = NON_REFERENCE;
492 }
493 break;
494 }
495
496 case JBC_istore: {
497 int index = bcodes.getLocalNumber();
498 if (!inJSRSub) {
499 currBBMap[index] = NON_REFERENCE;
500 } else {
501 currBBMap[index] = SET_TO_NONREFERENCE;
502 }
503 if (inTryBlock) {
504 setHandlersMapsNonRef(index, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
505 }
506 currBBStkTop--;
507 localTypes[index] |= INT_TYPE;
508 break;
509 }
510
511 case JBC_fstore: {
512 int index = bcodes.getLocalNumber();
513 if (!inJSRSub) {
514 currBBMap[index] = NON_REFERENCE;
515 } else {
516 currBBMap[index] = SET_TO_NONREFERENCE;
517 }
518 if (inTryBlock) {
519 setHandlersMapsNonRef(index, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
520 }
521 currBBStkTop--;
522 localTypes[index] |= FLOAT_TYPE;
523 break;
524 }
525
526 case JBC_lstore: {
527 int index = bcodes.getLocalNumber();
528 if (!inJSRSub) {
529 currBBMap[index] = NON_REFERENCE;
530 currBBMap[index + 1] = NON_REFERENCE;
531 } else {
532 currBBMap[index] = SET_TO_NONREFERENCE;
533 currBBMap[index + 1] = SET_TO_NONREFERENCE;
534 }
535
536 if (inTryBlock) {
537 setHandlersMapsNonRef(index, PrimitiveSize.DOUBLEWORD,
538 reachableHandlerBBNums, reachableHandlersCount, inJSRSub,
539 bbMaps);
540 }
541 currBBStkTop = currBBStkTop - 2;
542 localTypes[index] |= LONG_TYPE;
543 break;
544 }
545
546 case JBC_dstore: {
547 int index = bcodes.getLocalNumber();
548 if (!inJSRSub) {
549 currBBMap[index] = NON_REFERENCE;
550 currBBMap[index + 1] = NON_REFERENCE;
551 } else {
552 currBBMap[index] = SET_TO_NONREFERENCE;
553 currBBMap[index + 1] = SET_TO_NONREFERENCE;
554 }
555
556 if (inTryBlock) {
557 setHandlersMapsNonRef(index, PrimitiveSize.DOUBLEWORD,
558 reachableHandlerBBNums, reachableHandlersCount, inJSRSub,
559 bbMaps);
560 }
561 currBBStkTop = currBBStkTop - 2;
562 localTypes[index] |= DOUBLE_TYPE;
563 break;
564 }
565
566 case JBC_astore: {
567 int index = bcodes.getLocalNumber();
568 currBBMap[index] = currBBMap[currBBStkTop];// may be a reference or a return address
569 if (inJSRSub) {
570 if (currBBMap[index] == RETURN_ADDRESS) {
571 currPendingRET.updateReturnAddressLocation(index);
572 }
573 if (inTryBlock) {
574 if (currBBMap[index] == REFERENCE) {
575 setHandlersMapsRef(index, reachableHandlerBBNums, reachableHandlersCount, bbMaps);
576 } else {
577 setHandlersMapsReturnAddress(index, reachableHandlerBBNums, reachableHandlersCount, bbMaps);
578 }
579 }
580 }
581 currBBStkTop--;
582 localTypes[index] |= ADDRESS_TYPE;
583 break;
584 }
585
586 case JBC_istore_0: {
587 if (!inJSRSub) {
588 currBBMap[0] = NON_REFERENCE;
589 } else {
590 currBBMap[0] = SET_TO_NONREFERENCE;
591 }
592 if (inTryBlock) {
593 setHandlersMapsNonRef(0, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
594 }
595 currBBStkTop--;
596 localTypes[0] |= INT_TYPE;
597 break;
598 }
599
600 case JBC_fstore_0: {
601 if (!inJSRSub) {
602 currBBMap[0] = NON_REFERENCE;
603 } else {
604 currBBMap[0] = SET_TO_NONREFERENCE;
605 }
606 if (inTryBlock) {
607 setHandlersMapsNonRef(0, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
608 }
609 currBBStkTop--;
610 localTypes[0] |= FLOAT_TYPE;
611 break;
612 }
613
614 case JBC_istore_1: {
615 if (!inJSRSub) {
616 currBBMap[1] = NON_REFERENCE;
617 } else {
618 currBBMap[1] = SET_TO_NONREFERENCE;
619 }
620 if (inTryBlock) {
621 setHandlersMapsNonRef(1, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
622 }
623 currBBStkTop--;
624 localTypes[1] |= INT_TYPE;
625 break;
626 }
627
628 case JBC_fstore_1: {
629 if (!inJSRSub) {
630 currBBMap[1] = NON_REFERENCE;
631 } else {
632 currBBMap[1] = SET_TO_NONREFERENCE;
633 }
634 if (inTryBlock) {
635 setHandlersMapsNonRef(1, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
636 }
637 currBBStkTop--;
638 localTypes[1] |= FLOAT_TYPE;
639 break;
640 }
641
642 case JBC_istore_2: {
643 if (!inJSRSub) {
644 currBBMap[2] = NON_REFERENCE;
645 } else {
646 currBBMap[2] = SET_TO_NONREFERENCE;
647 }
648 if (inTryBlock) {
649 setHandlersMapsNonRef(2, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
650 }
651 currBBStkTop--;
652 localTypes[2] |= INT_TYPE;
653 break;
654 }
655
656 case JBC_fstore_2: {
657 if (!inJSRSub) {
658 currBBMap[2] = NON_REFERENCE;
659 } else {
660 currBBMap[2] = SET_TO_NONREFERENCE;
661 }
662 if (inTryBlock) {
663 setHandlersMapsNonRef(2, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
664 }
665 currBBStkTop--;
666 localTypes[2] |= FLOAT_TYPE;
667 break;
668 }
669
670 case JBC_istore_3: {
671 if (!inJSRSub) {
672 currBBMap[3] = NON_REFERENCE;
673 } else {
674 currBBMap[3] = SET_TO_NONREFERENCE;
675 }
676 if (inTryBlock) {
677 setHandlersMapsNonRef(3, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
678 }
679 currBBStkTop--;
680 localTypes[3] |= INT_TYPE;
681 break;
682 }
683
684 case JBC_fstore_3: {
685 if (!inJSRSub) {
686 currBBMap[3] = NON_REFERENCE;
687 } else {
688 currBBMap[3] = SET_TO_NONREFERENCE;
689 }
690 if (inTryBlock) {
691 setHandlersMapsNonRef(3, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
692 }
693 currBBStkTop--;
694 localTypes[3] |= FLOAT_TYPE;
695 break;
696 }
697
698 case JBC_lstore_0: {
699 if (inJSRSub) {
700 currBBMap[0] = NON_REFERENCE;
701 currBBMap[1] = NON_REFERENCE;
702 } else {
703 currBBMap[0] = SET_TO_NONREFERENCE;
704 currBBMap[1] = SET_TO_NONREFERENCE;
705 }
706 if (inTryBlock) {
707 setHandlersMapsNonRef(0, PrimitiveSize.DOUBLEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
708 }
709 currBBStkTop = currBBStkTop - 2;
710 localTypes[0] |= LONG_TYPE;
711 break;
712 }
713 case JBC_dstore_0: {
714 if (inJSRSub) {
715 currBBMap[0] = NON_REFERENCE;
716 currBBMap[1] = NON_REFERENCE;
717 } else {
718 currBBMap[0] = SET_TO_NONREFERENCE;
719 currBBMap[1] = SET_TO_NONREFERENCE;
720 }
721 if (inTryBlock) {
722 setHandlersMapsNonRef(0, PrimitiveSize.DOUBLEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
723 }
724 currBBStkTop = currBBStkTop - 2;
725 localTypes[0] |= DOUBLE_TYPE;
726 break;
727 }
728
729 case JBC_lstore_1: {
730 if (!inJSRSub) {
731 currBBMap[1] = NON_REFERENCE;
732 currBBMap[2] = NON_REFERENCE;
733 } else {
734 currBBMap[1] = SET_TO_NONREFERENCE;
735 currBBMap[2] = SET_TO_NONREFERENCE;
736 }
737 if (inTryBlock) {
738 setHandlersMapsNonRef(1, PrimitiveSize.DOUBLEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
739 }
740 currBBStkTop = currBBStkTop - 2;
741 localTypes[1] |= LONG_TYPE;
742 break;
743 }
744
745 case JBC_dstore_1: {
746 if (!inJSRSub) {
747 currBBMap[1] = NON_REFERENCE;
748 currBBMap[2] = NON_REFERENCE;
749 } else {
750 currBBMap[1] = SET_TO_NONREFERENCE;
751 currBBMap[2] = SET_TO_NONREFERENCE;
752 }
753 if (inTryBlock) {
754 setHandlersMapsNonRef(1, PrimitiveSize.DOUBLEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
755 }
756 currBBStkTop = currBBStkTop - 2;
757 localTypes[1] |= DOUBLE_TYPE;
758 break;
759 }
760
761 case JBC_lstore_2: {
762 if (!inJSRSub) {
763 currBBMap[2] = NON_REFERENCE;
764 currBBMap[3] = NON_REFERENCE;
765 } else {
766 currBBMap[2] = SET_TO_NONREFERENCE;
767 currBBMap[3] = SET_TO_NONREFERENCE;
768 }
769 if (inTryBlock) {
770 setHandlersMapsNonRef(2, PrimitiveSize.DOUBLEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
771 }
772 currBBStkTop = currBBStkTop - 2;
773 localTypes[2] |= LONG_TYPE;
774 break;
775 }
776
777 case JBC_dstore_2: {
778 if (!inJSRSub) {
779 currBBMap[2] = NON_REFERENCE;
780 currBBMap[3] = NON_REFERENCE;
781 } else {
782 currBBMap[2] = SET_TO_NONREFERENCE;
783 currBBMap[3] = SET_TO_NONREFERENCE;
784 }
785 if (inTryBlock) {
786 setHandlersMapsNonRef(2, PrimitiveSize.DOUBLEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
787 }
788 currBBStkTop = currBBStkTop - 2;
789 localTypes[2] |= DOUBLE_TYPE;
790 break;
791 }
792
793 case JBC_lstore_3: {
794 if (!inJSRSub) {
795 currBBMap[3] = NON_REFERENCE;
796 currBBMap[4] = NON_REFERENCE;
797 } else {
798 currBBMap[3] = SET_TO_NONREFERENCE;
799 currBBMap[4] = SET_TO_NONREFERENCE;
800 }
801 if (inTryBlock) {
802 setHandlersMapsNonRef(3, PrimitiveSize.DOUBLEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
803 }
804 currBBStkTop = currBBStkTop - 2;
805 localTypes[3] |= LONG_TYPE;
806 break;
807 }
808
809 case JBC_dstore_3: {
810 if (!inJSRSub) {
811 currBBMap[3] = NON_REFERENCE;
812 currBBMap[4] = NON_REFERENCE;
813 } else {
814 currBBMap[3] = SET_TO_NONREFERENCE;
815 currBBMap[4] = SET_TO_NONREFERENCE;
816 }
817 if (inTryBlock) {
818 setHandlersMapsNonRef(3, PrimitiveSize.DOUBLEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
819 }
820 currBBStkTop = currBBStkTop - 2;
821 localTypes[3] |= DOUBLE_TYPE;
822 break;
823 }
824
825 case JBC_astore_0: {
826 currBBMap[0] = currBBMap[currBBStkTop];
827 if (inJSRSub) {
828 if (currBBMap[0] == RETURN_ADDRESS) {
829 currPendingRET.updateReturnAddressLocation(0);
830 }
831 if (inTryBlock) {
832 if (currBBMap[0] == REFERENCE) {
833 setHandlersMapsRef(0, reachableHandlerBBNums, reachableHandlersCount, bbMaps);
834 } else {
835 setHandlersMapsReturnAddress(0, reachableHandlerBBNums, reachableHandlersCount, bbMaps);
836 }
837 }
838 }
839 currBBStkTop--;
840 localTypes[0] |= ADDRESS_TYPE;
841 break;
842 }
843
844 case JBC_astore_1: {
845 currBBMap[1] = currBBMap[currBBStkTop];
846 if (inJSRSub) {
847 if (currBBMap[1] == RETURN_ADDRESS) {
848 currPendingRET.updateReturnAddressLocation(1);
849 }
850 if (inTryBlock) {
851 if (currBBMap[1] == REFERENCE) {
852 setHandlersMapsRef(1, reachableHandlerBBNums, reachableHandlersCount, bbMaps);
853 } else {
854 setHandlersMapsReturnAddress(1, reachableHandlerBBNums, reachableHandlersCount, bbMaps);
855 }
856 }
857 }
858 currBBStkTop--;
859 localTypes[1] |= ADDRESS_TYPE;
860 break;
861 }
862
863 case JBC_astore_2: {
864 currBBMap[2] = currBBMap[currBBStkTop];
865 if (inJSRSub) {
866 if (currBBMap[2] == RETURN_ADDRESS) {
867 currPendingRET.updateReturnAddressLocation(2);
868 }
869 if (inTryBlock) {
870 if (currBBMap[2] == REFERENCE) {
871 setHandlersMapsRef(2, reachableHandlerBBNums, reachableHandlersCount, bbMaps);
872 } else {
873 setHandlersMapsReturnAddress(2, reachableHandlerBBNums, reachableHandlersCount, bbMaps);
874 }
875 }
876 }
877 currBBStkTop--;
878 localTypes[2] |= ADDRESS_TYPE;
879 break;
880 }
881 case JBC_astore_3: {
882 currBBMap[3] = currBBMap[currBBStkTop];
883 if (inJSRSub) {
884 if (currBBMap[3] == RETURN_ADDRESS) {
885 currPendingRET.updateReturnAddressLocation(3);
886 }
887 if (inTryBlock) {
888 if (currBBMap[3] == REFERENCE) {
889 setHandlersMapsRef(3, reachableHandlerBBNums, reachableHandlersCount, bbMaps);
890 } else {
891 setHandlersMapsReturnAddress(3, reachableHandlerBBNums, reachableHandlersCount, bbMaps);
892 }
893 }
894 }
895 currBBStkTop--;
896 localTypes[3] |= ADDRESS_TYPE;
897 break;
898 }
899
900 case JBC_dup: {
901 currBBMap[currBBStkTop + 1] = currBBMap[currBBStkTop];
902 currBBStkTop++;
903 break;
904 }
905 case JBC_dup2: {
906 currBBMap[currBBStkTop + 1] = currBBMap[currBBStkTop - 1];
907 currBBMap[currBBStkTop + 2] = currBBMap[currBBStkTop];
908 currBBStkTop = currBBStkTop + 2;
909 break;
910 }
911 case JBC_dup_x1: {
912 currBBMap[currBBStkTop + 1] = currBBMap[currBBStkTop];
913 currBBMap[currBBStkTop] = currBBMap[currBBStkTop - 1];
914 currBBMap[currBBStkTop - 1] = currBBMap[currBBStkTop + 1];
915 currBBStkTop++;
916 break;
917 }
918 case JBC_dup2_x1: {
919 currBBMap[currBBStkTop + 2] = currBBMap[currBBStkTop];
920 currBBMap[currBBStkTop + 1] = currBBMap[currBBStkTop - 1];
921 currBBMap[currBBStkTop] = currBBMap[currBBStkTop - 2];
922 currBBMap[currBBStkTop - 1] = currBBMap[currBBStkTop + 2];
923 currBBMap[currBBStkTop - 2] = currBBMap[currBBStkTop + 1];
924 currBBStkTop = currBBStkTop + 2;
925 break;
926 }
927 case JBC_dup_x2: {
928 currBBMap[currBBStkTop + 1] = currBBMap[currBBStkTop];
929 currBBMap[currBBStkTop] = currBBMap[currBBStkTop - 1];
930 currBBMap[currBBStkTop - 1] = currBBMap[currBBStkTop - 2];
931 currBBMap[currBBStkTop - 2] = currBBMap[currBBStkTop + 1];
932 currBBStkTop++;
933 break;
934 }
935 case JBC_dup2_x2: {
936 currBBMap[currBBStkTop + 2] = currBBMap[currBBStkTop];
937 currBBMap[currBBStkTop + 1] = currBBMap[currBBStkTop - 1];
938 currBBMap[currBBStkTop] = currBBMap[currBBStkTop - 2];
939 currBBMap[currBBStkTop - 1] = currBBMap[currBBStkTop - 3];
940 currBBMap[currBBStkTop - 2] = currBBMap[currBBStkTop + 2];
941 currBBMap[currBBStkTop - 3] = currBBMap[currBBStkTop + 1];
942 currBBStkTop = currBBStkTop + 2;
943 break;
944 }
945 case JBC_swap: {
946 byte temp;
947 temp = currBBMap[currBBStkTop];
948 currBBMap[currBBStkTop] = currBBMap[currBBStkTop - 1];
949 currBBMap[currBBStkTop - 1] = temp;
950 break;
951 }
952 case JBC_pop:
953 case JBC_iadd:
954 case JBC_fadd:
955 case JBC_isub:
956 case JBC_fsub:
957 case JBC_imul:
958 case JBC_fmul:
959 case JBC_fdiv:
960 case JBC_frem:
961 case JBC_ishl:
962 case JBC_ishr:
963 case JBC_iushr:
964 case JBC_lshl: // long shifts that int shift value
965 case JBC_lshr:
966 case JBC_lushr:
967 case JBC_iand:
968 case JBC_ior:
969 case JBC_ixor:
970 case JBC_l2i:
971 case JBC_l2f:
972 case JBC_d2i:
973 case JBC_d2f:
974 case JBC_fcmpl:
975 case JBC_fcmpg: {
976 currBBStkTop--;
977 bcodes.skipInstruction();
978 break;
979 }
980
981 case JBC_irem:
982 case JBC_idiv: {
983 currBBStkTop = currBBStkTop - 2; // record map after 2 integers popped off stack
984 if (!inJSRSub) {
985 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
986 } else {
987 referenceMaps.recordJSRSubroutineMap(biStart,
988 currBBMap,
989 currBBStkTop,
990 currPendingRET.returnAddressLocation,
991 blockSeen[currBBNum]);
992 }
993 currBBStkTop++;
994 break;
995 }
996 case JBC_ladd:
997 case JBC_dadd:
998 case JBC_lsub:
999 case JBC_dsub:
1000 case JBC_lmul:
1001 case JBC_dmul:
1002 case JBC_ddiv:
1003 case JBC_drem:
1004 case JBC_land:
1005 case JBC_lor:
1006 case JBC_lxor:
1007 case JBC_pop2: {
1008 currBBStkTop = currBBStkTop - 2;
1009 break;
1010 }
1011 case JBC_lrem:
1012 case JBC_ldiv: {
1013 currBBStkTop = currBBStkTop - 4; // record map after 2 longs popped off stack
1014 if (!inJSRSub) {
1015 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
1016 } else {
1017 referenceMaps.recordJSRSubroutineMap(biStart,
1018 currBBMap,
1019 currBBStkTop,
1020 currPendingRET.returnAddressLocation,
1021 blockSeen[currBBNum]);
1022 }
1023 currBBStkTop = currBBStkTop + 2;
1024 break;
1025 }
1026 case JBC_ineg:
1027 case JBC_lneg:
1028 case JBC_fneg:
1029 case JBC_dneg:
1030 case JBC_iinc:
1031 case JBC_i2f:
1032 case JBC_l2d:
1033 case JBC_f2i:
1034 case JBC_d2l:
1035 case JBC_int2byte:
1036 case JBC_int2char:
1037 case JBC_int2short: {
1038 bcodes.skipInstruction();
1039 break;
1040 }
1041
1042 case JBC_lcmp:
1043 case JBC_dcmpl:
1044 case JBC_dcmpg: {
1045 currBBStkTop = currBBStkTop - 3;
1046 break;
1047 }
1048
1049 case JBC_ifeq:
1050 case JBC_ifne:
1051 case JBC_iflt:
1052 case JBC_ifge:
1053 case JBC_ifgt:
1054 case JBC_ifle: {
1055 int offset = bcodes.getBranchOffset();
1056 if (offset <= 0) {
1057 // potential backward branch-generate reference map
1058 // Register the reference map
1059
1060 if (!inJSRSub) {
1061 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
1062 } else {
1063 // in a jsr subroutine
1064 referenceMaps.recordJSRSubroutineMap(biStart,
1065 currBBMap,
1066 currBBStkTop,
1067 currPendingRET.returnAddressLocation,
1068 blockSeen[currBBNum]);
1069 }
1070 }
1071
1072 // process the basic block logic
1073 currBBStkTop--;
1074 if (offset <= 0) {
1075 short fallThruBBNum = byteToBlockMap[biStart + 3];
1076 workStk =
1077 processBranchBB(fallThruBBNum,
1078 currBBStkTop,
1079 currBBMap,
1080 currBBStkEmpty,
1081 inJSRSub,
1082 bbMaps,
1083 blockStkTop,
1084 currPendingRET,
1085 bbPendingRETs,
1086 workStk);
1087 processNextBlock = false;
1088 }
1089 brBBNum = byteToBlockMap[biStart + offset];
1090 workStk =
1091 processBranchBB(brBBNum,
1092 currBBStkTop,
1093 currBBMap,
1094 currBBStkEmpty,
1095 inJSRSub,
1096 bbMaps,
1097 blockStkTop,
1098 currPendingRET,
1099 bbPendingRETs,
1100 workStk);
1101 break;
1102 }
1103
1104 case JBC_if_icmpeq:
1105 case JBC_if_icmpne:
1106 case JBC_if_icmplt:
1107 case JBC_if_icmpge:
1108 case JBC_if_icmpgt:
1109 case JBC_if_icmple:
1110 case JBC_if_acmpeq:
1111 case JBC_if_acmpne: {
1112 int offset = bcodes.getBranchOffset();
1113 if (offset <= 0) {
1114 // possible backward branch-generate reference map
1115 // Register the reference map
1116
1117 if (!inJSRSub) {
1118 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
1119 } else {
1120 // in a jsr subroutine
1121 referenceMaps.recordJSRSubroutineMap(biStart,
1122 currBBMap,
1123 currBBStkTop,
1124 currPendingRET.returnAddressLocation,
1125 blockSeen[currBBNum]);
1126 }
1127 }
1128
1129 //process the basic blocks
1130 currBBStkTop = currBBStkTop - 2;
1131 if (offset <= 0) {
1132 short fallThruBBNum = byteToBlockMap[biStart + 3];
1133 workStk =
1134 processBranchBB(fallThruBBNum,
1135 currBBStkTop,
1136 currBBMap,
1137 currBBStkEmpty,
1138 inJSRSub,
1139 bbMaps,
1140 blockStkTop,
1141 currPendingRET,
1142 bbPendingRETs,
1143 workStk);
1144 processNextBlock = false;
1145 }
1146 brBBNum = byteToBlockMap[biStart + offset];
1147 workStk =
1148 processBranchBB(brBBNum,
1149 currBBStkTop,
1150 currBBMap,
1151 currBBStkEmpty,
1152 inJSRSub,
1153 bbMaps,
1154 blockStkTop,
1155 currPendingRET,
1156 bbPendingRETs,
1157 workStk);
1158 break;
1159 }
1160
1161 case JBC_ifnull:
1162 case JBC_ifnonnull: {
1163 int offset = bcodes.getBranchOffset();
1164 if (offset <= 0) {
1165 // possible backward branch-generate reference map
1166 // Register the reference map
1167
1168 if (!inJSRSub) {
1169 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
1170 } else {
1171 // in a jsr subroutine
1172 referenceMaps.recordJSRSubroutineMap(biStart,
1173 currBBMap,
1174 currBBStkTop,
1175 currPendingRET.returnAddressLocation,
1176 blockSeen[currBBNum]);
1177 }
1178 }
1179
1180 //process the basic block logic
1181 currBBStkTop--;
1182 if (offset <= 0) {
1183 short fallThruBBNum = byteToBlockMap[biStart + 3];
1184 workStk =
1185 processBranchBB(fallThruBBNum,
1186 currBBStkTop,
1187 currBBMap,
1188 currBBStkEmpty,
1189 inJSRSub,
1190 bbMaps,
1191 blockStkTop,
1192 currPendingRET,
1193 bbPendingRETs,
1194 workStk);
1195 processNextBlock = false;
1196 }
1197 brBBNum = byteToBlockMap[biStart + offset];
1198 workStk =
1199 processBranchBB(brBBNum,
1200 currBBStkTop,
1201 currBBMap,
1202 currBBStkEmpty,
1203 inJSRSub,
1204 bbMaps,
1205 blockStkTop,
1206 currPendingRET,
1207 bbPendingRETs,
1208 workStk);
1209 break;
1210 }
1211
1212 case JBC_goto: {
1213 int offset = bcodes.getBranchOffset();
1214 if (offset <= 0) {
1215 // backward branch-generate reference map
1216 // Register the reference map
1217 if (!inJSRSub) {
1218 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
1219 } else {
1220 // in a jsr subroutine
1221 referenceMaps.recordJSRSubroutineMap(biStart,
1222 currBBMap,
1223 currBBStkTop,
1224 currPendingRET.returnAddressLocation,
1225 blockSeen[currBBNum]);
1226 }
1227 }
1228
1229 // process the basic block logic
1230 brBBNum = byteToBlockMap[biStart + offset];
1231 workStk =
1232 processBranchBB(brBBNum,
1233 currBBStkTop,
1234 currBBMap,
1235 currBBStkEmpty,
1236 inJSRSub,
1237 bbMaps,
1238 blockStkTop,
1239 currPendingRET,
1240 bbPendingRETs,
1241 workStk);
1242 processNextBlock = false;
1243 break;
1244 }
1245 case JBC_goto_w: {
1246 int offset = bcodes.getWideBranchOffset();
1247 if (offset <= 0) {
1248 // backward branch-generate reference map
1249 // Register the reference map
1250
1251 if (!inJSRSub) {
1252 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
1253 } else {
1254 // in a jsr subroutine
1255 referenceMaps.recordJSRSubroutineMap(biStart,
1256 currBBMap,
1257 currBBStkTop,
1258 currPendingRET.returnAddressLocation,
1259 blockSeen[currBBNum]);
1260 }
1261 }
1262
1263 //process basic block structures
1264 brBBNum = byteToBlockMap[biStart + offset];
1265 workStk =
1266 processBranchBB(brBBNum,
1267 currBBStkTop,
1268 currBBMap,
1269 currBBStkEmpty,
1270 inJSRSub,
1271 bbMaps,
1272 blockStkTop,
1273 currPendingRET,
1274 bbPendingRETs,
1275 workStk);
1276 processNextBlock = false;
1277 break;
1278 }
1279 case JBC_tableswitch: {
1280 currBBStkTop--;
1281 bcodes.alignSwitch();
1282 // get default offset and process branch to default branch point
1283 int def = bcodes.getDefaultSwitchOffset();
1284 workStk =
1285 processBranchBB(byteToBlockMap[biStart + def],
1286 currBBStkTop,
1287 currBBMap,
1288 currBBStkEmpty,
1289 inJSRSub,
1290 bbMaps,
1291 blockStkTop,
1292 currPendingRET,
1293 bbPendingRETs,
1294 workStk);
1295
1296 int low = bcodes.getLowSwitchValue();
1297 int high = bcodes.getHighSwitchValue();
1298 int n = high - low + 1;
1299 // generate labels for offsets
1300 for (int k = 0; k < n; k++) {
1301 int offset = bcodes.getTableSwitchOffset(k);
1302 workStk =
1303 processBranchBB(byteToBlockMap[biStart + offset],
1304 currBBStkTop,
1305 currBBMap,
1306 currBBStkEmpty,
1307 inJSRSub,
1308 bbMaps,
1309 blockStkTop,
1310 currPendingRET,
1311 bbPendingRETs,
1312 workStk);
1313 }
1314 bcodes.skipTableSwitchOffsets(n);
1315 processNextBlock = false;
1316 break;
1317 }
1318 case JBC_lookupswitch: {
1319 currBBStkTop--;
1320 bcodes.alignSwitch();
1321 // get default offset and process branch to default branch point
1322 int def = bcodes.getDefaultSwitchOffset();
1323 workStk =
1324 processBranchBB(byteToBlockMap[biStart + def],
1325 currBBStkTop,
1326 currBBMap,
1327 currBBStkEmpty,
1328 inJSRSub,
1329 bbMaps,
1330 blockStkTop,
1331 currPendingRET,
1332 bbPendingRETs,
1333 workStk);
1334
1335 int npairs = bcodes.getSwitchLength();
1336
1337 // generate label for each offset in table
1338 for (int k = 0; k < npairs; k++) {
1339 int offset = bcodes.getLookupSwitchOffset(k);
1340 workStk =
1341 processBranchBB(byteToBlockMap[biStart + offset],
1342 currBBStkTop,
1343 currBBMap,
1344 currBBStkEmpty,
1345 inJSRSub,
1346 bbMaps,
1347 blockStkTop,
1348 currPendingRET,
1349 bbPendingRETs,
1350 workStk);
1351 }
1352 bcodes.skipLookupSwitchPairs(npairs);
1353 processNextBlock = false;
1354 break;
1355 }
1356
1357 case JBC_jsr: {
1358 processNextBlock = false;
1359 int offset = bcodes.getBranchOffset();
1360 if (!inJSRSub) {
1361 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkEmpty, blockSeen[currBBNum]);
1362 } else {
1363 referenceMaps.recordJSRSubroutineMap(biStart,
1364 currBBMap,
1365 currBBStkEmpty,
1366 currPendingRET.returnAddressLocation,
1367 blockSeen[currBBNum]);
1368 }
1369 currBBStkTop++;
1370 currBBMap[currBBStkTop] = RETURN_ADDRESS;
1371 workStk =
1372 processJSR(byteToBlockMap[biStart],
1373 biStart + offset,
1374 byteToBlockMap[biStart + offset],
1375 byteToBlockMap[biStart + 3],
1376 bbMaps,
1377 currBBStkTop,
1378 currBBMap,
1379 currBBStkEmpty,
1380 blockStkTop,
1381 bbPendingRETs,
1382 currPendingRET,
1383 JSRSubs,
1384 workStk);
1385 break;
1386 }
1387 case JBC_jsr_w: {
1388 processNextBlock = false;
1389 int offset = bcodes.getWideBranchOffset();
1390 if (!inJSRSub) {
1391 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkEmpty, blockSeen[currBBNum]);
1392 } else {
1393 referenceMaps.recordJSRSubroutineMap(biStart,
1394 currBBMap,
1395 currBBStkEmpty,
1396 currPendingRET.returnAddressLocation,
1397 blockSeen[currBBNum]);
1398 }
1399 currBBStkTop++;
1400 currBBMap[currBBStkTop] = RETURN_ADDRESS;
1401 workStk =
1402 processJSR(byteToBlockMap[biStart],
1403 biStart + offset,
1404 byteToBlockMap[biStart + offset],
1405 byteToBlockMap[biStart + 5],
1406 bbMaps,
1407 currBBStkTop,
1408 currBBMap,
1409 currBBStkEmpty,
1410 blockStkTop,
1411 bbPendingRETs,
1412 currPendingRET,
1413 JSRSubs,
1414 workStk);
1415 break;
1416 }
1417 case JBC_ret: {
1418 int index = bcodes.getLocalNumber();
1419
1420 // Can not be used again as a return addr.
1421 //
1422 currBBMap[index] = SET_TO_NONREFERENCE;
1423 processNextBlock = false;
1424 int subStart = currPendingRET.JSRSubStartByteIndex;
1425 int k;
1426 for (k = 0; k < JSRSubNext; k++) {
1427 if (JSRSubs[k].subroutineByteCodeStart == subStart) {
1428 JSRSubs[k].newEndMaps(currBBMap, currBBStkTop);
1429 break;
1430 }
1431 }
1432
1433 boolean JSRisinJSRSub = bbPendingRETs[currPendingRET.JSRBBNum] != null;
1434 workStk =
1435 computeJSRNextMaps(currPendingRET.JSRNextBBNum,
1436 currBBMap.length,
1437 k,
1438 JSRisinJSRSub,
1439 bbMaps,
1440 blockStkTop,
1441 JSRSubs,
1442 currBBStkEmpty,
1443 workStk);
1444 if (JSRisinJSRSub && bbPendingRETs[currPendingRET.JSRNextBBNum] == null) {
1445 bbPendingRETs[currPendingRET.JSRNextBBNum] =
1446 new PendingRETInfo(bbPendingRETs[currPendingRET.JSRBBNum]);
1447 }
1448 break;
1449 }
1450 case JBC_invokevirtual:
1451 case JBC_invokespecial: {
1452 MethodReference target = bcodes.getMethodReference();
1453 currBBStkTop =
1454 processInvoke(target,
1455 biStart,
1456 currBBStkTop,
1457 currBBMap,
1458 false,
1459 inJSRSub,
1460 referenceMaps,
1461 currPendingRET,
1462 blockSeen[currBBNum],
1463 currBBStkEmpty);
1464 break;
1465 }
1466 case JBC_invokeinterface: {
1467 MethodReference target = bcodes.getMethodReference();
1468 bcodes.alignInvokeInterface();
1469 currBBStkTop =
1470 processInvoke(target,
1471 biStart,
1472 currBBStkTop,
1473 currBBMap,
1474 false,
1475 inJSRSub,
1476 referenceMaps,
1477 currPendingRET,
1478 blockSeen[currBBNum],
1479 currBBStkEmpty);
1480 break;
1481 }
1482 case JBC_invokestatic: {
1483 MethodReference target = bcodes.getMethodReference();
1484 currBBStkTop =
1485 processInvoke(target,
1486 biStart,
1487 currBBStkTop,
1488 currBBMap,
1489 true,
1490 inJSRSub,
1491 referenceMaps,
1492 currPendingRET,
1493 blockSeen[currBBNum],
1494 currBBStkEmpty);
1495 break;
1496 }
1497
1498 case JBC_ireturn:
1499 case JBC_lreturn:
1500 case JBC_freturn:
1501 case JBC_dreturn:
1502 case JBC_areturn:
1503 case JBC_return: {
1504 if (VM.UseEpilogueYieldPoints || method.isSynchronized()) {
1505 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
1506 }
1507 processNextBlock = false;
1508 break;
1509 }
1510
1511 case JBC_getstatic: {
1512 // Register the reference map (could cause dynamic linking)
1513 if (!inJSRSub) {
1514 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
1515 } else {
1516 referenceMaps.recordJSRSubroutineMap(biStart,
1517 currBBMap,
1518 currBBStkTop,
1519 currPendingRET.returnAddressLocation,
1520 blockSeen[currBBNum]);
1521 }
1522
1523 TypeReference fieldType = bcodes.getFieldReference().getFieldContentsType();
1524 currBBMap[++currBBStkTop] = fieldType.isPrimitiveType() ? NON_REFERENCE : REFERENCE;
1525 if (fieldType.getStackWords() == 2) {
1526 currBBMap[++currBBStkTop] = NON_REFERENCE;
1527 }
1528 break;
1529 }
1530 case JBC_putstatic: {
1531 // Register the reference map (could cause dynamic linking)
1532 if (!inJSRSub) {
1533 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
1534 } else {
1535 referenceMaps.recordJSRSubroutineMap(biStart,
1536 currBBMap,
1537 currBBStkTop,
1538 currPendingRET.returnAddressLocation,
1539 blockSeen[currBBNum]);
1540 }
1541 TypeReference fieldType = bcodes.getFieldReference().getFieldContentsType();
1542 currBBStkTop--;
1543 if (fieldType.getStackWords() == 2) {
1544 currBBStkTop--;
1545 }
1546 break;
1547 }
1548 case JBC_getfield: {
1549 TypeReference fieldType = bcodes.getFieldReference().getFieldContentsType();
1550 // Register the reference map (could cause dynamic linking..if so there will be a NPE, but the linking happens first.)
1551 if (!inJSRSub) {
1552 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
1553 } else {
1554 referenceMaps.recordJSRSubroutineMap(biStart,
1555 currBBMap,
1556 currBBStkTop,
1557 currPendingRET.returnAddressLocation,
1558 blockSeen[currBBNum]);
1559 }
1560 currBBStkTop--; // pop object pointer
1561 currBBMap[++currBBStkTop] = fieldType.isPrimitiveType() ? NON_REFERENCE : REFERENCE;
1562 if (fieldType.getStackWords() == 2) {
1563 currBBMap[++currBBStkTop] = NON_REFERENCE;
1564 }
1565 break;
1566 }
1567 case JBC_putfield: {
1568 TypeReference fieldType = bcodes.getFieldReference().getFieldContentsType();
1569 // Register the reference map with the values still on the stack
1570 // note: putfield could result in a call to the classloader
1571 if (!inJSRSub) {
1572 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
1573 } else {
1574 referenceMaps.recordJSRSubroutineMap(biStart,
1575 currBBMap,
1576 currBBStkTop,
1577 currPendingRET.returnAddressLocation,
1578 blockSeen[currBBNum]);
1579 }
1580 currBBStkTop -= 2; // remove objectref and one value
1581 if (fieldType.getStackWords() == 2) {
1582 currBBStkTop--;
1583 }
1584 break;
1585 }
1586 case JBC_checkcast: {
1587 if (!inJSRSub) {
1588 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
1589 } else {
1590 referenceMaps.recordJSRSubroutineMap(biStart,
1591 currBBMap,
1592 currBBStkTop,
1593 currPendingRET.returnAddressLocation,
1594 blockSeen[currBBNum]);
1595 }
1596 bcodes.skipInstruction();
1597 break;
1598 }
1599 case JBC_instanceof: {
1600 if (!inJSRSub) {
1601 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
1602 } else {
1603 referenceMaps.recordJSRSubroutineMap(biStart,
1604 currBBMap,
1605 currBBStkTop,
1606 currPendingRET.returnAddressLocation,
1607 blockSeen[currBBNum]);
1608 }
1609 currBBMap[currBBStkTop] = NON_REFERENCE;
1610 bcodes.skipInstruction();
1611 break;
1612 }
1613 case JBC_new: {
1614 if (!inJSRSub) {
1615 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
1616 } else {
1617 referenceMaps.recordJSRSubroutineMap(biStart,
1618 currBBMap,
1619 currBBStkTop,
1620 currPendingRET.returnAddressLocation,
1621 blockSeen[currBBNum]);
1622 }
1623 currBBStkTop++;
1624 currBBMap[currBBStkTop] = REFERENCE;
1625 bcodes.skipInstruction();
1626 break;
1627 }
1628
1629 // For the <x>aload instructions the map is needed in case gc occurs
1630 // while the array index check is taking place. Stack has not been
1631 // altered yet.
1632 case JBC_iaload:
1633 case JBC_faload:
1634 case JBC_baload:
1635 case JBC_caload:
1636 case JBC_saload: {
1637 if (!inJSRSub) {
1638 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
1639 } else {
1640 referenceMaps.recordJSRSubroutineMap(biStart,
1641 currBBMap,
1642 currBBStkTop,
1643 currPendingRET.returnAddressLocation,
1644 blockSeen[currBBNum]);
1645 }
1646 currBBStkTop--;
1647 currBBMap[currBBStkTop] = NON_REFERENCE;
1648 break;
1649 }
1650 case JBC_laload:
1651 case JBC_daload: {
1652 if (!inJSRSub) {
1653 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
1654 } else {
1655 referenceMaps.recordJSRSubroutineMap(biStart,
1656 currBBMap,
1657 currBBStkTop,
1658 currPendingRET.returnAddressLocation,
1659 blockSeen[currBBNum]);
1660 }
1661 currBBMap[currBBStkTop - 1] = NON_REFERENCE;
1662 break;
1663 }
1664
1665 case JBC_aaload: {
1666 if (!inJSRSub) {
1667 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
1668 } else {
1669 referenceMaps.recordJSRSubroutineMap(biStart,
1670 currBBMap,
1671 currBBStkTop,
1672 currPendingRET.returnAddressLocation,
1673 blockSeen[currBBNum]);
1674 }
1675 currBBStkTop--;
1676 break;
1677 }
1678
1679 // For the <x>astore instructions the map recorded is in case gc occurs
1680 // during the array index bounds check or the arraystore check (for aastore).
1681 // Stack has not been modified at this point.
1682 case JBC_iastore:
1683 case JBC_fastore:
1684 case JBC_aastore:
1685 case JBC_bastore:
1686 case JBC_castore:
1687 case JBC_sastore: {
1688 if (!inJSRSub) {
1689 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
1690 } else {
1691 referenceMaps.recordJSRSubroutineMap(biStart,
1692 currBBMap,
1693 currBBStkTop,
1694 currPendingRET.returnAddressLocation,
1695 blockSeen[currBBNum]);
1696 }
1697 currBBStkTop = currBBStkTop - 3;
1698 break;
1699 }
1700 case JBC_lastore:
1701 case JBC_dastore: {
1702 if (!inJSRSub) {
1703 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
1704 } else {
1705 referenceMaps.recordJSRSubroutineMap(biStart,
1706 currBBMap,
1707 currBBStkTop,
1708 currPendingRET.returnAddressLocation,
1709 blockSeen[currBBNum]);
1710 }
1711 currBBStkTop = currBBStkTop - 4;
1712 break;
1713 }
1714
1715 case JBC_newarray:
1716 case JBC_anewarray: {
1717 if (!inJSRSub) {
1718 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
1719 } else {
1720 referenceMaps.recordJSRSubroutineMap(biStart,
1721 currBBMap,
1722 currBBStkTop,
1723 currPendingRET.returnAddressLocation,
1724 blockSeen[currBBNum]);
1725 }
1726 currBBMap[currBBStkTop] = REFERENCE;
1727 bcodes.skipInstruction();
1728 break;
1729 }
1730
1731 case JBC_multianewarray: {
1732 bcodes.getTypeReference();
1733 int dim = bcodes.getArrayDimension();
1734 if (!inJSRSub) {
1735 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
1736 } else {
1737 referenceMaps.recordJSRSubroutineMap(biStart,
1738 currBBMap,
1739 currBBStkTop,
1740 currPendingRET.returnAddressLocation,
1741 blockSeen[currBBNum]);
1742 }
1743 currBBStkTop = currBBStkTop - dim + 1;
1744 currBBMap[currBBStkTop] = REFERENCE;
1745 break;
1746 }
1747 case JBC_arraylength: {
1748 currBBMap[currBBStkTop] = NON_REFERENCE;
1749 break;
1750 }
1751 case JBC_athrow: {
1752 if (!inJSRSub) {
1753 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
1754 } else {
1755 referenceMaps.recordJSRSubroutineMap(biStart,
1756 currBBMap,
1757 currBBStkTop,
1758 currPendingRET.returnAddressLocation,
1759 blockSeen[currBBNum]);
1760 }
1761 currBBStkTop = currBBStkEmpty + 1;
1762 currBBMap[currBBStkTop] = REFERENCE;
1763 processNextBlock = false;
1764 break;
1765 }
1766 case JBC_monitorenter:
1767 case JBC_monitorexit: {
1768 currBBStkTop--;
1769 if (!inJSRSub) {
1770 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
1771 } else {
1772 referenceMaps.recordJSRSubroutineMap(biStart,
1773 currBBMap,
1774 currBBStkTop,
1775 currPendingRET.returnAddressLocation,
1776 blockSeen[currBBNum]);
1777 }
1778 break;
1779 }
1780
1781 case JBC_wide: {
1782 int widecode = bcodes.getWideOpcode();
1783 int index = bcodes.getWideLocalNumber();
1784 switch (widecode) {
1785 case JBC_iload:
1786 case JBC_fload: {
1787 currBBStkTop++;
1788 currBBMap[currBBStkTop] = NON_REFERENCE;
1789 break;
1790 }
1791
1792 case JBC_lload:
1793 case JBC_dload: {
1794 currBBStkTop++;
1795 currBBMap[currBBStkTop] = NON_REFERENCE;
1796 currBBStkTop++;
1797 currBBMap[currBBStkTop] = NON_REFERENCE;
1798 break;
1799 }
1800
1801 case JBC_aload: {
1802 currBBStkTop++;
1803 currBBMap[currBBStkTop] = currBBMap[index];
1804 break;
1805 }
1806
1807 case JBC_istore: {
1808 if (!inJSRSub) {
1809 currBBMap[index] = NON_REFERENCE;
1810 } else {
1811 currBBMap[index] = SET_TO_NONREFERENCE;
1812 }
1813 currBBStkTop--;
1814 localTypes[index] |= INT_TYPE;
1815 break;
1816 }
1817
1818 case JBC_fstore: {
1819 if (!inJSRSub) {
1820 currBBMap[index] = NON_REFERENCE;
1821 } else {
1822 currBBMap[index] = SET_TO_NONREFERENCE;
1823 }
1824 currBBStkTop--;
1825 localTypes[index] |= FLOAT_TYPE;
1826 break;
1827 }
1828
1829 case JBC_lstore: {
1830 if (!inJSRSub) {
1831 currBBMap[index] = NON_REFERENCE;
1832 currBBMap[index + 1] = NON_REFERENCE;
1833 } else {
1834 currBBMap[index] = SET_TO_NONREFERENCE;
1835 currBBMap[index + 1] = SET_TO_NONREFERENCE;
1836 }
1837 currBBStkTop = currBBStkTop - 2;
1838 localTypes[index] |= LONG_TYPE;
1839 break;
1840 }
1841
1842 case JBC_dstore: {
1843 if (!inJSRSub) {
1844 currBBMap[index] = NON_REFERENCE;
1845 currBBMap[index + 1] = NON_REFERENCE;
1846 } else {
1847 currBBMap[index] = SET_TO_NONREFERENCE;
1848 currBBMap[index + 1] = SET_TO_NONREFERENCE;
1849 }
1850 currBBStkTop = currBBStkTop - 2;
1851 localTypes[index] |= DOUBLE_TYPE;
1852 break;
1853 }
1854
1855 case JBC_astore: {
1856 currBBMap[index] = currBBMap[currBBStkTop];
1857 currBBStkTop--;
1858 localTypes[index] |= ADDRESS_TYPE;
1859 break;
1860 }
1861
1862 case JBC_iinc: {
1863 bcodes.getWideIncrement();
1864 break;
1865 }
1866 case JBC_ret: {
1867 // Can not be used again as a return addr.
1868 //
1869 currBBMap[index] = SET_TO_NONREFERENCE;
1870 processNextBlock = false;
1871 int subStart = currPendingRET.JSRSubStartByteIndex;
1872 int k;
1873 for (k = 0; k < JSRSubNext; k++) {
1874 if (JSRSubs[k].subroutineByteCodeStart == subStart) {
1875 JSRSubs[k].newEndMaps(currBBMap, currBBStkTop);
1876 break;
1877 }
1878 }
1879
1880 boolean JSRisinJSRSub = bbPendingRETs[currPendingRET.JSRBBNum] != null;
1881 workStk =
1882 computeJSRNextMaps(currPendingRET.JSRNextBBNum,
1883 currBBMap.length,
1884 k,
1885 JSRisinJSRSub,
1886 bbMaps,
1887 blockStkTop,
1888 JSRSubs,
1889 currBBStkEmpty,
1890 workStk);
1891 if (JSRisinJSRSub && bbPendingRETs[currPendingRET.JSRNextBBNum] == null) {
1892 bbPendingRETs[currPendingRET.JSRNextBBNum] =
1893 new PendingRETInfo(bbPendingRETs[currPendingRET.JSRBBNum]);
1894 }
1895 break;
1896 }
1897 default: // switch on widecode
1898 if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);
1899 }
1900 break;
1901 } // case JBC_wide:
1902
1903 default: {
1904 VM.sysFail("Unknown opcode:" + opcode);
1905 }
1906
1907 } // end switch (opcode)
1908
1909 } // for start to end
1910
1911 blockSeen[currBBNum] = true;
1912
1913 if (processNextBlock) {
1914 short fallThruBBNum = byteToBlockMap[bcodes.index()];
1915 workStk =
1916 processBranchBB(fallThruBBNum,
1917 currBBStkTop,
1918 currBBMap,
1919 currBBStkEmpty,
1920 inJSRSub,
1921 bbMaps,
1922 blockStkTop,
1923 currPendingRET,
1924 bbPendingRETs,
1925 workStk);
1926
1927 }
1928
1929 // if the work stack is empty, we must have processed the whole program
1930 // we can now process the try handlers if there are any.
1931 // If a handler doesn't have a starting map already, then the associated try
1932 // has not been processed yet. The try and the handler must be in another
1933 // handler, so that handler must be processed first.
1934 // If one handler is in the try block associated with a second handler, then
1935 // the second handler must not be processed until the first handler has been.
1936 //
1937 if ((workStkTop == -1) && !handlersAllDone) {
1938 int i;
1939 for (i = 0; i < tryHandlerLength; i++) {
1940 // already processed this handler, or, haven't seen the
1941 // associated try block yet so no starting map is available,
1942 // the try block must be in one of the other handlers
1943 if (!handlerProcessed[i] && bbMaps[byteToBlockMap[tryHandlerPC[i]]] != null) break;
1944 }
1945 if (i == tryHandlerLength) {
1946 handlersAllDone = true;
1947 } else {
1948 int considerIndex = i;
1949
1950 while (i != tryHandlerLength) {
1951 int tryStart = tryStartPC[considerIndex];
1952 int tryEnd = tryEndPC[considerIndex];
1953
1954 for (i = 0; i < tryHandlerLength; i++) {
1955 // If the handler handles itself, then make the wild assumption
1956 // that the local variables will be the same......is this reasonable??
1957 // This is a patch to deal with defect 3046.
1958 // I'm not entirely convinced this is right, but don't know what else we can do. --dave
1959 if (i == considerIndex) continue;
1960
1961 // For every handler that has not yet been processed,
1962 // but already has a known starting map,
1963 // make sure it is not in the try block part of the handler
1964 // we are considering working on.
1965 if (!handlerProcessed[i] &&
1966 tryStart <= tryHandlerPC[i] &&
1967 tryHandlerPC[i] < tryEnd &&
1968 bbMaps[byteToBlockMap[tryHandlerPC[i]]] != null) {
1969 break;
1970 }
1971 }
1972
1973 if (i != tryHandlerLength) {
1974 considerIndex = i;
1975 }
1976 }
1977
1978 short blockNum = byteToBlockMap[tryHandlerPC[considerIndex]];
1979 handlerProcessed[considerIndex] = true;
1980 workStk = addToWorkStk(blockNum, workStk);
1981 }
1982 }
1983
1984 } // while workStk not empty
1985
1986 // Indicate that any temporaries can be freed
1987 referenceMaps.recordingComplete();
1988
1989 }
1990
1991 // -------------------- Private Instance Methods --------------------
1992
1993 private short[] addToWorkStk(short blockNum, short[] workStk) {
1994 workStkTop++;
1995 if (workStkTop >= workStk.length) {
1996 short[] biggerQ = new short[workStk.length + 20];
1997 for (int i = 0; i < workStk.length; i++) {
1998 biggerQ[i] = workStk[i];
1999 }
2000 workStk = biggerQ;
2001 biggerQ = null;
2002 }
2003 workStk[workStkTop] = blockNum;
2004 return workStk;
2005 }
2006
2007 private short[] addUniqueToWorkStk(short blockNum, short[] workStk) {
2008 if ((workStkTop + 1) >= workStk.length) {
2009 short[] biggerQ = new short[workStk.length + 20];
2010 boolean matchFound = false;
2011 for (int i = 0; i < workStk.length; i++) {
2012 biggerQ[i] = workStk[i];
2013 matchFound = (workStk[i] == blockNum);
2014 }
2015 workStk = biggerQ;
2016 biggerQ = null;
2017 if (matchFound) return workStk;
2018 } else {
2019 for (int i = 0; i <= workStkTop; i++) {
2020 if (workStk[i] == blockNum) {
2021 return workStk;
2022 }
2023 }
2024 }
2025 workStkTop++;
2026 workStk[workStkTop] = blockNum;
2027 return workStk;
2028 }
2029
2030 private short[] processBranchBB(short brBBNum, int currBBStkTop, byte[] currBBMap, int currBBStkEmpty,
2031 boolean inJSRSub, byte[][] bbMaps, int[] blockStkTop,
2032 PendingRETInfo currPendingRET, PendingRETInfo[] bbPendingRETs,
2033 short[] workStk) {
2034
2035 short[] newworkStk = workStk;
2036
2037 // If the destination block doesn't already have a map, then use this
2038 // map as its map and add it to the work stack
2039
2040 if (bbMaps[brBBNum] == null) {
2041 bbMaps[brBBNum] = new byte[currBBMap.length];
2042 for (int i = 0; i <= currBBStkTop; i++) {
2043 bbMaps[brBBNum][i] = currBBMap[i];
2044 }
2045 blockStkTop[brBBNum] = currBBStkTop;
2046 newworkStk = addToWorkStk(brBBNum, workStk);
2047 if (inJSRSub) {
2048 bbPendingRETs[brBBNum] = new PendingRETInfo(currPendingRET);
2049 }
2050
2051 } else {
2052 // If the destination block already has a map, then check if there are any
2053 // new NONReference values. Note that a new Reference value, will not change an
2054 // existing NONReference value to Reference, as there must be a valid path where
2055 // the variable is not a reference (and not "null" - which is treated as a
2056 // reference) so the variable is unusable.
2057 //
2058 int mismatchAt = -1;
2059 byte[] blockMap = bbMaps[brBBNum];
2060 for (int i = 0; i <= currBBStkEmpty; i++) {
2061 if ((currBBMap[i] != blockMap[i]) && (blockMap[i] != NON_REFERENCE)) {
2062 mismatchAt = i;
2063 break;
2064 }
2065 }
2066 if (mismatchAt == -1) {
2067 return newworkStk; // no further work to be done
2068 } else {
2069 newworkStk = addUniqueToWorkStk(brBBNum, workStk);
2070 for (int i = mismatchAt; i <= currBBStkEmpty; i++) {
2071 if (!inJSRSub) {
2072 blockMap[i] = (blockMap[i] == currBBMap[i]) ? blockMap[i] : NON_REFERENCE;
2073 } else {
2074 blockMap[i] = (blockMap[i] == currBBMap[i]) ? blockMap[i] : SET_TO_NONREFERENCE;
2075 }
2076 }
2077 }
2078 }
2079 return newworkStk;
2080 }
2081
2082 private int processInvoke(MethodReference target, int byteindex, int currBBStkTop, byte[] currBBMap,
2083 boolean isStatic, boolean inJSRSub, ReferenceMaps referenceMaps,
2084 PendingRETInfo currPendingRET, boolean blockSeen, int currBBStkEmpty) {
2085 boolean skipRecordingReferenceMap = false;
2086 boolean popParams = true;
2087
2088 if (target.getType().isMagicType()) {
2089 boolean producesCall = BaselineCompilerImpl.checkForActualCall(target);
2090 if (producesCall) {
2091 // register a map, but do NOT include any of the parameters to the call.
2092 // Chances are what appear to be parameters are not parameters to
2093 // the routine that is actually called.
2094 // In any case, the callee routine will map its parameters
2095 // and we don't have to double map because we are positive that this can't be
2096 // a dynamically linked call site.
2097 for (TypeReference parameterType : target.getParameterTypes()) {
2098 currBBStkTop -= parameterType.getStackWords();
2099 }
2100 if (!isStatic) currBBStkTop--; // pop implicit "this" object reference
2101 popParams = false;
2102 } else {
2103 skipRecordingReferenceMap = true;
2104 }
2105 }
2106
2107 if (!skipRecordingReferenceMap) {
2108 // Register the reference map, including the arguments on the stack for this call
2109 // (unless it is a magic call whose params we have popped above).
2110 if (!inJSRSub) {
2111 referenceMaps.recordStkMap(byteindex, currBBMap, currBBStkTop, blockSeen);
2112 } else {
2113 referenceMaps.recordJSRSubroutineMap(byteindex,
2114 currBBMap,
2115 currBBStkTop,
2116 currPendingRET.returnAddressLocation,
2117 blockSeen);
2118 }
2119 }
2120
2121 if (popParams) {
2122 TypeReference[] parameterTypes = target.getParameterTypes();
2123 int pTypesLength = parameterTypes.length;
2124
2125 // Pop the arguments for this call off the stack;
2126 for (int i = 0; i < pTypesLength; i++) {
2127 currBBStkTop -= parameterTypes[i].getStackWords();
2128 }
2129
2130 if (!isStatic) {
2131 currBBStkTop--; // pop implicit "this" object reference
2132 }
2133 }
2134
2135 // Add the return value to the stack
2136 TypeReference returnType = target.getReturnType();
2137 if (!returnType.isVoidType()) {
2138 // a non-void return value
2139 currBBMap[++currBBStkTop] = returnType.isReferenceType() ? REFERENCE : NON_REFERENCE;
2140 if (returnType.getStackWords() == 2) {
2141 currBBMap[++currBBStkTop] = NON_REFERENCE;
2142 }
2143 }
2144
2145 // Return updated stack top
2146 return currBBStkTop;
2147 }
2148
2149 private short[] processJSR(int JSRBBNum, int JSRSubStartIndex, short brBBNum, short nextBBNum, byte[][] bbMaps,
2150 int currBBStkTop, byte[] currBBMap, int currBBStkEmpty, int[] blockStkTop,
2151 PendingRETInfo[] bbPendingRETs, PendingRETInfo currPendingRET,
2152 JSRSubroutineInfo[] JSRSubs, short[] workStk) {
2153 short[] newworkStk = workStk;
2154
2155 // If the destination block doesn't already have a map, then use this map to build
2156 // the stack portion of the reference map and add the block to the work stack.
2157 // The locals maps should be started with all zeros.
2158
2159 if (bbMaps[brBBNum] == null) {
2160 bbMaps[brBBNum] = new byte[currBBMap.length];
2161 for (int i = currBBStkEmpty + 1; i <= currBBStkTop; i++) {
2162 bbMaps[brBBNum][i] = currBBMap[i];
2163 }
2164 blockStkTop[brBBNum] = currBBStkTop;
2165 newworkStk = addToWorkStk(brBBNum, workStk);
2166
2167 bbPendingRETs[brBBNum] = new PendingRETInfo(JSRSubStartIndex, JSRBBNum, currBBStkTop, nextBBNum);
2168 JSRSubs[JSRSubNext++] = new JSRSubroutineInfo(JSRSubStartIndex, currBBMap, currBBStkEmpty);
2169 } else {
2170 // If the JSR subroutine block already has a map, then locate the ending map
2171 // and use that to determine the map of the next block. No need to reprocess
2172 // the JSR subroutine
2173 int matchingJSRStart;
2174 for (matchingJSRStart = 0; matchingJSRStart < JSRSubNext; matchingJSRStart++) {
2175 if (JSRSubs[matchingJSRStart].subroutineByteCodeStart == JSRSubStartIndex) {
2176 JSRSubs[matchingJSRStart].newStartMaps(currBBMap);
2177 break;
2178 }
2179 }
2180
2181 boolean JSRisinJSRSub = (currPendingRET != null);
2182 newworkStk =
2183 computeJSRNextMaps(nextBBNum,
2184 currBBMap.length,
2185 matchingJSRStart,
2186 JSRisinJSRSub,
2187 bbMaps,
2188 blockStkTop,
2189 JSRSubs,
2190 currBBStkEmpty,
2191 workStk);
2192 if (JSRisinJSRSub && bbPendingRETs[nextBBNum] == null) {
2193 bbPendingRETs[nextBBNum] = new PendingRETInfo(currPendingRET);
2194 }
2195 }
2196
2197 return newworkStk;
2198 }
2199
2200 private short[] computeJSRNextMaps(short nextBBNum, int maplength, int JSRSubIndex, boolean JSRisinJSRSub,
2201 byte[][] bbMaps, int[] blockStkTop, JSRSubroutineInfo[] JSRSubs,
2202 int currBBStkEmpty, short[] workStk) {
2203 short[] newworkStk = workStk;
2204
2205 // Calculate the new map for the block starting at the instruction after the
2206 // JSR instruction (this is the block nextBBNum)
2207 byte[] refMap;
2208
2209 refMap = JSRSubs[JSRSubIndex].computeResultingMaps(maplength);
2210
2211 // If no map is computed, then the JSR Subroutine must have ended in a return
2212 // Do NOT add the next block to the work Q.
2213 if (refMap == null) {
2214 return newworkStk;
2215 }
2216
2217 // If the block after the JSR instruction does not have a map, then the newly
2218 // computed map should be used and the block should be added to the workStk.
2219 if (bbMaps[nextBBNum] == null) {
2220 bbMaps[nextBBNum] = refMap;
2221 blockStkTop[nextBBNum] = JSRSubs[JSRSubIndex].endReferenceTop;
2222 newworkStk = addToWorkStk(nextBBNum, workStk);
2223 } else {
2224 // The block after the JSR instruction already has a reference map.
2225 // Check if the computed map matches the previous map. If so, no further
2226 // work needed.
2227 int mismatchAt = -1;
2228 byte[] blockMap = bbMaps[nextBBNum];
2229 for (int i = 0; i <= currBBStkEmpty; i++) {
2230 if ((refMap[i] != blockMap[i]) && (blockMap[i] != NON_REFERENCE)) {
2231 mismatchAt = i;
2232 break;
2233 }
2234 }
2235 if (mismatchAt == -1) {
2236 return newworkStk; // no further work to be done
2237 } else {
2238 newworkStk = addUniqueToWorkStk(nextBBNum, workStk);
2239 for (int i = mismatchAt; i <= currBBStkEmpty; i++) {
2240 if (!JSRisinJSRSub) {
2241 blockMap[i] = (blockMap[i] == refMap[i]) ? blockMap[i] : NON_REFERENCE;
2242 } else {
2243 blockMap[i] = (blockMap[i] == refMap[i]) ? blockMap[i] : SET_TO_NONREFERENCE;
2244 }
2245 }
2246 }
2247 }
2248 return newworkStk;
2249 }
2250
2251 /**
2252 * For each of the reachable handlers (catch blocks) from the try block, track that
2253 * the local variable given by the index with 1 or 2 words, has been set to a
2254 * non reference value (eg int, float, etc)
2255 *
2256 * @param localVariable Variable index in the map
2257 * @param wordCount 2 for doubles and longs, 1 otherwise
2258 * @param reachableHandlerBBNums The array with all the block numbers of
2259 * reachable handlers
2260 * @param reachableHandlerCount 0 through <code>reachableHandlerCount
2261 * - 1 </code> will all be valid
2262 * array indices
2263 * @param inJSRSub TODO Document ME XXX
2264 * @param bbMaps TODO Document ME XXX
2265 */
2266 private void setHandlersMapsNonRef(int localVariable, PrimitiveSize wordCount, int[] reachableHandlerBBNums,
2267 int reachableHandlerCount, boolean inJSRSub, byte[][] bbMaps) {
2268 if (!inJSRSub) {
2269 for (int i = 0; i < reachableHandlerCount; i++) {
2270 bbMaps[reachableHandlerBBNums[i]][localVariable] = NON_REFERENCE;
2271 if (wordCount == PrimitiveSize.DOUBLEWORD) {
2272 bbMaps[reachableHandlerBBNums[i]][localVariable + 1] = NON_REFERENCE;
2273 }
2274 }
2275 } else {
2276 for (int i = 0; i < reachableHandlerCount; i++) {
2277 bbMaps[reachableHandlerBBNums[i]][localVariable] = SET_TO_NONREFERENCE;
2278 if (wordCount == PrimitiveSize.DOUBLEWORD) {
2279 bbMaps[reachableHandlerBBNums[i]][localVariable + 1] = SET_TO_NONREFERENCE;
2280 }
2281 }
2282 }
2283
2284 }
2285
2286 /**
2287 * For each of the reachable handlers (catch blocks) from the try block,
2288 * track that
2289 * the local variable given by the index, has been set to a reference value.
2290 * Only call this method if the try block is in a JSR subroutine.
2291 * If a non-reference value becomes a reference value,
2292 * then it can not be used as
2293 * as reference value within the handler
2294 * (there is a path to the handler where the
2295 * value is not a reference) so mark the local variable as
2296 * a non-reference if we
2297 * are tracking the difference maps (for a JSR subroutine).
2298 *
2299 * @param localVariable Variable index in the map
2300 * @param reachableHandlerBBNums The array with all the block numbers of
2301 * reachable handlers
2302 * @param reachableHandlerCount 0 through <code>reachableHandlerCount
2303 * - 1 </code> will all be valid
2304 * array indices
2305 * @param bbMaps TODO Document ME XXX
2306 */
2307 private void setHandlersMapsRef(int localVariable, int[] reachableHandlerBBNums, int reachableHandlerCount,
2308 byte[][] bbMaps) {
2309 for (int i = 0; i < reachableHandlerCount; i++) {
2310 if (bbMaps[reachableHandlerBBNums[i]][localVariable] != REFERENCE) {
2311 bbMaps[reachableHandlerBBNums[i]][localVariable] = SET_TO_NONREFERENCE;
2312 }
2313 }
2314 }
2315
2316 /**
2317 * For each of the reachable handlers (catch blocks)
2318 * from the try block, track that
2319 * the local variable given by the index,
2320 * has been set to a return address value.
2321 * Only call this routine within a JSR subroutine.
2322 * If a non-reference, or reference value becomes a return address value,
2323 * then it
2324 * cannot be used as any of these values within the handler
2325 * (there is a path to
2326 * the handler where the value is not an internal reference,
2327 * and a path where it
2328 * is an internal reference) so mark the local variable as a
2329 * non-reference if we
2330 * are tracking the difference maps (for a JSR subroutine).
2331 *
2332 * @param localVariable variable index in the map
2333 * @param reachableHandlerBBNums the array with all the block numbers of
2334 * reachable handlers
2335 * @param reachableHandlerCount 0 through <code>reachableHandlerCount
2336 * - 1 </code> will all be valid
2337 * array indices
2338 * @param bbMaps TODO Document ME XXX
2339 */
2340 private void setHandlersMapsReturnAddress(int localVariable, int[] reachableHandlerBBNums, int reachableHandlerCount,
2341 byte[][] bbMaps) {
2342 for (int i = 0; i < reachableHandlerCount; i++) {
2343 if (bbMaps[reachableHandlerBBNums[i]][localVariable] != RETURN_ADDRESS) {
2344 bbMaps[reachableHandlerBBNums[i]][localVariable] = SET_TO_NONREFERENCE;
2345 }
2346 }
2347
2348 }
2349 }