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
24
25 package org.graalvm.compiler.virtual.phases.ea;
26
27 import static org.graalvm.compiler.core.common.GraalOptions.MaximumEscapeAnalysisArrayLength;
28
29 import java.util.List;
30
31 import org.graalvm.compiler.core.common.spi.ArrayOffsetProvider;
32 import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
33 import org.graalvm.compiler.debug.DebugContext;
34 import org.graalvm.compiler.graph.Node;
35 import org.graalvm.compiler.graph.spi.CanonicalizerTool;
36 import org.graalvm.compiler.nodes.ConstantNode;
37 import org.graalvm.compiler.nodes.FixedNode;
38 import org.graalvm.compiler.nodes.FixedWithNextNode;
39 import org.graalvm.compiler.nodes.NodeView;
40 import org.graalvm.compiler.nodes.ValueNode;
41 import org.graalvm.compiler.nodes.calc.FloatingNode;
42 import org.graalvm.compiler.nodes.calc.UnpackEndianHalfNode;
43 import org.graalvm.compiler.nodes.java.MonitorIdNode;
44 import org.graalvm.compiler.nodes.spi.LoweringProvider;
45 import org.graalvm.compiler.nodes.spi.VirtualizerTool;
46 import org.graalvm.compiler.nodes.virtual.VirtualInstanceNode;
47 import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
48 import org.graalvm.compiler.options.OptionValues;
49
50 import jdk.vm.ci.meta.Assumptions;
51 import jdk.vm.ci.meta.ConstantReflectionProvider;
80 this.loweringProvider = loweringProvider;
81 }
82
83 private boolean deleted;
84 private PartialEscapeBlockState<?> state;
85 private ValueNode current;
86 private FixedNode position;
87 private GraphEffectList effects;
88
89 @Override
90 public OptionValues getOptions() {
91 return options;
92 }
93
94 @Override
95 public DebugContext getDebug() {
96 return debug;
97 }
98
99 @Override
100 public MetaAccessProvider getMetaAccessProvider() {
101 return metaAccess;
102 }
103
104 @Override
105 public ConstantReflectionProvider getConstantReflectionProvider() {
106 return constantReflection;
107 }
108
109 @Override
110 public ConstantFieldProvider getConstantFieldProvider() {
111 return constantFieldProvider;
112 }
113
114 @Override
115 public ArrayOffsetProvider getArrayOffsetProvider() {
116 return loweringProvider;
117 }
118
119 public void reset(PartialEscapeBlockState<?> newState, ValueNode newCurrent, FixedNode newPosition, GraphEffectList newEffects) {
120 deleted = false;
121 state = newState;
122 current = newCurrent;
123 position = newPosition;
124 effects = newEffects;
125 }
126
127 public boolean isDeleted() {
128 return deleted;
129 }
130
131 @Override
132 public ValueNode getAlias(ValueNode value) {
133 return closure.getAliasAndResolve(state, value);
134 }
135
136 @Override
137 public ValueNode getEntry(VirtualObjectNode virtualObject, int index) {
138 return state.getObjectState(virtualObject).getEntry(index);
151 newValue = closure.getAliasAndResolve(state, value);
152 }
153 getDebug().log(DebugContext.DETAILED_LEVEL, "Setting entry %d in virtual object %s %s results in %s", index, virtual.getObjectId(), virtual, state.getObjectState(virtual.getObjectId()));
154 ValueNode oldValue = getEntry(virtual, index);
155 boolean canVirtualize = entryKind == accessKind || (entryKind == accessKind.getStackKind() && virtual instanceof VirtualInstanceNode);
156 if (!canVirtualize) {
157 if (entryKind == JavaKind.Long && oldValue.getStackKind() == newValue.getStackKind() && oldValue.getStackKind().isPrimitive()) {
158 /*
159 * Special case: If the entryKind is long, allow arbitrary kinds as long as a value
160 * of the same kind is already there. This can only happen if some other node
161 * initialized the entry with a value of a different kind. One example where this
162 * happens is the Truffle NewFrameNode.
163 */
164 getDebug().log(DebugContext.DETAILED_LEVEL, "virtualizing %s with primitive of kind %s in long entry ", current, oldValue.getStackKind());
165 canVirtualize = true;
166 } else if (entryKind == JavaKind.Int && (accessKind == JavaKind.Long || accessKind == JavaKind.Double) && offset % 8 == 0) {
167 /*
168 * Special case: Allow storing a single long or double value into two consecutive
169 * int slots.
170 */
171 int nextIndex = virtual.entryIndexForOffset(getArrayOffsetProvider(), offset + 4, JavaKind.Int);
172 if (nextIndex != -1) {
173 canVirtualize = true;
174 assert nextIndex == index + 1 : "expected to be sequential";
175 getDebug().log(DebugContext.DETAILED_LEVEL, "virtualizing %s for double word stored in two ints", current);
176 }
177 }
178 }
179
180 if (canVirtualize) {
181 getDebug().log(DebugContext.DETAILED_LEVEL, "virtualizing %s for entryKind %s and access kind %s", current, entryKind, accessKind);
182 state.setEntry(virtual.getObjectId(), index, newValue);
183 if (entryKind == JavaKind.Int) {
184 if (accessKind.needsTwoSlots()) {
185 // Storing double word value two int slots
186 assert virtual.entryKind(index + 1) == JavaKind.Int;
187 state.setEntry(virtual.getObjectId(), index + 1, getIllegalConstant());
188 } else if (oldValue.getStackKind() == JavaKind.Double || oldValue.getStackKind() == JavaKind.Long) {
189 // Splitting double word constant by storing over it with an int
190 getDebug().log(DebugContext.DETAILED_LEVEL, "virtualizing %s producing second half of double word value %s", current, oldValue);
191 ValueNode secondHalf = UnpackEndianHalfNode.create(oldValue, false, NodeView.DEFAULT);
193 state.setEntry(virtual.getObjectId(), index + 1, secondHalf);
194 }
195 }
196 if (oldValue.isConstant() && oldValue.asConstant().equals(JavaConstant.forIllegal())) {
197 // Storing into second half of double, so replace previous value
198 ValueNode previous = getEntry(virtual, index - 1);
199 getDebug().log(DebugContext.DETAILED_LEVEL, "virtualizing %s producing first half of double word value %s", current, previous);
200 ValueNode firstHalf = UnpackEndianHalfNode.create(previous, true, NodeView.DEFAULT);
201 addNode(firstHalf);
202 state.setEntry(virtual.getObjectId(), index - 1, firstHalf);
203 }
204 return true;
205 }
206 // Should only occur if there are mismatches between the entry and access kind
207 assert entryKind != accessKind;
208 return false;
209 }
210
211 private ValueNode getIllegalConstant() {
212 if (illegalConstant == null) {
213 illegalConstant = ConstantNode.forConstant(JavaConstant.forIllegal(), getMetaAccessProvider());
214 addNode(illegalConstant);
215 }
216 return illegalConstant;
217 }
218
219 @Override
220 public void setEnsureVirtualized(VirtualObjectNode virtualObject, boolean ensureVirtualized) {
221 int id = virtualObject.getObjectId();
222 state.setEnsureVirtualized(id, ensureVirtualized);
223 }
224
225 @Override
226 public boolean getEnsureVirtualized(VirtualObjectNode virtualObject) {
227 return state.getObjectState(virtualObject).getEnsureVirtualized();
228 }
229
230 @Override
231 public void replaceWithVirtual(VirtualObjectNode virtual) {
232 closure.addVirtualAlias(virtual, current);
233 effects.deleteNode(current);
|
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
24
25 package org.graalvm.compiler.virtual.phases.ea;
26
27 import static org.graalvm.compiler.core.common.GraalOptions.MaximumEscapeAnalysisArrayLength;
28
29 import java.util.List;
30
31 import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
32 import org.graalvm.compiler.debug.DebugContext;
33 import org.graalvm.compiler.graph.Node;
34 import org.graalvm.compiler.graph.spi.CanonicalizerTool;
35 import org.graalvm.compiler.nodes.ConstantNode;
36 import org.graalvm.compiler.nodes.FixedNode;
37 import org.graalvm.compiler.nodes.FixedWithNextNode;
38 import org.graalvm.compiler.nodes.NodeView;
39 import org.graalvm.compiler.nodes.ValueNode;
40 import org.graalvm.compiler.nodes.calc.FloatingNode;
41 import org.graalvm.compiler.nodes.calc.UnpackEndianHalfNode;
42 import org.graalvm.compiler.nodes.java.MonitorIdNode;
43 import org.graalvm.compiler.nodes.spi.LoweringProvider;
44 import org.graalvm.compiler.nodes.spi.VirtualizerTool;
45 import org.graalvm.compiler.nodes.virtual.VirtualInstanceNode;
46 import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
47 import org.graalvm.compiler.options.OptionValues;
48
49 import jdk.vm.ci.meta.Assumptions;
50 import jdk.vm.ci.meta.ConstantReflectionProvider;
79 this.loweringProvider = loweringProvider;
80 }
81
82 private boolean deleted;
83 private PartialEscapeBlockState<?> state;
84 private ValueNode current;
85 private FixedNode position;
86 private GraphEffectList effects;
87
88 @Override
89 public OptionValues getOptions() {
90 return options;
91 }
92
93 @Override
94 public DebugContext getDebug() {
95 return debug;
96 }
97
98 @Override
99 public ConstantFieldProvider getConstantFieldProvider() {
100 return constantFieldProvider;
101 }
102
103 public void reset(PartialEscapeBlockState<?> newState, ValueNode newCurrent, FixedNode newPosition, GraphEffectList newEffects) {
104 deleted = false;
105 state = newState;
106 current = newCurrent;
107 position = newPosition;
108 effects = newEffects;
109 }
110
111 public boolean isDeleted() {
112 return deleted;
113 }
114
115 @Override
116 public ValueNode getAlias(ValueNode value) {
117 return closure.getAliasAndResolve(state, value);
118 }
119
120 @Override
121 public ValueNode getEntry(VirtualObjectNode virtualObject, int index) {
122 return state.getObjectState(virtualObject).getEntry(index);
135 newValue = closure.getAliasAndResolve(state, value);
136 }
137 getDebug().log(DebugContext.DETAILED_LEVEL, "Setting entry %d in virtual object %s %s results in %s", index, virtual.getObjectId(), virtual, state.getObjectState(virtual.getObjectId()));
138 ValueNode oldValue = getEntry(virtual, index);
139 boolean canVirtualize = entryKind == accessKind || (entryKind == accessKind.getStackKind() && virtual instanceof VirtualInstanceNode);
140 if (!canVirtualize) {
141 if (entryKind == JavaKind.Long && oldValue.getStackKind() == newValue.getStackKind() && oldValue.getStackKind().isPrimitive()) {
142 /*
143 * Special case: If the entryKind is long, allow arbitrary kinds as long as a value
144 * of the same kind is already there. This can only happen if some other node
145 * initialized the entry with a value of a different kind. One example where this
146 * happens is the Truffle NewFrameNode.
147 */
148 getDebug().log(DebugContext.DETAILED_LEVEL, "virtualizing %s with primitive of kind %s in long entry ", current, oldValue.getStackKind());
149 canVirtualize = true;
150 } else if (entryKind == JavaKind.Int && (accessKind == JavaKind.Long || accessKind == JavaKind.Double) && offset % 8 == 0) {
151 /*
152 * Special case: Allow storing a single long or double value into two consecutive
153 * int slots.
154 */
155 int nextIndex = virtual.entryIndexForOffset(getMetaAccess(), offset + 4, JavaKind.Int);
156 if (nextIndex != -1) {
157 canVirtualize = true;
158 assert nextIndex == index + 1 : "expected to be sequential";
159 getDebug().log(DebugContext.DETAILED_LEVEL, "virtualizing %s for double word stored in two ints", current);
160 }
161 }
162 }
163
164 if (canVirtualize) {
165 getDebug().log(DebugContext.DETAILED_LEVEL, "virtualizing %s for entryKind %s and access kind %s", current, entryKind, accessKind);
166 state.setEntry(virtual.getObjectId(), index, newValue);
167 if (entryKind == JavaKind.Int) {
168 if (accessKind.needsTwoSlots()) {
169 // Storing double word value two int slots
170 assert virtual.entryKind(index + 1) == JavaKind.Int;
171 state.setEntry(virtual.getObjectId(), index + 1, getIllegalConstant());
172 } else if (oldValue.getStackKind() == JavaKind.Double || oldValue.getStackKind() == JavaKind.Long) {
173 // Splitting double word constant by storing over it with an int
174 getDebug().log(DebugContext.DETAILED_LEVEL, "virtualizing %s producing second half of double word value %s", current, oldValue);
175 ValueNode secondHalf = UnpackEndianHalfNode.create(oldValue, false, NodeView.DEFAULT);
177 state.setEntry(virtual.getObjectId(), index + 1, secondHalf);
178 }
179 }
180 if (oldValue.isConstant() && oldValue.asConstant().equals(JavaConstant.forIllegal())) {
181 // Storing into second half of double, so replace previous value
182 ValueNode previous = getEntry(virtual, index - 1);
183 getDebug().log(DebugContext.DETAILED_LEVEL, "virtualizing %s producing first half of double word value %s", current, previous);
184 ValueNode firstHalf = UnpackEndianHalfNode.create(previous, true, NodeView.DEFAULT);
185 addNode(firstHalf);
186 state.setEntry(virtual.getObjectId(), index - 1, firstHalf);
187 }
188 return true;
189 }
190 // Should only occur if there are mismatches between the entry and access kind
191 assert entryKind != accessKind;
192 return false;
193 }
194
195 private ValueNode getIllegalConstant() {
196 if (illegalConstant == null) {
197 illegalConstant = ConstantNode.forConstant(JavaConstant.forIllegal(), getMetaAccess());
198 addNode(illegalConstant);
199 }
200 return illegalConstant;
201 }
202
203 @Override
204 public void setEnsureVirtualized(VirtualObjectNode virtualObject, boolean ensureVirtualized) {
205 int id = virtualObject.getObjectId();
206 state.setEnsureVirtualized(id, ensureVirtualized);
207 }
208
209 @Override
210 public boolean getEnsureVirtualized(VirtualObjectNode virtualObject) {
211 return state.getObjectState(virtualObject).getEnsureVirtualized();
212 }
213
214 @Override
215 public void replaceWithVirtual(VirtualObjectNode virtual) {
216 closure.addVirtualAlias(virtual, current);
217 effects.deleteNode(current);
|