188 * |
188 * |
189 * @param node the node expected to be popped, used to detect unbalanced pushes/pops |
189 * @param node the node expected to be popped, used to detect unbalanced pushes/pops |
190 * @return the node that was popped |
190 * @return the node that was popped |
191 */ |
191 */ |
192 @SuppressWarnings("unchecked") |
192 @SuppressWarnings("unchecked") |
193 public <T extends LexicalContextNode> T pop(final T node) { |
193 public <T extends Node> T pop(final T node) { |
194 --sp; |
194 --sp; |
195 final LexicalContextNode popped = stack[sp]; |
195 final LexicalContextNode popped = stack[sp]; |
196 stack[sp] = null; |
196 stack[sp] = null; |
197 if (popped instanceof Flags) { |
197 if (popped instanceof Flags) { |
198 return (T)((Flags<?>)popped).setFlag(this, flags[sp]); |
198 return (T)((Flags<?>)popped).setFlag(this, flags[sp]); |
467 /** |
467 /** |
468 * Count the number of scopes until a given node. Note that this method is solely used to figure out the number of |
468 * Count the number of scopes until a given node. Note that this method is solely used to figure out the number of |
469 * scopes that need to be explicitly popped in order to perform a break or continue jump within the current bytecode |
469 * scopes that need to be explicitly popped in order to perform a break or continue jump within the current bytecode |
470 * method. For this reason, the method returns 0 if it encounters a {@code SplitNode} between the current location |
470 * method. For this reason, the method returns 0 if it encounters a {@code SplitNode} between the current location |
471 * and the break/continue target. |
471 * and the break/continue target. |
472 * @param until node to stop counting at. Must be within the current function |
472 * @param until node to stop counting at. Must be within the current function |
473 * @return number of with scopes encountered in the context |
473 * @return number of with scopes encountered in the context |
474 */ |
474 */ |
475 public int getScopeNestingLevelTo(final LexicalContextNode until) { |
475 public int getScopeNestingLevelTo(final LexicalContextNode until) { |
476 assert until != null; |
476 assert until != null; |
477 //count the number of with nodes until "until" is hit |
477 //count the number of with nodes until "until" is hit |
563 } |
563 } |
564 return getContinueTo(); |
564 return getContinueTo(); |
565 } |
565 } |
566 |
566 |
567 /** |
567 /** |
|
568 * Find the inlined finally block node corresponding to this label. |
|
569 * @param labelName label name to search for. Must not be null. |
|
570 * @return closest inlined finally block with the given label |
|
571 */ |
|
572 public Block getInlinedFinally(final String labelName) { |
|
573 for (final NodeIterator<TryNode> iter = new NodeIterator<>(TryNode.class); iter.hasNext(); ) { |
|
574 final Block inlinedFinally = iter.next().getInlinedFinally(labelName); |
|
575 if (inlinedFinally != null) { |
|
576 return inlinedFinally; |
|
577 } |
|
578 } |
|
579 return null; |
|
580 } |
|
581 |
|
582 /** |
|
583 * Find the try node for an inlined finally block corresponding to this label. |
|
584 * @param labelName label name to search for. Must not be null. |
|
585 * @return the try node to which the labelled inlined finally block belongs. |
|
586 */ |
|
587 public TryNode getTryNodeForInlinedFinally(final String labelName) { |
|
588 for (final NodeIterator<TryNode> iter = new NodeIterator<>(TryNode.class); iter.hasNext(); ) { |
|
589 final TryNode tryNode = iter.next(); |
|
590 if (tryNode.getInlinedFinally(labelName) != null) { |
|
591 return tryNode; |
|
592 } |
|
593 } |
|
594 return null; |
|
595 } |
|
596 |
|
597 /** |
568 * Check the lexical context for a given label node by name |
598 * Check the lexical context for a given label node by name |
569 * @param name name of the label |
599 * @param name name of the label |
570 * @return LabelNode if found, null otherwise |
600 * @return LabelNode if found, null otherwise |
571 */ |
601 */ |
572 public LabelNode findLabel(final String name) { |
602 private LabelNode findLabel(final String name) { |
573 for (final Iterator<LabelNode> iter = new NodeIterator<>(LabelNode.class, getCurrentFunction()); iter.hasNext(); ) { |
603 for (final Iterator<LabelNode> iter = new NodeIterator<>(LabelNode.class, getCurrentFunction()); iter.hasNext(); ) { |
574 final LabelNode next = iter.next(); |
604 final LabelNode next = iter.next(); |
575 if (next.getLabelName().equals(name)) { |
605 if (next.getLabelName().equals(name)) { |
576 return next; |
606 return next; |
577 } |
607 } |
590 final LexicalContextNode next = stack[i]; |
620 final LexicalContextNode next = stack[i]; |
591 if (next == splitNode) { |
621 if (next == splitNode) { |
592 return true; |
622 return true; |
593 } else if (next == target) { |
623 } else if (next == target) { |
594 return false; |
624 return false; |
|
625 } else if (next instanceof TryNode) { |
|
626 for(final Block inlinedFinally: ((TryNode)next).getInlinedFinallies()) { |
|
627 if (TryNode.getLabelledInlinedFinallyBlock(inlinedFinally) == target) { |
|
628 return false; |
|
629 } |
|
630 } |
595 } |
631 } |
596 } |
632 } |
597 throw new AssertionError(target + " was expected in lexical context " + LexicalContext.this + " but wasn't"); |
633 throw new AssertionError(target + " was expected in lexical context " + LexicalContext.this + " but wasn't"); |
598 } |
634 } |
599 |
635 |