HotSpotWordOperationPlugin.java revision 12651:6ef01bd40ce2
1/*
2 * Copyright (c) 2015, 2016, 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 */
23package org.graalvm.compiler.hotspot.meta;
24
25import static org.graalvm.compiler.core.common.LocationIdentity.any;
26import static org.graalvm.compiler.hotspot.word.HotSpotOperation.HotspotOpcode.POINTER_EQ;
27import static org.graalvm.compiler.hotspot.word.HotSpotOperation.HotspotOpcode.POINTER_NE;
28import static org.graalvm.compiler.nodes.ConstantNode.forBoolean;
29
30import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
31import org.graalvm.compiler.bytecode.BridgeMethodUtils;
32import org.graalvm.compiler.core.common.LocationIdentity;
33import org.graalvm.compiler.core.common.type.Stamp;
34import org.graalvm.compiler.core.common.type.StampFactory;
35import org.graalvm.compiler.debug.GraalError;
36import org.graalvm.compiler.hotspot.nodes.LoadIndexedPointerNode;
37import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp;
38import org.graalvm.compiler.hotspot.nodes.type.MetaspacePointerStamp;
39import org.graalvm.compiler.hotspot.nodes.type.MethodPointerStamp;
40import org.graalvm.compiler.hotspot.word.HotSpotOperation;
41import org.graalvm.compiler.hotspot.word.HotSpotOperation.HotspotOpcode;
42import org.graalvm.compiler.hotspot.word.PointerCastNode;
43import org.graalvm.compiler.nodes.AbstractBeginNode;
44import org.graalvm.compiler.nodes.LogicNode;
45import org.graalvm.compiler.nodes.ValueNode;
46import org.graalvm.compiler.nodes.calc.ConditionalNode;
47import org.graalvm.compiler.nodes.calc.IsNullNode;
48import org.graalvm.compiler.nodes.calc.PointerEqualsNode;
49import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
50import org.graalvm.compiler.nodes.java.LoadIndexedNode;
51import org.graalvm.compiler.nodes.memory.HeapAccess.BarrierType;
52import org.graalvm.compiler.nodes.memory.ReadNode;
53import org.graalvm.compiler.nodes.memory.address.AddressNode;
54import org.graalvm.compiler.nodes.type.StampTool;
55import org.graalvm.compiler.replacements.WordOperationPlugin;
56import org.graalvm.compiler.word.WordTypes;
57
58import jdk.vm.ci.meta.JavaKind;
59import jdk.vm.ci.meta.ResolvedJavaMethod;
60import jdk.vm.ci.meta.ResolvedJavaType;
61
62/**
63 * Extends {@link WordOperationPlugin} to handle {@linkplain HotSpotOperation HotSpot word
64 * operations}.
65 */
66class HotSpotWordOperationPlugin extends WordOperationPlugin {
67    HotSpotWordOperationPlugin(SnippetReflectionProvider snippetReflection, WordTypes wordTypes) {
68        super(snippetReflection, wordTypes);
69    }
70
71    @Override
72    protected LoadIndexedNode createLoadIndexedNode(ValueNode array, ValueNode index) {
73        ResolvedJavaType arrayType = StampTool.typeOrNull(array);
74        Stamp componentStamp = wordTypes.getWordStamp(arrayType.getComponentType());
75        if (componentStamp instanceof MetaspacePointerStamp) {
76            return new LoadIndexedPointerNode(componentStamp, array, index);
77        } else {
78            return super.createLoadIndexedNode(array, index);
79        }
80    }
81
82    @Override
83    public boolean handleInvoke(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) {
84        if (!wordTypes.isWordOperation(method)) {
85            return false;
86        }
87
88        HotSpotOperation operation = BridgeMethodUtils.getAnnotation(HotSpotOperation.class, method);
89        if (operation == null) {
90            processWordOperation(b, args, wordTypes.getWordOperation(method, b.getMethod().getDeclaringClass()));
91            return true;
92        }
93        processHotSpotWordOperation(b, method, args, operation);
94        return true;
95    }
96
97    protected void processHotSpotWordOperation(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args, HotSpotOperation operation) {
98        JavaKind returnKind = method.getSignature().getReturnKind();
99        switch (operation.opcode()) {
100            case POINTER_EQ:
101            case POINTER_NE:
102                assert args.length == 2;
103                HotspotOpcode opcode = operation.opcode();
104                ValueNode left = args[0];
105                ValueNode right = args[1];
106                assert left.stamp() instanceof MetaspacePointerStamp : left + " " + left.stamp();
107                assert right.stamp() instanceof MetaspacePointerStamp : right + " " + right.stamp();
108                assert opcode == POINTER_EQ || opcode == POINTER_NE;
109
110                PointerEqualsNode comparison = b.add(new PointerEqualsNode(left, right));
111                ValueNode eqValue = b.add(forBoolean(opcode == POINTER_EQ));
112                ValueNode neValue = b.add(forBoolean(opcode == POINTER_NE));
113                b.addPush(returnKind, new ConditionalNode(comparison, eqValue, neValue));
114                break;
115
116            case IS_NULL:
117                assert args.length == 1;
118                ValueNode pointer = args[0];
119                assert pointer.stamp() instanceof MetaspacePointerStamp;
120
121                LogicNode isNull = b.add(IsNullNode.create(pointer));
122                b.addPush(returnKind, new ConditionalNode(isNull, b.add(forBoolean(true)), b.add(forBoolean(false))));
123                break;
124
125            case FROM_POINTER:
126                assert args.length == 1;
127                b.addPush(returnKind, new PointerCastNode(StampFactory.forKind(wordKind), args[0]));
128                break;
129
130            case TO_KLASS_POINTER:
131                assert args.length == 1;
132                b.addPush(returnKind, new PointerCastNode(KlassPointerStamp.klass(), args[0]));
133                break;
134
135            case TO_METHOD_POINTER:
136                assert args.length == 1;
137                b.addPush(returnKind, new PointerCastNode(MethodPointerStamp.method(), args[0]));
138                break;
139
140            case READ_KLASS_POINTER:
141                assert args.length == 2 || args.length == 3;
142                Stamp readStamp = KlassPointerStamp.klass();
143                AddressNode address = makeAddress(b, args[0], args[1]);
144                LocationIdentity location;
145                if (args.length == 2) {
146                    location = any();
147                } else {
148                    assert args[2].isConstant();
149                    location = snippetReflection.asObject(LocationIdentity.class, args[2].asJavaConstant());
150                }
151                ReadNode read = b.add(new ReadNode(address, location, readStamp, BarrierType.NONE));
152                /*
153                 * The read must not float outside its block otherwise it may float above an
154                 * explicit zero check on its base address.
155                 */
156                read.setGuard(AbstractBeginNode.prevBegin(read));
157                b.push(returnKind, read);
158                break;
159
160            default:
161                throw GraalError.shouldNotReachHere("unknown operation: " + operation.opcode());
162        }
163    }
164}
165