src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMemoryAccessProviderImpl.java
changeset 54669 ad45b3802d4e
parent 52220 9c260a6b6471
equal deleted inserted replaced
54668:0bda2308eded 54669:ad45b3802d4e
     1 /*
     1 /*
     2  * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
     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.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     7  * published by the Free Software Foundation.
    20  * or visit www.oracle.com if you need additional information or have any
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    21  * questions.
    22  */
    22  */
    23 package jdk.vm.ci.hotspot;
    23 package jdk.vm.ci.hotspot;
    24 
    24 
       
    25 import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
    25 import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
    26 import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
    26 
    27 
    27 import java.lang.reflect.Array;
       
    28 
       
    29 import jdk.vm.ci.common.JVMCIError;
       
    30 import jdk.vm.ci.meta.Constant;
    28 import jdk.vm.ci.meta.Constant;
    31 import jdk.vm.ci.meta.JavaConstant;
    29 import jdk.vm.ci.meta.JavaConstant;
    32 import jdk.vm.ci.meta.JavaKind;
    30 import jdk.vm.ci.meta.JavaKind;
    33 import jdk.vm.ci.meta.MemoryAccessProvider;
    31 import jdk.vm.ci.meta.MemoryAccessProvider;
    34 import jdk.vm.ci.meta.MetaAccessProvider;
       
    35 import jdk.vm.ci.meta.PrimitiveConstant;
    32 import jdk.vm.ci.meta.PrimitiveConstant;
    36 import jdk.vm.ci.meta.ResolvedJavaField;
       
    37 import jdk.vm.ci.meta.ResolvedJavaType;
       
    38 
    33 
    39 /**
    34 /**
    40  * HotSpot implementation of {@link MemoryAccessProvider}.
    35  * HotSpot implementation of {@link MemoryAccessProvider}.
    41  */
    36  */
    42 class HotSpotMemoryAccessProviderImpl implements HotSpotMemoryAccessProvider {
    37 class HotSpotMemoryAccessProviderImpl implements HotSpotMemoryAccessProvider {
    53      *
    48      *
    54      * @param base constant value containing the base address for a pending read
    49      * @param base constant value containing the base address for a pending read
    55      * @return {@code null} if {@code base} does not box an object otherwise the object boxed in
    50      * @return {@code null} if {@code base} does not box an object otherwise the object boxed in
    56      *         {@code base}
    51      *         {@code base}
    57      */
    52      */
    58     private Object asObject(Constant base, JavaKind kind, long displacement) {
    53     private static HotSpotObjectConstantImpl asObject(Constant base, JavaKind kind, long displacement) {
    59         if (base instanceof HotSpotObjectConstantImpl) {
    54         if (base instanceof HotSpotObjectConstantImpl) {
    60             HotSpotObjectConstantImpl constant = (HotSpotObjectConstantImpl) base;
    55             HotSpotObjectConstantImpl constant = (HotSpotObjectConstantImpl) base;
    61             HotSpotResolvedObjectType type = constant.getType();
    56             HotSpotResolvedObjectType type = constant.getType();
    62             Object object = constant.object();
    57             runtime().reflection.checkRead(constant, kind, displacement, type);
    63             checkRead(kind, displacement, type, object, runtime.getHostJVMCIBackend().getMetaAccess());
    58             return constant;
    64             return object;
       
    65         }
    59         }
    66         return null;
    60         return null;
    67     }
    61     }
    68 
    62 
    69     /**
    63     private boolean isValidObjectFieldDisplacement(Constant base, long displacement) {
    70      * Offset of injected {@code java.lang.Class::oop_size} field. No need to make {@code volatile}
    64         if (base instanceof HotSpotMetaspaceConstant) {
    71      * as initialization is idempotent.
    65             MetaspaceObject metaspaceObject = HotSpotMetaspaceConstantImpl.getMetaspaceObject(base);
    72      */
    66             if (metaspaceObject instanceof HotSpotResolvedObjectTypeImpl) {
    73     private long oopSizeOffset;
    67                 if (displacement == runtime.getConfig().javaMirrorOffset) {
    74 
    68                     // Klass::_java_mirror is valid for all Klass* values
    75     private static int computeOopSizeOffset(HotSpotJVMCIRuntime runtime) {
    69                     return true;
    76         MetaAccessProvider metaAccess = runtime.getHostJVMCIBackend().getMetaAccess();
       
    77         ResolvedJavaType staticType = metaAccess.lookupJavaType(Class.class);
       
    78         for (ResolvedJavaField f : staticType.getInstanceFields(false)) {
       
    79             if (f.getName().equals("oop_size")) {
       
    80                 int offset = ((HotSpotResolvedJavaField) f).getOffset();
       
    81                 assert offset != 0 : "not expecting offset of java.lang.Class::oop_size to be 0";
       
    82                 return offset;
       
    83             }
       
    84         }
       
    85         throw new JVMCIError("Could not find injected java.lang.Class::oop_size field");
       
    86     }
       
    87 
       
    88     private boolean checkRead(JavaKind kind, long displacement, HotSpotResolvedObjectType type, Object object, MetaAccessProvider metaAccess) {
       
    89         if (type.isArray()) {
       
    90             ResolvedJavaType componentType = type.getComponentType();
       
    91             JavaKind componentKind = componentType.getJavaKind();
       
    92             final int headerSize = metaAccess.getArrayBaseOffset(componentKind);
       
    93             int sizeOfElement = metaAccess.getArrayIndexScale(componentKind);
       
    94             int length = Array.getLength(object);
       
    95             long arrayEnd = headerSize + (sizeOfElement * length);
       
    96             boolean aligned = ((displacement - headerSize) % sizeOfElement) == 0;
       
    97             if (displacement < 0 || displacement > (arrayEnd - sizeOfElement) || (kind == JavaKind.Object && !aligned)) {
       
    98                 int index = (int) ((displacement - headerSize) / sizeOfElement);
       
    99                 throw new IllegalArgumentException("Unsafe array access: reading element of kind " + kind +
       
   100                                 " at offset " + displacement + " (index ~ " + index + ") in " +
       
   101                                 type.toJavaName() + " object of length " + length);
       
   102             }
       
   103         } else if (kind != JavaKind.Object) {
       
   104             long size;
       
   105             if (object instanceof Class) {
       
   106                 if (oopSizeOffset == 0) {
       
   107                     oopSizeOffset = computeOopSizeOffset(runtime);
       
   108                 }
    70                 }
   109                 int wordSize = runtime.getHostJVMCIBackend().getCodeCache().getTarget().wordSize;
       
   110                 size = UNSAFE.getInt(object, oopSizeOffset) * wordSize;
       
   111             } else {
    71             } else {
   112                 size = Math.abs(type.instanceSize());
    72                 throw new IllegalArgumentException(String.valueOf(metaspaceObject));
   113             }
    73             }
   114             int bytesToRead = kind.getByteCount();
    74         }
   115             if (displacement + bytesToRead > size || displacement < 0) {
    75         return false;
   116                 throw new IllegalArgumentException("Unsafe access: reading " + bytesToRead + " bytes at offset " + displacement + " in " +
       
   117                                 type.toJavaName() + " object of size " + size);
       
   118             }
       
   119         } else {
       
   120             ResolvedJavaField field = type.findInstanceFieldWithOffset(displacement, JavaKind.Object);
       
   121             if (field == null && object instanceof Class) {
       
   122                 // Read of a static field
       
   123                 HotSpotResolvedObjectTypeImpl staticFieldsHolder = (HotSpotResolvedObjectTypeImpl) metaAccess.lookupJavaType((Class<?>) object);
       
   124                 field = staticFieldsHolder.findStaticFieldWithOffset(displacement, JavaKind.Object);
       
   125             }
       
   126             if (field == null) {
       
   127                 throw new IllegalArgumentException("Unsafe object access: field not found for read of kind Object" +
       
   128                                 " at offset " + displacement + " in " + type.toJavaName() + " object");
       
   129             }
       
   130             if (field.getJavaKind() != JavaKind.Object) {
       
   131                 throw new IllegalArgumentException("Unsafe object access: field " + field.format("%H.%n:%T") + " not of expected kind Object" +
       
   132                                 " at offset " + displacement + " in " + type.toJavaName() + " object");
       
   133             }
       
   134         }
       
   135         return true;
       
   136     }
    76     }
   137 
    77 
   138     private static long asRawPointer(Constant base) {
    78     private static long asRawPointer(Constant base) {
   139         if (base instanceof HotSpotMetaspaceConstantImpl) {
    79         if (base instanceof HotSpotMetaspaceConstantImpl) {
   140             MetaspaceWrapperObject meta = HotSpotMetaspaceConstantImpl.getMetaspaceObject(base);
    80             MetaspaceObject meta = HotSpotMetaspaceConstantImpl.getMetaspaceObject(base);
   141             return meta.getMetaspacePointer();
    81             return meta.getMetaspacePointer();
   142         } else if (base instanceof PrimitiveConstant) {
    82         } else if (base instanceof PrimitiveConstant) {
   143             PrimitiveConstant prim = (PrimitiveConstant) base;
    83             PrimitiveConstant prim = (PrimitiveConstant) base;
   144             if (prim.getJavaKind().isNumericInteger()) {
    84             if (prim.getJavaKind().isNumericInteger()) {
   145                 return prim.asLong();
    85                 return prim.asLong();
   146             }
    86             }
   147         }
    87         }
   148         throw new IllegalArgumentException(String.valueOf(base));
    88         throw new IllegalArgumentException(String.valueOf(base));
   149     }
    89     }
   150 
    90 
   151     private long readRawValue(Constant baseConstant, long displacement, JavaKind kind, int bits) {
    91     private static long readRawValue(Constant baseConstant, long displacement, JavaKind kind, int bits) {
   152         Object base = asObject(baseConstant, kind, displacement);
    92         HotSpotObjectConstantImpl base = asObject(baseConstant, kind, displacement);
   153         if (base != null) {
    93         if (base != null) {
   154             switch (bits) {
    94             switch (bits) {
   155                 case Byte.SIZE:
    95                 case Byte.SIZE:
   156                     return UNSAFE.getByte(base, displacement);
    96                     return runtime().reflection.getByte(base, displacement);
   157                 case Short.SIZE:
    97                 case Short.SIZE:
   158                     return UNSAFE.getShort(base, displacement);
    98                     return runtime().reflection.getShort(base, displacement);
   159                 case Integer.SIZE:
    99                 case Integer.SIZE:
   160                     return UNSAFE.getInt(base, displacement);
   100                     return runtime().reflection.getInt(base, displacement);
   161                 case Long.SIZE:
   101                 case Long.SIZE:
   162                     return UNSAFE.getLong(base, displacement);
   102                     return runtime().reflection.getLong(base, displacement);
   163                 default:
   103                 default:
   164                     throw new IllegalArgumentException(String.valueOf(bits));
   104                     throw new IllegalArgumentException(String.valueOf(bits));
   165             }
   105             }
   166         } else {
   106         } else {
   167             long pointer = asRawPointer(baseConstant);
   107             long pointer = asRawPointer(baseConstant);
   178                     throw new IllegalArgumentException(String.valueOf(bits));
   118                     throw new IllegalArgumentException(String.valueOf(bits));
   179             }
   119             }
   180         }
   120         }
   181     }
   121     }
   182 
   122 
   183     private boolean verifyReadRawObject(Object expected, Constant base, long displacement) {
   123     private boolean verifyReadRawObject(JavaConstant expected, Constant base, long displacement) {
   184         if (base instanceof HotSpotMetaspaceConstant) {
   124         if (base instanceof HotSpotMetaspaceConstant) {
   185             MetaspaceWrapperObject metaspaceObject = HotSpotMetaspaceConstantImpl.getMetaspaceObject(base);
   125             MetaspaceObject metaspaceObject = HotSpotMetaspaceConstantImpl.getMetaspaceObject(base);
   186             if (metaspaceObject instanceof HotSpotResolvedObjectTypeImpl) {
   126             if (metaspaceObject instanceof HotSpotResolvedObjectTypeImpl) {
   187                 if (displacement == runtime.getConfig().classMirrorHandleOffset) {
   127                 if (displacement == runtime.getConfig().javaMirrorOffset) {
   188                     assert expected == ((HotSpotResolvedObjectTypeImpl) metaspaceObject).mirror();
   128                     HotSpotResolvedObjectTypeImpl type = (HotSpotResolvedObjectTypeImpl) metaspaceObject;
       
   129                     assert expected.equals(type.getJavaMirror());
   189                 }
   130                 }
   190             }
   131             }
   191         }
   132         }
   192         return true;
   133         return true;
   193     }
   134     }
   194 
   135 
   195     private Object readRawObject(Constant baseConstant, long initialDisplacement, boolean compressed) {
   136     private JavaConstant readRawObject(Constant baseConstant, long initialDisplacement, boolean compressed) {
   196         long displacement = initialDisplacement;
   137         long displacement = initialDisplacement;
   197         Object ret;
   138         JavaConstant ret;
   198         Object base = asObject(baseConstant, JavaKind.Object, displacement);
   139         HotSpotObjectConstantImpl base = asObject(baseConstant, JavaKind.Object, displacement);
   199         if (base == null) {
   140         if (base == null) {
   200             assert !compressed;
   141             assert !compressed;
   201             displacement += asRawPointer(baseConstant);
   142             displacement += asRawPointer(baseConstant);
   202             ret = UNSAFE.getUncompressedObject(displacement);
   143             ret = runtime.getCompilerToVM().readUncompressedOop(displacement);
   203             assert verifyReadRawObject(ret, baseConstant, initialDisplacement);
   144             assert verifyReadRawObject(ret, baseConstant, initialDisplacement);
   204         } else {
   145         } else {
   205             assert runtime.getConfig().useCompressedOops == compressed;
   146             assert runtime.getConfig().useCompressedOops == compressed;
   206             ret = UNSAFE.getReference(base, displacement);
   147             ret = runtime.getCompilerToVM().getObject(base, displacement);
   207         }
   148         }
   208         return ret;
   149         return ret == null ? JavaConstant.NULL_POINTER : ret;
   209     }
       
   210 
       
   211     JavaConstant readFieldValue(HotSpotResolvedJavaField field, Object obj, boolean isVolatile) {
       
   212         assert obj != null;
       
   213         assert !field.isStatic() || obj instanceof Class;
       
   214         long displacement = field.getOffset();
       
   215         assert checkRead(field.getJavaKind(), displacement, (HotSpotResolvedObjectType) runtime.getHostJVMCIBackend().getMetaAccess().lookupJavaType(obj.getClass()), obj,
       
   216                         runtime.getHostJVMCIBackend().getMetaAccess());
       
   217         JavaKind kind = field.getJavaKind();
       
   218         switch (kind) {
       
   219             case Boolean:
       
   220                 return JavaConstant.forBoolean(isVolatile ? UNSAFE.getBooleanVolatile(obj, displacement) : UNSAFE.getBoolean(obj, displacement));
       
   221             case Byte:
       
   222                 return JavaConstant.forByte(isVolatile ? UNSAFE.getByteVolatile(obj, displacement) : UNSAFE.getByte(obj, displacement));
       
   223             case Char:
       
   224                 return JavaConstant.forChar(isVolatile ? UNSAFE.getCharVolatile(obj, displacement) : UNSAFE.getChar(obj, displacement));
       
   225             case Short:
       
   226                 return JavaConstant.forShort(isVolatile ? UNSAFE.getShortVolatile(obj, displacement) : UNSAFE.getShort(obj, displacement));
       
   227             case Int:
       
   228                 return JavaConstant.forInt(isVolatile ? UNSAFE.getIntVolatile(obj, displacement) : UNSAFE.getInt(obj, displacement));
       
   229             case Long:
       
   230                 return JavaConstant.forLong(isVolatile ? UNSAFE.getLongVolatile(obj, displacement) : UNSAFE.getLong(obj, displacement));
       
   231             case Float:
       
   232                 return JavaConstant.forFloat(isVolatile ? UNSAFE.getFloatVolatile(obj, displacement) : UNSAFE.getFloat(obj, displacement));
       
   233             case Double:
       
   234                 return JavaConstant.forDouble(isVolatile ? UNSAFE.getDoubleVolatile(obj, displacement) : UNSAFE.getDouble(obj, displacement));
       
   235             case Object:
       
   236                 return HotSpotObjectConstantImpl.forObject(isVolatile ? UNSAFE.getReferenceVolatile(obj, displacement) : UNSAFE.getReference(obj, displacement));
       
   237             default:
       
   238                 throw new IllegalArgumentException("Unsupported kind: " + kind);
       
   239         }
       
   240     }
   150     }
   241 
   151 
   242     @Override
   152     @Override
   243     public JavaConstant readPrimitiveConstant(JavaKind kind, Constant baseConstant, long initialDisplacement, int bits) {
   153     public JavaConstant readPrimitiveConstant(JavaKind kind, Constant baseConstant, long initialDisplacement, int bits) {
   244         try {
   154         try {
   269     }
   179     }
   270 
   180 
   271     @Override
   181     @Override
   272     public JavaConstant readObjectConstant(Constant base, long displacement) {
   182     public JavaConstant readObjectConstant(Constant base, long displacement) {
   273         if (base instanceof HotSpotObjectConstantImpl) {
   183         if (base instanceof HotSpotObjectConstantImpl) {
   274             Object o = readRawObject(base, displacement, runtime.getConfig().useCompressedOops);
   184             return readRawObject(base, displacement, runtime.getConfig().useCompressedOops);
   275             return HotSpotObjectConstantImpl.forObject(o);
   185         }
   276         }
   186         if (!isValidObjectFieldDisplacement(base, displacement)) {
   277         if (base instanceof HotSpotMetaspaceConstant) {
   187             return null;
   278             MetaspaceWrapperObject metaspaceObject = HotSpotMetaspaceConstantImpl.getMetaspaceObject(base);
   188         }
   279             if (metaspaceObject instanceof HotSpotResolvedObjectTypeImpl) {
   189         if (base instanceof HotSpotMetaspaceConstant &&
   280                  if (displacement == runtime.getConfig().classMirrorHandleOffset) {
   190             displacement == runtime.getConfig().javaMirrorOffset) {
   281                     // Klass::_java_mirror is valid for all Klass* values
   191             MetaspaceObject metaspaceObject = HotSpotMetaspaceConstantImpl.getMetaspaceObject(base);
   282                     return HotSpotObjectConstantImpl.forObject(((HotSpotResolvedObjectTypeImpl) metaspaceObject).mirror());
   192             return ((HotSpotResolvedObjectTypeImpl) metaspaceObject).getJavaMirror();
   283                  }
   193         }
   284              } else {
   194         return readRawObject(base, displacement, false);
   285                  throw new IllegalArgumentException(String.valueOf(metaspaceObject));
       
   286              }
       
   287         }
       
   288         return null;
       
   289     }
   195     }
   290 
   196 
   291     @Override
   197     @Override
   292     public JavaConstant readNarrowOopConstant(Constant base, long displacement) {
   198     public JavaConstant readNarrowOopConstant(Constant base, long displacement) {
   293         return HotSpotObjectConstantImpl.forObject(readRawObject(base, displacement, true), true);
   199         JavaConstant res = readRawObject(base, displacement, true);
       
   200         return JavaConstant.NULL_POINTER.equals(res) ? HotSpotCompressedNullConstant.COMPRESSED_NULL : ((HotSpotObjectConstant) res).compress();
   294     }
   201     }
   295 
   202 
   296     private HotSpotResolvedObjectTypeImpl readKlass(Constant base, long displacement, boolean compressed) {
   203     private HotSpotResolvedObjectTypeImpl readKlass(Constant base, long displacement, boolean compressed) {
   297         assert (base instanceof HotSpotMetaspaceConstantImpl) || (base instanceof HotSpotObjectConstantImpl) : base.getClass();
   204         assert (base instanceof HotSpotMetaspaceConstantImpl) || (base instanceof HotSpotObjectConstantImpl) : base.getClass();
   298         Object baseObject = (base instanceof HotSpotMetaspaceConstantImpl) ? ((HotSpotMetaspaceConstantImpl) base).asResolvedJavaType() : ((HotSpotObjectConstantImpl) base).object();
   205         if (base instanceof HotSpotMetaspaceConstantImpl) {
   299         return runtime.getCompilerToVM().getResolvedJavaType(baseObject, displacement, compressed);
   206             return runtime.getCompilerToVM().getResolvedJavaType((HotSpotResolvedObjectTypeImpl) ((HotSpotMetaspaceConstantImpl) base).asResolvedJavaType(), displacement, compressed);
   300     }
   207         } else {
       
   208             return runtime.getCompilerToVM().getResolvedJavaType(((HotSpotObjectConstantImpl) base), displacement, compressed);
       
   209         }
       
   210     }
       
   211 
   301 
   212 
   302     @Override
   213     @Override
   303     public Constant readKlassPointerConstant(Constant base, long displacement) {
   214     public Constant readKlassPointerConstant(Constant base, long displacement) {
   304         HotSpotResolvedObjectTypeImpl klass = readKlass(base, displacement, false);
   215         HotSpotResolvedObjectTypeImpl klass = readKlass(base, displacement, false);
   305         if (klass == null) {
   216         if (klass == null) {
   318     }
   229     }
   319 
   230 
   320     @Override
   231     @Override
   321     public Constant readMethodPointerConstant(Constant base, long displacement) {
   232     public Constant readMethodPointerConstant(Constant base, long displacement) {
   322         assert (base instanceof HotSpotObjectConstantImpl);
   233         assert (base instanceof HotSpotObjectConstantImpl);
   323         Object baseObject = ((HotSpotObjectConstantImpl) base).object();
   234         HotSpotResolvedJavaMethodImpl method = runtime.getCompilerToVM().getResolvedJavaMethod((HotSpotObjectConstantImpl) base, displacement);
   324         HotSpotResolvedJavaMethodImpl method = runtime.getCompilerToVM().getResolvedJavaMethod(baseObject, displacement);
       
   325         return HotSpotMetaspaceConstantImpl.forMetaspaceObject(method, false);
   235         return HotSpotMetaspaceConstantImpl.forMetaspaceObject(method, false);
   326     }
   236     }
   327 }
   237 }