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