src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/JsrScope.java
changeset 58299 6df94ce3ab2f
parent 52910 583fd71c47d6
equal deleted inserted replaced
58298:0152ad7b38b8 58299:6df94ce3ab2f
     1 /*
     1 /*
     2  * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
     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.
     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.
    22  */
    22  */
    23 
    23 
    24 
    24 
    25 package org.graalvm.compiler.java;
    25 package org.graalvm.compiler.java;
    26 
    26 
    27 public class JsrScope {
    27 import org.graalvm.compiler.bytecode.Bytecodes;
    28 
    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      */
    29     public static final JsrScope EMPTY_SCOPE = new JsrScope();
    37     public static final JsrScope EMPTY_SCOPE = new JsrScope();
    30 
    38 
    31     private final long scope;
    39     private final char returnAddress;
    32 
    40 
    33     private JsrScope(long scope) {
    41     private final JsrScope parent;
    34         this.scope = scope;
    42 
       
    43     private JsrScope(int returnBci, JsrScope parent) {
       
    44         this.returnAddress = (char) returnBci;
       
    45         this.parent = parent;
    35     }
    46     }
    36 
    47 
    37     public JsrScope() {
    48     private JsrScope() {
    38         this.scope = 0;
    49         this.returnAddress = 0;
       
    50         this.parent = null;
    39     }
    51     }
    40 
    52 
    41     public int nextReturnAddress() {
    53     public int nextReturnAddress() {
    42         return (int) (scope & 0xffff);
    54         return returnAddress;
    43     }
    55     }
    44 
    56 
    45     public JsrScope push(int jsrReturnBci) {
    57     /**
    46         if ((scope & 0xffff000000000000L) != 0) {
    58      * Enters a new subroutine from the current scope represented by this object.
    47             throw new JsrNotSupportedBailout("only four jsr nesting levels are supported");
    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");
    48         }
    66         }
    49         return new JsrScope((scope << 16) | jsrReturnBci);
    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);
    50     }
    71     }
    51 
    72 
       
    73     /**
       
    74      * Determines if this is the scope outside of any JSR/RET subroutine.
       
    75      */
    52     public boolean isEmpty() {
    76     public boolean isEmpty() {
    53         return scope == 0;
    77         return returnAddress == 0;
    54     }
    78     }
    55 
    79 
    56     public boolean isPrefixOf(JsrScope other) {
    80     /**
    57         return (scope & other.scope) == scope;
    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();
    58     }
    95     }
    59 
    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      */
    60     public JsrScope pop() {
   115     public JsrScope pop() {
    61         return new JsrScope(scope >>> 16);
   116         if (isEmpty()) {
       
   117             return this;
       
   118         }
       
   119         return parent;
    62     }
   120     }
    63 
   121 
    64     @Override
   122     @Override
    65     public int hashCode() {
   123     public int hashCode() {
    66         return (int) (scope ^ (scope >>> 32));
   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;
    67     }
   131     }
    68 
   132 
    69     @Override
   133     @Override
    70     public boolean equals(Object obj) {
   134     public boolean equals(Object obj) {
    71         if (this == obj) {
   135         if (this == obj) {
    72             return true;
   136             return true;
    73         }
   137         }
    74         return obj != null && getClass() == obj.getClass() && scope == ((JsrScope) obj).scope;
   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;
    75     }
   156     }
    76 
   157 
    77     @Override
   158     @Override
    78     public String toString() {
   159     public String toString() {
    79         StringBuilder sb = new StringBuilder();
   160         StringBuilder sb = new StringBuilder();
    80         long tmp = scope;
   161 
    81         sb.append(" [");
   162         for (JsrScope ancestor = this; ancestor != null; ancestor = ancestor.parent) {
    82         while (tmp != 0) {
   163             if (!ancestor.isEmpty()) {
    83             sb.append(", ").append(tmp & 0xffff);
   164                 if (sb.length() != 0) {
    84             tmp = tmp >>> 16;
   165                     sb.append(", ");
       
   166                 }
       
   167                 sb.append((int) ancestor.returnAddress);
       
   168             }
    85         }
   169         }
    86         sb.append(']');
   170         return "[" + sb + "]";
    87         return sb.toString();
       
    88     }
   171     }
    89 }
   172 }