1 /*
   2  * Copyright (c) 2012, 2018, 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 
  24 
  25 package org.graalvm.compiler.hotspot.replacements;
  26 
  27 import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG;
  28 import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_METAACCESS;
  29 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.ARRAY_KLASS_COMPONENT_MIRROR;
  30 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.KLASS_ACCESS_FLAGS_LOCATION;
  31 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.KLASS_MODIFIER_FLAGS_LOCATION;
  32 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.KLASS_SUPER_KLASS_LOCATION;
  33 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.arrayKlassComponentMirrorOffset;
  34 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.klassAccessFlagsOffset;
  35 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.klassIsArray;
  36 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.klassModifierFlagsOffset;
  37 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.klassSuperKlassOffset;
  38 
  39 import java.lang.reflect.Modifier;
  40 
  41 import org.graalvm.compiler.api.replacements.ClassSubstitution;
  42 import org.graalvm.compiler.api.replacements.Fold;
  43 import org.graalvm.compiler.api.replacements.MethodSubstitution;
  44 import org.graalvm.compiler.hotspot.word.KlassPointer;
  45 import org.graalvm.compiler.nodes.ConstantNode;
  46 import org.graalvm.compiler.nodes.PiNode;
  47 import org.graalvm.compiler.nodes.SnippetAnchorNode;
  48 
  49 import jdk.vm.ci.meta.MetaAccessProvider;
  50 import jdk.vm.ci.meta.ResolvedJavaType;
  51 
  52 // JaCoCo Exclude
  53 
  54 /**
  55  * Substitutions for {@link java.lang.Class} methods.
  56  */
  57 @ClassSubstitution(Class.class)
  58 public class HotSpotClassSubstitutions {
  59 
  60     @MethodSubstitution(isStatic = false)
  61     public static int getModifiers(final Class<?> thisObj) {
  62         KlassPointer klass = ClassGetHubNode.readClass(thisObj);
  63         if (klass.isNull()) {
  64             // Class for primitive type
  65             return Modifier.ABSTRACT | Modifier.FINAL | Modifier.PUBLIC;
  66         } else {
  67             return klass.readInt(klassModifierFlagsOffset(INJECTED_VMCONFIG), KLASS_MODIFIER_FLAGS_LOCATION);
  68         }
  69     }
  70 
  71     @MethodSubstitution(isStatic = false)
  72     public static boolean isInterface(final Class<?> thisObj) {
  73         KlassPointer klass = ClassGetHubNode.readClass(thisObj);
  74         if (klass.isNull()) {
  75             // Class for primitive type
  76             return false;
  77         } else {
  78             int accessFlags = klass.readInt(klassAccessFlagsOffset(INJECTED_VMCONFIG), KLASS_ACCESS_FLAGS_LOCATION);
  79             return (accessFlags & Modifier.INTERFACE) != 0;
  80         }
  81     }
  82 
  83     @MethodSubstitution(isStatic = false)
  84     public static boolean isArray(final Class<?> thisObj) {
  85         KlassPointer klass = ClassGetHubNode.readClass(thisObj);
  86         if (klass.isNull()) {
  87             // Class for primitive type
  88             return false;
  89         } else {
  90             KlassPointer klassNonNull = ClassGetHubNode.piCastNonNull(klass, SnippetAnchorNode.anchor());
  91             return klassIsArray(klassNonNull);
  92         }
  93     }
  94 
  95     @MethodSubstitution(isStatic = false)
  96     public static boolean isPrimitive(final Class<?> thisObj) {
  97         KlassPointer klass = ClassGetHubNode.readClass(thisObj);
  98         return klass.isNull();
  99     }
 100 
 101     @Fold
 102     public static ResolvedJavaType getObjectType(@Fold.InjectedParameter MetaAccessProvider metaAccesss) {
 103         return metaAccesss.lookupJavaType(Object.class);
 104     }
 105 
 106     @MethodSubstitution(isStatic = false)
 107     public static Class<?> getSuperclass(final Class<?> thisObj) {
 108         KlassPointer klass = ClassGetHubNode.readClass(thisObj);
 109         if (!klass.isNull()) {
 110             KlassPointer klassNonNull = ClassGetHubNode.piCastNonNull(klass, SnippetAnchorNode.anchor());
 111             int accessFlags = klassNonNull.readInt(klassAccessFlagsOffset(INJECTED_VMCONFIG), KLASS_ACCESS_FLAGS_LOCATION);
 112             if ((accessFlags & Modifier.INTERFACE) == 0) {
 113                 if (klassIsArray(klassNonNull)) {
 114                     return ConstantNode.forClass(getObjectType(INJECTED_METAACCESS));
 115                 } else {
 116                     KlassPointer superKlass = klassNonNull.readKlassPointer(klassSuperKlassOffset(INJECTED_VMCONFIG), KLASS_SUPER_KLASS_LOCATION);
 117                     if (superKlass.isNull()) {
 118                         return null;
 119                     } else {
 120                         KlassPointer superKlassNonNull = ClassGetHubNode.piCastNonNull(superKlass, SnippetAnchorNode.anchor());
 121                         return HubGetClassNode.readClass(superKlassNonNull);
 122                     }
 123                 }
 124             }
 125         } else {
 126             // Class for primitive type
 127         }
 128         return null;
 129     }
 130 
 131     @MethodSubstitution(isStatic = false)
 132     public static Class<?> getComponentType(final Class<?> thisObj) {
 133         KlassPointer klass = ClassGetHubNode.readClass(thisObj);
 134         if (!klass.isNull()) {
 135             KlassPointer klassNonNull = ClassGetHubNode.piCastNonNull(klass, SnippetAnchorNode.anchor());
 136             if (klassIsArray(klassNonNull)) {
 137                 return PiNode.asNonNullClass(klassNonNull.readObject(arrayKlassComponentMirrorOffset(INJECTED_VMCONFIG), ARRAY_KLASS_COMPONENT_MIRROR));
 138             }
 139         } else {
 140             // Class for primitive type
 141         }
 142         return null;
 143     }
 144 }