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}