1 /*
2 * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
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
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24
25 package org.graalvm.compiler.java;
26
27 public class JsrScope {
28
29 public static final JsrScope EMPTY_SCOPE = new JsrScope();
30
31 private final long scope;
32
33 private JsrScope(long scope) {
34 this.scope = scope;
35 }
36
37 public JsrScope() {
38 this.scope = 0;
39 }
40
41 public int nextReturnAddress() {
42 return (int) (scope & 0xffff);
43 }
44
45 public JsrScope push(int jsrReturnBci) {
46 if ((scope & 0xffff000000000000L) != 0) {
47 throw new JsrNotSupportedBailout("only four jsr nesting levels are supported");
48 }
49 return new JsrScope((scope << 16) | jsrReturnBci);
50 }
51
52 public boolean isEmpty() {
53 return scope == 0;
54 }
55
56 public boolean isPrefixOf(JsrScope other) {
57 return (scope & other.scope) == scope;
58 }
59
60 public JsrScope pop() {
61 return new JsrScope(scope >>> 16);
62 }
63
64 @Override
65 public int hashCode() {
66 return (int) (scope ^ (scope >>> 32));
67 }
68
69 @Override
70 public boolean equals(Object obj) {
71 if (this == obj) {
72 return true;
73 }
74 return obj != null && getClass() == obj.getClass() && scope == ((JsrScope) obj).scope;
75 }
76
77 @Override
78 public String toString() {
79 StringBuilder sb = new StringBuilder();
80 long tmp = scope;
81 sb.append(" [");
82 while (tmp != 0) {
83 sb.append(", ").append(tmp & 0xffff);
84 tmp = tmp >>> 16;
85 }
86 sb.append(']');
87 return sb.toString();
88 }
89 }
|
1 /*
2 * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
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
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24
25 package org.graalvm.compiler.java;
26
27 import org.graalvm.compiler.bytecode.Bytecodes;
28
29 /**
30 * Represents a subroutine entered via {@link Bytecodes#JSR} and exited via {@link Bytecodes#RET}.
31 */
32 public final class JsrScope {
33
34 /**
35 * The scope outside of any JSR/RET subroutine.
36 */
37 public static final JsrScope EMPTY_SCOPE = new JsrScope();
38
39 private final char returnAddress;
40
41 private final JsrScope parent;
42
43 private JsrScope(int returnBci, JsrScope parent) {
44 this.returnAddress = (char) returnBci;
45 this.parent = parent;
46 }
47
48 private JsrScope() {
49 this.returnAddress = 0;
50 this.parent = null;
51 }
52
53 public int nextReturnAddress() {
54 return returnAddress;
55 }
56
57 /**
58 * Enters a new subroutine from the current scope represented by this object.
59 *
60 * @param returnBci the bytecode address returned to when leaving the new scope
61 * @return an object representing the newly entered scope
62 */
63 public JsrScope push(int returnBci) {
64 if (returnBci == 0) {
65 throw new IllegalArgumentException("A bytecode subroutine cannot have a return address of 0");
66 }
67 if (returnBci < 1 || returnBci > 0xFFFF) {
68 throw new IllegalArgumentException("Bytecode subroutine return address cannot be encoded as a char: " + returnBci);
69 }
70 return new JsrScope(returnBci, this);
71 }
72
73 /**
74 * Determines if this is the scope outside of any JSR/RET subroutine.
75 */
76 public boolean isEmpty() {
77 return returnAddress == 0;
78 }
79
80 /**
81 * Gets the ancestry of this scope starting with the {@link #returnAddress} of this scope's most
82 * distant ancestor and ending with the {@link #returnAddress} of this object.
83 *
84 * @return a String where each character is a 16-bit BCI. This value can be converted to an
85 * {@code int[]} with {@code value.chars().toArray()}.
86 */
87 public String getAncestry() {
88 StringBuilder sb = new StringBuilder();
89 for (JsrScope s = this; s != null; s = s.parent) {
90 if (!s.isEmpty()) {
91 sb.append(s.returnAddress);
92 }
93 }
94 return sb.reverse().toString();
95 }
96
97 /**
98 * Determines if the {@linkplain #getAncestry() ancestry} of this scope is a prefix of the
99 * ancestry of {@code other}.
100 */
101 public boolean isPrefixOf(JsrScope other) {
102 if (isEmpty()) {
103 return true;
104 }
105 String ancestry = getAncestry();
106 String otherAncestry = other.getAncestry();
107 return otherAncestry.startsWith(ancestry);
108 }
109
110 /**
111 * Gets this scope's parent.
112 *
113 * @return this scope's parent or {@link #EMPTY_SCOPE} if this is the {@link #EMPTY_SCOPE}
114 */
115 public JsrScope pop() {
116 if (isEmpty()) {
117 return this;
118 }
119 return parent;
120 }
121
122 @Override
123 public int hashCode() {
124 int hc = returnAddress;
125 JsrScope ancestor = parent;
126 while (ancestor != null) {
127 hc = hc ^ ancestor.returnAddress;
128 ancestor = ancestor.parent;
129 }
130 return hc;
131 }
132
133 @Override
134 public boolean equals(Object obj) {
135 if (this == obj) {
136 return true;
137 }
138 if (obj != null && getClass() == obj.getClass()) {
139 JsrScope ancestor = this;
140 JsrScope otherAncestor = (JsrScope) obj;
141 while (ancestor != null) {
142 if (otherAncestor == null) {
143 return false;
144 }
145 if (otherAncestor.returnAddress != ancestor.returnAddress) {
146 return false;
147 }
148 ancestor = ancestor.parent;
149 otherAncestor = otherAncestor.parent;
150 }
151 if (otherAncestor == null) {
152 return true;
153 }
154 }
155 return false;
156 }
157
158 @Override
159 public String toString() {
160 StringBuilder sb = new StringBuilder();
161
162 for (JsrScope ancestor = this; ancestor != null; ancestor = ancestor.parent) {
163 if (!ancestor.isEmpty()) {
164 if (sb.length() != 0) {
165 sb.append(", ");
166 }
167 sb.append((int) ancestor.returnAddress);
168 }
169 }
170 return "[" + sb + "]";
171 }
172 }
|