Search in sources :

Example 16 with LocationIdentity

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();
        }
    }
}
Also used : OptionValues(org.graalvm.compiler.options.OptionValues) LocationIdentity(org.graalvm.word.LocationIdentity) FieldLocationIdentity(org.graalvm.compiler.nodes.FieldLocationIdentity)

Example 17 with LocationIdentity

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;
}
Also used : RawStoreNode(org.graalvm.compiler.nodes.extended.RawStoreNode) StoreFieldNode(org.graalvm.compiler.nodes.java.StoreFieldNode) LoadFieldNode(org.graalvm.compiler.nodes.java.LoadFieldNode) UnsafeLoadCacheEntry(org.graalvm.compiler.virtual.phases.ea.ReadEliminationBlockState.UnsafeLoadCacheEntry) ResolvedJavaType(jdk.vm.ci.meta.ResolvedJavaType) RawLoadNode(org.graalvm.compiler.nodes.extended.RawLoadNode) FieldLocationIdentity(org.graalvm.compiler.nodes.FieldLocationIdentity) UnsafeAccessNode(org.graalvm.compiler.nodes.extended.UnsafeAccessNode) MemoryCheckpoint(org.graalvm.compiler.nodes.memory.MemoryCheckpoint) AccessFieldNode(org.graalvm.compiler.nodes.java.AccessFieldNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) LocationIdentity(org.graalvm.word.LocationIdentity) FieldLocationIdentity(org.graalvm.compiler.nodes.FieldLocationIdentity) ReadNode(org.graalvm.compiler.nodes.memory.ReadNode) WriteNode(org.graalvm.compiler.nodes.memory.WriteNode) LoadCacheEntry(org.graalvm.compiler.virtual.phases.ea.ReadEliminationBlockState.LoadCacheEntry) UnsafeLoadCacheEntry(org.graalvm.compiler.virtual.phases.ea.ReadEliminationBlockState.UnsafeLoadCacheEntry)

Example 18 with LocationIdentity

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();
    }
}
Also used : Stamp(org.graalvm.compiler.core.common.type.Stamp) StructuredGraph(org.graalvm.compiler.nodes.StructuredGraph) ValueNode(org.graalvm.compiler.nodes.ValueNode) RightShiftNode(org.graalvm.compiler.nodes.calc.RightShiftNode) LocationIdentity(org.graalvm.word.LocationIdentity) CInterfaceLocationIdentity(com.oracle.svm.core.c.struct.CInterfaceLocationIdentity) AndNode(org.graalvm.compiler.nodes.calc.AndNode) LeftShiftNode(org.graalvm.compiler.nodes.calc.LeftShiftNode) JavaKind(jdk.vm.ci.meta.JavaKind) OrNode(org.graalvm.compiler.nodes.calc.OrNode)

Example 19 with LocationIdentity

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;
}
Also used : CInterfaceError(com.oracle.svm.hosted.c.CInterfaceError) ValueNode(org.graalvm.compiler.nodes.ValueNode) StructFieldInfo(com.oracle.svm.hosted.c.info.StructFieldInfo) LocationIdentity(org.graalvm.word.LocationIdentity) CInterfaceLocationIdentity(com.oracle.svm.core.c.struct.CInterfaceLocationIdentity)

Example 20 with 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;
}
Also used : LocationIdentity(org.graalvm.word.LocationIdentity) FieldLocationIdentity(org.graalvm.compiler.nodes.FieldLocationIdentity) NamedLocationIdentity(org.graalvm.compiler.nodes.NamedLocationIdentity) ResolvedJavaType(jdk.vm.ci.meta.ResolvedJavaType) MemoryCheckpoint(org.graalvm.compiler.nodes.memory.MemoryCheckpoint) JavaKind(jdk.vm.ci.meta.JavaKind)

Aggregations

LocationIdentity (org.graalvm.word.LocationIdentity)32 ValueNode (org.graalvm.compiler.nodes.ValueNode)12 FieldLocationIdentity (org.graalvm.compiler.nodes.FieldLocationIdentity)11 NamedLocationIdentity (org.graalvm.compiler.nodes.NamedLocationIdentity)11 JavaKind (jdk.vm.ci.meta.JavaKind)10 MemoryCheckpoint (org.graalvm.compiler.nodes.memory.MemoryCheckpoint)10 ResolvedJavaType (jdk.vm.ci.meta.ResolvedJavaType)6 Stamp (org.graalvm.compiler.core.common.type.Stamp)5 AbstractBeginNode (org.graalvm.compiler.nodes.AbstractBeginNode)5 StructuredGraph (org.graalvm.compiler.nodes.StructuredGraph)5 AddressNode (org.graalvm.compiler.nodes.memory.address.AddressNode)4 CInterfaceLocationIdentity (com.oracle.svm.core.c.struct.CInterfaceLocationIdentity)3 ResolvedJavaField (jdk.vm.ci.meta.ResolvedJavaField)3 Node (org.graalvm.compiler.graph.Node)3 AbstractMergeNode (org.graalvm.compiler.nodes.AbstractMergeNode)3 StructFieldInfo (com.oracle.svm.hosted.c.info.StructFieldInfo)2 JavaConstant (jdk.vm.ci.meta.JavaConstant)2 ForeignCallDescriptor (org.graalvm.compiler.core.common.spi.ForeignCallDescriptor)2 KlassPointerStamp (org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp)2 FixedNode (org.graalvm.compiler.nodes.FixedNode)2