* src/vm/string.c (javastring_toutf): Check for NULL and return
authortwisti <none@none>
Fri, 23 Jun 2006 12:07:26 +0000 (12:07 +0000)
committertwisti <none@none>
Fri, 23 Jun 2006 12:07:26 +0000 (12:07 +0000)
utf_null.
(literalstring_u2): Replaced list_addfirst with list_add_first.

* src/vm/builtin.h (BUILTIN_MONITOR_ENTER, BUILTIN_MONITOR_EXIT):
Defined.

* src/vm/jit/powerpc/codegen.c (codegen): Don't use
BUILTIN_staticmonitorenter, use JITDATA_HAS_FLAG_VERBOSECALL instead
of opt_verbosecall.
(createnativestub): Likewise.

* src/vm/jit/code.c: Smaller changes.

* src/vm/jit/code.h (codeinfo): Added optlevel.

* src/vm/jit/Makefile.am (libjit_la_SOURCES): Added recompile.[ch].
* src/vm/jit/recompile.c: New file.
* src/vm/jit/recompile.h: Likewise.

* src/vm/jit/show.c (new_show_method, show_method)
(new_show_basicblock, show_basicblock): Use
JITDATA_HAS_FLAG_SHOWDISASSEMBLE instead of opt_showdisassemble.

* src/vm/jit/profile/profile.c (vm/jit/jit.h): Added.
(list_method_entry): Moved to src/vm/jit/recompile.h.
(profile_thread): First real implementation.
(profile_start_thread): Better code.
(profile_printstats): Use codeinfo frequencies.

* src/vm/jit/jit.c (jit_compile): Set jd->flags properly. Moved
codeinfo memory freeing before dump_release because we need jd, which
is allocated on dump memory.
(jit_recompile): New function.
(jit_compile_intern): Use jd->flags.

* src/vm/jit/codegen-common.c (codegen_createnativestub): Set
jd->flags.

* src/vm/jit/jit.h (JITDATA_FLAG_PARSE, JITDATA_FLAG_VERIFY)
(JITDATA_FLAG_SHOWINTERMEDIATE, JITDATA_FLAG_SHOWDISASSEMBLE)
(JITDATA_FLAG_VERBOSECALL): Added.
(JITDATA_HAS_FLAG_PARSE, JITDATA_HAS_FLAG_VERIFY)
(JITDATA_HAS_FLAG_IFCONV, JITDATA_HAS_FLAG_SHOWINTERMEDIATE)
(JITDATA_HAS_FLAG_SHOWDISASSEMBLE, JITDATA_HAS_FLAG_VERBOSECALL):
Likewise.
(jit_recompile): Likewise.

* src/vm/vm.c (vm/jit/recompile.h): Added.
(vm_create): Call recompile_init and recompile_start_thread.

* src/toolbox/list.h (config.h, vm/types.h, vm/global.h): Added.
(list): Added lock.
(list_init): Renamed to list_create.
(list_addfirst): Renamed to list_add_first.
(list_addlast): Renamed to list_add_last.
(list_add_last_unsynced): New function.

* src/toolbox/list.c (mm/memory.h, threads/native/threads.h)
(vm/builtin.h): Added.
(list_init): Renamed to list_create.
(list_addfirst): Renamed to list_add_first and made synchronized.
(list_addlast): Likewise.
(list_add_last_unsynced): Likewise.
(list_add_before): Made synchronized.
(list_remove): Likewise.
(list_first): Likewise.
(list_last): Likewise.
(list_next): Likewise.
(list_prev): Likewise.

* src/vm/suck.c (suck_init): Replaced list_init with list_create.
(suck_add): Replaced list_addlast with list_add_last.

* src/vm/loader.c (load_constantpool): Replaced list_addfirst with
list_add_first.
(load_newly_created_array): Likewise.

* src/vm/properties.c (properties_init): Replaced list_init with
list_create.
(properties_add): Use list_add_last_unsynced, as this is required
during bootstrapping.

* src/threads/native/threads.h (THREAD_FLAG_JAVA)
(THREAD_FLAG_INTERNAL): Added.
(threadobject): Added flags.

* src/threads/native/threads.c (threads_init): Flag main thread as
Java thread (required for profiling sampling).
(threads_startup_thread): Flag threads as Java or internal thread.

21 files changed:
src/threads/native/threads.c
src/threads/native/threads.h
src/toolbox/list.c
src/toolbox/list.h
src/vm/builtin.h
src/vm/jit/Makefile.am
src/vm/jit/code.c
src/vm/jit/code.h
src/vm/jit/codegen-common.c
src/vm/jit/jit.c
src/vm/jit/jit.h
src/vm/jit/powerpc/codegen.c
src/vm/jit/profile/profile.c
src/vm/jit/recompile.c [new file with mode: 0644]
src/vm/jit/recompile.h [new file with mode: 0644]
src/vm/jit/show.c
src/vm/loader.c
src/vm/properties.c
src/vm/string.c
src/vm/suck.c
src/vm/vm.c

index a9b24083e08bd54de1803f5fd09b42abe49a9422..3b1927b3c49ee4207731ad1f2eb89455377213c7 100644 (file)
@@ -29,7 +29,7 @@
    Changes: Christian Thalinger
                        Edwin Steiner
 
-   $Id: threads.c 5031 2006-06-14 18:36:22Z motse $
+   $Id: threads.c 5049 2006-06-23 12:07:26Z twisti $
 
 */
 
@@ -756,6 +756,10 @@ bool threads_init(void)
 
        threads_table_add(mainthreadobj);
 
+       /* mark main thread as Java thread */
+
+       mainthreadobj->flags = THREAD_FLAG_JAVA;
+
 #if defined(ENABLE_INTRP)
        /* create interpreter stack */
 
@@ -993,6 +997,9 @@ void threads_init_threadobject(java_lang_VMThread *t)
 
    Thread startup function called by pthread_create.
 
+   Thread which have a startup.function != NULL are marked as internal
+   threads. All other threads are threated as normal Java threads.
+
    NOTE: This function is not called directly by pthread_create. The Boehm GC
          inserts its own GC_start_routine in between, which then calls
                 threads_startup.
@@ -1093,19 +1100,27 @@ static void *threads_startup_thread(void *t)
        /* find and run the Thread.run()V method if no other function was passed */
 
        if (function == NULL) {
+               /* this is a normal Java thread */
+
+               thread->flags |= THREAD_FLAG_JAVA;
+
                method = class_resolveclassmethod(thread->o.header.vftbl->class,
                                                                                  utf_run,
                                                                                  utf_void__void,
                                                                                  thread->o.header.vftbl->class,
                                                                                  true);
 
-               if (!method)
+               if (method == NULL)
                        throw_exception();
 
                (void) vm_call_method(method, (java_objectheader *) thread);
 
        }
        else {
+               /* this is an internal thread */
+
+               thread->flags |= THREAD_FLAG_INTERNAL;
+
                /* call passed function, e.g. finalizer_thread */
 
                (function)();
index 0e2fd8147e019b10606c00f83db1c0ccf383c3b8..9278244d8fab69058b11b8b56158fdb51b406939 100644 (file)
@@ -29,7 +29,7 @@
 
    Changes: Christian Thalinger
 
-   $Id: threads.h 5039 2006-06-19 22:23:44Z twisti $
+   $Id: threads.h 5049 2006-06-23 12:07:26Z twisti $
 
 */
 
@@ -133,6 +133,10 @@ struct threads_table_t {
 
 *******************************************************************************/
 
+#define THREAD_FLAG_JAVA        0x01    /* a normal Java thread               */
+#define THREAD_FLAG_INTERNAL    0x02    /* CACAO internal thread              */
+
+
 struct threadobject {
        java_lang_VMThread    o;            /* the java.lang.VMThread object      */
 
@@ -143,9 +147,10 @@ struct threadobject {
 
        ptrint                thinlock;     /* pre-computed thin lock value       */
 
-       s4                    index;        /* thread index, startin with 1       */
+       s4                    index;        /* thread index, starting with 1      */
+       u1                    flags;        /* flag field                         */
 
-       pthread_t             tid;               /* pthread id                    */
+       pthread_t             tid;          /* pthread id                         */
 
 #if defined(__DARWIN__)
        mach_port_t           mach_thread;       /* Darwin thread id              */
index 39a547ed937e751b419c48331c7d6e0c54392579..ba9bfb1ed0e27a839633c9e606e07a9f2ef2f22f 100644 (file)
@@ -26,7 +26,7 @@
 
    Authors: Reinhard Grafl
 
-   $Id: list.c 4394 2006-01-31 22:27:23Z twisti $
+   $Id: list.c 5049 2006-06-23 12:07:26Z twisti $
 
 */
 
 
 #include "vm/types.h"
 
+#include "mm/memory.h"
+
+#if defined(ENABLE_THREADS)
+# include "threads/native/threads.h"
+#endif
+
 #include "toolbox/list.h"
+#include "vm/builtin.h"
+
+
+/* list_create *****************************************************************
 
+   Allocates a new list and initializes the lock object.
 
-void list_init(list *l, int nodeoffset)
+*******************************************************************************/
+
+list *list_create(s4 nodeoffset)
 {
-       l->first = NULL;
-       l->last = NULL;
+       list *l;
+
+       l = NEW(list);
+
+#if defined(ENABLE_THREADS)
+       lock_init_object_lock((java_objectheader *) l);
+#endif
+
+       l->first      = NULL;
+       l->last       = NULL;
        l->nodeoffset = nodeoffset;
+
+       return l;
 }
 
 
-void list_addfirst(list *l, void *element)
+void list_add_first(list *l, void *element)
 {
-       listnode *n = (listnode *) (((u1 *) element) + l->nodeoffset);
+       listnode *ln;
+
+       ln = (listnode *) (((u1 *) element) + l->nodeoffset);
+
+       BUILTIN_MONITOR_ENTER(l);
 
        if (l->first) {
-               n->prev = NULL;
-               n->next = l->first;
-               l->first->prev = n;
-               l->first = n;
-
-       } else {
-               n->prev = NULL;
-               n->next = NULL;
-               l->last = n;
-               l->first = n;
+               ln->prev       = NULL;
+               ln->next       = l->first;
+               l->first->prev = ln;
+               l->first       = ln;
+       }
+       else {
+               ln->prev = NULL;
+               ln->next = NULL;
+               l->last  = ln;
+               l->first = ln;
+       }
+
+       BUILTIN_MONITOR_EXIT(l);
+}
+
+
+/* list_add_last ***************************************************************
+
+   Adds the element as last element.
+
+*******************************************************************************/
+
+void list_add_last(list *l, void *element)
+{
+       listnode *ln;
+
+       ln = (listnode *) (((u1 *) element) + l->nodeoffset);
+
+       BUILTIN_MONITOR_ENTER(l);
+
+       if (l->last) {
+               ln->prev      = l->last;
+               ln->next      = NULL;
+               l->last->next = ln;
+               l->last       = ln;
+       }
+       else {
+               ln->prev = NULL;
+               ln->next = NULL;
+               l->last  = ln;
+               l->first = ln;
        }
+
+       BUILTIN_MONITOR_EXIT(l);
 }
 
 
-void list_addlast(list *l, void *element)
+/* list_add_list_unsynced ******************************************************
+
+   Adds the element as last element but does NO locking!
+
+   ATTENTION: This function is used during bootstrap.  DON'T USE IT!!!
+
+*******************************************************************************/
+
+void list_add_last_unsynced(list *l, void *element)
 {
-       listnode *n = (listnode *) (((u1 *) element) + l->nodeoffset);
+       listnode *ln;
+
+       ln = (listnode *) (((u1 *) element) + l->nodeoffset);
 
        if (l->last) {
-               n->prev = l->last;
-               n->next = NULL;
-               l->last->next = n;
-               l->last n;
-
-       else {
-               n->prev = NULL;
-               n->next = NULL;
-               l->last n;
-               l->first = n;
+               ln->prev      = l->last;
+               ln->next      = NULL;
+               l->last->next = ln;
+               l->last       = ln;
+       }
+       else {
+               ln->prev = NULL;
+               ln->next = NULL;
+               l->last  = ln;
+               l->first = ln;
        }
 }
 
@@ -96,89 +166,132 @@ void list_addlast(list *l, void *element)
 
 void list_add_before(list *l, void *element, void *newelement)
 {
-       listnode *n    = (listnode *) (((u1 *) element) + l->nodeoffset);
-       listnode *newn = (listnode *) (((u1 *) newelement) + l->nodeoffset);
+       listnode *ln;
+       listnode *newln;
+
+       ln    = (listnode *) (((u1 *) element) + l->nodeoffset);
+       newln = (listnode *) (((u1 *) newelement) + l->nodeoffset);
+
+       BUILTIN_MONITOR_ENTER(l);
 
        /* set the new links */
 
-       newn->prev = n->prev;
-       newn->next = n;
+       newln->prev = ln->prev;
+       newln->next = ln;
 
-       if (newn->prev)
-               newn->prev->next = newn;
+       if (newln->prev)
+               newln->prev->next = newln;
 
-       n->prev = newn;
+       ln->prev = newln;
 
        /* set list's first and last if necessary */
 
-       if (l->first == n)
-               l->first = newn;
+       if (l->first == ln)
+               l->first = newln;
+
+       if (l->last == ln)
+               l->last = newln;
 
-       if (l->last == n)
-               l->last = newn;
+       BUILTIN_MONITOR_EXIT(l);
 }
 
 
 void list_remove(list *l, void *element)
 {
-       listnode *n = (listnode *) (((u1 *) element) + l->nodeoffset);
+       listnode *ln;
+
+       ln = (listnode *) (((u1 *) element) + l->nodeoffset);
        
-       if (n->next)
-               n->next->prev = n->prev;
+       BUILTIN_MONITOR_ENTER(l);
+
+       if (ln->next)
+               ln->next->prev = ln->prev;
        else
-               l->last = n->prev;
+               l->last = ln->prev;
 
-       if (n->prev)
-               n->prev->next = n->next;
+       if (ln->prev)
+               ln->prev->next = ln->next;
        else
-               l->first = n->next;
+               l->first = ln->next;
+
+       ln->next = NULL;
+       ln->prev = NULL;
 
-       n->next = NULL;
-       n->prev = NULL;
+       BUILTIN_MONITOR_EXIT(l);
 }
 
  
 void *list_first(list *l)
 {
-       if (!l->first)
-               return NULL;
+       void *el;
 
-       return ((u1 *) l->first) - l->nodeoffset;
+       BUILTIN_MONITOR_ENTER(l);
+
+       if (l->first == NULL)
+               el = NULL;
+       else
+               el = ((u1 *) l->first) - l->nodeoffset;
+
+       BUILTIN_MONITOR_EXIT(l);
+
+       return el;
 }
 
 
 void *list_last(list *l)
 {
-       if (!l->last)
-               return NULL;
+       void *el;
+
+       BUILTIN_MONITOR_ENTER(l);
+
+       if (l->last == NULL)
+               el = NULL;
+       else
+               el = ((u1 *) l->last) - l->nodeoffset;
 
-       return ((u1 *) l->last) - l->nodeoffset;
+       BUILTIN_MONITOR_EXIT(l);
+
+       return el;
 }
 
 
 void *list_next(list *l, void *element)
 {
-       listnode *n;
+       listnode *ln;
+       void     *el;
+
+       ln = (listnode *) (((u1 *) element) + l->nodeoffset);
 
-       n = (listnode *) (((u1 *) element) + l->nodeoffset);
+       BUILTIN_MONITOR_ENTER(l);
+
+       if (ln->next == NULL)
+               el = NULL;
+       else
+               el = ((u1 *) ln->next) - l->nodeoffset;
 
-       if (!n->next)
-               return NULL;
+       BUILTIN_MONITOR_EXIT(l);
 
-       return ((u1 *) n->next) - l->nodeoffset;
+       return el;
 }
 
        
 void *list_prev(list *l, void *element)
 {
-       listnode *n;
+       listnode *ln;
+       void     *el;
 
-       n = (listnode *) (((u1 *) element) + l->nodeoffset);
+       ln = (listnode *) (((u1 *) element) + l->nodeoffset);
+
+       BUILTIN_MONITOR_ENTER(l);
+
+       if (ln->prev == NULL)
+               el = NULL;
+       else
+               el = ((u1 *) ln->prev) - l->nodeoffset;
 
-       if (!n->prev)
-               return NULL;
+       BUILTIN_MONITOR_EXIT(l);
 
-       return ((u1 *) n->prev) - l->nodeoffset;
+       return el;
 }
 
 
index c0fd452008bff5c602b9e9fe82fdb3c9c42ff2f3..5ec8b3e21253d09ed8bbb4680ec86635d0e645df 100644 (file)
@@ -1,4 +1,4 @@
-/* src/toolbox/list.h - 
+/* src/toolbox/list.h - synchronized linked list
 
    Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
@@ -28,7 +28,7 @@
 
    Changes: Christian Thalinger
 
-   $Id: list.h 4394 2006-01-31 22:27:23Z twisti $
+   $Id: list.h 5049 2006-06-23 12:07:26Z twisti $
 
 */
 
 #ifndef _LIST_H
 #define _LIST_H
 
+#include "config.h"
+#include "vm/types.h"
+
+#include "vm/global.h"
+
+
 /* ---------------------- interface description -----------------------------
 
 The list management with this module works like this:
@@ -93,25 +99,37 @@ distinct list).
 
 */
 
-typedef struct listnode {           /* structure for list element */
-       struct listnode *next;
-       struct listnode *prev;
-} listnode;
+/* listnode *******************************************************************/
+
+typedef struct listnode listnode;
+
+struct listnode {
+       listnode *next;
+       listnode *prev;
+};
+
+
+/* list ***********************************************************************/
 
+typedef struct list list;
 
-typedef struct list {               /* structure for list head */
-       listnode *first;
-       listnode *last;
-       int nodeoffset;
-} list;
+struct list {
+#if defined(ENABLE_THREADS)
+       java_objectheader  lock;            /* threads lock object                */
+#endif
+       listnode          *first;
+       listnode          *last;
+       s4                 nodeoffset;
+};
 
 
 /* function prototypes ********************************************************/
 
-void list_init(list *l, int nodeoffset);
+list *list_create(s4 nodeoffset);
 
-void list_addfirst(list *l, void *element);
-void list_addlast(list *l, void *element);
+void list_add_first(list *l, void *element);
+void list_add_last(list *l, void *element);
+void list_add_last_unsynced(list *l, void *element);
 
 void list_add_before(list *l, void *element, void *newelement);
 
index eed044fdb3b4a1c01eab5474806132f4e276f297..c1ee7f1a7071315c0c6faaf4a9aeab0d693b12c4 100644 (file)
@@ -29,7 +29,7 @@
    Changes: Edwin Steiner
             Christian Thalinger
 
-   $Id: builtin.h 4921 2006-05-15 14:24:36Z twisti $
+   $Id: builtin.h 5049 2006-06-23 12:07:26Z twisti $
 
 */
 
@@ -195,6 +195,12 @@ void builtin_staticmonitorenter(classinfo *c);
 #define BUILTIN_staticmonitorenter (functionptr) builtin_staticmonitorenter
 void builtin_monitorexit(java_objectheader *o);
 #define BUILTIN_monitorexit (functionptr) builtin_monitorexit
+
+# define BUILTIN_MONITOR_ENTER(o) builtin_monitorenter((java_objectheader *) o)
+# define BUILTIN_MONITOR_EXIT(o)  builtin_monitorexit((java_objectheader *) o)
+#else
+# define BUILTIN_MONITOR_ENTER(o) /* noop */
+# define BUILTIN_MONITOR_EXIT(o)  /* noop */
 #endif
 
 s4 builtin_idiv(s4 a, s4 b);
index ad05e388863708892a1aa4d9c7015ea95b4261e5..3abd7b7cf59985c1859db2750a21e678055802f9 100644 (file)
@@ -28,7 +28,7 @@
 ##
 ## Changes: Edwin Steiner
 ##
-## $Id: Makefile.am 5045 2006-06-21 16:29:29Z ajordan $
+## $Id: Makefile.am 5049 2006-06-23 12:07:26Z twisti $
 
 ## Process this file with automake to produce Makefile.in
 
@@ -125,6 +125,8 @@ libjit_la_SOURCES = \
        parse.h \
        reg.c \
        reg.h \
+       recompile.c \
+       recompile.h \
        replace.c \
        replace.h \
        show.c \
index 6323aeb80d1fe1f39cf2b873b5b4510376755ba0..445bd9c67a5109f9c906584e87de566f8b2ad5b1 100644 (file)
@@ -1,4 +1,4 @@
-/* vm/jit/code.c - codeinfo struct for representing compiled code
+/* src/vm/jit/code.c - codeinfo struct for representing compiled code
 
    Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
@@ -26,7 +26,7 @@
 
    Authors: Edwin Steiner
 
-   Changes:
+   Changes: Christian Thalinger
 
    $Id$
 
@@ -43,6 +43,7 @@
 #include "vm/options.h"
 #include "arch.h"
 
+
 /* code_codeinfo_new ***********************************************************
 
    Create a new codeinfo for the given method.
@@ -75,6 +76,7 @@ codeinfo *code_codeinfo_new(methodinfo *m)
        return code;
 }
 
+
 /* code_get_sync_slot_count ****************************************************
 
    Return the number of stack slots used for storing the synchronized object
@@ -124,6 +126,7 @@ int code_get_sync_slot_count(codeinfo *code)
 #endif /* ENABLE_THREADS */
 }
 
+
 /* code_get_stack_frame_size ***************************************************
 
    Return the number of stack slots that the stack frame of the given code
@@ -187,6 +190,7 @@ int code_get_stack_frame_size(codeinfo *code)
        return count;
 }
 
+
 /* code_codeinfo_free **********************************************************
 
    Free the memory used by a codeinfo.
@@ -206,9 +210,10 @@ void code_codeinfo_free(codeinfo *code)
 
        replace_free_replacement_points(code);
 
-       FREE(code,codeinfo);
+       FREE(code, codeinfo);
 }
 
+
 /* code_free_code_of_method ****************************************************
 
    Free all codeinfos of the given method
index 101d0abf37b5d469d2fc3ef75f150b5744bdd080..f784838682edca5a7595d8a77052c022fb025bed 100644 (file)
@@ -1,4 +1,4 @@
-/* vm/jit/code.h - codeinfo struct for representing compiled code
+/* src/vm/jit/code.h - codeinfo struct for representing compiled code
 
    Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
@@ -26,7 +26,7 @@
 
    Authors: Edwin Steiner
 
-   Changes:
+   Changes: Christian Thalinger
 
    $Id$
 
@@ -51,29 +51,30 @@ typedef struct codeinfo codeinfo;
 /* machine code.                                                       */
 
 struct codeinfo {
-       methodinfo   *m;                /* method this is a realization of */
-       codeinfo     *prev;             /* previous codeinfo of this method*/
-       
+       methodinfo   *m;                    /* method this is a realization of    */
+       codeinfo     *prev;                 /* previous codeinfo of this method   */
+
+       u1            optlevel;             /* optimization level of this code    */
+
        /* machine code */
-       u1           *mcode;            /* pointer to machine code         */
-       u1           *entrypoint;       /* machine code entry point        */
-       s4            mcodelength;      /* length of generated machine code*/
-       bool          isleafmethod;     /* does method call subroutines    */
-
-       /* replacement */
-       rplpoint     *rplpoints;        /* replacement points              */
-       rplalloc     *regalloc;         /* register allocation info        */
-       s4            rplpointcount;    /* number of replacement points    */
-       s4            globalcount;      /* number of global allocations    */
-       s4            regalloccount;    /* number of total allocations     */
-       s4            memuse;           /* number of arg + local slots     */
-       u1            savedintcount;    /* number of callee saved int regs */
-       u1            savedfltcount;    /* number of callee saved flt regs */
-
-       /* profiling XXX will be removed */
-       u4            frequency;        /* number of method invocations    */
-       u4           *bbfrequency;
-       s8            cycles;           /* number of cpu cycles            */
+       u1           *mcode;                /* pointer to machine code            */
+       u1           *entrypoint;           /* machine code entry point           */
+       s4            mcodelength;          /* length of generated machine code   */
+       bool          isleafmethod;         /* does method call subroutines       */
+
+       /* replacement */                                   
+       rplpoint     *rplpoints;            /* replacement points                 */
+       rplalloc     *regalloc;             /* register allocation info           */
+       s4            rplpointcount;        /* number of replacement points       */
+       s4            globalcount;          /* number of global allocations       */
+       s4            regalloccount;        /* number of total allocations        */
+       s4            memuse;               /* number of arg + local slots        */
+       u1            savedintcount;        /* number of callee saved int regs    */
+       u1            savedfltcount;        /* number of callee saved flt regs    */
+
+       u4            frequency;            /* number of method invocations       */
+       u4           *bbfrequency;                  
+       s8            cycles;               /* number of cpu cycles               */
 };
 
 codeinfo *code_codeinfo_new(methodinfo *m);
index 38998a6ef52b262e49123ef1aac27fa1b2b75c3a..687ccb065699157c8e90042693c200d98755962b 100644 (file)
@@ -48,7 +48,7 @@
    memory. All functions writing values into the data area return the offset
    relative the begin of the code area (start of procedure).   
 
-   $Id: codegen-common.c 5038 2006-06-19 22:22:34Z twisti $
+   $Id: codegen-common.c 5049 2006-06-23 12:07:26Z twisti $
 
 */
 
@@ -769,6 +769,11 @@ codeinfo *codegen_createnativestub(functionptr f, methodinfo *m)
 
        code = jd->code;
 
+       /* set the flags for the current JIT run */
+
+       if (opt_verbosecall)
+               jd->flags |= JITDATA_FLAG_VERBOSECALL;
+
        /* setup code generation stuff */
 
 #if defined(ENABLE_JIT)
index 68f02091191825136ba73235514600891078f43c..6186498756005279f75851dbecbc8bf759bbec3a 100644 (file)
@@ -31,7 +31,7 @@
             Christian Thalinger
             Christian Ullrich
 
-   $Id: jit.c 5007 2006-06-01 15:09:24Z edwin $
+   $Id: jit.c 5049 2006-06-23 12:07:26Z twisti $
 
 */
 
@@ -990,18 +990,14 @@ u1 *jit_compile(methodinfo *m)
                        return m->code->entrypoint;
        }
 
-#if defined(ENABLE_THREADS)
        /* enter a monitor on the method */
 
-       builtin_monitorenter((java_objectheader *) m);
-#endif
+       BUILTIN_MONITOR_ENTER(m);
 
        /* if method has been already compiled return immediately */
 
-       if (m->code) {
-#if defined(ENABLE_THREADS)
-               builtin_monitorexit((java_objectheader *) m);
-#endif
+       if (m->code != NULL) {
+               BUILTIN_MONITOR_EXIT(m);
 
                assert(m->code->entrypoint);
                return m->code->entrypoint;
@@ -1030,7 +1026,6 @@ u1 *jit_compile(methodinfo *m)
 #if defined(ENABLE_LOOP)
        jd->ld    = DNEW(loopdata);
 #endif
-       jd->flags = 0;
 
        /* Allocate codeinfo memory from the heap as we need to keep them. */
 
@@ -1038,9 +1033,23 @@ u1 *jit_compile(methodinfo *m)
 
        /* set the flags for the current JIT run */
 
+       jd->flags = JITDATA_FLAG_PARSE;
+
+       if (opt_verify)
+               jd->flags |= JITDATA_FLAG_VERIFY;
+
        if (opt_ifconv)
                jd->flags |= JITDATA_FLAG_IFCONV;
 
+       if (opt_showintermediate)
+               jd->flags |= JITDATA_FLAG_SHOWINTERMEDIATE;
+
+       if (opt_showdisassemble)
+               jd->flags |= JITDATA_FLAG_SHOWDISASSEMBLE;
+
+       if (opt_verbosecall)
+               jd->flags |= JITDATA_FLAG_VERBOSECALL;
+
 #if defined(ENABLE_JIT)
 # if defined(ENABLE_INTRP)
        if (!opt_intrp)
@@ -1065,6 +1074,23 @@ u1 *jit_compile(methodinfo *m)
        m->instructions    = NULL;
        m->stack           = NULL;
 
+       if (r != NULL) {
+               DEBUG_JIT_COMPILEVERBOSE("Running: ");
+       }
+       else {
+               /* We had an exception! Finish stuff here if necessary. */
+
+               /* release codeinfo */
+
+               code_codeinfo_free(jd->code);
+
+               /* Release memory for basic block profiling information. */
+
+               if (opt_prof)
+                       if (m->bbfrequency)
+                               MFREE(m->bbfrequency, u4, m->basicblockcount);
+       }
+
        /* release dump area */
 
        dump_release(dumpsize);
@@ -1076,31 +1102,130 @@ u1 *jit_compile(methodinfo *m)
                compilingtime_stop();
 #endif
 
-
-#if defined(ENABLE_THREADS)
        /* leave the monitor */
 
-       builtin_monitorexit((java_objectheader *) m);
+       BUILTIN_MONITOR_EXIT(m);
+
+       /* return pointer to the methods entry point */
+
+       return r;
+}
+
+
+/* jit_recompile ***************************************************************
+
+   Recompiles a Java method.
+
+*******************************************************************************/
+
+u1 *jit_recompile(methodinfo *m)
+{
+       u1      *r;
+       jitdata *jd;
+       u1       optlevel;
+       s4       dumpsize;
+
+       /* check for max. optimization level */
+
+       optlevel = m->code->optlevel;
+
+       if (optlevel == 1) {
+               log_message_method("not recompiling: ", m);
+               return NULL;
+       }
+
+       log_message_method("Recompiling start: ", m);
+
+       STATISTICS(count_jit_calls++);
+
+#if defined(ENABLE_STATISTICS)
+       /* measure time */
+
+       if (opt_getcompilingtime)
+               compilingtime_start();
 #endif
 
-       if (r) {
-               DEBUG_JIT_COMPILEVERBOSE("Running: ");
+       /* mark start of dump memory area */
+
+       dumpsize = dump_size();
+
+       /* allocate jitdata structure and fill it */
+
+       jd = DNEW(jitdata);
 
-       } else {
+       jd->m     = m;
+       jd->cd    = DNEW(codegendata);
+       jd->rd    = DNEW(registerdata);
+#if defined(ENABLE_LOOP)
+       jd->ld    = DNEW(loopdata);
+#endif
+       jd->flags = 0;
+
+       /* Allocate codeinfo memory from the heap as we need to keep them. */
+
+       jd->code  = code_codeinfo_new(m); /* XXX check allocation */
+
+       /* set the current optimization level to the previous one plus 1 */
+
+       jd->code->optlevel = optlevel + 1;
+
+       /* get the optimization flags for the current JIT run */
+
+       jd->flags |= JITDATA_FLAG_SHOWINTERMEDIATE;
+       jd->flags |= JITDATA_FLAG_SHOWDISASSEMBLE;
+/*     jd->flags |= JITDATA_FLAG_VERBOSECALL; */
+
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+       if (!opt_intrp)
+# endif
+               /* initialize the register allocator */
+
+               reg_setup(jd);
+#endif
+
+       /* setup the codegendata memory */
+
+       codegen_setup(jd);
+
+       /* now call internal compile function */
+
+       r = jit_compile_intern(jd);
+
+       /* clear pointers to dump memory area */
+
+       m->basicblocks     = NULL;
+       m->basicblockindex = NULL;
+       m->instructions    = NULL;
+       m->stack           = NULL;
+
+       if (r == NULL) {
                /* We had an exception! Finish stuff here if necessary. */
 
-               /* Release memory for basic block profiling information. */
+               /* release codeinfo */
 
-               if (opt_prof)
-                       if (m->bbfrequency)
-                               MFREE(m->bbfrequency, u4, m->basicblockcount);
+               code_codeinfo_free(jd->code);
        }
 
+       /* release dump area */
+
+       dump_release(dumpsize);
+
+#if defined(ENABLE_STATISTICS)
+       /* measure time */
+
+       if (opt_getcompilingtime)
+               compilingtime_stop();
+#endif
+
+       log_message_method("Recompiling done: ", m);
+
        /* return pointer to the methods entry point */
 
        return r;
 }
 
+
 /* jit_compile_intern **********************************************************
 
    Static internal function which does the actual compilation.
@@ -1142,7 +1267,6 @@ static u1 *jit_compile_intern(jitdata *jd)
                if (f == NULL)
                        return NULL;
 #else
-
                f = NULL;
 #endif
 
@@ -1156,7 +1280,7 @@ static u1 *jit_compile_intern(jitdata *jd)
 
        /* if there is no javacode, print error message and return empty method   */
 
-       if (!m->jcode) {
+       if (m->jcode == NULL) {
                DEBUG_JIT_COMPILEVERBOSE("No code given for: ");
 
                code->entrypoint = (u1 *) (ptrint) do_nothing_function;
@@ -1207,7 +1331,7 @@ static u1 *jit_compile_intern(jitdata *jd)
        DEBUG_JIT_COMPILEVERBOSE("Analysing done: ");
 
 #ifdef ENABLE_VERIFIER
-       if (opt_verify) {
+       if (jd->flags & JITDATA_FLAG_VERIFY) {
                DEBUG_JIT_COMPILEVERBOSE("Typechecking: ");
 
                /* call typecheck pass */
@@ -1232,7 +1356,7 @@ static u1 *jit_compile_intern(jitdata *jd)
        RT_TIMING_GET_TIME(time_loop);
 
 #if defined(ENABLE_IFCONV)
-       if (jd->flags & JITDATA_FLAG_IFCONV)
+       if (JITDATA_HAS_FLAG_IFCONV(jd))
                if (!ifconv_static(jd))
                        return NULL;
 #endif
@@ -1317,10 +1441,10 @@ static u1 *jit_compile_intern(jitdata *jd)
 #if !defined(NDEBUG)
        /* intermediate and assembly code listings */
                
-       if (opt_showintermediate) {
+       if (JITDATA_HAS_FLAG_SHOWINTERMEDIATE(jd)) {
                show_method(jd);
-
-       } else if (opt_showdisassemble) {
+       }
+       else if (JITDATA_HAS_FLAG_SHOWDISASSEMBLE(jd)) {
 # if defined(ENABLE_DISASSEMBLER)
                DISASSEMBLE(code->entrypoint,
                                        code->entrypoint + (code->mcodelength - cd->dseglen));
@@ -1361,10 +1485,13 @@ static u1 *jit_compile_intern(jitdata *jd)
 
 /* jit_asm_compile *************************************************************
 
-   This method is called from asm_vm_call_method and does things like:
-   create stackframe info for exceptions, compile the method, patch
-   the entrypoint of the method into the calculated address in the JIT
-   code, and flushes the instruction cache.
+   This method is called from asm_vm_call_method and does:
+
+     - create stackframe info for exceptions
+     - compile the method
+     - patch the entrypoint of the method into the calculated address in
+       the JIT code
+     - flushes the instruction cache.
 
 *******************************************************************************/
 
index d42070e6fc1ecc6391a6e2bbbc3381d7dda462fa..2fe41c4af1cffe62403133f5a9f1f2fcfdb044f9 100644 (file)
@@ -30,7 +30,7 @@
    Changes: Christian Thalinger
                        Edwin Steiner
 
-   $Id: jit.h 5026 2006-06-12 18:50:13Z edwin $
+   $Id: jit.h 5049 2006-06-23 12:07:26Z twisti $
 
 */
 
@@ -87,17 +87,44 @@ typedef struct insinfo_inline insinfo_inline;
 
 /* jitdata ********************************************************************/
 
-#define JITDATA_FLAG_IFCONV    0x00000001
+#define JITDATA_FLAG_PARSE               0x00000001
+#define JITDATA_FLAG_VERIFY              0x00000002
+
+#define JITDATA_FLAG_IFCONV              0x00000004
+
+#define JITDATA_FLAG_SHOWINTERMEDIATE    0x20000000
+#define JITDATA_FLAG_SHOWDISASSEMBLE     0x40000000
+#define JITDATA_FLAG_VERBOSECALL         0x80000000
+
+
+#define JITDATA_HAS_FLAG_PARSE(jd) \
+    ((jd)->flags & JITDATA_FLAG_PARSE)
+
+#define JITDATA_HAS_FLAG_VERIFY(jd) \
+    ((jd)->flags & JITDATA_FLAG_VERIFY)
+
+#define JITDATA_HAS_FLAG_IFCONV(jd) \
+    ((jd)->flags & JITDATA_FLAG_IFCONV)
+
+#define JITDATA_HAS_FLAG_SHOWINTERMEDIATE(jd) \
+    ((jd)->flags & JITDATA_FLAG_SHOWINTERMEDIATE)
+
+#define JITDATA_HAS_FLAG_SHOWDISASSEMBLE(jd) \
+    ((jd)->flags & JITDATA_FLAG_SHOWDISASSEMBLE)
+
+#define JITDATA_HAS_FLAG_VERBOSECALL(jd) \
+    ((jd)->flags & JITDATA_FLAG_VERBOSECALL)
+
 
 struct jitdata {
-       methodinfo   *m;                    /* methodinfo of the method compiled  */
-       codeinfo     *code;
-       codegendata  *cd;
-       registerdata *rd;
+       methodinfo      *m;                 /* methodinfo of the method compiled  */
+       codeinfo        *code;
+       codegendata     *cd;
+       registerdata    *rd;
 #if defined(ENABLE_LOOP)
-       loopdata     *ld;
+       loopdata        *ld;
 #endif
-       u4            flags;                /* contains JIT compiler flags        */
+       u4               flags;             /* contains JIT compiler flags        */
 
        new_instruction *new_instructions;
        basicblock      *new_basicblocks;
@@ -1201,6 +1228,7 @@ void jit_close(void);
 
 /* compile a method with jit compiler */
 u1 *jit_compile(methodinfo *m);
+u1 *jit_recompile(methodinfo *m);
 
 /* patch the method entrypoint */
 u1 *jit_asm_compile(methodinfo *m, u1 *mptr, u1 *sp, u1 *ra);
index 3606284af2587107896f3a4a511d09b84bc647d0..7b8ca1c7ba30d57836d04624b1608407e2bedc7b 100644 (file)
@@ -31,7 +31,7 @@
             Christian Ullrich
             Edwin Steiner
 
-   $Id: codegen.c 5038 2006-06-19 22:22:34Z twisti $
+   $Id: codegen.c 5049 2006-06-23 12:07:26Z twisti $
 
 */
 
@@ -306,64 +306,30 @@ bool codegen(jitdata *jd)
 
 #if defined(ENABLE_THREADS)
        if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
-               /* stack offset for monitor argument */
+               p = dseg_addaddress(cd, BUILTIN_monitorenter);
+               M_ALD(REG_ITMP3, REG_PV, p);
+               M_MTCTR(REG_ITMP3);
 
-               s1 = rd->memuse;
-
-#if 0
-               if (opt_verbosecall) {
-                       M_LDA(REG_SP, REG_SP, -(INT_ARG_CNT * 4 + FLT_ARG_CNT * 8));
-
-                       for (p = 0; p < INT_ARG_CNT; p++)
-                               M_IST(rd->argintregs[p], REG_SP, p * 4);
-
-                       for (p = 0; p < FLT_ARG_CNT * 2; p += 2)
-                               M_DST(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 4);
-
-                       s1 += INT_ARG_CNT + FLT_ARG_CNT;
-               }
-#endif
-
-               /* decide which monitor enter function to call */
+               /* get or test the lock object */
 
                if (m->flags & ACC_STATIC) {
-                       p = dseg_addaddress(cd, BUILTIN_staticmonitorenter);
-                       M_ALD(REG_ITMP3, REG_PV, p);
-                       M_MTCTR(REG_ITMP3);
-                       p = dseg_addaddress(cd, m->class);
+                       p = dseg_addaddress(cd, &m->class->object.header);
                        M_ALD(rd->argintregs[0], REG_PV, p);
-                       M_AST(rd->argintregs[0], REG_SP, s1 * 4);
-                       M_JSR;
-
-               } else {
-                       p = dseg_addaddress(cd, BUILTIN_monitorenter);
-                       M_ALD(REG_ITMP3, REG_PV, p);
-                       M_MTCTR(REG_ITMP3);
+               }
+               else {
                        M_TST(rd->argintregs[0]);
                        M_BEQ(0);
                        codegen_add_nullpointerexception_ref(cd);
-                       M_AST(rd->argintregs[0], REG_SP, s1 * 4);
-                       M_JSR;
                }
 
-#if 0
-               if (opt_verbosecall) {
-                       for (p = 0; p < INT_ARG_CNT; p++)
-                               M_ILD(rd->argintregs[p], REG_SP, p * 4);
-
-                       for (p = 0; p < FLT_ARG_CNT; p++)
-                               M_DLD(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 4);
-
-
-                       M_LDA(REG_SP, REG_SP, (INT_ARG_CNT + FLT_ARG_CNT) * 8);
-               }
-#endif
+               M_AST(rd->argintregs[0], REG_SP, rd->memuse * 4);
+               M_JSR;
        }
 #endif
 
        /* call trace function */
 
-       if (opt_verbosecall)
+       if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
                codegen_trace_args(jd, stackframesize, false);
        }
 
@@ -2581,7 +2547,7 @@ nowperformreturn:
 
                        /* call trace function */
 
-                       if (opt_verbosecall) {
+                       if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
                                M_MFLR(REG_ZERO);
                                M_LDA(REG_SP, REG_SP, -10 * 8);
                                M_DST(REG_FRESULT, REG_SP, 48+0);
@@ -3800,7 +3766,7 @@ u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
        M_AST_INTERN(REG_ZERO, REG_SP, LA_LR_OFFSET);
        M_STWU(REG_SP, REG_SP, -(stackframesize * 4));
 
-       if (opt_verbosecall)
+       if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
                /* parent_argbase == stackframesize * 4 */
                codegen_trace_args(jd, stackframesize * 4 , true);
 
@@ -4002,7 +3968,7 @@ u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
 
        /* print call trace */
 
-       if (opt_verbosecall) {
+       if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
                 /* just restore the value we need, don't care about the other */
 
                if (md->returntype.type != TYPE_VOID) {
index d7341be68805b442bcb01f63c23476f13565538d..8c6f668f5e2af638b0c12d548256c67d833a5192 100644 (file)
 #include "vm/method.h"
 #include "vm/options.h"
 #include "vm/stringlocal.h"
+#include "vm/jit/jit.h"
 #include "vm/jit/methodheader.h"
-
-
-/* list_method_entry **********************************************************/
-
-typedef struct list_method_entry list_method_entry;
-
-struct list_method_entry {
-       methodinfo *m;
-       listnode    linkage;
-};
+#include "vm/jit/recompile.h"
 
 
 /* global variables ***********************************************************/
 
 #if defined(ENABLE_THREADS)
-static java_lang_VMThread *profile_vmthread;
+static threadobject *profile_threadobject;
 #endif
 
 
@@ -102,23 +94,15 @@ static s4 misses = 0;
 #if defined(ENABLE_THREADS)
 static void profile_thread(void)
 {
-       threadobject *tobj;
-       pthread_t     tid;
+       threadobject *t;
        s4            nanos;
        u1           *pc;
        u1           *pv;
-       codeinfo     *code;
        methodinfo   *m;
-
-       /* Get the thread id of the profiling thread, so we can skip it in
-          the profiling runs. */
-
-       tobj = THREADOBJECT;
-
-       tid = tobj->tid;
+       codeinfo     *code;
 
        while (true) {
-               /* sleep thread for 0.5-1 ms */
+               /* sleep thread for 0.5-1.0 ms */
 
                nanos = 500 + (int) (500.0 * (rand() / (RAND_MAX + 1.0)));
 /*             fprintf(stderr, "%d\n", nanos); */
@@ -128,19 +112,19 @@ static void profile_thread(void)
 
                /* iterate over all started threads */
 
-               tobj = mainthreadobj;
+               t = mainthreadobj;
 
                do {
-                       /* are we a different thread? */
+                       /* is this a Java thread? */
 
-                       if (tobj->tid != tid) {
+                       if (t->flags & THREAD_FLAG_JAVA) {
                                /* send SIGUSR2 to thread to get the current PC */
 
-                               pthread_kill(tobj->tid, SIGUSR2);
+                               pthread_kill(t->tid, SIGUSR2);
 
                                /* the thread object now contains the current thread PC */
 
-                               pc = tobj->pc;
+                               pc = t->pc;
 
                                /* get the PV for the current PC */
 
@@ -149,7 +133,6 @@ static void profile_thread(void)
                                /* get methodinfo pointer from data segment */
 
                                if (pv == NULL) {
-                                       m = NULL;
                                        misses++;
                                }
                                else {
@@ -161,22 +144,32 @@ static void profile_thread(void)
                                        if (code != NULL) {
                                                m = code->m;
 
-                                               /* increase the method incovation counter */
+                                               /* native methods are never recompiled */
 
-                                               m->frequency++;
-                                               hits++;
+                                               if (!(m->flags & ACC_NATIVE)) {
+                                                       /* increase the method incovation counter */
 
-/*                                             if (m->frequency > 1000) { */
-/*                                                     printf("Recompile: "); */
-/*                                                     method_println(m); */
-/*                                                     m->frequency = 0; */
-/*                                             } */
+                                                       code->frequency++;
+                                                       hits++;
+
+                                                       if (code->frequency > 500) {
+                                                               /* clear frequency count before
+                                                                  recompilation */
+
+                                                               code->frequency = 0;
+
+                                                               /* add this method to the method list
+                                                                  and start recompilation */
+
+                                                               recompile_queue_method(m);
+                                                       }
+                                               }
                                        }
                                }
                        }
 
-                       tobj = tobj->next;
-               } while ((tobj != NULL) && (tobj != mainthreadobj));
+                       t = t->next;
+               } while ((t != NULL) && (t != mainthreadobj));
        }
 }
 #endif
@@ -195,20 +188,19 @@ bool profile_start_thread(void)
 
        /* create the profile object */
 
-       profile_vmthread =
-               (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
+       profile_threadobject = NEW(threadobject);
 
-       if (!profile_vmthread)
+       if (profile_threadobject == NULL)
                return false;
 
        t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
 
-       t->vmThread = profile_vmthread;
+       t->vmThread = (java_lang_VMThread *) profile_threadobject;
        t->name     = javastring_new_from_ascii("Profiling Sampler");
        t->daemon   = true;
        t->priority = 5;
 
-       profile_vmthread->thread = t;
+       profile_threadobject->o.thread = t;
 
        /* actually start the profile sampling thread */
 
@@ -235,6 +227,7 @@ void profile_printstats(void)
        list_method_entry      *tlme;
        classinfo              *c;
        methodinfo             *m;
+       codeinfo               *code;
        u4                      slot;
        classcache_name_entry  *nmen;
        classcache_class_entry *clsen;
@@ -248,9 +241,7 @@ void profile_printstats(void)
 
        /* create new method list */
 
-       l = NEW(list);
-
-       list_init(l, OFFSET(list_method_entry, linkage));
+       l = list_create(OFFSET(list_method_entry, linkage));
 
        /* iterate through all classes and methods */
 
@@ -271,13 +262,15 @@ void profile_printstats(void)
                                for (i = 0; i < c->methodscount; i++) {
                                        m = &(c->methods[i]);
 
+                                       code = m->code;
+
                                        /* was this method actually called? */
 
-                                       if (m->frequency > 0) {
+                                       if ((code != NULL) && (code->frequency > 0)) {
                                                /* add to overall stats */
 
-                                               frequency += m->frequency;
-                                               cycles    += m->cycles;
+                                               frequency += code->frequency;
+                                               cycles    += code->cycles;
 
                                                /* create new list entry */
 
@@ -287,13 +280,13 @@ void profile_printstats(void)
                                                /* sort the new entry into the list */
                                                
                                                if ((tlme = list_first(l)) == NULL) {
-                                                       list_addfirst(l, lme);
+                                                       list_add_first(l, lme);
                                                }
                                                else {
                                                        for (; tlme != NULL; tlme = list_next(l, tlme)) {
                                                                /* check the frequency */
 
-                                                               if (m->frequency > tlme->m->frequency) {
+                                                               if (code->frequency > tlme->m->code->frequency) {
                                                                        list_add_before(l, tlme, lme);
                                                                        break;
                                                                }
@@ -303,7 +296,7 @@ void profile_printstats(void)
                                                           it as last entry */
 
                                                        if (tlme == NULL)
-                                                               list_addlast(l, lme);
+                                                               list_add_last(l, lme);
                                                }
                                        }
                                }
@@ -323,11 +316,13 @@ void profile_printstats(void)
 
                m = lme->m;
 
+               code = m->code;
+
                printf("%10d   %.5f   %12ld   %.5f   ",
-                          m->frequency,
-                          (double) m->frequency / (double) frequency,
-                          (long)m->cycles,
-                          (double) m->cycles / (double) cycles);
+                          code->frequency,
+                          (double) code->frequency / (double) frequency,
+                          (long) code->cycles,
+                          (double) code->cycles / (double) cycles);
 
                method_println(m);
 
@@ -341,7 +336,7 @@ void profile_printstats(void)
        }
 
        printf("-----------           -------------- \n");
-       printf("%10d             %12ld\n", frequency, (long)cycles);
+       printf("%10d             %12ld\n", frequency, (long) cycles);
 
        printf("\nruns  : %10d\n", runs);
        printf("hits  : %10d\n", hits);
diff --git a/src/vm/jit/recompile.c b/src/vm/jit/recompile.c
new file mode 100644 (file)
index 0000000..112e651
--- /dev/null
@@ -0,0 +1,285 @@
+/* src/vm/recompile.c - recompilation system
+
+   Copyright (C) 1996-2005, 2006 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, J. Wenninger, Institut f. Computersprachen - TU Wien
+
+   This file is part of CACAO.
+
+   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.
+
+   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.
+
+   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., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+   Contact: cacao@cacaojvm.org
+
+   Authors: Christian Thalinger
+
+   Changes:
+
+   $Id: cacao.c 4357 2006-01-22 23:33:38Z twisti $
+
+*/
+
+
+#include "config.h"
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include "vm/types.h"
+
+#include "mm/memory.h"
+#include "native/jni.h"
+#include "native/include/java_lang_Thread.h"
+#include "native/include/java_lang_VMThread.h"
+
+#if defined(ENABLE_THREADS)
+# include "threads/native/threads.h"
+#endif
+
+#include "toolbox/list.h"
+#include "vm/builtin.h"
+#include "vm/classcache.h"
+#include "vm/stringlocal.h"
+#include "vm/jit/recompile.h"
+
+
+/* global variables ***********************************************************/
+
+static threadobject *recompile_threadobject;
+static java_objectheader *lock_recompile_thread;
+static list *list_recompile_methods;
+
+
+/* recompile_init **************************************************************
+
+   Initializes the recompilation system.
+
+*******************************************************************************/
+
+bool recompile_init(void)
+{
+       /* initialize the recompile lock object */
+
+       lock_recompile_thread = NEW(java_objectheader);
+
+       lock_init_object_lock(lock_recompile_thread);
+
+       /* create method list */
+
+       list_recompile_methods = list_create(OFFSET(list_method_entry, linkage));
+
+       /* everything's ok */
+
+       return true;
+}
+
+
+/* recompile_replace_vftbl *****************************************************
+
+   XXX
+
+*******************************************************************************/
+
+static void recompile_replace_vftbl(methodinfo *m)
+{
+       codeinfo               *code;
+       codeinfo               *pcode;
+       u4                      slot;
+       classcache_name_entry  *nmen;
+       classcache_class_entry *clsen;
+       classinfo              *c;
+       vftbl_t                *vftbl;
+       s4                      i;
+
+       /* get current and previous codeinfo structure */
+
+       code  = m->code;
+       pcode = code->prev;
+
+       assert(pcode);
+
+       /* iterate over all classes */
+
+       for (slot = 0; slot < hashtable_classcache.size; slot++) {
+               nmen = (classcache_name_entry *) hashtable_classcache.ptr[slot];
+
+               for (; nmen; nmen = nmen->hashlink) {
+                       /* iterate over all class entries */
+
+                       for (clsen = nmen->classes; clsen; clsen = clsen->next) {
+                               c = clsen->classobj;
+
+                               if (c == NULL)
+                                       continue;
+
+                               /* Search for entrypoint of the previous codeinfo in
+                                  the vftbl and replace it with the current one. */
+
+                               vftbl = c->vftbl;
+
+                               /* Is the class linked? Means, is the vftbl finished? */
+
+                               if (!(c->state & CLASS_LINKED))
+                                       continue;
+
+                               /* Does the class have a vftbl? Some internal classes
+                                  (e.g. $NEW$) are linked, but do not have a
+                                  vftbl. */
+
+                               if (vftbl == NULL)
+                                       continue;
+
+                               for (i = 0; i < vftbl->vftbllength; i++) {
+                                       if (vftbl->table[i] == pcode->entrypoint) {
+                                               printf("replacing vftbl in: ");
+                                               class_println(c);
+                                               vftbl->table[i] = code->entrypoint;
+                                       }
+                               }
+                       }
+               }
+       }
+}
+
+
+/* recompile_thread ************************************************************
+
+   XXX
+
+*******************************************************************************/
+
+static void recompile_thread(void)
+{
+       list_method_entry *lme;
+
+       while (true) {
+               /* get the lock on the recompile lock object, so we can call wait */
+
+               builtin_monitorenter(lock_recompile_thread);
+
+               /* wait forever (0, 0) on that object till we are signaled */
+       
+               lock_wait_for_object(lock_recompile_thread, 0, 0);
+
+               /* leave the lock */
+
+               builtin_monitorexit(lock_recompile_thread);
+
+               /* get the next method and recompile it */
+
+               while ((lme = list_first(list_recompile_methods)) != NULL) {
+                       /* recompile this method */
+
+                       (void) jit_recompile(lme->m);
+
+                       /* replace in vftbl's */
+
+                       recompile_replace_vftbl(lme->m);
+
+                       /* remove the compiled method */
+
+                       list_remove(list_recompile_methods, lme);
+
+                       /* free the entry */
+
+                       FREE(lme, list_method_entry);
+               }
+       }
+}
+
+
+/* recompile_start_thread ******************************************************
+
+   Starts the recompilation thread.
+
+*******************************************************************************/
+
+bool recompile_start_thread(void)
+{
+       java_lang_Thread *t;
+
+       /* create the profile object */
+
+       recompile_threadobject = NEW(threadobject);
+
+       if (recompile_threadobject == NULL)
+               return false;
+
+       t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
+
+       t->vmThread = (java_lang_VMThread *) recompile_threadobject;
+       t->name     = javastring_new_from_ascii("Recompiler");
+       t->daemon   = true;
+       t->priority = 5;
+
+       recompile_threadobject->o.thread = t;
+
+       /* actually start the recompilation thread */
+
+       threads_start_thread(t, recompile_thread);
+
+       /* everything's ok */
+
+       return true;
+}
+
+
+/* recompile_queue_method ******************************************************
+
+   Adds a method to the recompilation list and signal the
+   recompilation thread that there is some work to do.
+
+*******************************************************************************/
+
+void recompile_queue_method(methodinfo *m)
+{
+       list_method_entry *lme;
+
+       /* create a method entry */
+
+       lme = NEW(list_method_entry);
+       lme->m = m;
+
+       /* and add it to the list */
+
+       list_add_last(list_recompile_methods, lme);
+
+       /* get the lock on the recompile lock object, so we can call notify */
+
+       builtin_monitorenter(lock_recompile_thread);
+
+       /* signal the recompiler thread */
+       
+       lock_notify_object(lock_recompile_thread);
+
+       /* leave the lock */
+
+       builtin_monitorexit(lock_recompile_thread);
+}
+
+
+/*
+ * 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:
+ */
diff --git a/src/vm/jit/recompile.h b/src/vm/jit/recompile.h
new file mode 100644 (file)
index 0000000..73cec30
--- /dev/null
@@ -0,0 +1,76 @@
+/* src/vm/jit/recompile.h - recompilation system
+
+   Copyright (C) 1996-2005, 2006 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, J. Wenninger, Institut f. Computersprachen - TU Wien
+
+   This file is part of CACAO.
+
+   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.
+
+   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.
+
+   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., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+   Contact: cacao@cacaojvm.org
+
+   Authors: Christian Thalinger
+
+   Changes:
+
+   $Id: cacao.c 4357 2006-01-22 23:33:38Z twisti $
+
+*/
+
+
+#ifndef _RECOMPILE_H
+#define _RECOMPILE_H
+
+#include "config.h"
+#include "vm/types.h"
+
+#include "vm/global.h"
+
+
+/* list_method_entry **********************************************************/
+
+typedef struct list_method_entry list_method_entry;
+
+struct list_method_entry {
+       methodinfo *m;
+       listnode    linkage;
+};
+
+
+/* function prototypes ********************************************************/
+
+bool recompile_init(void);
+bool recompile_start_thread(void);
+
+void recompile_queue_method(methodinfo *m);
+
+#endif /* _PROFILE_H */
+
+
+/*
+ * 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:
+ */
index 9f1100cb641fc6caf30180f5a913fd0147ab749d..370d0ee0e229f6bc5acbc19209557490430412f1 100644 (file)
@@ -1,4 +1,4 @@
-/* vm/jit/show.c - showing the intermediate representation
+/* src/vm/jit/show.c - showing the intermediate representation
 
    Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
@@ -504,7 +504,7 @@ void new_show_method(jitdata *jd, int stage)
 #if defined(ENABLE_DISASSEMBLER)
        /* show code before first basic block */
 
-       if (stage >= SHOW_CODE && opt_showdisassemble) {
+       if ((stage >= SHOW_CODE) && JITDATA_HAS_FLAG_SHOWDISASSEMBLE(jd)) {
                u1ptr = (u1 *) ((ptrint) code->mcode + cd->dseglen);
 
                for (; u1ptr < (u1 *) ((ptrint) code->mcode + cd->dseglen + jd->new_basicblocks[0].mpc);)
@@ -730,7 +730,7 @@ void show_method(jitdata *jd)
 #if defined(ENABLE_DISASSEMBLER)
        /* show code before first basic block */
 
-       if (opt_showdisassemble) {
+       if (JITDATA_HAS_FLAG_SHOWDISASSEMBLE(jd)) {
                u1ptr = (u1 *) ((ptrint) code->mcode + cd->dseglen);
 
                for (; u1ptr < (u1 *) ((ptrint) code->mcode + cd->dseglen + m->basicblocks[0].mpc);)
@@ -748,7 +748,7 @@ void show_method(jitdata *jd)
 #if defined(ENABLE_DISASSEMBLER)
        /* show stubs code */
 
-       if (opt_showdisassemble && opt_showexceptionstubs) {
+       if (JITDATA_HAS_FLAG_SHOWDISASSEMBLE(jd) && opt_showexceptionstubs) {
                printf("\nException stubs code:\n");
                printf("Length: %d\n\n", (s4) (code->mcodelength -
                                                                           ((ptrint) cd->dseglen +
@@ -833,7 +833,8 @@ void new_show_basicblock(jitdata *jd, basicblock *bptr, int stage)
                }
 
 #if defined(ENABLE_DISASSEMBLER)
-               if (stage >= SHOW_CODE && opt_showdisassemble && (!deadcode)) {
+               if ((stage >= SHOW_CODE) && JITDATA_HAS_FLAG_SHOWDISASSEMBLE(jd) &&
+                       (!deadcode)) {
                        printf("\n");
                        u1ptr = (u1 *) ((ptrint) code->mcode + cd->dseglen + bptr->mpc);
 
@@ -919,7 +920,7 @@ void show_basicblock(jitdata *jd, basicblock *bptr)
                }
 
 #if defined(ENABLE_DISASSEMBLER)
-               if (opt_showdisassemble && (!deadcode)) {
+               if (JITDATA_HAS_FLAG_SHOWDISASSEMBLE(jd) && (!deadcode)) {
                        printf("\n");
                        u1ptr = (u1 *) ((ptrint) code->mcode + cd->dseglen + bptr->mpc);
 
index b92abb3aad9b279fe9a2f2add0dada78da41d156..ece2627952d6be67b8011f8f30a1b2d4cb6dd7ed 100644 (file)
@@ -32,7 +32,7 @@
             Edwin Steiner
             Christian Thalinger
 
-   $Id: loader.c 5031 2006-06-14 18:36:22Z motse $
+   $Id: loader.c 5049 2006-06-23 12:07:26Z twisti $
 
 */
 
@@ -679,7 +679,7 @@ static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
 
                        /* link the class later, because we cannot link the class currently
                           loading */
-                       list_addfirst(&unlinkedclasses, tc);
+                       list_add_first(&unlinkedclasses, tc);
                }
 
                /* the classref is created later */
@@ -2454,12 +2454,12 @@ classinfo *load_newly_created_array(classinfo *c, java_objectheader *loader)
 
                tc = class_java_lang_Cloneable;
                LOADER_ASSERT(tc->state & CLASS_LOADED);
-               list_addfirst(&unlinkedclasses, tc);
+               list_add_first(&unlinkedclasses, tc);
                c->interfaces[0].cls = tc;
 
                tc = class_java_io_Serializable;
                LOADER_ASSERT(tc->state & CLASS_LOADED);
-               list_addfirst(&unlinkedclasses, tc);
+               list_add_first(&unlinkedclasses, tc);
                c->interfaces[1].cls = tc;
 
        } else {
index 30577dc09195b0523a141f51616b80129e3d733a..3b093650446068d04caede416319c7cb068a415d 100644 (file)
@@ -28,7 +28,7 @@
 
    Changes:
 
-   $Id: properties.c 4958 2006-05-26 11:57:20Z twisti $
+   $Id: properties.c 5049 2006-06-23 12:07:26Z twisti $
 
 */
 
@@ -79,9 +79,7 @@ static methodinfo *mput;
 
 bool properties_init(void)
 {
-       list_properties = NEW(list);
-
-       list_init(list_properties, OFFSET(list_properties_entry, linkage));
+       list_properties = list_create(OFFSET(list_properties_entry, linkage));
 
        /* everything's ok */
 
@@ -131,7 +129,7 @@ void properties_add(char *key, char *value)
        p->key   = key;
        p->value = value;
 
-       list_addlast(list_properties, p);
+       list_add_last_unsynced(list_properties, p);
 }
 
 
index 7259258de59d3b364b1128b385d108628db11110..98a7bc7371ae309c32851db06c629bb16fc14e9c 100644 (file)
@@ -31,7 +31,7 @@
    Changes: Christian Thalinger
                        Edwin Steiner
 
-   $Id: string.c 4921 2006-05-15 14:24:36Z twisti $
+   $Id: string.c 5049 2006-06-23 12:07:26Z twisti $
 
 */
 
@@ -521,11 +521,12 @@ char *javastring_tochar(java_objectheader *so)
 
 *******************************************************************************/
 
-utf *javastring_toutf(java_lang_String *string, bool isclassname)
+utf *javastring_toutf(java_lang_String *s, bool isclassname)
 {
-       java_lang_String *str = (java_lang_String *) string;
+       if (s == NULL)
+               return utf_null;
 
-       return utf_new_u2(str->value->data + str->offset, str->count, isclassname);
+       return utf_new_u2(s->value->data + s->offset, s->count, isclassname);
 }
 
 
@@ -537,7 +538,7 @@ utf *javastring_toutf(java_lang_String *string, bool isclassname)
 
 s4 javastring_strlen(java_lang_String *s)
 {
-       if (!s)
+       if (s == NULL)
                return 0;
 
        return s->count;
@@ -624,7 +625,7 @@ java_objectheader *literalstring_u2(java_chararray *a, u4 length, u4 offset,
        /* if we use eager loading, we have to check loaded String class */
 
        if (opt_eager)
-               list_addfirst(&unlinkedclasses, class_java_lang_String);
+               list_add_first(&unlinkedclasses, class_java_lang_String);
 
        /* create new javastring */
 
index f9b9f16d5deedc52ecb4339c4dfed7649966f674..96dea7a969098b78fac4a557efe0cb0936a759c9 100644 (file)
@@ -28,7 +28,7 @@
 
    Changes:
 
-   $Id: suck.c 5022 2006-06-07 12:51:50Z twisti $
+   $Id: suck.c 5049 2006-06-23 12:07:26Z twisti $
 
 */
 
@@ -70,9 +70,7 @@ list *list_classpath_entries;
 
 bool suck_init(void)
 {
-       list_classpath_entries = NEW(list);
-
-       list_init(list_classpath_entries, OFFSET(list_classpath_entry, linkage));
+       list_classpath_entries = list_create(OFFSET(list_classpath_entry, linkage));
 
        /* everything's ok */
 
@@ -216,7 +214,7 @@ void suck_add(char *classpath)
                        /* add current classpath entry, if no error */
 
                        if (lce)
-                               list_addlast(list_classpath_entries, lce);
+                               list_add_last(list_classpath_entries, lce);
                }
 
                /* goto next classpath entry, skip ':' delimiter */
index 4a9efc84983ef9ae92aa1b2ccb5d9d07b23fbdf8..1089ca76367bff41fdc7ccfa12e924bba994493a 100644 (file)
@@ -62,6 +62,9 @@
 #include "vm/vm.h"
 #include "vm/jit/jit.h"
 #include "vm/jit/asmpart.h"
+
+#include "vm/jit/recompile.h"
+
 #include "vm/jit/profile/profile.h"
 #include "vm/rt-timing.h"
 
@@ -69,6 +72,7 @@
 #include "native/jvmti/cacaodbg.h"
 #endif
 
+
 /* Invocation API variables ***************************************************/
 
 _Jv_JavaVM *_Jv_jvm;                    /* denotes a Java VM                  */
@@ -1237,12 +1241,23 @@ bool vm_create(JavaVMInitArgs *vm_args)
                throw_main_exception_exit();
 #endif
 
+       /* initialize recompilation */
+
+       if (!recompile_init())
+               throw_main_exception_exit();
+               
 #if defined(ENABLE_THREADS)
        /* finally, start the finalizer thread */
 
        if (!finalizer_start_thread())
                throw_main_exception_exit();
 
+       /* start the recompilation thread (must be done before the
+          profiling thread) */
+
+       if (!recompile_start_thread())
+               throw_main_exception_exit();
+
 # if defined(ENABLE_PROFILING)
        /* start the profile sampling thread */