< prev index next >
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationClosure.java
Print this page
*** 29,39 ****
import java.util.Iterator;
import java.util.List;
import org.graalvm.compiler.core.common.cfg.Loop;
import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
- import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.nodes.AbstractBeginNode;
import org.graalvm.compiler.nodes.FieldLocationIdentity;
import org.graalvm.compiler.nodes.FixedNode;
import org.graalvm.compiler.nodes.FixedWithNextNode;
--- 29,38 ----
*** 129,208 ****
}
return false;
}
! private boolean processStore(FixedNode store, ValueNode object, LocationIdentity identity, int index, JavaKind kind, ValueNode value, PEReadEliminationBlockState state, GraphEffectList effects) {
ValueNode unproxiedObject = GraphUtil.unproxify(object);
! ValueNode cachedValue = state.getReadCache(object, identity, index, kind, this);
ValueNode finalValue = getScalarAlias(value);
boolean result = false;
if (GraphUtil.unproxify(finalValue) == GraphUtil.unproxify(cachedValue)) {
effects.deleteNode(store);
result = true;
}
state.killReadCache(identity, index);
! state.addReadCache(unproxiedObject, identity, index, kind, finalValue, this);
return result;
}
private boolean processLoad(FixedNode load, ValueNode object, LocationIdentity identity, int index, JavaKind kind, PEReadEliminationBlockState state, GraphEffectList effects) {
ValueNode unproxiedObject = GraphUtil.unproxify(object);
ValueNode cachedValue = state.getReadCache(unproxiedObject, identity, index, kind, this);
if (cachedValue != null) {
- Stamp loadStamp = load.stamp();
- Stamp cachedValueStamp = cachedValue.stamp();
- if (!loadStamp.isCompatible(cachedValueStamp)) {
- /*
- * Can either be the first field of a two slot write to a one slot field which would
- * have a non compatible stamp or the second load which will see Illegal.
- */
- assert load.stamp().getStackKind() == JavaKind.Int && (cachedValue.stamp().getStackKind() == JavaKind.Long || cachedValue.getStackKind() == JavaKind.Double ||
- cachedValue.getStackKind() == JavaKind.Illegal) : "Can only allow different stack kind two slot marker writes on one slot fields.";
- return false;
- } else {
// perform the read elimination
effects.replaceAtUsages(load, cachedValue, load);
addScalarAlias(load, cachedValue);
return true;
- }
} else {
! state.addReadCache(unproxiedObject, identity, index, kind, load, this);
return false;
}
}
private boolean processUnsafeLoad(RawLoadNode load, PEReadEliminationBlockState state, GraphEffectList effects) {
if (load.offset().isConstant()) {
ResolvedJavaType type = StampTool.typeOrNull(load.object());
if (type != null && type.isArray()) {
long offset = load.offset().asJavaConstant().asLong();
! int index = VirtualArrayNode.entryIndexForOffset(offset, load.accessKind(), type.getComponentType(), Integer.MAX_VALUE);
ValueNode object = GraphUtil.unproxify(load.object());
! LocationIdentity location = NamedLocationIdentity.getArrayLocation(type.getComponentType().getJavaKind());
! ValueNode cachedValue = state.getReadCache(object, location, index, load.accessKind(), this);
! if (cachedValue != null && load.stamp().isCompatible(cachedValue.stamp())) {
effects.replaceAtUsages(load, cachedValue, load);
addScalarAlias(load, cachedValue);
return true;
} else {
! state.addReadCache(object, location, index, load.accessKind(), load, this);
}
}
}
return false;
}
private boolean processUnsafeStore(RawStoreNode store, PEReadEliminationBlockState state, GraphEffectList effects) {
ResolvedJavaType type = StampTool.typeOrNull(store.object());
if (type != null && type.isArray()) {
! LocationIdentity location = NamedLocationIdentity.getArrayLocation(type.getComponentType().getJavaKind());
if (store.offset().isConstant()) {
long offset = store.offset().asJavaConstant().asLong();
! int index = VirtualArrayNode.entryIndexForOffset(offset, store.accessKind(), type.getComponentType(), Integer.MAX_VALUE);
! return processStore(store, store.object(), location, index, store.accessKind(), store.value(), state, effects);
} else {
processIdentity(state, location);
}
} else {
state.killReadCache();
--- 128,220 ----
}
return false;
}
! private boolean processStore(FixedNode store, ValueNode object, LocationIdentity identity, int index, JavaKind accessKind, boolean overflowAccess, ValueNode value,
! PEReadEliminationBlockState state, GraphEffectList effects) {
ValueNode unproxiedObject = GraphUtil.unproxify(object);
! ValueNode cachedValue = state.getReadCache(object, identity, index, accessKind, this);
ValueNode finalValue = getScalarAlias(value);
boolean result = false;
if (GraphUtil.unproxify(finalValue) == GraphUtil.unproxify(cachedValue)) {
effects.deleteNode(store);
result = true;
}
state.killReadCache(identity, index);
! state.addReadCache(unproxiedObject, identity, index, accessKind, overflowAccess, finalValue, this);
return result;
}
private boolean processLoad(FixedNode load, ValueNode object, LocationIdentity identity, int index, JavaKind kind, PEReadEliminationBlockState state, GraphEffectList effects) {
ValueNode unproxiedObject = GraphUtil.unproxify(object);
ValueNode cachedValue = state.getReadCache(unproxiedObject, identity, index, kind, this);
if (cachedValue != null) {
// perform the read elimination
effects.replaceAtUsages(load, cachedValue, load);
addScalarAlias(load, cachedValue);
return true;
} else {
! state.addReadCache(unproxiedObject, identity, index, kind, false, load, this);
return false;
}
}
+ private static boolean isOverflowAccess(JavaKind accessKind, JavaKind declaredKind) {
+ if (accessKind == declaredKind) {
+ return false;
+ }
+ if (accessKind == JavaKind.Object) {
+ switch (declaredKind) {
+ case Object:
+ case Double:
+ case Long:
+ return false;
+ default:
+ return true;
+ }
+ }
+ assert accessKind.isPrimitive() : "Illegal access kind";
+ return declaredKind.isPrimitive() ? accessKind.getBitCount() > declaredKind.getBitCount() : true;
+ }
+
private boolean processUnsafeLoad(RawLoadNode load, PEReadEliminationBlockState state, GraphEffectList effects) {
if (load.offset().isConstant()) {
ResolvedJavaType type = StampTool.typeOrNull(load.object());
if (type != null && type.isArray()) {
+ JavaKind accessKind = load.accessKind();
+ JavaKind componentKind = type.getComponentType().getJavaKind();
long offset = load.offset().asJavaConstant().asLong();
! int index = VirtualArrayNode.entryIndexForOffset(offset, accessKind, type.getComponentType(), Integer.MAX_VALUE);
ValueNode object = GraphUtil.unproxify(load.object());
! LocationIdentity location = NamedLocationIdentity.getArrayLocation(componentKind);
! ValueNode cachedValue = state.getReadCache(object, location, index, accessKind, this);
! assert cachedValue == null || load.stamp().isCompatible(cachedValue.stamp()) : "The RawLoadNode's stamp is not compatible with the cached value.";
! if (cachedValue != null) {
effects.replaceAtUsages(load, cachedValue, load);
addScalarAlias(load, cachedValue);
return true;
} else {
! state.addReadCache(object, location, index, accessKind, isOverflowAccess(accessKind, componentKind), load, this);
}
}
}
return false;
}
private boolean processUnsafeStore(RawStoreNode store, PEReadEliminationBlockState state, GraphEffectList effects) {
ResolvedJavaType type = StampTool.typeOrNull(store.object());
if (type != null && type.isArray()) {
! JavaKind accessKind = store.accessKind();
! JavaKind componentKind = type.getComponentType().getJavaKind();
! LocationIdentity location = NamedLocationIdentity.getArrayLocation(componentKind);
if (store.offset().isConstant()) {
long offset = store.offset().asJavaConstant().asLong();
! boolean overflowAccess = isOverflowAccess(accessKind, componentKind);
! int index = overflowAccess ? -1 : VirtualArrayNode.entryIndexForOffset(offset, accessKind, type.getComponentType(), Integer.MAX_VALUE);
! return processStore(store, store.object(), location, index, accessKind, overflowAccess, store.value(), state, effects);
} else {
processIdentity(state, location);
}
} else {
state.killReadCache();
*** 217,253 ****
private boolean processStoreField(StoreFieldNode store, PEReadEliminationBlockState state, GraphEffectList effects) {
if (store.isVolatile()) {
state.killReadCache();
return false;
}
! return processStore(store, store.object(), new FieldLocationIdentity(store.field()), -1, store.field().getJavaKind(), store.value(), state, effects);
}
private boolean processLoadField(LoadFieldNode load, PEReadEliminationBlockState state, GraphEffectList effects) {
if (load.isVolatile()) {
state.killReadCache();
return false;
}
return processLoad(load, load.object(), new FieldLocationIdentity(load.field()), -1, load.field().getJavaKind(), state, effects);
}
private boolean processStoreIndexed(StoreIndexedNode store, PEReadEliminationBlockState state, GraphEffectList effects) {
! LocationIdentity arrayLocation = NamedLocationIdentity.getArrayLocation(store.elementKind());
! if (store.index().isConstant()) {
! int index = ((JavaConstant) store.index().asConstant()).asInt();
! return processStore(store, store.array(), arrayLocation, index, store.elementKind(), store.value(), state, effects);
} else {
state.killReadCache(arrayLocation, -1);
}
return false;
}
private boolean processLoadIndexed(LoadIndexedNode load, PEReadEliminationBlockState state, GraphEffectList effects) {
if (load.index().isConstant()) {
int index = ((JavaConstant) load.index().asConstant()).asInt();
! LocationIdentity arrayLocation = NamedLocationIdentity.getArrayLocation(load.elementKind());
! return processLoad(load, load.array(), arrayLocation, index, load.elementKind(), state, effects);
}
return false;
}
private boolean processUnbox(UnboxNode unbox, PEReadEliminationBlockState state, GraphEffectList effects) {
--- 229,296 ----
private boolean processStoreField(StoreFieldNode store, PEReadEliminationBlockState state, GraphEffectList effects) {
if (store.isVolatile()) {
state.killReadCache();
return false;
}
! JavaKind kind = store.field().getJavaKind();
! return processStore(store, store.object(), new FieldLocationIdentity(store.field()), -1, kind, false, store.value(), state, effects);
}
private boolean processLoadField(LoadFieldNode load, PEReadEliminationBlockState state, GraphEffectList effects) {
if (load.isVolatile()) {
state.killReadCache();
return false;
}
return processLoad(load, load.object(), new FieldLocationIdentity(load.field()), -1, load.field().getJavaKind(), state, effects);
}
+ private static JavaKind getElementKindFromStamp(ValueNode array) {
+ ResolvedJavaType type = StampTool.typeOrNull(array);
+ if (type != null && type.isArray()) {
+ return type.getComponentType().getJavaKind();
+ } else {
+ // It is likely an OSRLocal without valid stamp
+ return JavaKind.Illegal;
+ }
+ }
+
private boolean processStoreIndexed(StoreIndexedNode store, PEReadEliminationBlockState state, GraphEffectList effects) {
! int index = store.index().isConstant() ? ((JavaConstant) store.index().asConstant()).asInt() : -1;
! // BASTORE (with elementKind being Byte) can be used to store values in boolean arrays.
! JavaKind elementKind = store.elementKind();
! if (elementKind == JavaKind.Byte) {
! elementKind = getElementKindFromStamp(store.array());
! if (elementKind == JavaKind.Illegal) {
! // Could not determine the actual access kind from stamp. Hence kill both.
! state.killReadCache(NamedLocationIdentity.getArrayLocation(JavaKind.Boolean), index);
! state.killReadCache(NamedLocationIdentity.getArrayLocation(JavaKind.Byte), index);
! return false;
! }
! }
! LocationIdentity arrayLocation = NamedLocationIdentity.getArrayLocation(elementKind);
! if (index != -1) {
! return processStore(store, store.array(), arrayLocation, index, elementKind, false, store.value(), state, effects);
} else {
state.killReadCache(arrayLocation, -1);
}
return false;
}
private boolean processLoadIndexed(LoadIndexedNode load, PEReadEliminationBlockState state, GraphEffectList effects) {
if (load.index().isConstant()) {
int index = ((JavaConstant) load.index().asConstant()).asInt();
! // BALOAD (with elementKind being Byte) can be used to retrieve values from boolean
! // arrays.
! JavaKind elementKind = load.elementKind();
! if (elementKind == JavaKind.Byte) {
! elementKind = getElementKindFromStamp(load.array());
! if (elementKind == JavaKind.Illegal) {
! return false;
! }
! }
! LocationIdentity arrayLocation = NamedLocationIdentity.getArrayLocation(elementKind);
! return processLoad(load, load.array(), arrayLocation, index, elementKind, state, effects);
}
return false;
}
private boolean processUnbox(UnboxNode unbox, PEReadEliminationBlockState state, GraphEffectList effects) {
*** 291,301 ****
for (ReadCacheEntry entry : entries) {
ValueNode object = entry.object;
if (object != null) {
Pair<ValueNode, Object> pair = firstValueSet.get(object);
while (pair != null) {
! initialState.addReadCache(pair.getLeft(), entry.identity, entry.index, entry.kind, initialState.getReadCache().get(entry), this);
pair = (Pair<ValueNode, Object>) pair.getRight();
}
}
}
}
--- 334,344 ----
for (ReadCacheEntry entry : entries) {
ValueNode object = entry.object;
if (object != null) {
Pair<ValueNode, Object> pair = firstValueSet.get(object);
while (pair != null) {
! initialState.addReadCache(pair.getLeft(), entry.identity, entry.index, entry.kind, entry.overflowAccess, initialState.getReadCache().get(entry), this);
pair = (Pair<ValueNode, Object>) pair.getRight();
}
}
}
}
*** 384,401 ****
*/
for (PhiNode phi : getPhis()) {
if (phi.getStackKind() == JavaKind.Object) {
for (ReadCacheEntry entry : states.get(0).readCache.getKeys()) {
if (entry.object == getPhiValueAt(phi, 0)) {
! mergeReadCachePhi(phi, entry.identity, entry.index, entry.kind, states);
}
}
}
}
}
! private void mergeReadCachePhi(PhiNode phi, LocationIdentity identity, int index, JavaKind kind, List<PEReadEliminationBlockState> states) {
ValueNode[] values = new ValueNode[states.size()];
values[0] = states.get(0).getReadCache(getPhiValueAt(phi, 0), identity, index, kind, PEReadEliminationClosure.this);
if (values[0] != null) {
for (int i = 1; i < states.size(); i++) {
ValueNode value = states.get(i).getReadCache(getPhiValueAt(phi, i), identity, index, kind, PEReadEliminationClosure.this);
--- 427,444 ----
*/
for (PhiNode phi : getPhis()) {
if (phi.getStackKind() == JavaKind.Object) {
for (ReadCacheEntry entry : states.get(0).readCache.getKeys()) {
if (entry.object == getPhiValueAt(phi, 0)) {
! mergeReadCachePhi(phi, entry.identity, entry.index, entry.kind, entry.overflowAccess, states);
}
}
}
}
}
! private void mergeReadCachePhi(PhiNode phi, LocationIdentity identity, int index, JavaKind kind, boolean overflowAccess, List<PEReadEliminationBlockState> states) {
ValueNode[] values = new ValueNode[states.size()];
values[0] = states.get(0).getReadCache(getPhiValueAt(phi, 0), identity, index, kind, PEReadEliminationClosure.this);
if (values[0] != null) {
for (int i = 1; i < states.size(); i++) {
ValueNode value = states.get(i).getReadCache(getPhiValueAt(phi, i), identity, index, kind, PEReadEliminationClosure.this);
*** 405,420 ****
return;
}
values[i] = value;
}
! PhiNode phiNode = getPhi(new ReadCacheEntry(identity, phi, index, kind), values[0].stamp().unrestricted());
mergeEffects.addFloatingNode(phiNode, "mergeReadCachePhi");
for (int i = 0; i < values.length; i++) {
setPhiInput(phiNode, i, values[i]);
}
! newState.readCache.put(new ReadCacheEntry(identity, phi, index, kind), phiNode);
}
}
}
@Override
--- 448,463 ----
return;
}
values[i] = value;
}
! PhiNode phiNode = getPhi(new ReadCacheEntry(identity, phi, index, kind, overflowAccess), values[0].stamp().unrestricted());
mergeEffects.addFloatingNode(phiNode, "mergeReadCachePhi");
for (int i = 0; i < values.length; i++) {
setPhiInput(phiNode, i, values[i]);
}
! newState.readCache.put(new ReadCacheEntry(identity, phi, index, kind, overflowAccess), phiNode);
}
}
}
@Override
< prev index next >