src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FinalizableSubclassTest.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File hotspot Sdiff src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test

src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FinalizableSubclassTest.java

Print this page




  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 package org.graalvm.compiler.core.test;
  24 
  25 import java.io.ByteArrayOutputStream;
  26 import java.io.IOException;
  27 import java.io.InputStream;
  28 import java.lang.reflect.Constructor;
  29 import java.util.HashMap;
  30 
  31 import jdk.vm.ci.meta.Assumptions;
  32 import jdk.vm.ci.meta.Assumptions.Assumption;
  33 import jdk.vm.ci.meta.Assumptions.LeafType;
  34 import jdk.vm.ci.meta.Assumptions.NoFinalizableSubclass;
  35 import jdk.vm.ci.meta.ResolvedJavaMethod;
  36 
  37 import org.junit.Assert;
  38 import org.junit.Test;
  39 
  40 import org.graalvm.compiler.debug.Debug;
  41 import org.graalvm.compiler.java.GraphBuilderPhase;
  42 import org.graalvm.compiler.nodes.StructuredGraph;
  43 import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
  44 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
  45 import org.graalvm.compiler.nodes.java.RegisterFinalizerNode;

  46 import org.graalvm.compiler.phases.OptimisticOptimizations;
  47 import org.graalvm.compiler.phases.common.CanonicalizerPhase;
  48 import org.graalvm.compiler.phases.common.inlining.InliningPhase;
  49 import org.graalvm.compiler.phases.tiers.HighTierContext;








  50 
  51 public class FinalizableSubclassTest extends GraalCompilerTest {
  52 
  53     /**
  54      * used as template to generate class files at runtime.
  55      */
  56     public static class NoFinalizerEverAAAA {
  57     }
  58 
  59     public static class NoFinalizerYetAAAA {
  60     }
  61 
  62     public static final class WithFinalizerAAAA extends NoFinalizerYetAAAA {
  63 
  64         @Override
  65         protected void finalize() throws Throwable {
  66             super.finalize();
  67         }
  68     }
  69 
  70     private StructuredGraph parseAndProcess(Class<?> cl, AllowAssumptions allowAssumptions) {
  71         Constructor<?>[] constructors = cl.getConstructors();
  72         Assert.assertTrue(constructors.length == 1);
  73         final ResolvedJavaMethod javaMethod = getMetaAccess().lookupJavaMethod(constructors[0]);
  74         StructuredGraph graph = new StructuredGraph.Builder(getInitialOptions(), allowAssumptions).method(javaMethod).build();

  75 
  76         GraphBuilderConfiguration conf = GraphBuilderConfiguration.getSnippetDefault(getDefaultGraphBuilderPlugins());
  77         new GraphBuilderPhase.Instance(getMetaAccess(), getProviders().getStampProvider(), getProviders().getConstantReflection(), getProviders().getConstantFieldProvider(), conf,
  78                         OptimisticOptimizations.ALL, null).apply(graph);
  79         HighTierContext context = new HighTierContext(getProviders(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
  80         new InliningPhase(new CanonicalizerPhase()).apply(graph, context);
  81         new CanonicalizerPhase().apply(graph, context);
  82         return graph;
  83     }
  84 
  85     private void checkForRegisterFinalizeNode(Class<?> cl, boolean shouldContainFinalizer, AllowAssumptions allowAssumptions) {
  86         StructuredGraph graph = parseAndProcess(cl, allowAssumptions);
  87         Assert.assertTrue(graph.getNodes().filter(RegisterFinalizerNode.class).count() == (shouldContainFinalizer ? 1 : 0));
  88         int noFinalizerAssumption = 0;
  89         Assumptions assumptions = graph.getAssumptions();
  90         if (assumptions != null) {
  91             for (Assumption a : assumptions) {
  92                 if (a instanceof NoFinalizableSubclass) {
  93                     noFinalizerAssumption++;
  94                 } else if (a instanceof LeafType) {
  95                     // Need to also allow leaf type assumption instead of no finalizable subclass
  96                     // assumption.
  97                     noFinalizerAssumption++;
  98                 }
  99             }
 100         }
 101         Assert.assertTrue(noFinalizerAssumption == (shouldContainFinalizer ? 0 : 1));
 102     }
 103 
 104     /**
 105      * Use a custom class loader to generate classes, to make sure the given classes are loaded in
 106      * correct order.
 107      */
 108     @Test
 109     public void test1() throws ClassNotFoundException {

 110         for (int i = 0; i < 2; i++) {
 111             ClassTemplateLoader loader = new ClassTemplateLoader();
 112             checkForRegisterFinalizeNode(loader.findClass("NoFinalizerEverAAAA"), true, AllowAssumptions.NO);
 113             checkForRegisterFinalizeNode(loader.findClass("NoFinalizerEverAAAA"), false, AllowAssumptions.YES);
 114 
 115             checkForRegisterFinalizeNode(loader.findClass("NoFinalizerYetAAAA"), false, AllowAssumptions.YES);
 116 
 117             checkForRegisterFinalizeNode(loader.findClass("WithFinalizerAAAA"), true, AllowAssumptions.YES);
 118             checkForRegisterFinalizeNode(loader.findClass("NoFinalizerYetAAAA"), true, AllowAssumptions.YES);
 119         }
 120     }
 121 
 122     private static class ClassTemplateLoader extends ClassLoader {
 123 
 124         private static int loaderInstance = 0;
 125 
 126         private final String replaceTo;
 127         private HashMap<String, Class<?>> cache = new HashMap<>();
 128 
 129         ClassTemplateLoader() {


 130             loaderInstance++;

 131             replaceTo = String.format("%04d", loaderInstance);
 132         }
 133 
 134         @Override
 135         protected Class<?> findClass(final String name) throws ClassNotFoundException {
 136             String nameReplaced = name.replaceAll("AAAA", replaceTo);
 137             if (cache.containsKey(nameReplaced)) {
 138                 return cache.get(nameReplaced);
 139             }
 140 
 141             // copy classfile to byte array
 142             byte[] classData = null;
 143             try {
 144                 InputStream is = FinalizableSubclassTest.class.getResourceAsStream("FinalizableSubclassTest$" + name + ".class");
 145                 assert is != null;
 146                 ByteArrayOutputStream baos = new ByteArrayOutputStream();
 147 
 148                 byte[] buf = new byte[1024];
 149                 int size;
 150                 while ((size = is.read(buf, 0, buf.length)) != -1) {
 151                     baos.write(buf, 0, size);
 152                 }
 153                 baos.flush();
 154                 classData = baos.toByteArray();
 155             } catch (IOException e) {
 156                 Assert.fail("can't access class: " + name);
 157             }
 158             dumpStringsInByteArray(classData);

 159 
 160             // replace all occurrences of "AAAA" in classfile
 161             int index = -1;
 162             while ((index = indexOfAAAA(classData, index + 1)) != -1) {
 163                 replaceAAAA(classData, index, replaceTo);
 164             }
 165             dumpStringsInByteArray(classData);
 166 
 167             Class<?> c = defineClass(null, classData, 0, classData.length);
 168             cache.put(nameReplaced, c);
 169             return c;
 170         }
 171 
 172         private static int indexOfAAAA(byte[] b, int index) {
 173             for (int i = index; i < b.length; i++) {
 174                 boolean match = true;
 175                 for (int j = i; j < i + 4; j++) {
 176                     if (b[j] != (byte) 'A') {
 177                         match = false;
 178                         break;
 179                     }
 180                 }
 181                 if (match) {
 182                     return i;
 183                 }
 184             }
 185             return -1;
 186         }
 187 
 188         private static void replaceAAAA(byte[] b, int index, String replacer) {
 189             assert replacer.length() == 4;
 190             for (int i = index; i < index + 4; i++) {
 191                 b[i] = (byte) replacer.charAt(i - index);
 192             }
 193         }
 194 
 195         private static void dumpStringsInByteArray(byte[] b) {
 196             boolean wasChar = true;
 197             StringBuilder sb = new StringBuilder();
 198             for (Byte x : b) {
 199                 // check for [a-zA-Z0-9]
 200                 if ((x >= 0x41 && x <= 0x7a) || (x >= 0x30 && x <= 0x39)) {
 201                     if (!wasChar) {
 202                         Debug.log(sb + "");
 203                         sb.setLength(0);
 204                     }
 205                     sb.append(String.format("%c", x));
 206                     wasChar = true;
 207                 } else {
 208                     wasChar = false;
 209                 }
 210             }
 211             Debug.log(sb + "");
 212         }
 213     }
 214 }


  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 package org.graalvm.compiler.core.test;
  24 
  25 import java.io.ByteArrayOutputStream;
  26 import java.io.IOException;
  27 import java.io.InputStream;
  28 import java.lang.reflect.Constructor;
  29 import java.util.HashMap;
  30 
  31 import org.graalvm.compiler.debug.DebugContext;









  32 import org.graalvm.compiler.java.GraphBuilderPhase;
  33 import org.graalvm.compiler.nodes.StructuredGraph;
  34 import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
  35 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
  36 import org.graalvm.compiler.nodes.java.RegisterFinalizerNode;
  37 import org.graalvm.compiler.options.OptionValues;
  38 import org.graalvm.compiler.phases.OptimisticOptimizations;
  39 import org.graalvm.compiler.phases.common.CanonicalizerPhase;
  40 import org.graalvm.compiler.phases.common.inlining.InliningPhase;
  41 import org.graalvm.compiler.phases.tiers.HighTierContext;
  42 import org.junit.Assert;
  43 import org.junit.Test;
  44 
  45 import jdk.vm.ci.meta.Assumptions;
  46 import jdk.vm.ci.meta.Assumptions.Assumption;
  47 import jdk.vm.ci.meta.Assumptions.LeafType;
  48 import jdk.vm.ci.meta.Assumptions.NoFinalizableSubclass;
  49 import jdk.vm.ci.meta.ResolvedJavaMethod;
  50 
  51 public class FinalizableSubclassTest extends GraalCompilerTest {
  52 
  53     /**
  54      * used as template to generate class files at runtime.
  55      */
  56     public static class NoFinalizerEverAAAA {
  57     }
  58 
  59     public static class NoFinalizerYetAAAA {
  60     }
  61 
  62     public static final class WithFinalizerAAAA extends NoFinalizerYetAAAA {
  63 
  64         @Override
  65         protected void finalize() throws Throwable {
  66             super.finalize();
  67         }
  68     }
  69 
  70     private StructuredGraph parseAndProcess(Class<?> cl, AllowAssumptions allowAssumptions) {
  71         Constructor<?>[] constructors = cl.getConstructors();
  72         Assert.assertTrue(constructors.length == 1);
  73         final ResolvedJavaMethod javaMethod = getMetaAccess().lookupJavaMethod(constructors[0]);
  74         OptionValues options = getInitialOptions();
  75         StructuredGraph graph = new StructuredGraph.Builder(options, getDebugContext(options), allowAssumptions).method(javaMethod).build();
  76 
  77         GraphBuilderConfiguration conf = GraphBuilderConfiguration.getSnippetDefault(getDefaultGraphBuilderPlugins());
  78         new GraphBuilderPhase.Instance(getMetaAccess(), getProviders().getStampProvider(), getProviders().getConstantReflection(), getProviders().getConstantFieldProvider(), conf,
  79                         OptimisticOptimizations.ALL, null).apply(graph);
  80         HighTierContext context = new HighTierContext(getProviders(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
  81         new InliningPhase(new CanonicalizerPhase()).apply(graph, context);
  82         new CanonicalizerPhase().apply(graph, context);
  83         return graph;
  84     }
  85 
  86     private void checkForRegisterFinalizeNode(Class<?> cl, boolean shouldContainFinalizer, AllowAssumptions allowAssumptions) {
  87         StructuredGraph graph = parseAndProcess(cl, allowAssumptions);
  88         Assert.assertTrue(graph.getNodes().filter(RegisterFinalizerNode.class).count() == (shouldContainFinalizer ? 1 : 0));
  89         int noFinalizerAssumption = 0;
  90         Assumptions assumptions = graph.getAssumptions();
  91         if (assumptions != null) {
  92             for (Assumption a : assumptions) {
  93                 if (a instanceof NoFinalizableSubclass) {
  94                     noFinalizerAssumption++;
  95                 } else if (a instanceof LeafType) {
  96                     // Need to also allow leaf type assumption instead of no finalizable subclass
  97                     // assumption.
  98                     noFinalizerAssumption++;
  99                 }
 100             }
 101         }
 102         Assert.assertTrue(noFinalizerAssumption == (shouldContainFinalizer ? 0 : 1));
 103     }
 104 
 105     /**
 106      * Use a custom class loader to generate classes, to make sure the given classes are loaded in
 107      * correct order.
 108      */
 109     @Test
 110     public void test1() throws ClassNotFoundException {
 111         DebugContext debug = getDebugContext();
 112         for (int i = 0; i < 2; i++) {
 113             ClassTemplateLoader loader = new ClassTemplateLoader(debug);
 114             checkForRegisterFinalizeNode(loader.findClass("NoFinalizerEverAAAA"), true, AllowAssumptions.NO);
 115             checkForRegisterFinalizeNode(loader.findClass("NoFinalizerEverAAAA"), false, AllowAssumptions.YES);
 116 
 117             checkForRegisterFinalizeNode(loader.findClass("NoFinalizerYetAAAA"), false, AllowAssumptions.YES);
 118 
 119             checkForRegisterFinalizeNode(loader.findClass("WithFinalizerAAAA"), true, AllowAssumptions.YES);
 120             checkForRegisterFinalizeNode(loader.findClass("NoFinalizerYetAAAA"), true, AllowAssumptions.YES);
 121         }
 122     }
 123 
 124     private static class ClassTemplateLoader extends ClassLoader {
 125 
 126         private static int loaderInstance = 0;
 127 
 128         private final String replaceTo;
 129         private HashMap<String, Class<?>> cache = new HashMap<>();
 130 
 131         private final DebugContext debug;
 132 
 133         ClassTemplateLoader(DebugContext debug) {
 134             loaderInstance++;
 135             this.debug = debug;
 136             replaceTo = String.format("%04d", loaderInstance);
 137         }
 138 
 139         @Override
 140         protected Class<?> findClass(final String name) throws ClassNotFoundException {
 141             String nameReplaced = name.replaceAll("AAAA", replaceTo);
 142             if (cache.containsKey(nameReplaced)) {
 143                 return cache.get(nameReplaced);
 144             }
 145 
 146             // copy classfile to byte array
 147             byte[] classData = null;
 148             try {
 149                 InputStream is = FinalizableSubclassTest.class.getResourceAsStream("FinalizableSubclassTest$" + name + ".class");
 150                 assert is != null;
 151                 ByteArrayOutputStream baos = new ByteArrayOutputStream();
 152 
 153                 byte[] buf = new byte[1024];
 154                 int size;
 155                 while ((size = is.read(buf, 0, buf.length)) != -1) {
 156                     baos.write(buf, 0, size);
 157                 }
 158                 baos.flush();
 159                 classData = baos.toByteArray();
 160             } catch (IOException e) {
 161                 Assert.fail("can't access class: " + name);
 162             }
 163 
 164             dumpStringsInByteArray(debug, classData);
 165 
 166             // replace all occurrences of "AAAA" in classfile
 167             int index = -1;
 168             while ((index = indexOfAAAA(classData, index + 1)) != -1) {
 169                 replaceAAAA(classData, index, replaceTo);
 170             }
 171             dumpStringsInByteArray(debug, classData);
 172 
 173             Class<?> c = defineClass(null, classData, 0, classData.length);
 174             cache.put(nameReplaced, c);
 175             return c;
 176         }
 177 
 178         private static int indexOfAAAA(byte[] b, int index) {
 179             for (int i = index; i < b.length; i++) {
 180                 boolean match = true;
 181                 for (int j = i; j < i + 4; j++) {
 182                     if (b[j] != (byte) 'A') {
 183                         match = false;
 184                         break;
 185                     }
 186                 }
 187                 if (match) {
 188                     return i;
 189                 }
 190             }
 191             return -1;
 192         }
 193 
 194         private static void replaceAAAA(byte[] b, int index, String replacer) {
 195             assert replacer.length() == 4;
 196             for (int i = index; i < index + 4; i++) {
 197                 b[i] = (byte) replacer.charAt(i - index);
 198             }
 199         }
 200 
 201         private static void dumpStringsInByteArray(DebugContext debug, byte[] b) {
 202             boolean wasChar = true;
 203             StringBuilder sb = new StringBuilder();
 204             for (Byte x : b) {
 205                 // check for [a-zA-Z0-9]
 206                 if ((x >= 0x41 && x <= 0x7a) || (x >= 0x30 && x <= 0x39)) {
 207                     if (!wasChar) {
 208                         debug.log(sb + "");
 209                         sb.setLength(0);
 210                     }
 211                     sb.append(String.format("%c", x));
 212                     wasChar = true;
 213                 } else {
 214                     wasChar = false;
 215                 }
 216             }
 217             debug.log(sb + "");
 218         }
 219     }
 220 }
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FinalizableSubclassTest.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File