1/*
2 * Copyright (c) 2015, 2017, 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.nodes;
24
25import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
26import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG;
27import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_1;
28import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1;
29
30import org.graalvm.compiler.api.replacements.Fold;
31import org.graalvm.compiler.api.replacements.Fold.InjectedParameter;
32import org.graalvm.compiler.core.common.type.Stamp;
33import org.graalvm.compiler.core.common.type.StampFactory;
34import org.graalvm.compiler.graph.Node;
35import org.graalvm.compiler.graph.NodeClass;
36import org.graalvm.compiler.graph.spi.Canonicalizable;
37import org.graalvm.compiler.graph.spi.CanonicalizerTool;
38import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
39import org.graalvm.compiler.hotspot.HotSpotLIRGenerator;
40import org.graalvm.compiler.nodeinfo.NodeInfo;
41import org.graalvm.compiler.nodes.ConstantNode;
42import org.graalvm.compiler.nodes.calc.FloatingNode;
43import org.graalvm.compiler.nodes.spi.LIRLowerable;
44import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
45
46import jdk.vm.ci.meta.JavaKind;
47import jdk.vm.ci.meta.Value;
48
49/**
50 * Represents {@link GraalHotSpotVMConfig} values that may change after compilation.
51 */
52@NodeInfo(cycles = CYCLES_1, size = SIZE_1)
53public class GraalHotSpotVMConfigNode extends FloatingNode implements LIRLowerable, Canonicalizable {
54    public static final NodeClass<GraalHotSpotVMConfigNode> TYPE = NodeClass.create(GraalHotSpotVMConfigNode.class);
55
56    private final GraalHotSpotVMConfig config;
57    protected final int markId;
58
59    /**
60     * Constructor for {@link #areConfigValuesConstant()}.
61     *
62     * @param config
63     */
64    public GraalHotSpotVMConfigNode(@InjectedNodeParameter GraalHotSpotVMConfig config) {
65        super(TYPE, StampFactory.forKind(JavaKind.Boolean));
66        this.config = config;
67        this.markId = 0;
68    }
69
70    /**
71     * Constructor for node intrinsics below.
72     *
73     * @param config
74     * @param markId id of the config value
75     */
76    public GraalHotSpotVMConfigNode(@InjectedNodeParameter Stamp stamp, @InjectedNodeParameter GraalHotSpotVMConfig config, int markId) {
77        super(TYPE, stamp);
78        this.config = config;
79        this.markId = markId;
80    }
81
82    /**
83     * Constructor with explicit type specification.
84     *
85     * @param config
86     * @param markId id of the config value
87     * @param kind explicit type of the node
88     */
89    public GraalHotSpotVMConfigNode(GraalHotSpotVMConfig config, int markId, JavaKind kind) {
90        super(TYPE, StampFactory.forKind(kind));
91        this.config = config;
92        this.markId = markId;
93    }
94
95    @Override
96    public void generate(NodeLIRBuilderTool generator) {
97        Value res = ((HotSpotLIRGenerator) generator.getLIRGeneratorTool()).emitLoadConfigValue(markId, generator.getLIRGeneratorTool().getLIRKind(stamp));
98        generator.setResult(this, res);
99    }
100
101    @NodeIntrinsic
102    private static native boolean areConfigValuesConstant();
103
104    @NodeIntrinsic
105    private static native long loadLongConfigValue(@ConstantNodeParameter int markId);
106
107    @NodeIntrinsic
108    private static native int loadIntConfigValue(@ConstantNodeParameter int markId);
109
110    @NodeIntrinsic
111    private static native byte loadByteConfigValue(@ConstantNodeParameter int markId);
112
113    public static long cardTableAddress() {
114        return loadLongConfigValue(cardTableAddressMark(INJECTED_VMCONFIG));
115    }
116
117    public static boolean isCardTableAddressConstant() {
118        return areConfigValuesConstant();
119    }
120
121    public static long heapTopAddress() {
122        return loadLongConfigValue(heapTopAddressMark(INJECTED_VMCONFIG));
123    }
124
125    public static long heapEndAddress() {
126        return loadLongConfigValue(heapEndAddressMark(INJECTED_VMCONFIG));
127    }
128
129    public static long crcTableAddress() {
130        return loadLongConfigValue(crcTableAddressMark(INJECTED_VMCONFIG));
131    }
132
133    public static int logOfHeapRegionGrainBytes() {
134        return loadIntConfigValue(logOfHeapRegionGrainBytesMark(INJECTED_VMCONFIG));
135    }
136
137    public static boolean inlineContiguousAllocationSupported() {
138        return loadByteConfigValue(inlineContiguousAllocationSupportedMark(INJECTED_VMCONFIG)) != 0;
139    }
140
141    @Fold
142    public static int cardTableAddressMark(@InjectedParameter GraalHotSpotVMConfig config) {
143        return config.MARKID_CARD_TABLE_ADDRESS;
144    }
145
146    @Fold
147    public static int heapTopAddressMark(@InjectedParameter GraalHotSpotVMConfig config) {
148        return config.MARKID_HEAP_TOP_ADDRESS;
149    }
150
151    @Fold
152    public static int heapEndAddressMark(@InjectedParameter GraalHotSpotVMConfig config) {
153        return config.MARKID_HEAP_END_ADDRESS;
154    }
155
156    @Fold
157    public static int crcTableAddressMark(@InjectedParameter GraalHotSpotVMConfig config) {
158        return config.MARKID_CRC_TABLE_ADDRESS;
159    }
160
161    @Fold
162    public static int logOfHeapRegionGrainBytesMark(@InjectedParameter GraalHotSpotVMConfig config) {
163        return config.MARKID_LOG_OF_HEAP_REGION_GRAIN_BYTES;
164    }
165
166    @Fold
167    public static int inlineContiguousAllocationSupportedMark(@InjectedParameter GraalHotSpotVMConfig config) {
168        return config.MARKID_INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED;
169    }
170
171    @Override
172    public Node canonical(CanonicalizerTool tool) {
173        if (markId == 0) {
174            return ConstantNode.forBoolean(!GeneratePIC.getValue(tool.getOptions()));
175        }
176        if (!GeneratePIC.getValue(tool.getOptions())) {
177            if (markId == config.MARKID_CARD_TABLE_ADDRESS) {
178                return ConstantNode.forLong(config.cardtableStartAddress);
179            } else if (markId == config.MARKID_HEAP_TOP_ADDRESS) {
180                return ConstantNode.forLong(config.heapTopAddress);
181            } else if (markId == config.MARKID_HEAP_END_ADDRESS) {
182                return ConstantNode.forLong(config.heapEndAddress);
183            } else if (markId == config.MARKID_CRC_TABLE_ADDRESS) {
184                return ConstantNode.forLong(config.crcTableAddress);
185            } else if (markId == config.MARKID_LOG_OF_HEAP_REGION_GRAIN_BYTES) {
186                return ConstantNode.forInt(config.logOfHRGrainBytes);
187            } else if (markId == config.MARKID_INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED) {
188                return ConstantNode.forBoolean(config.inlineContiguousAllocationSupported);
189            } else {
190                assert false;
191            }
192        }
193        return this;
194    }
195}
196