001/* 002 * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.replacements; 024 025import static com.oracle.graal.compiler.common.GraalOptions.*; 026import static com.oracle.graal.replacements.SnippetTemplate.*; 027 028import java.util.*; 029 030import jdk.internal.jvmci.code.*; 031import com.oracle.graal.debug.*; 032import jdk.internal.jvmci.meta.*; 033 034import com.oracle.graal.api.replacements.*; 035import com.oracle.graal.compiler.common.type.*; 036import com.oracle.graal.nodes.*; 037import com.oracle.graal.nodes.calc.*; 038import com.oracle.graal.nodes.extended.*; 039import com.oracle.graal.nodes.spi.*; 040import com.oracle.graal.phases.util.*; 041import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; 042import com.oracle.graal.replacements.SnippetTemplate.Arguments; 043import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; 044 045public class BoxingSnippets implements Snippets { 046 047 @Snippet 048 public static Object booleanValueOf(boolean value) { 049 valueOfCounter.inc(); 050 return PiNode.piCast(Boolean.valueOf(value), StampFactory.forNodeIntrinsic()); 051 } 052 053 @Snippet 054 public static Object byteValueOf(byte value) { 055 valueOfCounter.inc(); 056 return PiNode.piCast(Byte.valueOf(value), StampFactory.forNodeIntrinsic()); 057 } 058 059 @Snippet 060 public static Object charValueOf(char value) { 061 valueOfCounter.inc(); 062 return PiNode.piCast(Character.valueOf(value), StampFactory.forNodeIntrinsic()); 063 } 064 065 @Snippet 066 public static Object doubleValueOf(double value) { 067 valueOfCounter.inc(); 068 return PiNode.piCast(Double.valueOf(value), StampFactory.forNodeIntrinsic()); 069 } 070 071 @Snippet 072 public static Object floatValueOf(float value) { 073 valueOfCounter.inc(); 074 return PiNode.piCast(Float.valueOf(value), StampFactory.forNodeIntrinsic()); 075 } 076 077 @Snippet 078 public static Object intValueOf(int value) { 079 valueOfCounter.inc(); 080 return PiNode.piCast(Integer.valueOf(value), StampFactory.forNodeIntrinsic()); 081 } 082 083 @Snippet 084 public static Object longValueOf(long value) { 085 valueOfCounter.inc(); 086 return PiNode.piCast(Long.valueOf(value), StampFactory.forNodeIntrinsic()); 087 } 088 089 @Snippet 090 public static Object shortValueOf(short value) { 091 valueOfCounter.inc(); 092 return PiNode.piCast(Short.valueOf(value), StampFactory.forNodeIntrinsic()); 093 } 094 095 @Snippet 096 public static boolean booleanValue(Boolean value) { 097 valueOfCounter.inc(); 098 return value.booleanValue(); 099 } 100 101 @Snippet 102 public static byte byteValue(Byte value) { 103 valueOfCounter.inc(); 104 return value.byteValue(); 105 } 106 107 @Snippet 108 public static char charValue(Character value) { 109 valueOfCounter.inc(); 110 return value.charValue(); 111 } 112 113 @Snippet 114 public static double doubleValue(Double value) { 115 valueOfCounter.inc(); 116 return value.doubleValue(); 117 } 118 119 @Snippet 120 public static float floatValue(Float value) { 121 valueOfCounter.inc(); 122 return value.floatValue(); 123 } 124 125 @Snippet 126 public static int intValue(Integer value) { 127 valueOfCounter.inc(); 128 return value.intValue(); 129 } 130 131 @Snippet 132 public static long longValue(Long value) { 133 valueOfCounter.inc(); 134 return value.longValue(); 135 } 136 137 @Snippet 138 public static short shortValue(Short value) { 139 valueOfCounter.inc(); 140 return value.shortValue(); 141 } 142 143 public static FloatingNode canonicalizeBoxing(BoxNode box, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection) { 144 ValueNode value = box.getValue(); 145 if (value.isConstant()) { 146 JavaConstant sourceConstant = value.asJavaConstant(); 147 if (sourceConstant.getKind() != box.getBoxingKind() && sourceConstant.getKind().isNumericInteger()) { 148 switch (box.getBoxingKind()) { 149 case Boolean: 150 sourceConstant = JavaConstant.forBoolean(sourceConstant.asLong() != 0L); 151 break; 152 case Byte: 153 sourceConstant = JavaConstant.forByte((byte) sourceConstant.asLong()); 154 break; 155 case Char: 156 sourceConstant = JavaConstant.forChar((char) sourceConstant.asLong()); 157 break; 158 case Short: 159 sourceConstant = JavaConstant.forShort((short) sourceConstant.asLong()); 160 break; 161 } 162 } 163 JavaConstant boxedConstant = constantReflection.boxPrimitive(sourceConstant); 164 if (boxedConstant != null && sourceConstant.getKind() == box.getBoxingKind()) { 165 return ConstantNode.forConstant(boxedConstant, metaAccess, box.graph()); 166 } 167 } 168 return null; 169 } 170 171 public static class Templates extends AbstractTemplates { 172 173 private final EnumMap<Kind, SnippetInfo> boxSnippets = new EnumMap<>(Kind.class); 174 private final EnumMap<Kind, SnippetInfo> unboxSnippets = new EnumMap<>(Kind.class); 175 176 public Templates(Providers providers, SnippetReflectionProvider snippetReflection, TargetDescription target) { 177 super(providers, snippetReflection, target); 178 for (Kind kind : new Kind[]{Kind.Boolean, Kind.Byte, Kind.Char, Kind.Double, Kind.Float, Kind.Int, Kind.Long, Kind.Short}) { 179 boxSnippets.put(kind, snippet(BoxingSnippets.class, kind.getJavaName() + "ValueOf")); 180 unboxSnippets.put(kind, snippet(BoxingSnippets.class, kind.getJavaName() + "Value")); 181 } 182 } 183 184 public void lower(BoxNode box, LoweringTool tool) { 185 FloatingNode canonical = canonicalizeBoxing(box, providers.getMetaAccess(), providers.getConstantReflection()); 186 // if in AOT mode, we don't want to embed boxed constants. 187 if (canonical != null && !ImmutableCode.getValue()) { 188 box.graph().replaceFixedWithFloating(box, canonical); 189 } else { 190 Arguments args = new Arguments(boxSnippets.get(box.getBoxingKind()), box.graph().getGuardsStage(), tool.getLoweringStage()); 191 args.add("value", box.getValue()); 192 193 SnippetTemplate template = template(args); 194 Debug.log("Lowering integerValueOf in %s: node=%s, template=%s, arguments=%s", box.graph(), box, template, args); 195 template.instantiate(providers.getMetaAccess(), box, DEFAULT_REPLACER, args); 196 } 197 } 198 199 public void lower(UnboxNode unbox, LoweringTool tool) { 200 Arguments args = new Arguments(unboxSnippets.get(unbox.getBoxingKind()), unbox.graph().getGuardsStage(), tool.getLoweringStage()); 201 args.add("value", unbox.getValue()); 202 203 SnippetTemplate template = template(args); 204 Debug.log("Lowering integerValueOf in %s: node=%s, template=%s, arguments=%s", unbox.graph(), unbox, template, args); 205 template.instantiate(providers.getMetaAccess(), unbox, DEFAULT_REPLACER, args); 206 } 207 } 208 209 private static final SnippetCounter.Group integerCounters = SnippetCounters.getValue() ? new SnippetCounter.Group("Integer intrinsifications") : null; 210 private static final SnippetCounter valueOfCounter = new SnippetCounter(integerCounters, "valueOf", "valueOf intrinsification"); 211 212}