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 package jdk.vm.ci.hotspot; 24 25 import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime; 26 import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE; 27 28 import jdk.vm.ci.meta.Constant; 29 import jdk.vm.ci.meta.JavaConstant; 30 import jdk.vm.ci.meta.JavaKind; 31 import jdk.vm.ci.meta.MemoryAccessProvider; 32 import jdk.vm.ci.meta.PrimitiveConstant; 33 34 /** 35 * HotSpot implementation of {@link MemoryAccessProvider}. 36 */ 37 class HotSpotMemoryAccessProviderImpl implements HotSpotMemoryAccessProvider { 38 39 protected final HotSpotJVMCIRuntime runtime; 40 HotSpotMemoryAccessProviderImpl(HotSpotJVMCIRuntime runtime)41 HotSpotMemoryAccessProviderImpl(HotSpotJVMCIRuntime runtime) { 42 this.runtime = runtime; 43 } 44 asRawPointer(Constant base)45 private static long asRawPointer(Constant base) { 46 if (base instanceof HotSpotMetaspaceConstantImpl) { 47 MetaspaceObject meta = HotSpotMetaspaceConstantImpl.getMetaspaceObject(base); 48 return meta.getMetaspacePointer(); 49 } else if (base instanceof PrimitiveConstant) { 50 PrimitiveConstant prim = (PrimitiveConstant) base; 51 if (prim.getJavaKind().isNumericInteger()) { 52 return prim.asLong(); 53 } 54 } 55 throw new IllegalArgumentException(String.valueOf(base)); 56 } 57 58 @Override readPrimitiveConstant(JavaKind kind, Constant baseConstant, long initialDisplacement, int bits)59 public JavaConstant readPrimitiveConstant(JavaKind kind, Constant baseConstant, long initialDisplacement, int bits) { 60 if (baseConstant instanceof HotSpotObjectConstantImpl) { 61 JavaKind readKind = kind; 62 if (kind.getBitCount() != bits) { 63 switch (bits) { 64 case Byte.SIZE: 65 readKind = JavaKind.Byte; 66 break; 67 case Short.SIZE: 68 readKind = JavaKind.Short; 69 break; 70 case Integer.SIZE: 71 readKind = JavaKind.Int; 72 break; 73 case Long.SIZE: 74 readKind = JavaKind.Long; 75 break; 76 default: 77 throw new IllegalArgumentException(String.valueOf(bits)); 78 } 79 } 80 JavaConstant result = runtime().compilerToVm.readFieldValue((HotSpotObjectConstantImpl) baseConstant, null, initialDisplacement, true, readKind); 81 if (result != null && kind != readKind) { 82 return JavaConstant.forPrimitive(kind, result.asLong()); 83 } 84 return result; 85 } else { 86 long pointer = asRawPointer(baseConstant); 87 long value; 88 switch (bits) { 89 case Byte.SIZE: 90 value = UNSAFE.getByte(pointer + initialDisplacement); 91 break; 92 case Short.SIZE: 93 value = UNSAFE.getShort(pointer + initialDisplacement); 94 break; 95 case Integer.SIZE: 96 value = UNSAFE.getInt(pointer + initialDisplacement); 97 break; 98 case Long.SIZE: 99 value = UNSAFE.getLong(pointer + initialDisplacement); 100 break; 101 default: 102 throw new IllegalArgumentException(String.valueOf(bits)); 103 } 104 return JavaConstant.forPrimitive(kind, value); 105 } 106 } 107 108 @Override readObjectConstant(Constant base, long displacement)109 public JavaConstant readObjectConstant(Constant base, long displacement) { 110 if (base instanceof HotSpotObjectConstantImpl) { 111 return runtime.getCompilerToVM().readFieldValue((HotSpotObjectConstantImpl) base, null, displacement, true, JavaKind.Object); 112 } 113 if (base instanceof HotSpotMetaspaceConstant) { 114 MetaspaceObject metaspaceObject = HotSpotMetaspaceConstantImpl.getMetaspaceObject(base); 115 if (metaspaceObject instanceof HotSpotResolvedObjectTypeImpl) { 116 HotSpotResolvedObjectTypeImpl type = (HotSpotResolvedObjectTypeImpl) metaspaceObject; 117 if (displacement == runtime.getConfig().javaMirrorOffset) { 118 // Klass::_java_mirror is valid for all Klass* values 119 return type.getJavaMirror(); 120 } 121 return null; 122 } else { 123 throw new IllegalArgumentException(String.valueOf(metaspaceObject)); 124 } 125 } 126 return null; 127 } 128 129 @Override readNarrowOopConstant(Constant base, long displacement)130 public JavaConstant readNarrowOopConstant(Constant base, long displacement) { 131 if (base instanceof HotSpotObjectConstantImpl) { 132 assert runtime.getConfig().useCompressedOops; 133 JavaConstant res = runtime.getCompilerToVM().readFieldValue((HotSpotObjectConstantImpl) base, null, displacement, true, JavaKind.Object); 134 if (res != null) { 135 return JavaConstant.NULL_POINTER.equals(res) ? HotSpotCompressedNullConstant.COMPRESSED_NULL : ((HotSpotObjectConstant) res).compress(); 136 } 137 } 138 return null; 139 } 140 readKlass(Constant base, long displacement, boolean compressed)141 private HotSpotResolvedObjectTypeImpl readKlass(Constant base, long displacement, boolean compressed) { 142 assert (base instanceof HotSpotMetaspaceConstantImpl) || (base instanceof HotSpotObjectConstantImpl) : base.getClass(); 143 if (base instanceof HotSpotMetaspaceConstantImpl) { 144 return runtime.getCompilerToVM().getResolvedJavaType((HotSpotResolvedObjectTypeImpl) ((HotSpotMetaspaceConstantImpl) base).asResolvedJavaType(), displacement, compressed); 145 } else { 146 return runtime.getCompilerToVM().getResolvedJavaType(((HotSpotObjectConstantImpl) base), displacement, compressed); 147 } 148 } 149 150 151 @Override readKlassPointerConstant(Constant base, long displacement)152 public Constant readKlassPointerConstant(Constant base, long displacement) { 153 HotSpotResolvedObjectTypeImpl klass = readKlass(base, displacement, false); 154 if (klass == null) { 155 return JavaConstant.NULL_POINTER; 156 } 157 return HotSpotMetaspaceConstantImpl.forMetaspaceObject(klass, false); 158 } 159 160 @Override readNarrowKlassPointerConstant(Constant base, long displacement)161 public Constant readNarrowKlassPointerConstant(Constant base, long displacement) { 162 HotSpotResolvedObjectTypeImpl klass = readKlass(base, displacement, true); 163 if (klass == null) { 164 return HotSpotCompressedNullConstant.COMPRESSED_NULL; 165 } 166 return HotSpotMetaspaceConstantImpl.forMetaspaceObject(klass, true); 167 } 168 169 @Override readMethodPointerConstant(Constant base, long displacement)170 public Constant readMethodPointerConstant(Constant base, long displacement) { 171 assert (base instanceof HotSpotObjectConstantImpl); 172 HotSpotResolvedJavaMethodImpl method = runtime.getCompilerToVM().getResolvedJavaMethod((HotSpotObjectConstantImpl) base, displacement); 173 return HotSpotMetaspaceConstantImpl.forMetaspaceObject(method, false); 174 } 175 } 176