/**
   * Change machine code that will be used by future executions of this method (ie. optimized <->
   * non-optimized)
   *
   * <p>Side effect: updates JTOC or method dispatch tables ("type information blocks") for this
   * class and its subclasses
   *
   * @param compiledMethod new machine code
   */
  public final synchronized void replaceCompiledMethod(CompiledMethod compiledMethod) {
    if (VM.VerifyAssertions) VM._assert(getDeclaringClass().isInstantiated());
    // If we're replacing with a non-null compiledMethod, ensure that is still valid!
    if (compiledMethod != null) {
      synchronized (compiledMethod) {
        if (compiledMethod.isInvalid()) return;
      }
    }

    // Grab version that is being replaced
    CompiledMethod oldCompiledMethod = currentCompiledMethod;
    currentCompiledMethod = compiledMethod;

    // Install the new method in JTOC/TIB. If virtual, will also replace in
    // all subclasses that inherited the method.
    getDeclaringClass().updateMethod(this);

    // Replace constant-ified virtual method in JTOC if necessary
    Offset jtocOffset = getJtocOffset();
    if (jtocOffset.NE(Offset.zero())) {
      Statics.setSlotContents(jtocOffset, getCurrentEntryCodeArray());
    }

    // Now that we've updated the JTOC/TIB, old version is obsolete
    if (oldCompiledMethod != null) {
      CompiledMethods.setCompiledMethodObsolete(oldCompiledMethod);
    }
  }
  /** Generate machine code for this method if valid machine code doesn't already exist. */
  public final synchronized void compile() {
    if (VM.VerifyAssertions) VM._assert(getDeclaringClass().isResolved());
    if (isCompiled()) return;

    if (VM.TraceClassLoading && VM.runningVM)
      VM.sysWrite("RVMMethod: (begin) compiling " + this + "\n");

    CompiledMethod cm = genCode();

    // Ensure that cm wasn't invalidated while it was being compiled.
    synchronized (cm) {
      if (cm.isInvalid()) {
        CompiledMethods.setCompiledMethodObsolete(cm);
      } else {
        currentCompiledMethod = cm;
      }
    }

    if (VM.TraceClassLoading && VM.runningVM)
      VM.sysWrite("RVMMethod: (end)   compiling " + this + "\n");
  }