//===- ClasspathVMClassLoader.cpp - GNU classpath java/lang/VMClassLoader -===//
//
//                            The VMKit project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "types.h"

#include "Classpath.h"
#include "JavaAccess.h"
#include "JavaArray.h"
#include "JavaClass.h"
#include "JavaConstantPool.h"
#include "JavaObject.h"
#include "JavaString.h"
#include "JavaThread.h"
#include "JavaUpcalls.h"
#include "Jnjvm.h"
#include "Reader.h"

using namespace j3;

extern "C" {

JavaObject* internalFillInStackTrace(JavaObject* throwable) {
  
  JavaObject* vmThrowable = 0;
  llvm_gcroot(throwable, 0);
  llvm_gcroot(vmThrowable, 0);

  JavaThread* th = JavaThread::get();
  Jnjvm* vm = th->getJVM();
 
  uint32 length = th->getFrameContextLength();

  ClassArray* cl = sizeof(void*) == 4 ? vm->upcalls->ArrayOfInt : 
                                        vm->upcalls->ArrayOfLong;
  JavaArray* result = (JavaArray*) cl->doNew(length, vm);
  void** tab = (void**)result->elements;
  
  // Get the frame context.
  th->getFrameContext(tab);
  
  // Set the tempory data in the new VMThrowable object.
  vmThrowable = vm->upcalls->newVMThrowable->doNew(vm);
  uint64 ptr = (uint64)vmThrowable + vm->upcalls->vmDataVMThrowable->ptrOffset;
  ((JavaObject**)ptr)[0] = result;
  return vmThrowable;
}

JNIEXPORT JavaObject* JNICALL Java_java_lang_VMThrowable_fillInStackTrace(
#ifdef NATIVE_JNI
JNIEnv *env,
jclass clazz,
#endif
JavaObject* throwable) {
  
  JavaObject* res = 0;
  llvm_gcroot(res, 0);
  llvm_gcroot(throwable, 0);

  BEGIN_NATIVE_EXCEPTION(0)

  res = internalFillInStackTrace(throwable);

  END_NATIVE_EXCEPTION

  return res;
}


static JavaObject* consStackElement(JavaMethod* meth, void* ip) {

  JavaString* methodName = 0;
  JavaString* className = 0;
  JavaString* sourceName = 0;
  JavaObject* res = 0;
  llvm_gcroot(methodName, 0);
  llvm_gcroot(className, 0);
  llvm_gcroot(sourceName, 0);
  llvm_gcroot(res, 0);

  Jnjvm* vm = JavaThread::get()->getJVM();
  methodName = vm->internalUTF8ToStr(meth->name);
  Class* cl = meth->classDef;
  className = JavaString::internalToJava(cl->name, vm);
  
  Attribut* sourceAtt = cl->lookupAttribut(Attribut::sourceFileAttribut);
  
  // We don't have the bytes if the class was vmjc'ed.
  if (sourceAtt && cl->getBytes()) {
    Reader reader(sourceAtt, cl->getBytesPtr());
    uint16 index = reader.readU2();
    sourceName = vm->internalUTF8ToStr(cl->getConstantPool()->UTF8At(index));
  }

  bool native = isNative(meth->access);
  uint16 lineNumber = meth->lookupLineNumber(reinterpret_cast<uintptr_t>(ip));

  UserClass* newS = vm->upcalls->newStackTraceElement;
  res = newS->doNew(vm);
  vm->upcalls->initStackTraceElement->invokeIntSpecial(vm, newS, res,
                                                       &sourceName,
                                                       lineNumber,
                                                       &className,
                                                       &methodName, native);
  return res;
}

JNIEXPORT JavaObject* JNICALL Java_java_lang_VMThrowable_getStackTrace(
#ifdef NATIVE_JNI
JNIEnv *env,
#endif
JavaObject* vmthrow, JavaObject* throwable) {

  ArrayObject* result = 0;
  llvm_gcroot(vmthrow, 0);
  llvm_gcroot(throwable, 0);
  llvm_gcroot(result, 0);

  BEGIN_NATIVE_EXCEPTION(0)
  Jnjvm* vm = JavaThread::get()->getJVM();
  JavaField* field = vm->upcalls->vmDataVMThrowable;
  JavaArray* stack = (JavaArray*)field->getObjectField(vmthrow);
  
  // remove the VMThrowable.fillInStackTrace method and the last method
  // on the stack.
  sint32 index = 2;;
  while (index != stack->size) {
    mvm::MethodInfo* MI = vm->IPToMethodInfo(stack->elements[index]);
    if (MI->MethodType != 1) ++index;
    else {
      JavaMethod* meth = (JavaMethod*)MI->getMetaInfo();
      assert(meth && "Wrong stack trace");
      if (meth->classDef->isAssignableFrom(vm->upcalls->newThrowable)) {
        ++index;
      } else break;
    }
  }
  
  sint32 size = 0;
  sint32 cur = index;
  while (cur < stack->size) {
    mvm::MethodInfo* MI = vm->IPToMethodInfo(stack->elements[cur]);
    ++cur;
    if (MI->MethodType == 1) ++size;
  }

  result = (ArrayObject*)
    vm->upcalls->stackTraceArray->doNew(size, vm);
  
  cur = 0;
  for (sint32 i = index; i < stack->size; ++i) {
    mvm::MethodInfo* MI = vm->IPToMethodInfo(stack->elements[i]);
    if (MI->MethodType == 1) {
      JavaMethod* meth = (JavaMethod*)MI->getMetaInfo();
      result->elements[cur] = consStackElement(meth, stack->elements[i]);
      cur++;
    }
  }
  
  END_NATIVE_EXCEPTION

  return result;
}

}

