1 /* 2 * Copyright (c) 2011, 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 package jdk.vm.ci.hotspot; 24 25 import static jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl.*; 26 import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE; 27 28 import java.lang.reflect.*; 29 30 import jdk.vm.ci.code.*; 31 import jdk.vm.ci.common.*; 32 import jdk.vm.ci.meta.*; 33 34 // JaCoCo Exclude 35 36 /** 37 * HotSpot implementation of {@link MetaAccessProvider}. 38 */ 39 public class HotSpotMetaAccessProvider implements MetaAccessProvider, HotSpotProxified { 40 41 protected final HotSpotJVMCIRuntimeProvider runtime; 42 43 public HotSpotMetaAccessProvider(HotSpotJVMCIRuntimeProvider runtime) { 44 this.runtime = runtime; 45 } 46 47 public ResolvedJavaType lookupJavaType(Class<?> clazz) { 48 if (clazz == null) { 49 throw new IllegalArgumentException("Class parameter was null"); 50 } 51 return runtime.fromClass(clazz); 52 } 53 54 public HotSpotResolvedObjectType lookupJavaType(JavaConstant constant) { 55 if (constant.isNull() || !(constant instanceof HotSpotObjectConstant)) { 56 return null; 57 } 58 return ((HotSpotObjectConstant) constant).getType(); 59 } 60 61 public Signature parseMethodDescriptor(String signature) { 62 return new HotSpotSignature(runtime, signature); 63 } 64 65 /** 66 * {@link Field} object of {@link Method#slot}. 67 */ 68 private Field reflectionMethodSlot = getReflectionSlotField(Method.class); 69 70 /** 71 * {@link Field} object of {@link Constructor#slot}. 72 */ 73 private Field reflectionConstructorSlot = getReflectionSlotField(Constructor.class); 74 75 private static Field getReflectionSlotField(Class<?> reflectionClass) { 76 try { 77 Field field = reflectionClass.getDeclaredField("slot"); 78 field.setAccessible(true); 79 return field; 80 } catch (NoSuchFieldException | SecurityException e) { 81 throw new JVMCIError(e); 82 } 83 } 84 85 public ResolvedJavaMethod lookupJavaMethod(Executable reflectionMethod) { 86 try { 87 Class<?> holder = reflectionMethod.getDeclaringClass(); 88 Field slotField = reflectionMethod instanceof Constructor ? reflectionConstructorSlot : reflectionMethodSlot; 89 final int slot = slotField.getInt(reflectionMethod); 90 return runtime.getCompilerToVM().getResolvedJavaMethodAtSlot(holder, slot); 91 } catch (IllegalArgumentException | IllegalAccessException e) { 92 throw new JVMCIError(e); 93 } 94 } 95 96 public ResolvedJavaField lookupJavaField(Field reflectionField) { 97 String name = reflectionField.getName(); 98 Class<?> fieldHolder = reflectionField.getDeclaringClass(); 99 Class<?> fieldType = reflectionField.getType(); 100 // java.lang.reflect.Field's modifiers should be enough here since VM internal modifier bits 101 // are not used (yet). 102 final int modifiers = reflectionField.getModifiers(); 103 final long offset = Modifier.isStatic(modifiers) ? UNSAFE.staticFieldOffset(reflectionField) : UNSAFE.objectFieldOffset(reflectionField); 104 105 HotSpotResolvedObjectType holder = fromObjectClass(fieldHolder); 106 JavaType type = runtime.fromClass(fieldType); 107 108 if (offset != -1) { 109 HotSpotResolvedObjectType resolved = holder; 110 return resolved.createField(name, type, offset, modifiers); 111 } else { 112 throw new JVMCIError("unresolved field %s", reflectionField); 113 } 114 } 115 116 private static int intMaskRight(int n) { 117 assert n <= 32; 118 return n == 32 ? -1 : (1 << n) - 1; 119 } 120 121 @Override 122 public JavaConstant encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason, int debugId) { 123 HotSpotVMConfig config = runtime.getConfig(); 124 int actionValue = convertDeoptAction(action); 125 int reasonValue = convertDeoptReason(reason); 126 int debugValue = debugId & intMaskRight(config.deoptimizationDebugIdBits); 127 JavaConstant c = JavaConstant.forInt(~((debugValue << config.deoptimizationDebugIdShift) | (reasonValue << config.deoptimizationReasonShift) | (actionValue << config.deoptimizationActionShift))); 128 assert c.asInt() < 0; 129 return c; 130 } 131 132 public DeoptimizationReason decodeDeoptReason(JavaConstant constant) { 133 HotSpotVMConfig config = runtime.getConfig(); 134 int reasonValue = ((~constant.asInt()) >> config.deoptimizationReasonShift) & intMaskRight(config.deoptimizationReasonBits); 135 DeoptimizationReason reason = convertDeoptReason(reasonValue); 136 return reason; 137 } 138 139 public DeoptimizationAction decodeDeoptAction(JavaConstant constant) { 140 HotSpotVMConfig config = runtime.getConfig(); 141 int actionValue = ((~constant.asInt()) >> config.deoptimizationActionShift) & intMaskRight(config.deoptimizationActionBits); 142 DeoptimizationAction action = convertDeoptAction(actionValue); 143 return action; 144 } 145 146 public int decodeDebugId(JavaConstant constant) { 147 HotSpotVMConfig config = runtime.getConfig(); 148 return ((~constant.asInt()) >> config.deoptimizationDebugIdShift) & intMaskRight(config.deoptimizationDebugIdBits); 149 } 150 151 public int convertDeoptAction(DeoptimizationAction action) { 152 HotSpotVMConfig config = runtime.getConfig(); 153 switch (action) { 154 case None: 155 return config.deoptActionNone; 156 case RecompileIfTooManyDeopts: 157 return config.deoptActionMaybeRecompile; 158 case InvalidateReprofile: 159 return config.deoptActionReinterpret; 160 case InvalidateRecompile: 161 return config.deoptActionMakeNotEntrant; 162 case InvalidateStopCompiling: 163 return config.deoptActionMakeNotCompilable; 164 default: 165 throw new JVMCIError("%s", action); 166 } 167 } 168 169 public DeoptimizationAction convertDeoptAction(int action) { 170 HotSpotVMConfig config = runtime.getConfig(); 171 if (action == config.deoptActionNone) { 172 return DeoptimizationAction.None; 173 } 174 if (action == config.deoptActionMaybeRecompile) { 175 return DeoptimizationAction.RecompileIfTooManyDeopts; 176 } 177 if (action == config.deoptActionReinterpret) { 178 return DeoptimizationAction.InvalidateReprofile; 179 } 180 if (action == config.deoptActionMakeNotEntrant) { 181 return DeoptimizationAction.InvalidateRecompile; 182 } 183 if (action == config.deoptActionMakeNotCompilable) { 184 return DeoptimizationAction.InvalidateStopCompiling; 185 } 186 throw new JVMCIError("%d", action); 187 } 188 189 public int convertDeoptReason(DeoptimizationReason reason) { 190 HotSpotVMConfig config = runtime.getConfig(); 191 switch (reason) { 192 case None: 193 return config.deoptReasonNone; 194 case NullCheckException: 195 return config.deoptReasonNullCheck; 196 case BoundsCheckException: 197 return config.deoptReasonRangeCheck; 198 case ClassCastException: 199 return config.deoptReasonClassCheck; 200 case ArrayStoreException: 201 return config.deoptReasonArrayCheck; 202 case UnreachedCode: 203 return config.deoptReasonUnreached0; 204 case TypeCheckedInliningViolated: 205 return config.deoptReasonTypeCheckInlining; 206 case OptimizedTypeCheckViolated: 207 return config.deoptReasonOptimizedTypeCheck; 208 case NotCompiledExceptionHandler: 209 return config.deoptReasonNotCompiledExceptionHandler; 210 case Unresolved: 211 return config.deoptReasonUnresolved; 212 case JavaSubroutineMismatch: 213 return config.deoptReasonJsrMismatch; 214 case ArithmeticException: 215 return config.deoptReasonDiv0Check; 216 case RuntimeConstraint: 217 return config.deoptReasonConstraint; 218 case LoopLimitCheck: 219 return config.deoptReasonLoopLimitCheck; 220 case Aliasing: 221 return config.deoptReasonAliasing; 222 case TransferToInterpreter: 223 return config.deoptReasonTransferToInterpreter; 224 default: 225 throw new JVMCIError("%s", reason); 226 } 227 } 228 229 public DeoptimizationReason convertDeoptReason(int reason) { 230 HotSpotVMConfig config = runtime.getConfig(); 231 if (reason == config.deoptReasonNone) { 232 return DeoptimizationReason.None; 233 } 234 if (reason == config.deoptReasonNullCheck) { 235 return DeoptimizationReason.NullCheckException; 236 } 237 if (reason == config.deoptReasonRangeCheck) { 238 return DeoptimizationReason.BoundsCheckException; 239 } 240 if (reason == config.deoptReasonClassCheck) { 241 return DeoptimizationReason.ClassCastException; 242 } 243 if (reason == config.deoptReasonArrayCheck) { 244 return DeoptimizationReason.ArrayStoreException; 245 } 246 if (reason == config.deoptReasonUnreached0) { 247 return DeoptimizationReason.UnreachedCode; 248 } 249 if (reason == config.deoptReasonTypeCheckInlining) { 250 return DeoptimizationReason.TypeCheckedInliningViolated; 251 } 252 if (reason == config.deoptReasonOptimizedTypeCheck) { 253 return DeoptimizationReason.OptimizedTypeCheckViolated; 254 } 255 if (reason == config.deoptReasonNotCompiledExceptionHandler) { 256 return DeoptimizationReason.NotCompiledExceptionHandler; 257 } 258 if (reason == config.deoptReasonUnresolved) { 259 return DeoptimizationReason.Unresolved; 260 } 261 if (reason == config.deoptReasonJsrMismatch) { 262 return DeoptimizationReason.JavaSubroutineMismatch; 263 } 264 if (reason == config.deoptReasonDiv0Check) { 265 return DeoptimizationReason.ArithmeticException; 266 } 267 if (reason == config.deoptReasonConstraint) { 268 return DeoptimizationReason.RuntimeConstraint; 269 } 270 if (reason == config.deoptReasonLoopLimitCheck) { 271 return DeoptimizationReason.LoopLimitCheck; 272 } 273 if (reason == config.deoptReasonAliasing) { 274 return DeoptimizationReason.Aliasing; 275 } 276 if (reason == config.deoptReasonTransferToInterpreter) { 277 return DeoptimizationReason.TransferToInterpreter; 278 } 279 throw new JVMCIError("%x", reason); 280 } 281 282 @Override 283 public long getMemorySize(JavaConstant constant) { 284 if (constant.getJavaKind() == JavaKind.Object) { 285 HotSpotResolvedObjectType lookupJavaType = lookupJavaType(constant); 286 287 if (lookupJavaType == null) { 288 return 0; 289 } else { 290 if (lookupJavaType.isArray()) { 291 // TODO(tw): Add compressed pointer support. 292 int length = Array.getLength(((HotSpotObjectConstantImpl) constant).object()); 293 ResolvedJavaType elementType = lookupJavaType.getComponentType(); 294 JavaKind elementKind = elementType.getJavaKind(); 295 final int headerSize = runtime.getArrayBaseOffset(elementKind); 296 TargetDescription target = runtime.getHostJVMCIBackend().getTarget(); 297 int sizeOfElement = target.getSizeInBytes(elementKind); 298 int alignment = target.wordSize; 299 int log2ElementSize = CodeUtil.log2(sizeOfElement); 300 return computeArrayAllocationSize(length, alignment, headerSize, log2ElementSize); 301 } 302 return lookupJavaType.instanceSize(); 303 } 304 } else { 305 return constant.getJavaKind().getByteCount(); 306 } 307 } 308 309 /** 310 * Computes the size of the memory chunk allocated for an array. This size accounts for the 311 * array header size, body size and any padding after the last element to satisfy object 312 * alignment requirements. 313 * 314 * @param length the number of elements in the array 315 * @param alignment the object alignment requirement 316 * @param headerSize the size of the array header 317 * @param log2ElementSize log2 of the size of an element in the array 318 */ 319 public static int computeArrayAllocationSize(int length, int alignment, int headerSize, int log2ElementSize) { 320 int size = (length << log2ElementSize) + headerSize + (alignment - 1); 321 int mask = ~(alignment - 1); 322 return size & mask; 323 } 324 }