Mercurial > hg > truffle
comparison graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java @ 19535:97b35083d49d
Reduce casting in AbstractBytecodeParser. Consolidate asserts in HIRFrameStateBuilder.
author | Thomas Wuerthinger <thomas.wuerthinger@oracle.com> |
---|---|
date | Sun, 22 Feb 2015 15:19:54 +0100 |
parents | 9525e4d5b385 |
children | 2c3ea61e8b65 |
comparison
equal
deleted
inserted
replaced
19534:50b19dc35c66 | 19535:97b35083d49d |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. | 2 * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | 4 * |
5 * This code is free software; you can redistribute it and/or modify it | 5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as | 6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
29 | 29 |
30 import com.oracle.graal.api.code.*; | 30 import com.oracle.graal.api.code.*; |
31 import com.oracle.graal.api.meta.*; | 31 import com.oracle.graal.api.meta.*; |
32 import com.oracle.graal.compiler.common.type.*; | 32 import com.oracle.graal.compiler.common.type.*; |
33 import com.oracle.graal.debug.*; | 33 import com.oracle.graal.debug.*; |
34 import com.oracle.graal.java.BciBlockMapping.*; | |
34 import com.oracle.graal.java.GraphBuilderPlugin.ParameterPlugin; | 35 import com.oracle.graal.java.GraphBuilderPlugin.ParameterPlugin; |
35 import com.oracle.graal.nodeinfo.*; | 36 import com.oracle.graal.nodeinfo.*; |
36 import com.oracle.graal.nodes.*; | 37 import com.oracle.graal.nodes.*; |
37 import com.oracle.graal.nodes.calc.*; | 38 import com.oracle.graal.nodes.calc.*; |
38 import com.oracle.graal.nodes.java.*; | 39 import com.oracle.graal.nodes.java.*; |
39 import com.oracle.graal.nodes.util.*; | 40 import com.oracle.graal.nodes.util.*; |
40 | 41 |
41 public class HIRFrameStateBuilder extends AbstractFrameStateBuilder<ValueNode, HIRFrameStateBuilder> { | 42 public final class HIRFrameStateBuilder { |
42 | 43 |
43 private static final ValueNode[] EMPTY_ARRAY = new ValueNode[0]; | 44 private static final ValueNode[] EMPTY_ARRAY = new ValueNode[0]; |
44 private static final MonitorIdNode[] EMPTY_MONITOR_ARRAY = new MonitorIdNode[0]; | 45 private static final MonitorIdNode[] EMPTY_MONITOR_ARRAY = new MonitorIdNode[0]; |
46 | |
47 protected final ResolvedJavaMethod method; | |
48 protected int stackSize; | |
49 protected final ValueNode[] locals; | |
50 protected final ValueNode[] stack; | |
51 protected ValueNode[] lockedObjects; | |
52 | |
53 /** | |
54 * Specifies if asserting type checks are enabled. | |
55 */ | |
56 protected final boolean checkTypes; | |
57 | |
58 /** | |
59 * @see BytecodeFrame#rethrowException | |
60 */ | |
61 protected boolean rethrowException; | |
45 | 62 |
46 private MonitorIdNode[] monitorIds; | 63 private MonitorIdNode[] monitorIds; |
47 private final StructuredGraph graph; | 64 private final StructuredGraph graph; |
48 private final Supplier<FrameState> outerFrameStateSupplier; | 65 private final Supplier<FrameState> outerFrameStateSupplier; |
49 | 66 |
52 * | 69 * |
53 * @param method the method whose frame is simulated | 70 * @param method the method whose frame is simulated |
54 * @param graph the target graph of Graal nodes created by the builder | 71 * @param graph the target graph of Graal nodes created by the builder |
55 */ | 72 */ |
56 public HIRFrameStateBuilder(ResolvedJavaMethod method, StructuredGraph graph, boolean checkTypes, Supplier<FrameState> outerFrameStateSupplier) { | 73 public HIRFrameStateBuilder(ResolvedJavaMethod method, StructuredGraph graph, boolean checkTypes, Supplier<FrameState> outerFrameStateSupplier) { |
57 super(method, checkTypes); | 74 this.method = method; |
75 this.locals = allocateArray(method.getMaxLocals()); | |
76 this.stack = allocateArray(Math.max(1, method.getMaxStackSize())); | |
77 this.lockedObjects = allocateArray(0); | |
78 this.checkTypes = checkTypes; | |
58 | 79 |
59 assert graph != null; | 80 assert graph != null; |
60 | 81 |
61 this.monitorIds = EMPTY_MONITOR_ARRAY; | 82 this.monitorIds = EMPTY_MONITOR_ARRAY; |
62 this.graph = graph; | 83 this.graph = graph; |
63 this.outerFrameStateSupplier = outerFrameStateSupplier; | 84 this.outerFrameStateSupplier = outerFrameStateSupplier; |
64 } | 85 } |
65 | 86 |
66 public final void initializeFromArgumentsArray(ValueNode[] arguments) { | 87 public void initializeFromArgumentsArray(ValueNode[] arguments) { |
67 | 88 |
68 int javaIndex = 0; | 89 int javaIndex = 0; |
69 int index = 0; | 90 int index = 0; |
70 if (!method.isStatic()) { | 91 if (!method.isStatic()) { |
71 // set the receiver | 92 // set the receiver |
80 javaIndex += arguments[index].getKind().getSlotCount(); | 101 javaIndex += arguments[index].getKind().getSlotCount(); |
81 index++; | 102 index++; |
82 } | 103 } |
83 } | 104 } |
84 | 105 |
85 public final void initializeForMethodStart(boolean eagerResolve, ParameterPlugin parameterPlugin) { | 106 public void initializeForMethodStart(boolean eagerResolve, ParameterPlugin parameterPlugin) { |
86 | 107 |
87 int javaIndex = 0; | 108 int javaIndex = 0; |
88 int index = 0; | 109 int index = 0; |
89 if (!method.isStatic()) { | 110 if (!method.isStatic()) { |
90 // add the receiver | 111 // add the receiver |
126 index++; | 147 index++; |
127 } | 148 } |
128 } | 149 } |
129 | 150 |
130 private HIRFrameStateBuilder(HIRFrameStateBuilder other) { | 151 private HIRFrameStateBuilder(HIRFrameStateBuilder other) { |
131 super(other); | 152 this.method = other.method; |
153 this.stackSize = other.stackSize; | |
154 this.locals = other.locals.clone(); | |
155 this.stack = other.stack.clone(); | |
156 this.lockedObjects = other.lockedObjects.length == 0 ? other.lockedObjects : other.lockedObjects.clone(); | |
157 this.rethrowException = other.rethrowException; | |
158 this.checkTypes = other.checkTypes; | |
159 | |
160 assert locals.length == method.getMaxLocals(); | |
161 assert stack.length == Math.max(1, method.getMaxStackSize()); | |
162 | |
132 assert other.graph != null; | 163 assert other.graph != null; |
133 graph = other.graph; | 164 graph = other.graph; |
134 monitorIds = other.monitorIds.length == 0 ? other.monitorIds : other.monitorIds.clone(); | 165 monitorIds = other.monitorIds.length == 0 ? other.monitorIds : other.monitorIds.clone(); |
135 this.outerFrameStateSupplier = other.outerFrameStateSupplier; | 166 this.outerFrameStateSupplier = other.outerFrameStateSupplier; |
136 | 167 |
137 assert locals.length == method.getMaxLocals(); | 168 assert locals.length == method.getMaxLocals(); |
138 assert stack.length == Math.max(1, method.getMaxStackSize()); | 169 assert stack.length == Math.max(1, method.getMaxStackSize()); |
139 assert lockedObjects.length == monitorIds.length; | 170 assert lockedObjects.length == monitorIds.length; |
140 } | 171 } |
141 | 172 |
142 @Override | 173 private static ValueNode[] allocateArray(int length) { |
143 protected ValueNode[] allocateArray(int length) { | |
144 return length == 0 ? EMPTY_ARRAY : new ValueNode[length]; | 174 return length == 0 ? EMPTY_ARRAY : new ValueNode[length]; |
145 } | 175 } |
146 | 176 |
147 @Override | 177 @Override |
148 public String toString() { | 178 public String toString() { |
173 outerFrameState = outerFrameStateSupplier.get(); | 203 outerFrameState = outerFrameStateSupplier.get(); |
174 } | 204 } |
175 return graph.add(new FrameState(outerFrameState, method, bci, locals, stack, stackSize, lockedObjects, Arrays.asList(monitorIds), rethrowException, false)); | 205 return graph.add(new FrameState(outerFrameState, method, bci, locals, stack, stackSize, lockedObjects, Arrays.asList(monitorIds), rethrowException, false)); |
176 } | 206 } |
177 | 207 |
178 @Override | |
179 public HIRFrameStateBuilder copy() { | 208 public HIRFrameStateBuilder copy() { |
180 return new HIRFrameStateBuilder(this); | 209 return new HIRFrameStateBuilder(this); |
181 } | 210 } |
182 | 211 |
183 @Override | |
184 public boolean isCompatibleWith(HIRFrameStateBuilder other) { | 212 public boolean isCompatibleWith(HIRFrameStateBuilder other) { |
185 assert method.equals(other.method) && graph == other.graph && localsSize() == other.localsSize() : "Can only compare frame states of the same method"; | 213 assert method.equals(other.method) && graph == other.graph && localsSize() == other.localsSize() : "Can only compare frame states of the same method"; |
186 assert lockedObjects.length == monitorIds.length && other.lockedObjects.length == other.monitorIds.length : "mismatch between lockedObjects and monitorIds"; | 214 assert lockedObjects.length == monitorIds.length && other.lockedObjects.length == other.monitorIds.length : "mismatch between lockedObjects and monitorIds"; |
187 | 215 |
188 if (stackSize() != other.stackSize()) { | 216 if (stackSize() != other.stackSize()) { |
378 } | 406 } |
379 | 407 |
380 /** | 408 /** |
381 * @return the current lock depth | 409 * @return the current lock depth |
382 */ | 410 */ |
383 @Override | |
384 public int lockDepth() { | 411 public int lockDepth() { |
385 assert lockedObjects.length == monitorIds.length; | 412 assert lockedObjects.length == monitorIds.length; |
386 return lockedObjects.length; | 413 return lockedObjects.length; |
387 } | 414 } |
388 | 415 |
403 return true; | 430 return true; |
404 } | 431 } |
405 } | 432 } |
406 return false; | 433 return false; |
407 } | 434 } |
435 | |
436 public void clearNonLiveLocals(BciBlock block, LocalLiveness liveness, boolean liveIn) { | |
437 /* | |
438 * (lstadler) if somebody is tempted to remove/disable this clearing code: it's possible to | |
439 * remove it for normal compilations, but not for OSR compilations - otherwise dead object | |
440 * slots at the OSR entry aren't cleared. it is also not enough to rely on PiNodes with | |
441 * Kind.Illegal, because the conflicting branch might not have been parsed. | |
442 */ | |
443 if (liveness == null) { | |
444 return; | |
445 } | |
446 if (liveIn) { | |
447 for (int i = 0; i < locals.length; i++) { | |
448 if (!liveness.localIsLiveIn(block, i)) { | |
449 locals[i] = null; | |
450 } | |
451 } | |
452 } else { | |
453 for (int i = 0; i < locals.length; i++) { | |
454 if (!liveness.localIsLiveOut(block, i)) { | |
455 locals[i] = null; | |
456 } | |
457 } | |
458 } | |
459 } | |
460 | |
461 /** | |
462 * @see BytecodeFrame#rethrowException | |
463 */ | |
464 public boolean rethrowException() { | |
465 return rethrowException; | |
466 } | |
467 | |
468 /** | |
469 * @see BytecodeFrame#rethrowException | |
470 */ | |
471 public void setRethrowException(boolean b) { | |
472 rethrowException = b; | |
473 } | |
474 | |
475 /** | |
476 * Returns the size of the local variables. | |
477 * | |
478 * @return the size of the local variables | |
479 */ | |
480 public int localsSize() { | |
481 return locals.length; | |
482 } | |
483 | |
484 /** | |
485 * Gets the current size (height) of the stack. | |
486 */ | |
487 public int stackSize() { | |
488 return stackSize; | |
489 } | |
490 | |
491 /** | |
492 * Gets the value in the local variables at the specified index, without any sanity checking. | |
493 * | |
494 * @param i the index into the locals | |
495 * @return the instruction that produced the value for the specified local | |
496 */ | |
497 public ValueNode localAt(int i) { | |
498 return locals[i]; | |
499 } | |
500 | |
501 /** | |
502 * Get the value on the stack at the specified stack index. | |
503 * | |
504 * @param i the index into the stack, with {@code 0} being the bottom of the stack | |
505 * @return the instruction at the specified position in the stack | |
506 */ | |
507 public ValueNode stackAt(int i) { | |
508 return stack[i]; | |
509 } | |
510 | |
511 /** | |
512 * Gets the value in the lock at the specified index, without any sanity checking. | |
513 * | |
514 * @param i the index into the lock | |
515 * @return the instruction that produced the value for the specified lock | |
516 */ | |
517 public ValueNode lockAt(int i) { | |
518 return lockedObjects[i]; | |
519 } | |
520 | |
521 public void storeLock(int i, ValueNode lock) { | |
522 lockedObjects[i] = lock; | |
523 } | |
524 | |
525 /** | |
526 * Loads the local variable at the specified index, checking that the returned value is non-null | |
527 * and that two-stack values are properly handled. | |
528 * | |
529 * @param i the index of the local variable to load | |
530 * @return the instruction that produced the specified local | |
531 */ | |
532 public ValueNode loadLocal(int i) { | |
533 ValueNode x = locals[i]; | |
534 assert assertLoadLocal(i, x); | |
535 return x; | |
536 } | |
537 | |
538 private boolean assertLoadLocal(int i, ValueNode x) { | |
539 assert x != null : i; | |
540 assert !checkTypes || (x.getKind().getSlotCount() == 1 || locals[i + 1] == null); | |
541 assert !checkTypes || (i == 0 || locals[i - 1] == null || locals[i - 1].getKind().getSlotCount() == 1); | |
542 return true; | |
543 } | |
544 | |
545 /** | |
546 * Stores a given local variable at the specified index. If the value occupies two slots, then | |
547 * the next local variable index is also overwritten. | |
548 * | |
549 * @param i the index at which to store | |
550 * @param x the instruction which produces the value for the local | |
551 */ | |
552 public void storeLocal(int i, ValueNode x) { | |
553 assert assertStoreLocal(x); | |
554 locals[i] = x; | |
555 if (x != null && x.getKind().needsTwoSlots()) { | |
556 // if this is a double word, then kill i+1 | |
557 locals[i + 1] = null; | |
558 } | |
559 if (x != null && i > 0) { | |
560 ValueNode p = locals[i - 1]; | |
561 if (p != null && p.getKind().needsTwoSlots()) { | |
562 // if there was a double word at i - 1, then kill it | |
563 locals[i - 1] = null; | |
564 } | |
565 } | |
566 } | |
567 | |
568 private boolean assertStoreLocal(ValueNode x) { | |
569 assert x == null || !checkTypes || (x.getKind() != Kind.Void && x.getKind() != Kind.Illegal) : "unexpected value: " + x; | |
570 return true; | |
571 } | |
572 | |
573 public void storeStack(int i, ValueNode x) { | |
574 assert assertStoreStack(i, x); | |
575 stack[i] = x; | |
576 } | |
577 | |
578 private boolean assertStoreStack(int i, ValueNode x) { | |
579 assert x == null || (stack[i] == null || x.getKind() == stack[i].getKind()) : "Method does not handle changes from one-slot to two-slot values or non-alive values"; | |
580 return true; | |
581 } | |
582 | |
583 /** | |
584 * Pushes an instruction onto the stack with the expected type. | |
585 * | |
586 * @param kind the type expected for this instruction | |
587 * @param x the instruction to push onto the stack | |
588 */ | |
589 public void push(Kind kind, ValueNode x) { | |
590 assert assertPush(kind, x); | |
591 xpush(x); | |
592 if (kind.needsTwoSlots()) { | |
593 xpush(null); | |
594 } | |
595 } | |
596 | |
597 private boolean assertPush(Kind kind, ValueNode x) { | |
598 assert !checkTypes || (x.getKind() != Kind.Void && x.getKind() != Kind.Illegal); | |
599 assert x != null && (!checkTypes || x.getKind() == kind); | |
600 return true; | |
601 } | |
602 | |
603 /** | |
604 * Pushes a value onto the stack without checking the type. | |
605 * | |
606 * @param x the instruction to push onto the stack | |
607 */ | |
608 public void xpush(ValueNode x) { | |
609 assert assertXpush(x); | |
610 stack[stackSize++] = x; | |
611 } | |
612 | |
613 private boolean assertXpush(ValueNode x) { | |
614 assert !checkTypes || (x == null || (x.getKind() != Kind.Void && x.getKind() != Kind.Illegal)); | |
615 return true; | |
616 } | |
617 | |
618 /** | |
619 * Pushes a value onto the stack and checks that it is an int. | |
620 * | |
621 * @param x the instruction to push onto the stack | |
622 */ | |
623 public void ipush(ValueNode x) { | |
624 assert assertInt(x); | |
625 xpush(x); | |
626 } | |
627 | |
628 /** | |
629 * Pushes a value onto the stack and checks that it is a float. | |
630 * | |
631 * @param x the instruction to push onto the stack | |
632 */ | |
633 public void fpush(ValueNode x) { | |
634 assert assertFloat(x); | |
635 xpush(x); | |
636 } | |
637 | |
638 /** | |
639 * Pushes a value onto the stack and checks that it is an object. | |
640 * | |
641 * @param x the instruction to push onto the stack | |
642 */ | |
643 public void apush(ValueNode x) { | |
644 assert assertObject(x); | |
645 xpush(x); | |
646 } | |
647 | |
648 /** | |
649 * Pushes a value onto the stack and checks that it is a long. | |
650 * | |
651 * @param x the instruction to push onto the stack | |
652 */ | |
653 public void lpush(ValueNode x) { | |
654 assert assertLong(x); | |
655 xpush(x); | |
656 xpush(null); | |
657 } | |
658 | |
659 /** | |
660 * Pushes a value onto the stack and checks that it is a double. | |
661 * | |
662 * @param x the instruction to push onto the stack | |
663 */ | |
664 public void dpush(ValueNode x) { | |
665 assert assertDouble(x); | |
666 xpush(x); | |
667 xpush(null); | |
668 } | |
669 | |
670 public void pushReturn(Kind kind, ValueNode x) { | |
671 if (kind != Kind.Void) { | |
672 push(kind.getStackKind(), x); | |
673 } | |
674 } | |
675 | |
676 /** | |
677 * Pops an instruction off the stack with the expected type. | |
678 * | |
679 * @param kind the expected type | |
680 * @return the instruction on the top of the stack | |
681 */ | |
682 public ValueNode pop(Kind kind) { | |
683 if (kind.needsTwoSlots()) { | |
684 xpop(); | |
685 } | |
686 assert assertPop(kind); | |
687 return xpop(); | |
688 } | |
689 | |
690 private boolean assertPop(Kind kind) { | |
691 assert kind != Kind.Void; | |
692 ValueNode x = xpeek(); | |
693 assert x != null && (!checkTypes || x.getKind() == kind); | |
694 return true; | |
695 } | |
696 | |
697 /** | |
698 * Pops a value off of the stack without checking the type. | |
699 * | |
700 * @return x the instruction popped off the stack | |
701 */ | |
702 public ValueNode xpop() { | |
703 return stack[--stackSize]; | |
704 } | |
705 | |
706 private ValueNode xpeek() { | |
707 return stack[stackSize - 1]; | |
708 } | |
709 | |
710 /** | |
711 * Pops a value off of the stack and checks that it is an int. | |
712 * | |
713 * @return x the instruction popped off the stack | |
714 */ | |
715 public ValueNode ipop() { | |
716 assert assertIntPeek(); | |
717 return xpop(); | |
718 } | |
719 | |
720 /** | |
721 * Pops a value off of the stack and checks that it is a float. | |
722 * | |
723 * @return x the instruction popped off the stack | |
724 */ | |
725 public ValueNode fpop() { | |
726 assert assertFloatPeek(); | |
727 return xpop(); | |
728 } | |
729 | |
730 /** | |
731 * Pops a value off of the stack and checks that it is an object. | |
732 * | |
733 * @return x the instruction popped off the stack | |
734 */ | |
735 public ValueNode apop() { | |
736 assert assertObjectPeek(); | |
737 return xpop(); | |
738 } | |
739 | |
740 /** | |
741 * Pops a value off of the stack and checks that it is a long. | |
742 * | |
743 * @return x the instruction popped off the stack | |
744 */ | |
745 public ValueNode lpop() { | |
746 assert assertHighPeek(); | |
747 xpop(); | |
748 assert assertLongPeek(); | |
749 return xpop(); | |
750 } | |
751 | |
752 /** | |
753 * Pops a value off of the stack and checks that it is a double. | |
754 * | |
755 * @return x the instruction popped off the stack | |
756 */ | |
757 public ValueNode dpop() { | |
758 assert assertHighPeek(); | |
759 xpop(); | |
760 assert assertDoublePeek(); | |
761 return xpop(); | |
762 } | |
763 | |
764 /** | |
765 * Pop the specified number of slots off of this stack and return them as an array of | |
766 * instructions. | |
767 * | |
768 * @return an array containing the arguments off of the stack | |
769 */ | |
770 public ValueNode[] popArguments(int argSize) { | |
771 ValueNode[] result = allocateArray(argSize); | |
772 int newStackSize = stackSize; | |
773 for (int i = argSize - 1; i >= 0; i--) { | |
774 newStackSize--; | |
775 if (stack[newStackSize] == null) { | |
776 /* Two-slot value. */ | |
777 newStackSize--; | |
778 assert stack[newStackSize].getKind().needsTwoSlots(); | |
779 } else { | |
780 assert !checkTypes || (stack[newStackSize].getKind().getSlotCount() == 1); | |
781 } | |
782 result[i] = stack[newStackSize]; | |
783 } | |
784 stackSize = newStackSize; | |
785 return result; | |
786 } | |
787 | |
788 /** | |
789 * Peeks an element from the operand stack. | |
790 * | |
791 * @param argumentNumber The number of the argument, relative from the top of the stack (0 = | |
792 * top). Long and double arguments only count as one argument, i.e., null-slots are | |
793 * ignored. | |
794 * @return The peeked argument. | |
795 */ | |
796 public ValueNode peek(int argumentNumber) { | |
797 int idx = stackSize() - 1; | |
798 for (int i = 0; i < argumentNumber; i++) { | |
799 if (stackAt(idx) == null) { | |
800 idx--; | |
801 assert stackAt(idx).getKind().needsTwoSlots(); | |
802 } | |
803 idx--; | |
804 } | |
805 return stackAt(idx); | |
806 } | |
807 | |
808 /** | |
809 * Clears all values on this stack. | |
810 */ | |
811 public void clearStack() { | |
812 stackSize = 0; | |
813 } | |
814 | |
815 private boolean assertLongPeek() { | |
816 return assertLong(xpeek()); | |
817 } | |
818 | |
819 private static boolean assertLong(ValueNode x) { | |
820 assert x != null && (x.getKind() == Kind.Long); | |
821 return true; | |
822 } | |
823 | |
824 private boolean assertIntPeek() { | |
825 return assertInt(xpeek()); | |
826 } | |
827 | |
828 private static boolean assertInt(ValueNode x) { | |
829 assert x != null && (x.getKind() == Kind.Int); | |
830 return true; | |
831 } | |
832 | |
833 private boolean assertFloatPeek() { | |
834 return assertFloat(xpeek()); | |
835 } | |
836 | |
837 private static boolean assertFloat(ValueNode x) { | |
838 assert x != null && (x.getKind() == Kind.Float); | |
839 return true; | |
840 } | |
841 | |
842 private boolean assertObjectPeek() { | |
843 return assertObject(xpeek()); | |
844 } | |
845 | |
846 private boolean assertObject(ValueNode x) { | |
847 assert x != null && (!checkTypes || (x.getKind() == Kind.Object)); | |
848 return true; | |
849 } | |
850 | |
851 private boolean assertDoublePeek() { | |
852 return assertDouble(xpeek()); | |
853 } | |
854 | |
855 private static boolean assertDouble(ValueNode x) { | |
856 assert x != null && (x.getKind() == Kind.Double); | |
857 return true; | |
858 } | |
859 | |
860 private boolean assertHighPeek() { | |
861 assert xpeek() == null; | |
862 return true; | |
863 } | |
408 } | 864 } |