use of org.graalvm.word.LocationIdentity in project graal by oracle.
the class ReadEliminationClosure method processKilledLoopLocations.
@Override
protected void processKilledLoopLocations(Loop<Block> loop, ReadEliminationBlockState initialState, ReadEliminationBlockState mergedStates) {
assert initialState != null;
assert mergedStates != null;
if (initialState.readCache.size() > 0) {
LoopKillCache loopKilledLocations = loopLocationKillCache.get(loop);
// it is visited
if (loopKilledLocations == null) {
loopKilledLocations = new LoopKillCache(1);
loopLocationKillCache.put(loop, loopKilledLocations);
} else {
OptionValues options = loop.getHeader().getBeginNode().getOptions();
if (loopKilledLocations.visits() > ReadEliminationMaxLoopVisits.getValue(options)) {
// we have processed the loop too many times, kill all locations so the inner
// loop will never be processed more than once again on visit
loopKilledLocations.setKillsAll();
} else {
// we have fully processed this loop >1 times, update the killed locations
EconomicSet<LocationIdentity> forwardEndLiveLocations = EconomicSet.create(Equivalence.DEFAULT);
for (CacheEntry<?> entry : initialState.readCache.getKeys()) {
forwardEndLiveLocations.add(entry.getIdentity());
}
for (CacheEntry<?> entry : mergedStates.readCache.getKeys()) {
forwardEndLiveLocations.remove(entry.getIdentity());
}
// loop
for (LocationIdentity location : forwardEndLiveLocations) {
loopKilledLocations.rememberLoopKilledLocation(location);
}
if (debug.isLogEnabled() && loopKilledLocations != null) {
debug.log("[Early Read Elimination] Setting loop killed locations of loop at node %s with %s", loop.getHeader().getBeginNode(), forwardEndLiveLocations);
}
}
// remember the loop visit
loopKilledLocations.visited();
}
}
}
use of org.graalvm.word.LocationIdentity in project graal by oracle.
the class ReadEliminationClosure method processNode.
@Override
protected boolean processNode(Node node, ReadEliminationBlockState state, GraphEffectList effects, FixedWithNextNode lastFixedNode) {
boolean deleted = false;
if (node instanceof AccessFieldNode) {
AccessFieldNode access = (AccessFieldNode) node;
if (access.isVolatile()) {
processIdentity(state, any());
} else {
ValueNode object = GraphUtil.unproxify(access.object());
LoadCacheEntry identifier = new LoadCacheEntry(object, new FieldLocationIdentity(access.field()));
ValueNode cachedValue = state.getCacheEntry(identifier);
if (node instanceof LoadFieldNode) {
if (cachedValue != null && access.stamp(NodeView.DEFAULT).isCompatible(cachedValue.stamp(NodeView.DEFAULT))) {
effects.replaceAtUsages(access, cachedValue, access);
addScalarAlias(access, cachedValue);
deleted = true;
} else {
state.addCacheEntry(identifier, access);
}
} else {
assert node instanceof StoreFieldNode;
StoreFieldNode store = (StoreFieldNode) node;
ValueNode value = getScalarAlias(store.value());
if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) {
effects.deleteNode(store);
deleted = true;
}
state.killReadCache(identifier.identity);
state.addCacheEntry(identifier, value);
}
}
} else if (node instanceof ReadNode) {
ReadNode read = (ReadNode) node;
if (read.getLocationIdentity().isSingle()) {
ValueNode object = GraphUtil.unproxify(read.getAddress());
LoadCacheEntry identifier = new LoadCacheEntry(object, read.getLocationIdentity());
ValueNode cachedValue = state.getCacheEntry(identifier);
if (cachedValue != null && areValuesReplaceable(read, cachedValue, considerGuards)) {
effects.replaceAtUsages(read, cachedValue, read);
addScalarAlias(read, cachedValue);
deleted = true;
} else {
state.addCacheEntry(identifier, read);
}
}
} else if (node instanceof WriteNode) {
WriteNode write = (WriteNode) node;
if (write.getLocationIdentity().isSingle()) {
ValueNode object = GraphUtil.unproxify(write.getAddress());
LoadCacheEntry identifier = new LoadCacheEntry(object, write.getLocationIdentity());
ValueNode cachedValue = state.getCacheEntry(identifier);
ValueNode value = getScalarAlias(write.value());
if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) {
effects.deleteNode(write);
deleted = true;
}
processIdentity(state, write.getLocationIdentity());
state.addCacheEntry(identifier, value);
} else {
processIdentity(state, write.getLocationIdentity());
}
} else if (node instanceof UnsafeAccessNode) {
ResolvedJavaType type = StampTool.typeOrNull(((UnsafeAccessNode) node).object());
if (type != null && !type.isArray()) {
if (node instanceof RawLoadNode) {
RawLoadNode load = (RawLoadNode) node;
if (load.getLocationIdentity().isSingle()) {
ValueNode object = GraphUtil.unproxify(load.object());
UnsafeLoadCacheEntry identifier = new UnsafeLoadCacheEntry(object, load.offset(), load.getLocationIdentity());
ValueNode cachedValue = state.getCacheEntry(identifier);
if (cachedValue != null && areValuesReplaceable(load, cachedValue, considerGuards)) {
effects.replaceAtUsages(load, cachedValue, load);
addScalarAlias(load, cachedValue);
deleted = true;
} else {
state.addCacheEntry(identifier, load);
}
}
} else {
assert node instanceof RawStoreNode;
RawStoreNode write = (RawStoreNode) node;
if (write.getLocationIdentity().isSingle()) {
ValueNode object = GraphUtil.unproxify(write.object());
UnsafeLoadCacheEntry identifier = new UnsafeLoadCacheEntry(object, write.offset(), write.getLocationIdentity());
ValueNode cachedValue = state.getCacheEntry(identifier);
ValueNode value = getScalarAlias(write.value());
if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) {
effects.deleteNode(write);
deleted = true;
}
processIdentity(state, write.getLocationIdentity());
state.addCacheEntry(identifier, value);
} else {
processIdentity(state, write.getLocationIdentity());
}
}
}
} else if (node instanceof MemoryCheckpoint.Single) {
LocationIdentity identity = ((MemoryCheckpoint.Single) node).getLocationIdentity();
processIdentity(state, identity);
} else if (node instanceof MemoryCheckpoint.Multi) {
for (LocationIdentity identity : ((MemoryCheckpoint.Multi) node).getLocationIdentities()) {
processIdentity(state, identity);
}
}
return deleted;
}
use of org.graalvm.word.LocationIdentity in project graal by oracle.
the class CInterfaceInvocationPlugin method replaceBitfieldAccessor.
private boolean replaceBitfieldAccessor(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args, StructBitfieldInfo bitfieldInfo, AccessorInfo accessorInfo) {
int byteOffset = bitfieldInfo.getByteOffsetInfo().getProperty();
int startBit = bitfieldInfo.getStartBitInfo().getProperty();
int endBit = bitfieldInfo.getEndBitInfo().getProperty();
boolean isUnsigned = bitfieldInfo.isUnsigned();
assert byteOffset >= 0 && byteOffset < ((SizableInfo) bitfieldInfo.getParent()).getSizeInfo().getProperty();
assert startBit >= 0 && startBit < 8;
assert endBit >= startBit && endBit < 64;
/*
* The startBit is always in the first byte. Therefore, the endBit tells us how many bytes
* we actually have to read and write.
*/
JavaKind memoryKind;
if (endBit < 8) {
memoryKind = JavaKind.Byte;
} else if (endBit < 16) {
memoryKind = JavaKind.Short;
} else if (endBit < 32) {
memoryKind = JavaKind.Int;
} else {
memoryKind = JavaKind.Long;
}
int numBytes = memoryKind.getByteCount();
/*
* Try to align the byteOffset to be a multiple of numBytes. That should always be possible,
* but we don't trust the C compiler and memory layout enough to make it an assertion.
*/
int alignmentCorrection = byteOffset % numBytes;
if (alignmentCorrection > 0 && endBit + alignmentCorrection * 8 < numBytes * 8) {
byteOffset -= alignmentCorrection;
startBit += alignmentCorrection * 8;
endBit += alignmentCorrection * 8;
}
assert byteOffset >= 0 && byteOffset < ((SizableInfo) bitfieldInfo.getParent()).getSizeInfo().getProperty();
assert startBit >= 0 && startBit < numBytes * 8;
assert endBit >= startBit && endBit < numBytes * 8;
int numBits = endBit - startBit + 1;
assert numBits > 0 && numBits <= numBytes * 8;
/*
* The bit-operations on the value are either performed on Int or Long. We do not perform 8
* or 16 bit arithmetic operations.
*/
JavaKind computeKind = memoryKind.getStackKind();
Stamp computeStamp = StampFactory.forKind(computeKind);
int computeBits = computeKind.getBitCount();
assert startBit >= 0 && startBit < computeBits;
assert endBit >= startBit && endBit < computeBits;
assert computeBits >= numBits;
assert args.length == accessorInfo.parameterCount(true);
ValueNode base = args[accessorInfo.baseParameterNumber(true)];
StructuredGraph graph = b.getGraph();
/*
* Read the memory location. This is also necessary for writes, since we need to keep the
* bits around the written bitfield unchanged.
*/
ValueNode address = makeAddress(graph, args, accessorInfo, base, byteOffset, -1);
LocationIdentity locationIdentity = makeLocationIdentity(b, method, args, accessorInfo);
Stamp stamp = StampFactory.forInteger(memoryKind.getBitCount());
ValueNode cur = readOp(b, address, locationIdentity, stamp, accessorInfo);
cur = adaptPrimitiveType(graph, cur, memoryKind, computeKind, true);
switch(accessorInfo.getAccessorKind()) {
case GETTER:
{
if (isUnsigned) {
/*
* Unsigned reads: shift the bitfield to the right and mask out the unnecessary
* high-order bits.
*/
cur = graph.unique(new RightShiftNode(cur, ConstantNode.forInt(startBit, graph)));
cur = graph.unique(new AndNode(cur, ConstantNode.forIntegerStamp(computeStamp, (1L << numBits) - 1, graph)));
} else {
/*
* Signed reads: shift the bitfield to the right end to get the sign bit in
* place, then do a signed left shift to have a proper sign extension.
*/
cur = graph.unique(new LeftShiftNode(cur, ConstantNode.forInt(computeBits - endBit - 1, graph)));
cur = graph.unique(new RightShiftNode(cur, ConstantNode.forInt(computeBits - numBits, graph)));
}
JavaKind resultKind = wordTypes.asKind(b.getInvokeReturnType());
b.push(pushKind(method), adaptPrimitiveType(graph, cur, computeKind, resultKind == JavaKind.Boolean ? resultKind : resultKind.getStackKind(), isUnsigned));
return true;
}
case SETTER:
{
/* Zero out the bits of our bitfields, i.e., the bits we are going to change. */
long mask = ~(((1L << numBits) - 1) << startBit);
cur = graph.unique(new AndNode(cur, ConstantNode.forIntegerStamp(computeStamp, mask, graph)));
/*
* Mask the unnecessary high-order bits of the value to be written, and shift it to
* its place.
*/
ValueNode value = args[accessorInfo.valueParameterNumber(true)];
value = adaptPrimitiveType(graph, value, value.getStackKind(), computeKind, isUnsigned);
value = graph.unique(new AndNode(value, ConstantNode.forIntegerStamp(computeStamp, (1L << numBits) - 1, graph)));
value = graph.unique(new LeftShiftNode(value, ConstantNode.forInt(startBit, graph)));
/* Combine the leftover bits of the original memory word with the new value. */
cur = graph.unique(new OrNode(cur, value));
/* Narrow value to the number of bits we need to write. */
cur = adaptPrimitiveType(graph, cur, computeKind, memoryKind, true);
/* Perform the write (bitcount is taken from the stamp of the written value). */
writeOp(b, address, locationIdentity, cur, accessorInfo);
return true;
}
default:
throw shouldNotReachHere();
}
}
use of org.graalvm.word.LocationIdentity in project graal by oracle.
the class CInterfaceInvocationPlugin method makeLocationIdentity.
private static LocationIdentity makeLocationIdentity(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args, AccessorInfo accessorInfo) {
LocationIdentity locationIdentity;
if (accessorInfo.hasLocationIdentityParameter()) {
ValueNode locationIdentityNode = args[accessorInfo.locationIdentityParameterNumber(true)];
if (!locationIdentityNode.isConstant()) {
throw UserError.abort(new CInterfaceError("locationIdentity is not a compile time constant for call to " + method.format("%H.%n(%p)") + " in " + b.getMethod().asStackTraceElement(b.bci()), method).getMessage());
}
locationIdentity = (LocationIdentity) SubstrateObjectConstant.asObject(locationIdentityNode.asConstant());
} else if (accessorInfo.hasUniqueLocationIdentity()) {
StructFieldInfo fieldInfo = (StructFieldInfo) accessorInfo.getParent();
assert fieldInfo.getLocationIdentity() != null;
locationIdentity = fieldInfo.getLocationIdentity();
} else {
locationIdentity = CInterfaceLocationIdentity.DEFAULT_LOCATION_IDENTITY;
}
return locationIdentity;
}
use of org.graalvm.word.LocationIdentity in project graal by oracle.
the class PEReadEliminationClosure method processUnsafeStore.
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(tool.getArrayOffsetProvider(), 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();
}
return false;
}
Aggregations