1 /*
   2  * Copyright (c) 2013, 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 package com.oracle.graal.hotspot;
  24 
  25 import java.lang.reflect.*;
  26 
  27 import com.oracle.graal.api.code.*;
  28 import com.oracle.graal.api.meta.*;
  29 import com.oracle.graal.api.replacements.*;
  30 import com.oracle.graal.compiler.common.*;
  31 import com.oracle.graal.hotspot.meta.*;
  32 import com.oracle.graal.hotspot.replacements.*;
  33 import com.oracle.graal.hotspot.word.*;
  34 import com.oracle.graal.nodes.*;
  35 import com.oracle.graal.phases.util.*;
  36 import com.oracle.graal.replacements.*;
  37 import com.oracle.graal.replacements.IntegerSubstitutions;
  38 import com.oracle.graal.replacements.LongSubstitutions;
  39 import com.oracle.graal.word.phases.*;
  40 
  41 /**
  42  * Filters certain method substitutions based on whether there is underlying hardware support for
  43  * them.
  44  */
  45 public class HotSpotReplacementsImpl extends ReplacementsImpl {
  46 
  47     private final HotSpotVMConfig config;
  48 
  49     public HotSpotReplacementsImpl(Providers providers, SnippetReflectionProvider snippetReflection, HotSpotVMConfig config, Assumptions assumptions, TargetDescription target) {
  50         super(providers, snippetReflection, assumptions, target);
  51         this.config = config;
  52     }
  53 
  54     @Override
  55     protected ResolvedJavaMethod registerMethodSubstitution(ClassReplacements cr, Executable originalMethod, Method substituteMethod) {
  56         final Class<?> substituteClass = substituteMethod.getDeclaringClass();
  57         if (substituteClass.getDeclaringClass() == BoxingSubstitutions.class) {
  58             if (config.useHeapProfiler) {
  59                 return null;
  60             }
  61         } else if (substituteClass == IntegerSubstitutions.class || substituteClass == LongSubstitutions.class) {
  62             if (substituteMethod.getName().equals("bitCount")) {
  63                 if (!config.usePopCountInstruction) {
  64                     return null;
  65                 }
  66             } else if (substituteMethod.getName().equals("numberOfLeadingZeros")) {
  67                 if (config.useCountLeadingZerosInstruction) {
  68                     return null;
  69                 }
  70             } else if (substituteMethod.getName().equals("numberOfTrailingZeros")) {
  71                 if (config.useCountTrailingZerosInstruction) {
  72                     return null;
  73                 }
  74             }
  75         } else if (substituteClass == CRC32Substitutions.class) {
  76             if (!config.useCRC32Intrinsics) {
  77                 return null;
  78             }
  79         } else if (substituteClass == StringSubstitutions.class) {
  80             /*
  81              * AMD64's String.equals substitution needs about 8 registers so we better disable the
  82              * substitution if there is some register pressure.
  83              */
  84             if (GraalOptions.RegisterPressure.getValue() != null) {
  85                 return null;
  86             }
  87         }
  88         return super.registerMethodSubstitution(cr, originalMethod, substituteMethod);
  89     }
  90 
  91     @Override
  92     public Class<? extends FixedWithNextNode> getMacroSubstitution(ResolvedJavaMethod method) {
  93         HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) method;
  94         int intrinsicId = hsMethod.intrinsicId();
  95         if (intrinsicId != 0) {
  96             /*
  97              * The methods of MethodHandle that need substitution are signature-polymorphic, i.e.,
  98              * the VM replicates them for every signature that they are actually used for.
  99              * Therefore, we cannot use the usual annotation-driven mechanism to define the
 100              */
 101             if (MethodHandleNode.lookupMethodHandleIntrinsic(method, providers.getMetaAccess().getMethodHandleAccess()) != null) {
 102                 return MethodHandleNode.class;
 103             }
 104         }
 105         return super.getMacroSubstitution(method);
 106     }
 107 
 108     @Override
 109     protected GraphMaker createGraphMaker(ResolvedJavaMethod substitute, ResolvedJavaMethod original, FrameStateProcessing frameStateProcessing) {
 110         return new HotSpotGraphMaker(this, substitute, original, frameStateProcessing);
 111     }
 112 
 113     private static class HotSpotGraphMaker extends ReplacementsImpl.GraphMaker {
 114 
 115         protected HotSpotGraphMaker(ReplacementsImpl replacements, ResolvedJavaMethod substitute, ResolvedJavaMethod substitutedMethod, FrameStateProcessing frameStateProcessing) {
 116             super(replacements, substitute, substitutedMethod, frameStateProcessing);
 117         }
 118 
 119         @Override
 120         protected void afterParsing(StructuredGraph graph) {
 121             MetaAccessProvider metaAccess = replacements.providers.getMetaAccess();
 122             new WordTypeVerificationPhase(metaAccess, replacements.snippetReflection, replacements.target.wordKind).apply(graph);
 123             new HotSpotWordTypeRewriterPhase(metaAccess, replacements.snippetReflection, replacements.target.wordKind).apply(graph);
 124         }
 125     }
 126 }