// return (address of) next ref in the current "frame" on the
  // threads JNIEnvironment stack of refs
  // When at the end of the current frame, update register locations to point
  // to the non-volatile registers saved in the JNI transition frame.
  //
  public Address getNextReferenceAddress() {
    // first report jni refs in the current frame in the jniRef side stack
    // until all in the frame are reported
    //
    if (jniNextRef > jniFramePtr) {
      Address ref_address = Magic.objectAsAddress(jniRefs).plus(jniNextRef);
      jniNextRef -= BYTES_IN_ADDRESS;
      return ref_address;
    }

    // no more refs to report, before returning 0, setup for processing
    // the next jni frame, if any

    // jniNextRef -> savedFramePtr for another "frame" of refs for another
    // sequence of Native C frames lower in the stack, or to 0 if this is the
    // last jni frame in the JNIRefs stack.  If more frames, initialize for a
    // later scan of those refs.
    //
    if (jniFramePtr > 0) {
      jniFramePtr = jniRefs.get(jniFramePtr >> LOG_BYTES_IN_ADDRESS).toInt();
      jniNextRef = jniNextRef - BYTES_IN_ADDRESS;
    }

    // set register locations for non-volatiles to point to registers saved in
    // the JNI transition frame at a fixed negative offset from the callers FP.
    // the save non-volatiles are EBX EBP and EDI.
    //
    registerLocations.set(EDI.value(), framePtr.plus(JNICompiler.EDI_SAVE_OFFSET));
    registerLocations.set(EBX.value(), framePtr.plus(JNICompiler.EBX_SAVE_OFFSET));
    registerLocations.set(EBP.value(), framePtr.plus(JNICompiler.EBP_SAVE_OFFSET));

    return Address.zero(); // no more refs to report
  }
 /**
  * Pop an address from the address stack, return zero if the stack is empty.
  *
  * @return The next address in the address stack, or zero if the stack is empty
  */
 @Inline
 public final Address pop() {
   if (checkDequeue(1)) {
     return uncheckedDequeue();
   } else {
     return Address.zero();
   }
 }
Example #3
0
 /**
  * Resolve a symbol to an address in a currently loaded dynamic library.
  *
  * @return the address of the symbol of Address.zero() if it cannot be resolved
  */
 public static synchronized Address resolveSymbol(String symbol) {
   for (VM_DynamicLibrary lib : dynamicLibraries.values()) {
     Address symbolAddress = lib.getSymbol(symbol);
     if (!symbolAddress.isZero()) {
       return symbolAddress;
     }
   }
   return Address.zero();
 }
Example #4
0
  /**
   * Cast bits. Note: the returned integer is only valid until next garbage collection cycle
   * (thereafter the referenced object might have moved and its address changed)
   *
   * @param object object reference
   * @return object reference as bits
   */
  public static <T> Address objectAsAddress(T object) {
    if (VM.runningVM && VM.VerifyAssertions) {
      VM._assert(VM.NOT_REACHED); // call site should have been hijacked by magic in compiler
    }

    if (objectAddressRemapper == null) {
      return Address.zero(); // tool isn't interested in remapping
    }

    return objectAddressRemapper.objectAsAddress(object);
  }
 /** Reset the allocator. Note that this does not reset the space. */
 public void reset() {
   cursor = Address.zero();
   limit = Address.zero();
   largeCursor = Address.zero();
   largeLimit = Address.zero();
   markTable = Address.zero();
   recyclableBlock = Address.zero();
   requestForLarge = false;
   recyclableExhausted = false;
   line = LINES_IN_BLOCK;
   lineUseCount = 0;
 }
 public Address getNextReturnAddressAddress() {
   return Address.zero();
 }
 static void deleteGlobalRef(int index) {
   if (VM.VerifyAssertions) VM._assert(!isWeakRef(index));
   JNIGlobalRefs.set(-index, Address.zero());
 }
 public static Address getDirectBufferAddress(Buffer buffer) {
   if (buffer.address == null) return Address.zero();
   else return gnu.classpath.JikesRVMSupport.getAddressFromPointer(buffer.address);
 }
Example #9
0
  /**
   * This method is called when a call stack edge needs to be sampled. Expect the sfp argument to
   * point to the stack frame that contains the target of the edge to be sampled.
   *
   * <p>NOTE: This method is uninterruptible, therefore we don't need to disable thread switching
   * during stackframe inspection.
   *
   * @param sfp a pointer to the stack frame that corresponds to the callee of the call graph edge
   *     that is to be sampled.
   * @param whereFrom Was this a yieldpoint in a PROLOGUE, BACKEDGE, or EPILOGUE?
   */
  @Override
  public final void update(Address sfp, int whereFrom) {
    if (DEBUG) {
      VM.sysWrite("EdgeListener.update(", sfp, ",", whereFrom);
      VM.sysWriteln("): enter ", samplesTaken);
    }

    Synchronization.fetchAndAdd(this, AosEntrypoints.edgeListenerUpdateCalledField.getOffset(), 1);

    // don't take a sample for back edge yield points
    if (whereFrom == RVMThread.BACKEDGE) return;

    int calleeCMID = 0;
    int callerCMID = 0;
    Address returnAddress = Address.zero();

    if (sfp.loadAddress().EQ(STACKFRAME_SENTINEL_FP)) {
      if (DEBUG) VM.sysWrite(" Walking off end of stack!\n");
      return;
    }

    calleeCMID = Magic.getCompiledMethodID(sfp);
    if (calleeCMID == INVISIBLE_METHOD_ID) {
      if (DEBUG) {
        VM.sysWrite(" INVISIBLE_METHOD_ID  (assembler code) ");
        VM.sysWrite(calleeCMID);
        VM.sysWrite("\n");
      }
      return;
    }

    returnAddress = Magic.getReturnAddress(sfp); // return address in caller
    sfp = Magic.getCallerFramePointer(sfp); // caller's frame pointer
    if (sfp.loadAddress().EQ(STACKFRAME_SENTINEL_FP)) {
      if (DEBUG) VM.sysWrite(" Walking off end of stack\n");
      return;
    }
    callerCMID = Magic.getCompiledMethodID(sfp);
    if (callerCMID == INVISIBLE_METHOD_ID) {
      if (DEBUG) {
        VM.sysWrite(" INVISIBLE_METHOD_ID  (assembler code) ");
        VM.sysWrite(callerCMID);
        VM.sysWrite("\n");
      }
      return;
    }

    // store the offset of the return address from the beginning of the
    // instruction
    CompiledMethod callerCM = CompiledMethods.getCompiledMethod(callerCMID);
    if (callerCM.getCompilerType() == CompiledMethod.TRAP) {
      if (DEBUG) {
        VM.sysWriteln(" HARDWARE TRAP FRAME ");
      }
      return;
    }
    Offset callSite = callerCM.getInstructionOffset(returnAddress);

    if (DEBUG) {
      VM.sysWrite("  <");
      VM.sysWrite(calleeCMID);
      VM.sysWrite(",");
      VM.sysWrite(callerCMID);
      VM.sysWrite(",");
      VM.sysWrite(returnAddress);
      VM.sysWrite(">\n");
    }

    // Find out what sample we are.
    int sampleNumber =
        Synchronization.fetchAndAdd(
            this, AosEntrypoints.edgeListenerSamplesTakenField.getOffset(), 1);
    int idx = 3 * sampleNumber;

    // If we got buffer slots that are beyond the end of the buffer, that means
    // that we're actually not supposed to take the sample at all (the system
    // is in the process of activating our organizer and processing the buffer).
    if (idx < buffer.length) {
      buffer[idx + 1] = callerCMID;
      buffer[idx + 2] = callSite.toInt();
      Magic.sync();
      buffer[idx + 0] = calleeCMID;

      // If we are the last sample, we need to activate the organizer.
      if (sampleNumber + 1 == desiredSamples) {
        activateOrganizer();
      }
    }
  }