--- old/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java 2019-03-28 11:24:06.000000000 -0700 +++ new/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java 2019-03-28 11:24:05.000000000 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,8 +35,6 @@ import java.lang.reflect.Executable; import java.lang.reflect.Modifier; import java.lang.reflect.Type; -import java.util.HashMap; -import java.util.Map; import jdk.vm.ci.common.JVMCIError; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.Option; @@ -58,23 +56,24 @@ /** * Implementation of {@link JavaMethod} for resolved HotSpot methods. */ -final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSpotResolvedJavaMethod, MetaspaceWrapperObject { +final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSpotResolvedJavaMethod, MetaspaceHandleObject { /** - * Reference to metaspace Method object. + * Handle to the metaspace {@code Method} object. The handle is in + * {@code JVMCI::_metadata_handles}. */ - private final long metaspaceMethod; + private final long metadataHandle; private final HotSpotResolvedObjectTypeImpl holder; private final HotSpotConstantPool constantPool; - private final HotSpotSignature signature; + final HotSpotSignature signature; private HotSpotMethodData methodData; private byte[] code; /** - * Cache for {@link #toJava()}. + * Cache for {@link HotSpotJDKReflection#getMethod}. */ - private volatile Executable toJavaCache; + volatile Executable toJavaCache; /** * Only 30% of {@link HotSpotResolvedJavaMethodImpl}s have their name accessed so compute it @@ -85,35 +84,40 @@ /** * Gets the holder of a HotSpot metaspace method native object. * - * @param metaspaceMethod a metaspace Method object + * @param metaspaceHandle a handle to a metaspace Method object * @return the {@link ResolvedJavaType} corresponding to the holder of the * {@code metaspaceMethod} */ - private static HotSpotResolvedObjectTypeImpl getHolder(long metaspaceMethod) { + private static HotSpotResolvedObjectTypeImpl getHolder(long metaspaceHandle) { HotSpotVMConfig config = config(); + long metaspaceMethod = UNSAFE.getLong(metaspaceHandle); + assert metaspaceMethod != 0 : metaspaceHandle; final long metaspaceConstMethod = UNSAFE.getAddress(metaspaceMethod + config.methodConstMethodOffset); final long metaspaceConstantPool = UNSAFE.getAddress(metaspaceConstMethod + config.constMethodConstantsOffset); - return compilerToVM().getResolvedJavaType(null, metaspaceConstantPool + config.constantPoolHolderOffset, false); + HotSpotResolvedObjectTypeImpl result = compilerToVM().getResolvedJavaType(metaspaceConstantPool + config.constantPoolHolderOffset, false); + assert result != null; + return result; } /** * Gets the JVMCI mirror from a HotSpot method. The VM is responsible for ensuring that the - * Method* is kept alive for the duration of this call and the - * {@link HotSpotJVMCIMetaAccessContext} keeps it alive after that. - * + * Method* is kept alive for the duration of this call and the {@link HotSpotJVMCIRuntime} keeps + * it alive after that. + *

* Called from the VM. * - * @param metaspaceMethod a metaspace Method object + * @param metaspaceHandle a handle to metaspace Method object * @return the {@link ResolvedJavaMethod} corresponding to {@code metaspaceMethod} */ @SuppressWarnings("unused") - private static HotSpotResolvedJavaMethod fromMetaspace(long metaspaceMethod) { - HotSpotResolvedObjectTypeImpl holder = getHolder(metaspaceMethod); - return holder.createMethod(metaspaceMethod); + @VMEntryPoint + private static HotSpotResolvedJavaMethod fromMetaspace(long metaspaceHandle) { + HotSpotResolvedObjectTypeImpl holder = getHolder(metaspaceHandle); + return holder.createMethod(metaspaceHandle); } - HotSpotResolvedJavaMethodImpl(HotSpotResolvedObjectTypeImpl holder, long metaspaceMethod) { - this.metaspaceMethod = metaspaceMethod; + HotSpotResolvedJavaMethodImpl(HotSpotResolvedObjectTypeImpl holder, long metaspaceHandle) { + this.metadataHandle = metaspaceHandle; this.holder = holder; HotSpotVMConfig config = config(); @@ -133,6 +137,7 @@ final int signatureIndex = UNSAFE.getChar(constMethod + config.constMethodSignatureIndexOffset); this.signature = (HotSpotSignature) constantPool.lookupSignature(signatureIndex); + HandleCleaner.create(this, metaspaceHandle); } /** @@ -144,8 +149,7 @@ * @return pointer to this method's ConstMethod */ private long getConstMethod() { - assert metaspaceMethod != 0; - return UNSAFE.getAddress(metaspaceMethod + config().methodConstMethodOffset); + return UNSAFE.getAddress(getMetaspaceMethod() + config().methodConstMethodOffset); } @Override @@ -164,14 +168,14 @@ } if (obj instanceof HotSpotResolvedJavaMethodImpl) { HotSpotResolvedJavaMethodImpl that = (HotSpotResolvedJavaMethodImpl) obj; - return that.metaspaceMethod == metaspaceMethod; + return that.getMetaspaceMethod() == getMetaspaceMethod(); } return false; } @Override public int hashCode() { - return (int) metaspaceMethod; + return (int) getMetaspaceMethod(); } /** @@ -180,7 +184,7 @@ * @return flags of this method */ private int getFlags() { - return UNSAFE.getShort(metaspaceMethod + config().methodFlagsOffset); + return UNSAFE.getShort(getMetaspaceMethod() + config().methodFlagsOffset); } /** @@ -204,9 +208,17 @@ return HotSpotMetaspaceConstantImpl.forMetaspaceObject(this, false); } + long getMetaspaceMethod() { + long metaspacePointer = getMetaspacePointer(); + if (metaspacePointer == 0) { + throw new NullPointerException("Method* is null"); + } + return metaspacePointer; + } + @Override - public long getMetaspacePointer() { - return metaspaceMethod; + public long getMetadataHandle() { + return metadataHandle; } @Override @@ -219,7 +231,7 @@ * modifiers as well as the HotSpot internal modifiers. */ public int getAllModifiers() { - return UNSAFE.getInt(metaspaceMethod + config().methodAccessFlagsOffset); + return UNSAFE.getInt(getMetaspaceMethod() + config().methodAccessFlagsOffset); } @Override @@ -277,7 +289,7 @@ // Check for Throwable which catches everything. if (catchType instanceof HotSpotResolvedObjectTypeImpl) { HotSpotResolvedObjectTypeImpl resolvedType = (HotSpotResolvedObjectTypeImpl) catchType; - if (resolvedType.mirror() == Throwable.class) { + if (resolvedType.equals(runtime().getJavaLangThrowable())) { catchTypeIndex = 0; catchType = null; } @@ -424,7 +436,7 @@ */ private long getCompiledCode() { HotSpotVMConfig config = config(); - return UNSAFE.getAddress(metaspaceMethod + config.methodCodeOffset); + return UNSAFE.getAddress(getMetaspaceMethod() + config.methodCodeOffset); } /** @@ -455,7 +467,7 @@ ProfilingInfo info; if (Option.UseProfilingInformation.getBoolean() && methodData == null) { - long metaspaceMethodData = UNSAFE.getAddress(metaspaceMethod + config().methodDataOffset); + long metaspaceMethodData = UNSAFE.getAddress(getMetaspaceMethod() + config().methodDataOffset); if (metaspaceMethodData != 0) { methodData = new HotSpotMethodData(metaspaceMethodData, this); String methodDataFilter = Option.TraceMethodDataFilter.getString(); @@ -490,14 +502,7 @@ if (signature.getParameterCount(false) == 0) { return new ResolvedJavaMethod.Parameter[0]; } - java.lang.reflect.Parameter[] javaParameters = toJava().getParameters(); - Parameter[] res = new Parameter[javaParameters.length]; - for (int i = 0; i < res.length; i++) { - java.lang.reflect.Parameter src = javaParameters[i]; - String paramName = src.isNamePresent() ? src.getName() : null; - res[i] = new Parameter(paramName, src.getModifiers(), this, i); - } - return res; + return runtime().reflection.getParameters(this); } @Override @@ -505,7 +510,7 @@ if ((getConstMethodFlags() & config().constMethodHasParameterAnnotations) == 0) { return new Annotation[signature.getParameterCount(false)][0]; } - return toJava().getParameterAnnotations(); + return runtime().reflection.getParameterAnnotations(this); } @Override @@ -513,7 +518,7 @@ if ((getConstMethodFlags() & config().constMethodHasMethodAnnotations) == 0) { return new Annotation[0]; } - return toJava().getAnnotations(); + return runtime().reflection.getMethodAnnotations(this); } @Override @@ -521,7 +526,7 @@ if ((getConstMethodFlags() & config().constMethodHasMethodAnnotations) == 0) { return new Annotation[0]; } - return toJava().getDeclaredAnnotations(); + return runtime().reflection.getMethodDeclaredAnnotations(this); } @Override @@ -529,7 +534,7 @@ if ((getConstMethodFlags() & config().constMethodHasMethodAnnotations) == 0) { return null; } - return toJava().getAnnotation(annotationClass); + return runtime().reflection.getMethodAnnotation(this, annotationClass); } @Override @@ -559,19 +564,7 @@ if (isClassInitializer()) { return new Type[0]; } - return toJava().getGenericParameterTypes(); - } - - private Executable toJava() { - if (toJavaCache == null) { - assert !isClassInitializer() : this; - synchronized (this) { - if (toJavaCache == null) { - toJavaCache = compilerToVM().asReflectionExecutable(this); - } - } - } - return toJavaCache; + return runtime().reflection.getGenericParameterTypes(this); } @Override @@ -698,7 +691,7 @@ private int getVtableIndex() { assert !holder.isInterface(); HotSpotVMConfig config = config(); - int result = UNSAFE.getInt(metaspaceMethod + config.methodVtableIndexOffset); + int result = UNSAFE.getInt(getMetaspaceMethod() + config.methodVtableIndexOffset); assert result >= config.nonvirtualVtableIndex : "must be linked"; return result; } @@ -708,40 +701,16 @@ return compilerToVM().getVtableIndexForInterfaceMethod(hotspotType, this); } - /** - * The {@link SpeculationLog} for methods compiled by JVMCI hang off this per-declaring-type - * {@link ClassValue}. The raw Method* value is safe to use as a key in the map as a) it is - * never moves and b) we never read from it. - *

- * One implication is that we will preserve {@link SpeculationLog}s for methods that have been - * redefined via class redefinition. It's tempting to periodically flush such logs but we cannot - * read the JVM_ACC_IS_OBSOLETE bit (or anything else) via the raw pointer as obsoleted methods - * are subject to clean up and deletion (see InstanceKlass::purge_previous_versions_internal). - */ - private static final ClassValue> SpeculationLogs = new ClassValue<>() { - @Override - protected Map computeValue(java.lang.Class type) { - return new HashMap<>(4); - } - }; - @Override public SpeculationLog getSpeculationLog() { - Map map = SpeculationLogs.get(holder.mirror()); - synchronized (map) { - SpeculationLog log = map.get(this.metaspaceMethod); - if (log == null) { - log = new HotSpotSpeculationLog(); - map.put(metaspaceMethod, log); - } - return log; - } + long address = compilerToVM().getFailedSpeculationsAddress(this); + return new HotSpotSpeculationLog(address); } @Override public int intrinsicId() { HotSpotVMConfig config = config(); - return UNSAFE.getChar(metaspaceMethod + config.methodIntrinsicIdOffset); + return UNSAFE.getChar(getMetaspaceMethod() + config.methodIntrinsicIdOffset); } @Override