Exemplo n.º 1
0
void set_debug(Debug *_debug)
{
  debug = _debug;
  debugThread = currentThread;
  debug->methodBase = ptr2word(get_method_table(get_class_record(0)));
  debug->classBase = ptr2word(get_class_base());
  debug->fieldBase = ptr2word(get_field_table(get_class_record(0)));
  debug->threads = threads;
  int i;
  for(i = 0; i < sizeof(debugEventOptions); i++)
    debugEventOptions[i] = DBG_EVENT_DISABLE;
}
Exemplo n.º 2
0
boolean debug_event(int event, Object *exception, const Thread *thread, const MethodRecord *method, byte *pc, int frame)
{
  // Inform the debug thread (if any) that there has been a debug event.
  // return false if no debug thread is waiting.
  switch(debugEventOptions[event])
  {
    case DBG_EVENT_DISABLE:
      return false;
    case DBG_EVENT_IGNORE:
      return true;
    default:
      break;
  }
  // Check that we have a debugger attached and that it is ready to go...
  if (!debug || get_monitor_count((&(debug->_super.sync))) != 0 ||
      debugThread->state != CONDVAR_WAITING || (Debug *)debugThread->waitingOn != debug)
    return false;
  // Setup the state
  debug->typ = event;
  debug->exception = ptr2ref(exception);
  debug->thread = ptr2ref(thread);
  debug->pc = (pc ? pc - get_binary_base() : 0);
  debug->method = (method ? method - get_method_table(get_class_record(0)) : 0);
  debug->frame = frame;
  // Suspend all threads (except current)
  suspend_thread(null);
  // Make sure current thread is also suspended
  suspend_thread(currentThread);
  //  Allow the debug thread to run
  resume_thread(debugThread);
  monitor_notify_unchecked(&debug->_super, 1);
  return true;
}
Exemplo n.º 3
0
/**
 * @return 1 or 0.
 */
STACKWORD instance_of (Object *obj, byte classIndex)
{
  byte rtType;

  if (obj == null)
    return 0;
  rtType = get_class_index(obj);
  // TBD: support for interfaces
  if (is_interface (get_class_record(classIndex)))
    return 1;
 LABEL_INSTANCE:
  if (rtType == classIndex)
    return 1;
  if (rtType == JAVA_LANG_OBJECT)
    return 0;
  rtType = get_class_record(rtType)->parentClass;
  goto LABEL_INSTANCE;
}
Exemplo n.º 4
0
/**
 * Check to see if obj is a sub type of the type described by
 * cls.
 */
static boolean sub_type_of(byte obj, const byte cls)
{
  if (cls == JAVA_LANG_OBJECT) return true;
  while (obj != cls)
  {
    obj = get_class_record(obj)->parentClass;
    if (obj == JAVA_LANG_OBJECT) return false;
  }
  return true;
}
Exemplo n.º 5
0
/**
 * Check to see if it is allowed to assign the an object of type srcCls
 * to an object of type dstCls.
 */
boolean is_assignable(const byte srcCls, const byte dstCls)
{
  ClassRecord *dstRec;
  // Check common cases
  if (srcCls == dstCls || dstCls == JAVA_LANG_OBJECT) return true;
  dstRec = get_class_record(dstCls);
  if (is_interface(dstRec))
  {
    // we are testing against an interface. So we use the associated interface
    // map to test if the src implements it...
    int base = get_interface_map_base(dstRec);
    // Special case all arrays implement cloneable
    if (dstCls == JAVA_LANG_CLONEABLE && is_array_class(get_class_record(srcCls))) return true;
    if (srcCls < base) return false;
    if (srcCls - base >= get_interface_map_len(dstRec)) return false;
    base = srcCls - base;
    return ((get_interface_map(dstRec)[base/8]) & (1 << (base%8))) != 0;
  }
  return sub_type_of(srcCls, dstCls);
}
Exemplo n.º 6
0
/**
 * Calls static initializer if necessary before
 * dispatching with dispatch_special().
 * @param retAddr Return bytecode address.
 * @param btAddr Backtrack bytecode address (in case
 *               static initializer is executed).
 */
void dispatch_special_checked (byte classIndex, byte methodIndex,
                               byte *retAddr, byte *btAddr)
{
  ClassRecord *classRecord;

  #if DEBUG_METHODS
  printf ("dispatch_special_checked: %d, %d, %d, %d\n",
          classIndex, methodIndex, (int) retAddr, (int) btAddr);
  #endif

  classRecord = get_class_record (classIndex);
  if (dispatch_static_initializer (classRecord, btAddr))
    return;
  dispatch_special (get_method_record (classRecord, methodIndex), retAddr);
}
Exemplo n.º 7
0
Arquivo: gc.c Projeto: Han40/spamOSEK
void mark (Object *obj)
{
    if (obj == JNULL)
        return;

#ifdef VERIFY_GC
    assert (is_allocated (obj), GC0);
#endif

    if (is_gc_marked (obj))
        return;
    set_gc_marked (obj);
    if (is_array (obj))
    {
        if (get_element_type (obj) == T_REFERENCE)
        {
            unsigned short i;
            unsigned short length = get_array_length (obj);
            REFERENCE *refarr = ref_array (obj);

            for (i = 0; i < length; i++)
                mark (refarr[i]);
        }
    }
    else
    {
        ClassRecord *classRecord;
        byte classIndex;

        classIndex = get_na_class_index (obj);
        for (;;)
        {
            classRecord = get_class_record (classIndex);
            // Mark fields of type REFERENCE.
            mark_reference_fields (obj, classRecord);
            if (classIndex == JAVA_LANG_OBJECT)
                break;
            classIndex = classRecord -> parentClass;
        }
    }
}
Exemplo n.º 8
0
void dispatch_virtual (Object *ref, int signature, byte *retAddr)
{
  ClassRecord *classRecord;
  MethodRecord *methodRecord;
  int classIndex;

#if DEBUG_METHODS
  printf("dispatch_virtual %d\n", signature);
#endif
  if (ref == JNULL)
  {
    throw_new_exception (JAVA_LANG_NULLPOINTEREXCEPTION);
    return;
  }
  // When calling methods on arrays, we use the methods for the Object class...
  classIndex = get_class_index(ref);
 LABEL_METHODLOOKUP:
  classRecord = get_class_record (classIndex);
  methodRecord = find_method (classRecord, signature);
  if (methodRecord == null)
  {
    #if SAFE
    if (classIndex == JAVA_LANG_OBJECT)
    {
      throw_new_exception (JAVA_LANG_NOSUCHMETHODERROR);
      return;
    }
    #endif
    classIndex = classRecord->parentClass;
    goto LABEL_METHODLOOKUP;
  }

  if (dispatch_special (methodRecord, retAddr))
  {
    if (is_synchronized(methodRecord))
    {
      current_stackframe()->monitor = ref;
      enter_monitor (currentThread, ref);
    }
  }
}
Exemplo n.º 9
0
void dispatch_virtual (Object *ref, TWOBYTES signature, byte *retAddr)
{
  MethodRecord *auxMethodRecord;
  byte auxByte;

#if DEBUG_METHODS
  printf("dispatch_virtual %d\n", signature);
#endif
  if (ref == JNULL)
  {
    throw_exception (nullPointerException);
    return;
  }

  auxByte = get_class_index(ref);
 LABEL_METHODLOOKUP:
  tempClassRecord = get_class_record (auxByte);
  auxMethodRecord = find_method (tempClassRecord, signature);
  if (auxMethodRecord == null)
  {
    #if SAFE
    if (auxByte == JAVA_LANG_OBJECT)
    {
      throw_exception (noSuchMethodError);
      return;
    }
    #endif
    auxByte = tempClassRecord->parentClass;
    goto LABEL_METHODLOOKUP;
  }

  if (dispatch_special (auxMethodRecord, retAddr))
  {
    if (is_synchronized(auxMethodRecord))
    {
      current_stackframe()->monitor = ref;
      enter_monitor (currentThread, ref);
    }
  }
}
Exemplo n.º 10
0
/**
 * Create a compact form of the specified  call stack.
 * One int per frame containing
 * the method number and current offset. If the ignore parameter is non null
 * then frames that have a matching this field will not be included in the
 * trace. This allow the frames for the creation of an exception object to
 * be ignored.
 */
Object *
create_stack_trace(Thread *thread, Object *ignore)
{
  int frameCnt = thread->stackFrameIndex;
  Object *stackArray;
  JINT *data;
  int i;
  StackFrame *topFrame = ((StackFrame *)array_start(thread->stackFrameArray)) + frameCnt;
  StackFrame *stackFrame = topFrame;
  MethodRecord *methodBase = get_method_table(get_class_record(0));
  byte *pcBase = get_binary_base() + 2;

  // Ignore frames if required.
  if (ignore)
  {
    while ((STACKWORD)ignore == *(stackFrame->localsBase))
    {
      stackFrame--;
      frameCnt--;
    }
  }
  // Try and allocate the space for the trace.
  stackArray = new_single_array(AI, frameCnt);
  if (stackArray == JNULL) return JNULL;
  if (thread == currentThread)
    topFrame->pc = getPc();
  // adjust top most pc to allow for return address hack
  topFrame->pc += 2;
  // Fill in the trace.
  data = jint_array(stackArray);
  for(i = 0; i < frameCnt; i++)
  {
    data[i] = ((stackFrame->methodRecord - methodBase) << 16) | (stackFrame->pc - pcBase - stackFrame->methodRecord->codeOffset);
    stackFrame--;
  }
  // restore correct pc
  topFrame->pc -= 2;
  return stackArray;
}
Exemplo n.º 11
0
/**
 * Calls static initializer if necessary before
 * dispatching with dispatch_special().
 * @param retAddr Return bytecode address.
 * @param btAddr Backtrack bytecode address (in case
 *               static initializer is executed).
 */
void dispatch_special_checked (byte classIndex, byte methodIndex,
                               byte *retAddr, byte *btAddr)
{
  ClassRecord *classRecord;
  MethodRecord *methodRecord;
  #if DEBUG_METHODS
  printf ("dispatch_special_checked: %d, %d, %d, %d\n",
          classIndex, methodIndex, (int) retAddr, (int) btAddr);
  #endif

  // If we need to run the initializer then the real method will get called
  // later, when we re-run the current instruction.
  classRecord = get_class_record (classIndex);
  if (!is_initialized_idx (classIndex))
    if (dispatch_static_initializer (classRecord, btAddr) != EXEC_CONTINUE)
      return;
  methodRecord = get_method_record (classRecord, methodIndex);
  if(dispatch_special (methodRecord, retAddr))
  {
    if (is_synchronized(methodRecord))
    {
      if (!is_static(methodRecord))
      {

        Object *ref = (Object *)curLocalsBase[0];
        current_stackframe()->monitor = ref;
        enter_monitor (currentThread, ref);
      }
      else
      {

        Object *ref = (Object *)classRecord;
        current_stackframe()->monitor = ref;
        enter_monitor (currentThread, ref);
      }
    }
  }
}
Exemplo n.º 12
0
/**
 * @param classRecord Record for method class.
 * @param methodRecord Calle's method record.
 * @param retAddr What the PC should be upon return.
 * @return true iff the stack frame was pushed.
 */
boolean dispatch_special (MethodRecord *methodRecord, byte *retAddr)
{
  /**
   * Note: This code is a little tricky, particularly when used with
   * a garbage collector. It manipulates the stack frame and in some cases
   * may need to perform memory allocation. In all cases we must take care
   * to ensure that if an allocation can be made then any live objects
   * on the stack must be below the current stack pointer.
   * In addition to the above we take great care so that this function can
   * be restarted (to allow us to wait for available memory). To enable this
   * we avoid making any commitments to changes to global state until both
   * stacks have been commited.
   */
  #if DEBUG_METHODS
  int debug_ctr;
  #endif

  Object *stackFrameArray;
  StackFrame *stackFrame;
  StackFrame *stackBase;
  int newStackFrameIndex;
  STACKWORD *newStackTop;
  #if DEBUG_BYTECODE
  printf("call method %d ret %x\n", methodRecord - get_method_table(get_class_record(0)), retAddr);
  printf ("\n------ dispatch special - %d ------------------\n\n",
          methodRecord->signatureId);
  #endif

  #if DEBUG_METHODS
  printf ("dispatch_special: %d, %d\n",
          (int) methodRecord, (int) retAddr);
  printf ("-- signature id = %d\n", methodRecord->signatureId);
  printf ("-- code offset  = %d\n", methodRecord->codeOffset);
  printf ("-- flags        = %d\n", methodRecord->mflags);
  printf ("-- num params   = %d\n", methodRecord->numParameters);
  //printf ("-- stack ptr    = %d\n", (int) get_stack_ptr());
  //printf ("-- max stack ptr= %d\n", (int) (currentThread->stackArray + (get_array_size(currentThread->stackArray))*2));
  #endif


  // First deal with the easy case of a native call...
  if (is_native (methodRecord))
  {
  #if DEBUG_METHODS
  printf ("-- native\n");
  #endif
    // WARNING: Once the instruction below has been executed we may have
    // references on the stack that are above the stack pointer. If a GC
    // gets run when in this state the reference may get collected as
    // grabage. This means that any native functions that take a reference
    // parameter and that may end up allocating memory *MUST* protect that
    // reference before calling the allocator...
    pop_words_cur (methodRecord->numParameters);
    switch(dispatch_native (methodRecord->signatureId, get_stack_ptr_cur() + 1))
    {
      case EXEC_RETRY:
        // Need to re-start the instruction, so reset the state of the stack
        curStackTop += methodRecord->numParameters;
        break;
      case EXEC_CONTINUE:
        // Normal completion return to the requested point.
        curPc = retAddr;
        break;
      case EXEC_RUN:
        // We are running new code, curPc will be set. Nothing to do.
        break;
      case EXEC_EXCEPTION:
        // An exception has been thrown. The PC will be set correctly and
        // the stack may have been adjusted...
        break;
    }
    // Stack frame not pushed
    return false;
  }
  // Now start to build the new stack frames. We start by placing the
  // the new stack pointer below any params. The params will become locals
  // in the new frame.
  newStackTop = get_stack_ptr_cur() - methodRecord->numParameters;

  newStackFrameIndex = (int)(byte)currentThread->stackFrameIndex;
  if (newStackFrameIndex >=  255)
  {
      throw_new_exception (JAVA_LANG_STACKOVERFLOWERROR);
      return false;
  }
  #if DEBUG_METHODS
  //for (debug_ctr = 0; debug_ctr < methodRecord->numParameters; debug_ctr++)
  //  printf ("-- param[%d]    = %ld\n", debug_ctr, (long) get_stack_ptr()[debug_ctr+1]);
  #endif
  stackFrameArray = ref2obj(currentThread->stackFrameArray);
  stackBase = (StackFrame *)array_start(stackFrameArray);
  // Setup OLD stackframe ready for return
  stackFrame = stackBase + (newStackFrameIndex);
  stackFrame->stackTop = newStackTop;
  stackFrame->pc = retAddr;
  // Push NEW stack frame
  // Increment size of stack frame array but do not commit to it until we have
  // completely built both new stacks.
  newStackFrameIndex++;
  stackFrame++;
  if (((byte *)stackFrame - (byte *)stackBase) >= get_array_length(stackFrameArray))
  {
#if FIXED_STACK_SIZE
    throw_new_exception (JAVA_LANG_STACKOVERFLOWERROR);
    return false;
#else
    if (expand_call_stack(currentThread) < 0)
      return false;
    stackFrame = (StackFrame *)array_start(currentThread->stackFrameArray) + newStackFrameIndex;
#endif
  }

  // Initialize rest of new stack frame
  stackFrame->methodRecord = methodRecord;
  stackFrame->monitor = null;
  stackFrame->localsBase = newStackTop + 1;
  // Allocate space for locals etc.
  newStackTop = init_sp(stackFrame, methodRecord);
  stackFrame->stackTop = newStackTop;
  currentThread->stackFrameIndex = newStackFrameIndex;

  // Check for stack overflow
  if (is_stack_overflow (newStackTop, methodRecord))
  {
#if FIXED_STACK_SIZE
    throw_new_exception (JAVA_LANG_STACKOVERFLOWERROR);
    return false;
#else

    if (expand_value_stack(currentThread, methodRecord->maxOperands+methodRecord->numLocals) < 0)
    {
      currentThread->stackFrameIndex--;
      return false;
    }
    // NOTE at this point newStackTop is no longer valid!
    newStackTop = stackFrame->stackTop;
#endif
  }
  // All set. So now we can finally commit to the new stack frames
  update_constant_registers (stackFrame);
  curStackTop = newStackTop;
  // and jump to the start of the new code
  curPc = get_code_ptr(methodRecord);
  return true;
}
Exemplo n.º 13
0
/**
 * Call a java static method from the VM
 * NOTE: This can only be used to call methods that have a signature
 * value that is less than 255. Normally it will be used to call
 * one of the specialsignature entries (which are all less than 255).
 */
void dispatch_java(byte classIndex, byte sig, byte *retAddr, byte *btAddr)
{
  ClassRecord *classRecord = get_class_record (classIndex);
  MethodRecord *mRec = find_method (classRecord, sig);
  dispatch_special_checked(classIndex, mRec - get_method_table(classRecord), retAddr, btAddr);
}
Exemplo n.º 14
0
/**
 * Exceute the static initializer if required. Note that the ret address used
 * here is set such that the current instruction will be re-started when the
 * initialization completes.
 * @return An indication of how the VM should proceed
 */
int dispatch_static_initializer (ClassRecord *aRec, byte *retAddr)
{
  int state = get_init_state(aRec);
  ClassRecord *init = aRec;
  ClassRecord *super = get_class_record(init->parentClass);
  MethodRecord *method;
  // Are we needed?
  if (state & C_INITIALIZED) return EXEC_CONTINUE;
  // We need to initialize all of the super classes first. So we find the
  // highest one that has not been initialized and deal with that. This code
  // will then be called again and we will init the next highest and so on
  // until all of the classes in the chain are done.
  for(;;)
  {
    // find first super class that has not been initialized
    while (init != super && (get_init_state(super) & C_INITIALIZED) == 0)
    {
      init = super;
      super = get_class_record(init->parentClass);
    }
    // Do we have an initilizer if so we have found our class
    if (has_clinit (init)) break;
    // no initializer so mark as now initialized
    set_init_state (init, C_INITIALIZED);
    // If we are at the start of the list we are done
    if (init == aRec) return EXEC_CONTINUE;
    // Otherwise go do it all again
    init = aRec;
  }
  state = get_init_state(init);
  // are we already initializing ?
  if (state & C_INITIALIZING)
  {
    // Is it this thread that is doing the init?
    if (get_sync(init)->threadId == currentThread->threadId)
      return EXEC_CONTINUE;
    // No so we must retry the current instruction
    curPc = retAddr;
    sleep_thread(1);
    schedule_request(REQUEST_SWITCH_THREAD);
    return EXEC_RETRY;
  }
  #if DEBUG_METHODS
  printf ("dispatch_static_initializer: has clinit: %d, %d\n",
          (int) aRec, (int) retAddr);
  #endif
  // Static initializer is always the first method
  method = get_method_table(init);
  if ((byte *)method == get_binary_base() || method->signatureId != _6clinit_7_4_5V)
  {
    throw_new_exception (JAVA_LANG_NOSUCHMETHODERROR);
    return EXEC_EXCEPTION;
  }

  // Can we run it?
  if (!dispatch_special (method, retAddr))
    return EXEC_RETRY;
  // Mark for next time
  set_init_state(init, C_INITIALIZING);
  // and claim the monitor
  current_stackframe()->monitor = (Object *)init;
  enter_monitor (currentThread, (Object *)init);
  return EXEC_RUN;
}