//===--- IsolateCommonClass.cpp - User visible classes with isolates -------===//
//
//                              JnJVM
//
// This file is distributed under the University of Illinois Open Source 
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//


#include "IsolateSharedLoader.h"
#include "JavaAllocator.h"
#include "JavaClass.h"
#include "JavaThread.h"
#include "JavaUpcalls.h"
#include "Jnjvm.h"
#include "JnjvmModule.h"

using namespace jnjvm;

UserCommonClass::UserCommonClass() {
  this->lockVar = mvm::Lock::allocRecursive();
  this->condVar = mvm::Cond::allocCond();
  this->status = loaded;
}

UserClass::UserClass(JnjvmClassLoader* JCL, const UTF8* name,
                     ArrayUInt8* bytes) {
  Class* cl = JnjvmSharedLoader::sharedLoader->constructSharedClass(name,
                                                                    bytes);
  if (!cl) {
    cl = allocator_new(JCL->allocator, Class)(JCL, name, bytes);
  }

  classDef = cl;
  classLoader = JCL;
  delegatee = 0;
  staticInstance = 0;
  ctpInfo = 0;
}

UserClassArray::UserClassArray(JnjvmClassLoader* JCL, const UTF8* name) {
  ClassArray* cl = JnjvmSharedLoader::sharedLoader->constructSharedClassArray(name);
  if (!cl) {
    cl = allocator_new(JCL->allocator, ClassArray)(JCL, name);
  }
  classDef = cl;
  classLoader = JCL;
  delegatee = 0;
  _baseClass = 0;
  _funcs = 0;
  super = JCL->bootstrapLoader->SuperArray;
  interfaces = JCL->bootstrapLoader->InterfacesArray;
  depth = 1;
  display = (UserCommonClass**)malloc(2 * sizeof(UserCommonClass*));
  display[0] = super;
  display[1] = this;
}

UserClassPrimitive::UserClassPrimitive(JnjvmClassLoader* JCL, const UTF8* name,
                                       uint32 nb) {
  ClassPrimitive* cl = 
    JnjvmSharedLoader::sharedLoader->constructSharedClassPrimitive(name, nb);
  if (!cl) {
    cl = new ClassPrimitive(JCL, name, nb);
  }
  classDef = cl;
  classLoader = JCL;
  delegatee = 0;
  display = (UserCommonClass**)malloc(sizeof(UserCommonClass*));
  display[0] = this;
  virtualSize = nb;
  status = ready;
}

void UserCommonClass::resolveClass() {
  if (status < resolved) {
    acquire();
    if (status >= resolved) {
      release();
    } else if (status == loaded) {
      if (isArray()) {
        UserClassArray* arrayCl = (UserClassArray*)this;
        UserCommonClass* baseClass =  arrayCl->baseClass();
        baseClass->resolveClass();
        status = resolved;
      } else {
        UserClass* cl = (UserClass*)this;
        Class* def = (Class*)classDef;
        if (classDef->status < resolved) {
          classDef->acquire();
          if (classDef->status == loaded) {
            def->readClass();
            def->status = classRead;
            status = classRead;
            cl->ctpInfo = 
              new(classLoader->allocator, def->ctpInfo->ctpSize) UserConstantPool(cl);
            cl->loadParents();
            if (cl->super)
              def->super = cl->super->classDef;
            for (std::vector<UserClass*>::iterator i = interfaces.begin(),
                 e = interfaces.end(); i != e; ++i) {
              def->interfaces.push_back((Class*)((*i)->classDef));
            }
            def->status = prepared;
            status = prepared;
            def->classLoader->TheModule->resolveVirtualClass(def);
            virtualSize = def->virtualSize;
            
            uint64 vtSize = def->virtualTableSize * sizeof(void*);
            
            virtualVT = (VirtualTable*)malloc(2 * vtSize);
            
            memcpy((void*)((uint64)virtualVT + vtSize), def->virtualVT, vtSize);
            if (super) {
              memcpy(virtualVT, (void*)((uint64)super->virtualVT - vtSize),
                     vtSize);
            }
            
            virtualVT = (VirtualTable*)((uint64)virtualVT + vtSize);
            
            for (CommonClass::method_iterator i = def->virtualMethods.begin(),
                 e = def->virtualMethods.end(); i != e; ++i) {
              if (i->second->offset > 0) {
                ((void**)virtualVT)[-(i->second->offset)] = ctpInfo;
              }
            }
            
            def->status = resolved;
            status = resolved;
            classDef->broadcastClass();
          } else {
            while (classDef->status < resolved) {
              classDef->waitClass();
            }
          }
          classDef->release();
        } else {
          cl->ctpInfo = 
            new(classLoader->allocator, def->ctpInfo->ctpSize) UserConstantPool(cl);
          release();
          status = classRead,
          cl->loadParents();
          status = resolved;
          broadcastClass();
        }
      }
      release();
    } else {
      while (status < resolved) {
        waitClass();
      }
      release();
    }
  }
}

UserClass* UserCommonClass::lookupClassFromMethod(JavaMethod* meth) {
  UserClass* res = 0;
  lookupMethodDontThrow(meth->name, meth->type,
                        isStatic(meth->access), true, res);
  return res;
}

UserCommonClass* UserCommonClass::getUserClass(CommonClass* cl) {
  fprintf(stderr, "implement me");
  abort();
  return 0;
}


UserCommonClass* UserConstantPool::isClassLoaded(uint32 entry) {
  JavaConstantPool* ctpInfo = getSharedPool();
  if (! ((entry > 0) && (entry < ctpInfo->ctpSize) && 
        ctpInfo->typeAt(entry) == JavaConstantPool::ConstantClass)) {
    JavaThread::get()->isolate->classFormatError(
              "bad constant pool number for class at entry %d", entry);
  }
  return (UserCommonClass*)ctpRes[entry];
}

UserCommonClass* UserConstantPool::loadClass(uint32 index) {
  UserCommonClass* temp = isClassLoaded(index);
  if (!temp) {
    JavaConstantPool* ctpInfo = getSharedPool();
    JnjvmClassLoader* loader = getClass()->classLoader;
    const UTF8* name = ctpInfo->UTF8At(ctpInfo->ctpDef[index]);
    if (name->elements[0] == AssessorDesc::I_TAB) {
      temp = loader->constructArray(name);
      temp->resolveClass();
    } else {
      // Put into ctpRes because there is only one representation of the class
      temp = loader->loadName(name, true, false);
    }
    ctpRes[index] = temp;
    ctpInfo->ctpRes[index] = temp->classDef;
  }
  return temp;
}

void UserConstantPool::resolveMethod(uint32 index, UserCommonClass*& cl,
                                     const UTF8*& utf8, Signdef*& sign) {
  JavaConstantPool* ctpInfo = getSharedPool();
  sint32 entry = ctpInfo->ctpDef[index];
  sint32 ntIndex = entry & 0xFFFF;
  sign = (Signdef*)ctpInfo->ctpRes[ntIndex];
  assert(sign && "No cached signature after JITting");
  utf8 = ctpInfo->UTF8At(ctpInfo->ctpDef[ntIndex] >> 16);
  cl = loadClass(entry >> 16);
  assert(cl && cl->isResolved() && "No resolved class when resolving method");
}
  
void UserConstantPool::resolveField(uint32 index, UserCommonClass*& cl,
                                    const UTF8*& utf8, Typedef*& sign) {
  JavaConstantPool* ctpInfo = getSharedPool();
  sint32 entry = ctpInfo->ctpDef[index];
  sint32 ntIndex = entry & 0xFFFF;
  sign = (Typedef*)ctpInfo->ctpRes[ntIndex];
  assert(sign && "No cached Typedef after JITting");
  utf8 = ctpInfo->UTF8At(ctpInfo->ctpDef[ntIndex] >> 16);
  cl = loadClass(entry >> 16);
  assert(cl && cl->isResolved() && "No resolved class when resolving field");
}

void* UserConstantPool::operator new(size_t sz, JavaAllocator* alloc,
                                     uint32 size){
  return alloc->allocateObject(sz + size * sizeof(void*), VT);
}

UserClassPrimitive* AssessorDesc::getPrimitiveClass() const {
  Jnjvm* vm = JavaThread::get()->isolate;
  if (numId > VOID_ID && numId < ARRAY_ID) {
    UserClassArray* arrayCl = vm->arrayClasses[numId];
    UserClassPrimitive* cl = (UserClassPrimitive*)arrayCl->_baseClass;
    assert(cl && "Primitive array class does not have a primitive.");
    return cl;
  } else if (numId == VOID_ID) {
    return vm->upcalls->OfVoid;
  }
  return 0;
}

UserClassArray* AssessorDesc::getArrayClass() const {
  Jnjvm* vm = JavaThread::get()->isolate;
  UserClassArray* arrayCl = vm->arrayClasses[numId];
  return arrayCl;
}

JavaMethod* UserCommonClass::lookupMethodDontThrow(const UTF8* name,
                                                   const UTF8* type,
                                                   bool isStatic,
                                                   bool recurse,
                                                   UserClass*& methodCl) {
  
  CommonClass::FieldCmp CC(name, type);
  CommonClass::method_map* map = isStatic ? getStaticMethods() :
                                            getVirtualMethods();
  CommonClass::method_iterator End = map->end();
  CommonClass::method_iterator I = map->find(CC);
  if (I != End) {
    methodCl = (UserClass*)this;
    return I->second;
  }
  
  JavaMethod *cur = 0;
  
  if (recurse) {
    if (super) cur = super->lookupMethodDontThrow(name, type, isStatic,
                                                  recurse, methodCl);
    if (cur) return cur;

    if (isStatic) {
      std::vector<UserClass*>* interfaces = getInterfaces();
      for (std::vector<UserClass*>::iterator i = interfaces->begin(),
           e = interfaces->end(); i!= e; i++) {
        cur = (*i)->lookupMethodDontThrow(name, type, isStatic, recurse,
                                          methodCl);
        if (cur) return cur;
      }
    }
  }

  return 0;
}

JavaMethod* UserCommonClass::lookupMethod(const UTF8* name, const UTF8* type,
                                          bool isStatic, bool recurse,
                                          UserClass*& methodCl) {
  JavaMethod* res = lookupMethodDontThrow(name, type, isStatic, recurse,
                                          methodCl);
  if (!res) {
    JavaThread::get()->isolate->noSuchMethodError(this->classDef, name);
  }
  return res;
}

JavaField*
UserCommonClass::lookupFieldDontThrow(const UTF8* name, const UTF8* type,
                                      bool isStatic, bool recurse,
                                      UserCommonClass*& definingClass) {

  CommonClass::FieldCmp CC(name, type);
  CommonClass::field_map* map = isStatic ? getStaticFields() :
                                           getVirtualFields();
  CommonClass::field_iterator End = map->end();
  CommonClass::field_iterator I = map->find(CC);
  if (I != End) {
    definingClass = this;
    return I->second;
  }
  
  JavaField *cur = 0;

  if (recurse) {
    if (super) cur = super->lookupFieldDontThrow(name, type, isStatic,
                                                 recurse, definingClass);
    if (cur) return cur;

    if (isStatic) {
      std::vector<UserClass*>* interfaces = getInterfaces();
      for (std::vector<UserClass*>::iterator i = interfaces->begin(),
           e = interfaces->end(); i!= e; i++) {
        cur = (*i)->lookupFieldDontThrow(name, type, isStatic, recurse,
                                         definingClass);
        if (cur) return cur;
      }
    }
  }

  return 0;
}

JavaField* UserCommonClass::lookupField(const UTF8* name, const UTF8* type,
                                        bool isStatic, bool recurse,
                                        UserCommonClass*& definingClass) {
  
  JavaField* res = lookupFieldDontThrow(name, type, isStatic, recurse,
                                        definingClass);
  if (!res) {
    JavaThread::get()->isolate->noSuchFieldError(this->classDef, name);
  }
  return res;
}

void UserConstantPool::print(mvm::PrintBuffer* buf) const {
  buf->write("User constant pool of <");
  getClass()->classDef->print(buf);
  buf->write(">");
}

void UserCommonClass::print(mvm::PrintBuffer* buf) const {
  buf->write("User class of <");
  classDef->print(buf);
  buf->write(">");
}
