--- /dev/null 2017-01-22 10:16:57.869617664 -0800 +++ new/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantReflectionProvider.java 2017-02-15 16:55:46.256180531 -0800 @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2011, 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.vm.ci.hotspot; + +import java.lang.reflect.Array; +import java.util.Objects; + +import jdk.vm.ci.common.JVMCIError; +import jdk.vm.ci.meta.Constant; +import jdk.vm.ci.meta.ConstantReflectionProvider; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.MemoryAccessProvider; +import jdk.vm.ci.meta.MethodHandleAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaField; +import jdk.vm.ci.meta.ResolvedJavaType; + +/** + * HotSpot implementation of {@link ConstantReflectionProvider}. + */ +public class HotSpotConstantReflectionProvider implements ConstantReflectionProvider { + + protected final HotSpotJVMCIRuntimeProvider runtime; + protected final HotSpotMethodHandleAccessProvider methodHandleAccess; + protected final HotSpotMemoryAccessProviderImpl memoryAccess; + + public HotSpotConstantReflectionProvider(HotSpotJVMCIRuntimeProvider runtime) { + this.runtime = runtime; + this.methodHandleAccess = new HotSpotMethodHandleAccessProvider(this); + this.memoryAccess = new HotSpotMemoryAccessProviderImpl(runtime); + } + + public MethodHandleAccessProvider getMethodHandleAccess() { + return methodHandleAccess; + } + + @Override + public MemoryAccessProvider getMemoryAccessProvider() { + return memoryAccess; + } + + @Override + public Boolean constantEquals(Constant x, Constant y) { + if (x == y) { + return true; + } else if (x instanceof HotSpotObjectConstantImpl) { + return y instanceof HotSpotObjectConstantImpl && ((HotSpotObjectConstantImpl) x).object() == ((HotSpotObjectConstantImpl) y).object(); + } else { + return Objects.equals(x, y); + } + } + + @Override + public Integer readArrayLength(JavaConstant array) { + if (array == null || array.getJavaKind() != JavaKind.Object || array.isNull()) { + return null; + } + + Object arrayObject = ((HotSpotObjectConstantImpl) array).object(); + if (!arrayObject.getClass().isArray()) { + return null; + } + return Array.getLength(arrayObject); + } + + @Override + public JavaConstant readArrayElement(JavaConstant array, int index) { + if (array == null || array.getJavaKind() != JavaKind.Object || array.isNull()) { + return null; + } + Object a = ((HotSpotObjectConstantImpl) array).object(); + + if (!a.getClass().isArray() || index < 0 || index >= Array.getLength(a)) { + return null; + } + + if (a instanceof Object[]) { + Object element = ((Object[]) a)[index]; + return HotSpotObjectConstantImpl.forObject(element); + } else { + return JavaConstant.forBoxedPrimitive(Array.get(a, index)); + } + } + + /** + * Check if the constant is a boxed value that is guaranteed to be cached by the platform. + * Otherwise the generated code might be the only reference to the boxed value and since object + * references from nmethods are weak this can cause GC problems. + * + * @param source + * @return true if the box is cached + */ + private static boolean isBoxCached(JavaConstant source) { + switch (source.getJavaKind()) { + case Boolean: + return true; + case Char: + return source.asInt() <= 127; + case Byte: + case Short: + case Int: + return source.asInt() >= -128 && source.asInt() <= 127; + case Long: + return source.asLong() >= -128 && source.asLong() <= 127; + case Float: + case Double: + return false; + default: + throw new IllegalArgumentException("unexpected kind " + source.getJavaKind()); + } + } + + @Override + public JavaConstant boxPrimitive(JavaConstant source) { + if (source == null || !source.getJavaKind().isPrimitive() || !isBoxCached(source)) { + return null; + } + return HotSpotObjectConstantImpl.forObject(source.asBoxedPrimitive()); + } + + @Override + public JavaConstant unboxPrimitive(JavaConstant source) { + if (source == null || !source.getJavaKind().isObject()) { + return null; + } + if (source.isNull()) { + return null; + } + return JavaConstant.forBoxedPrimitive(((HotSpotObjectConstantImpl) source).object()); + } + + public JavaConstant forString(String value) { + return HotSpotObjectConstantImpl.forObject(value); + } + + public JavaConstant forObject(Object value) { + return HotSpotObjectConstantImpl.forObject(value); + } + + @Override + public ResolvedJavaType asJavaType(Constant constant) { + if (constant instanceof HotSpotObjectConstant) { + Object obj = ((HotSpotObjectConstantImpl) constant).object(); + if (obj instanceof Class) { + return runtime.getHostJVMCIBackend().getMetaAccess().lookupJavaType((Class) obj); + } + } + if (constant instanceof HotSpotMetaspaceConstant) { + MetaspaceWrapperObject obj = HotSpotMetaspaceConstantImpl.getMetaspaceObject(constant); + if (obj instanceof HotSpotResolvedObjectTypeImpl) { + return (ResolvedJavaType) obj; + } + } + return null; + } + + public JavaConstant readFieldValue(ResolvedJavaField field, JavaConstant receiver) { + HotSpotResolvedJavaField hotspotField = (HotSpotResolvedJavaField) field; + if (hotspotField.isStatic()) { + HotSpotResolvedJavaType holder = (HotSpotResolvedJavaType) hotspotField.getDeclaringClass(); + if (holder.isInitialized()) { + return memoryAccess.readUnsafeConstant(hotspotField.getJavaKind(), HotSpotObjectConstantImpl.forObject(holder.mirror()), hotspotField.offset()); + } + } else { + if (receiver.isNonNull() && hotspotField.isInObject(((HotSpotObjectConstantImpl) receiver).object())) { + return memoryAccess.readUnsafeConstant(hotspotField.getJavaKind(), receiver, hotspotField.offset()); + } + } + return null; + } + + @Override + public JavaConstant asJavaClass(ResolvedJavaType type) { + return HotSpotObjectConstantImpl.forObject(((HotSpotResolvedJavaType) type).mirror()); + } + + @Override + public Constant asObjectHub(ResolvedJavaType type) { + if (type instanceof HotSpotResolvedObjectType) { + return ((HotSpotResolvedObjectType) type).klass(); + } else { + throw JVMCIError.unimplemented(); + } + } +}