1 /*
   2  * Copyright (c) 2015, 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 /*
  26  * @test
  27  * @bug 8136421
  28  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
  29  * @library /testlibrary /../../test/lib /
  30  * @compile ../common/CompilerToVMHelper.java
  31  * @build sun.hotspot.WhiteBox
  32  *        compiler.jvmci.compilerToVM.GetConstantPoolTest
  33  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  34  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
  35  *                              jdk.vm.ci.hotspot.CompilerToVMHelper
  36  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  37  *                   -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions
  38  *                   -XX:+EnableJVMCI compiler.jvmci.compilerToVM.GetConstantPoolTest
  39  */
  40 package compiler.jvmci.compilerToVM;
  41 
  42 import java.lang.reflect.Field;
  43 import jdk.vm.ci.hotspot.CompilerToVMHelper;
  44 import jdk.vm.ci.hotspot.HotSpotConstantPool;
  45 import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
  46 import jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl;
  47 import jdk.vm.ci.hotspot.MetaspaceWrapperObject;
  48 import jdk.test.lib.Utils;
  49 import sun.hotspot.WhiteBox;
  50 import sun.misc.Unsafe;
  51 
  52 /**
  53  * Tests for jdk.vm.ci.hotspot.CompilerToVM::getConstantPool method
  54  */
  55 public class GetConstantPoolTest {
  56     private static enum TestCase {
  57         NULL_BASE {
  58             @Override
  59             HotSpotConstantPool getConstantPool() {
  60                 return CompilerToVMHelper.getConstantPool(null,
  61                         getPtrToCpAddress());
  62             }
  63         },
  64         JAVA_METHOD_BASE {
  65             @Override
  66             HotSpotConstantPool getConstantPool() {
  67                 HotSpotResolvedJavaMethodImpl methodInstance
  68                         = CompilerToVMHelper.getResolvedJavaMethodAtSlot(
  69                                 TEST_CLASS, 0);
  70                 Field field;
  71                 try {
  72                     field = HotSpotResolvedJavaMethodImpl
  73                             .class.getDeclaredField("metaspaceMethod");
  74                     field.setAccessible(true);
  75                     field.set(methodInstance, getPtrToCpAddress());
  76                 } catch (ReflectiveOperationException e) {
  77                     throw new Error("TESTBUG : " + e.getMessage(), e);
  78                 }
  79 
  80                 return CompilerToVMHelper.getConstantPool(methodInstance, 0L);
  81             }
  82         },
  83         CONSTANT_POOL_BASE {
  84             @Override
  85             HotSpotConstantPool getConstantPool() {
  86                 HotSpotConstantPool cpInst;
  87                 try {
  88                     cpInst = CompilerToVMHelper.getConstantPool(null,
  89                             getPtrToCpAddress());
  90                     Field field = HotSpotConstantPool.class
  91                             .getDeclaredField("metaspaceConstantPool");
  92                     field.setAccessible(true);
  93                     field.set(cpInst, getPtrToCpAddress());
  94                 } catch (ReflectiveOperationException e) {
  95                     throw new Error("TESTBUG : " + e.getMessage(), e);
  96                 }
  97                 return CompilerToVMHelper.getConstantPool(cpInst, 0L);
  98             }
  99         },
 100         CONSTANT_POOL_BASE_IN_TWO {
 101             @Override
 102             HotSpotConstantPool getConstantPool() {
 103                 long ptr = getPtrToCpAddress();
 104                 HotSpotConstantPool cpInst;
 105                 try {
 106                     cpInst = CompilerToVMHelper.getConstantPool(null, ptr);
 107                     Field field = HotSpotConstantPool.class
 108                             .getDeclaredField("metaspaceConstantPool");
 109                     field.setAccessible(true);
 110                     field.set(cpInst, ptr / 2L);
 111                 } catch (ReflectiveOperationException e) {
 112                     throw new Error("TESTBUG : " + e.getMessage(), e);
 113                 }
 114                 return CompilerToVMHelper.getConstantPool(cpInst,
 115                         ptr - ptr / 2L);
 116             }
 117         },
 118         CONSTANT_POOL_BASE_ZERO {
 119             @Override
 120             HotSpotConstantPool getConstantPool() {
 121                 long ptr = getPtrToCpAddress();
 122                 HotSpotConstantPool cpInst;
 123                 try {
 124                     cpInst = CompilerToVMHelper.getConstantPool(null, ptr);
 125                     Field field = HotSpotConstantPool.class
 126                             .getDeclaredField("metaspaceConstantPool");
 127                     field.setAccessible(true);
 128                     field.set(cpInst, 0L);
 129                 } catch (ReflectiveOperationException e) {
 130                     throw new Error("TESTBUG : " + e.getMessage(), e);
 131                 }
 132                 return CompilerToVMHelper.getConstantPool(cpInst, ptr);
 133             }
 134         },
 135         OBJECT_TYPE_BASE {
 136             @Override
 137             HotSpotConstantPool getConstantPool() {
 138                 HotSpotResolvedObjectTypeImpl type
 139                         = HotSpotResolvedObjectTypeImpl.fromObjectClass(
 140                                 OBJECT_TYPE_BASE.getClass());
 141                 long ptrToClass = UNSAFE.getKlassPointer(OBJECT_TYPE_BASE);
 142                 return CompilerToVMHelper.getConstantPool(type,
 143                         getPtrToCpAddress() - ptrToClass);
 144             }
 145         },
 146         ;
 147         abstract HotSpotConstantPool getConstantPool();
 148     }
 149 
 150     private static final WhiteBox WB = WhiteBox.getWhiteBox();
 151     private static final Unsafe UNSAFE = Utils.getUnsafe();
 152     private static final Class TEST_CLASS = GetConstantPoolTest.class;
 153     private static final long CP_ADDRESS
 154             = WB.getConstantPool(GetConstantPoolTest.class);
 155 
 156     public void test(TestCase testCase) {
 157         System.out.println(testCase.name());
 158         HotSpotConstantPool cp = testCase.getConstantPool();
 159         String cpStringRep = cp.toString();
 160         if (!cpStringRep.contains(HotSpotConstantPool.class.getSimpleName())
 161                 || !cpStringRep.contains(TEST_CLASS.getName())) {
 162             String msg = String.format("%s : "
 163                     + " Constant pool is not valid."
 164                     + " String representation should contain \"%s\" and \"%s\"",
 165                     testCase.name(),
 166                     HotSpotConstantPool.class.getSimpleName(),
 167                     TEST_CLASS.getName());
 168             throw new AssertionError(msg);
 169         }
 170     }
 171 
 172     public static void main(String[] args) {
 173         GetConstantPoolTest test = new GetConstantPoolTest();
 174         for (TestCase testCase : TestCase.values()) {
 175             test.test(testCase);
 176         }
 177         testObjectBase();
 178         testMetaspaceWrapperBase();
 179     }
 180 
 181     private static void testObjectBase() {
 182         try {
 183             HotSpotConstantPool cp
 184                     = CompilerToVMHelper.getConstantPool(new Object(), 0L);
 185             throw new AssertionError("Test OBJECT_BASE."
 186                 + " Expected IllegalArgumentException has not been caught");
 187         } catch (IllegalArgumentException iae) {
 188             // expected
 189         }
 190     }
 191     private static void testMetaspaceWrapperBase() {
 192         try {
 193             HotSpotConstantPool cp = CompilerToVMHelper.getConstantPool(
 194                     new MetaspaceWrapperObject() {
 195                         @Override
 196                         public long getMetaspacePointer() {
 197                             return getPtrToCpAddress();
 198                         }
 199                     }, 0L);
 200             throw new AssertionError("Test METASPACE_WRAPPER_BASE."
 201                 + " Expected IllegalArgumentException has not been caught");
 202         } catch (IllegalArgumentException iae) {
 203             // expected
 204         }
 205     }
 206 
 207     private static long getPtrToCpAddress() {
 208         Field field;
 209         try {
 210             field = TEST_CLASS.getDeclaredField("CP_ADDRESS");
 211         } catch (NoSuchFieldException nsfe) {
 212             throw new Error("TESTBUG : cannot find field \"CP_ADDRESS\" : "
 213                     + nsfe.getMessage(), nsfe);
 214         }
 215         Object base = UNSAFE.staticFieldBase(field);
 216         return WB.getObjectAddress(base) + UNSAFE.staticFieldOffset(field);
 217     }
 218 }