/* -*- Mode: C; c-file-style: "gnu" -*-
   objects.h -- Our low-level representation of objects.
   Created: Chris Toshok <toshok@hungry.com>, 10-Aug-1997
 */

/*
  This file is part of Japhar, the GNU Virtual Machine for Java Bytecodes.
  Japhar is a project of The Hungry Programmers, GNU, and OryxSoft.

  Copyright (C) 1997, 1998, 1999 The Hungry Programmers

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Library General Public
  License as published by the Free Software Foundation; either
  version 2 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Library General Public License for more details.

  You should have received a copy of the GNU Library General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
#ifndef _objects_h
#define _objects_h

#include "gc.h"
#include "ClazzFile.h"

#ifdef __cplusplus
extern "C" {
#endif

  /*
  ** Ok.  it's time for a different object representation.
  **
  ** This one borrows from the object representation we used in the
  ** pre-japhar runtime, as well as from recent discussions with jason
  ** evans (jasone@canonware.com).  It ought to be very efficient.
  **
  ** Objects are layed out in the following way (on a 32 bit machine):
  **
  **       +0 / object's monitor            /
  **       +4 / object's hashcode           /
  **	 +8 / object's native state       /
  **      +12 / null pointer                /
  **      +16 / most deeply nested subclass / <- japhar_obj pointer
  **      +20 / parent class                /
  **      +24 / parent class                /
  **                          ..
  **          / java.lang.Object            /
  **          / fields for java.lang.Object / packed and aligned properly.
  **          / fields for subclass         /
  **                          ..
  **          / fields for deepest subclass /
  **
  ** fields are layed on in parent class-subclass order, so the offset
  ** for java.lang.Object fields are lower (at a lower offset) than
  ** those for java.lang.String.
  **
  ** each of the ClazzFile structures has a "nesting value" in them -
  ** since they know they're level in the inheritance tree.  Using this
  ** value we can get at the fields for the object in constant time,
  ** regardless of the class.  superclass/supclass testing is much the
  ** same as it was with the POSTS, except we don't use two - the
  ** java.lang.Object ClazzFile* acts as one post.
  ** 
  ** perhaps the biggest impetus for the move is that fewer mallocs are
  ** required and also that we're mallocing less total space.  The old
  ** code allocated 96 bits for every instance field, when all of them
  ** were substantially smaller than this -- the largest java type calls
  ** for 64 bits.  we were wasting a *lot* of memory.
  **
  ** Also, the addition of the hashcode field permits the use of copying
  ** collectors.  The first time the object is asked for its hashcode,
  ** it calculates it (from it's address) and stores it in that field.
  ** from that point on it just returns it, regardless of it's address.
  **
  ** Another topic of discussion was to split off the packed field data
  ** from all the ClazzFile pointers.  This would create the need for
  ** more than one malloc (one for the instance fields and one for the
  ** ClazzFile* for the most deeply nested subclass), and it would
  ** require a new ClazzFile** to be allocated with every cast, but it
  ** would save some memory in the initial malloc (since we wouldn't put
  ** any ClazzFile*'s in the object) and would remove some of the
  ** duplicate logic -- the inheritance tree is already avaiable in the
  ** ClazzFile->super_class pointer, although this scheme might prove
  ** slower due to lack of locality, since we'd have to traverse
  ** linearly through parent pointers instead of using ++.
  **
  ** we can investigate that later.
  **
  ** christoph
  */
  typedef struct instance_data {
    char fields;	 /* isn't really a char -- we use a pointer to this to
			    actually get at the fields. */
  } instance_data;

  typedef struct japhar_object {
    HMonitor monitor;
    jint hash_code;
    void *native_state;

    void *_post; /* NULL pointer. */

    /*
     * This isn't really one ClazzFile*.  this structure is allocated to
     * contain enough ClazzFile*'s for the object's class's inheritance
     * path.
     */
    ClazzFile *_static;

    /* instance_data comes after all the ClazzFile*'s */
  } japhar_object;

#define OffsetOf(p_type,field) ((unsigned int)&(((p_type)NULL)->field))

#define obj_to_object(obj,jobj) do { \
  japhar_obj _tmp_obj = (japhar_obj)(obj); \
  while (*_tmp_obj) _tmp_obj--; \
  (jobj) = (japhar_object*)((char*)_tmp_obj - OffsetOf(japhar_object*, _post)); \
} while (0)

  typedef ClazzFile** japhar_obj;

  extern japhar_obj clazzfile_to_jclass(JNIEnv *env, ClazzFile *cf);
  extern ClazzFile* jclass_to_clazzfile(JNIEnv *env, jclass cls);
  extern japhar_obj new_object(JNIEnv *env, ClazzFile *cf);
  extern japhar_obj clone_object(JNIEnv *env, japhar_obj obj);
  extern void object_finalize(japhar_object *obj);

  extern void create_static_class_data(ClazzFile* cf);

  extern void initialize_class(JNIEnv *env, ClazzFile* cf);

  extern japhar_obj cast_obj(japhar_obj object_ref,
			     ClazzFile *cf);

  extern MethodStruct *get_interface_method_info(JNIEnv *env,
						 japhar_obj obj,
						 ClazzFile **cf,
						 char *method_name,
						 char *method_sig);

  extern jboolean is_instance_of(JNIEnv *env, japhar_obj obj, ClazzFile *cf);
  extern void calculate_instance_field_offsets(JNIEnv *env, ClazzFile *cf);

  extern jboolean obj_is_reference(JNIEnv *env, japhar_obj obj);
  extern japhar_obj get_obj_from_reference(JNIEnv *env, japhar_obj obj);

  extern void* NSA_GetNativeState(japhar_obj object_ref);
  extern void  NSA_SetNativeState(japhar_obj obj, void *native_state);

#ifdef __cplusplus
};
#endif

#endif /* _objects_h */
