@NodeInfo
public abstract class EscapeObjectState extends VirtualState implements ValueNumberable {
  public static final NodeClass<EscapeObjectState> TYPE = NodeClass.create(EscapeObjectState.class);

  @Input protected VirtualObjectNode object;

  public VirtualObjectNode object() {
    return object;
  }

  public EscapeObjectState(NodeClass<? extends EscapeObjectState> c, VirtualObjectNode object) {
    super(c);
    this.object = object;
  }

  @Override
  public abstract EscapeObjectState duplicateWithVirtualState();

  @Override
  public boolean isPartOfThisState(VirtualState state) {
    return this == state;
  }

  @Override
  public void applyToVirtual(VirtualClosure closure) {
    closure.apply(this);
  }
}
示例#2
0
@NodeInfo
public abstract class AbstractEndNode extends FixedNode implements IterableNodeType, LIRLowerable {

  public static final NodeClass<AbstractEndNode> TYPE = NodeClass.create(AbstractEndNode.class);

  protected AbstractEndNode(NodeClass<? extends AbstractEndNode> c) {
    super(c, StampFactory.forVoid());
  }

  @Override
  public void generate(NodeLIRBuilderTool gen) {
    gen.visitEndNode(this);
  }

  public AbstractMergeNode merge() {
    return (AbstractMergeNode) usages().first();
  }

  @Override
  public boolean verify() {
    assertTrue(getUsageCount() <= 1, "at most one usage");
    return super.verify();
  }

  @Override
  public Iterable<? extends Node> cfgSuccessors() {
    return Arrays.asList(merge());
  }
}
示例#3
0
  @NodeInfo
  static final class DummyGuardHandle extends ValueNode implements GuardedNode {
    public static final NodeClass<DummyGuardHandle> TYPE = NodeClass.create(DummyGuardHandle.class);

    @Input(InputType.Guard)
    GuardingNode guard;

    protected DummyGuardHandle(GuardingNode guard) {
      super(TYPE, StampFactory.forVoid());
      this.guard = guard;
    }

    public GuardingNode getGuard() {
      return guard;
    }

    public void setGuard(GuardingNode guard) {
      updateUsagesInterface(this.guard, guard);
      this.guard = guard;
    }

    @Override
    public ValueNode asNode() {
      return this;
    }
  }
示例#4
0
/**
 * A node that changes the type of its input, usually narrowing it. For example, a GuardedValueNode
 * is used to keep the nodes depending on guards inside a loop during speculative guard movement.
 *
 * <p>A GuardedValueNode will only go away if its guard is null or {@link StructuredGraph#start()}.
 */
@NodeInfo
public final class GuardedValueNode extends FloatingGuardedNode
    implements LIRLowerable, Virtualizable, IterableNodeType, Canonicalizable, ValueProxy {

  public static final NodeClass<GuardedValueNode> TYPE = NodeClass.create(GuardedValueNode.class);
  @Input ValueNode object;
  protected final Stamp piStamp;

  public GuardedValueNode(ValueNode object, GuardingNode guard, Stamp stamp) {
    super(TYPE, stamp, guard);
    this.object = object;
    this.piStamp = stamp;
  }

  public GuardedValueNode(ValueNode object, GuardingNode guard) {
    this(object, guard, object.stamp());
  }

  public ValueNode object() {
    return object;
  }

  @Override
  public void generate(NodeLIRBuilderTool generator) {
    if (object.getStackKind() != JavaKind.Void && object.getStackKind() != JavaKind.Illegal) {
      generator.setResult(this, generator.operand(object));
    }
  }

  @Override
  public boolean inferStamp() {
    return updateStamp(piStamp.improveWith(object().stamp()));
  }

  @Override
  public void virtualize(VirtualizerTool tool) {
    ValueNode alias = tool.getAlias(object());
    if (alias instanceof VirtualObjectNode) {
      tool.replaceWithVirtual((VirtualObjectNode) alias);
    }
  }

  @Override
  public Node canonical(CanonicalizerTool tool) {
    if (getGuard() == null) {
      if (stamp().equals(object().stamp())) {
        return object();
      } else {
        return new PiNode(object(), stamp());
      }
    }
    return this;
  }

  @Override
  public ValueNode getOriginalNode() {
    return object;
  }
}
示例#5
0
@NodeInfo(allowedUsageTypes = {InputType.Association})
public final class EndNode extends AbstractEndNode {
  public static final NodeClass<EndNode> TYPE = NodeClass.create(EndNode.class);

  public EndNode() {
    super(TYPE);
  }
}
示例#6
0
/** The {@code StoreFieldNode} represents a write to a static or instance field. */
@NodeInfo(nameTemplate = "StoreField#{p#field/s}")
public final class StoreFieldNode extends AccessFieldNode implements StateSplit, Virtualizable {
  public static final NodeClass<StoreFieldNode> TYPE = NodeClass.create(StoreFieldNode.class);

  @Input ValueNode value;

  @OptionalInput(InputType.State)
  FrameState stateAfter;

  public FrameState stateAfter() {
    return stateAfter;
  }

  public void setStateAfter(FrameState x) {
    assert x == null || x.isAlive() : "frame state must be in a graph";
    updateUsages(stateAfter, x);
    stateAfter = x;
  }

  public boolean hasSideEffect() {
    return true;
  }

  public ValueNode value() {
    return value;
  }

  public StoreFieldNode(ValueNode object, ResolvedJavaField field, ValueNode value) {
    super(TYPE, StampFactory.forVoid(), object, field);
    this.value = value;
  }

  public StoreFieldNode(
      ValueNode object, ResolvedJavaField field, ValueNode value, FrameState stateAfter) {
    super(TYPE, StampFactory.forVoid(), object, field);
    this.value = value;
    this.stateAfter = stateAfter;
  }

  @Override
  public void virtualize(VirtualizerTool tool) {
    ValueNode alias = tool.getAlias(object());
    if (alias instanceof VirtualObjectNode) {
      VirtualInstanceNode virtual = (VirtualInstanceNode) alias;
      int fieldIndex = virtual.fieldIndex(field());
      if (fieldIndex != -1) {
        tool.setVirtualEntry(virtual, fieldIndex, value(), false);
        tool.delete();
      }
    }
  }

  public FrameState getState() {
    return stateAfter;
  }
}
示例#7
0
  @NodeInfo
  static final class TestNode extends Node {
    public static final NodeClass<TestNode> TYPE = NodeClass.create(TestNode.class);
    @Input NodeInputList<ValueNode> itail;
    @Input ConstantNode i1;
    @Input FloatingNode i2;

    protected TestNode() {
      super(TYPE);
    }
  }
  @NodeInfo(cycles = CYCLES_UNKNOWN, size = SIZE_UNKNOWN)
  static final class TestNode extends Node {
    public static final NodeClass<TestNode> TYPE = NodeClass.create(TestNode.class);

    @Input TestNode input;
    @Successor TestNode successor;

    protected TestNode(TestNode input, TestNode successor) {
      super(TYPE);
      this.input = input;
      this.successor = successor;
    }
  }
示例#9
0
/** Start node for a {@link Stub}'s graph. */
@NodeInfo(cycles = CYCLES_0, size = SIZE_0)
public final class StubStartNode extends StartNode {

  public static final NodeClass<StubStartNode> TYPE = NodeClass.create(StubStartNode.class);
  protected final Stub stub;

  public StubStartNode(Stub stub) {
    super(TYPE);
    this.stub = stub;
  }

  public Stub getStub() {
    return stub;
  }
}
@NodeInfo
public abstract class DeoptimizingStubCall extends DeoptimizingFixedWithNextNode {

  public static final NodeClass<DeoptimizingStubCall> TYPE =
      NodeClass.create(DeoptimizingStubCall.class);

  public DeoptimizingStubCall(NodeClass<? extends DeoptimizingStubCall> c, Stamp stamp) {
    super(c, stamp);
  }

  @Override
  public boolean canDeoptimize() {
    return true;
  }
}
/** A call to the runtime code {@code Deoptimization::fetch_unroll_info}. */
@NodeInfo(allowedUsageTypes = {InputType.Memory})
public final class DeoptimizationFetchUnrollInfoCallNode extends FixedWithNextNode
    implements LIRLowerable, MemoryCheckpoint.Single {

  public static final NodeClass<DeoptimizationFetchUnrollInfoCallNode> TYPE =
      NodeClass.create(DeoptimizationFetchUnrollInfoCallNode.class);
  @Input SaveAllRegistersNode registerSaver;
  @Input ValueNode mode;
  protected final ForeignCallsProvider foreignCalls;

  public DeoptimizationFetchUnrollInfoCallNode(
      @InjectedNodeParameter ForeignCallsProvider foreignCalls,
      ValueNode registerSaver,
      ValueNode mode) {
    super(TYPE, StampFactory.forKind(JavaKind.fromJavaClass(FETCH_UNROLL_INFO.getResultType())));
    this.registerSaver = (SaveAllRegistersNode) registerSaver;
    this.mode = mode;
    this.foreignCalls = foreignCalls;
  }

  @Override
  public LocationIdentity getLocationIdentity() {
    return LocationIdentity.any();
  }

  public SaveRegistersOp getSaveRegistersOp() {
    return registerSaver.getSaveRegistersOp();
  }

  /**
   * Returns the node representing the exec_mode/unpack_kind used during this fetch_unroll_info
   * call.
   */
  public ValueNode getMode() {
    return mode;
  }

  @Override
  public void generate(NodeLIRBuilderTool gen) {
    Value result =
        ((HotSpotLIRGenerator) gen.getLIRGeneratorTool())
            .emitDeoptimizationFetchUnrollInfoCall(gen.operand(getMode()), getSaveRegistersOp());
    gen.setResult(this, result);
  }

  @NodeIntrinsic
  public static native Word fetchUnrollInfo(long registerSaver, int mode);
}
示例#12
0
/**
 * The {@code Parameter} instruction is a placeholder for an incoming argument to a function call.
 */
@NodeInfo(nameTemplate = "P({p#index})")
public final class ParameterNode extends AbstractLocalNode
    implements IterableNodeType, UncheckedInterfaceProvider {

  public static final NodeClass<ParameterNode> TYPE = NodeClass.create(ParameterNode.class);

  private Stamp uncheckedStamp;

  public ParameterNode(int index, StampPair stamp) {
    super(TYPE, index, stamp.getTrustedStamp());
    this.uncheckedStamp = stamp.getUncheckedStamp();
  }

  public Stamp uncheckedStamp() {
    return uncheckedStamp;
  }
}
/** Logic node that negates its argument. */
@NodeInfo
public final class LogicNegationNode extends LogicNode implements Canonicalizable.Unary<LogicNode> {

  public static final NodeClass<LogicNegationNode> TYPE = NodeClass.create(LogicNegationNode.class);

  @Input(InputType.Condition)
  LogicNode value;

  public LogicNegationNode(LogicNode value) {
    super(TYPE);
    this.value = value;
  }

  public static LogicNode create(LogicNode value) {
    LogicNode synonym = findSynonym(value);
    if (synonym != null) {
      return synonym;
    }
    return new LogicNegationNode(value);
  }

  private static LogicNode findSynonym(LogicNode value) {
    if (value instanceof LogicConstantNode) {
      LogicConstantNode logicConstantNode = (LogicConstantNode) value;
      return LogicConstantNode.forBoolean(!logicConstantNode.getValue());
    } else if (value instanceof LogicNegationNode) {
      return ((LogicNegationNode) value).getValue();
    }
    return null;
  }

  public LogicNode getValue() {
    return value;
  }

  @Override
  public LogicNode canonical(CanonicalizerTool tool, LogicNode forValue) {
    LogicNode synonym = findSynonym(forValue);
    if (synonym != null) {
      return synonym;
    }
    return this;
  }
}
/**
 * This node represents an unconditional explicit request for immediate deoptimization.
 *
 * <p>After this node, execution will continue using a fallback execution engine (such as an
 * interpreter) at the position described by the {@link #stateBefore() deoptimization state}.
 */
@NodeInfo
public abstract class AbstractDeoptimizeNode extends ControlSinkNode
    implements IterableNodeType, DeoptimizingNode.DeoptBefore {

  public static final NodeClass<AbstractDeoptimizeNode> TYPE =
      NodeClass.create(AbstractDeoptimizeNode.class);

  @OptionalInput(InputType.State)
  FrameState stateBefore;

  protected AbstractDeoptimizeNode(
      NodeClass<? extends AbstractDeoptimizeNode> c, FrameState stateBefore) {
    super(c, StampFactory.forVoid());
    this.stateBefore = stateBefore;
  }

  @Override
  public boolean canDeoptimize() {
    return true;
  }

  @Override
  public FrameState stateBefore() {
    return stateBefore;
  }

  @Override
  public void setStateBefore(FrameState f) {
    updateUsages(stateBefore, f);
    stateBefore = f;
  }

  public abstract ValueNode getActionAndReason(MetaAccessProvider metaAccess);

  public abstract ValueNode getSpeculation(MetaAccessProvider metaAccess);
}
示例#15
0
// @formatter:off
@NodeInfo(
    cycles = CYCLES_UNKNOWN,
    cyclesRationale =
        "If this node is not optimized away it will be lowered to a call, which we cannot estimate",
    size = SIZE_UNKNOWN,
    sizeRationale =
        "If this node is not optimized away it will be lowered to a call, which we cannot estimate")
// @formatter:on
public abstract class MacroNode extends FixedWithNextNode implements Lowerable {

  public static final NodeClass<MacroNode> TYPE = NodeClass.create(MacroNode.class);
  @Input protected NodeInputList<ValueNode> arguments;

  protected final int bci;
  protected final ResolvedJavaMethod targetMethod;
  protected final StampPair returnStamp;
  protected final InvokeKind invokeKind;

  protected MacroNode(
      NodeClass<? extends MacroNode> c,
      InvokeKind invokeKind,
      ResolvedJavaMethod targetMethod,
      int bci,
      StampPair returnStamp,
      ValueNode... arguments) {
    super(c, returnStamp.getTrustedStamp());
    assert targetMethod.getSignature().getParameterCount(!targetMethod.isStatic())
        == arguments.length;
    this.arguments = new NodeInputList<>(this, arguments);
    this.bci = bci;
    this.targetMethod = targetMethod;
    this.returnStamp = returnStamp;
    this.invokeKind = invokeKind;
    assert !isPlaceholderBci(bci);
  }

  public int getBci() {
    return bci;
  }

  public ResolvedJavaMethod getTargetMethod() {
    return targetMethod;
  }

  protected FrameState stateAfter() {
    return null;
  }

  /**
   * Gets a snippet to be used for lowering this macro node. The returned graph (if non-null) must
   * have been {@linkplain #lowerReplacement(StructuredGraph, LoweringTool) lowered}.
   */
  @SuppressWarnings("unused")
  protected StructuredGraph getLoweredSnippetGraph(LoweringTool tool) {
    return null;
  }

  /**
   * Applies {@linkplain LoweringPhase lowering} to a replacement graph.
   *
   * @param replacementGraph a replacement (i.e., snippet or method substitution) graph
   */
  @SuppressWarnings("try")
  protected StructuredGraph lowerReplacement(
      final StructuredGraph replacementGraph, LoweringTool tool) {
    final PhaseContext c =
        new PhaseContext(
            tool.getMetaAccess(),
            tool.getConstantReflection(),
            tool.getConstantFieldProvider(),
            tool.getLowerer(),
            tool.getReplacements(),
            tool.getStampProvider(),
            tool.getNodeCostProvider());
    if (!graph().hasValueProxies()) {
      new RemoveValueProxyPhase().apply(replacementGraph);
    }
    GuardsStage guardsStage = graph().getGuardsStage();
    if (!guardsStage.allowsFloatingGuards()) {
      new GuardLoweringPhase().apply(replacementGraph, null);
      if (guardsStage.areFrameStatesAtDeopts()) {
        new FrameStateAssignmentPhase().apply(replacementGraph);
      }
    }
    try (Scope s = Debug.scope("LoweringSnippetTemplate", replacementGraph)) {
      new LoweringPhase(new CanonicalizerPhase(), tool.getLoweringStage())
          .apply(replacementGraph, c);
    } catch (Throwable e) {
      throw Debug.handle(e);
    }
    return replacementGraph;
  }

  @Override
  public void lower(LoweringTool tool) {
    StructuredGraph replacementGraph = getLoweredSnippetGraph(tool);

    InvokeNode invoke = replaceWithInvoke();
    assert invoke.verify();

    if (replacementGraph != null) {
      // Pull out the receiver null check so that a replaced
      // receiver can be lowered if necessary
      if (!targetMethod.isStatic()) {
        ValueNode nonNullReceiver = InliningUtil.nonNullReceiver(invoke);
        if (nonNullReceiver instanceof Lowerable) {
          ((Lowerable) nonNullReceiver).lower(tool);
        }
      }
      InliningUtil.inline(invoke, replacementGraph, false, null);
      Debug.dump(Debug.INFO_LOG_LEVEL, graph(), "After inlining replacement %s", replacementGraph);
    } else {
      if (isPlaceholderBci(invoke.bci())) {
        throw new GraalError("%s: cannot lower to invoke with placeholder BCI: %s", graph(), this);
      }

      if (invoke.stateAfter() == null) {
        ResolvedJavaMethod method = graph().method();
        if (method.getAnnotation(MethodSubstitution.class) != null
            || method.getAnnotation(Snippet.class) != null) {
          // One cause for this is that a MacroNode is created for a method that
          // no longer needs a MacroNode. For example, Class.getComponentType()
          // only needs a MacroNode prior to JDK9 as it was given a non-native
          // implementation in JDK9.
          throw new GraalError(
              "%s macro created for call to %s in %s must be lowerable to a snippet or intrinsic graph. "
                  + "Maybe a macro node is not needed for this method in the current JDK?",
              getClass().getSimpleName(), targetMethod.format("%h.%n(%p)"), graph());
        }
        throw new GraalError("%s: cannot lower to invoke without state: %s", graph(), this);
      }
      invoke.lower(tool);
    }
  }

  protected InvokeNode replaceWithInvoke() {
    InvokeNode invoke = createInvoke();
    graph().replaceFixedWithFixed(this, invoke);
    return invoke;
  }

  protected InvokeNode createInvoke() {
    MethodCallTargetNode callTarget =
        graph()
            .add(
                new MethodCallTargetNode(
                    invokeKind,
                    targetMethod,
                    arguments.toArray(new ValueNode[arguments.size()]),
                    returnStamp,
                    null));
    InvokeNode invoke = graph().add(new InvokeNode(callTarget, bci));
    if (stateAfter() != null) {
      invoke.setStateAfter(stateAfter().duplicate());
      if (getStackKind() != JavaKind.Void) {
        invoke.stateAfter().replaceFirstInput(this, invoke);
      }
    }
    return invoke;
  }
}
@NodeInfo(
    allowedUsageTypes = {InputType.Memory, InputType.Value},
    cycles = CYCLES_UNKNOWN,
    size = SIZE_UNKNOWN)
public final class CheckcastArrayCopyCallNode extends AbstractMemoryCheckpoint
    implements Lowerable, MemoryCheckpoint.Single {

  public static final NodeClass<CheckcastArrayCopyCallNode> TYPE =
      NodeClass.create(CheckcastArrayCopyCallNode.class);
  @Input ValueNode src;
  @Input ValueNode srcPos;
  @Input ValueNode dest;
  @Input ValueNode destPos;
  @Input ValueNode length;
  @Input ValueNode destElemKlass;
  @Input ValueNode superCheckOffset;

  protected final boolean uninit;

  protected final HotSpotGraalRuntimeProvider runtime;

  protected CheckcastArrayCopyCallNode(
      @InjectedNodeParameter HotSpotGraalRuntimeProvider runtime,
      ValueNode src,
      ValueNode srcPos,
      ValueNode dest,
      ValueNode destPos,
      ValueNode length,
      ValueNode superCheckOffset,
      ValueNode destElemKlass,
      boolean uninit) {
    super(TYPE, StampFactory.forKind(JavaKind.Int));
    this.src = src;
    this.srcPos = srcPos;
    this.dest = dest;
    this.destPos = destPos;
    this.length = length;
    this.superCheckOffset = superCheckOffset;
    this.destElemKlass = destElemKlass;
    this.uninit = uninit;
    this.runtime = runtime;
  }

  public ValueNode getSource() {
    return src;
  }

  public ValueNode getSourcePosition() {
    return srcPos;
  }

  public ValueNode getDestination() {
    return dest;
  }

  public ValueNode getDestinationPosition() {
    return destPos;
  }

  public ValueNode getLength() {
    return length;
  }

  public boolean isUninit() {
    return uninit;
  }

  private ValueNode computeBase(ValueNode base, ValueNode pos) {
    FixedWithNextNode basePtr = graph().add(new GetObjectAddressNode(base));
    graph().addBeforeFixed(this, basePtr);

    int shift = CodeUtil.log2(getArrayIndexScale(JavaKind.Object));
    ValueNode scaledIndex =
        graph().unique(new LeftShiftNode(pos, ConstantNode.forInt(shift, graph())));
    ValueNode offset =
        graph()
            .unique(
                new AddNode(
                    scaledIndex,
                    ConstantNode.forInt(getArrayBaseOffset(JavaKind.Object), graph())));
    return graph().unique(new OffsetAddressNode(basePtr, offset));
  }

  @Override
  public void lower(LoweringTool tool) {
    if (graph().getGuardsStage().areFrameStatesAtDeopts()) {
      ForeignCallDescriptor desc =
          HotSpotHostForeignCallsProvider.lookupCheckcastArraycopyDescriptor(isUninit());
      StructuredGraph graph = graph();
      ValueNode srcAddr = computeBase(getSource(), getSourcePosition());
      ValueNode destAddr = computeBase(getDestination(), getDestinationPosition());
      ValueNode len = getLength();
      if (len.stamp().getStackKind() != runtime.getTarget().wordJavaKind) {
        len =
            IntegerConvertNode.convert(
                len, StampFactory.forKind(runtime.getTarget().wordJavaKind), graph());
      }
      ForeignCallNode call =
          graph.add(
              new ForeignCallNode(
                  runtime.getHostBackend().getForeignCalls(),
                  desc,
                  srcAddr,
                  destAddr,
                  len,
                  superCheckOffset,
                  destElemKlass));
      call.setStateAfter(stateAfter());
      graph.replaceFixedWithFixed(this, call);
    }
  }

  @Override
  public LocationIdentity getLocationIdentity() {
    /*
     * Because of restrictions that the memory graph of snippets matches the original node,
     * pretend that we kill any.
     */
    return LocationIdentity.any();
  }

  @NodeIntrinsic
  public static native int checkcastArraycopy(
      Object src,
      int srcPos,
      Object dest,
      int destPos,
      int length,
      Word superCheckOffset,
      Object destElemKlass,
      @ConstantNodeParameter boolean uninit);
}
/**
 * Represents the lowered version of an atomic compare-and-swap operation{@code CompareAndSwapNode}.
 */
@NodeInfo(
    allowedUsageTypes = {Value, Memory},
    cycles = CYCLES_30,
    size = SIZE_8)
public final class LoweredCompareAndSwapNode extends FixedAccessNode
    implements StateSplit, LIRLowerable, MemoryCheckpoint.Single {

  public static final NodeClass<LoweredCompareAndSwapNode> TYPE =
      NodeClass.create(LoweredCompareAndSwapNode.class);
  @Input ValueNode expectedValue;
  @Input ValueNode newValue;

  @OptionalInput(State)
  FrameState stateAfter;

  @Override
  public FrameState stateAfter() {
    return stateAfter;
  }

  @Override
  public void setStateAfter(FrameState x) {
    assert x == null || x.isAlive() : "frame state must be in a graph";
    updateUsages(stateAfter, x);
    stateAfter = x;
  }

  @Override
  public boolean hasSideEffect() {
    return true;
  }

  public ValueNode getExpectedValue() {
    return expectedValue;
  }

  public ValueNode getNewValue() {
    return newValue;
  }

  public LoweredCompareAndSwapNode(
      AddressNode address,
      LocationIdentity location,
      ValueNode expectedValue,
      ValueNode newValue,
      BarrierType barrierType) {
    super(
        TYPE,
        address,
        location,
        StampFactory.forKind(JavaKind.Boolean.getStackKind()),
        barrierType);
    assert expectedValue.getStackKind() == newValue.getStackKind();
    this.expectedValue = expectedValue;
    this.newValue = newValue;
  }

  @Override
  public boolean canNullCheck() {
    return false;
  }

  @Override
  public void generate(NodeLIRBuilderTool gen) {
    assert getNewValue().stamp().isCompatible(getExpectedValue().stamp());
    LIRGeneratorTool tool = gen.getLIRGeneratorTool();

    LIRKind resultKind = tool.getLIRKind(stamp());
    Value trueResult = tool.emitConstant(resultKind, JavaConstant.TRUE);
    Value falseResult = tool.emitConstant(resultKind, JavaConstant.FALSE);
    Value result =
        tool.emitCompareAndSwap(
            gen.operand(getAddress()),
            gen.operand(getExpectedValue()),
            gen.operand(getNewValue()),
            trueResult,
            falseResult);

    gen.setResult(this, result);
  }
}