-/* -*- mode: c; tab-width: 4; c-basic-offset: 4 -*- */
-/****************************** tables.c ***************************************
+/* src/vm/tables.c -
- Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+ Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
+ R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
+ C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
+ Institut f. Computersprachen - TU Wien
- See file COPYRIGHT for information on usage and disclaimer of warranties
+ This file is part of CACAO.
- Enth"alt Supportfunktionen f"ur:
- - Lesen von JavaClass-Files
- - unicode-Symbole
- - den Heap
- - zus"atzliche Support-Funktionen
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
- Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
- Changes: Mark Probst EMAIL: cacao@complang.tuwien.ac.at
- Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
+ This program 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
+ General Public License for more details.
- Last Change: 1998/03/24
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
-*******************************************************************************/
+ Contact: cacao@complang.tuwien.ac.at
-#include <assert.h>
-#include <sys/mman.h>
-#include <unistd.h>
-#include "global.h"
-#include "tables.h"
-#include "asmpart.h"
-#include "callargs.h"
+ Authors: Reinhard Grafl
-#include "threads/thread.h" /* schani */
-#include "threads/locks.h"
+ Changes: Mark Probst
+ Andreas Krall
+ Christian Thalinger
+ Contains support functions for:
+ - Reading of Java class files
+ - Unicode symbols
+ - the heap
+ - additional support functions
-bool runverbose = false;
+ $Id: tables.c 2505 2005-05-23 08:23:40Z twisti $
-int count_unicode_len = 0;
+*/
-/******************************************************************************
-************************* Der Dateien-Sauger **********************************
-*******************************************************************************
-
- dient zum Behandeln von Java-ClassFiles ("offnen, schlie"sen,
- einlesen von 8-, 16-, 32-, 64-bit Integers und 32-, 64- bit Floats)
-
-******************************************************************************/
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <unistd.h>
-static FILE *classfile = NULL; /* File-handle der gerade gelesenen Datei */
-static char *classpath = ""; /* Suchpfad f"ur die ClassFiles */
+#include "types.h"
+#include "mm/memory.h"
+#include "native/native.h"
+#include "toolbox/logging.h"
+#include "vm/builtin.h"
+#include "vm/exceptions.h"
+#include "vm/global.h"
+#include "vm/loader.h"
+#include "vm/options.h"
+#include "vm/statistics.h"
+#include "vm/stringlocal.h"
+#include "vm/tables.h"
+#include "vm/classcache.h"
+hashtable string_hash; /* hashtable for javastrings */
-/************************** Funktion: suck_init ******************************
- Wird zu Programmstart einmal aufgerufen und setzt den Suchpfad f"ur
- Klassenfiles
+/******************************************************************************
+ *********************** hashtable functions **********************************
+ ******************************************************************************/
-******************************************************************************/
+/* hashsize must be power of 2 */
-void suck_init (char *cpath)
-{
- classfile = NULL;
- classpath = cpath;
-}
+#define UTF_HASHSTART 16384 /* initial size of utf-hash */
+#define HASHSTART 2048 /* initial size of javastring and class-hash */
-/************************** Funktion: suck_start ******************************
+/******************** function: init_hashtable ******************************
- "Offnet die Datei f"ur die Klasse des gegebenen Namens zum Lesen.
- Dabei werden alle im Suchpfad angegebenen Verzeichnisse durchsucht,
- bis eine entsprechende Datei ( <classname>.class) gefunden wird.
+ Initializes a hashtable structure and allocates memory.
+ The parameter size specifies the initial size of the hashtable.
-******************************************************************************/
-
-bool suck_start (unicode *classname)
-{
-#define MAXFILENAME 1000 /* Maximale Langes des Dateinamens plus Pfad */
-
- char filename[MAXFILENAME+10]; /* Platz fuer '.class' */
- u2 filenamelen;
- char *pathpos;
- u2 i,c;
-
-
- pathpos = classpath;
-
- while (*pathpos) {
- while ( *pathpos == ':' ) pathpos++;
-
- filenamelen=0;
- while ( (*pathpos) && (*pathpos!=':') ) {
- PANICIF (filenamelen >= MAXFILENAME, "Filename too long") ;
-
- filename[filenamelen++] = *(pathpos++);
- }
-
- filename[filenamelen++] = '/';
-
- for (i=0; i < classname -> length; i++) {
- PANICIF (filenamelen >= MAXFILENAME, "Filename too long");
-
- c = classname -> text [i];
- if (c=='/') c = '/'; /* Slashes im Namen passen zu UNIX */
- else {
- if ( c<=' ' || c>'z') {
- c = '?';
- }
- }
-
- filename[filenamelen++] = c;
- }
-
- strcpy (filename+filenamelen, ".class");
-
- classfile = fopen(filename, "r");
- if (classfile) {
- return true;
- }
-
-
- }
-
- sprintf (logtext,"Can not open class file '%s'", filename);
- error();
- return false;
-}
-
-
-/************************** Funktion: suck_stop *******************************
-
- Schlie"st die offene Datei wieder.
-
-******************************************************************************/
-
-void suck_stop ()
-{
- u4 rest=0;
- u1 dummy;
-
- while ( fread (&dummy, 1,1, classfile) > 0) rest++;
- if (rest) {
- sprintf (logtext,"There are %d access bytes at end of classfile",
- (int) rest);
- dolog();
- }
-
- fclose (classfile);
- classfile = NULL;
-}
-
-
-
-/************************** Lesefunktionen ***********************************
-
- Lesen von der Datei in verschieden grossen Paketen
- (8,16,32,64-bit Integer oder Float)
-
*****************************************************************************/
-void suck_nbytes (u1 *buffer, u4 len)
-{
- if ( fread (buffer, 1, len, classfile) != len) panic ("Unexpected EOF");
-}
-
-
-void skip_nbytes (u4 len)
+void init_hashtable(hashtable *hash, u4 size)
{
u4 i;
- for (i=0; i<len; i++) suck_u1 ();
-}
-
-
-u1 suck_u1 ()
-{
- u1 b;
- if ( fread (&b, 1,1, classfile) != 1) panic ("Unexpected EOF");
- return b;
-}
-
-s1 suck_s1 ()
-{
- s1 b;
- if ( fread (&b, 1,1, classfile) != 1) panic ("Unexpected EOF");
- return b;
-}
-
-
-u2 suck_u2 ()
-{
- u1 b[2];
- if ( fread (b, 1,2, classfile) != 2) panic ("Unexpected EOF");
- return (b[0]<<8) + b[1];
-}
-s2 suck_s2 ()
-{
- return suck_u2 ();
-}
+ hash->entries = 0;
+ hash->size = size;
+ hash->ptr = MNEW(void*, size);
-
-u4 suck_u4 ()
-{
- u1 b[4];
- u4 v;
- if ( fread (b, 1,4, classfile) != 4) panic ("Unexpected EOF");
- v = ( ((u4)b[0]) <<24) + ( ((u4)b[1])<<16) + ( ((u4)b[2])<<8) + ((u4)b[3]);
- return v;
+ /* clear table */
+ for (i = 0; i < size; i++) hash->ptr[i] = NULL;
}
-s4 suck_s4 ()
-{
- s4 v = suck_u4 ();
- return v;
-}
-u8 suck_u8 ()
-{
-#if U8_AVAILABLE
- u8 lo,hi;
- hi = suck_u4();
- lo = suck_u4();
- return (hi<<32) + lo;
-#else
- u8 v;
- v.high = suck_u4();
- v.low = suck_u4();
- return v;
-#endif
-}
+/*********************** function: tables_init *****************************
-s8 suck_s8 ()
-{
- return suck_u8 ();
-}
+ creates hashtables for symboltables
+ (called once at startup)
+*****************************************************************************/
-float suck_float ()
+void tables_init()
{
- float f;
-
-#if !WORDS_BIGENDIAN
- u1 buffer[4];
- u2 i;
- for (i=0; i<4; i++) buffer[3-i] = suck_u1 ();
- memcpy ( (u1*) (&f), buffer, 4);
-#else
- suck_nbytes ( (u1*) (&f), 4 );
-#endif
+ init_hashtable(&utf_hash, UTF_HASHSTART); /* hashtable for utf8-symbols */
+ init_hashtable(&string_hash, HASHSTART); /* hashtable for javastrings */
- PANICIF (sizeof(float) != 4, "Incompatible float-format");
-
- return f;
-}
+ classcache_init();
+/* if (opt_eager) */
+/* list_init(&unlinkedclasses, OFFSET(classinfo, listnode)); */
-double suck_double ()
-{
- double d;
-
-#if !WORDS_BIGENDIAN
- u1 buffer[8];
- u2 i;
- for (i=0; i<8; i++) buffer[7-i] = suck_u1 ();
- memcpy ( (u1*) (&d), buffer, 8);
-#else
- suck_nbytes ( (u1*) (&d), 8 );
+#if defined(STATISTICS)
+ if (opt_stat)
+ count_utf_len += sizeof(utf*) * utf_hash.size;
#endif
-
- PANICIF (sizeof(double) != 8, "Incompatible double-format" );
-
- return d;
}
+/********************** function: tables_close ******************************
-
-/******************************************************************************
-******************** Der Unicode-Symbol-Verwalter *****************************
-*******************************************************************************
-
- legt eine Hashtabelle f"ur unicode-Symbole an und verwaltet
- das Eintragen neuer Symbole
-
-******************************************************************************/
-
-
-
-#define UNICODESTART 2187 /* Startgr"osse: moeglichst gross und prim */
-
-static u4 unicodeentries; /* Anzahl der Eintr"age in der Tabelle */
-static u4 unicodehashsize; /* Gr"osse der Tabelle */
-static unicode ** unicodehash; /* Zeiger auf die Tabelle selbst */
-
-
-/*********************** Funktion: unicode_init ******************************
-
- Initialisiert die unicode-Symboltabelle (muss zu Systemstart einmal
- aufgerufen werden)
+ free memory for hashtables
*****************************************************************************/
-void unicode_init ()
+void tables_close()
{
+ utf *u = NULL;
+ literalstring *s;
u4 i;
-
-#ifdef STATISTICS
- count_unicode_len += sizeof(unicode*) * unicodehashsize;
-#endif
-
- unicodeentries = 0;
- unicodehashsize = UNICODESTART;
- unicodehash = MNEW (unicode*, unicodehashsize);
- for (i=0; i<unicodehashsize; i++) unicodehash[i] = NULL;
-}
-
-/*********************** Funktion: unicode_close *****************************
-
- Gibt allen Speicher der Symboltabellen frei.
- Parameter: Ein Zeiger auf eine Funktion, die dazu n"otig ist,
- Stringkonstanten (die mit 'unicode_setstringlink'
- Unicode-Symbole gebunden wurden) wieder freizugeben
+ classcache_free();
-*****************************************************************************/
-
-void unicode_close (stringdeleter del)
-{
- unicode *u;
- u4 i;
-
- for (i=0; i<unicodehashsize; i++) {
- u = unicodehash[i];
+ /* dispose utf symbols */
+ for (i = 0; i < utf_hash.size; i++) {
+ u = utf_hash.ptr[i];
while (u) {
- unicode *nextu = u->hashlink;
-
- if (u->string) del (u->string);
-
- MFREE (u->text, u2, u->length);
- FREE (u, unicode);
+ /* process elements in external hash chain */
+ utf *nextu = u->hashlink;
+ MFREE(u->text, u1, u->blength);
+ FREE(u, utf);
u = nextu;
- }
- }
- MFREE (unicodehash, unicode*, unicodehashsize);
-}
-
-
-/********************* Funktion: unicode_display ******************************
-
- Gibt ein unicode-Symbol auf stdout aus (zu Debugzwecken)
-
-******************************************************************************/
-
-void unicode_display (unicode *u)
-{
- u2 i,c;
- for (i=0; i < u->length; i++) {
- c = u->text[i];
- if (c>=32 && c<=127) printf ("%c",c);
- else printf ("?");
- }
- fflush (stdout);
-}
-
-
-/********************* Funktion: unicode_sprint ******************************
-
- Schreibt ein unicode-Symbol in einen C-String
-
-******************************************************************************/
-
-void unicode_sprint (char *buffer, unicode *u)
-{
- u2 i;
- for (i=0; i < u->length; i++) buffer[i] = u->text[i];
- buffer[i] = '\0';
-}
-
-
-/********************* Funktion: unicode_fprint ******************************
-
- Schreibt ein unicode-Symbol auf eine Datei aus
-
-******************************************************************************/
-
-void unicode_fprint (FILE *file, unicode *u)
-{
- u2 i;
- for (i=0; i < u->length; i++) putc (u->text[i], file);
-}
-
-
-/****************** interne Funktion: u_hashkey ******************************/
-
-static u4 u_hashkey (u2 *text, u2 length)
-{
- u4 k = 0;
- u2 i,sh=0;
-
- for (i=0; i<length; i++) {
- k ^= ( ((u4) (text[i])) << sh );
- if (sh<16) sh++;
- else sh=0;
- }
-
- return k;
-}
-
-/*************** interne Funktion: u_reorganizehash **************************/
-
-static void u_reorganizehash ()
-{
- u4 i;
- unicode *u;
-
- u4 newhashsize = unicodehashsize*2;
- unicode **newhash = MNEW (unicode*, newhashsize);
-
-#ifdef STATISTICS
- count_unicode_len += sizeof(unicode*) * unicodehashsize;
-#endif
-
- for (i=0; i<newhashsize; i++) newhash[i] = NULL;
+ }
+ }
- for (i=0; i<unicodehashsize; i++) {
- u = unicodehash[i];
+ /* dispose javastrings */
+ for (i = 0; i < string_hash.size; i++) {
+ s = string_hash.ptr[i];
while (u) {
- unicode *nextu = u -> hashlink;
- u4 slot = (u->key) % newhashsize;
-
- u->hashlink = newhash[slot];
- newhash[slot] = u;
-
- u = nextu;
- }
- }
-
- MFREE (unicodehash, unicode*, unicodehashsize);
- unicodehash = newhash;
- unicodehashsize = newhashsize;
-}
-
-
-/****************** Funktion: unicode_new_u2 **********************************
-
- Legt ein neues unicode-Symbol an. Der Text des Symbols wird dieser
- Funktion als u2-Array "ubergeben
-
-******************************************************************************/
-
-unicode *unicode_new_u2 (u2 *text, u2 length)
-{
- u4 key = u_hashkey (text, length);
- u4 slot = key % unicodehashsize;
- unicode *u = unicodehash[slot];
- u2 i;
-
- while (u) {
- if (u->key == key) {
- if (u->length == length) {
- for (i=0; i<length; i++) {
- if (text[i] != u->text[i]) goto nomatch;
- }
- return u;
- }
- }
- nomatch:
- u = u->hashlink;
- }
-
-#ifdef STATISTICS
- count_unicode_len += sizeof(unicode) + 2 * length;
-#endif
-
- u = NEW (unicode);
- u->key = key;
- u->length = length;
- u->text = MNEW (u2, length);
- u->class = NULL;
- u->string = NULL;
- u->hashlink = unicodehash[slot];
- unicodehash[slot] = u;
- for (i=0; i<length; i++) u->text[i] = text[i];
-
- unicodeentries++;
-
- if ( unicodeentries > (unicodehashsize/2)) u_reorganizehash();
-
- return u;
-}
-
-
-/********************* Funktion: unicode_new_char *****************************
-
- Legt ein neues unicode-Symbol an. Der Text des Symbols wird dieser
- Funktion als C-String ( = char* ) "ubergeben
-
-******************************************************************************/
-
-unicode *unicode_new_char (char *text)
-{
-#define MAXNEWCHAR 500
- u2 buffer[MAXNEWCHAR];
- u2 length = 0;
- u1 c;
-
- while ( (c = *text) != '\0' ) {
- if (length>=MAXNEWCHAR) panic ("Text too long in unicode_new_char");
- buffer[length++] = c;
- text ++;
- }
- return unicode_new_u2 (buffer, length);
-}
-
-
-/********************** Funktion: unicode_setclasslink ************************
-
- H"angt einen Verweis auf eine Klasse an ein unicode-Symbol an.
-
-******************************************************************************/
-
-void unicode_setclasslink (unicode *u, classinfo *class)
-{
- PANICIF (u->class, "Attempt to attach class to already attached symbol");
- u->class = class;
-}
-
-/********************** Funktion: unicode_getclasslink ************************
-
- Sucht den Verweis von einem unicode-Symbol auf eine Klasse.
- Wenn keine solche Klasse existiert, dann wird ein Fehler
- ausgegeben.
-
-******************************************************************************/
-
-classinfo *unicode_getclasslink (unicode *u)
-{
- PANICIF (!u->class, "Attempt to get unknown class-reference");
- return u->class;
-}
-
-
-
-/********************* Funktion: unicode_unlinkclass *************************
-
- Entfernt den Verweis auf eine Klasse wieder von einem Symbol
-
-******************************************************************************/
-
-void unicode_unlinkclass (unicode *u)
-{
- PANICIF (!u->class, "Attempt to unlink not yet linked symbol");
- u -> class = NULL;
-}
-
-
-
-/******************* Funktion> unicode_setstringlink *********************
-
- H"angt einen Verweis auf einen konstanten String an ein
- Unicode-Symbol
-
-*************************************************************************/
-
-void unicode_setstringlink (unicode *u, java_objectheader *str)
-{
- PANICIF (u->string, "Attempt to attach string to already attached symbol");
- u->string = str;
-}
-
-
-/********************* Funktion: unicode_unlinkstring *************************
-
- Entfernt den Verweis auf einen String wieder von einem Symbol
-
-******************************************************************************/
-
-void unicode_unlinkstring (unicode *u)
-{
- PANICIF (!u->class, "Attempt to unlink not yet linked symbol");
- u -> string = NULL;
-}
-
-
-
-/*********************** Funktion: unicode_show ******************************
-
- gibt eine Aufstellung aller Symbol im unicode-hash auf stdout aus.
- (nur f"ur Debug-Zwecke)
-
-*****************************************************************************/
-
-void unicode_show ()
-{
- unicode *u;
- u4 i;
+ /* process elements in external hash chain */
+ literalstring *nexts = s->hashlink;
+ literalstring_free(s->string);
+ FREE(s, literalstring);
+ s = nexts;
+ }
+ }
- printf ("UNICODE-HASH: %d slots for %d entries\n",
- (int) unicodehashsize, (int) unicodeentries );
-
- for (i=0; i<unicodehashsize; i++) {
- u = unicodehash[i];
- if (u) {
- printf ("SLOT %d: ", (int) i);
- while (u) {
- printf ("'");
- unicode_display (u);
- printf ("' ");
- if (u->string) printf ("(string) ");
- u = u->hashlink;
- }
- printf ("\n");
- }
-
- }
+ /* dispose hashtable structures */
+ MFREE(utf_hash.ptr, void*, utf_hash.size);
+ MFREE(string_hash.ptr, void*, string_hash.size);
}
-
/******************************************************************************
-*********************** Diverse Support-Funktionen ****************************
+*********************** Misc support functions ********************************
******************************************************************************/
-/******************** Funktion: desc_to_type **********************************
-
- Findet zu einem gegebenen Typdescriptor den entsprechenden
- Java-Grunddatentyp.
+/******************** Function: desc_to_type **********************************
+
+ Determines the corresponding Java base data type for a given type
+ descriptor.
******************************************************************************/
-u2 desc_to_type (unicode *descriptor)
+u2 desc_to_type(utf *descriptor)
{
- if (descriptor->length < 1) panic ("Type-Descriptor is empty string");
+ char *utf_ptr = descriptor->text; /* current position in utf text */
+
+ if (descriptor->blength < 1) {
+ log_text("Type-Descriptor is empty string");
+ assert(0);
+ }
- switch (descriptor->text[0]) {
+ switch (*utf_ptr++) {
case 'B':
case 'C':
case 'I':
case '[': return TYPE_ADDRESS;
}
- sprintf (logtext, "Invalid Type-Descriptor: ");
- unicode_sprint (logtext+strlen(logtext), descriptor);
- error ();
+ assert(0);
+
return 0;
}
-/********************** Funktion: desc_typesize *******************************
+/********************** Function: desc_typesize *******************************
- Berechnet die L"ange (in Byte) eines Datenelements gegebenen Typs,
- der durch den Typdescriptor gegeben ist.
+ Calculates the lenght in bytes needed for a data element of the type given
+ by its type descriptor.
******************************************************************************/
-u2 desc_typesize (unicode *descriptor)
+u2 desc_typesize(utf *descriptor)
{
switch (desc_to_type(descriptor)) {
case TYPE_INT: return 4;
}
-
-
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */