# HG changeset patch # User Stefan Anzinger # Date 1430238916 -7200 # Node ID 7a62f41ed61081faa758480357063b9256ee6b30 # Parent fb2b2741834746c078fdae7ceee4b1981ba52f61# Parent a5faa9aafc8031075ef187bf8f136331731c4659 Merge diff -r fb2b27418347 -r 7a62f41ed610 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PostWriteBarrier.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PostWriteBarrier.java Tue Apr 28 18:35:01 2015 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PostWriteBarrier.java Tue Apr 28 18:35:16 2015 +0200 @@ -22,14 +22,13 @@ */ package com.oracle.graal.hotspot.nodes; -import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; @NodeInfo -public class G1PostWriteBarrier extends WriteBarrier implements MemoryCheckpoint.Single { +public class G1PostWriteBarrier extends WriteBarrier { public static final NodeClass TYPE = NodeClass.create(G1PostWriteBarrier.class); protected final boolean alwaysNull; @@ -46,8 +45,4 @@ public boolean alwaysNull() { return alwaysNull; } - - public LocationIdentity getLocationIdentity() { - return LocationIdentity.any(); - } } diff -r fb2b27418347 -r 7a62f41ed610 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java Tue Apr 28 18:35:01 2015 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java Tue Apr 28 18:35:16 2015 +0200 @@ -212,13 +212,13 @@ // If the written value is not null continue with the barrier addition. if (probability(FREQUENT_PROBABILITY, writtenValue.notEqual(0))) { - byte cardByte = cardAddress.readByte(0); + byte cardByte = cardAddress.readByte(0, GC_CARD_LOCATION); g1EffectiveAfterNullPostWriteBarrierCounter.inc(); // If the card is already dirty, (hence already enqueued) skip the insertion. if (probability(NOT_FREQUENT_PROBABILITY, cardByte != g1YoungCardValue())) { - MembarNode.memoryBarrier(STORE_LOAD); - byte cardByteReload = cardAddress.readByte(0); + MembarNode.memoryBarrier(STORE_LOAD, GC_CARD_LOCATION); + byte cardByteReload = cardAddress.readByte(0, GC_CARD_LOCATION); if (probability(NOT_FREQUENT_PROBABILITY, cardByteReload != dirtyCardValue())) { log(trace, "[%d] G1-Post Thread: %p Card: %p \n", gcCycle, thread.rawValue(), Word.unsigned(cardByte).rawValue()); cardAddress.writeByte(0, (byte) 0, GC_CARD_LOCATION); @@ -298,11 +298,11 @@ while (count-- > 0) { Word cardAddress = Word.unsigned((start + cardStart) + count); - byte cardByte = cardAddress.readByte(0); + byte cardByte = cardAddress.readByte(0, GC_CARD_LOCATION); // If the card is already dirty, (hence already enqueued) skip the insertion. if (probability(NOT_FREQUENT_PROBABILITY, cardByte != g1YoungCardValue())) { - MembarNode.memoryBarrier(STORE_LOAD); - byte cardByteReload = cardAddress.readByte(0); + MembarNode.memoryBarrier(STORE_LOAD, GC_CARD_LOCATION); + byte cardByteReload = cardAddress.readByte(0, GC_CARD_LOCATION); if (probability(NOT_FREQUENT_PROBABILITY, cardByteReload != dirtyCardValue())) { cardAddress.writeByte(0, (byte) 0, GC_CARD_LOCATION); // If the thread local card queue is full, issue a native call which will diff -r fb2b27418347 -r 7a62f41ed610 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java Tue Apr 28 18:35:01 2015 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java Tue Apr 28 18:35:16 2015 +0200 @@ -37,15 +37,21 @@ public static final NodeClass TYPE = NodeClass.create(MembarNode.class); protected final int barriers; + protected final LocationIdentity location; public MembarNode(int barriers) { + this(barriers, LocationIdentity.any()); + } + + public MembarNode(int barriers, LocationIdentity location) { super(TYPE, StampFactory.forVoid()); this.barriers = barriers; + this.location = location; } @Override public LocationIdentity getLocationIdentity() { - return LocationIdentity.any(); + return location; } @Override @@ -55,4 +61,7 @@ @NodeIntrinsic public static native void memoryBarrier(@ConstantNodeParameter int barriers); + + @NodeIntrinsic + public static native void memoryBarrier(@ConstantNodeParameter int barriers, @ConstantNodeParameter LocationIdentity location); } diff -r fb2b27418347 -r 7a62f41ed610 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Probe.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Probe.java Tue Apr 28 18:35:01 2015 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Probe.java Tue Apr 28 18:35:16 2015 +0200 @@ -39,7 +39,8 @@ /** * A binding between: *
    - *
  1. A program location in an executing Truffle AST (defined by a {@link SourceSection}), and
  2. + *
  3. A program location in an executing Truffle AST (corresponding to a {@link SourceSection}), + * and
  4. *
  5. A dynamically managed collection of "attached" {@linkplain Instrument Instruments} that * receive event notifications on behalf of external clients.
  6. *
@@ -97,7 +98,7 @@ * @see ProbeListener * @see SyntaxTag */ -public final class Probe implements SyntaxTagged { +public final class Probe { private static final List astProbers = new ArrayList<>(); @@ -108,7 +109,17 @@ */ private static final List> probes = new ArrayList<>(); - @CompilationFinal private static SyntaxTagTrap tagTrap = null; + /** + * A global trap that triggers notification just before executing any Node that is Probed with a + * matching tag. + */ + @CompilationFinal private static SyntaxTagTrap beforeTagTrap = null; + + /** + * A global trap that triggers notification just after executing any Node that is Probed with a + * matching tag. + */ + @CompilationFinal private static SyntaxTagTrap afterTagTrap = null; private static final class FindSourceVisitor implements NodeVisitor { @@ -198,24 +209,50 @@ return taggedProbes; } - // TODO (mlvdv) can this be generalized to permit multiple traps without a performance hit? + // TODO (mlvdv) generalize to permit multiple "before traps" without a performance hit? /** - * Sets the current "tag trap"; there can be no more than one set at a time. + * Sets the current "before tag trap"; there can be no more than one in effect. *
    - *
  • A non-null trap sets a callback to be triggered whenever execution reaches a - * {@link Probe} (either existing or subsequently created) with the specified tag.
  • - *
  • Setting the trap to null clears the existing trap.
  • - *
  • Setting a non-null trap when one is already set will clear the previously set trap.
  • + *
  • The before-trap triggers a callback just before execution + * reaches any {@link Probe} (either existing or subsequently created) + * with the specified {@link SyntaxTag}.
  • + *
  • Setting the before-trap to {@code null} clears an existing before-trap.
  • + *
  • Setting a non{@code -null} before-trap when one is already set clears the previously set + * before-trap.
  • *
* - * @param newTagTrap The {@link SyntaxTagTrap} to set. + * @param newBeforeTagTrap The new "before" {@link SyntaxTagTrap} to set. */ - public static void setTagTrap(SyntaxTagTrap newTagTrap) { - tagTrap = newTagTrap; + public static void setBeforeTagTrap(SyntaxTagTrap newBeforeTagTrap) { + beforeTagTrap = newBeforeTagTrap; for (WeakReference ref : probes) { final Probe probe = ref.get(); if (probe != null) { - probe.notifyTrapSet(); + probe.notifyTrapsChanged(); + } + } + } + + // TODO (mlvdv) generalize to permit multiple "after traps" without a performance hit? + /** + * Sets the current "after tag trap"; there can be no more than one in effect. + *
    + *
  • The after-trap triggers a callback just after execution leaves + * any {@link Probe} (either existing or subsequently created) with + * the specified {@link SyntaxTag}.
  • + *
  • Setting the after-trap to {@code null} clears an existing after-trap.
  • + *
  • Setting a non{@code -null} after-trap when one is already set clears the previously set + * after-trap.
  • + *
+ * + * @param newAfterTagTrap The new "after" {@link SyntaxTagTrap} to set. + */ + public static void setAfterTagTrap(SyntaxTagTrap newAfterTagTrap) { + afterTagTrap = newAfterTagTrap; + for (WeakReference ref : probes) { + final Probe probe = ref.get(); + if (probe != null) { + probe.notifyTrapsChanged(); } } } @@ -236,8 +273,11 @@ */ @CompilationFinal private Assumption probeStateUnchangedAssumption = probeStateUnchangedCyclic.getAssumption(); - // Must invalidate whenever this changes. - @CompilationFinal private boolean isTrapActive = false; + // Must invalidate whenever changed + @CompilationFinal private boolean isBeforeTrapActive = false; + + // Must invalidate whenever changed + @CompilationFinal private boolean isAfterTrapActive = false; /** * Intended for use only by {@link ProbeNode}. @@ -251,11 +291,18 @@ } } + /** + * Is this node tagged as belonging to a particular human-sensible category of language + * constructs? + */ public boolean isTaggedAs(SyntaxTag tag) { assert tag != null; return tags.contains(tag); } + /** + * In which user-sensible categories has this node been tagged (empty set if none). + */ public Collection getSyntaxTags() { return Collections.unmodifiableCollection(tags); } @@ -271,8 +318,18 @@ for (ProbeListener listener : probeListeners) { listener.probeTaggedAs(this, tag, tagValue); } - if (tagTrap != null && tag == tagTrap.getTag()) { - this.isTrapActive = true; + + // Update the status of this Probe with respect to global tag traps + boolean tagTrapsChanged = false; + if (beforeTagTrap != null && tag == beforeTagTrap.getTag()) { + this.isBeforeTrapActive = true; + tagTrapsChanged = true; + } + if (afterTagTrap != null && tag == afterTagTrap.getTag()) { + this.isAfterTrapActive = true; + tagTrapsChanged = true; + } + if (tagTrapsChanged) { invalidateProbeUnchanged(); } } @@ -341,11 +398,25 @@ } /** - * Gets the currently active {@linkplain SyntaxTagTrap tagTrap}; {@code null} if not set. + * Gets the currently active before {@linkplain SyntaxTagTrap Tag + * Trap} at this Probe. Non{@code -null} if the global + * {@linkplain Probe#setBeforeTagTrap(SyntaxTagTrap) Before Tag Trap} is set and if this Probe + * holds the {@link SyntaxTag} specified in the trap. */ - SyntaxTagTrap getTrap() { + SyntaxTagTrap getBeforeTrap() { checkProbeUnchanged(); - return isTrapActive ? tagTrap : null; + return isBeforeTrapActive ? beforeTagTrap : null; + } + + /** + * Gets the currently active after {@linkplain SyntaxTagTrap Tag Trap} + * at this Probe. Non{@code -null} if the global + * {@linkplain Probe#setAfterTagTrap(SyntaxTagTrap) After Tag Trap} is set and if this Probe + * holds the {@link SyntaxTag} specified in the trap. + */ + SyntaxTagTrap getAfterTrap() { + checkProbeUnchanged(); + return isAfterTrapActive ? afterTagTrap : null; } /** @@ -366,8 +437,9 @@ probeStateUnchangedCyclic.invalidate(); } - private void notifyTrapSet() { - this.isTrapActive = tagTrap != null && this.isTaggedAs(tagTrap.getTag()); + private void notifyTrapsChanged() { + this.isBeforeTrapActive = beforeTagTrap != null && this.isTaggedAs(beforeTagTrap.getTag()); + this.isAfterTrapActive = afterTagTrap != null && this.isTaggedAs(afterTagTrap.getTag()); invalidateProbeUnchanged(); } diff -r fb2b27418347 -r 7a62f41ed610 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeNode.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeNode.java Tue Apr 28 18:35:01 2015 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeNode.java Tue Apr 28 18:35:16 2015 +0200 @@ -153,9 +153,9 @@ public void enter(Node node, VirtualFrame vFrame) { this.probe.checkProbeUnchanged(); - final SyntaxTagTrap trap = probe.getTrap(); - if (trap != null) { - trap.tagTrappedAt(((WrapperNode) this.getParent()).getChild(), vFrame.materialize()); + final SyntaxTagTrap beforeTagTrap = probe.getBeforeTrap(); + if (beforeTagTrap != null) { + beforeTagTrap.tagTrappedAt(((WrapperNode) this.getParent()).getChild(), vFrame.materialize()); } if (firstInstrumentNode != null) { firstInstrumentNode.enter(node, vFrame); @@ -167,6 +167,10 @@ if (firstInstrumentNode != null) { firstInstrumentNode.returnVoid(node, vFrame); } + final SyntaxTagTrap afterTagTrap = probe.getAfterTrap(); + if (afterTagTrap != null) { + afterTagTrap.tagTrappedAt(((WrapperNode) this.getParent()).getChild(), vFrame.materialize()); + } } public void returnValue(Node node, VirtualFrame vFrame, Object result) { @@ -174,6 +178,10 @@ if (firstInstrumentNode != null) { firstInstrumentNode.returnValue(node, vFrame, result); } + final SyntaxTagTrap afterTagTrap = probe.getAfterTrap(); + if (afterTagTrap != null) { + afterTagTrap.tagTrappedAt(((WrapperNode) this.getParent()).getChild(), vFrame.materialize()); + } } public void returnExceptional(Node node, VirtualFrame vFrame, Exception exception) { @@ -181,6 +189,10 @@ if (firstInstrumentNode != null) { firstInstrumentNode.returnExceptional(node, vFrame, exception); } + final SyntaxTagTrap afterTagTrap = probe.getAfterTrap(); + if (afterTagTrap != null) { + afterTagTrap.tagTrappedAt(((WrapperNode) this.getParent()).getChild(), vFrame.materialize()); + } } public String instrumentationInfo() { diff -r fb2b27418347 -r 7a62f41ed610 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/SyntaxTagTrap.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/SyntaxTagTrap.java Tue Apr 28 18:35:01 2015 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/SyntaxTagTrap.java Tue Apr 28 18:35:16 2015 +0200 @@ -45,7 +45,7 @@ } /** - * Callback that will be received whenever execution enters a node with the specified tag. + * Notifies that execution is halted at a node with the specified tag. */ public abstract void tagTrappedAt(Node node, MaterializedFrame frame); } diff -r fb2b27418347 -r 7a62f41ed610 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/SyntaxTagged.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/SyntaxTagged.java Tue Apr 28 18:35:01 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.api.instrument; - -import java.util.*; - -/** - * Information about a guest language program element in a Truffle AST that can be marked as - * belonging to 0 or more {@linkplain SyntaxTag tags}. - */ -public interface SyntaxTagged { - - /** - * Is this node tagged as belonging to a particular human-sensible category of language - * constructs? - */ - boolean isTaggedAs(SyntaxTag tag); - - /** - * In which user-sensible categories has this node been tagged (empty set if none). - */ - Collection getSyntaxTags(); - -}