* Small typo
[cacao.git] / src / vm / tables.c
index 48103bee3b6b5db2d5ac74854066bb4730bbe21f..21437fbe09b1782f864fb163c016ff2f2bb5dd6a 100644 (file)
-/* -*- 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':
@@ -645,21 +198,20 @@ u2 desc_to_type (unicode *descriptor)
        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;
@@ -672,5 +224,15 @@ u2 desc_typesize (unicode *descriptor)
 }
 
 
-
-
+/*
+ * 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:
+ */