< prev index next >
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/JsrScope.java
Print this page
rev 56282 : [mq]: graal
*** 1,7 ****
/*
! * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
--- 1,7 ----
/*
! * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*** 22,89 ****
*/
package org.graalvm.compiler.java;
! public class JsrScope {
public static final JsrScope EMPTY_SCOPE = new JsrScope();
! private final long scope;
! private JsrScope(long scope) {
! this.scope = scope;
}
! public JsrScope() {
! this.scope = 0;
}
public int nextReturnAddress() {
! return (int) (scope & 0xffff);
}
! public JsrScope push(int jsrReturnBci) {
! if ((scope & 0xffff000000000000L) != 0) {
! throw new JsrNotSupportedBailout("only four jsr nesting levels are supported");
}
! return new JsrScope((scope << 16) | jsrReturnBci);
}
public boolean isEmpty() {
! return scope == 0;
}
public boolean isPrefixOf(JsrScope other) {
! return (scope & other.scope) == scope;
}
public JsrScope pop() {
! return new JsrScope(scope >>> 16);
}
@Override
public int hashCode() {
! return (int) (scope ^ (scope >>> 32));
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
! return obj != null && getClass() == obj.getClass() && scope == ((JsrScope) obj).scope;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
! long tmp = scope;
! sb.append(" [");
! while (tmp != 0) {
! sb.append(", ").append(tmp & 0xffff);
! tmp = tmp >>> 16;
}
! sb.append(']');
! return sb.toString();
}
}
--- 22,172 ----
*/
package org.graalvm.compiler.java;
! import org.graalvm.compiler.bytecode.Bytecodes;
+ /**
+ * Represents a subroutine entered via {@link Bytecodes#JSR} and exited via {@link Bytecodes#RET}.
+ */
+ public final class JsrScope {
+
+ /**
+ * The scope outside of any JSR/RET subroutine.
+ */
public static final JsrScope EMPTY_SCOPE = new JsrScope();
! private final char returnAddress;
!
! private final JsrScope parent;
! private JsrScope(int returnBci, JsrScope parent) {
! this.returnAddress = (char) returnBci;
! this.parent = parent;
}
! private JsrScope() {
! this.returnAddress = 0;
! this.parent = null;
}
public int nextReturnAddress() {
! return returnAddress;
}
! /**
! * Enters a new subroutine from the current scope represented by this object.
! *
! * @param returnBci the bytecode address returned to when leaving the new scope
! * @return an object representing the newly entered scope
! */
! public JsrScope push(int returnBci) {
! if (returnBci == 0) {
! throw new IllegalArgumentException("A bytecode subroutine cannot have a return address of 0");
}
! if (returnBci < 1 || returnBci > 0xFFFF) {
! throw new IllegalArgumentException("Bytecode subroutine return address cannot be encoded as a char: " + returnBci);
! }
! return new JsrScope(returnBci, this);
}
+ /**
+ * Determines if this is the scope outside of any JSR/RET subroutine.
+ */
public boolean isEmpty() {
! return returnAddress == 0;
}
+ /**
+ * Gets the ancestry of this scope starting with the {@link #returnAddress} of this scope's most
+ * distant ancestor and ending with the {@link #returnAddress} of this object.
+ *
+ * @return a String where each character is a 16-bit BCI. This value can be converted to an
+ * {@code int[]} with {@code value.chars().toArray()}.
+ */
+ public String getAncestry() {
+ StringBuilder sb = new StringBuilder();
+ for (JsrScope s = this; s != null; s = s.parent) {
+ if (!s.isEmpty()) {
+ sb.append(s.returnAddress);
+ }
+ }
+ return sb.reverse().toString();
+ }
+
+ /**
+ * Determines if the {@linkplain #getAncestry() ancestry} of this scope is a prefix of the
+ * ancestry of {@code other}.
+ */
public boolean isPrefixOf(JsrScope other) {
! if (isEmpty()) {
! return true;
! }
! String ancestry = getAncestry();
! String otherAncestry = other.getAncestry();
! return otherAncestry.startsWith(ancestry);
}
+ /**
+ * Gets this scope's parent.
+ *
+ * @return this scope's parent or {@link #EMPTY_SCOPE} if this is the {@link #EMPTY_SCOPE}
+ */
public JsrScope pop() {
! if (isEmpty()) {
! return this;
! }
! return parent;
}
@Override
public int hashCode() {
! int hc = returnAddress;
! JsrScope ancestor = parent;
! while (ancestor != null) {
! hc = hc ^ ancestor.returnAddress;
! ancestor = ancestor.parent;
! }
! return hc;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
! if (obj != null && getClass() == obj.getClass()) {
! JsrScope ancestor = this;
! JsrScope otherAncestor = (JsrScope) obj;
! while (ancestor != null) {
! if (otherAncestor == null) {
! return false;
! }
! if (otherAncestor.returnAddress != ancestor.returnAddress) {
! return false;
! }
! ancestor = ancestor.parent;
! otherAncestor = otherAncestor.parent;
! }
! if (otherAncestor == null) {
! return true;
! }
! }
! return false;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
!
! for (JsrScope ancestor = this; ancestor != null; ancestor = ancestor.parent) {
! if (!ancestor.isEmpty()) {
! if (sb.length() != 0) {
! sb.append(", ");
! }
! sb.append((int) ancestor.returnAddress);
! }
}
! return "[" + sb + "]";
}
}
< prev index next >