001/* 002 * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package jdk.internal.jvmci.hotspot; 024 025import static jdk.internal.jvmci.common.UnsafeAccess.*; 026import static jdk.internal.jvmci.hotspot.HotSpotResolvedJavaType.*; 027import static jdk.internal.jvmci.hotspot.HotSpotResolvedObjectTypeImpl.*; 028 029import java.lang.reflect.*; 030 031import jdk.internal.jvmci.code.*; 032import jdk.internal.jvmci.common.*; 033import jdk.internal.jvmci.meta.*; 034 035// JaCoCo Exclude 036 037/** 038 * HotSpot implementation of {@link MetaAccessProvider}. 039 */ 040public class HotSpotMetaAccessProvider implements MetaAccessProvider, HotSpotProxified { 041 042 protected final HotSpotJVMCIRuntimeProvider runtime; 043 044 public HotSpotMetaAccessProvider(HotSpotJVMCIRuntimeProvider runtime) { 045 this.runtime = runtime; 046 } 047 048 public ResolvedJavaType lookupJavaType(Class<?> clazz) { 049 if (clazz == null) { 050 throw new IllegalArgumentException("Class parameter was null"); 051 } 052 return runtime.fromClass(clazz); 053 } 054 055 public HotSpotResolvedObjectType lookupJavaType(JavaConstant constant) { 056 if (constant.isNull() || !(constant instanceof HotSpotObjectConstant)) { 057 return null; 058 } 059 return ((HotSpotObjectConstant) constant).getType(); 060 } 061 062 public Signature parseMethodDescriptor(String signature) { 063 return new HotSpotSignature(runtime, signature); 064 } 065 066 /** 067 * {@link Field} object of {@link Method#slot}. 068 */ 069 @SuppressWarnings("javadoc") private Field reflectionMethodSlot = getReflectionSlotField(Method.class); 070 071 /** 072 * {@link Field} object of {@link Constructor#slot}. 073 */ 074 @SuppressWarnings("javadoc") private Field reflectionConstructorSlot = getReflectionSlotField(Constructor.class); 075 076 private static Field getReflectionSlotField(Class<?> reflectionClass) { 077 try { 078 Field field = reflectionClass.getDeclaredField("slot"); 079 field.setAccessible(true); 080 return field; 081 } catch (NoSuchFieldException | SecurityException e) { 082 throw new JVMCIError(e); 083 } 084 } 085 086 public ResolvedJavaMethod lookupJavaMethod(Executable reflectionMethod) { 087 try { 088 Class<?> holder = reflectionMethod.getDeclaringClass(); 089 Field slotField = reflectionMethod instanceof Constructor ? reflectionConstructorSlot : reflectionMethodSlot; 090 final int slot = slotField.getInt(reflectionMethod); 091 final long metaspaceMethod = runtime.getCompilerToVM().getMetaspaceMethod(holder, slot); 092 return HotSpotResolvedJavaMethodImpl.fromMetaspace(metaspaceMethod); 093 } catch (IllegalArgumentException | IllegalAccessException e) { 094 throw new JVMCIError(e); 095 } 096 } 097 098 public ResolvedJavaField lookupJavaField(Field reflectionField) { 099 String name = reflectionField.getName(); 100 Class<?> fieldHolder = reflectionField.getDeclaringClass(); 101 Class<?> fieldType = reflectionField.getType(); 102 // java.lang.reflect.Field's modifiers should be enough here since VM internal modifier bits 103 // are not used (yet). 104 final int modifiers = reflectionField.getModifiers(); 105 final long offset = Modifier.isStatic(modifiers) ? unsafe.staticFieldOffset(reflectionField) : unsafe.objectFieldOffset(reflectionField); 106 107 HotSpotResolvedObjectType holder = fromObjectClass(fieldHolder); 108 JavaType type = fromClass(fieldType); 109 110 if (offset != -1) { 111 HotSpotResolvedObjectType resolved = holder; 112 return resolved.createField(name, type, offset, modifiers); 113 } else { 114 throw new JVMCIError("unresolved field %s", reflectionField); 115 } 116 } 117 118 private static int intMaskRight(int n) { 119 assert n <= 32; 120 return n == 32 ? -1 : (1 << n) - 1; 121 } 122 123 @Override 124 public JavaConstant encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason, int debugId) { 125 HotSpotVMConfig config = runtime.getConfig(); 126 int actionValue = convertDeoptAction(action); 127 int reasonValue = convertDeoptReason(reason); 128 int debugValue = debugId & intMaskRight(config.deoptimizationDebugIdBits); 129 JavaConstant c = JavaConstant.forInt(~((debugValue << config.deoptimizationDebugIdShift) | (reasonValue << config.deoptimizationReasonShift) | (actionValue << config.deoptimizationActionShift))); 130 assert c.asInt() < 0; 131 return c; 132 } 133 134 public DeoptimizationReason decodeDeoptReason(JavaConstant constant) { 135 HotSpotVMConfig config = runtime.getConfig(); 136 int reasonValue = ((~constant.asInt()) >> config.deoptimizationReasonShift) & intMaskRight(config.deoptimizationReasonBits); 137 DeoptimizationReason reason = convertDeoptReason(reasonValue); 138 return reason; 139 } 140 141 public DeoptimizationAction decodeDeoptAction(JavaConstant constant) { 142 HotSpotVMConfig config = runtime.getConfig(); 143 int actionValue = ((~constant.asInt()) >> config.deoptimizationActionShift) & intMaskRight(config.deoptimizationActionBits); 144 DeoptimizationAction action = convertDeoptAction(actionValue); 145 return action; 146 } 147 148 public int decodeDebugId(JavaConstant constant) { 149 HotSpotVMConfig config = runtime.getConfig(); 150 return ((~constant.asInt()) >> config.deoptimizationDebugIdShift) & intMaskRight(config.deoptimizationDebugIdBits); 151 } 152 153 public int convertDeoptAction(DeoptimizationAction action) { 154 HotSpotVMConfig config = runtime.getConfig(); 155 switch (action) { 156 case None: 157 return config.deoptActionNone; 158 case RecompileIfTooManyDeopts: 159 return config.deoptActionMaybeRecompile; 160 case InvalidateReprofile: 161 return config.deoptActionReinterpret; 162 case InvalidateRecompile: 163 return config.deoptActionMakeNotEntrant; 164 case InvalidateStopCompiling: 165 return config.deoptActionMakeNotCompilable; 166 default: 167 throw new JVMCIError("%s", action); 168 } 169 } 170 171 public DeoptimizationAction convertDeoptAction(int action) { 172 HotSpotVMConfig config = runtime.getConfig(); 173 if (action == config.deoptActionNone) { 174 return DeoptimizationAction.None; 175 } 176 if (action == config.deoptActionMaybeRecompile) { 177 return DeoptimizationAction.RecompileIfTooManyDeopts; 178 } 179 if (action == config.deoptActionReinterpret) { 180 return DeoptimizationAction.InvalidateReprofile; 181 } 182 if (action == config.deoptActionMakeNotEntrant) { 183 return DeoptimizationAction.InvalidateRecompile; 184 } 185 if (action == config.deoptActionMakeNotCompilable) { 186 return DeoptimizationAction.InvalidateStopCompiling; 187 } 188 throw new JVMCIError("%d", action); 189 } 190 191 public int convertDeoptReason(DeoptimizationReason reason) { 192 HotSpotVMConfig config = runtime.getConfig(); 193 switch (reason) { 194 case None: 195 return config.deoptReasonNone; 196 case NullCheckException: 197 return config.deoptReasonNullCheck; 198 case BoundsCheckException: 199 return config.deoptReasonRangeCheck; 200 case ClassCastException: 201 return config.deoptReasonClassCheck; 202 case ArrayStoreException: 203 return config.deoptReasonArrayCheck; 204 case UnreachedCode: 205 return config.deoptReasonUnreached0; 206 case TypeCheckedInliningViolated: 207 return config.deoptReasonTypeCheckInlining; 208 case OptimizedTypeCheckViolated: 209 return config.deoptReasonOptimizedTypeCheck; 210 case NotCompiledExceptionHandler: 211 return config.deoptReasonNotCompiledExceptionHandler; 212 case Unresolved: 213 return config.deoptReasonUnresolved; 214 case JavaSubroutineMismatch: 215 return config.deoptReasonJsrMismatch; 216 case ArithmeticException: 217 return config.deoptReasonDiv0Check; 218 case RuntimeConstraint: 219 return config.deoptReasonConstraint; 220 case LoopLimitCheck: 221 return config.deoptReasonLoopLimitCheck; 222 case Aliasing: 223 return config.deoptReasonAliasing; 224 case TransferToInterpreter: 225 return config.deoptReasonTransferToInterpreter; 226 default: 227 throw new JVMCIError("%s", reason); 228 } 229 } 230 231 public DeoptimizationReason convertDeoptReason(int reason) { 232 HotSpotVMConfig config = runtime.getConfig(); 233 if (reason == config.deoptReasonNone) { 234 return DeoptimizationReason.None; 235 } 236 if (reason == config.deoptReasonNullCheck) { 237 return DeoptimizationReason.NullCheckException; 238 } 239 if (reason == config.deoptReasonRangeCheck) { 240 return DeoptimizationReason.BoundsCheckException; 241 } 242 if (reason == config.deoptReasonClassCheck) { 243 return DeoptimizationReason.ClassCastException; 244 } 245 if (reason == config.deoptReasonArrayCheck) { 246 return DeoptimizationReason.ArrayStoreException; 247 } 248 if (reason == config.deoptReasonUnreached0) { 249 return DeoptimizationReason.UnreachedCode; 250 } 251 if (reason == config.deoptReasonTypeCheckInlining) { 252 return DeoptimizationReason.TypeCheckedInliningViolated; 253 } 254 if (reason == config.deoptReasonOptimizedTypeCheck) { 255 return DeoptimizationReason.OptimizedTypeCheckViolated; 256 } 257 if (reason == config.deoptReasonNotCompiledExceptionHandler) { 258 return DeoptimizationReason.NotCompiledExceptionHandler; 259 } 260 if (reason == config.deoptReasonUnresolved) { 261 return DeoptimizationReason.Unresolved; 262 } 263 if (reason == config.deoptReasonJsrMismatch) { 264 return DeoptimizationReason.JavaSubroutineMismatch; 265 } 266 if (reason == config.deoptReasonDiv0Check) { 267 return DeoptimizationReason.ArithmeticException; 268 } 269 if (reason == config.deoptReasonConstraint) { 270 return DeoptimizationReason.RuntimeConstraint; 271 } 272 if (reason == config.deoptReasonLoopLimitCheck) { 273 return DeoptimizationReason.LoopLimitCheck; 274 } 275 if (reason == config.deoptReasonAliasing) { 276 return DeoptimizationReason.Aliasing; 277 } 278 if (reason == config.deoptReasonTransferToInterpreter) { 279 return DeoptimizationReason.TransferToInterpreter; 280 } 281 throw new JVMCIError("%x", reason); 282 } 283 284 @Override 285 public long getMemorySize(JavaConstant constant) { 286 if (constant.getKind() == Kind.Object) { 287 HotSpotResolvedObjectType lookupJavaType = lookupJavaType(constant); 288 289 if (lookupJavaType == null) { 290 return 0; 291 } else { 292 if (lookupJavaType.isArray()) { 293 // TODO(tw): Add compressed pointer support. 294 int length = Array.getLength(((HotSpotObjectConstantImpl) constant).object()); 295 ResolvedJavaType elementType = lookupJavaType.getComponentType(); 296 Kind elementKind = elementType.getKind(); 297 final int headerSize = runtime.getArrayBaseOffset(elementKind); 298 TargetDescription target = runtime.getHostJVMCIBackend().getTarget(); 299 int sizeOfElement = target.getSizeInBytes(elementKind); 300 int alignment = target.wordSize; 301 int log2ElementSize = CodeUtil.log2(sizeOfElement); 302 return computeArrayAllocationSize(length, alignment, headerSize, log2ElementSize); 303 } 304 return lookupJavaType.instanceSize(); 305 } 306 } else { 307 return constant.getKind().getByteCount(); 308 } 309 } 310 311 /** 312 * Computes the size of the memory chunk allocated for an array. This size accounts for the 313 * array header size, body size and any padding after the last element to satisfy object 314 * alignment requirements. 315 * 316 * @param length the number of elements in the array 317 * @param alignment the object alignment requirement 318 * @param headerSize the size of the array header 319 * @param log2ElementSize log2 of the size of an element in the array 320 */ 321 public static int computeArrayAllocationSize(int length, int alignment, int headerSize, int log2ElementSize) { 322 int size = (length << log2ElementSize) + headerSize + (alignment - 1); 323 int mask = ~(alignment - 1); 324 return size & mask; 325 } 326}