< prev index next >

src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/VirtualizerToolImpl.java

Print this page
rev 52509 : [mq]: graal2


  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);


< prev index next >