From: Stefan Ring Date: Sat, 20 Dec 2008 15:06:26 +0000 (+0100) Subject: Merged branch subtype-trunk into default. X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=commitdiff_plain;h=8c6bb03b79a31fcdb02e2331a91a928d558c2845;hp=cce34f898a508bde05c54be7f19c0fbfeb2dc0a2;p=cacao.git Merged branch subtype-trunk into default. --- diff --git a/src/mm/Makefile.am b/src/mm/Makefile.am index 78ba758a1..b486fcf33 100644 --- a/src/mm/Makefile.am +++ b/src/mm/Makefile.am @@ -63,8 +63,8 @@ libmm_la_SOURCES = \ dumpmemory.hpp \ $(GC_FILE) \ gc.hpp \ - memory.c \ - memory.h + memory.cpp \ + memory.hpp libmm_la_LIBADD = \ $(GC_LIB) diff --git a/src/mm/cacao-gc/compact.c b/src/mm/cacao-gc/compact.c index 5e384d397..0cd0ad60d 100644 --- a/src/mm/cacao-gc/compact.c +++ b/src/mm/cacao-gc/compact.c @@ -31,8 +31,8 @@ #include "gc.h" #include "heap.h" #include "mark.h" -#include "mm/memory.h" -#include "toolbox/logging.h" +#include "mm/memory.hpp" +#include "toolbox/logging.hpp" /* Threading macros ***********************************************************/ diff --git a/src/mm/cacao-gc/copy.c b/src/mm/cacao-gc/copy.c index 425da5872..94822d938 100644 --- a/src/mm/cacao-gc/copy.c +++ b/src/mm/cacao-gc/copy.c @@ -33,8 +33,8 @@ #include "mark.h" #include "region.h" #include "rootset.h" -#include "mm/memory.h" -#include "toolbox/logging.h" +#include "mm/memory.hpp" +#include "toolbox/logging.hpp" #include "vm/global.h" diff --git a/src/mm/cacao-gc/final.c b/src/mm/cacao-gc/final.c index b895797e4..fadad8687 100644 --- a/src/mm/cacao-gc/final.c +++ b/src/mm/cacao-gc/final.c @@ -29,8 +29,8 @@ #include "gc.h" #include "final.h" #include "heap.h" -#include "mm/memory.h" -#include "vm/finalizer.h" +#include "mm/memory.hpp" +#include "vm/finalizer.hpp" /* Global Variables ***********************************************************/ diff --git a/src/mm/cacao-gc/gc.c b/src/mm/cacao-gc/gc.c index e9fd6d50f..6853ebc95 100644 --- a/src/mm/cacao-gc/gc.c +++ b/src/mm/cacao-gc/gc.c @@ -41,10 +41,10 @@ #include "mark.h" #include "region.h" #include "rootset.h" -#include "mm/memory.h" -#include "toolbox/logging.h" +#include "mm/memory.hpp" +#include "toolbox/logging.hpp" -#include "vm/finalizer.h" +#include "vm/finalizer.hpp" #include "vm/rt-timing.h" #include "vm/vm.hpp" diff --git a/src/mm/cacao-gc/heap.c b/src/mm/cacao-gc/heap.c index 22ce06917..66a9f8c5e 100644 --- a/src/mm/cacao-gc/heap.c +++ b/src/mm/cacao-gc/heap.c @@ -33,10 +33,10 @@ #include "heap.h" #include "mark.h" #include "region.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/include/java_lang_String.h" #include "native/llni.h" -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" #include "vm/global.h" #include "vm/options.h" diff --git a/src/mm/cacao-gc/mark.c b/src/mm/cacao-gc/mark.c index fedfb9abb..a18ceca72 100644 --- a/src/mm/cacao-gc/mark.c +++ b/src/mm/cacao-gc/mark.c @@ -30,8 +30,8 @@ #include "heap.h" #include "mark.h" #include "rootset.h" -#include "mm/memory.h" -#include "toolbox/logging.h" +#include "mm/memory.hpp" +#include "toolbox/logging.hpp" #include "vm/global.h" #include "vm/linker.hpp" diff --git a/src/mm/cacao-gc/region.c b/src/mm/cacao-gc/region.c index 44a443d1c..f601e530a 100644 --- a/src/mm/cacao-gc/region.c +++ b/src/mm/cacao-gc/region.c @@ -29,8 +29,8 @@ #include "vm/types.h" #include "region.h" -#include "mm/memory.h" -#include "toolbox/logging.h" +#include "mm/memory.hpp" +#include "toolbox/logging.hpp" /* region_init ***************************************************************** diff --git a/src/mm/cacao-gc/rootset.c b/src/mm/cacao-gc/rootset.c index 7761fa808..ce6a68071 100644 --- a/src/mm/cacao-gc/rootset.c +++ b/src/mm/cacao-gc/rootset.c @@ -30,12 +30,12 @@ #include "heap.h" #include "mark.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "threads/threadlist.h" #include "threads/thread.hpp" -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" #include "vm/global.h" #include "vm/jit/replace.hpp" diff --git a/src/mm/codememory.c b/src/mm/codememory.c index b56179221..c3e00384c 100644 --- a/src/mm/codememory.c +++ b/src/mm/codememory.c @@ -33,7 +33,7 @@ #include "threads/thread.hpp" #include "mm/codememory.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "vm/global.h" #include "vm/options.h" diff --git a/src/mm/dumpmemory.cpp b/src/mm/dumpmemory.cpp index 4650d52fb..75de734a5 100644 --- a/src/mm/dumpmemory.cpp +++ b/src/mm/dumpmemory.cpp @@ -29,7 +29,7 @@ #include #include "mm/dumpmemory.hpp" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "threads/thread.hpp" diff --git a/src/mm/dumpmemory.hpp b/src/mm/dumpmemory.hpp index c871d3e04..79433a186 100644 --- a/src/mm/dumpmemory.hpp +++ b/src/mm/dumpmemory.hpp @@ -209,7 +209,7 @@ public: // Includes. -#include "mm/memory.h" +#include "mm/memory.hpp" #include "threads/thread.hpp" diff --git a/src/mm/gc-boehm.cpp b/src/mm/gc-boehm.cpp index bfd612b01..ca8501e63 100644 --- a/src/mm/gc-boehm.cpp +++ b/src/mm/gc-boehm.cpp @@ -39,13 +39,13 @@ #include "boehm-gc/include/gc.h" #include "mm/gc.hpp" -#include "mm/memory.h" +#include "mm/memory.hpp" -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" #include "vm/jit/builtin.hpp" #include "vm/exceptions.hpp" -#include "vm/finalizer.h" +#include "vm/finalizer.hpp" #include "vm/global.h" #include "vm/loader.hpp" #include "vm/options.h" diff --git a/src/mm/gc-none.cpp b/src/mm/gc-none.cpp index d0a488d2a..0ef0cf3f0 100644 --- a/src/mm/gc-none.cpp +++ b/src/mm/gc-none.cpp @@ -36,9 +36,9 @@ #include "boehm-gc/include/gc.h" #include "mm/gc.hpp" -#include "mm/memory.h" +#include "mm/memory.hpp" -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" #include "vm/jit/builtin.hpp" #include "vm/global.h" diff --git a/src/mm/memory.c b/src/mm/memory.c deleted file mode 100644 index 0774aee01..000000000 --- a/src/mm/memory.c +++ /dev/null @@ -1,274 +0,0 @@ -/* src/mm/memory.c - memory management - - Copyright (C) 1996-2005, 2006, 2007, 2008 - CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO - - 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. - -*/ - - -#include "config.h" - -#include -#include - -#if defined(__DARWIN__) -/* If we compile with -ansi on darwin, is not - included. So let's do it here. */ -# include -#endif - -#include "vm/types.h" - -#include "arch.h" - -#include "mm/memory.h" - -#include "native/native.hpp" - -#include "threads/lock.hpp" -#include "threads/thread.hpp" - -#include "toolbox/logging.h" - -#include "vm/global.h" -#include "vm/string.hpp" -#include "vm/vm.hpp" - -#include "vm/options.h" -#include "vm/os.hpp" - -#if defined(ENABLE_STATISTICS) -# include "vm/statistics.h" -#endif - - -/* memory_mprotect ************************************************************* - - Convenience function for mprotect. This function also does error - checking. - -*******************************************************************************/ - -void memory_mprotect(void *addr, size_t len, int prot) -{ - if (os_mprotect(addr, len, prot) != 0) - vm_abort_errno("memory_mprotect: os_mprotect failed"); -} - - -/* memory_checked_alloc ******************************************************** - - Allocated zeroed-out memory and does an OOM check. - - ERROR HANDLING: - XXX If no memory could be allocated, this function justs *exists*. - -*******************************************************************************/ - -void *memory_checked_alloc(size_t size) -{ - /* always allocate memory zeroed out */ - - void *p = os_calloc(size, 1); - - if (p == NULL) - vm_abort("memory_checked_alloc: calloc failed: out of memory"); - - return p; -} - - -void *mem_alloc(int32_t size) -{ - void *m; - - if (size == 0) - return NULL; - -#if defined(ENABLE_STATISTICS) - if (opt_stat) { - memoryusage += size; - - if (memoryusage > maxmemusage) - maxmemusage = memoryusage; - } -#endif - - m = memory_checked_alloc(size); - -#if defined(ENABLE_MEMCHECK) - /* XXX we would like to poison the memory, but callers rely on */ - /* the zeroing. This should change sooner or later. */ - /* memset(m, MEMORY_CLEAR_BYTE, size); */ -#endif - - return m; -} - - -void *mem_realloc(void *src, int32_t len1, int32_t len2) -{ - void *dst; - - /* prevent compiler warnings */ - - dst = NULL; - - if (src == NULL) - if (len1 != 0) - vm_abort("mem_realloc: reallocating memoryblock with address NULL, length != 0"); - -#if defined(ENABLE_STATISTICS) - if (opt_stat) - memoryusage = (memoryusage - len1) + len2; -#endif - -#if defined(ENABLE_MEMCHECK) - if (len2 < len1) - os_memset((u1*)dst + len2, MEMORY_CLEAR_BYTE, len1 - len2); -#endif - - dst = realloc(src, len2); - - if (dst == NULL) - vm_abort("mem_realloc: realloc failed: out of memory"); - -#if defined(ENABLE_MEMCHECK) - if (len2 > len1) - os_memset((u1*)dst + len1, MEMORY_CLEAR_BYTE, len2 - len1); -#endif - - return dst; -} - - -void mem_free(void *m, int32_t size) -{ - if (!m) { - if (size == 0) - return; - - log_text("returned memoryblock with address NULL, length != 0"); - assert(0); - } - -#if defined(ENABLE_STATISTICS) - if (opt_stat) - memoryusage -= size; -#endif - -#if defined(ENABLE_MEMCHECK) - /* destroy the contents */ - os_memset(m, MEMORY_CLEAR_BYTE, size); -#endif - - os_free(m); -} - - -/* memory_thread *************************************************************** - - Prints regularly memory statistics. - -*******************************************************************************/ - -#if defined(ENABLE_THREADS) && !defined(NDEBUG) -static void memory_thread(void) -{ - int32_t seconds; - - /* Prevent compiler warning. */ - - seconds = 1; - - /* If both arguments are specified, use the value of - ProfileMemoryUsage. */ - - if (opt_ProfileGCMemoryUsage) - seconds = opt_ProfileGCMemoryUsage; - - if (opt_ProfileMemoryUsage) - seconds = opt_ProfileMemoryUsage; - - while (true) { - /* sleep thread */ - - threads_sleep(seconds * 1000, 0); - -# if defined(ENABLE_STATISTICS) - /* Print current date and time (only when we print to the - stdout). */ - - if (!opt_ProfileMemoryUsageGNUPlot) - statistics_print_date(); - - /* print memory usage */ - - if (opt_ProfileMemoryUsage) - statistics_print_memory_usage(); - - /* print GC memory usage */ - - if (opt_ProfileGCMemoryUsage) - statistics_print_gc_memory_usage(); -# endif - } -} -#endif - - -/* memory_start_thread ********************************************************* - - Starts the memory profiling thread. - -*******************************************************************************/ - -#if defined(ENABLE_THREADS) && !defined(NDEBUG) -bool memory_start_thread(void) -{ - utf *name; - - name = utf_new_char("Memory Profiler"); - - /* start the memory profiling thread */ - - if (!threads_thread_start_internal(name, memory_thread)) - return false; - - /* everything's ok */ - - return true; -} -#endif - - -/* - * 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: - * vim:noexpandtab:sw=4:ts=4: - */ diff --git a/src/mm/memory.cpp b/src/mm/memory.cpp new file mode 100644 index 000000000..f074e1d20 --- /dev/null +++ b/src/mm/memory.cpp @@ -0,0 +1,274 @@ +/* src/mm/memory.cpp - memory management + + Copyright (C) 1996-2005, 2006, 2007, 2008 + CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO + + 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. + +*/ + + +#include "config.h" + +#include +#include + +#if defined(__DARWIN__) +/* If we compile with -ansi on darwin, is not + included. So let's do it here. */ +# include +#endif + +#include "vm/types.h" + +#include "arch.h" + +#include "mm/memory.hpp" + +#include "native/native.hpp" + +#include "threads/lock.hpp" +#include "threads/thread.hpp" + +#include "toolbox/logging.hpp" + +#include "vm/global.h" +#include "vm/string.hpp" +#include "vm/vm.hpp" + +#include "vm/options.h" +#include "vm/os.hpp" + +#if defined(ENABLE_STATISTICS) +# include "vm/statistics.h" +#endif + + +/* memory_mprotect ************************************************************* + + Convenience function for mprotect. This function also does error + checking. + +*******************************************************************************/ + +void memory_mprotect(void *addr, size_t len, int prot) +{ + if (os::mprotect(addr, len, prot) != 0) + vm_abort_errno("memory_mprotect: os::mprotect failed"); +} + + +/* memory_checked_alloc ******************************************************** + + Allocated zeroed-out memory and does an OOM check. + + ERROR HANDLING: + XXX If no memory could be allocated, this function justs *exists*. + +*******************************************************************************/ + +void *memory_checked_alloc(size_t size) +{ + /* always allocate memory zeroed out */ + + void *p = os::calloc(size, 1); + + if (p == NULL) + vm_abort("memory_checked_alloc: calloc failed: out of memory"); + + return p; +} + + +void *mem_alloc(int32_t size) +{ + void *m; + + if (size == 0) + return NULL; + +#if defined(ENABLE_STATISTICS) + if (opt_stat) { + memoryusage += size; + + if (memoryusage > maxmemusage) + maxmemusage = memoryusage; + } +#endif + + m = memory_checked_alloc(size); + +#if defined(ENABLE_MEMCHECK) + /* XXX we would like to poison the memory, but callers rely on */ + /* the zeroing. This should change sooner or later. */ + /* memset(m, MEMORY_CLEAR_BYTE, size); */ +#endif + + return m; +} + + +void *mem_realloc(void *src, int32_t len1, int32_t len2) +{ + void *dst; + + /* prevent compiler warnings */ + + dst = NULL; + + if (src == NULL) + if (len1 != 0) + vm_abort("mem_realloc: reallocating memoryblock with address NULL, length != 0"); + +#if defined(ENABLE_STATISTICS) + if (opt_stat) + memoryusage = (memoryusage - len1) + len2; +#endif + +#if defined(ENABLE_MEMCHECK) + if (len2 < len1) + os::memset((u1*)dst + len2, MEMORY_CLEAR_BYTE, len1 - len2); +#endif + + dst = realloc(src, len2); + + if (dst == NULL) + vm_abort("mem_realloc: realloc failed: out of memory"); + +#if defined(ENABLE_MEMCHECK) + if (len2 > len1) + os::memset((u1*)dst + len1, MEMORY_CLEAR_BYTE, len2 - len1); +#endif + + return dst; +} + + +void mem_free(void *m, int32_t size) +{ + if (!m) { + if (size == 0) + return; + + log_text("returned memoryblock with address NULL, length != 0"); + assert(0); + } + +#if defined(ENABLE_STATISTICS) + if (opt_stat) + memoryusage -= size; +#endif + +#if defined(ENABLE_MEMCHECK) + /* destroy the contents */ + os::memset(m, MEMORY_CLEAR_BYTE, size); +#endif + + os::free(m); +} + + +/* memory_thread *************************************************************** + + Prints regularly memory statistics. + +*******************************************************************************/ + +#if defined(ENABLE_THREADS) && !defined(NDEBUG) +static void memory_thread(void) +{ + int32_t seconds; + + /* Prevent compiler warning. */ + + seconds = 1; + + /* If both arguments are specified, use the value of + ProfileMemoryUsage. */ + + if (opt_ProfileGCMemoryUsage) + seconds = opt_ProfileGCMemoryUsage; + + if (opt_ProfileMemoryUsage) + seconds = opt_ProfileMemoryUsage; + + while (true) { + /* sleep thread */ + + threads_sleep(seconds * 1000, 0); + +# if defined(ENABLE_STATISTICS) + /* Print current date and time (only when we print to the + stdout). */ + + if (!opt_ProfileMemoryUsageGNUPlot) + statistics_print_date(); + + /* print memory usage */ + + if (opt_ProfileMemoryUsage) + statistics_print_memory_usage(); + + /* print GC memory usage */ + + if (opt_ProfileGCMemoryUsage) + statistics_print_gc_memory_usage(); +# endif + } +} +#endif + + +/* memory_start_thread ********************************************************* + + Starts the memory profiling thread. + +*******************************************************************************/ + +#if defined(ENABLE_THREADS) && !defined(NDEBUG) +bool memory_start_thread(void) +{ + utf *name; + + name = utf_new_char("Memory Profiler"); + + /* start the memory profiling thread */ + + if (!threads_thread_start_internal(name, memory_thread)) + return false; + + /* everything's ok */ + + return true; +} +#endif + + +/* + * 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: + * vim:noexpandtab:sw=4:ts=4: + */ diff --git a/src/mm/memory.h b/src/mm/memory.h deleted file mode 100644 index ec6393f19..000000000 --- a/src/mm/memory.h +++ /dev/null @@ -1,169 +0,0 @@ -/* src/mm/memory.h - macros for memory management - - Copyright (C) 1996-2005, 2006, 2007, 2008 - CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO - - 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. - -*/ - - -#ifndef _MEMORY_H -#define _MEMORY_H - -#include "config.h" - -#include - - -// Align the size of memory allocations to this size. -#define ALIGNSIZE 8 -#define MEMORY_ALIGN(pos,size) ((((pos) + (size) - 1) / (size)) * (size)) - - -// Constants for ENABLE_MEMCHECK. - -#if defined(ENABLE_MEMCHECK) -#define MEMORY_CANARY_SIZE 16 -#define MEMORY_CANARY_FIRST_BYTE 0xca -#define MEMORY_CLEAR_BYTE 0xa5 -#endif - - -// Includes. -#include "mm/codememory.h" -#include "mm/dumpmemory.hpp" -#include "mm/gc.hpp" - - -/* ----------------------------- Interface description ----------------------- - -There are two possible choices for allocating memory: - - 1. explicit allocating / deallocating - - mem_alloc ..... allocate a memory block - mem_free ...... free a memory block - mem_realloc ... change size of a memory block (position may change) - mem_usage ..... amount of allocated memory - -There are some useful macros: - - NEW (type) ....... allocate memory for an element of type `type` - FREE (ptr,type) .. free memory - - MNEW (type,num) .. allocate memory for an array - MFREE (ptr,type,num) .. free memory - - MREALLOC (ptr,type,num1,num2) .. enlarge the array to size num2 - -------------------------------------------------------------------------------- - -Some more macros: - - MEMORY_ALIGN (pos, size) ... make pos divisible by size. always returns an - address >= pos. - - - OFFSET (s,el) ....... returns the offset of 'el' in structure 's' in bytes. - - MCOPY (dest,src,type,num) ... copy 'num' elements of type 'type'. - - -*/ - -#define PADDING(pos,size) (MEMORY_ALIGN((pos),(size)) - (pos)) -#define OFFSET(s,el) ((int32_t) ((ptrint) &(((s*) 0)->el))) - - -#define NEW(type) ((type *) mem_alloc(sizeof(type))) -#define FREE(ptr,type) mem_free((ptr), sizeof(type)) - -#define MNEW(type,num) ((type *) mem_alloc(sizeof(type) * (num))) -#define MFREE(ptr,type,num) mem_free((ptr), sizeof(type) * (num)) - -#define MREALLOC(ptr,type,num1,num2) mem_realloc((ptr), sizeof(type) * (num1), \ - sizeof(type) * (num2)) - - -#define MCOPY(dest,src,type,num) memcpy((dest), (src), sizeof(type) * (num)) -#define MSET(ptr,byte,type,num) memset((ptr), (byte), sizeof(type) * (num)) -#define MZERO(ptr,type,num) MSET(ptr,0,type,num) -#define MMOVE(dest,src,type,num) memmove((dest), (src), sizeof(type) * (num)) - - -/* GC macros (boehm only) *****************************************************/ - -#if defined(ENABLE_GC_BOEHM) - -/* Uncollectable memory which can contain references */ - -#define GCNEW_UNCOLLECTABLE(type,num) ((type *) heap_alloc_uncollectable(sizeof(type) * (num))) - -#define GCNEW(type) heap_alloc(sizeof(type), true, NULL, true) -#define GCMNEW(type,num) heap_alloc(sizeof(type) * (num), true, NULL, true) - -#define GCFREE(ptr) heap_free((ptr)) - -#endif - - -/* function prototypes ********************************************************/ - -#ifdef __cplusplus -extern "C" { -#endif - -bool memory_init(void); - -void memory_mprotect(void *addr, size_t len, int prot); - -void *memory_checked_alloc(size_t size); - -void *memory_cnew(int32_t size); -void memory_cfree(void *p, int32_t size); - -void *mem_alloc(int32_t size); -void mem_free(void *m, int32_t size); -void *mem_realloc(void *src, int32_t len1, int32_t len2); - -#if defined(ENABLE_THREADS) -bool memory_start_thread(void); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* _MEMORY_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: - * vim:noexpandtab:sw=4:ts=4: - */ diff --git a/src/mm/memory.hpp b/src/mm/memory.hpp new file mode 100644 index 000000000..9045b4871 --- /dev/null +++ b/src/mm/memory.hpp @@ -0,0 +1,169 @@ +/* src/mm/memory.hpp - macros for memory management + + Copyright (C) 1996-2005, 2006, 2007, 2008 + CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO + + 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. + +*/ + + +#ifndef _MEMORY_H +#define _MEMORY_H + +#include "config.h" + +#include + + +// Align the size of memory allocations to this size. +#define ALIGNSIZE 8 +#define MEMORY_ALIGN(pos,size) ((((pos) + (size) - 1) / (size)) * (size)) + + +// Constants for ENABLE_MEMCHECK. + +#if defined(ENABLE_MEMCHECK) +#define MEMORY_CANARY_SIZE 16 +#define MEMORY_CANARY_FIRST_BYTE 0xca +#define MEMORY_CLEAR_BYTE 0xa5 +#endif + + +// Includes. +#include "mm/codememory.h" +#include "mm/dumpmemory.hpp" +#include "mm/gc.hpp" + + +/* +---------------------------- Interface description ----------------------- + +There are two possible choices for allocating memory: + + 1. explicit allocating / deallocating + + mem_alloc ..... allocate a memory block + mem_free ...... free a memory block + mem_realloc ... change size of a memory block (position may change) + mem_usage ..... amount of allocated memory + +There are some useful macros: + + NEW (type) ....... allocate memory for an element of type `type` + FREE (ptr,type) .. free memory + + MNEW (type,num) .. allocate memory for an array + MFREE (ptr,type,num) .. free memory + + MREALLOC (ptr,type,num1,num2) .. enlarge the array to size num2 + +------------------------------------------------------------------------------- + +Some more macros: + + MEMORY_ALIGN (pos, size) ... make pos divisible by size. always returns an + address >= pos. + + + OFFSET (s,el) ....... returns the offset of 'el' in structure 's' in bytes. + + MCOPY (dest,src,type,num) ... copy 'num' elements of type 'type'. + + +*/ + +#define PADDING(pos,size) (MEMORY_ALIGN((pos),(size)) - (pos)) +#define OFFSET(s,el) ((int32_t) ((ptrint) &(((s*) 0)->el))) + + +#define NEW(type) ((type *) mem_alloc(sizeof(type))) +#define FREE(ptr,type) mem_free((ptr), sizeof(type)) + +#define MNEW(type,num) ((type *) mem_alloc(sizeof(type) * (num))) +#define MFREE(ptr,type,num) mem_free((ptr), sizeof(type) * (num)) + +#define MREALLOC(ptr,type,num1,num2) mem_realloc((ptr), sizeof(type) * (num1), \ + sizeof(type) * (num2)) + + +#define MCOPY(dest,src,type,num) memcpy((dest), (src), sizeof(type) * (num)) +#define MSET(ptr,byte,type,num) memset((ptr), (byte), sizeof(type) * (num)) +#define MZERO(ptr,type,num) MSET(ptr,0,type,num) +#define MMOVE(dest,src,type,num) memmove((dest), (src), sizeof(type) * (num)) + + +/* GC macros (boehm only) *****************************************************/ + +#if defined(ENABLE_GC_BOEHM) + +/* Uncollectable memory which can contain references */ + +#define GCNEW_UNCOLLECTABLE(type,num) ((type *) heap_alloc_uncollectable(sizeof(type) * (num))) + +#define GCNEW(type) heap_alloc(sizeof(type), true, NULL, true) +#define GCMNEW(type,num) heap_alloc(sizeof(type) * (num), true, NULL, true) + +#define GCFREE(ptr) heap_free((ptr)) + +#endif + + +/* function prototypes ********************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +bool memory_init(void); + +void memory_mprotect(void *addr, size_t len, int prot); + +void *memory_checked_alloc(size_t size); + +void *memory_cnew(int32_t size); +void memory_cfree(void *p, int32_t size); + +void *mem_alloc(int32_t size); +void mem_free(void *m, int32_t size); +void *mem_realloc(void *src, int32_t len1, int32_t len2); + +#if defined(ENABLE_THREADS) +bool memory_start_thread(void); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _MEMORY_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: + * vim:noexpandtab:sw=4:ts=4: + */ diff --git a/src/mm/tlh.c b/src/mm/tlh.c index e46cf8760..6fcaf5a7a 100644 --- a/src/mm/tlh.c +++ b/src/mm/tlh.c @@ -23,7 +23,7 @@ #include "config.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "mm/tlh.h" #include "vm/global.h" diff --git a/src/native/jni.cpp b/src/native/jni.cpp index 674f3b8b0..1f3bb40d2 100644 --- a/src/native/jni.cpp +++ b/src/native/jni.cpp @@ -32,7 +32,7 @@ #include "vm/types.h" #include "mm/gc.hpp" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/jni.hpp" #include "native/llni.h" @@ -47,7 +47,7 @@ #include "threads/mutex.hpp" #include "threads/thread.hpp" -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" #include "vm/array.hpp" #include "vm/jit/builtin.hpp" diff --git a/src/native/jvmti/cacaodbg.c b/src/native/jvmti/cacaodbg.c index eb29c6f7b..85c4f8774 100644 --- a/src/native/jvmti/cacaodbg.c +++ b/src/native/jvmti/cacaodbg.c @@ -32,7 +32,7 @@ #include "vm/jit/builtin.hpp" #include "vm/jit/asmpart.h" #include "vm/string.hpp" -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" #include "threads/mutex.h" #include "threads/thread.hpp" diff --git a/src/native/jvmti/jvmti.c b/src/native/jvmti/jvmti.c index e152104dc..461869ecc 100644 --- a/src/native/jvmti/jvmti.c +++ b/src/native/jvmti/jvmti.c @@ -48,10 +48,10 @@ #include "vm/class.hpp" #include "vm/classcache.hpp" #include "mm/gc.hpp" -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" #include "vm/options.h" #include "vm/string.hpp" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "threads/mutex.h" #include "threads/thread.hpp" #include "threads/lock.hpp" diff --git a/src/native/localref.cpp b/src/native/localref.cpp index d236afb51..bec9bfe02 100644 --- a/src/native/localref.cpp +++ b/src/native/localref.cpp @@ -28,13 +28,13 @@ #include #include -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/localref.hpp" #include "threads/thread.hpp" -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" #include "vm/options.h" #include "vm/vm.hpp" diff --git a/src/native/native.cpp b/src/native/native.cpp index 7f0f078ba..0c12b69d1 100644 --- a/src/native/native.cpp +++ b/src/native/native.cpp @@ -34,14 +34,14 @@ #include #include -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/jni.hpp" #include "native/native.hpp" #include "threads/mutex.hpp" -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" #include "vm/jit/builtin.hpp" #include "vm/exceptions.hpp" diff --git a/src/native/vm/cldc1.1/com_sun_cldc_io_ResourceInputStream.cpp b/src/native/vm/cldc1.1/com_sun_cldc_io_ResourceInputStream.cpp index 2ece32fc4..ba78eaadd 100644 --- a/src/native/vm/cldc1.1/com_sun_cldc_io_ResourceInputStream.cpp +++ b/src/native/vm/cldc1.1/com_sun_cldc_io_ResourceInputStream.cpp @@ -31,7 +31,7 @@ #include #include -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/jni.hpp" #include "native/llni.h" diff --git a/src/native/vm/cldc1.1/com_sun_cldc_io_j2me_socket_Protocol.cpp b/src/native/vm/cldc1.1/com_sun_cldc_io_j2me_socket_Protocol.cpp index 9ad7f7c20..16bebd345 100644 --- a/src/native/vm/cldc1.1/com_sun_cldc_io_j2me_socket_Protocol.cpp +++ b/src/native/vm/cldc1.1/com_sun_cldc_io_j2me_socket_Protocol.cpp @@ -34,7 +34,7 @@ #include "vm/types.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/jni.hpp" #include "native/llni.h" diff --git a/src/native/vm/cldc1.1/java_lang_Float.cpp b/src/native/vm/cldc1.1/java_lang_Float.cpp index 9d521e2a1..d4c200150 100644 --- a/src/native/vm/cldc1.1/java_lang_Float.cpp +++ b/src/native/vm/cldc1.1/java_lang_Float.cpp @@ -63,6 +63,18 @@ JNIEXPORT jint JNICALL Java_java_lang_Float_floatToIntBits(JNIEnv *env, jclass c return val.i; } +/* + * Class: java/lang/Float + * Method: intBitsToFloat + * Signature: (I)F + */ +JNIEXPORT jfloat JNICALL Java_java_lang_Float_intBitsToFloat(JNIEnv *env, jclass clazz, jint value) +{ + imm_union val; + val.i = value; + return val.f; +} + } // extern "C" @@ -70,6 +82,7 @@ JNIEXPORT jint JNICALL Java_java_lang_Float_floatToIntBits(JNIEnv *env, jclass c static JNINativeMethod methods[] = { { (char*) "floatToIntBits", (char*) "(F)I", (void*) (uintptr_t) &Java_java_lang_Float_floatToIntBits }, + { (char*) "intBitsToFloat", (char*) "(I)F", (void*) (uintptr_t) &Java_java_lang_Float_intBitsToFloat } }; diff --git a/src/native/vm/cldc1.1/java_lang_System.cpp b/src/native/vm/cldc1.1/java_lang_System.cpp index ccc1c0ecc..7403c9622 100644 --- a/src/native/vm/cldc1.1/java_lang_System.cpp +++ b/src/native/vm/cldc1.1/java_lang_System.cpp @@ -28,7 +28,7 @@ #include #include -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/jni.hpp" #include "native/native.hpp" @@ -38,6 +38,7 @@ #endif #include "vm/jit/builtin.hpp" +#include "vm/javaobjects.hpp" #include "vm/properties.hpp" #include "vm/string.hpp" #include "vm/vm.hpp" @@ -93,6 +94,18 @@ JNIEXPORT jstring JNICALL Java_java_lang_System_getProperty0(JNIEnv *env, jclass return (jstring) result; } +/* + * Class: java/lang/System + * Method: identityHashCode + * Signature: (Ljava/lang/Object;)I + */ +JNIEXPORT jint JNICALL Java_java_lang_System_identityHashCode(JNIEnv *env, jclass clazz, jobject obj) +{ + java_lang_Object o(obj); + + return o.get_hashcode(); +} + } // extern "C" @@ -101,6 +114,7 @@ JNIEXPORT jstring JNICALL Java_java_lang_System_getProperty0(JNIEnv *env, jclass static JNINativeMethod methods[] = { { (char*) "arraycopy", (char*) "(Ljava/lang/Object;ILjava/lang/Object;II)V", (void*) (uintptr_t) &Java_java_lang_System_arraycopy }, { (char*) "getProperty0", (char*) "(Ljava/lang/String;)Ljava/lang/String;", (void*) (uintptr_t) &Java_java_lang_System_getProperty0 }, + { (char*) "identityHashCode", (char*) "(Ljava/lang/Object;)I", (void*) (uintptr_t) &Java_java_lang_System_identityHashCode } }; diff --git a/src/native/vm/cldc1.1/java_lang_Thread.cpp b/src/native/vm/cldc1.1/java_lang_Thread.cpp index 99a7393a0..0f68bd5e0 100644 --- a/src/native/vm/cldc1.1/java_lang_Thread.cpp +++ b/src/native/vm/cldc1.1/java_lang_Thread.cpp @@ -35,8 +35,9 @@ #endif #include "threads/thread.hpp" +#include "threads/threadlist.hpp" -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" #include "vm/jit/builtin.hpp" #include "vm/javaobjects.hpp" @@ -128,7 +129,6 @@ JNIEXPORT jboolean JNICALL Java_java_lang_Thread_isAlive(JNIEnv *env, jobject _t } -#if 0 /* * Class: java/lang/Thread * Method: activeCount @@ -136,6 +136,11 @@ JNIEXPORT jboolean JNICALL Java_java_lang_Thread_isAlive(JNIEnv *env, jobject _t */ JNIEXPORT s4 JNICALL Java_java_lang_Thread_activeCount(JNIEnv *env, jclass clazz) { +#if defined(ENABLE_THREADS) + return ThreadList::get_number_of_non_daemon_threads(); +#else + return 1; +#endif } @@ -146,9 +151,14 @@ JNIEXPORT s4 JNICALL Java_java_lang_Thread_activeCount(JNIEnv *env, jclass clazz */ JNIEXPORT void JNICALL Java_java_lang_Thread_interrupt0(JNIEnv *env, jobject _this) { +#if defined(ENABLE_THREADS) + java_lang_Thread jlt(_this); + threadobject* t = jlt.get_vm_thread(); + threads_thread_interrupt(t); +#endif } - +#if 0 /* * Class: java/lang/Thread * Method: internalExit @@ -183,10 +193,10 @@ static JNINativeMethod methods[] = { { (char*) "sleep", (char*) "(J)V", (void*) (uintptr_t) &Java_java_lang_Thread_sleep }, { (char*) "start0", (char*) "()V", (void*) (uintptr_t) &Java_java_lang_Thread_start0 }, { (char*) "isAlive", (char*) "()Z", (void*) (uintptr_t) &Java_java_lang_Thread_isAlive }, -#if 0 { (char*) "activeCount", (char*) "()I", (void*) (uintptr_t) &Java_java_lang_Thread_activeCount }, { (char*) "setPriority0", (char*) "(II)V", (void*) (uintptr_t) &Java_java_lang_Thread_setPriority0 }, { (char*) "interrupt0", (char*) "()V", (void*) (uintptr_t) &Java_java_lang_Thread_interrupt0 }, +#if 0 { (char*) "internalExit", (char*) "()V", (void*) (uintptr_t) &Java_java_lang_Thread_internalExit }, #endif { (char*) "yield", (char*) "()V", (void*) (uintptr_t) &Java_java_lang_Thread_yield }, diff --git a/src/native/vm/gnuclasspath/gnu_classpath_VMSystemProperties.cpp b/src/native/vm/gnuclasspath/gnu_classpath_VMSystemProperties.cpp index 0789c0eda..dc4e5ebb0 100644 --- a/src/native/vm/gnuclasspath/gnu_classpath_VMSystemProperties.cpp +++ b/src/native/vm/gnuclasspath/gnu_classpath_VMSystemProperties.cpp @@ -30,7 +30,7 @@ #include "vm/types.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/jni.hpp" #include "native/native.hpp" diff --git a/src/native/vm/gnuclasspath/gnu_classpath_jdwp_VMFrame.c b/src/native/vm/gnuclasspath/gnu_classpath_jdwp_VMFrame.c index 9276ebb8f..4897589cb 100644 --- a/src/native/vm/gnuclasspath/gnu_classpath_jdwp_VMFrame.c +++ b/src/native/vm/gnuclasspath/gnu_classpath_jdwp_VMFrame.c @@ -32,7 +32,7 @@ #include "native/include/java_lang_Object.h" #include "native/include/gnu_classpath_jdwp_VMFrame.h" -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" /* diff --git a/src/native/vm/gnuclasspath/gnu_classpath_jdwp_VMVirtualMachine.c b/src/native/vm/gnuclasspath/gnu_classpath_jdwp_VMVirtualMachine.c index eaf47e630..63e253b7c 100644 --- a/src/native/vm/gnuclasspath/gnu_classpath_jdwp_VMVirtualMachine.c +++ b/src/native/vm/gnuclasspath/gnu_classpath_jdwp_VMVirtualMachine.c @@ -28,7 +28,7 @@ #include #include -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" #include "native/jni.hpp" #include "native/include/java_lang_Thread.h" #include "native/include/java_nio_ByteBuffer.h" diff --git a/src/native/vm/gnuclasspath/gnu_java_lang_management_VMClassLoadingMXBeanImpl.cpp b/src/native/vm/gnuclasspath/gnu_java_lang_management_VMClassLoadingMXBeanImpl.cpp index c706681c9..c00c3e9a4 100644 --- a/src/native/vm/gnuclasspath/gnu_java_lang_management_VMClassLoadingMXBeanImpl.cpp +++ b/src/native/vm/gnuclasspath/gnu_java_lang_management_VMClassLoadingMXBeanImpl.cpp @@ -36,7 +36,7 @@ # include "native/vm/include/gnu_java_lang_management_VMClassLoadingMXBeanImpl.h" #endif -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" #include "vm/classcache.hpp" #include "vm/utf8.h" diff --git a/src/native/vm/gnuclasspath/gnu_java_lang_management_VMThreadMXBeanImpl.cpp b/src/native/vm/gnuclasspath/gnu_java_lang_management_VMThreadMXBeanImpl.cpp index f04140ff3..359931c25 100644 --- a/src/native/vm/gnuclasspath/gnu_java_lang_management_VMThreadMXBeanImpl.cpp +++ b/src/native/vm/gnuclasspath/gnu_java_lang_management_VMThreadMXBeanImpl.cpp @@ -36,7 +36,7 @@ # include "native/vm/include/gnu_java_lang_management_VMThreadMXBeanImpl.h" #endif -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" #include "vm/classcache.hpp" #include "vm/utf8.h" diff --git a/src/native/vm/gnuclasspath/java_lang_VMClass.cpp b/src/native/vm/gnuclasspath/java_lang_VMClass.cpp index 5141c335d..d0d9e44df 100644 --- a/src/native/vm/gnuclasspath/java_lang_VMClass.cpp +++ b/src/native/vm/gnuclasspath/java_lang_VMClass.cpp @@ -43,7 +43,7 @@ #include "vm/string.hpp" #if defined(ENABLE_ANNOTATIONS) -#include "vm/annotation.h" +#include "vm/annotation.hpp" #include "vm/vm.hpp" #endif diff --git a/src/native/vm/gnuclasspath/java_lang_VMClassLoader.cpp b/src/native/vm/gnuclasspath/java_lang_VMClassLoader.cpp index 7e2c0b835..ebeeb1628 100644 --- a/src/native/vm/gnuclasspath/java_lang_VMClassLoader.cpp +++ b/src/native/vm/gnuclasspath/java_lang_VMClassLoader.cpp @@ -29,7 +29,7 @@ #include #include -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/jni.hpp" #include "native/llni.h" @@ -39,7 +39,7 @@ # include "native/vm/include/java_lang_VMClassLoader.h" #endif -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" #include "toolbox/list.hpp" #if defined(ENABLE_ASSERTION) diff --git a/src/native/vm/gnuclasspath/java_lang_VMRuntime.cpp b/src/native/vm/gnuclasspath/java_lang_VMRuntime.cpp index 93b8833f1..2a8856678 100644 --- a/src/native/vm/gnuclasspath/java_lang_VMRuntime.cpp +++ b/src/native/vm/gnuclasspath/java_lang_VMRuntime.cpp @@ -39,7 +39,7 @@ # include #endif -#include "mm/memory.h" +#include "mm/memory.hpp" #include "mm/gc.hpp" #include "native/jni.hpp" diff --git a/src/native/vm/gnuclasspath/java_lang_VMThread.cpp b/src/native/vm/gnuclasspath/java_lang_VMThread.cpp index da3eccb25..da561ab5a 100644 --- a/src/native/vm/gnuclasspath/java_lang_VMThread.cpp +++ b/src/native/vm/gnuclasspath/java_lang_VMThread.cpp @@ -25,6 +25,7 @@ #include "config.h" +#include #include #include "native/jni.hpp" @@ -56,7 +57,7 @@ JNIEXPORT jint JNICALL Java_java_lang_VMThread_countStackFrames(JNIEnv *env, job { log_println("Java_java_lang_VMThread_countStackFrames: Deprecated. Not implemented."); - return 0; + return 0; } @@ -88,6 +89,7 @@ JNIEXPORT void JNICALL Java_java_lang_VMThread_interrupt(JNIEnv *env, jobject _t h = (java_handle_t *) _this; t = thread_get_thread(h); + assert(t != NULL); threads_thread_interrupt(t); #endif @@ -107,6 +109,7 @@ JNIEXPORT jboolean JNICALL Java_java_lang_VMThread_isInterrupted(JNIEnv *env, jo h = (java_handle_t *) _this; t = thread_get_thread(h); + assert(t != NULL); return thread_is_interrupted(t); #else @@ -154,6 +157,7 @@ JNIEXPORT void JNICALL Java_java_lang_VMThread_nativeSetPriority(JNIEnv *env, jo h = (java_handle_t *) _this; t = thread_get_thread(h); + assert(t != NULL); threads_set_thread_priority(t->tid, priority); #endif @@ -279,6 +283,7 @@ JNIEXPORT jstring JNICALL Java_java_lang_VMThread_getState(JNIEnv *env, jobject h = (java_handle_t *) _this; t = thread_get_thread(h); + assert(t != NULL); state = cacaothread_get_state(t); @@ -298,6 +303,12 @@ JNIEXPORT jstring JNICALL Java_java_lang_VMThread_getState(JNIEnv *env, jobject case THREAD_STATE_TIMED_WAITING: u = utf_new_char("TIMED_WAITING"); break; + case THREAD_STATE_PARKED: + u = utf_new_char("PARKED"); + break; + case THREAD_STATE_TIMED_PARKED: + u = utf_new_char("TIMED_PARKED"); + break; case THREAD_STATE_TERMINATED: u = utf_new_char("TERMINATED"); break; diff --git a/src/native/vm/gnuclasspath/java_lang_VMThrowable.cpp b/src/native/vm/gnuclasspath/java_lang_VMThrowable.cpp index d62fe2926..fca7f8d1d 100644 --- a/src/native/vm/gnuclasspath/java_lang_VMThrowable.cpp +++ b/src/native/vm/gnuclasspath/java_lang_VMThrowable.cpp @@ -101,66 +101,7 @@ JNIEXPORT jobjectArray JNICALL Java_java_lang_VMThrowable_getStackTrace(JNIEnv * assert(st != NULL); - stacktrace_entry_t* ste = st->entries; - - /* Create the stacktrace element array. */ - - java_handle_objectarray_t* oa = builtin_anewarray(st->length, class_java_lang_StackTraceElement); - - if (oa == NULL) - return NULL; - - for (int i = 0; i < st->length; i++, ste++) { - /* Get the codeinfo and methodinfo. */ - - codeinfo* code = ste->code; - methodinfo* m = code->m; - - /* Get filename. */ - - java_handle_t* filename; - - if (!(m->flags & ACC_NATIVE)) { - if (m->clazz->sourcefile) - filename = javastring_new(m->clazz->sourcefile); - else - filename = NULL; - } - else - filename = NULL; - - /* get line number */ - - int32_t linenumber; - - if (m->flags & ACC_NATIVE) { - linenumber = -1; - } - else { - /* FIXME linenumbertable->find could change the methodinfo - pointer when hitting an inlined method. */ - - linenumber = code->linenumbertable->find(&m, ste->pc); - linenumber = (linenumber == 0) ? -1 : linenumber; - } - - /* get declaring class name */ - - java_handle_t* declaringclass = class_get_classname(m->clazz); - - /* allocate a new stacktrace element */ - - java_handle_t* h = builtin_new(class_java_lang_StackTraceElement); - - if (h == NULL) - return NULL; - - java_lang_StackTraceElement ste(h, filename, linenumber, declaringclass, javastring_new(m->name), ((m->flags & ACC_NATIVE) ? 1 : 0)); - - array_objectarray_element_set(oa, i, ste.get_handle()); - } - - return (jobjectArray) oa; + return stacktrace_get_StackTraceElements(st); } } // extern "C" diff --git a/src/native/vm/gnuclasspath/java_lang_management_VMManagementFactory.cpp b/src/native/vm/gnuclasspath/java_lang_management_VMManagementFactory.cpp index 10f450dd1..234007759 100644 --- a/src/native/vm/gnuclasspath/java_lang_management_VMManagementFactory.cpp +++ b/src/native/vm/gnuclasspath/java_lang_management_VMManagementFactory.cpp @@ -36,7 +36,7 @@ # include "native/vm/include/java_lang_management_VMManagementFactory.h" #endif -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" #include "vm/globals.hpp" #include "vm/vm.hpp" diff --git a/src/native/vm/gnuclasspath/sun_reflect_ConstantPool.cpp b/src/native/vm/gnuclasspath/sun_reflect_ConstantPool.cpp index b56ca42c3..b811d6068 100644 --- a/src/native/vm/gnuclasspath/sun_reflect_ConstantPool.cpp +++ b/src/native/vm/gnuclasspath/sun_reflect_ConstantPool.cpp @@ -40,7 +40,7 @@ #include #include -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/jni.hpp" #include "native/llni.h" @@ -51,7 +51,7 @@ #include "native/vm/reflection.hpp" -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" #include "vm/class.hpp" #include "vm/exceptions.hpp" diff --git a/src/native/vm/nativevm.cpp b/src/native/vm/nativevm.cpp index a61f61920..675bacb85 100644 --- a/src/native/vm/nativevm.cpp +++ b/src/native/vm/nativevm.cpp @@ -36,7 +36,7 @@ #include "vm/os.hpp" #if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) -# include "mm/memory.h" +# include "mm/memory.hpp" # include "native/native.hpp" diff --git a/src/native/vm/openjdk/hpi.cpp b/src/native/vm/openjdk/hpi.cpp index ad6eec544..7c7527897 100644 --- a/src/native/vm/openjdk/hpi.cpp +++ b/src/native/vm/openjdk/hpi.cpp @@ -28,7 +28,7 @@ // Include this one early. #include "native/vm/openjdk/hpi.hpp" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/native.hpp" diff --git a/src/native/vm/openjdk/jvm.cpp b/src/native/vm/openjdk/jvm.cpp index 7a63880ba..cc4312631 100644 --- a/src/native/vm/openjdk/jvm.cpp +++ b/src/native/vm/openjdk/jvm.cpp @@ -50,7 +50,9 @@ #include INCLUDE_JVM_MD_H #include INCLUDE_JVM_H -#include "mm/memory.h" +#include "fdlibm/fdlibm.h" + +#include "mm/memory.hpp" #include "native/llni.h" #include "native/native.hpp" @@ -62,8 +64,9 @@ #include "threads/lock.hpp" #include "threads/thread.hpp" +#include "threads/threadlist.hpp" -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" #include "toolbox/list.hpp" #include "vm/array.hpp" @@ -85,7 +88,7 @@ #include "vm/primitive.hpp" #include "vm/properties.hpp" #include "vm/resolve.hpp" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/string.hpp" #include "vm/vm.hpp" @@ -435,64 +438,11 @@ jobject JVM_GetStackTraceElement(JNIEnv *env, jobject throwable, jint index) java_lang_Throwable jlt(throwable); java_handle_bytearray_t* ba = jlt.get_backtrace(); - // We need a critical section here as the stacktrace structure is + // XXX We need a critical section here as the stacktrace structure is // mapped onto a Java byte-array. - LLNI_CRITICAL_START; - stacktrace_t* st = (stacktrace_t *) LLNI_array_data(ba); - if ((index < 0) || (index >= st->length)) { - /* XXX This should be an IndexOutOfBoundsException (check this - again). */ - exceptions_throw_arrayindexoutofboundsexception(); - return NULL; - } - - // Get the stacktrace entry. - stacktrace_entry_t* ste = &(st->entries[index]); - - // Get the codeinfo, methodinfo and classinfo. - codeinfo* code = ste->code; - methodinfo* m = code->m; - classinfo* c = m->clazz; - - // Get filename. - java_handle_t* filename; - - if (!(m->flags & ACC_NATIVE)) { - if (c->sourcefile != NULL) - filename = javastring_new(c->sourcefile); - else - filename = NULL; - } - else - filename = NULL; - - // Get line number. - int32_t linenumber; - - if (m->flags & ACC_NATIVE) { - linenumber = -2; - } - else { - // FIXME linenumbertable->find could change the methodinfo - // pointer when hitting an inlined method. - linenumber = code->linenumbertable->find(&m, ste->pc); - linenumber = (linenumber == 0) ? -1 : linenumber; - } - - LLNI_CRITICAL_END; - - // Get declaring class name. - java_handle_t* declaringclass = class_get_classname(c); - - // Allocate a new StackTraceElement object. - java_lang_StackTraceElement jlste(declaringclass, javastring_new(m->name), filename, linenumber); - - if (jlste.is_null()) - return NULL; - - return (jobject) jlste.get_handle(); + return stacktrace_get_StackTraceElement(st, index); } @@ -2183,8 +2133,7 @@ jboolean JVM_IsThreadAlive(JNIEnv* env, jobject jthread) h = (java_handle_t *) jthread; t = thread_get_thread(h); - /* The threadobject is null when a thread is created in Java. The - priority is set later during startup. */ + /* The threadobject is null when a thread is created in Java. */ if (t == NULL) return 0; @@ -2289,6 +2238,8 @@ void JVM_Interrupt(JNIEnv* env, jobject jthread) h = (java_handle_t *) jthread; t = thread_get_thread(h); + /* The threadobject is null when a thread is created in Java. */ + if (t == NULL) return; @@ -2309,6 +2260,11 @@ jboolean JVM_IsInterrupted(JNIEnv* env, jobject jthread, jboolean clear_interrup h = (java_handle_t *) jthread; t = thread_get_thread(h); + /* The threadobject is null when a thread is created in Java. */ + + if (t == NULL) + return JNI_FALSE; + interrupted = thread_is_interrupted(t); if (interrupted && clear_interrupted) @@ -2648,14 +2604,26 @@ jobject JVM_NewMultiArray(JNIEnv *env, jclass eltClass, jintArray dim) /* Create an array-class if necessary. */ - if (class_is_primitive(c)) + if (class_is_primitive(c)) { ac = Primitive::get_arrayclass_by_name(c->name); + + // Arrays of void are not allowed. + if (ac == NULL) { + exceptions_throw_illegalargumentexception(); + return NULL; + } + + if (length > 1) + ac = class_multiarray_of((length - 1), ac, true); + } else - ac = class_array_of(c, true); + ac = class_multiarray_of(length, c, true); if (ac == NULL) return NULL; + /* Allocate a new array on the heap. */ + a = builtin_multianewarray(length, (java_handle_t *) ac, dims); return (jobject) a; @@ -2717,9 +2685,13 @@ jint JVM_Recv(jint fd, char *buf, jint nBytes, jint flags) jint JVM_Send(jint fd, char *buf, jint nBytes, jint flags) { - log_println("JVM_Send: IMPLEMENT ME!"); + TRACEJVMCALLSENTER(("JVM_Send(fd=%d, buf=%p, nBytes=%d, flags=%d", fd, buf, nBytes, flags)); - return 0; + int result = os::send(fd, buf, nBytes, flags); + + TRACEJVMCALLSEXIT(("->%d", result)); + + return result; } @@ -2942,11 +2914,17 @@ void *JVM_FindLibraryEntry(void* handle, const char* name) /* JVM_IsNaN */ -jboolean JVM_IsNaN(jdouble a) +jboolean JVM_IsNaN(jdouble d) { - log_println("JVM_IsNaN: IMPLEMENT ME!"); + bool result; - return 0; + TRACEJVMCALLSENTER(("JVM_IsNaN(d=%f)", d)); + + result = isnan(d); + + TRACEJVMCALLSEXIT(("->%d", result)); + + return result; } @@ -3221,9 +3199,31 @@ jboolean JVM_CX8Field(JNIEnv *env, jobject obj, jfieldID fid, jlong oldVal, jlon jobjectArray JVM_GetAllThreads(JNIEnv *env, jclass dummy) { - log_println("JVM_GetAllThreads: IMPLEMENT ME!"); + // Get a list of all active threads. + list active_threads; + ThreadList::get_active_threads(active_threads); - return NULL; + // Allocate array to hold the java.lang.Thread objects. + int32_t length = active_threads.size(); + java_handle_objectarray_t* oa = builtin_anewarray(length, class_java_lang_Thread); + + if (oa == NULL) + return NULL; + + // Iterate over all threads (which were active just a second ago). + int32_t index = 0; + for (List::iterator it = active_threads.begin(); it != active_threads.end(); it++) { + threadobject* t = *it; + + java_handle_t* h = thread_get_object(t); + assert(h != NULL); + + array_objectarray_element_set(oa, index, h); + + index++; + } + + return oa; } @@ -3231,9 +3231,55 @@ jobjectArray JVM_GetAllThreads(JNIEnv *env, jclass dummy) jobjectArray JVM_DumpThreads(JNIEnv *env, jclass threadClass, jobjectArray threads) { - log_println("JVM_DumpThreads: IMPLEMENT ME!"); + int32_t i; - return NULL; + TRACEJVMCALLS(("JVM_DumpThreads((env=%p, threadClass=%p, threads=%p)", env, threadClass, threads)); + + if (threads == NULL) { + exceptions_throw_nullpointerexception(); + return NULL; + } + + // Get length of the threads array. + int32_t length = array_length_get((java_handle_t*) threads); + + if (length <= 0) { + exceptions_throw_illegalargumentexception(); + return NULL; + } + + // Allocate array to hold stacktraces. + classinfo* arrayclass = class_array_of(class_java_lang_StackTraceElement, true); + java_handle_objectarray_t* oas = builtin_anewarray(length, arrayclass); + + if (oas == NULL) { + return NULL; + } + + // Iterate over all passed thread objects. + for (i = 0; i < length; i++) { + java_handle_t* thread = array_objectarray_element_get(threads, i); + + // Get thread for the given thread object. + threadobject* t = thread_get_thread(thread); + + // The threadobject is null when a thread is created in Java. + if (t == NULL) + continue; + + // Get stacktrace for given thread. + stacktrace_t* st = stacktrace_get_of_thread(t); + + // Convert stacktrace into array of StackTraceElements. + java_handle_objectarray_t* oa = stacktrace_get_StackTraceElements(st); + + if (oa == NULL) + return NULL; + + array_objectarray_element_set(oas, i, (java_handle_t*) oa); + } + + return oas; } @@ -3341,12 +3387,11 @@ jintArray JVM_GetThreadStateValues(JNIEnv* env, jint javaThreadState) return NULL; array_intarray_element_set(ia, 0, THREAD_STATE_WAITING); - /* XXX Implement parked stuff. */ -/* array_intarray_element_set(ia, 1, PARKED); */ + array_intarray_element_set(ia, 1, THREAD_STATE_PARKED); break; case THREAD_STATE_TIMED_WAITING: - ia = builtin_newarray_int(3); + ia = builtin_newarray_int(2); if (ia == NULL) return NULL; @@ -3354,8 +3399,7 @@ jintArray JVM_GetThreadStateValues(JNIEnv* env, jint javaThreadState) /* XXX Not sure about that one. */ /* array_intarray_element_set(ia, 0, SLEEPING); */ array_intarray_element_set(ia, 0, THREAD_STATE_TIMED_WAITING); - /* XXX Implement parked stuff. */ -/* array_intarray_element_set(ia, 2, PARKED); */ + array_intarray_element_set(ia, 1, THREAD_STATE_TIMED_PARKED); break; case THREAD_STATE_TERMINATED: @@ -3453,31 +3497,40 @@ jobjectArray JVM_GetThreadStateNames(JNIEnv* env, jint javaThreadState, jintArra return NULL; s = javastring_new(utf_new_char("WAITING.OBJECT_WAIT")); -/* s = javastring_new(utf_new_char("WAITING.PARKED")); */ if (s == NULL) return NULL; array_objectarray_element_set(oa, 0, s); -/* array_objectarray_element_set(oa, 1, s); */ + + s = javastring_new(utf_new_char("WAITING.PARKED")); + + if (s == NULL) + return NULL; + + array_objectarray_element_set(oa, 1, s); break; case THREAD_STATE_TIMED_WAITING: - oa = builtin_anewarray(3, class_java_lang_String); + oa = builtin_anewarray(2, class_java_lang_String); if (oa == NULL) return NULL; /* s = javastring_new(utf_new_char("TIMED_WAITING.SLEEPING")); */ s = javastring_new(utf_new_char("TIMED_WAITING.OBJECT_WAIT")); -/* s = javastring_new(utf_new_char("TIMED_WAITING.PARKED")); */ if (s == NULL) return NULL; -/* array_objectarray_element_set(oa, 0, s); */ array_objectarray_element_set(oa, 0, s); -/* array_objectarray_element_set(oa, 2, s); */ + + s = javastring_new(utf_new_char("TIMED_WAITING.PARKED")); + + if (s == NULL) + return NULL; + + array_objectarray_element_set(oa, 1, s); break; case THREAD_STATE_TERMINATED: diff --git a/src/native/vm/openjdk/management.cpp b/src/native/vm/openjdk/management.cpp index 388489399..5bfb6c63b 100644 --- a/src/native/vm/openjdk/management.cpp +++ b/src/native/vm/openjdk/management.cpp @@ -34,7 +34,7 @@ #include "native/vm/openjdk/management.hpp" -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" #include "vm/os.hpp" #include "vm/vm.hpp" diff --git a/src/native/vm/sun_misc_Unsafe.cpp b/src/native/vm/sun_misc_Unsafe.cpp index 950df1352..a6c86a6da 100644 --- a/src/native/vm/sun_misc_Unsafe.cpp +++ b/src/native/vm/sun_misc_Unsafe.cpp @@ -30,7 +30,7 @@ #include "threads/atomic.hpp" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/jni.hpp" #include "native/llni.h" @@ -461,6 +461,39 @@ JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putFloat__JF(JNIEnv *env, jobject _t } +/* + * Class: sun/misc/Unsafe + * Method: getDouble + * Signature: (J)D + */ +JNIEXPORT jdouble JNICALL Java_sun_misc_Unsafe_getDouble__J(JNIEnv *env, jobject _this, jlong address) +{ + double *p; + double value; + + p = (double*) (intptr_t) address; + + value = *p; + + return value; +} + + +/* + * Class: sun/misc/Unsafe + * Method: putDouble + * Signature: (JD)V + */ +JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putDouble__JD(JNIEnv *env, jobject _this, jlong address, jdouble value) +{ + double* p; + + p = (double*) (intptr_t) address; + + *p = value; +} + + /* * Class: sun/misc/Unsafe * Method: objectFieldOffset @@ -950,6 +983,17 @@ JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putObjectVolatile(JNIEnv *env, jobje } +/* + * Class: sun/misc/Unsafe + * Method: getBooleanVolatile + * Signature: (Ljava/lang/Object;J)Z + */ +JNIEXPORT jboolean JNICALL Java_sun_misc_Unsafe_getBooleanVolatile(JNIEnv* env, jobject _this, jobject o, jlong offset) +{ + return FieldAccess::get_volatile(o, offset); +} + + /* * Class: sun/misc/Unsafe * Method: getByteVolatile @@ -961,6 +1005,28 @@ JNIEXPORT jbyte JNICALL Java_sun_misc_Unsafe_getByteVolatile(JNIEnv* env, jobjec } +/* + * Class: sun/misc/Unsafe + * Method: getShortVolatile + * Signature: (Ljava/lang/Object;J)S + */ +JNIEXPORT jshort JNICALL Java_sun_misc_Unsafe_getShortVolatile(JNIEnv* env, jobject _this, jobject o, jlong offset) +{ + return FieldAccess::get_volatile(o, offset); +} + + +/* + * Class: sun/misc/Unsafe + * Method: getCharVolatile + * Signature: (Ljava/lang/Object;J)C + */ +JNIEXPORT jchar JNICALL Java_sun_misc_Unsafe_getCharVolatile(JNIEnv* env, jobject _this, jobject o, jlong offset) +{ + return FieldAccess::get_volatile(o, offset); +} + + /* * Class: sun/misc/Unsafe * Method: getIntVolatile @@ -1126,6 +1192,8 @@ static JNINativeMethod methods[] = { { (char*) "putLong", (char*) "(JJ)V", (void*) (uintptr_t) &Java_sun_misc_Unsafe_putLong__JJ }, { (char*) "getFloat", (char*) "(J)F", (void*) (uintptr_t) &Java_sun_misc_Unsafe_getFloat__J }, { (char*) "putFloat", (char*) "(JF)V", (void*) (uintptr_t) &Java_sun_misc_Unsafe_putFloat__JF }, + { (char*) "getDouble", (char*) "(J)D", (void*) (uintptr_t) &Java_sun_misc_Unsafe_getDouble__J }, + { (char*) "putDouble", (char*) "(JD)V", (void*) (uintptr_t) &Java_sun_misc_Unsafe_putDouble__JD }, { (char*) "objectFieldOffset", (char*) "(Ljava/lang/reflect/Field;)J", (void*) (uintptr_t) &Java_sun_misc_Unsafe_objectFieldOffset }, { (char*) "allocateMemory", (char*) "(J)J", (void*) (uintptr_t) &Java_sun_misc_Unsafe_allocateMemory }, #if 0 @@ -1152,7 +1220,10 @@ static JNINativeMethod methods[] = { { (char*) "compareAndSwapLong", (char*) "(Ljava/lang/Object;JJJ)Z", (void*) (uintptr_t) &Java_sun_misc_Unsafe_compareAndSwapLong }, { (char*) "getObjectVolatile", (char*) "(Ljava/lang/Object;J)Ljava/lang/Object;", (void*) (uintptr_t) &Java_sun_misc_Unsafe_getObjectVolatile }, { (char*) "putObjectVolatile", (char*) "(Ljava/lang/Object;JLjava/lang/Object;)V", (void*) (uintptr_t) &Java_sun_misc_Unsafe_putObjectVolatile }, + { (char*) "getBooleanVolatile", (char*) "(Ljava/lang/Object;J)Z", (void*) (uintptr_t) &Java_sun_misc_Unsafe_getBooleanVolatile }, { (char*) "getByteVolatile", (char*) "(Ljava/lang/Object;J)B", (void*) (uintptr_t) &Java_sun_misc_Unsafe_getByteVolatile }, + { (char*) "getShortVolatile", (char*) "(Ljava/lang/Object;J)S", (void*) (uintptr_t) &Java_sun_misc_Unsafe_getShortVolatile }, + { (char*) "getCharVolatile", (char*) "(Ljava/lang/Object;J)C", (void*) (uintptr_t) &Java_sun_misc_Unsafe_getCharVolatile }, { (char*) "getIntVolatile", (char*) "(Ljava/lang/Object;J)I", (void*) (uintptr_t) &Java_sun_misc_Unsafe_getIntVolatile }, { (char*) "putIntVolatile", (char*) "(Ljava/lang/Object;JI)V", (void*) (uintptr_t) &Java_sun_misc_Unsafe_putIntVolatile }, { (char*) "getLongVolatile", (char*) "(Ljava/lang/Object;J)J", (void*) (uintptr_t) &Java_sun_misc_Unsafe_getLongVolatile }, diff --git a/src/threads/lock.cpp b/src/threads/lock.cpp index 5bcee690d..df007f1e8 100644 --- a/src/threads/lock.cpp +++ b/src/threads/lock.cpp @@ -33,7 +33,7 @@ #include "vm/types.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/llni.h" @@ -46,7 +46,7 @@ #include "toolbox/list.hpp" #include "vm/exceptions.hpp" -#include "vm/finalizer.h" +#include "vm/finalizer.hpp" #include "vm/global.h" #include "vm/options.h" #include "vm/string.hpp" @@ -675,6 +675,22 @@ static void lock_inflate(java_handle_t *o, lock_record_t *lr) } +/* sable_flc_waiting *********************************************************** + + Enqueue the current thread on another thread's FLC list. The function + blocks until the lock has been inflated by the owning thread. + + The algorithm used to be an almost literal copy from SableVM. The + superfluous list traversal in the waiting loop has been removed since, + though. + + IN: + lockword.....the object's lockword as seen at the first locking attempt + t............the current thread + o............the object of which to enter the monitor + +*******************************************************************************/ + static void sable_flc_waiting(Lockword *lockword, threadobject *t, java_handle_t *o) { int32_t index; @@ -714,30 +730,18 @@ static void sable_flc_waiting(Lockword *lockword, threadobject *t, java_handle_t t_other->flc_tail = t; f = t_other->flc_tail; - for (;;) + // The other thread will clear flc_object. + while (t->flc_object) { - threadobject *current; + // We are not cleared yet -- the other thread cannot have seen + // the FLC bit yet. + assert(t_other->flc_bit); // Wait until another thread sees the flc bit and notifies // us of unlocking. t->flc_cond->wait(t_other->flc_lock); - - if (t_other->flc_tail != f) - break; - /* Traverse FLC list looking if we're still there */ - current = t_other->flc_list; - while (current && current != t) - current = current->flc_next; - if (!current) - /* not in list anymore, can stop waiting */ - break; - - /* We are still in the list -- the other thread cannot have seen - the FLC bit yet */ - assert(t_other->flc_bit); } - t->flc_object = NULL; /* for garbage collector? */ t->flc_next = NULL; } else @@ -746,6 +750,17 @@ static void sable_flc_waiting(Lockword *lockword, threadobject *t, java_handle_t t_other->flc_lock->unlock(); } +/* notify_flc_waiters ********************************************************** + + Traverse the thread's FLC list and inflate all corresponding locks. Notify + the associated threads as well. + + IN: + t............the current thread + o............the object currently being unlocked + +*******************************************************************************/ + static void notify_flc_waiters(threadobject *t, java_handle_t *o) { threadobject *current; @@ -775,6 +790,7 @@ static void notify_flc_waiters(threadobject *t, java_handle_t *o) // Wake the waiting threads. current->flc_cond->broadcast(); + current->flc_object = NULL; current = current->flc_next; } diff --git a/src/threads/posix/thread-posix.cpp b/src/threads/posix/thread-posix.cpp index 949c1b599..40c59aa68 100644 --- a/src/threads/posix/thread-posix.cpp +++ b/src/threads/posix/thread-posix.cpp @@ -43,7 +43,7 @@ #include "arch.h" #include "mm/gc.hpp" -#include "mm/memory.h" +#include "mm/memory.hpp" #if defined(ENABLE_GC_CACAO) # include "mm/cacao-gc/gc.h" @@ -58,7 +58,7 @@ #include "threads/threadlist.hpp" #include "threads/thread.hpp" -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" #include "vm/jit/builtin.hpp" #include "vm/exceptions.hpp" @@ -66,7 +66,7 @@ #include "vm/globals.hpp" #include "vm/javaobjects.hpp" #include "vm/options.h" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/string.hpp" #include "vm/vm.hpp" @@ -1381,7 +1381,10 @@ static void threads_wait_with_timeout(threadobject *t, struct timespec *wakeupTi while (!t->interrupted && !(parking ? t->park_permit : t->signaled) && threads_current_time_is_earlier_than(wakeupTime)) { - thread_set_state_timed_waiting(t); + if (parking) + thread_set_state_timed_parked(t); + else + thread_set_state_timed_waiting(t); t->waitcond->timedwait(t->waitmutex, wakeupTime); @@ -1391,7 +1394,10 @@ static void threads_wait_with_timeout(threadobject *t, struct timespec *wakeupTi else { /* no timeout */ while (!t->interrupted && !(parking ? t->park_permit : t->signaled)) { - thread_set_state_waiting(t); + if (parking) + thread_set_state_parked(t); + else + thread_set_state_waiting(t); t->waitcond->wait(t->waitmutex); diff --git a/src/threads/posix/thread-posix.hpp b/src/threads/posix/thread-posix.hpp index 76892b7c3..8f0e55c71 100644 --- a/src/threads/posix/thread-posix.hpp +++ b/src/threads/posix/thread-posix.hpp @@ -193,7 +193,7 @@ inline static threadobject* thread_get_current(void); // Includes. -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/localref.hpp" diff --git a/src/threads/thread.cpp b/src/threads/thread.cpp index 8804f6eb5..1579fd4e1 100644 --- a/src/threads/thread.cpp +++ b/src/threads/thread.cpp @@ -31,7 +31,7 @@ #include "vm/types.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #if defined(ENABLE_GC_BOEHM) /* We need to include Boehm's gc.h here for GC_register_my_thread and @@ -948,6 +948,12 @@ void thread_print_info(threadobject *t) case THREAD_STATE_TIMED_WAITING: printf(" waiting on condition"); break; + case THREAD_STATE_PARKED: + printf(" parked"); + break; + case THREAD_STATE_TIMED_PARKED: + printf(" timed parked"); + break; case THREAD_STATE_TERMINATED: printf(" terminated"); break; @@ -981,6 +987,26 @@ intptr_t threads_get_current_tid(void) } +/** + * Set the current state of the given thread. This method should only + * be called while holding the threadlist-lock and after checking that + * the new state is valid. It is best to not call this method directly + * but call the specific setter methods below. + */ +static inline void thread_set_state(threadobject *t, int state) +{ + // Set the state of our internal threadobject. + t->state = state; + +#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) + // Set the state of the java.lang.Thread object. + java_lang_Thread thread(thread_get_object(t)); + assert(thread.is_non_null()); + thread.set_threadStatus(state); +#endif +} + + /* thread_set_state_runnable *************************************************** Set the current state of the given thread to THREAD_STATE_RUNNABLE. @@ -997,7 +1023,7 @@ void thread_set_state_runnable(threadobject *t) ThreadList::lock(); if (t->state != THREAD_STATE_TERMINATED) { - t->state = THREAD_STATE_RUNNABLE; + thread_set_state(t, THREAD_STATE_RUNNABLE); DEBUGTHREADS("is RUNNABLE", t); } @@ -1022,7 +1048,7 @@ void thread_set_state_waiting(threadobject *t) ThreadList::lock(); if (t->state != THREAD_STATE_TERMINATED) { - t->state = THREAD_STATE_WAITING; + thread_set_state(t, THREAD_STATE_WAITING); DEBUGTHREADS("is WAITING", t); } @@ -1048,7 +1074,7 @@ void thread_set_state_timed_waiting(threadobject *t) ThreadList::lock(); if (t->state != THREAD_STATE_TERMINATED) { - t->state = THREAD_STATE_TIMED_WAITING; + thread_set_state(t, THREAD_STATE_TIMED_WAITING); DEBUGTHREADS("is TIMED_WAITING", t); } @@ -1057,6 +1083,56 @@ void thread_set_state_timed_waiting(threadobject *t) } +/* thread_set_state_parked ***************************************************** + + Set the current state of the given thread to THREAD_STATE_PARKED. + + NOTE: If the thread has already terminated, don't set the state. + This is important for threads_detach_thread. + +*******************************************************************************/ + +void thread_set_state_parked(threadobject *t) +{ + /* Set the state inside a lock. */ + + ThreadList::lock(); + + if (t->state != THREAD_STATE_TERMINATED) { + thread_set_state(t, THREAD_STATE_PARKED); + + DEBUGTHREADS("is PARKED", t); + } + + ThreadList::unlock(); +} + + +/* thread_set_state_timed_parked *********************************************** + + Set the current state of the given thread to THREAD_STATE_TIMED_PARKED. + + NOTE: If the thread has already terminated, don't set the state. + This is important for threads_detach_thread. + +*******************************************************************************/ + +void thread_set_state_timed_parked(threadobject *t) +{ + /* Set the state inside a lock. */ + + ThreadList::lock(); + + if (t->state != THREAD_STATE_TERMINATED) { + thread_set_state(t, THREAD_STATE_TIMED_PARKED); + + DEBUGTHREADS("is TIMED_PARKED", t); + } + + ThreadList::unlock(); +} + + /* thread_set_state_terminated ************************************************* Set the current state of the given thread to @@ -1070,7 +1146,7 @@ void thread_set_state_terminated(threadobject *t) ThreadList::lock(); - t->state = THREAD_STATE_TERMINATED; + thread_set_state(t, THREAD_STATE_TERMINATED); DEBUGTHREADS("is TERMINATED", t); @@ -1136,6 +1212,8 @@ bool threads_thread_is_alive(threadobject *t) case THREAD_STATE_BLOCKED: case THREAD_STATE_WAITING: case THREAD_STATE_TIMED_WAITING: + case THREAD_STATE_PARKED: + case THREAD_STATE_TIMED_PARKED: return true; default: diff --git a/src/threads/thread.hpp b/src/threads/thread.hpp index b50db4370..c3563cf33 100644 --- a/src/threads/thread.hpp +++ b/src/threads/thread.hpp @@ -59,6 +59,8 @@ #define THREAD_STATE_WAITING 3 #define THREAD_STATE_TIMED_WAITING 4 #define THREAD_STATE_TERMINATED 5 +#define THREAD_STATE_PARKED 6 +#define THREAD_STATE_TIMED_PARKED 7 /* thread priorities **********************************************************/ @@ -326,6 +328,8 @@ intptr_t threads_get_current_tid(void); void thread_set_state_runnable(threadobject *t); void thread_set_state_waiting(threadobject *t); void thread_set_state_timed_waiting(threadobject *t); +void thread_set_state_parked(threadobject *t); +void thread_set_state_timed_parked(threadobject *t); void thread_set_state_terminated(threadobject *t); threadobject *thread_get_thread(java_handle_t *h); diff --git a/src/threads/threadlist.cpp b/src/threads/threadlist.cpp index bcf7f0e18..9284bdb84 100644 --- a/src/threads/threadlist.cpp +++ b/src/threads/threadlist.cpp @@ -34,7 +34,7 @@ #include "threads/thread.hpp" #include "toolbox/list.hpp" -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" #include "vm/jit/stacktrace.hpp" @@ -101,6 +101,26 @@ void ThreadList::dump_threads() } +/** + * Fills the passed list with all currently active threads. Creating a copy + * of the thread list here, is the only way to ensure we do not end up in a + * dead-lock when iterating over the list. + * + * @param list list class to be filled + */ +void ThreadList::get_active_threads(list &list) +{ + // Lock the thread lists. + lock(); + + // Use the assignment operator to create a copy of the thread list. + list = _active_thread_list; + + // Unlock the thread lists. + unlock(); +} + + /** * Return a free thread object. * diff --git a/src/threads/threadlist.hpp b/src/threads/threadlist.hpp index 2a9f2059c..4df7b9345 100644 --- a/src/threads/threadlist.hpp +++ b/src/threads/threadlist.hpp @@ -73,6 +73,7 @@ public: static inline void add_to_active_thread_list(threadobject* t); static void dump_threads(); + static void get_active_threads(list &list); static inline threadobject* get_main_thread(); static threadobject* get_free_thread(); static int32_t get_free_thread_index(); diff --git a/src/toolbox/Makefile.am b/src/toolbox/Makefile.am index c5c2cae12..32048a75b 100644 --- a/src/toolbox/Makefile.am +++ b/src/toolbox/Makefile.am @@ -36,8 +36,8 @@ libtoolbox_la_SOURCES = \ hashtable.c \ hashtable.h \ list.hpp \ - logging.c \ - logging.h \ + logging.cpp \ + logging.hpp \ set.h \ set.c \ util.c \ diff --git a/src/toolbox/avl.c b/src/toolbox/avl.c index 404328c05..d9d31210b 100644 --- a/src/toolbox/avl.c +++ b/src/toolbox/avl.c @@ -29,12 +29,12 @@ #include "vm/types.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "threads/mutex.hpp" #include "toolbox/avl.h" -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" #include "vm/global.h" #include "vm/vm.hpp" diff --git a/src/toolbox/bitvector.c b/src/toolbox/bitvector.c index 66b9df115..9d82d46b9 100644 --- a/src/toolbox/bitvector.c +++ b/src/toolbox/bitvector.c @@ -26,7 +26,7 @@ #include "config.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "toolbox/bitvector.h" diff --git a/src/toolbox/hashtable.c b/src/toolbox/hashtable.c index dd49f3de5..9fa938f41 100644 --- a/src/toolbox/hashtable.c +++ b/src/toolbox/hashtable.c @@ -26,7 +26,7 @@ #include "config.h" #include "vm/types.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "threads/mutex.hpp" diff --git a/src/toolbox/logging.c b/src/toolbox/logging.c deleted file mode 100644 index 7ff7f1b69..000000000 --- a/src/toolbox/logging.c +++ /dev/null @@ -1,287 +0,0 @@ -/* src/toolbox/logging.c - contains logging functions - - Copyright (C) 1996-2005, 2006, 2007, 2008 - CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO - - 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. - -*/ - - -#include "config.h" - -#include -#include -#include - -#include "vm/types.h" - -#include "mm/memory.h" - -#include "threads/thread.hpp" - -#include "toolbox/logging.h" -#include "toolbox/util.h" - -#include "vm/global.h" - -#if defined(ENABLE_STATISTICS) -# include "vm/statistics.h" -#endif - - -/*************************************************************************** - LOG FILE HANDLING -***************************************************************************/ - -FILE *logfile = NULL; - - -void log_init(const char *fname) -{ - if (fname) { - if (fname[0]) { - logfile = fopen(fname, "w"); - } - } -} - - -/* log_start ******************************************************************* - - Writes the preleading LOG: text to the protocol file (if opened) or - to stdout. - -*******************************************************************************/ - -void log_start(void) -{ -#if defined(ENABLE_THREADS) - ptrint tid; - - tid = threads_get_current_tid(); -#endif - - if (logfile) { -#if defined(ENABLE_THREADS) -# if SIZEOF_VOID_P == 8 - fprintf(logfile, "[0x%016lx] ", tid ); -# else - fprintf(logfile, "[0x%08x] ", tid); -# endif -#endif - } - else { -#if defined(ENABLE_THREADS) -# if SIZEOF_VOID_P == 8 - fprintf(stdout, "LOG: [0x%016lx] ", tid); -# else - fprintf(stdout, "LOG: [0x%08x] ", tid); -# endif -#else - fputs("LOG: ", stdout); -#endif - } -} - - -/* log_vprint ****************************************************************** - - Writes logtext to the protocol file (if opened) or to stdout. - -*******************************************************************************/ - -void log_vprint(const char *text, va_list ap) -{ - if (logfile) - vfprintf(logfile, text, ap); - else - vfprintf(stdout, text, ap); -} - - -/* log_print ******************************************************************* - - Writes logtext to the protocol file (if opened) or to stdout. - -*******************************************************************************/ - -void log_print(const char *text, ...) -{ - va_list ap; - - va_start(ap, text); - log_vprint(text, ap); - va_end(ap); -} - - -/* log_println ***************************************************************** - - Writes logtext to the protocol file (if opened) or to stdout with a - trailing newline. - -*******************************************************************************/ - -void log_println(const char *text, ...) -{ - va_list ap; - - log_start(); - - va_start(ap, text); - log_vprint(text, ap); - va_end(ap); - - log_finish(); -} - - -/* log_finish ****************************************************************** - - Finishes a logtext line with trailing newline and a fflush. - -*******************************************************************************/ - -void log_finish(void) -{ - if (logfile) { - fputs("\n", logfile); - fflush(logfile); - } - else { - fputs("\n", stdout); - fflush(stdout); - } -} - - -/* log_message_utf ************************************************************* - - Outputs log text like this: - - LOG: Creating class: java/lang/Object - -*******************************************************************************/ - -void log_message_utf(const char *msg, utf *u) -{ - char *buf; - s4 len; - - len = strlen(msg) + utf_bytes(u) + strlen("0"); - - buf = MNEW(char, len); - - strcpy(buf, msg); - utf_cat(buf, u); - - log_text(buf); - - MFREE(buf, char, len); -} - - -/* log_message_class *********************************************************** - - Outputs log text like this: - - LOG: Loading class: java/lang/Object - -*******************************************************************************/ - -void log_message_class(const char *msg, classinfo *c) -{ - log_message_utf(msg, c->name); -} - - -/* log_message_class_message_class ********************************************* - - Outputs log text like this: - - LOG: Initialize super class java/lang/Object from java/lang/VMThread - -*******************************************************************************/ - -void log_message_class_message_class(const char *msg1, classinfo *c1, - const char *msg2, classinfo *c2) -{ - char *buf; - s4 len; - - len = - strlen(msg1) + utf_bytes(c1->name) + - strlen(msg2) + utf_bytes(c2->name) + strlen("0"); - - buf = MNEW(char, len); - - strcpy(buf, msg1); - utf_cat_classname(buf, c1->name); - strcat(buf, msg2); - utf_cat_classname(buf, c2->name); - - log_text(buf); - - MFREE(buf, char, len); -} - - -/* log_message_method ********************************************************** - - Outputs log text like this: - - LOG: Compiling: java.lang.Object.clone()Ljava/lang/Object; - -*******************************************************************************/ - -void log_message_method(const char *msg, methodinfo *m) -{ - char *buf; - s4 len; - - len = strlen(msg) + utf_bytes(m->clazz->name) + strlen(".") + - utf_bytes(m->name) + utf_bytes(m->descriptor) + strlen("0"); - - buf = MNEW(char, len); - - strcpy(buf, msg); - utf_cat_classname(buf, m->clazz->name); - strcat(buf, "."); - utf_cat(buf, m->name); - utf_cat(buf, m->descriptor); - - log_text(buf); - - MFREE(buf, char, len); -} - - -/* - * 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: - * vim:noexpandtab:sw=4:ts=4: - */ diff --git a/src/toolbox/logging.cpp b/src/toolbox/logging.cpp new file mode 100644 index 000000000..c38b32b02 --- /dev/null +++ b/src/toolbox/logging.cpp @@ -0,0 +1,287 @@ +/* src/toolbox/logging.c - contains logging functions + + Copyright (C) 1996-2005, 2006, 2007, 2008 + CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO + + 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. + +*/ + + +#include "config.h" + +#include +#include +#include + +#include "vm/types.h" + +#include "mm/memory.hpp" + +#include "threads/thread.hpp" + +#include "toolbox/logging.hpp" +#include "toolbox/util.h" + +#include "vm/global.h" + +#if defined(ENABLE_STATISTICS) +# include "vm/statistics.h" +#endif + + +/*************************************************************************** + LOG FILE HANDLING +***************************************************************************/ + +FILE *logfile = NULL; + + +void log_init(const char *fname) +{ + if (fname) { + if (fname[0]) { + logfile = fopen(fname, "w"); + } + } +} + + +/* log_start ******************************************************************* + + Writes the preleading LOG: text to the protocol file (if opened) or + to stdout. + +*******************************************************************************/ + +void log_start(void) +{ +#if defined(ENABLE_THREADS) + ptrint tid; + + tid = threads_get_current_tid(); +#endif + + if (logfile) { +#if defined(ENABLE_THREADS) +# if SIZEOF_VOID_P == 8 + fprintf(logfile, "[0x%016lx] ", tid ); +# else + fprintf(logfile, "[0x%08x] ", tid); +# endif +#endif + } + else { +#if defined(ENABLE_THREADS) +# if SIZEOF_VOID_P == 8 + fprintf(stdout, "LOG: [0x%016lx] ", tid); +# else + fprintf(stdout, "LOG: [0x%08x] ", tid); +# endif +#else + fputs("LOG: ", stdout); +#endif + } +} + + +/* log_vprint ****************************************************************** + + Writes logtext to the protocol file (if opened) or to stdout. + +*******************************************************************************/ + +void log_vprint(const char *text, va_list ap) +{ + if (logfile) + vfprintf(logfile, text, ap); + else + vfprintf(stdout, text, ap); +} + + +/* log_print ******************************************************************* + + Writes logtext to the protocol file (if opened) or to stdout. + +*******************************************************************************/ + +void log_print(const char *text, ...) +{ + va_list ap; + + va_start(ap, text); + log_vprint(text, ap); + va_end(ap); +} + + +/* log_println ***************************************************************** + + Writes logtext to the protocol file (if opened) or to stdout with a + trailing newline. + +*******************************************************************************/ + +void log_println(const char *text, ...) +{ + va_list ap; + + log_start(); + + va_start(ap, text); + log_vprint(text, ap); + va_end(ap); + + log_finish(); +} + + +/* log_finish ****************************************************************** + + Finishes a logtext line with trailing newline and a fflush. + +*******************************************************************************/ + +void log_finish(void) +{ + if (logfile) { + fputs("\n", logfile); + fflush(logfile); + } + else { + fputs("\n", stdout); + fflush(stdout); + } +} + + +/* log_message_utf ************************************************************* + + Outputs log text like this: + + LOG: Creating class: java/lang/Object + +*******************************************************************************/ + +void log_message_utf(const char *msg, utf *u) +{ + char *buf; + s4 len; + + len = strlen(msg) + utf_bytes(u) + strlen("0"); + + buf = MNEW(char, len); + + strcpy(buf, msg); + utf_cat(buf, u); + + log_text(buf); + + MFREE(buf, char, len); +} + + +/* log_message_class *********************************************************** + + Outputs log text like this: + + LOG: Loading class: java/lang/Object + +*******************************************************************************/ + +void log_message_class(const char *msg, classinfo *c) +{ + log_message_utf(msg, c->name); +} + + +/* log_message_class_message_class ********************************************* + + Outputs log text like this: + + LOG: Initialize super class java/lang/Object from java/lang/VMThread + +*******************************************************************************/ + +void log_message_class_message_class(const char *msg1, classinfo *c1, + const char *msg2, classinfo *c2) +{ + char *buf; + s4 len; + + len = + strlen(msg1) + utf_bytes(c1->name) + + strlen(msg2) + utf_bytes(c2->name) + strlen("0"); + + buf = MNEW(char, len); + + strcpy(buf, msg1); + utf_cat_classname(buf, c1->name); + strcat(buf, msg2); + utf_cat_classname(buf, c2->name); + + log_text(buf); + + MFREE(buf, char, len); +} + + +/* log_message_method ********************************************************** + + Outputs log text like this: + + LOG: Compiling: java.lang.Object.clone()Ljava/lang/Object; + +*******************************************************************************/ + +void log_message_method(const char *msg, methodinfo *m) +{ + char *buf; + s4 len; + + len = strlen(msg) + utf_bytes(m->clazz->name) + strlen(".") + + utf_bytes(m->name) + utf_bytes(m->descriptor) + strlen("0"); + + buf = MNEW(char, len); + + strcpy(buf, msg); + utf_cat_classname(buf, m->clazz->name); + strcat(buf, "."); + utf_cat(buf, m->name); + utf_cat(buf, m->descriptor); + + log_text(buf); + + MFREE(buf, char, len); +} + + +/* + * 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: + * vim:noexpandtab:sw=4:ts=4: + */ diff --git a/src/toolbox/logging.h b/src/toolbox/logging.h deleted file mode 100644 index eed61bd8d..000000000 --- a/src/toolbox/logging.h +++ /dev/null @@ -1,84 +0,0 @@ -/* src/toolbox/logging.h - contains logging functions - - Copyright (C) 1996-2005, 2006, 2007, 2008 - CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO - - 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. - -*/ - - -#ifndef _LOGGING_H -#define _LOGGING_H - -#include "config.h" - -#include -#include - -#include "vm/class.hpp" -#include "vm/method.hpp" -#include "vm/utf8.h" - - -/* function prototypes ********************************************************/ - -#ifdef __cplusplus -extern "C" { -#endif - -void log_init(const char *fname); - -void log_start(void); - -void log_vprint(const char *text, va_list ap); -void log_print(const char *text, ...); -void log_println(const char *text, ...); - -void log_finish(void); - - -/* log message functions */ -void log_message_utf(const char *msg, utf *u); -void log_message_class(const char *msg, classinfo *c); -void log_message_class_message_class(const char *msg1, classinfo *c1, - const char *msg2, classinfo *c2); -void log_message_method(const char *msg, methodinfo *m); - -#define log_text(s) log_println("%s", (s)) -#define dolog log_println - -#ifdef __cplusplus -} -#endif - -#endif /* _LOGGING_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: - */ diff --git a/src/toolbox/logging.hpp b/src/toolbox/logging.hpp new file mode 100644 index 000000000..3b70b6b06 --- /dev/null +++ b/src/toolbox/logging.hpp @@ -0,0 +1,84 @@ +/* src/toolbox/logging.h - contains logging functions + + Copyright (C) 1996-2005, 2006, 2007, 2008 + CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO + + 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. + +*/ + + +#ifndef _LOGGING_H +#define _LOGGING_H + +#include "config.h" + +#include +#include + +#include "vm/class.hpp" +#include "vm/method.hpp" +#include "vm/utf8.h" + + +/* function prototypes ********************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +void log_init(const char *fname); + +void log_start(void); + +void log_vprint(const char *text, va_list ap); +void log_print(const char *text, ...); +void log_println(const char *text, ...); + +void log_finish(void); + + +/* log message functions */ +void log_message_utf(const char *msg, utf *u); +void log_message_class(const char *msg, classinfo *c); +void log_message_class_message_class(const char *msg1, classinfo *c1, + const char *msg2, classinfo *c2); +void log_message_method(const char *msg, methodinfo *m); + +#define log_text(s) log_println("%s", (s)) +#define dolog log_println + +#ifdef __cplusplus +} +#endif + +#endif /* _LOGGING_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: + */ diff --git a/src/toolbox/set.c b/src/toolbox/set.c index c63ddf882..d30fafaae 100644 --- a/src/toolbox/set.c +++ b/src/toolbox/set.c @@ -36,7 +36,7 @@ #include "toolbox/set.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "vm/global.h" diff --git a/src/toolbox/util.c b/src/toolbox/util.c index 2e26c259b..4adb970f5 100644 --- a/src/toolbox/util.c +++ b/src/toolbox/util.c @@ -32,7 +32,7 @@ #include "vm/types.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "vm/vm.hpp" diff --git a/src/toolbox/worklist.c b/src/toolbox/worklist.c index 6cb9fb37a..5489f1709 100644 --- a/src/toolbox/worklist.c +++ b/src/toolbox/worklist.c @@ -29,7 +29,7 @@ */ -#include "mm/memory.h" +#include "mm/memory.hpp" #include "toolbox/worklist.h" diff --git a/src/vm/Makefile.am b/src/vm/Makefile.am index 4dd35b777..7830a5a19 100644 --- a/src/vm/Makefile.am +++ b/src/vm/Makefile.am @@ -42,8 +42,8 @@ endif if ENABLE_JAVASE if ENABLE_ANNOTATIONS ANNOTATION_SOURCES = \ - annotation.c \ - annotation.h + annotation.cpp \ + annotation.hpp endif STACKMAP_SOURCES = \ @@ -88,14 +88,14 @@ libvm_la_SOURCES = \ classcache.cpp \ classcache.hpp \ $(CYCLES_STATS_SOURCES) \ - descriptor.c \ - descriptor.h \ + descriptor.cpp \ + descriptor.hpp \ exceptions.cpp \ exceptions.hpp \ field.cpp \ field.hpp \ - finalizer.c \ - finalizer.h \ + finalizer.cpp \ + finalizer.hpp \ globals.cpp \ globals.hpp \ initialize.cpp \ @@ -122,8 +122,8 @@ libvm_la_SOURCES = \ resolve.cpp \ resolve.hpp \ $(RT_TIMING_SOURCES) \ - signal.c \ - signallocal.h \ + signal.cpp \ + signallocal.hpp \ $(STACKMAP_SOURCES) \ $(STATISTICS_SOURCES) \ string.cpp \ diff --git a/src/vm/access.cpp b/src/vm/access.cpp index a0abbc156..73899e0e3 100644 --- a/src/vm/access.cpp +++ b/src/vm/access.cpp @@ -30,7 +30,7 @@ #include "vm/types.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/llni.h" @@ -341,10 +341,10 @@ bool access_check_method(methodinfo *m, int callerdepth) return true; } -#if defined(__cplusplus) -} #endif +#if defined(__cplusplus) +} #endif diff --git a/src/vm/annotation.c b/src/vm/annotation.c deleted file mode 100644 index bbca2affd..000000000 --- a/src/vm/annotation.c +++ /dev/null @@ -1,614 +0,0 @@ -/* src/vm/annotation.c - class annotations - - Copyright (C) 2006, 2007, 2008 - CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO - - 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. - -*/ - - -#include "config.h" - -#include -#include - -#include "native/llni.h" - -#include "mm/memory.h" - -#include "toolbox/logging.h" - -#include "vm/annotation.h" -#include "vm/array.hpp" -#include "vm/jit/builtin.hpp" -#include "vm/class.hpp" -#include "vm/loader.hpp" -#include "vm/primitive.hpp" -#include "vm/suck.hpp" -#include "vm/types.h" - -#if !defined(ENABLE_ANNOTATIONS) -# error annotation support has to be enabled when compling this file! -#endif - - -/* annotation_bytearrays_resize *********************************************** - - Resize an array of bytearrays. - - IN: - bytearrays.....array of bytearrays - size...........new size of the refered array - - RETURN VALUE: - The new array if a resize was neccessarry, the old if the given size - equals the current size or NULL if an error occured. - -*******************************************************************************/ - -static java_handle_objectarray_t *annotation_bytearrays_resize( - java_handle_objectarray_t *bytearrays, uint32_t size) -{ - java_handle_objectarray_t *newbas = NULL; /* new array */ - uint32_t minsize = 0; /* count of object refs to copy */ - uint32_t oldsize = 0; /* size of old array */ - - if (bytearrays != NULL) { - oldsize = array_length_get((java_handle_t*)bytearrays); - - /* if the size already fits do nothing */ - if (size == oldsize) { - return bytearrays; - } - } - - newbas = builtin_anewarray(size, - Primitive_get_arrayclass_by_type(PRIMITIVETYPE_BYTE)); - - /* is there a old byte array array? */ - if (newbas != NULL && bytearrays != NULL) { - minsize = size < oldsize ? size : oldsize; - - LLNI_CRITICAL_START; - MCOPY( - LLNI_array_data(newbas), LLNI_array_data(bytearrays), - java_object_t*, minsize); - LLNI_CRITICAL_END; - } - - return newbas; -} - - -/* annotation_bytearrays_insert *********************************************** - - Insert a bytearray into an array of bytearrays. - - IN: - bytearrays........array of bytearrays where 'bytearray' has to be - inserted at position 'index'. - index.............position where 'ba' has to be inserted into - 'bytearrays'. - bytearray.........byte array which has to be inserted into - 'bytearrays'. - - RETURN VALUE: - The new array if a resize was neccessarry, the old if the given size - equals the current size or NULL if an error occured. - -*******************************************************************************/ - -static java_handle_t *annotation_bytearrays_insert( - java_handle_t *bytearrays, uint32_t index, - java_handle_bytearray_t *bytearray) -{ - java_handle_objectarray_t *bas; /* bytearrays */ - uint32_t size = 0; /* current size of the array */ - - /* do nothing if NULL is inserted but no array exists */ - if (bytearray == NULL && bytearrays == NULL) { - return NULL; - } - - /* get lengths if array exists */ - if (bytearrays != NULL) { - size = array_length_get(bytearrays); - } - - bas = (java_handle_objectarray_t*)bytearrays; - - if (bytearray == NULL) { - /* insert NULL only if array is big enough */ - if (size > index) { - array_objectarray_element_set(bas, index, NULL); - } - } - else { - /* resize array if it's not enough for inserted value */ - if (size <= index) { - bas = annotation_bytearrays_resize(bas, index + 1); - - if (bas == NULL) { - /* out of memory */ - return NULL; - } - } - - array_objectarray_element_set(bas, index, (java_handle_t*)bytearray); - } - - return (java_handle_t*)bas; -} - - -/* annotation_load_attribute_body ********************************************* - - This function loads the body of a generic attribute. - - XXX: Maybe this function should be called loader_load_attribute_body and - located in vm/loader.c? - - attribute_info { - u2 attribute_name_index; - u4 attribute_length; - u1 info[attribute_length]; - } - - IN: - cb.................classbuffer from which to read the data. - errormsg_prefix....prefix for error messages (if any). - - OUT: - attribute..........bytearray-pointer which will be set to the read data. - - RETURN VALUE: - true if all went good. false otherwhise. - -*******************************************************************************/ - -static bool annotation_load_attribute_body(classbuffer *cb, - java_handle_bytearray_t **attribute, const char *errormsg_prefix) -{ - uint32_t size = 0; /* size of the attribute */ - java_handle_bytearray_t *ba = NULL; /* the raw attributes' bytes */ - - assert(cb != NULL); - assert(attribute != NULL); - - if (!suck_check_classbuffer_size(cb, 4)) { - log_println("%s: size missing", errormsg_prefix); - return false; - } - - /* load attribute_length */ - size = suck_u4(cb); - - if (!suck_check_classbuffer_size(cb, size)) { - log_println("%s: invalid size", errormsg_prefix); - return false; - } - - /* if attribute_length == 0 then NULL is - * the right value for this attribute */ - if (size > 0) { - ba = builtin_newarray_byte(size); - - if (ba == NULL) { - /* out of memory */ - return false; - } - - /* load data */ - LLNI_CRITICAL_START; - - suck_nbytes((uint8_t*)LLNI_array_data(ba), cb, size); - - LLNI_CRITICAL_END; - - /* return data */ - *attribute = ba; - } - - return true; -} - - -/* annotation_load_method_attribute_annotationdefault ************************* - - Load annotation default value. - - AnnotationDefault_attribute { - u2 attribute_name_index; - u4 attribute_length; - element_value default_value; - } - - IN: - cb.................classbuffer from which to read the data. - m..................methodinfo for the method of which the annotation - default value is read and into which the value is - stored into. - - RETURN VALUE: - true if all went good. false otherwhise. - -*******************************************************************************/ - -bool annotation_load_method_attribute_annotationdefault( - classbuffer *cb, methodinfo *m) -{ - int slot = 0; - /* the slot of the method */ - java_handle_bytearray_t *annotationdefault = NULL; - /* unparsed annotation defalut value */ - java_handle_t *annotationdefaults = NULL; - /* array of unparsed annotation default values */ - - assert(cb != NULL); - assert(m != NULL); - - LLNI_classinfo_field_get( - m->clazz, method_annotationdefaults, annotationdefaults); - - if (!annotation_load_attribute_body( - cb, &annotationdefault, - "invalid annotation default method attribute")) { - return false; - } - - if (annotationdefault != NULL) { - slot = m - m->clazz->methods; - annotationdefaults = annotation_bytearrays_insert( - annotationdefaults, slot, annotationdefault); - - if (annotationdefaults == NULL) { - return false; - } - - LLNI_classinfo_field_set( - m->clazz, method_annotationdefaults, annotationdefaults); - } - - return true; -} - - -/* annotation_load_method_attribute_runtimevisibleparameterannotations ******** - - Load runtime visible parameter annotations. - - RuntimeVisibleParameterAnnotations_attribute { - u2 attribute_name_index; - u4 attribute_length; - u1 num_parameters; - { - u2 num_annotations; - annotation annotations[num_annotations]; - } parameter_annotations[num_parameters]; - } - - IN: - cb.................classbuffer from which to read the data. - m..................methodinfo for the method of which the parameter - annotations are read and into which the parameter - annotations are stored into. - - RETURN VALUE: - true if all went good. false otherwhise. - -*******************************************************************************/ - -bool annotation_load_method_attribute_runtimevisibleparameterannotations( - classbuffer *cb, methodinfo *m) -{ - int slot = 0; - /* the slot of the method */ - java_handle_bytearray_t *annotations = NULL; - /* unparsed parameter annotations */ - java_handle_t *parameterannotations = NULL; - /* array of unparsed parameter annotations */ - - assert(cb != NULL); - assert(m != NULL); - - LLNI_classinfo_field_get( - m->clazz, method_parameterannotations, parameterannotations); - - if (!annotation_load_attribute_body( - cb, &annotations, - "invalid runtime visible parameter annotations method attribute")) { - return false; - } - - if (annotations != NULL) { - slot = m - m->clazz->methods; - parameterannotations = annotation_bytearrays_insert( - parameterannotations, slot, annotations); - - if (parameterannotations == NULL) { - return false; - } - - LLNI_classinfo_field_set( - m->clazz, method_parameterannotations, parameterannotations); - } - - return true; -} - - -/* annotation_load_method_attribute_runtimeinvisibleparameterannotations ****** - - Load runtime invisible parameter annotations. - - - The RuntimeInvisibleParameterAnnotations attribute is similar to the - RuntimeVisibleParameterAnnotations attribute, except that the annotations - represented by a RuntimeInvisibleParameterAnnotations attribute must not be - made available for return by reflective APIs, unless the the JVM has - specifically been instructed to retain these annotations via some - implementation-specific mechanism such as a command line flag. In the - absence of such instructions, the JVM ignores this attribute. - - - Hotspot loads them into the same bytearray as the runtime visible parameter - annotations (after the runtime visible parameter annotations). But in J2SE - the bytearray will only be parsed as if there is only one annotation - structure in it, so the runtime invisible parameter annotatios will be - ignored. - - Therefore I do not even bother to read them. - - RuntimeInvisibleParameterAnnotations_attribute { - u2 attribute_name_index; - u4 attribute_length; - u1 num_parameters; - { - u2 num_annotations; - annotation annotations[num_annotations]; - } parameter_annotations[num_parameters]; - } - - IN: - cb.................classbuffer from which to read the data. - m..................methodinfo for the method of which the parameter - annotations are read and into which the parameter - annotations are stored into. - - RETURN VALUE: - true if all went good. false otherwhise. - -*******************************************************************************/ - -bool annotation_load_method_attribute_runtimeinvisibleparameterannotations( - classbuffer *cb, methodinfo *m) -{ - return loader_skip_attribute_body(cb); -} - - -/* annotation_load_class_attribute_runtimevisibleannotations ****************** - - Load runtime visible annotations of a class. - - IN: - cb........the classbuffer from which the attribute has to be loaded. - - RETURN VALUE: - true if all went good. false otherwhise. - -*******************************************************************************/ - -bool annotation_load_class_attribute_runtimevisibleannotations( - classbuffer *cb) -{ - java_handle_bytearray_t *annotations = NULL; /* unparsed annotations */ - - if (!annotation_load_attribute_body( - cb, &annotations, - "invalid runtime visible annotations class attribute")) { - return false; - } - - LLNI_classinfo_field_set(cb->clazz, annotations, (java_handle_t*)annotations); - - return true; -} - - -/* annotation_load_class_attribute_runtimeinvisibleannotations **************** - - Load runtime invisible annotations of a class (just skip them). - - IN: - cb........the classbuffer from which the attribute has to be loaded. - - RETURN VALUE: - true if all went good. false otherwhise. - -*******************************************************************************/ - -bool annotation_load_class_attribute_runtimeinvisibleannotations( - classbuffer *cb) -{ - return loader_skip_attribute_body(cb); -} - - -/* annotation_load_method_attribute_runtimevisibleannotations ***************** - - Load runtime visible annotations of a method. - - IN: - cb........the classbuffer from which the attribute has to be loaded. - m.........the method of which the runtime visible annotations have - to be loaded. - - RETURN VALUE: - true if all went good. false otherwhise. - -*******************************************************************************/ - -bool annotation_load_method_attribute_runtimevisibleannotations( - classbuffer *cb, methodinfo *m) -{ - int slot = 0; - /* slot of the method */ - java_handle_bytearray_t *annotations = NULL; - /* unparsed annotations */ - java_handle_t *method_annotations = NULL; - /* array of unparsed method annotations */ - - assert(cb != NULL); - assert(m != NULL); - - LLNI_classinfo_field_get( - m->clazz, method_annotations, method_annotations); - - if (!annotation_load_attribute_body( - cb, &annotations, - "invalid runtime visible annotations method attribute")) { - return false; - } - - if (annotations != NULL) { - slot = m - m->clazz->methods; - method_annotations = annotation_bytearrays_insert( - method_annotations, slot, annotations); - - if (method_annotations == NULL) { - return false; - } - - LLNI_classinfo_field_set( - m->clazz, method_annotations, method_annotations); - } - - return true; -} - - -/* annotation_load_method_attribute_runtimeinvisibleannotations **************** - - Load runtime invisible annotations of a method (just skip them). - - IN: - cb........the classbuffer from which the attribute has to be loaded. - m.........the method of which the runtime invisible annotations have - to be loaded. - - RETURN VALUE: - true if all went good. false otherwhise. - -*******************************************************************************/ - -bool annotation_load_method_attribute_runtimeinvisibleannotations( - classbuffer *cb, methodinfo *m) -{ - return loader_skip_attribute_body(cb); -} - - -/* annotation_load_field_attribute_runtimevisibleannotations ****************** - - Load runtime visible annotations of a field. - - IN: - cb........the classbuffer from which the attribute has to be loaded. - f.........the field of which the runtime visible annotations have - to be loaded. - - RETURN VALUE: - true if all went good. false otherwhise. - -*******************************************************************************/ - -bool annotation_load_field_attribute_runtimevisibleannotations( - classbuffer *cb, fieldinfo *f) -{ - int slot = 0; - /* slot of the field */ - java_handle_bytearray_t *annotations = NULL; - /* unparsed annotations */ - java_handle_t *field_annotations = NULL; - /* array of unparsed field annotations */ - - assert(cb != NULL); - assert(f != NULL); - - LLNI_classinfo_field_get( - f->clazz, field_annotations, field_annotations); - - if (!annotation_load_attribute_body( - cb, &annotations, - "invalid runtime visible annotations field attribute")) { - return false; - } - - if (annotations != NULL) { - slot = f - f->clazz->fields; - field_annotations = annotation_bytearrays_insert( - field_annotations, slot, annotations); - - if (field_annotations == NULL) { - return false; - } - - LLNI_classinfo_field_set( - f->clazz, field_annotations, field_annotations); - } - - return true; -} - - -/* annotation_load_field_attribute_runtimeinvisibleannotations **************** - - Load runtime invisible annotations of a field (just skip them). - - IN: - cb........the classbuffer from which the attribute has to be loaded. - f.........the field of which the runtime invisible annotations have - to be loaded. - - RETURN VALUE: - true if all went good. false otherwhise. - -*******************************************************************************/ - -bool annotation_load_field_attribute_runtimeinvisibleannotations( - classbuffer *cb, fieldinfo *f) -{ - return loader_skip_attribute_body(cb); -} - - -/* - * 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: - * vim:noexpandtab:sw=4:ts=4: - */ diff --git a/src/vm/annotation.cpp b/src/vm/annotation.cpp new file mode 100644 index 000000000..2a5fafdff --- /dev/null +++ b/src/vm/annotation.cpp @@ -0,0 +1,614 @@ +/* src/vm/annotation.cpp - class annotations + + Copyright (C) 2006, 2007, 2008 + CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO + + 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. + +*/ + + +#include "config.h" + +#include +#include + +#include "native/llni.h" + +#include "mm/memory.hpp" + +#include "toolbox/logging.hpp" + +#include "vm/annotation.hpp" +#include "vm/array.hpp" +#include "vm/jit/builtin.hpp" +#include "vm/class.hpp" +#include "vm/loader.hpp" +#include "vm/primitive.hpp" +#include "vm/suck.hpp" +#include "vm/types.h" + +#if !defined(ENABLE_ANNOTATIONS) +# error annotation support has to be enabled when compling this file! +#endif + + +/* annotation_bytearrays_resize *********************************************** + + Resize an array of bytearrays. + + IN: + bytearrays.....array of bytearrays + size...........new size of the refered array + + RETURN VALUE: + The new array if a resize was neccessarry, the old if the given size + equals the current size or NULL if an error occured. + +*******************************************************************************/ + +static java_handle_objectarray_t *annotation_bytearrays_resize( + java_handle_objectarray_t *bytearrays, uint32_t size) +{ + java_handle_objectarray_t *newbas = NULL; /* new array */ + uint32_t minsize = 0; /* count of object refs to copy */ + uint32_t oldsize = 0; /* size of old array */ + + if (bytearrays != NULL) { + oldsize = array_length_get((java_handle_t*)bytearrays); + + /* if the size already fits do nothing */ + if (size == oldsize) { + return bytearrays; + } + } + + newbas = builtin_anewarray(size, + Primitive::get_arrayclass_by_type(PRIMITIVETYPE_BYTE)); + + /* is there a old byte array array? */ + if (newbas != NULL && bytearrays != NULL) { + minsize = size < oldsize ? size : oldsize; + + LLNI_CRITICAL_START; + MCOPY( + LLNI_array_data(newbas), LLNI_array_data(bytearrays), + java_object_t*, minsize); + LLNI_CRITICAL_END; + } + + return newbas; +} + + +/* annotation_bytearrays_insert *********************************************** + + Insert a bytearray into an array of bytearrays. + + IN: + bytearrays........array of bytearrays where 'bytearray' has to be + inserted at position 'index'. + index.............position where 'ba' has to be inserted into + 'bytearrays'. + bytearray.........byte array which has to be inserted into + 'bytearrays'. + + RETURN VALUE: + The new array if a resize was neccessarry, the old if the given size + equals the current size or NULL if an error occured. + +*******************************************************************************/ + +static java_handle_t *annotation_bytearrays_insert( + java_handle_t *bytearrays, uint32_t index, + java_handle_bytearray_t *bytearray) +{ + java_handle_objectarray_t *bas; /* bytearrays */ + uint32_t size = 0; /* current size of the array */ + + /* do nothing if NULL is inserted but no array exists */ + if (bytearray == NULL && bytearrays == NULL) { + return NULL; + } + + /* get lengths if array exists */ + if (bytearrays != NULL) { + size = array_length_get(bytearrays); + } + + bas = (java_handle_objectarray_t*)bytearrays; + + if (bytearray == NULL) { + /* insert NULL only if array is big enough */ + if (size > index) { + array_objectarray_element_set(bas, index, NULL); + } + } + else { + /* resize array if it's not enough for inserted value */ + if (size <= index) { + bas = annotation_bytearrays_resize(bas, index + 1); + + if (bas == NULL) { + /* out of memory */ + return NULL; + } + } + + array_objectarray_element_set(bas, index, (java_handle_t*)bytearray); + } + + return (java_handle_t*)bas; +} + + +/* annotation_load_attribute_body ********************************************* + + This function loads the body of a generic attribute. + + XXX: Maybe this function should be called loader_load_attribute_body and + located in vm/loader.c? + + attribute_info { + u2 attribute_name_index; + u4 attribute_length; + u1 info[attribute_length]; + } + + IN: + cb.................classbuffer from which to read the data. + errormsg_prefix....prefix for error messages (if any). + + OUT: + attribute..........bytearray-pointer which will be set to the read data. + + RETURN VALUE: + true if all went good. false otherwhise. + +*******************************************************************************/ + +static bool annotation_load_attribute_body(classbuffer *cb, + java_handle_bytearray_t **attribute, const char *errormsg_prefix) +{ + uint32_t size = 0; /* size of the attribute */ + java_handle_bytearray_t *ba = NULL; /* the raw attributes' bytes */ + + assert(cb != NULL); + assert(attribute != NULL); + + if (!suck_check_classbuffer_size(cb, 4)) { + log_println("%s: size missing", errormsg_prefix); + return false; + } + + /* load attribute_length */ + size = suck_u4(cb); + + if (!suck_check_classbuffer_size(cb, size)) { + log_println("%s: invalid size", errormsg_prefix); + return false; + } + + /* if attribute_length == 0 then NULL is + * the right value for this attribute */ + if (size > 0) { + ba = builtin_newarray_byte(size); + + if (ba == NULL) { + /* out of memory */ + return false; + } + + /* load data */ + LLNI_CRITICAL_START; + + suck_nbytes((uint8_t*)LLNI_array_data(ba), cb, size); + + LLNI_CRITICAL_END; + + /* return data */ + *attribute = ba; + } + + return true; +} + + +/* annotation_load_method_attribute_annotationdefault ************************* + + Load annotation default value. + + AnnotationDefault_attribute { + u2 attribute_name_index; + u4 attribute_length; + element_value default_value; + } + + IN: + cb.................classbuffer from which to read the data. + m..................methodinfo for the method of which the annotation + default value is read and into which the value is + stored into. + + RETURN VALUE: + true if all went good. false otherwhise. + +*******************************************************************************/ + +bool annotation_load_method_attribute_annotationdefault( + classbuffer *cb, methodinfo *m) +{ + int slot = 0; + /* the slot of the method */ + java_handle_bytearray_t *annotationdefault = NULL; + /* unparsed annotation defalut value */ + java_handle_t *annotationdefaults = NULL; + /* array of unparsed annotation default values */ + + assert(cb != NULL); + assert(m != NULL); + + LLNI_classinfo_field_get( + m->clazz, method_annotationdefaults, annotationdefaults); + + if (!annotation_load_attribute_body( + cb, &annotationdefault, + "invalid annotation default method attribute")) { + return false; + } + + if (annotationdefault != NULL) { + slot = m - m->clazz->methods; + annotationdefaults = annotation_bytearrays_insert( + annotationdefaults, slot, annotationdefault); + + if (annotationdefaults == NULL) { + return false; + } + + LLNI_classinfo_field_set( + m->clazz, method_annotationdefaults, annotationdefaults); + } + + return true; +} + + +/* annotation_load_method_attribute_runtimevisibleparameterannotations ******** + + Load runtime visible parameter annotations. + + RuntimeVisibleParameterAnnotations_attribute { + u2 attribute_name_index; + u4 attribute_length; + u1 num_parameters; + { + u2 num_annotations; + annotation annotations[num_annotations]; + } parameter_annotations[num_parameters]; + } + + IN: + cb.................classbuffer from which to read the data. + m..................methodinfo for the method of which the parameter + annotations are read and into which the parameter + annotations are stored into. + + RETURN VALUE: + true if all went good. false otherwhise. + +*******************************************************************************/ + +bool annotation_load_method_attribute_runtimevisibleparameterannotations( + classbuffer *cb, methodinfo *m) +{ + int slot = 0; + /* the slot of the method */ + java_handle_bytearray_t *annotations = NULL; + /* unparsed parameter annotations */ + java_handle_t *parameterannotations = NULL; + /* array of unparsed parameter annotations */ + + assert(cb != NULL); + assert(m != NULL); + + LLNI_classinfo_field_get( + m->clazz, method_parameterannotations, parameterannotations); + + if (!annotation_load_attribute_body( + cb, &annotations, + "invalid runtime visible parameter annotations method attribute")) { + return false; + } + + if (annotations != NULL) { + slot = m - m->clazz->methods; + parameterannotations = annotation_bytearrays_insert( + parameterannotations, slot, annotations); + + if (parameterannotations == NULL) { + return false; + } + + LLNI_classinfo_field_set( + m->clazz, method_parameterannotations, parameterannotations); + } + + return true; +} + + +/* annotation_load_method_attribute_runtimeinvisibleparameterannotations ****** + + Load runtime invisible parameter annotations. + + + The RuntimeInvisibleParameterAnnotations attribute is similar to the + RuntimeVisibleParameterAnnotations attribute, except that the annotations + represented by a RuntimeInvisibleParameterAnnotations attribute must not be + made available for return by reflective APIs, unless the the JVM has + specifically been instructed to retain these annotations via some + implementation-specific mechanism such as a command line flag. In the + absence of such instructions, the JVM ignores this attribute. + + + Hotspot loads them into the same bytearray as the runtime visible parameter + annotations (after the runtime visible parameter annotations). But in J2SE + the bytearray will only be parsed as if there is only one annotation + structure in it, so the runtime invisible parameter annotatios will be + ignored. + + Therefore I do not even bother to read them. + + RuntimeInvisibleParameterAnnotations_attribute { + u2 attribute_name_index; + u4 attribute_length; + u1 num_parameters; + { + u2 num_annotations; + annotation annotations[num_annotations]; + } parameter_annotations[num_parameters]; + } + + IN: + cb.................classbuffer from which to read the data. + m..................methodinfo for the method of which the parameter + annotations are read and into which the parameter + annotations are stored into. + + RETURN VALUE: + true if all went good. false otherwhise. + +*******************************************************************************/ + +bool annotation_load_method_attribute_runtimeinvisibleparameterannotations( + classbuffer *cb, methodinfo *m) +{ + return loader_skip_attribute_body(cb); +} + + +/* annotation_load_class_attribute_runtimevisibleannotations ****************** + + Load runtime visible annotations of a class. + + IN: + cb........the classbuffer from which the attribute has to be loaded. + + RETURN VALUE: + true if all went good. false otherwhise. + +*******************************************************************************/ + +bool annotation_load_class_attribute_runtimevisibleannotations( + classbuffer *cb) +{ + java_handle_bytearray_t *annotations = NULL; /* unparsed annotations */ + + if (!annotation_load_attribute_body( + cb, &annotations, + "invalid runtime visible annotations class attribute")) { + return false; + } + + LLNI_classinfo_field_set(cb->clazz, annotations, (java_handle_t*)annotations); + + return true; +} + + +/* annotation_load_class_attribute_runtimeinvisibleannotations **************** + + Load runtime invisible annotations of a class (just skip them). + + IN: + cb........the classbuffer from which the attribute has to be loaded. + + RETURN VALUE: + true if all went good. false otherwhise. + +*******************************************************************************/ + +bool annotation_load_class_attribute_runtimeinvisibleannotations( + classbuffer *cb) +{ + return loader_skip_attribute_body(cb); +} + + +/* annotation_load_method_attribute_runtimevisibleannotations ***************** + + Load runtime visible annotations of a method. + + IN: + cb........the classbuffer from which the attribute has to be loaded. + m.........the method of which the runtime visible annotations have + to be loaded. + + RETURN VALUE: + true if all went good. false otherwhise. + +*******************************************************************************/ + +bool annotation_load_method_attribute_runtimevisibleannotations( + classbuffer *cb, methodinfo *m) +{ + int slot = 0; + /* slot of the method */ + java_handle_bytearray_t *annotations = NULL; + /* unparsed annotations */ + java_handle_t *method_annotations = NULL; + /* array of unparsed method annotations */ + + assert(cb != NULL); + assert(m != NULL); + + LLNI_classinfo_field_get( + m->clazz, method_annotations, method_annotations); + + if (!annotation_load_attribute_body( + cb, &annotations, + "invalid runtime visible annotations method attribute")) { + return false; + } + + if (annotations != NULL) { + slot = m - m->clazz->methods; + method_annotations = annotation_bytearrays_insert( + method_annotations, slot, annotations); + + if (method_annotations == NULL) { + return false; + } + + LLNI_classinfo_field_set( + m->clazz, method_annotations, method_annotations); + } + + return true; +} + + +/* annotation_load_method_attribute_runtimeinvisibleannotations **************** + + Load runtime invisible annotations of a method (just skip them). + + IN: + cb........the classbuffer from which the attribute has to be loaded. + m.........the method of which the runtime invisible annotations have + to be loaded. + + RETURN VALUE: + true if all went good. false otherwhise. + +*******************************************************************************/ + +bool annotation_load_method_attribute_runtimeinvisibleannotations( + classbuffer *cb, methodinfo *m) +{ + return loader_skip_attribute_body(cb); +} + + +/* annotation_load_field_attribute_runtimevisibleannotations ****************** + + Load runtime visible annotations of a field. + + IN: + cb........the classbuffer from which the attribute has to be loaded. + f.........the field of which the runtime visible annotations have + to be loaded. + + RETURN VALUE: + true if all went good. false otherwhise. + +*******************************************************************************/ + +bool annotation_load_field_attribute_runtimevisibleannotations( + classbuffer *cb, fieldinfo *f) +{ + int slot = 0; + /* slot of the field */ + java_handle_bytearray_t *annotations = NULL; + /* unparsed annotations */ + java_handle_t *field_annotations = NULL; + /* array of unparsed field annotations */ + + assert(cb != NULL); + assert(f != NULL); + + LLNI_classinfo_field_get( + f->clazz, field_annotations, field_annotations); + + if (!annotation_load_attribute_body( + cb, &annotations, + "invalid runtime visible annotations field attribute")) { + return false; + } + + if (annotations != NULL) { + slot = f - f->clazz->fields; + field_annotations = annotation_bytearrays_insert( + field_annotations, slot, annotations); + + if (field_annotations == NULL) { + return false; + } + + LLNI_classinfo_field_set( + f->clazz, field_annotations, field_annotations); + } + + return true; +} + + +/* annotation_load_field_attribute_runtimeinvisibleannotations **************** + + Load runtime invisible annotations of a field (just skip them). + + IN: + cb........the classbuffer from which the attribute has to be loaded. + f.........the field of which the runtime invisible annotations have + to be loaded. + + RETURN VALUE: + true if all went good. false otherwhise. + +*******************************************************************************/ + +bool annotation_load_field_attribute_runtimeinvisibleannotations( + classbuffer *cb, fieldinfo *f) +{ + return loader_skip_attribute_body(cb); +} + + +/* + * 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: + * vim:noexpandtab:sw=4:ts=4: + */ diff --git a/src/vm/annotation.h b/src/vm/annotation.h deleted file mode 100644 index 2a8b11616..000000000 --- a/src/vm/annotation.h +++ /dev/null @@ -1,93 +0,0 @@ -/* src/vm/annotation.h - class annotations - - Copyright (C) 2006, 2007, 2008 - CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO - - 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. - -*/ - - -#ifndef _ANNOTATION_H -#define _ANNOTATION_H - - -#include "config.h" - -#include "vm/types.h" - -#include "vm/class.hpp" -#include "vm/field.hpp" -#include "vm/global.h" -#include "vm/loader.hpp" -#include "vm/method.hpp" - - -/* function prototypes ********************************************************/ - -#ifdef __cplusplus -extern "C" { -#endif - -bool annotation_load_class_attribute_runtimevisibleannotations( - classbuffer *cb); - -bool annotation_load_class_attribute_runtimeinvisibleannotations( - classbuffer *cb); - -bool annotation_load_method_attribute_runtimevisibleannotations( - classbuffer *cb, methodinfo *m); - -bool annotation_load_method_attribute_runtimeinvisibleannotations( - classbuffer *cb, methodinfo *m); - -bool annotation_load_field_attribute_runtimevisibleannotations( - classbuffer *cb, fieldinfo *f); - -bool annotation_load_field_attribute_runtimeinvisibleannotations( - classbuffer *cb, fieldinfo *f); - -bool annotation_load_method_attribute_annotationdefault( - classbuffer *cb, methodinfo *m); - -bool annotation_load_method_attribute_runtimevisibleparameterannotations( - classbuffer *cb, methodinfo *m); - -bool annotation_load_method_attribute_runtimeinvisibleparameterannotations( - classbuffer *cb, methodinfo *m); - -#ifdef __cplusplus -} -#endif - -#endif /* _ANNOTATION_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: - * vim:noexpandtab:sw=4:ts=4: - */ diff --git a/src/vm/annotation.hpp b/src/vm/annotation.hpp new file mode 100644 index 000000000..3ee896c2b --- /dev/null +++ b/src/vm/annotation.hpp @@ -0,0 +1,93 @@ +/* src/vm/annotation.hpp - class annotations + + Copyright (C) 2006, 2007, 2008 + CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO + + 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. + +*/ + + +#ifndef _ANNOTATION_HPP +#define _ANNOTATION_HPP + + +#include "config.h" + +#include "vm/types.h" + +#include "vm/class.hpp" +#include "vm/field.hpp" +#include "vm/global.h" +#include "vm/loader.hpp" +#include "vm/method.hpp" + + +/* function prototypes ********************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +bool annotation_load_class_attribute_runtimevisibleannotations( + classbuffer *cb); + +bool annotation_load_class_attribute_runtimeinvisibleannotations( + classbuffer *cb); + +bool annotation_load_method_attribute_runtimevisibleannotations( + classbuffer *cb, methodinfo *m); + +bool annotation_load_method_attribute_runtimeinvisibleannotations( + classbuffer *cb, methodinfo *m); + +bool annotation_load_field_attribute_runtimevisibleannotations( + classbuffer *cb, fieldinfo *f); + +bool annotation_load_field_attribute_runtimeinvisibleannotations( + classbuffer *cb, fieldinfo *f); + +bool annotation_load_method_attribute_annotationdefault( + classbuffer *cb, methodinfo *m); + +bool annotation_load_method_attribute_runtimevisibleparameterannotations( + classbuffer *cb, methodinfo *m); + +bool annotation_load_method_attribute_runtimeinvisibleparameterannotations( + classbuffer *cb, methodinfo *m); + +#ifdef __cplusplus +} +#endif + +#endif /* _ANNOTATION_HPP */ + + +/* + * 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: + * vim:noexpandtab:sw=4:ts=4: + */ diff --git a/src/vm/assertion.cpp b/src/vm/assertion.cpp index 7252aa320..ada17e4d0 100644 --- a/src/vm/assertion.cpp +++ b/src/vm/assertion.cpp @@ -29,7 +29,7 @@ #include -#include "mm/memory.h" +#include "mm/memory.hpp" #include "toolbox/list.hpp" diff --git a/src/vm/class.cpp b/src/vm/class.cpp index 0aa5f2123..698356d11 100644 --- a/src/vm/class.cpp +++ b/src/vm/class.cpp @@ -34,14 +34,14 @@ #include "arch.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/llni.h" #include "threads/lock.hpp" #include "threads/mutex.hpp" -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" #include "vm/array.hpp" #include "vm/jit/builtin.hpp" @@ -2117,6 +2117,13 @@ int32_t class_get_modifiers(classinfo *c, bool ignoreInnerClassesAttrib) classref_or_classinfo outer; utf *innername; int i; + int32_t flags; + + /* default to flags of passed class */ + + flags = c->flags; + + /* if requested we check if passed class is inner class */ if (!ignoreInnerClassesAttrib && (c->innerclasscount != 0)) { /* search for passed class as inner class */ @@ -2137,16 +2144,16 @@ int32_t class_get_modifiers(classinfo *c, bool ignoreInnerClassesAttrib) if (outer.any) /* return flags got from the outer class file */ - return c->innerclass[i].flags & ACC_CLASS_REFLECT_MASK; - else - return c->flags & ACC_CLASS_REFLECT_MASK; + flags = c->innerclass[i].flags; + + break; } } } - /* passed class is no inner class or it was not requested */ + /* remove ACC_SUPER bit from flags */ - return c->flags & ACC_CLASS_REFLECT_MASK; + return flags & ~ACC_SUPER & ACC_CLASS_REFLECT_MASK; } diff --git a/src/vm/class.hpp b/src/vm/class.hpp index d1584b1c4..b09bcca47 100644 --- a/src/vm/class.hpp +++ b/src/vm/class.hpp @@ -40,7 +40,7 @@ typedef struct extra_classref extra_classref; #include "vm/types.h" #if defined(ENABLE_JAVASE) -# include "vm/annotation.h" +# include "vm/annotation.hpp" #endif #include "vm/field.hpp" diff --git a/src/vm/classcache.cpp b/src/vm/classcache.cpp index 93db61a9b..f0900e228 100644 --- a/src/vm/classcache.cpp +++ b/src/vm/classcache.cpp @@ -29,13 +29,13 @@ #include "vm/types.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "threads/lock.hpp" #include "threads/mutex.hpp" #include "toolbox/hashtable.h" -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" #include "vm/classcache.hpp" #include "vm/exceptions.hpp" @@ -138,10 +138,6 @@ /* #define CLASSCACHE_VERBOSE */ -#if defined(__cplusplus) -extern "C" { -#endif - /*============================================================================*/ /* STATISTICS */ /*============================================================================*/ @@ -1574,10 +1570,6 @@ dump_it: CLASSCACHE_UNLOCK(); } -#if defined(__cplusplus) -} -#endif - #endif /* NDEBUG */ /* diff --git a/src/vm/descriptor.c b/src/vm/descriptor.c deleted file mode 100644 index 235154e42..000000000 --- a/src/vm/descriptor.c +++ /dev/null @@ -1,1398 +0,0 @@ -/* src/vm/descriptor.c - checking and parsing of field / method descriptors - - Copyright (C) 1996-2005, 2006, 2007, 2008 - CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO - - 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. - -*/ - - -#include "config.h" - -#include - -#include "vm/types.h" - -#include "md-abi.h" - -#include "mm/memory.h" - -#include "vm/descriptor.h" -#include "vm/exceptions.hpp" -#include "vm/options.h" -#include "vm/primitive.hpp" -#include "vm/vm.hpp" - -#include "vm/jit/abi.h" - - -/* constants (private to descriptor.c) ****************************************/ - -/* initial number of entries for the classrefhash of a descriptor_pool */ -/* (currently the hash is never grown!) */ -#define CLASSREFHASH_INIT_SIZE 64 - -/* initial number of entries for the descriptorhash of a descriptor_pool */ -/* (currently the hash is never grown!) */ -#define DESCRIPTORHASH_INIT_SIZE 128 - -/* data structures (private to descriptor.c) **********************************/ - -typedef struct classref_hash_entry classref_hash_entry; -typedef struct descriptor_hash_entry descriptor_hash_entry; - -/* entry struct for the classrefhash of descriptor_pool */ -struct classref_hash_entry { - classref_hash_entry *hashlink; /* for hash chaining */ - utf *name; /* name of the class refered to */ - u2 index; /* index into classref table */ -}; - -/* entry struct for the descriptorhash of descriptor_pool */ -struct descriptor_hash_entry { - descriptor_hash_entry *hashlink; - utf *desc; - parseddesc_t parseddesc; - s2 paramslots; /* number of params, LONG/DOUBLE counted as 2 */ -}; - - -/****************************************************************************/ -/* MACROS FOR DESCRIPTOR PARSING (private to descriptor.c) */ -/****************************************************************************/ - -/* SKIP_FIELDDESCRIPTOR: - * utf_ptr must point to the first character of a field descriptor. - * After the macro call utf_ptr points to the first character after - * the field descriptor. - * - * CAUTION: This macro does not check for an unexpected end of the - * descriptor. Better use SKIP_FIELDDESCRIPTOR_SAFE. - */ -#define SKIP_FIELDDESCRIPTOR(utf_ptr) \ - do { while (*(utf_ptr)=='[') (utf_ptr)++; \ - if (*(utf_ptr)++=='L') \ - while(*(utf_ptr)++ != ';') /* skip */; } while(0) - -/* SKIP_FIELDDESCRIPTOR_SAFE: - * utf_ptr must point to the first character of a field descriptor. - * After the macro call utf_ptr points to the first character after - * the field descriptor. - * - * Input: - * utf_ptr....points to first char of descriptor - * end_ptr....points to first char after the end of the string - * errorflag..must be initialized (to false) by the caller! - * Output: - * utf_ptr....points to first char after the descriptor - * errorflag..set to true if the string ended unexpectedly - */ -#define SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr,end_ptr,errorflag) \ - do { while ((utf_ptr) != (end_ptr) && *(utf_ptr)=='[') (utf_ptr)++; \ - if ((utf_ptr) == (end_ptr)) \ - (errorflag) = true; \ - else \ - if (*(utf_ptr)++=='L') { \ - while((utf_ptr) != (end_ptr) && *(utf_ptr)++ != ';') \ - /* skip */; \ - if ((utf_ptr)[-1] != ';') \ - (errorflag) = true; }} while(0) - - -/****************************************************************************/ -/* DEBUG HELPERS */ -/****************************************************************************/ - -/*#define DESCRIPTOR_VERBOSE*/ - -/****************************************************************************/ -/* FUNCTIONS */ -/****************************************************************************/ - -/* descriptor_to_basic_type **************************************************** - - Return the basic type to use for a value with this descriptor. - - IN: - utf..............descriptor utf string - - OUT: - A TYPE_* constant. - - PRECONDITIONS: - This function assumes that the descriptor has passed - descriptor_pool_add checks and that it does not start with '('. - -*******************************************************************************/ - -int descriptor_to_basic_type(utf *descriptor) -{ - assert(descriptor->blength >= 1); - - switch (descriptor->text[0]) { - case 'Z': - case 'B': - case 'C': - case 'S': - case 'I': - return TYPE_INT; - - case 'J': - return TYPE_LNG; - - case 'F': - return TYPE_FLT; - - case 'D': - return TYPE_DBL; - - case 'L': - case '[': - return TYPE_ADR; - - default: - vm_abort("descriptor_to_basic_type: invalid type %c", - descriptor->text[0]); - } - - /* keep the compiler happy */ - - return 0; -} - - -/* descriptor_typesize ********************************************************* - - Return the size in bytes needed for the given type. - - IN: - td..............typedesc describing the type - - OUT: - The number of bytes - -*******************************************************************************/ - -int descriptor_typesize(typedesc *td) -{ - assert(td); - - switch (td->type) { - case TYPE_INT: - case TYPE_FLT: - return 4; - - case TYPE_LNG: - case TYPE_DBL: - return 8; - - case TYPE_ADR: - return SIZEOF_VOID_P; - - default: - vm_abort("descriptor_typesize: invalid type %d", td->type); - } - - /* keep the compiler happy */ - - return 0; -} - - -/* name_from_descriptor ******************************************************** - - Return the class name indicated by the given descriptor - (Internally used helper function) - - IN: - c................class containing the descriptor - utf_ptr..........first character of descriptor - end_ptr..........first character after the end of the string - mode.............a combination (binary or) of the following flags: - - (Flags marked with * are the default settings.) - - How to handle "V" descriptors: - - * DESCRIPTOR_VOID.....handle it like other primitive types - DESCRIPTOR_NOVOID...treat it as an error - - How to deal with extra characters after the end of the - descriptor: - - * DESCRIPTOR_NOCHECKEND...ignore (useful for parameter lists) - DESCRIPTOR_CHECKEND.....treat them as an error - - OUT: - *next............if non-NULL, *next is set to the first character after - the descriptor. (Undefined if an error occurs.) - *name............set to the utf name of the class - - RETURN VALUE: - true.............descriptor parsed successfully - false............an exception has been thrown - -*******************************************************************************/ - -#define DESCRIPTOR_VOID 0 /* default */ -#define DESCRIPTOR_NOVOID 0x0040 -#define DESCRIPTOR_NOCHECKEND 0 /* default */ -#define DESCRIPTOR_CHECKEND 0x1000 - -static bool -name_from_descriptor(classinfo *c, - char *utf_ptr, char *end_ptr, - char **next, int mode, utf **name) -{ - char *start = utf_ptr; - bool error = false; - - assert(c); - assert(utf_ptr); - assert(end_ptr); - assert(name); - - *name = NULL; - SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr, end_ptr, error); - - if (mode & DESCRIPTOR_CHECKEND) - error |= (utf_ptr != end_ptr); - - if (!error) { - if (next) *next = utf_ptr; - - switch (*start) { - case 'V': - if (mode & DESCRIPTOR_NOVOID) - break; - /* FALLTHROUGH! */ - case 'I': - case 'J': - case 'F': - case 'D': - case 'B': - case 'C': - case 'S': - case 'Z': - return true; - - case 'L': - start++; - utf_ptr--; - /* FALLTHROUGH! */ - case '[': - *name = utf_new(start, utf_ptr - start); - return true; - } - } - - exceptions_throw_classformaterror(c, "Invalid descriptor"); - return false; -} - - -/* descriptor_to_typedesc ****************************************************** - - Parse the given type descriptor and fill a typedesc struct - (Internally used helper function) - - IN: - pool.............the descriptor pool - utf_ptr..........points to first character of type descriptor - end_pos..........points after last character of the whole descriptor - - OUT: - *next............set to next character after type descriptor - *d...............filled with parsed information - - RETURN VALUE: - true.............parsing succeeded - false............an exception has been thrown - -*******************************************************************************/ - -static bool -descriptor_to_typedesc(descriptor_pool *pool, char *utf_ptr, char *end_pos, - char **next, typedesc *td) -{ - utf *name; - - if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, next, 0, &name)) - return false; - - if (name) { - /* a reference type */ - td->type = TYPE_ADR; - td->primitivetype = TYPE_ADR; - td->arraydim = 0; - for (utf_ptr = name->text; *utf_ptr == '['; ++utf_ptr) - td->arraydim++; - td->classref = descriptor_pool_lookup_classref(pool, name); - - } else { - /* a primitive type */ - switch (*utf_ptr) { - case 'B': - td->primitivetype = PRIMITIVETYPE_BYTE; - td->type = TYPE_INT; - break; - case 'C': - td->primitivetype = PRIMITIVETYPE_CHAR; - td->type = TYPE_INT; - break; - case 'S': - td->primitivetype = PRIMITIVETYPE_SHORT; - td->type = TYPE_INT; - break; - case 'Z': - td->primitivetype = PRIMITIVETYPE_BOOLEAN; - td->type = TYPE_INT; - break; - case 'I': - td->primitivetype = PRIMITIVETYPE_INT; - td->type = TYPE_INT; - break; - case 'D': - td->primitivetype = PRIMITIVETYPE_DOUBLE; - td->type = TYPE_DBL; - break; - case 'F': - td->primitivetype = PRIMITIVETYPE_FLOAT; - td->type = TYPE_FLT; - break; - case 'J': - td->primitivetype = PRIMITIVETYPE_LONG; - td->type = TYPE_LNG; - break; - case 'V': - td->primitivetype = PRIMITIVETYPE_VOID; - td->type = TYPE_VOID; - break; - default: - assert(false); - } - - td->arraydim = 0; - td->classref = NULL; - } - - return true; -} - - -/* descriptor_pool_new ********************************************************* - - Allocate a new descriptor_pool - - IN: - referer..........class for which to create the pool - - RETURN VALUE: - a pointer to the new descriptor_pool - -*******************************************************************************/ - -descriptor_pool * -descriptor_pool_new(classinfo *referer) -{ - descriptor_pool *pool; - u4 hashsize; - u4 slot; - - pool = DNEW(descriptor_pool); - assert(pool); - - pool->referer = referer; - pool->fieldcount = 0; - pool->methodcount = 0; - pool->paramcount = 0; - pool->descriptorsize = 0; - pool->descriptors = NULL; - pool->descriptors_next = NULL; - pool->classrefs = NULL; - pool->descriptor_kind = NULL; - pool->descriptor_kind_next = NULL; - - hashsize = CLASSREFHASH_INIT_SIZE; - pool->classrefhash.size = hashsize; - pool->classrefhash.entries = 0; - pool->classrefhash.ptr = DMNEW(void*, hashsize); - for (slot=0; slotclassrefhash.ptr[slot] = NULL; - - hashsize = DESCRIPTORHASH_INIT_SIZE; - pool->descriptorhash.size = hashsize; - pool->descriptorhash.entries = 0; - pool->descriptorhash.ptr = DMNEW(void*, hashsize); - for (slot=0; slotdescriptorhash.ptr[slot] = NULL; - - return pool; -} - - -/* descriptor_pool_add_class *************************************************** - - Add the given class reference to the pool - - IN: - pool.............the descriptor_pool - name.............the class reference to add - - RETURN VALUE: - true.............reference has been added - false............an exception has been thrown - -*******************************************************************************/ - -bool -descriptor_pool_add_class(descriptor_pool *pool, utf *name) -{ - u4 key,slot; - classref_hash_entry *c; - - assert(pool); - assert(name); - -#ifdef DESCRIPTOR_VERBOSE - fprintf(stderr,"descriptor_pool_add_class(%p,",(void*)pool); - utf_fprint_printable_ascii(stderr,name);fprintf(stderr,")\n"); -#endif - - /* find a place in the hashtable */ - - key = utf_hashkey(name->text, name->blength); - slot = key & (pool->classrefhash.size - 1); - c = (classref_hash_entry *) pool->classrefhash.ptr[slot]; - - while (c) { - if (c->name == name) - return true; /* already stored */ - c = c->hashlink; - } - - /* check if the name is a valid classname */ - - if (!is_valid_name(name->text,UTF_END(name))) { - exceptions_throw_classformaterror(pool->referer, "Invalid class name"); - return false; /* exception */ - } - - /* XXX check maximum array dimension */ - - c = DNEW(classref_hash_entry); - c->name = name; - c->index = pool->classrefhash.entries++; - c->hashlink = (classref_hash_entry *) pool->classrefhash.ptr[slot]; - pool->classrefhash.ptr[slot] = c; - - return true; -} - - -/* descriptor_pool_add ********************************************************* - - Check the given descriptor and add it to the pool - - IN: - pool.............the descriptor_pool - desc.............the descriptor to add. Maybe a field or method desc. - - OUT: - *paramslots......if non-NULL, set to the number of parameters. - LONG and DOUBLE are counted twice - - RETURN VALUE: - true.............descriptor has been added - false............an exception has been thrown - -*******************************************************************************/ - -bool -descriptor_pool_add(descriptor_pool *pool, utf *desc, int *paramslots) -{ - u4 key,slot; - descriptor_hash_entry *d; - char *utf_ptr; - char *end_pos; - utf *name; - s4 argcount = 0; - -#ifdef DESCRIPTOR_VERBOSE - fprintf(stderr,"descriptor_pool_add(%p,",(void*)pool); - utf_fprint_printable_ascii(stderr,desc);fprintf(stderr,")\n"); -#endif - - assert(pool); - assert(desc); - - /* find a place in the hashtable */ - - key = utf_hashkey(desc->text, desc->blength); - slot = key & (pool->descriptorhash.size - 1); - d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot]; - - /* Save all method descriptors in the hashtable, since the parsed */ - /* descriptor may vary between differenf methods (static vs. non-static). */ - - utf_ptr = desc->text; - - if (*utf_ptr != '(') { - while (d) { - if (d->desc == desc) { - if (paramslots) - *paramslots = d->paramslots; - return true; /* already stored */ - } - d = d->hashlink; - } - } - - /* add the descriptor to the pool */ - - d = DNEW(descriptor_hash_entry); - d->desc = desc; - d->parseddesc.any = NULL; - d->hashlink = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot]; - pool->descriptorhash.ptr[slot] = d; - - /* now check the descriptor */ - - end_pos = UTF_END(desc); - - if (*utf_ptr == '(') { - /* a method descriptor */ - - pool->methodcount++; - utf_ptr++; - - /* check arguments */ - - while ((utf_ptr != end_pos) && (*utf_ptr != ')')) { - pool->paramcount++; - - /* We cannot count the `this' argument here because - * we don't know if the method is static. */ - - if (*utf_ptr == 'J' || *utf_ptr == 'D') - argcount += 2; - else - argcount++; - - if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, &utf_ptr, - DESCRIPTOR_NOVOID, &name)) - return false; - - if (name) - if (!descriptor_pool_add_class(pool, name)) - return false; - } - - if (utf_ptr == end_pos) { - exceptions_throw_classformaterror(pool->referer, - "Missing ')' in method descriptor"); - return false; - } - - utf_ptr++; /* skip ')' */ - - if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, NULL, - DESCRIPTOR_CHECKEND, &name)) - return false; - - if (name) - if (!descriptor_pool_add_class(pool,name)) - return false; - - if (argcount > 255) { - exceptions_throw_classformaterror(pool->referer, - "Too many arguments in signature"); - return false; - } - - } else { - /* a field descriptor */ - - pool->fieldcount++; - - if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, NULL, - DESCRIPTOR_NOVOID | DESCRIPTOR_CHECKEND, - &name)) - return false; - - if (name) - if (!descriptor_pool_add_class(pool,name)) - return false; - } - - d->paramslots = argcount; - - if (paramslots) - *paramslots = argcount; - - return true; -} - - -/* descriptor_pool_create_classrefs ******************************************** - - Create a table containing all the classrefs which were added to the pool - - IN: - pool.............the descriptor_pool - - OUT: - *count...........if count is non-NULL, this is set to the number - of classrefs in the table - - RETURN VALUE: - a pointer to the constant_classref table - -*******************************************************************************/ - -constant_classref * -descriptor_pool_create_classrefs(descriptor_pool *pool, s4 *count) -{ - u4 nclasses; - u4 slot; - classref_hash_entry *c; - constant_classref *ref; - - assert(pool); - - nclasses = pool->classrefhash.entries; - pool->classrefs = MNEW(constant_classref,nclasses); - - /* fill the constant_classref structs */ - - for (slot = 0; slot < pool->classrefhash.size; ++slot) { - c = (classref_hash_entry *) pool->classrefhash.ptr[slot]; - while (c) { - ref = pool->classrefs + c->index; - CLASSREF_INIT(*ref, pool->referer, c->name); - c = c->hashlink; - } - } - - if (count) - *count = nclasses; - - return pool->classrefs; -} - - -/* descriptor_pool_lookup_classref ********************************************* - - Return the constant_classref for the given class name - - IN: - pool.............the descriptor_pool - classname........name of the class to look up - - RETURN VALUE: - a pointer to the constant_classref, or - NULL if an exception has been thrown - -*******************************************************************************/ - -constant_classref * -descriptor_pool_lookup_classref(descriptor_pool *pool, utf *classname) -{ - u4 key,slot; - classref_hash_entry *c; - - assert(pool); - assert(pool->classrefs); - assert(classname); - - key = utf_hashkey(classname->text, classname->blength); - slot = key & (pool->classrefhash.size - 1); - c = (classref_hash_entry *) pool->classrefhash.ptr[slot]; - - while (c) { - if (c->name == classname) - return pool->classrefs + c->index; - c = c->hashlink; - } - - exceptions_throw_internalerror("Class reference not found in descriptor pool"); - return NULL; -} - - -/* descriptor_pool_alloc_parsed_descriptors ************************************ - - Allocate space for the parsed descriptors - - IN: - pool.............the descriptor_pool - - NOTE: - This function must be called after all descriptors have been added - with descriptor_pool_add. - -*******************************************************************************/ - -void -descriptor_pool_alloc_parsed_descriptors(descriptor_pool *pool) -{ - u4 size; - - assert(pool); - - /* TWISTI: paramcount + 1: we don't know if the method is static or */ - /* not, i have no better solution yet. */ - - size = - pool->fieldcount * sizeof(typedesc) + - pool->methodcount * (sizeof(methoddesc) - sizeof(typedesc)) + - pool->paramcount * sizeof(typedesc) + - pool->methodcount * sizeof(typedesc); /* possible `this' pointer */ - - pool->descriptorsize = size; - if (size) { - pool->descriptors = MNEW(u1, size); - pool->descriptors_next = pool->descriptors; - } - - size = pool->fieldcount + pool->methodcount; - if (size) { - pool->descriptor_kind = DMNEW(u1, size); - pool->descriptor_kind_next = pool->descriptor_kind; - } -} - - -/* descriptor_pool_parse_field_descriptor ************************************** - - Parse the given field descriptor - - IN: - pool.............the descriptor_pool - desc.............the field descriptor - - RETURN VALUE: - a pointer to the parsed field descriptor, or - NULL if an exception has been thrown - - NOTE: - descriptor_pool_alloc_parsed_descriptors must be called (once) - before this function is used. - -*******************************************************************************/ - -typedesc * -descriptor_pool_parse_field_descriptor(descriptor_pool *pool, utf *desc) -{ - u4 key,slot; - descriptor_hash_entry *d; - typedesc *td; - - assert(pool); - assert(pool->descriptors); - assert(pool->descriptors_next); - - /* lookup the descriptor in the hashtable */ - - key = utf_hashkey(desc->text, desc->blength); - slot = key & (pool->descriptorhash.size - 1); - d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot]; - - while (d) { - if (d->desc == desc) { - /* found */ - if (d->parseddesc.fd) - return d->parseddesc.fd; - break; - } - d = d->hashlink; - } - - assert(d); - - if (desc->text[0] == '(') { - exceptions_throw_classformaterror(pool->referer, - "Method descriptor used in field reference"); - return NULL; - } - - td = (typedesc *) pool->descriptors_next; - pool->descriptors_next += sizeof(typedesc); - - if (!descriptor_to_typedesc(pool, desc->text, UTF_END(desc), NULL, td)) - return NULL; - - *(pool->descriptor_kind_next++) = 'f'; - - d->parseddesc.fd = td; - - return td; -} - - -/* descriptor_pool_parse_method_descriptor ************************************* - - Parse the given method descriptor - - IN: - pool.............the descriptor_pool - desc.............the method descriptor - mflags...........the method flags - thisclass........classref to the class containing the method. - This is ignored if mflags contains ACC_STATIC. - The classref is stored for inserting the 'this' argument. - - RETURN VALUE: - a pointer to the parsed method descriptor, or - NULL if an exception has been thrown - - NOTE: - descriptor_pool_alloc_parsed_descriptors must be called - (once) before this function is used. - -*******************************************************************************/ - -methoddesc * -descriptor_pool_parse_method_descriptor(descriptor_pool *pool, utf *desc, - s4 mflags,constant_classref *thisclass) -{ - u4 key, slot; - descriptor_hash_entry *d; - methoddesc *md; - typedesc *td; - char *utf_ptr; - char *end_pos; - s2 paramcount = 0; - s2 paramslots = 0; - -#ifdef DESCRIPTOR_VERBOSE - fprintf(stderr,"descriptor_pool_parse_method_descriptor(%p,%d,%p,", - (void*)pool,(int)mflags,(void*)thisclass); - utf_fprint_printable_ascii(stderr,desc); fprintf(stderr,")\n"); -#endif - - assert(pool); - assert(pool->descriptors); - assert(pool->descriptors_next); - - /* check that it is a method descriptor */ - - if (desc->text[0] != '(') { - exceptions_throw_classformaterror(pool->referer, - "Field descriptor used in method reference"); - return NULL; - } - - /* lookup the descriptor in the hashtable */ - - key = utf_hashkey(desc->text, desc->blength); - slot = key & (pool->descriptorhash.size - 1); - d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot]; - - /* find an un-parsed descriptor */ - - while (d) { - if (d->desc == desc) - if (!d->parseddesc.md) - break; - d = d->hashlink; - } - - assert(d); - - md = (methoddesc *) pool->descriptors_next; - pool->descriptors_next += sizeof(methoddesc) - sizeof(typedesc); - - utf_ptr = desc->text + 1; /* skip '(' */ - end_pos = UTF_END(desc); - - td = md->paramtypes; - - /* count the `this' pointer */ - - if ((mflags != ACC_UNDEF) && !(mflags & ACC_STATIC)) { - td->type = TYPE_ADR; - td->primitivetype = TYPE_ADR; - td->arraydim = 0; - td->classref = thisclass; - - td++; - pool->descriptors_next += sizeof(typedesc); - paramcount++; - paramslots++; - } - - while (*utf_ptr != ')') { - /* parse a parameter type */ - - if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, &utf_ptr, td)) - return NULL; - - if (IS_2_WORD_TYPE(td->type)) - paramslots++; - - td++; - pool->descriptors_next += sizeof(typedesc); - paramcount++; - paramslots++; - } - utf_ptr++; /* skip ')' */ - - /* Skip possible `this' pointer in paramtypes array to allow a possible */ - /* memory move later in parse. */ - /* We store the thisclass reference, so we can later correctly fill in */ - /* the parameter slot of the 'this' argument. */ - - if (mflags == ACC_UNDEF) { - td->classref = thisclass; - td++; - pool->descriptors_next += sizeof(typedesc); - } - - /* parse return type */ - - if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, NULL, - &(md->returntype))) - return NULL; - - md->paramcount = paramcount; - md->paramslots = paramslots; - - /* If mflags != ACC_UNDEF we parse a real loaded method, so do - param prealloc. Otherwise we do this in stack analysis. */ - - if (mflags != ACC_UNDEF) { - if (md->paramcount > 0) { - /* allocate memory for params */ - - md->params = MNEW(paramdesc, md->paramcount); - } - else { - md->params = METHODDESC_NOPARAMS; - } - - /* fill the paramdesc */ - /* md_param_alloc has to be called if md->paramcount == 0, - too, so it can make the reservation for the Linkage Area, - Return Register... */ - -#if defined(ENABLE_JIT) -# if defined(ENABLE_INTRP) - if (!opt_intrp) -# endif - { - /* As builtin-functions are native functions, we have - to pre-allocate for the native ABI. */ - - if (mflags & ACC_METHOD_BUILTIN) - md_param_alloc_native(md); - else - md_param_alloc(md); - } -#endif - } - else { - /* params will be allocated later by - descriptor_params_from_paramtypes if necessary */ - - md->params = NULL; - } - - *(pool->descriptor_kind_next++) = 'm'; - - d->parseddesc.md = md; - - return md; -} - -/* descriptor_params_from_paramtypes ******************************************* - - Create the paramdescs for a method descriptor. This function is called - when we know whether the method is static or not. This function may only - be called once for each methoddesc, and only if md->params == NULL. - - IN: - md...............the parsed method descriptor - md->params MUST be NULL. - mflags...........the ACC_* access flags of the method. Only the - ACC_STATIC bit is checked. - The value ACC_UNDEF is NOT allowed. - - RETURN VALUE: - true.............the paramdescs were created successfully - false............an exception has been thrown - - POSTCONDITION: - md->parms != NULL - -*******************************************************************************/ - -bool descriptor_params_from_paramtypes(methoddesc *md, s4 mflags) -{ - typedesc *td; - - assert(md); - assert(md->params == NULL); - assert(mflags != ACC_UNDEF); - - td = md->paramtypes; - - /* check for `this' pointer */ - - if (!(mflags & ACC_STATIC)) { - constant_classref *thisclass; - - /* fetch class reference from reserved param slot */ - thisclass = td[md->paramcount].classref; - assert(thisclass); - - if (md->paramcount > 0) { - /* shift param types by 1 argument */ - MMOVE(td + 1, td, typedesc, md->paramcount); - } - - /* fill in first argument `this' */ - - td->type = TYPE_ADR; - td->primitivetype = TYPE_ADR; - td->arraydim = 0; - td->classref = thisclass; - - md->paramcount++; - md->paramslots++; - } - - /* if the method has params, process them */ - - if (md->paramcount > 0) { - /* allocate memory for params */ - - md->params = MNEW(paramdesc, md->paramcount); - - } else { - md->params = METHODDESC_NOPARAMS; - } - - /* fill the paramdesc */ - /* md_param_alloc has to be called if md->paramcount == 0, too, so - it can make the reservation for the Linkage Area, Return - Register.. */ - -#if defined(ENABLE_JIT) -# if defined(ENABLE_INTRP) - if (!opt_intrp) -# endif - { - /* As builtin-functions are native functions, we have to - pre-allocate for the native ABI. */ - - if (mflags & ACC_METHOD_BUILTIN) - md_param_alloc_native(md); - else - md_param_alloc(md); - } -#endif - - return true; -} - - -/* descriptor_pool_get_parsed_descriptors ************************************** - - Return a pointer to the block of parsed descriptors - - IN: - pool.............the descriptor_pool - - OUT: - *size............if size is non-NULL, this is set to the size of the - parsed descriptor block (in u1) - - RETURN VALUE: - a pointer to the block of parsed descriptors - - NOTE: - descriptor_pool_alloc_parsed_descriptors must be called (once) - before this function is used. - -*******************************************************************************/ - -void * -descriptor_pool_get_parsed_descriptors(descriptor_pool *pool, s4 *size) -{ - assert(pool); - assert((!pool->fieldcount && !pool->methodcount) || pool->descriptors); - - if (size) - *size = pool->descriptorsize; - - return pool->descriptors; -} - - -/* descriptor_pool_get_sizes *************************************************** - - Get the sizes of the class reference table and the parsed descriptors - - IN: - pool.............the descriptor_pool - - OUT: - *classrefsize....set to size of the class reference table - *descsize........set to size of the parsed descriptors - - NOTE: - This function may only be called after both - descriptor_pool_create_classrefs, and - descriptor_pool_alloc_parsed_descriptors - have been called. - -*******************************************************************************/ - -void -descriptor_pool_get_sizes(descriptor_pool *pool, u4 *classrefsize, u4 *descsize) -{ - assert(pool); - assert((!pool->fieldcount && !pool->methodcount) || pool->descriptors); - assert(pool->classrefs); - assert(classrefsize); - assert(descsize); - - *classrefsize = pool->classrefhash.entries * sizeof(constant_classref); - *descsize = pool->descriptorsize; -} - - -/****************************************************************************/ -/* DEBUG HELPERS */ -/****************************************************************************/ - -#ifndef NDEBUG -/* descriptor_debug_print_typedesc ********************************************* - - Print the given typedesc to the given stream - - IN: - file.............stream to print to - d................the parsed descriptor - -*******************************************************************************/ - -void -descriptor_debug_print_typedesc(FILE *file,typedesc *d) -{ - int ch; - - if (!d) { - fprintf(file,"(typedesc *)NULL"); - return; - } - - if (d->type == TYPE_ADR) { - if (d->classref) - utf_fprint_printable_ascii(file,d->classref->name); - else - fprintf(file,""); - } - else { - switch (d->primitivetype) { - case PRIMITIVETYPE_INT : ch='I'; break; - case PRIMITIVETYPE_CHAR : ch='C'; break; - case PRIMITIVETYPE_BYTE : ch='B'; break; - case PRIMITIVETYPE_SHORT : ch='S'; break; - case PRIMITIVETYPE_BOOLEAN: ch='Z'; break; - case PRIMITIVETYPE_LONG : ch='J'; break; - case PRIMITIVETYPE_FLOAT : ch='F'; break; - case PRIMITIVETYPE_DOUBLE : ch='D'; break; - case PRIMITIVETYPE_VOID : ch='V'; break; - default : ch='!'; - } - fputc(ch,file); - } - if (d->arraydim) - fprintf(file,"[%d]",d->arraydim); -} - -/* descriptor_debug_print_paramdesc ******************************************** - - Print the given paramdesc to the given stream - - IN: - file.............stream to print to - d................the parameter descriptor - -*******************************************************************************/ - -void -descriptor_debug_print_paramdesc(FILE *file,paramdesc *d) -{ - if (!d) { - fprintf(file,"(paramdesc *)NULL"); - return; - } - - if (d->inmemory) { - fprintf(file,"",d->regoff); - } - else { - fprintf(file,"",d->regoff); - } -} - -/* descriptor_debug_print_methoddesc ******************************************* - - Print the given methoddesc to the given stream - - IN: - file.............stream to print to - d................the parsed descriptor - -*******************************************************************************/ - -void -descriptor_debug_print_methoddesc(FILE *file,methoddesc *d) -{ - int i; - - if (!d) { - fprintf(file,"(methoddesc *)NULL"); - return; - } - - fputc('(',file); - for (i=0; iparamcount; ++i) { - if (i) - fputc(',',file); - descriptor_debug_print_typedesc(file,d->paramtypes + i); - if (d->params) { - descriptor_debug_print_paramdesc(file,d->params + i); - } - } - if (d->params == METHODDESC_NOPARAMS) - fputs("",file); - fputc(')',file); - descriptor_debug_print_typedesc(file,&(d->returntype)); -} - -/* descriptor_pool_debug_dump ************************************************** - - Print the state of the descriptor_pool to the given stream - - IN: - pool.............the descriptor_pool - file.............stream to print to - -*******************************************************************************/ - -void -descriptor_pool_debug_dump(descriptor_pool *pool,FILE *file) -{ - u4 slot; - u1 *pos; - u1 *kind; - u4 size; - - fprintf(file,"======[descriptor_pool for "); - utf_fprint_printable_ascii(file,pool->referer->name); - fprintf(file,"]======\n"); - - fprintf(file,"fieldcount: %d\n",pool->fieldcount); - fprintf(file,"methodcount: %d\n",pool->methodcount); - fprintf(file,"paramcount: %d\n",pool->paramcount); - fprintf(file,"classrefcount: %d\n",pool->classrefhash.entries); - fprintf(file,"descriptorsize: %d bytes\n",pool->descriptorsize); - fprintf(file,"classrefsize: %d bytes\n", - (int)(pool->classrefhash.entries * sizeof(constant_classref))); - - fprintf(file,"class references:\n"); - for (slot=0; slotclassrefhash.size; ++slot) { - classref_hash_entry *c = (classref_hash_entry *) pool->classrefhash.ptr[slot]; - while (c) { - fprintf(file," %4d: ",c->index); - utf_fprint_printable_ascii(file,c->name); - fprintf(file,"\n"); - c = c->hashlink; - } - } - - fprintf(file,"hashed descriptors:\n"); - for (slot=0; slotdescriptorhash.size; ++slot) { - descriptor_hash_entry *c = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot]; - while (c) { - fprintf(file," %p: ",c->parseddesc.any); - utf_fprint_printable_ascii(file,c->desc); - fprintf(file,"\n"); - c = c->hashlink; - } - } - - fprintf(file,"descriptors:\n"); - if (pool->descriptors) { - pos = pool->descriptors; - size = pool->descriptors_next - pool->descriptors; - fprintf(file," size: %d bytes\n",size); - - if (pool->descriptor_kind) { - kind = pool->descriptor_kind; - - while (pos < (pool->descriptors + size)) { - fprintf(file," %p: ",pos); - switch (*kind++) { - case 'f': - descriptor_debug_print_typedesc(file,(typedesc*)pos); - pos += sizeof(typedesc); - break; - case 'm': - descriptor_debug_print_methoddesc(file,(methoddesc*)pos); - pos += ((methoddesc*)pos)->paramcount * sizeof(typedesc); - pos += sizeof(methoddesc) - sizeof(typedesc); - break; - default: - fprintf(file,"INVALID KIND"); - } - fputc('\n',file); - } - } - else { - while (size >= sizeof(void*)) { - fprintf(file," %p\n",*((void**)pos)); - pos += sizeof(void*); - size -= sizeof(void*); - } - } - } - - fprintf(file,"==========================================================\n"); -} -#endif /* !defined(NDEBUG) */ - -/* - * 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: - * vim:noexpandtab:sw=4:ts=4: - */ - diff --git a/src/vm/descriptor.cpp b/src/vm/descriptor.cpp new file mode 100644 index 000000000..d8e0e3443 --- /dev/null +++ b/src/vm/descriptor.cpp @@ -0,0 +1,1406 @@ +/* src/vm/descriptor.c - checking and parsing of field / method descriptors + + Copyright (C) 1996-2005, 2006, 2007, 2008 + CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO + + 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. + +*/ + + +#include "config.h" + +#include + +#include "vm/types.h" + +#include "md-abi.h" + +#include "mm/memory.hpp" + +#include "vm/descriptor.hpp" +#include "vm/exceptions.hpp" +#include "vm/options.h" +#include "vm/primitive.hpp" +#include "vm/vm.hpp" + +#include "vm/jit/abi.h" + + +/* constants (private to descriptor.c) ****************************************/ + +/* initial number of entries for the classrefhash of a descriptor_pool */ +/* (currently the hash is never grown!) */ +#define CLASSREFHASH_INIT_SIZE 64 + +/* initial number of entries for the descriptorhash of a descriptor_pool */ +/* (currently the hash is never grown!) */ +#define DESCRIPTORHASH_INIT_SIZE 128 + +/* data structures (private to descriptor.c) **********************************/ + +typedef struct classref_hash_entry classref_hash_entry; +typedef struct descriptor_hash_entry descriptor_hash_entry; + +/* entry struct for the classrefhash of descriptor_pool */ +struct classref_hash_entry { + classref_hash_entry *hashlink; /* for hash chaining */ + utf *name; /* name of the class refered to */ + u2 index; /* index into classref table */ +}; + +/* entry struct for the descriptorhash of descriptor_pool */ +struct descriptor_hash_entry { + descriptor_hash_entry *hashlink; + utf *desc; + parseddesc_t parseddesc; + s2 paramslots; /* number of params, LONG/DOUBLE counted as 2 */ +}; + + +/****************************************************************************/ +/* MACROS FOR DESCRIPTOR PARSING (private to descriptor.c) */ +/****************************************************************************/ + +/* SKIP_FIELDDESCRIPTOR: + * utf_ptr must point to the first character of a field descriptor. + * After the macro call utf_ptr points to the first character after + * the field descriptor. + * + * CAUTION: This macro does not check for an unexpected end of the + * descriptor. Better use SKIP_FIELDDESCRIPTOR_SAFE. + */ +#define SKIP_FIELDDESCRIPTOR(utf_ptr) \ + do { while (*(utf_ptr)=='[') (utf_ptr)++; \ + if (*(utf_ptr)++=='L') \ + while(*(utf_ptr)++ != ';') /* skip */; } while(0) + +/* SKIP_FIELDDESCRIPTOR_SAFE: + * utf_ptr must point to the first character of a field descriptor. + * After the macro call utf_ptr points to the first character after + * the field descriptor. + * + * Input: + * utf_ptr....points to first char of descriptor + * end_ptr....points to first char after the end of the string + * errorflag..must be initialized (to false) by the caller! + * Output: + * utf_ptr....points to first char after the descriptor + * errorflag..set to true if the string ended unexpectedly + */ +#define SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr,end_ptr,errorflag) \ + do { while ((utf_ptr) != (end_ptr) && *(utf_ptr)=='[') (utf_ptr)++; \ + if ((utf_ptr) == (end_ptr)) \ + (errorflag) = true; \ + else \ + if (*(utf_ptr)++=='L') { \ + while((utf_ptr) != (end_ptr) && *(utf_ptr)++ != ';') \ + /* skip */; \ + if ((utf_ptr)[-1] != ';') \ + (errorflag) = true; }} while(0) + + +#if defined(__cplusplus) +extern "C" { +#endif + +/****************************************************************************/ +/* DEBUG HELPERS */ +/****************************************************************************/ + +/*#define DESCRIPTOR_VERBOSE*/ + +/****************************************************************************/ +/* FUNCTIONS */ +/****************************************************************************/ + +/* descriptor_to_basic_type **************************************************** + + Return the basic type to use for a value with this descriptor. + + IN: + utf..............descriptor utf string + + OUT: + A TYPE_* constant. + + PRECONDITIONS: + This function assumes that the descriptor has passed + descriptor_pool_add checks and that it does not start with '('. + +*******************************************************************************/ + +int descriptor_to_basic_type(utf *descriptor) +{ + assert(descriptor->blength >= 1); + + switch (descriptor->text[0]) { + case 'Z': + case 'B': + case 'C': + case 'S': + case 'I': + return TYPE_INT; + + case 'J': + return TYPE_LNG; + + case 'F': + return TYPE_FLT; + + case 'D': + return TYPE_DBL; + + case 'L': + case '[': + return TYPE_ADR; + + default: + vm_abort("descriptor_to_basic_type: invalid type %c", + descriptor->text[0]); + } + + /* keep the compiler happy */ + + return 0; +} + + +/* descriptor_typesize ********************************************************* + + Return the size in bytes needed for the given type. + + IN: + td..............typedesc describing the type + + OUT: + The number of bytes + +*******************************************************************************/ + +int descriptor_typesize(typedesc *td) +{ + assert(td); + + switch (td->type) { + case TYPE_INT: + case TYPE_FLT: + return 4; + + case TYPE_LNG: + case TYPE_DBL: + return 8; + + case TYPE_ADR: + return SIZEOF_VOID_P; + + default: + vm_abort("descriptor_typesize: invalid type %d", td->type); + } + + /* keep the compiler happy */ + + return 0; +} + + +/* name_from_descriptor ******************************************************** + + Return the class name indicated by the given descriptor + (Internally used helper function) + + IN: + c................class containing the descriptor + utf_ptr..........first character of descriptor + end_ptr..........first character after the end of the string + mode.............a combination (binary or) of the following flags: + + (Flags marked with * are the default settings.) + + How to handle "V" descriptors: + + * DESCRIPTOR_VOID.....handle it like other primitive types + DESCRIPTOR_NOVOID...treat it as an error + + How to deal with extra characters after the end of the + descriptor: + + * DESCRIPTOR_NOCHECKEND...ignore (useful for parameter lists) + DESCRIPTOR_CHECKEND.....treat them as an error + + OUT: + *next............if non-NULL, *next is set to the first character after + the descriptor. (Undefined if an error occurs.) + *name............set to the utf name of the class + + RETURN VALUE: + true.............descriptor parsed successfully + false............an exception has been thrown + +*******************************************************************************/ + +#define DESCRIPTOR_VOID 0 /* default */ +#define DESCRIPTOR_NOVOID 0x0040 +#define DESCRIPTOR_NOCHECKEND 0 /* default */ +#define DESCRIPTOR_CHECKEND 0x1000 + +static bool +name_from_descriptor(classinfo *c, + char *utf_ptr, char *end_ptr, + char **next, int mode, utf **name) +{ + char *start = utf_ptr; + bool error = false; + + assert(c); + assert(utf_ptr); + assert(end_ptr); + assert(name); + + *name = NULL; + SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr, end_ptr, error); + + if (mode & DESCRIPTOR_CHECKEND) + error |= (utf_ptr != end_ptr); + + if (!error) { + if (next) *next = utf_ptr; + + switch (*start) { + case 'V': + if (mode & DESCRIPTOR_NOVOID) + break; + /* FALLTHROUGH! */ + case 'I': + case 'J': + case 'F': + case 'D': + case 'B': + case 'C': + case 'S': + case 'Z': + return true; + + case 'L': + start++; + utf_ptr--; + /* FALLTHROUGH! */ + case '[': + *name = utf_new(start, utf_ptr - start); + return true; + } + } + + exceptions_throw_classformaterror(c, "Invalid descriptor"); + return false; +} + + +/* descriptor_to_typedesc ****************************************************** + + Parse the given type descriptor and fill a typedesc struct + (Internally used helper function) + + IN: + pool.............the descriptor pool + utf_ptr..........points to first character of type descriptor + end_pos..........points after last character of the whole descriptor + + OUT: + *next............set to next character after type descriptor + *d...............filled with parsed information + + RETURN VALUE: + true.............parsing succeeded + false............an exception has been thrown + +*******************************************************************************/ + +static bool +descriptor_to_typedesc(descriptor_pool *pool, char *utf_ptr, char *end_pos, + char **next, typedesc *td) +{ + utf *name; + + if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, next, 0, &name)) + return false; + + if (name) { + /* a reference type */ + td->type = TYPE_ADR; + td->primitivetype = TYPE_ADR; + td->arraydim = 0; + for (utf_ptr = name->text; *utf_ptr == '['; ++utf_ptr) + td->arraydim++; + td->classref = descriptor_pool_lookup_classref(pool, name); + + } else { + /* a primitive type */ + switch (*utf_ptr) { + case 'B': + td->primitivetype = PRIMITIVETYPE_BYTE; + td->type = TYPE_INT; + break; + case 'C': + td->primitivetype = PRIMITIVETYPE_CHAR; + td->type = TYPE_INT; + break; + case 'S': + td->primitivetype = PRIMITIVETYPE_SHORT; + td->type = TYPE_INT; + break; + case 'Z': + td->primitivetype = PRIMITIVETYPE_BOOLEAN; + td->type = TYPE_INT; + break; + case 'I': + td->primitivetype = PRIMITIVETYPE_INT; + td->type = TYPE_INT; + break; + case 'D': + td->primitivetype = PRIMITIVETYPE_DOUBLE; + td->type = TYPE_DBL; + break; + case 'F': + td->primitivetype = PRIMITIVETYPE_FLOAT; + td->type = TYPE_FLT; + break; + case 'J': + td->primitivetype = PRIMITIVETYPE_LONG; + td->type = TYPE_LNG; + break; + case 'V': + td->primitivetype = PRIMITIVETYPE_VOID; + td->type = TYPE_VOID; + break; + default: + assert(false); + } + + td->arraydim = 0; + td->classref = NULL; + } + + return true; +} + + +/* descriptor_pool_new ********************************************************* + + Allocate a new descriptor_pool + + IN: + referer..........class for which to create the pool + + RETURN VALUE: + a pointer to the new descriptor_pool + +*******************************************************************************/ + +descriptor_pool * +descriptor_pool_new(classinfo *referer) +{ + descriptor_pool *pool; + u4 hashsize; + u4 slot; + + pool = (descriptor_pool*) DumpMemory::allocate(sizeof(descriptor_pool)); + assert(pool); + + pool->referer = referer; + pool->fieldcount = 0; + pool->methodcount = 0; + pool->paramcount = 0; + pool->descriptorsize = 0; + pool->descriptors = NULL; + pool->descriptors_next = NULL; + pool->classrefs = NULL; + pool->descriptor_kind = NULL; + pool->descriptor_kind_next = NULL; + + hashsize = CLASSREFHASH_INIT_SIZE; + pool->classrefhash.size = hashsize; + pool->classrefhash.entries = 0; + pool->classrefhash.ptr = (void **) DumpMemory::allocate(sizeof(void*) * hashsize); + for (slot=0; slotclassrefhash.ptr[slot] = NULL; + + hashsize = DESCRIPTORHASH_INIT_SIZE; + pool->descriptorhash.size = hashsize; + pool->descriptorhash.entries = 0; + pool->descriptorhash.ptr = (void**) DumpMemory::allocate(sizeof(void*) * hashsize); + for (slot=0; slotdescriptorhash.ptr[slot] = NULL; + + return pool; +} + + +/* descriptor_pool_add_class *************************************************** + + Add the given class reference to the pool + + IN: + pool.............the descriptor_pool + name.............the class reference to add + + RETURN VALUE: + true.............reference has been added + false............an exception has been thrown + +*******************************************************************************/ + +bool +descriptor_pool_add_class(descriptor_pool *pool, utf *name) +{ + u4 key,slot; + classref_hash_entry *c; + + assert(pool); + assert(name); + +#ifdef DESCRIPTOR_VERBOSE + fprintf(stderr,"descriptor_pool_add_class(%p,",(void*)pool); + utf_fprint_printable_ascii(stderr,name);fprintf(stderr,")\n"); +#endif + + /* find a place in the hashtable */ + + key = utf_hashkey(name->text, name->blength); + slot = key & (pool->classrefhash.size - 1); + c = (classref_hash_entry *) pool->classrefhash.ptr[slot]; + + while (c) { + if (c->name == name) + return true; /* already stored */ + c = c->hashlink; + } + + /* check if the name is a valid classname */ + + if (!is_valid_name(name->text,UTF_END(name))) { + exceptions_throw_classformaterror(pool->referer, "Invalid class name"); + return false; /* exception */ + } + + /* XXX check maximum array dimension */ + + c = (classref_hash_entry*) DumpMemory::allocate(sizeof(classref_hash_entry)); + c->name = name; + c->index = pool->classrefhash.entries++; + c->hashlink = (classref_hash_entry *) pool->classrefhash.ptr[slot]; + pool->classrefhash.ptr[slot] = c; + + return true; +} + + +/* descriptor_pool_add ********************************************************* + + Check the given descriptor and add it to the pool + + IN: + pool.............the descriptor_pool + desc.............the descriptor to add. Maybe a field or method desc. + + OUT: + *paramslots......if non-NULL, set to the number of parameters. + LONG and DOUBLE are counted twice + + RETURN VALUE: + true.............descriptor has been added + false............an exception has been thrown + +*******************************************************************************/ + +bool +descriptor_pool_add(descriptor_pool *pool, utf *desc, int *paramslots) +{ + u4 key,slot; + descriptor_hash_entry *d; + char *utf_ptr; + char *end_pos; + utf *name; + s4 argcount = 0; + +#ifdef DESCRIPTOR_VERBOSE + fprintf(stderr,"descriptor_pool_add(%p,",(void*)pool); + utf_fprint_printable_ascii(stderr,desc);fprintf(stderr,")\n"); +#endif + + assert(pool); + assert(desc); + + /* find a place in the hashtable */ + + key = utf_hashkey(desc->text, desc->blength); + slot = key & (pool->descriptorhash.size - 1); + d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot]; + + /* Save all method descriptors in the hashtable, since the parsed */ + /* descriptor may vary between differenf methods (static vs. non-static). */ + + utf_ptr = desc->text; + + if (*utf_ptr != '(') { + while (d) { + if (d->desc == desc) { + if (paramslots) + *paramslots = d->paramslots; + return true; /* already stored */ + } + d = d->hashlink; + } + } + + /* add the descriptor to the pool */ + + d = (descriptor_hash_entry*) DumpMemory::allocate(sizeof(descriptor_hash_entry)); + d->desc = desc; + d->parseddesc.any = NULL; + d->hashlink = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot]; + pool->descriptorhash.ptr[slot] = d; + + /* now check the descriptor */ + + end_pos = UTF_END(desc); + + if (*utf_ptr == '(') { + /* a method descriptor */ + + pool->methodcount++; + utf_ptr++; + + /* check arguments */ + + while ((utf_ptr != end_pos) && (*utf_ptr != ')')) { + pool->paramcount++; + + /* We cannot count the `this' argument here because + * we don't know if the method is static. */ + + if (*utf_ptr == 'J' || *utf_ptr == 'D') + argcount += 2; + else + argcount++; + + if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, &utf_ptr, + DESCRIPTOR_NOVOID, &name)) + return false; + + if (name) + if (!descriptor_pool_add_class(pool, name)) + return false; + } + + if (utf_ptr == end_pos) { + exceptions_throw_classformaterror(pool->referer, + "Missing ')' in method descriptor"); + return false; + } + + utf_ptr++; /* skip ')' */ + + if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, NULL, + DESCRIPTOR_CHECKEND, &name)) + return false; + + if (name) + if (!descriptor_pool_add_class(pool,name)) + return false; + + if (argcount > 255) { + exceptions_throw_classformaterror(pool->referer, + "Too many arguments in signature"); + return false; + } + + } else { + /* a field descriptor */ + + pool->fieldcount++; + + if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, NULL, + DESCRIPTOR_NOVOID | DESCRIPTOR_CHECKEND, + &name)) + return false; + + if (name) + if (!descriptor_pool_add_class(pool,name)) + return false; + } + + d->paramslots = argcount; + + if (paramslots) + *paramslots = argcount; + + return true; +} + + +/* descriptor_pool_create_classrefs ******************************************** + + Create a table containing all the classrefs which were added to the pool + + IN: + pool.............the descriptor_pool + + OUT: + *count...........if count is non-NULL, this is set to the number + of classrefs in the table + + RETURN VALUE: + a pointer to the constant_classref table + +*******************************************************************************/ + +constant_classref * +descriptor_pool_create_classrefs(descriptor_pool *pool, s4 *count) +{ + u4 nclasses; + u4 slot; + classref_hash_entry *c; + constant_classref *ref; + + assert(pool); + + nclasses = pool->classrefhash.entries; + pool->classrefs = MNEW(constant_classref,nclasses); + + /* fill the constant_classref structs */ + + for (slot = 0; slot < pool->classrefhash.size; ++slot) { + c = (classref_hash_entry *) pool->classrefhash.ptr[slot]; + while (c) { + ref = pool->classrefs + c->index; + CLASSREF_INIT(*ref, pool->referer, c->name); + c = c->hashlink; + } + } + + if (count) + *count = nclasses; + + return pool->classrefs; +} + + +/* descriptor_pool_lookup_classref ********************************************* + + Return the constant_classref for the given class name + + IN: + pool.............the descriptor_pool + classname........name of the class to look up + + RETURN VALUE: + a pointer to the constant_classref, or + NULL if an exception has been thrown + +*******************************************************************************/ + +constant_classref * +descriptor_pool_lookup_classref(descriptor_pool *pool, utf *classname) +{ + u4 key,slot; + classref_hash_entry *c; + + assert(pool); + assert(pool->classrefs); + assert(classname); + + key = utf_hashkey(classname->text, classname->blength); + slot = key & (pool->classrefhash.size - 1); + c = (classref_hash_entry *) pool->classrefhash.ptr[slot]; + + while (c) { + if (c->name == classname) + return pool->classrefs + c->index; + c = c->hashlink; + } + + exceptions_throw_internalerror("Class reference not found in descriptor pool"); + return NULL; +} + + +/* descriptor_pool_alloc_parsed_descriptors ************************************ + + Allocate space for the parsed descriptors + + IN: + pool.............the descriptor_pool + + NOTE: + This function must be called after all descriptors have been added + with descriptor_pool_add. + +*******************************************************************************/ + +void +descriptor_pool_alloc_parsed_descriptors(descriptor_pool *pool) +{ + u4 size; + + assert(pool); + + /* TWISTI: paramcount + 1: we don't know if the method is static or */ + /* not, i have no better solution yet. */ + + size = + pool->fieldcount * sizeof(typedesc) + + pool->methodcount * (sizeof(methoddesc) - sizeof(typedesc)) + + pool->paramcount * sizeof(typedesc) + + pool->methodcount * sizeof(typedesc); /* possible `this' pointer */ + + pool->descriptorsize = size; + if (size) { + pool->descriptors = MNEW(u1, size); + pool->descriptors_next = pool->descriptors; + } + + size = pool->fieldcount + pool->methodcount; + if (size) { + pool->descriptor_kind = (u1*) DumpMemory::allocate(sizeof(u1) * size); + pool->descriptor_kind_next = pool->descriptor_kind; + } +} + + +/* descriptor_pool_parse_field_descriptor ************************************** + + Parse the given field descriptor + + IN: + pool.............the descriptor_pool + desc.............the field descriptor + + RETURN VALUE: + a pointer to the parsed field descriptor, or + NULL if an exception has been thrown + + NOTE: + descriptor_pool_alloc_parsed_descriptors must be called (once) + before this function is used. + +*******************************************************************************/ + +typedesc * +descriptor_pool_parse_field_descriptor(descriptor_pool *pool, utf *desc) +{ + u4 key,slot; + descriptor_hash_entry *d; + typedesc *td; + + assert(pool); + assert(pool->descriptors); + assert(pool->descriptors_next); + + /* lookup the descriptor in the hashtable */ + + key = utf_hashkey(desc->text, desc->blength); + slot = key & (pool->descriptorhash.size - 1); + d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot]; + + while (d) { + if (d->desc == desc) { + /* found */ + if (d->parseddesc.fd) + return d->parseddesc.fd; + break; + } + d = d->hashlink; + } + + assert(d); + + if (desc->text[0] == '(') { + exceptions_throw_classformaterror(pool->referer, + "Method descriptor used in field reference"); + return NULL; + } + + td = (typedesc *) pool->descriptors_next; + pool->descriptors_next += sizeof(typedesc); + + if (!descriptor_to_typedesc(pool, desc->text, UTF_END(desc), NULL, td)) + return NULL; + + *(pool->descriptor_kind_next++) = 'f'; + + d->parseddesc.fd = td; + + return td; +} + + +/* descriptor_pool_parse_method_descriptor ************************************* + + Parse the given method descriptor + + IN: + pool.............the descriptor_pool + desc.............the method descriptor + mflags...........the method flags + thisclass........classref to the class containing the method. + This is ignored if mflags contains ACC_STATIC. + The classref is stored for inserting the 'this' argument. + + RETURN VALUE: + a pointer to the parsed method descriptor, or + NULL if an exception has been thrown + + NOTE: + descriptor_pool_alloc_parsed_descriptors must be called + (once) before this function is used. + +*******************************************************************************/ + +methoddesc * +descriptor_pool_parse_method_descriptor(descriptor_pool *pool, utf *desc, + s4 mflags,constant_classref *thisclass) +{ + u4 key, slot; + descriptor_hash_entry *d; + methoddesc *md; + typedesc *td; + char *utf_ptr; + char *end_pos; + s2 paramcount = 0; + s2 paramslots = 0; + +#ifdef DESCRIPTOR_VERBOSE + fprintf(stderr,"descriptor_pool_parse_method_descriptor(%p,%d,%p,", + (void*)pool,(int)mflags,(void*)thisclass); + utf_fprint_printable_ascii(stderr,desc); fprintf(stderr,")\n"); +#endif + + assert(pool); + assert(pool->descriptors); + assert(pool->descriptors_next); + + /* check that it is a method descriptor */ + + if (desc->text[0] != '(') { + exceptions_throw_classformaterror(pool->referer, + "Field descriptor used in method reference"); + return NULL; + } + + /* lookup the descriptor in the hashtable */ + + key = utf_hashkey(desc->text, desc->blength); + slot = key & (pool->descriptorhash.size - 1); + d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot]; + + /* find an un-parsed descriptor */ + + while (d) { + if (d->desc == desc) + if (!d->parseddesc.md) + break; + d = d->hashlink; + } + + assert(d); + + md = (methoddesc *) pool->descriptors_next; + pool->descriptors_next += sizeof(methoddesc) - sizeof(typedesc); + + utf_ptr = desc->text + 1; /* skip '(' */ + end_pos = UTF_END(desc); + + td = md->paramtypes; + + /* count the `this' pointer */ + + if ((mflags != ACC_UNDEF) && !(mflags & ACC_STATIC)) { + td->type = TYPE_ADR; + td->primitivetype = TYPE_ADR; + td->arraydim = 0; + td->classref = thisclass; + + td++; + pool->descriptors_next += sizeof(typedesc); + paramcount++; + paramslots++; + } + + while (*utf_ptr != ')') { + /* parse a parameter type */ + + if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, &utf_ptr, td)) + return NULL; + + if (IS_2_WORD_TYPE(td->type)) + paramslots++; + + td++; + pool->descriptors_next += sizeof(typedesc); + paramcount++; + paramslots++; + } + utf_ptr++; /* skip ')' */ + + /* Skip possible `this' pointer in paramtypes array to allow a possible */ + /* memory move later in parse. */ + /* We store the thisclass reference, so we can later correctly fill in */ + /* the parameter slot of the 'this' argument. */ + + if (mflags == ACC_UNDEF) { + td->classref = thisclass; + td++; + pool->descriptors_next += sizeof(typedesc); + } + + /* parse return type */ + + if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, NULL, + &(md->returntype))) + return NULL; + + md->paramcount = paramcount; + md->paramslots = paramslots; + + /* If mflags != ACC_UNDEF we parse a real loaded method, so do + param prealloc. Otherwise we do this in stack analysis. */ + + if (mflags != ACC_UNDEF) { + if (md->paramcount > 0) { + /* allocate memory for params */ + + md->params = MNEW(paramdesc, md->paramcount); + } + else { + md->params = METHODDESC_NOPARAMS; + } + + /* fill the paramdesc */ + /* md_param_alloc has to be called if md->paramcount == 0, + too, so it can make the reservation for the Linkage Area, + Return Register... */ + +#if defined(ENABLE_JIT) +# if defined(ENABLE_INTRP) + if (!opt_intrp) +# endif + { + /* As builtin-functions are native functions, we have + to pre-allocate for the native ABI. */ + + if (mflags & ACC_METHOD_BUILTIN) + md_param_alloc_native(md); + else + md_param_alloc(md); + } +#endif + } + else { + /* params will be allocated later by + descriptor_params_from_paramtypes if necessary */ + + md->params = NULL; + } + + *(pool->descriptor_kind_next++) = 'm'; + + d->parseddesc.md = md; + + return md; +} + +/* descriptor_params_from_paramtypes ******************************************* + + Create the paramdescs for a method descriptor. This function is called + when we know whether the method is static or not. This function may only + be called once for each methoddesc, and only if md->params == NULL. + + IN: + md...............the parsed method descriptor + md->params MUST be NULL. + mflags...........the ACC_* access flags of the method. Only the + ACC_STATIC bit is checked. + The value ACC_UNDEF is NOT allowed. + + RETURN VALUE: + true.............the paramdescs were created successfully + false............an exception has been thrown + + POSTCONDITION: + md->parms != NULL + +*******************************************************************************/ + +bool descriptor_params_from_paramtypes(methoddesc *md, s4 mflags) +{ + typedesc *td; + + assert(md); + assert(md->params == NULL); + assert(mflags != ACC_UNDEF); + + td = md->paramtypes; + + /* check for `this' pointer */ + + if (!(mflags & ACC_STATIC)) { + constant_classref *thisclass; + + /* fetch class reference from reserved param slot */ + thisclass = td[md->paramcount].classref; + assert(thisclass); + + if (md->paramcount > 0) { + /* shift param types by 1 argument */ + MMOVE(td + 1, td, typedesc, md->paramcount); + } + + /* fill in first argument `this' */ + + td->type = TYPE_ADR; + td->primitivetype = TYPE_ADR; + td->arraydim = 0; + td->classref = thisclass; + + md->paramcount++; + md->paramslots++; + } + + /* if the method has params, process them */ + + if (md->paramcount > 0) { + /* allocate memory for params */ + + md->params = MNEW(paramdesc, md->paramcount); + + } else { + md->params = METHODDESC_NOPARAMS; + } + + /* fill the paramdesc */ + /* md_param_alloc has to be called if md->paramcount == 0, too, so + it can make the reservation for the Linkage Area, Return + Register.. */ + +#if defined(ENABLE_JIT) +# if defined(ENABLE_INTRP) + if (!opt_intrp) +# endif + { + /* As builtin-functions are native functions, we have to + pre-allocate for the native ABI. */ + + if (mflags & ACC_METHOD_BUILTIN) + md_param_alloc_native(md); + else + md_param_alloc(md); + } +#endif + + return true; +} + + +/* descriptor_pool_get_parsed_descriptors ************************************** + + Return a pointer to the block of parsed descriptors + + IN: + pool.............the descriptor_pool + + OUT: + *size............if size is non-NULL, this is set to the size of the + parsed descriptor block (in u1) + + RETURN VALUE: + a pointer to the block of parsed descriptors + + NOTE: + descriptor_pool_alloc_parsed_descriptors must be called (once) + before this function is used. + +*******************************************************************************/ + +void * +descriptor_pool_get_parsed_descriptors(descriptor_pool *pool, s4 *size) +{ + assert(pool); + assert((!pool->fieldcount && !pool->methodcount) || pool->descriptors); + + if (size) + *size = pool->descriptorsize; + + return pool->descriptors; +} + + +/* descriptor_pool_get_sizes *************************************************** + + Get the sizes of the class reference table and the parsed descriptors + + IN: + pool.............the descriptor_pool + + OUT: + *classrefsize....set to size of the class reference table + *descsize........set to size of the parsed descriptors + + NOTE: + This function may only be called after both + descriptor_pool_create_classrefs, and + descriptor_pool_alloc_parsed_descriptors + have been called. + +*******************************************************************************/ + +void +descriptor_pool_get_sizes(descriptor_pool *pool, u4 *classrefsize, u4 *descsize) +{ + assert(pool); + assert((!pool->fieldcount && !pool->methodcount) || pool->descriptors); + assert(pool->classrefs); + assert(classrefsize); + assert(descsize); + + *classrefsize = pool->classrefhash.entries * sizeof(constant_classref); + *descsize = pool->descriptorsize; +} + + +/****************************************************************************/ +/* DEBUG HELPERS */ +/****************************************************************************/ + +#ifndef NDEBUG +/* descriptor_debug_print_typedesc ********************************************* + + Print the given typedesc to the given stream + + IN: + file.............stream to print to + d................the parsed descriptor + +*******************************************************************************/ + +void +descriptor_debug_print_typedesc(FILE *file,typedesc *d) +{ + int ch; + + if (!d) { + fprintf(file,"(typedesc *)NULL"); + return; + } + + if (d->type == TYPE_ADR) { + if (d->classref) + utf_fprint_printable_ascii(file,d->classref->name); + else + fprintf(file,""); + } + else { + switch (d->primitivetype) { + case PRIMITIVETYPE_INT : ch='I'; break; + case PRIMITIVETYPE_CHAR : ch='C'; break; + case PRIMITIVETYPE_BYTE : ch='B'; break; + case PRIMITIVETYPE_SHORT : ch='S'; break; + case PRIMITIVETYPE_BOOLEAN: ch='Z'; break; + case PRIMITIVETYPE_LONG : ch='J'; break; + case PRIMITIVETYPE_FLOAT : ch='F'; break; + case PRIMITIVETYPE_DOUBLE : ch='D'; break; + case PRIMITIVETYPE_VOID : ch='V'; break; + default : ch='!'; + } + fputc(ch,file); + } + if (d->arraydim) + fprintf(file,"[%d]",d->arraydim); +} + +/* descriptor_debug_print_paramdesc ******************************************** + + Print the given paramdesc to the given stream + + IN: + file.............stream to print to + d................the parameter descriptor + +*******************************************************************************/ + +void +descriptor_debug_print_paramdesc(FILE *file,paramdesc *d) +{ + if (!d) { + fprintf(file,"(paramdesc *)NULL"); + return; + } + + if (d->inmemory) { + fprintf(file,"",d->regoff); + } + else { + fprintf(file,"",d->regoff); + } +} + +/* descriptor_debug_print_methoddesc ******************************************* + + Print the given methoddesc to the given stream + + IN: + file.............stream to print to + d................the parsed descriptor + +*******************************************************************************/ + +void +descriptor_debug_print_methoddesc(FILE *file,methoddesc *d) +{ + int i; + + if (!d) { + fprintf(file,"(methoddesc *)NULL"); + return; + } + + fputc('(',file); + for (i=0; iparamcount; ++i) { + if (i) + fputc(',',file); + descriptor_debug_print_typedesc(file,d->paramtypes + i); + if (d->params) { + descriptor_debug_print_paramdesc(file,d->params + i); + } + } + if (d->params == METHODDESC_NOPARAMS) + fputs("",file); + fputc(')',file); + descriptor_debug_print_typedesc(file,&(d->returntype)); +} + +/* descriptor_pool_debug_dump ************************************************** + + Print the state of the descriptor_pool to the given stream + + IN: + pool.............the descriptor_pool + file.............stream to print to + +*******************************************************************************/ + +void +descriptor_pool_debug_dump(descriptor_pool *pool,FILE *file) +{ + u4 slot; + u1 *pos; + u1 *kind; + u4 size; + + fprintf(file,"======[descriptor_pool for "); + utf_fprint_printable_ascii(file,pool->referer->name); + fprintf(file,"]======\n"); + + fprintf(file,"fieldcount: %d\n",pool->fieldcount); + fprintf(file,"methodcount: %d\n",pool->methodcount); + fprintf(file,"paramcount: %d\n",pool->paramcount); + fprintf(file,"classrefcount: %d\n",pool->classrefhash.entries); + fprintf(file,"descriptorsize: %d bytes\n",pool->descriptorsize); + fprintf(file,"classrefsize: %d bytes\n", + (int)(pool->classrefhash.entries * sizeof(constant_classref))); + + fprintf(file,"class references:\n"); + for (slot=0; slotclassrefhash.size; ++slot) { + classref_hash_entry *c = (classref_hash_entry *) pool->classrefhash.ptr[slot]; + while (c) { + fprintf(file," %4d: ",c->index); + utf_fprint_printable_ascii(file,c->name); + fprintf(file,"\n"); + c = c->hashlink; + } + } + + fprintf(file,"hashed descriptors:\n"); + for (slot=0; slotdescriptorhash.size; ++slot) { + descriptor_hash_entry *c = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot]; + while (c) { + fprintf(file," %p: ",c->parseddesc.any); + utf_fprint_printable_ascii(file,c->desc); + fprintf(file,"\n"); + c = c->hashlink; + } + } + + fprintf(file,"descriptors:\n"); + if (pool->descriptors) { + pos = pool->descriptors; + size = pool->descriptors_next - pool->descriptors; + fprintf(file," size: %d bytes\n",size); + + if (pool->descriptor_kind) { + kind = pool->descriptor_kind; + + while (pos < (pool->descriptors + size)) { + fprintf(file," %p: ",pos); + switch (*kind++) { + case 'f': + descriptor_debug_print_typedesc(file,(typedesc*)pos); + pos += sizeof(typedesc); + break; + case 'm': + descriptor_debug_print_methoddesc(file,(methoddesc*)pos); + pos += ((methoddesc*)pos)->paramcount * sizeof(typedesc); + pos += sizeof(methoddesc) - sizeof(typedesc); + break; + default: + fprintf(file,"INVALID KIND"); + } + fputc('\n',file); + } + } + else { + while (size >= sizeof(void*)) { + fprintf(file," %p\n",*((void**)pos)); + pos += sizeof(void*); + size -= sizeof(void*); + } + } + } + + fprintf(file,"==========================================================\n"); +} +#endif /* !defined(NDEBUG) */ + +#if defined(__cplusplus) +} +#endif + +/* + * 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: + * vim:noexpandtab:sw=4:ts=4: + */ + diff --git a/src/vm/descriptor.h b/src/vm/descriptor.h deleted file mode 100644 index bf6c69efb..000000000 --- a/src/vm/descriptor.h +++ /dev/null @@ -1,208 +0,0 @@ -/* src/vm/descriptor.h - checking and parsing of field / method descriptors - - Copyright (C) 1996-2005, 2006, 2007, 2008 - CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO - - 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. - -*/ - - -#ifndef _DESCRIPTOR_H -#define _DESCRIPTOR_H - -/* forward typedefs ***********************************************************/ - -typedef struct descriptor_pool descriptor_pool; -typedef struct typedesc typedesc; -typedef struct paramdesc paramdesc; -typedef struct methoddesc methoddesc; - - -#include "config.h" - -#include - -#include "vm/types.h" - -#include "toolbox/hashtable.h" - -#include "vm/class.hpp" -#include "vm/global.h" -#include "vm/method.hpp" -#include "vm/references.h" -#include "vm/utf8.h" - -#include "arch.h" /* needed for HAS_ADDRESS_REGISTER_FILE */ - - -/* data structures ************************************************************/ - -/*----------------------------------------------------------------------------*/ -/* Descriptor Pools */ -/* */ -/* A descriptor_pool is a temporary data structure used during loading of */ -/* a class. The descriptor_pool is used to allocate the table of */ -/* constant_classrefs the class uses, and for parsing the field and method */ -/* descriptors which occurr within the class. The inner workings of */ -/* descriptor_pool are not important for outside code. */ -/* */ -/* You use a descriptor_pool as follows: */ -/* */ -/* 1. create one with descriptor_pool_new */ -/* 2. add all explicit class references with descriptor_pool_add_class */ -/* 3. add all field/method descriptors with descriptor_pool_add */ -/* 4. call descriptor_pool_create_classrefs */ -/* You can now lookup classrefs with descriptor_pool_lookup_classref */ -/* 5. call descriptor_pool_alloc_parsed_descriptors */ -/* 6. for each field descriptor call descriptor_pool_parse_field_descriptor */ -/* for each method descriptor call descriptor_pool_parse_method_descriptor */ -/* 7. call descriptor_pool_get_parsed_descriptors */ -/* */ -/* IMPORTANT: The descriptor_pool functions use DNEW and DMNEW for allocating */ -/* memory which can be thrown away when the steps above have been */ -/* done. */ -/*----------------------------------------------------------------------------*/ - -struct descriptor_pool { - classinfo *referer; - u4 fieldcount; - u4 methodcount; - u4 paramcount; - u4 descriptorsize; - u1 *descriptors; - u1 *descriptors_next; - hashtable descriptorhash; - constant_classref *classrefs; - hashtable classrefhash; - u1 *descriptor_kind; /* useful for debugging */ - u1 *descriptor_kind_next; /* useful for debugging */ -}; - - -/* data structures for parsed field/method descriptors ************************/ - -struct typedesc { - constant_classref *classref; /* class reference for TYPE_ADR types */ - u1 type; /* TYPE_??? constant [1] */ - u1 primitivetype; /* (PRIMITIVE)TYPE_??? constant [2] */ - u1 arraydim; /* array dimension (0 if no array) */ -}; - -/* [1]...the type field contains the basic type used within the VM. So ints, */ -/* shorts, chars, bytes, booleans all have TYPE_INT. */ -/* [2]...the primitivetype field contains the declared type. */ -/* So short is PRIMITIVETYPE_SHORT, char is PRIMITIVETYPE_CHAR. */ -/* For non-primitive types primitivetype is TYPE_ADR. */ - -struct paramdesc { -#if defined(__MIPS__) - u1 type; /* TYPE_??? of the register allocated */ -#endif - bool inmemory; /* argument in register or on stack */ - uint32_t index; /* index into argument register array */ - uint32_t regoff; /* register index or stack offset */ -}; - -struct methoddesc { - s2 paramcount; /* number of parameters */ - s2 paramslots; /* like above but LONG,DOUBLE count twice */ - s4 argintreguse; /* number of used integer argument registers */ - s4 argfltreguse; /* number of used float argument registers */ -#if defined(HAS_ADDRESS_REGISTER_FILE) - s4 argadrreguse; /* number of used address registers */ -#endif - s4 memuse; /* number of stack slots used */ - paramdesc *params; /* allocated parameter descriptions [3] */ - typedesc returntype; /* parsed descriptor of the return type */ - typedesc paramtypes[1]; /* parameter types, variable length! */ -}; - -/* [3]...If params is NULL, the parameter descriptions have not yet been */ -/* allocated. In this case ___the possible 'this' pointer of the method */ -/* is NOT counted in paramcount/paramslots and it is NOT included in */ -/* the paramtypes array___. */ -/* If params != NULL, the parameter descriptions have been */ -/* allocated, and the 'this' pointer of the method, if any, IS included.*/ -/* In case the method has no parameters at all, the special value */ -/* METHODDESC_NO_PARAMS is used (see below). */ - -/* METHODDESC_NO_PARAMS is a special value for the methoddesc.params field */ -/* indicating that the method is a static method without any parameters. */ -/* This special value must be != NULL and it may only be set if */ -/* md->paramcount == 0. */ - -#define METHODDESC_NOPARAMS ((paramdesc*)1) - -/* function prototypes ********************************************************/ - -#ifdef __cplusplus -extern "C" { -#endif - -descriptor_pool * descriptor_pool_new(classinfo *referer); - -bool descriptor_pool_add_class(descriptor_pool *pool,utf *name); -bool descriptor_pool_add(descriptor_pool *pool,utf *desc,int *paramslots); - -int descriptor_to_basic_type(utf *desc); -int descriptor_typesize(typedesc *td); - -constant_classref * descriptor_pool_create_classrefs(descriptor_pool *pool, - s4 *count); -constant_classref * descriptor_pool_lookup_classref(descriptor_pool *pool,utf *classname); - -void descriptor_pool_alloc_parsed_descriptors(descriptor_pool *pool); - -typedesc *descriptor_pool_parse_field_descriptor(descriptor_pool *pool, utf *desc); -methoddesc *descriptor_pool_parse_method_descriptor(descriptor_pool *pool, utf *desc, s4 mflags, - constant_classref *thisclass); - -bool descriptor_params_from_paramtypes(methoddesc *md, s4 mflags); - -void *descriptor_pool_get_parsed_descriptors(descriptor_pool *pool, s4 *size); -void descriptor_pool_get_sizes(descriptor_pool *pool, u4 *classrefsize, - u4 *descsize); - -#ifndef NDEBUG -void descriptor_debug_print_typedesc(FILE *file,typedesc *d); -void descriptor_debug_print_methoddesc(FILE *file,methoddesc *d); -void descriptor_debug_print_paramdesc(FILE *file,paramdesc *d); -void descriptor_pool_debug_dump(descriptor_pool *pool, FILE *file); -#endif /* !defined(NDEBUG) */ - -#ifdef __cplusplus -} -#endif - -#endif /* _DESCRIPTOR_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: - * vim:noexpandtab:sw=4:ts=4: - */ diff --git a/src/vm/descriptor.hpp b/src/vm/descriptor.hpp new file mode 100644 index 000000000..bf6c69efb --- /dev/null +++ b/src/vm/descriptor.hpp @@ -0,0 +1,208 @@ +/* src/vm/descriptor.h - checking and parsing of field / method descriptors + + Copyright (C) 1996-2005, 2006, 2007, 2008 + CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO + + 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. + +*/ + + +#ifndef _DESCRIPTOR_H +#define _DESCRIPTOR_H + +/* forward typedefs ***********************************************************/ + +typedef struct descriptor_pool descriptor_pool; +typedef struct typedesc typedesc; +typedef struct paramdesc paramdesc; +typedef struct methoddesc methoddesc; + + +#include "config.h" + +#include + +#include "vm/types.h" + +#include "toolbox/hashtable.h" + +#include "vm/class.hpp" +#include "vm/global.h" +#include "vm/method.hpp" +#include "vm/references.h" +#include "vm/utf8.h" + +#include "arch.h" /* needed for HAS_ADDRESS_REGISTER_FILE */ + + +/* data structures ************************************************************/ + +/*----------------------------------------------------------------------------*/ +/* Descriptor Pools */ +/* */ +/* A descriptor_pool is a temporary data structure used during loading of */ +/* a class. The descriptor_pool is used to allocate the table of */ +/* constant_classrefs the class uses, and for parsing the field and method */ +/* descriptors which occurr within the class. The inner workings of */ +/* descriptor_pool are not important for outside code. */ +/* */ +/* You use a descriptor_pool as follows: */ +/* */ +/* 1. create one with descriptor_pool_new */ +/* 2. add all explicit class references with descriptor_pool_add_class */ +/* 3. add all field/method descriptors with descriptor_pool_add */ +/* 4. call descriptor_pool_create_classrefs */ +/* You can now lookup classrefs with descriptor_pool_lookup_classref */ +/* 5. call descriptor_pool_alloc_parsed_descriptors */ +/* 6. for each field descriptor call descriptor_pool_parse_field_descriptor */ +/* for each method descriptor call descriptor_pool_parse_method_descriptor */ +/* 7. call descriptor_pool_get_parsed_descriptors */ +/* */ +/* IMPORTANT: The descriptor_pool functions use DNEW and DMNEW for allocating */ +/* memory which can be thrown away when the steps above have been */ +/* done. */ +/*----------------------------------------------------------------------------*/ + +struct descriptor_pool { + classinfo *referer; + u4 fieldcount; + u4 methodcount; + u4 paramcount; + u4 descriptorsize; + u1 *descriptors; + u1 *descriptors_next; + hashtable descriptorhash; + constant_classref *classrefs; + hashtable classrefhash; + u1 *descriptor_kind; /* useful for debugging */ + u1 *descriptor_kind_next; /* useful for debugging */ +}; + + +/* data structures for parsed field/method descriptors ************************/ + +struct typedesc { + constant_classref *classref; /* class reference for TYPE_ADR types */ + u1 type; /* TYPE_??? constant [1] */ + u1 primitivetype; /* (PRIMITIVE)TYPE_??? constant [2] */ + u1 arraydim; /* array dimension (0 if no array) */ +}; + +/* [1]...the type field contains the basic type used within the VM. So ints, */ +/* shorts, chars, bytes, booleans all have TYPE_INT. */ +/* [2]...the primitivetype field contains the declared type. */ +/* So short is PRIMITIVETYPE_SHORT, char is PRIMITIVETYPE_CHAR. */ +/* For non-primitive types primitivetype is TYPE_ADR. */ + +struct paramdesc { +#if defined(__MIPS__) + u1 type; /* TYPE_??? of the register allocated */ +#endif + bool inmemory; /* argument in register or on stack */ + uint32_t index; /* index into argument register array */ + uint32_t regoff; /* register index or stack offset */ +}; + +struct methoddesc { + s2 paramcount; /* number of parameters */ + s2 paramslots; /* like above but LONG,DOUBLE count twice */ + s4 argintreguse; /* number of used integer argument registers */ + s4 argfltreguse; /* number of used float argument registers */ +#if defined(HAS_ADDRESS_REGISTER_FILE) + s4 argadrreguse; /* number of used address registers */ +#endif + s4 memuse; /* number of stack slots used */ + paramdesc *params; /* allocated parameter descriptions [3] */ + typedesc returntype; /* parsed descriptor of the return type */ + typedesc paramtypes[1]; /* parameter types, variable length! */ +}; + +/* [3]...If params is NULL, the parameter descriptions have not yet been */ +/* allocated. In this case ___the possible 'this' pointer of the method */ +/* is NOT counted in paramcount/paramslots and it is NOT included in */ +/* the paramtypes array___. */ +/* If params != NULL, the parameter descriptions have been */ +/* allocated, and the 'this' pointer of the method, if any, IS included.*/ +/* In case the method has no parameters at all, the special value */ +/* METHODDESC_NO_PARAMS is used (see below). */ + +/* METHODDESC_NO_PARAMS is a special value for the methoddesc.params field */ +/* indicating that the method is a static method without any parameters. */ +/* This special value must be != NULL and it may only be set if */ +/* md->paramcount == 0. */ + +#define METHODDESC_NOPARAMS ((paramdesc*)1) + +/* function prototypes ********************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +descriptor_pool * descriptor_pool_new(classinfo *referer); + +bool descriptor_pool_add_class(descriptor_pool *pool,utf *name); +bool descriptor_pool_add(descriptor_pool *pool,utf *desc,int *paramslots); + +int descriptor_to_basic_type(utf *desc); +int descriptor_typesize(typedesc *td); + +constant_classref * descriptor_pool_create_classrefs(descriptor_pool *pool, + s4 *count); +constant_classref * descriptor_pool_lookup_classref(descriptor_pool *pool,utf *classname); + +void descriptor_pool_alloc_parsed_descriptors(descriptor_pool *pool); + +typedesc *descriptor_pool_parse_field_descriptor(descriptor_pool *pool, utf *desc); +methoddesc *descriptor_pool_parse_method_descriptor(descriptor_pool *pool, utf *desc, s4 mflags, + constant_classref *thisclass); + +bool descriptor_params_from_paramtypes(methoddesc *md, s4 mflags); + +void *descriptor_pool_get_parsed_descriptors(descriptor_pool *pool, s4 *size); +void descriptor_pool_get_sizes(descriptor_pool *pool, u4 *classrefsize, + u4 *descsize); + +#ifndef NDEBUG +void descriptor_debug_print_typedesc(FILE *file,typedesc *d); +void descriptor_debug_print_methoddesc(FILE *file,methoddesc *d); +void descriptor_debug_print_paramdesc(FILE *file,paramdesc *d); +void descriptor_pool_debug_dump(descriptor_pool *pool, FILE *file); +#endif /* !defined(NDEBUG) */ + +#ifdef __cplusplus +} +#endif + +#endif /* _DESCRIPTOR_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: + * vim:noexpandtab:sw=4:ts=4: + */ diff --git a/src/vm/exceptions.cpp b/src/vm/exceptions.cpp index 5f01f221e..332fca04b 100644 --- a/src/vm/exceptions.cpp +++ b/src/vm/exceptions.cpp @@ -35,7 +35,7 @@ #include "md-abi.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/llni.h" #include "native/native.hpp" diff --git a/src/vm/field.cpp b/src/vm/field.cpp index 987217cff..6b6b4ed43 100644 --- a/src/vm/field.cpp +++ b/src/vm/field.cpp @@ -29,17 +29,17 @@ #include #include -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/llni.h" #include "vm/types.h" -#include "vm/annotation.h" +#include "vm/annotation.hpp" #include "vm/array.hpp" #include "vm/jit/builtin.hpp" #include "vm/class.hpp" -#include "vm/descriptor.h" +#include "vm/descriptor.hpp" #include "vm/exceptions.hpp" #include "vm/field.hpp" #include "vm/global.h" diff --git a/src/vm/field.hpp b/src/vm/field.hpp index a25d09e3b..2bb538290 100644 --- a/src/vm/field.hpp +++ b/src/vm/field.hpp @@ -34,7 +34,7 @@ typedef struct fieldinfo fieldinfo; #include "config.h" #include "vm/types.h" -#include "vm/descriptor.h" +#include "vm/descriptor.hpp" #include "vm/class.hpp" #include "vm/global.h" #include "vm/loader.hpp" diff --git a/src/vm/finalizer.c b/src/vm/finalizer.c deleted file mode 100644 index ea331ec96..000000000 --- a/src/vm/finalizer.c +++ /dev/null @@ -1,234 +0,0 @@ -/* src/vm/finalizer.c - finalizer linked list and thread - - Copyright (C) 1996-2005, 2006, 2007, 2008 - CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO - - 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. - -*/ - - -#include "config.h" - -#include - -#include "vm/types.h" - -#include "mm/memory.h" - -#include "threads/condition.hpp" -#include "threads/mutex.hpp" -#include "threads/thread.hpp" - -#include "vm/jit/builtin.hpp" -#include "vm/exceptions.hpp" -#include "vm/global.h" -#include "vm/options.h" -#include "vm/vm.hpp" - -#include "vm/jit/asmpart.h" - - -/* global variables ***********************************************************/ - -#if defined(ENABLE_THREADS) -static Mutex *finalizer_thread_mutex; -static Condition *finalizer_thread_cond; -#endif - - -/* finalizer_init ************************************************************** - - Initializes the finalizer global lock and the linked list. - -*******************************************************************************/ - -bool finalizer_init(void) -{ - TRACESUBSYSTEMINITIALIZATION("finalizer_init"); - -#if defined(ENABLE_THREADS) - finalizer_thread_mutex = Mutex_new(); - finalizer_thread_cond = Condition_new(); -#endif - - /* everything's ok */ - - return true; -} - - -/* finalizer_thread ************************************************************ - - This thread waits on an object for a notification and the runs the - finalizers (finalizer thread). This is necessary because of a - possible deadlock in the GC. - -*******************************************************************************/ - -#if defined(ENABLE_THREADS) -static void finalizer_thread(void) -{ - while (true) { - /* get the lock on the finalizer mutex, so we can call wait */ - - Mutex_lock(finalizer_thread_mutex); - - /* wait forever on that condition till we are signaled */ - - Condition_wait(finalizer_thread_cond, finalizer_thread_mutex); - - /* leave the lock */ - - Mutex_unlock(finalizer_thread_mutex); - -#if !defined(NDEBUG) - if (opt_DebugFinalizer) - log_println("[finalizer thread : status=awake]"); -#endif - - /* and call the finalizers */ - - gc_invoke_finalizers(); - -#if !defined(NDEBUG) - if (opt_DebugFinalizer) - log_println("[finalizer thread : status=sleeping]"); -#endif - } -} -#endif - - -/* finalizer_start_thread ****************************************************** - - Starts the finalizer thread. - -*******************************************************************************/ - -#if defined(ENABLE_THREADS) -bool finalizer_start_thread(void) -{ - utf *name; - - name = utf_new_char("Finalizer"); - - if (!threads_thread_start_internal(name, finalizer_thread)) - return false; - - /* everything's ok */ - - return true; -} -#endif - - -/* finalizer_notify ************************************************************ - - Notifies the finalizer thread that it should run the - gc_invoke_finalizers from the GC. - -*******************************************************************************/ - -void finalizer_notify(void) -{ -#if !defined(NDEBUG) - if (opt_DebugFinalizer) - log_println("[finalizer notified]"); -#endif - -#if defined(ENABLE_THREADS) - /* get the lock on the finalizer lock object, so we can call wait */ - - Mutex_lock(finalizer_thread_mutex); - - /* signal the finalizer thread */ - - Condition_signal(finalizer_thread_cond); - - /* leave the lock */ - - Mutex_unlock(finalizer_thread_mutex); -#else - /* if we don't have threads, just run the finalizers */ - - gc_invoke_finalizers(); -#endif -} - - -/* finalizer_run *************************************************************** - - Actually run the finalizer functions. - -*******************************************************************************/ - -void finalizer_run(void *o, void *p) -{ - java_handle_t *h; - classinfo *c; - - h = (java_handle_t *) o; - -#if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES) - /* XXX this is only a dirty hack to make Boehm work with handles */ - - h = LLNI_WRAP((java_object_t *) h); -#endif - - LLNI_class_get(h, c); - -#if !defined(NDEBUG) - if (opt_DebugFinalizer) { - log_start(); - log_print("[finalizer running : o=%p p=%p class=", o, p); - class_print(c); - log_print("]"); - log_finish(); - } -#endif - - /* call the finalizer function */ - - (void) vm_call_method(c->finalizer, h); - -#if !defined(NDEBUG) - if (opt_DebugFinalizer && (exceptions_get_exception() != NULL)) { - log_println("[finalizer exception]"); - exceptions_print_stacktrace(); - } -#endif - - /* if we had an exception in the finalizer, ignore it */ - - exceptions_clear_exception(); -} - - -/* - * 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/finalizer.cpp b/src/vm/finalizer.cpp new file mode 100644 index 000000000..cd14c484e --- /dev/null +++ b/src/vm/finalizer.cpp @@ -0,0 +1,240 @@ +/* src/vm/finalizer.c - finalizer linked list and thread + + Copyright (C) 1996-2005, 2006, 2007, 2008 + CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO + + 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. + +*/ + + +#include "config.h" + +#include + +#include "vm/types.h" + +#include "mm/memory.hpp" + +#include "threads/condition.hpp" +#include "threads/mutex.hpp" +#include "threads/thread.hpp" + +#include "vm/jit/builtin.hpp" +#include "vm/exceptions.hpp" +#include "vm/global.h" +#include "vm/options.h" +#include "vm/vm.hpp" + +#include "vm/jit/asmpart.h" + + +/* global variables ***********************************************************/ + +#if defined(ENABLE_THREADS) +static Mutex *finalizer_thread_mutex; +static Condition *finalizer_thread_cond; +#endif + +#if defined(__cplusplus) +extern "C" { +#endif + +/* finalizer_init ************************************************************** + + Initializes the finalizer global lock and the linked list. + +*******************************************************************************/ + +bool finalizer_init(void) +{ + TRACESUBSYSTEMINITIALIZATION("finalizer_init"); + +#if defined(ENABLE_THREADS) + finalizer_thread_mutex = new Mutex(); + finalizer_thread_cond = new Condition(); +#endif + + /* everything's ok */ + + return true; +} + + +/* finalizer_thread ************************************************************ + + This thread waits on an object for a notification and the runs the + finalizers (finalizer thread). This is necessary because of a + possible deadlock in the GC. + +*******************************************************************************/ + +#if defined(ENABLE_THREADS) +static void finalizer_thread(void) +{ + while (true) { + /* get the lock on the finalizer mutex, so we can call wait */ + + finalizer_thread_mutex->lock(); + + /* wait forever on that condition till we are signaled */ + + finalizer_thread_cond->wait(finalizer_thread_mutex); + + /* leave the lock */ + + finalizer_thread_mutex->unlock(); + +#if !defined(NDEBUG) + if (opt_DebugFinalizer) + log_println("[finalizer thread : status=awake]"); +#endif + + /* and call the finalizers */ + + gc_invoke_finalizers(); + +#if !defined(NDEBUG) + if (opt_DebugFinalizer) + log_println("[finalizer thread : status=sleeping]"); +#endif + } +} +#endif + + +/* finalizer_start_thread ****************************************************** + + Starts the finalizer thread. + +*******************************************************************************/ + +#if defined(ENABLE_THREADS) +bool finalizer_start_thread(void) +{ + utf *name; + + name = utf_new_char("Finalizer"); + + if (!threads_thread_start_internal(name, finalizer_thread)) + return false; + + /* everything's ok */ + + return true; +} +#endif + + +/* finalizer_notify ************************************************************ + + Notifies the finalizer thread that it should run the + gc_invoke_finalizers from the GC. + +*******************************************************************************/ + +void finalizer_notify(void) +{ +#if !defined(NDEBUG) + if (opt_DebugFinalizer) + log_println("[finalizer notified]"); +#endif + +#if defined(ENABLE_THREADS) + /* get the lock on the finalizer lock object, so we can call wait */ + + finalizer_thread_mutex->lock(); + + /* signal the finalizer thread */ + + finalizer_thread_cond->signal(); + + /* leave the lock */ + + finalizer_thread_mutex->unlock(); +#else + /* if we don't have threads, just run the finalizers */ + + gc_invoke_finalizers(); +#endif +} + + +/* finalizer_run *************************************************************** + + Actually run the finalizer functions. + +*******************************************************************************/ + +void finalizer_run(void *o, void *p) +{ + java_handle_t *h; + classinfo *c; + + h = (java_handle_t *) o; + +#if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES) + /* XXX this is only a dirty hack to make Boehm work with handles */ + + h = LLNI_WRAP((java_object_t *) h); +#endif + + LLNI_class_get(h, c); + +#if !defined(NDEBUG) + if (opt_DebugFinalizer) { + log_start(); + log_print("[finalizer running : o=%p p=%p class=", o, p); + class_print(c); + log_print("]"); + log_finish(); + } +#endif + + /* call the finalizer function */ + + (void) vm_call_method(c->finalizer, h); + +#if !defined(NDEBUG) + if (opt_DebugFinalizer && (exceptions_get_exception() != NULL)) { + log_println("[finalizer exception]"); + exceptions_print_stacktrace(); + } +#endif + + /* if we had an exception in the finalizer, ignore it */ + + exceptions_clear_exception(); +} + +#if defined(__cplusplus) +} +#endif + +/* + * 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/finalizer.h b/src/vm/finalizer.h deleted file mode 100644 index 04abf9ed0..000000000 --- a/src/vm/finalizer.h +++ /dev/null @@ -1,65 +0,0 @@ -/* src/vm/finalizer.h - finalizer linked list and thread header - - Copyright (C) 1996-2005, 2006, 2008 - CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO - - 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. - -*/ - - -#ifndef _FINALIZER_H -#define _FINALIZER_H - -#include "config.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#include "vm/types.h" - -#include "vm/global.h" - - -/* function prototypes ********************************************************/ - -bool finalizer_init(void); -bool finalizer_start_thread(void); -void finalizer_notify(void); -void finalizer_run(void *o, void *p); - -#ifdef __cplusplus -} -#endif - -#endif /* _FINALIZER_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: - */ diff --git a/src/vm/finalizer.hpp b/src/vm/finalizer.hpp new file mode 100644 index 000000000..04abf9ed0 --- /dev/null +++ b/src/vm/finalizer.hpp @@ -0,0 +1,65 @@ +/* src/vm/finalizer.h - finalizer linked list and thread header + + Copyright (C) 1996-2005, 2006, 2008 + CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO + + 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. + +*/ + + +#ifndef _FINALIZER_H +#define _FINALIZER_H + +#include "config.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#include "vm/types.h" + +#include "vm/global.h" + + +/* function prototypes ********************************************************/ + +bool finalizer_init(void); +bool finalizer_start_thread(void); +void finalizer_notify(void); +void finalizer_run(void *o, void *p); + +#ifdef __cplusplus +} +#endif + +#endif /* _FINALIZER_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: + */ diff --git a/src/vm/javaobjects.hpp b/src/vm/javaobjects.hpp index f53021823..285e23572 100644 --- a/src/vm/javaobjects.hpp +++ b/src/vm/javaobjects.hpp @@ -29,7 +29,7 @@ #include -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/llni.h" @@ -1969,8 +1969,9 @@ public: inline java_handle_t* get_uncaughtExceptionHandler() const; // Setters. - inline void set_priority(int32_t value); - inline void set_group (java_handle_t* value); + inline void set_priority (int32_t value); + inline void set_group (java_handle_t* value); + inline void set_threadStatus(int32_t value); }; @@ -2005,6 +2006,11 @@ inline void java_lang_Thread::set_group(java_handle_t* value) set(_handle, offset_group, value); } +inline void java_lang_Thread::set_threadStatus(int32_t value) +{ + set(_handle, offset_threadStatus, value); +} + /** diff --git a/src/vm/jit/allocator/liveness.c b/src/vm/jit/allocator/liveness.c index de94a0f44..8e7486887 100644 --- a/src/vm/jit/allocator/liveness.c +++ b/src/vm/jit/allocator/liveness.c @@ -30,9 +30,9 @@ #include "vm/types.h" -#include "mm/memory.h" +#include "mm/memory.hpp" -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" #include "toolbox/worklist.h" #include "vm/jit/builtin.hpp" diff --git a/src/vm/jit/allocator/lsra.c b/src/vm/jit/allocator/lsra.c index bfe0e1666..c5e1ad299 100644 --- a/src/vm/jit/allocator/lsra.c +++ b/src/vm/jit/allocator/lsra.c @@ -35,9 +35,9 @@ #include "vm/types.h" -#include "mm/memory.h" +#include "mm/memory.hpp" -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" #include "vm/jit/builtin.hpp" #include "vm/exceptions.hpp" diff --git a/src/vm/jit/allocator/simplereg.c b/src/vm/jit/allocator/simplereg.c index f852229bf..f3390ba04 100644 --- a/src/vm/jit/allocator/simplereg.c +++ b/src/vm/jit/allocator/simplereg.c @@ -33,7 +33,7 @@ #include "arch.h" #include "md-abi.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "vm/jit/builtin.hpp" #include "vm/exceptions.hpp" diff --git a/src/vm/jit/alpha/codegen.c b/src/vm/jit/alpha/codegen.c index b136fd4dc..a49b1a0af 100644 --- a/src/vm/jit/alpha/codegen.c +++ b/src/vm/jit/alpha/codegen.c @@ -36,7 +36,7 @@ #include "vm/jit/alpha/arch.h" #include "vm/jit/alpha/codegen.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/localref.hpp" #include "native/native.hpp" diff --git a/src/vm/jit/alpha/emit.c b/src/vm/jit/alpha/emit.c index 8bf59e90e..96fb6f0be 100644 --- a/src/vm/jit/alpha/emit.c +++ b/src/vm/jit/alpha/emit.c @@ -33,7 +33,7 @@ #include "vm/jit/alpha/codegen.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "threads/lock.hpp" diff --git a/src/vm/jit/alpha/freebsd/md-os.c b/src/vm/jit/alpha/freebsd/md-os.c index e60626f3f..3d9169da8 100644 --- a/src/vm/jit/alpha/freebsd/md-os.c +++ b/src/vm/jit/alpha/freebsd/md-os.c @@ -35,7 +35,7 @@ #include "vm/jit/alpha/md-abi.h" #include "vm/global.h" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/jit/asmpart.h" diff --git a/src/vm/jit/alpha/linux/md-os.c b/src/vm/jit/alpha/linux/md-os.c index 8e127a9fa..1fe5e8086 100644 --- a/src/vm/jit/alpha/linux/md-os.c +++ b/src/vm/jit/alpha/linux/md-os.c @@ -39,7 +39,7 @@ #include "threads/thread.hpp" #include "vm/jit/builtin.hpp" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/os.hpp" #include "vm/jit/asmpart.h" diff --git a/src/vm/jit/alpha/md-abi.c b/src/vm/jit/alpha/md-abi.c index 496834761..c968be986 100644 --- a/src/vm/jit/alpha/md-abi.c +++ b/src/vm/jit/alpha/md-abi.c @@ -28,7 +28,7 @@ #include "vm/jit/alpha/md-abi.h" -#include "vm/descriptor.h" +#include "vm/descriptor.hpp" #include "vm/global.h" #include "vm/jit/abi.h" diff --git a/src/vm/jit/alpha/patcher.c b/src/vm/jit/alpha/patcher.c index 6d3c5fdf4..2e0aeaa95 100644 --- a/src/vm/jit/alpha/patcher.c +++ b/src/vm/jit/alpha/patcher.c @@ -31,7 +31,7 @@ #include "vm/jit/alpha/md.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/native.hpp" diff --git a/src/vm/jit/argument.cpp b/src/vm/jit/argument.cpp index a670883d6..5ee7ca6d5 100644 --- a/src/vm/jit/argument.cpp +++ b/src/vm/jit/argument.cpp @@ -30,12 +30,12 @@ #include "arch.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/llni.h" #include "vm/array.hpp" -#include "vm/descriptor.h" +#include "vm/descriptor.hpp" #include "vm/global.h" #include "vm/method.hpp" #include "vm/primitive.hpp" diff --git a/src/vm/jit/arm/codegen.c b/src/vm/jit/arm/codegen.c index 4b86e510f..a0085a806 100644 --- a/src/vm/jit/arm/codegen.c +++ b/src/vm/jit/arm/codegen.c @@ -35,7 +35,7 @@ #include "vm/jit/arm/arch.h" #include "vm/jit/arm/codegen.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/localref.hpp" #include "native/native.hpp" @@ -2296,21 +2296,33 @@ bool codegen_emit(jitdata *jd) case ICMD_INVOKEVIRTUAL: if (lm == NULL) { - patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0); + int32_t disp = dseg_add_unique_s4(cd, 0); + patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, disp); - s1 = 0; - } - else - s1 = OFFSET(vftbl_t, table[0]) + - sizeof(methodptr) * lm->vftblindex; + // The following instruction MUST NOT change a0 because of the implicit NPE check. + M_LDR_INTERN(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl)); - /* implicit null-pointer check */ - M_LDR_INTERN(REG_METHODPTR, REG_A0, - OFFSET(java_object_t, vftbl)); - M_LDR_INTERN(REG_PV, REG_METHODPTR, s1); + // Sanity check. + assert(REG_ITMP1 != REG_METHODPTR); + assert(REG_ITMP2 == REG_METHODPTR); - /* generate the actual call */ + M_DSEG_LOAD(REG_ITMP1, disp); + M_ADD(REG_METHODPTR, REG_METHODPTR, REG_ITMP1); + // This must be a load with displacement, + // otherwise the JIT method address patching does + // not work anymore (see md_jit_method_patch_address). + M_LDR_INTERN(REG_PV, REG_METHODPTR, 0); + } + else { + s1 = OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * lm->vftblindex; + + // The following instruction MUST NOT change a0 because of the implicit NPE check. + M_LDR_INTERN(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl)); + M_LDR(REG_PV, REG_METHODPTR, s1); + } + + // Generate the actual call. M_MOV(REG_LR, REG_PC); M_MOV(REG_PC, REG_PV); s1 = (s4) (cd->mcodeptr - cd->mcodebase); @@ -2319,25 +2331,43 @@ bool codegen_emit(jitdata *jd) case ICMD_INVOKEINTERFACE: if (lm == NULL) { - patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0); + int32_t disp = dseg_add_unique_s4(cd, 0); + int32_t disp2 = dseg_add_unique_s4(cd, 0); - s1 = 0; - s2 = 0; + // XXX We need two displacements. + assert(disp2 == disp - 4); + patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, disp); + + // The following instruction MUST NOT change a0 because of the implicit NPE check. + M_LDR_INTERN(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl)); + + // Sanity check. + assert(REG_ITMP1 != REG_METHODPTR); + assert(REG_ITMP2 == REG_METHODPTR); + assert(REG_ITMP3 != REG_METHODPTR); + + M_DSEG_LOAD(REG_ITMP1, disp); + M_LDR_REG(REG_METHODPTR, REG_METHODPTR, REG_ITMP1); + + M_DSEG_LOAD(REG_ITMP3, disp2); + M_ADD(REG_METHODPTR, REG_METHODPTR, REG_ITMP3); + + // This must be a load with displacement, + // otherwise the JIT method address patching does + // not work anymore (see md_jit_method_patch_address). + M_LDR_INTERN(REG_PV, REG_METHODPTR, 0); } else { - s1 = OFFSET(vftbl_t, interfacetable[0]) - - sizeof(methodptr*) * lm->clazz->index; + s1 = OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * lm->clazz->index; s2 = sizeof(methodptr) * (lm - lm->clazz->methods); - } - - /* implicit null-pointer check */ - M_LDR_INTERN(REG_METHODPTR, REG_A0, - OFFSET(java_object_t, vftbl)); - M_LDR_INTERN(REG_METHODPTR, REG_METHODPTR, s1); - M_LDR_INTERN(REG_PV, REG_METHODPTR, s2); - /* generate the actual call */ + // The following instruction MUST NOT change a0 because of the implicit NPE check. + M_LDR_INTERN(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl)); + M_LDR(REG_METHODPTR, REG_METHODPTR, s1); + M_LDR(REG_PV, REG_METHODPTR, s2); + } + // Generate the actual call. M_MOV(REG_LR, REG_PC); M_MOV(REG_PC, REG_PV); s1 = (s4) (cd->mcodeptr - cd->mcodebase); diff --git a/src/vm/jit/arm/codegen.h b/src/vm/jit/arm/codegen.h index b57d26cb2..1a45898e8 100644 --- a/src/vm/jit/arm/codegen.h +++ b/src/vm/jit/arm/codegen.h @@ -186,6 +186,9 @@ void asm_debug_intern(int a1, int a2, int a3, int a4); cd->mcodeptr += 4; \ } while (0) +#define M_MEM_GET_Rd(mcode) (((mcode) >> 12) & 0x0f) +#define M_MEM_GET_Rbase(mcode) (((mcode) >> 16) & 0x0f) + /* load and store instruction: M_MEM2 cond ... conditional execution @@ -487,6 +490,9 @@ void asm_debug_intern(int a1, int a2, int a3, int a4); #define M_LDMFD(regs,base) M_MEM_MULTI(UNCOND,1,0,regs,base,0,1,1) #define M_STMFD(regs,base) M_MEM_MULTI(UNCOND,0,0,regs,base,1,0,1) +#define M_LDR_REG(d,base,offreg) M_MEM(UNCOND,1,0,d,base,offreg,1,1,1,0) +#define M_STR_REG(d,base,offreg) M_MEM(UNCOND,0,0,d,base,offreg,1,1,1,0) + #define M_LDR_INTERN(d,base,off) \ do { \ CHECK_OFFSET(off, 0x0fff); \ diff --git a/src/vm/jit/arm/emit.c b/src/vm/jit/arm/emit.c index a30de7736..c6c922c21 100644 --- a/src/vm/jit/arm/emit.c +++ b/src/vm/jit/arm/emit.c @@ -34,7 +34,7 @@ #include "vm/jit/arm/codegen.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "threads/lock.hpp" @@ -49,7 +49,7 @@ #include "vm/jit/trace.hpp" #include "vm/jit/trap.h" -#include "toolbox/logging.h" /* XXX for debugging only */ +#include "toolbox/logging.hpp" /* XXX for debugging only */ /* emit_load ******************************************************************* diff --git a/src/vm/jit/arm/linux/md-os.c b/src/vm/jit/arm/linux/md-os.c index 1b1142e5a..10e7c13a2 100644 --- a/src/vm/jit/arm/linux/md-os.c +++ b/src/vm/jit/arm/linux/md-os.c @@ -52,7 +52,7 @@ typedef struct ucontext { #include "threads/thread.hpp" #include "vm/os.hpp" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/vm.hpp" #include "vm/jit/asmpart.h" diff --git a/src/vm/jit/arm/md-abi.c b/src/vm/jit/arm/md-abi.c index bdf6a14f9..c0f00f81a 100644 --- a/src/vm/jit/arm/md-abi.c +++ b/src/vm/jit/arm/md-abi.c @@ -28,7 +28,7 @@ #include "vm/jit/arm/md-abi.h" -#include "vm/descriptor.h" +#include "vm/descriptor.hpp" #include "vm/global.h" #include "vm/jit/abi.h" diff --git a/src/vm/jit/arm/md.c b/src/vm/jit/arm/md.c index b150f1a14..30df98d48 100644 --- a/src/vm/jit/arm/md.c +++ b/src/vm/jit/arm/md.c @@ -28,6 +28,7 @@ #include #include +#include "vm/jit/arm/codegen.h" #include "vm/jit/arm/md.h" #include "vm/jit/arm/md-abi.h" @@ -59,10 +60,18 @@ void md_init(void) or e590b000 ldr fp, [r0] - e59bc000 ldr ip, [fp] + e59bc004 ldr ip, [fp, #4] e1a0e00f mov lr, pc e1a0f00c mov pc, ip + or + + e590b000 ldr fp, [r0] + e28bca01 add ip, fp, #4096 ; 0x1000 + e59cc004 ldr ip, [ip, #4] + e1a0e00f mov lr, pc + e1a0f00c mov pc, ip + How we find out the patching address to store new method pointer: - loaded IP with LDR IP,[METHODPTR]? yes=INVOKEVIRTUAL or INVOKEINTERFACE (things are easy!) @@ -76,7 +85,7 @@ void *md_jit_method_patch_address(void *pv, void *ra, void *mptr) { uint32_t *pc; uint32_t mcode; - int32_t offset; + int32_t disp; void *pa; /* patch address */ /* Go back to the actual load instruction. */ @@ -87,22 +96,39 @@ void *md_jit_method_patch_address(void *pv, void *ra, void *mptr) mcode = pc[0]; - /* sanity check: are we inside jit code? */ + /* Sanity check: Are we inside jit code? */ assert(pc[1] == 0xe1a0e00f /*MOV LR,PC*/); assert(pc[2] == 0xe1a0f00c /*MOV PC,IP*/); - /* get the load instruction and offset */ - - offset = (int32_t) (mcode & 0x0fff); + /* Sanity check: We unconditionally loaded a word into REG_PV? */ assert ((mcode & 0xff70f000) == 0xe510c000); - if ((mcode & 0x000f0000) == 0x000b0000) { - /* sanity check: offset was positive */ + /* Get load displacement. */ + + disp = (int32_t) (mcode & 0x0fff); + + /* Case: We loaded from base REG_PV with negative displacement. */ + + if (M_MEM_GET_Rbase(mcode) == REG_PV && (mcode & 0x00800000) == 0) { + /* We loaded from data segment, displacement can be larger. */ + + mcode = pc[-1]; + + /* check for "SUB IP, IP, #??, ROTL 12" */ + + if ((mcode & 0xffffff00) == 0xe24cca00) + disp += (int32_t) ((mcode & 0x00ff) << 12); + + /* and get the final data segment address */ + + pa = ((uint8_t *) pv) - disp; + } - assert((mcode & 0x00800000) == 0x00800000); + /* Case: We loaded from base REG_METHODPTR with positive displacement. */ + else if (M_MEM_GET_Rbase(mcode) == REG_METHODPTR && (mcode & 0x00800000) == 0x00800000) { /* return NULL if no mptr was specified (used for replacement) */ if (mptr == NULL) @@ -110,26 +136,36 @@ void *md_jit_method_patch_address(void *pv, void *ra, void *mptr) /* we loaded from REG_METHODPTR */ - pa = ((uint8_t *) mptr) + offset; + pa = ((uint8_t *) mptr) + disp; } - else { - /* sanity check: we loaded from REG_IP; offset was negative or zero */ - assert((mcode & 0x008f0000) == 0x000c0000 || - (mcode & 0x008f0fff) == 0x008c0000); + /* Case: We loaded from base REG_PV with positive offset. */ - /* we loaded from data segment; offset can be larger */ + else if (M_MEM_GET_Rbase(mcode) == REG_PV && (mcode & 0x00800000) == 0x00800000) { + /* We loaded from REG_METHODPTR with a larger displacement */ mcode = pc[-1]; - /* check for "SUB IP, IP, #??, ROTL 12" */ + /* check for "ADD IP, FP, #??, ROTL 12" */ - if ((mcode & 0xffffff00) == 0xe24cca00) - offset += (int32_t) ((mcode & 0x00ff) << 12); + if ((mcode & 0xffffff00) == 0xe28bca00) + disp += (int32_t) ((mcode & 0x00ff) << 12); + else + vm_abort_disassemble(pc - 1, 4, "md_jit_method_patch_address: unknown instruction %x", mcode); - /* and get the final data segment address */ + /* we loaded from REG_METHODPTR */ + + pa = ((uint8_t *) mptr) + disp; + } + + /* Case is not covered, something is severely wrong. */ + + else { + vm_abort_disassemble(pc, 3, "md_jit_method_patch_address: unknown instruction %x", mcode); + + /* Keep compiler happy. */ - pa = ((uint8_t *) pv) - offset; + pa = NULL; } return pa; diff --git a/src/vm/jit/arm/patcher.c b/src/vm/jit/arm/patcher.c index 36f0adfc3..c2fbbe340 100644 --- a/src/vm/jit/arm/patcher.c +++ b/src/vm/jit/arm/patcher.c @@ -33,7 +33,7 @@ #include "vm/jit/arm/md.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/native.hpp" @@ -49,18 +49,6 @@ #include "vm/jit/patcher-common.hpp" -#define gen_resolveload(inst,offset) \ - assert((offset) >= -0x0fff && (offset) <= 0x0fff); \ - assert(!((inst) & 0x0fff)); \ - if ((offset) < 0) { \ - (inst) = ((inst) & 0xff7ff000) | ((-(offset)) & 0x0fff); \ - /*(inst) &= ~(1 << 23);*/ \ - } else { \ - (inst) = ((inst) & 0xfffff000) | ((offset) & 0x0fff); \ - /*(inst) |= (1 << 23);*/ \ - } - - /* patcher_patch_code ********************************************************** Just patches back the original machine code. @@ -282,8 +270,8 @@ bool patcher_invokestatic_special(patchref_t *pr) bool patcher_invokevirtual(patchref_t *pr) { - uint32_t* pc = (uint32_t*) pr->mpc; - unresolved_method* um = (unresolved_method *) pr->ref; + unresolved_method* um = (unresolved_method*) pr->ref; + int32_t* datap = (int32_t*) pr->datap; // Resolve the method. methodinfo* m = resolve_method_eager(um); @@ -292,10 +280,8 @@ bool patcher_invokevirtual(patchref_t *pr) return false; // Patch vftbl index. - gen_resolveload(pc[1], (int32_t) (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex)); - - // Synchronize instruction cache. - md_icacheflush(pc + 1, 1 * 4); + int32_t disp = OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex; + *datap = disp; // Patch back the original code. patcher_patch_code(pr); @@ -315,13 +301,12 @@ bool patcher_invokevirtual(patchref_t *pr) e1a0e00f mov lr, pc e1a0f00c mov pc, ip - *******************************************************************************/ bool patcher_invokeinterface(patchref_t *pr) { - uint32_t* pc = (uint32_t*) pr->mpc; - unresolved_method* um = (unresolved_method *) pr->ref; + unresolved_method* um = (unresolved_method*) pr->ref; + int32_t* datap = (int32_t*) pr->datap; // Resolve the method. methodinfo* m = resolve_method_eager(um); @@ -330,13 +315,15 @@ bool patcher_invokeinterface(patchref_t *pr) return false; // Patch interfacetable index. - gen_resolveload(pc[1], (int32_t) (OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * m->clazz->index)); + int32_t disp = OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * m->clazz->index; + *datap = disp; - // Patch method offset. - gen_resolveload(pc[2], (int32_t) (sizeof(methodptr) * (m - m->clazz->methods))); + // HACK The next data segment entry is one below. + datap--; - // Synchronize instruction cache. - md_icacheflush(pc + 1, 2 * 4); + // Patch method offset. + disp = sizeof(methodptr) * (m - m->clazz->methods); + *datap = disp; // Patch back the original code. patcher_patch_code(pr); diff --git a/src/vm/jit/builtin.cpp b/src/vm/jit/builtin.cpp index f2c1a5f6b..491d48ce6 100644 --- a/src/vm/jit/builtin.cpp +++ b/src/vm/jit/builtin.cpp @@ -48,7 +48,7 @@ #endif #include "mm/gc.hpp" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/llni.h" @@ -56,7 +56,7 @@ #include "threads/mutex.hpp" #include "threads/thread.hpp" -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" #include "toolbox/util.h" #include "vm/array.hpp" diff --git a/src/vm/jit/builtin.hpp b/src/vm/jit/builtin.hpp index eb2d80e1c..60b58e25c 100644 --- a/src/vm/jit/builtin.hpp +++ b/src/vm/jit/builtin.hpp @@ -36,9 +36,9 @@ typedef struct builtintable_entry builtintable_entry; #include "arch.h" #include "md-abi.h" -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" -#include "vm/descriptor.h" +#include "vm/descriptor.hpp" #include "vm/utf8.h" diff --git a/src/vm/jit/cfg.c b/src/vm/jit/cfg.c index 4772b95f2..63e3821c4 100644 --- a/src/vm/jit/cfg.c +++ b/src/vm/jit/cfg.c @@ -30,7 +30,7 @@ #include #include -#include "mm/memory.h" +#include "mm/memory.hpp" #include "vm/global.h" diff --git a/src/vm/jit/code.cpp b/src/vm/jit/code.cpp index b39852d2e..53dec1fd2 100644 --- a/src/vm/jit/code.cpp +++ b/src/vm/jit/code.cpp @@ -30,7 +30,7 @@ #include "arch.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "vm/options.h" #include "vm/vm.hpp" diff --git a/src/vm/jit/codegen-common.cpp b/src/vm/jit/codegen-common.cpp index dd1768e58..218c2537f 100644 --- a/src/vm/jit/codegen-common.cpp +++ b/src/vm/jit/codegen-common.cpp @@ -51,11 +51,11 @@ #include "md.h" #include "md-abi.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "toolbox/avl.h" #include "toolbox/list.hpp" -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" #include "native/llni.h" #include "native/localref.hpp" diff --git a/src/vm/jit/codegen-common.hpp b/src/vm/jit/codegen-common.hpp index 98a714236..b988853b3 100644 --- a/src/vm/jit/codegen-common.hpp +++ b/src/vm/jit/codegen-common.hpp @@ -41,7 +41,7 @@ typedef struct dataref dataref; #include "toolbox/list.hpp" #include "vm/jit/builtin.hpp" -#include "vm/descriptor.h" +#include "vm/descriptor.hpp" #include "vm/global.h" #include "vm/method.hpp" #include "vm/references.h" diff --git a/src/vm/jit/disass-common.c b/src/vm/jit/disass-common.c index f3636f88d..75ebe3b3d 100644 --- a/src/vm/jit/disass-common.c +++ b/src/vm/jit/disass-common.c @@ -33,7 +33,7 @@ #include "vm/types.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "vm/jit/disass.h" diff --git a/src/vm/jit/dseg.c b/src/vm/jit/dseg.c index b66da4bd4..92129f411 100644 --- a/src/vm/jit/dseg.c +++ b/src/vm/jit/dseg.c @@ -29,7 +29,7 @@ #include "vm/types.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "vm/options.h" diff --git a/src/vm/jit/exceptiontable.c b/src/vm/jit/exceptiontable.c index 9130543d2..7745c7ff3 100644 --- a/src/vm/jit/exceptiontable.c +++ b/src/vm/jit/exceptiontable.c @@ -28,7 +28,7 @@ #include #include -#include "mm/memory.h" +#include "mm/memory.hpp" #include "vm/jit/code.hpp" #include "vm/jit/exceptiontable.h" diff --git a/src/vm/jit/executionstate.c b/src/vm/jit/executionstate.c index cfcac31c3..2a7958dea 100644 --- a/src/vm/jit/executionstate.c +++ b/src/vm/jit/executionstate.c @@ -30,7 +30,7 @@ #include "md-abi.h" -#include "vm/descriptor.h" +#include "vm/descriptor.hpp" #include "vm/os.hpp" #include "vm/jit/abi.h" diff --git a/src/vm/jit/i386/codegen.c b/src/vm/jit/i386/codegen.c index a367f37aa..8eab0fbf0 100644 --- a/src/vm/jit/i386/codegen.c +++ b/src/vm/jit/i386/codegen.c @@ -36,7 +36,7 @@ #include "vm/jit/i386/codegen.h" #include "vm/jit/i386/emit.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/localref.hpp" #include "native/native.hpp" diff --git a/src/vm/jit/i386/cygwin/md-os.c b/src/vm/jit/i386/cygwin/md-os.c index e35e6f6a1..add516af7 100644 --- a/src/vm/jit/i386/cygwin/md-os.c +++ b/src/vm/jit/i386/cygwin/md-os.c @@ -32,7 +32,7 @@ #include "vm/types.h" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/jit/asmpart.h" diff --git a/src/vm/jit/i386/darwin/md-os.c b/src/vm/jit/i386/darwin/md-os.c index 87157e500..b9f3afd9d 100644 --- a/src/vm/jit/i386/darwin/md-os.c +++ b/src/vm/jit/i386/darwin/md-os.c @@ -39,7 +39,7 @@ #include "vm/jit/builtin.hpp" #include "vm/global.h" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/jit/asmpart.h" #include "vm/jit/executionstate.h" diff --git a/src/vm/jit/i386/emit.c b/src/vm/jit/i386/emit.c index d7140291a..3a264f162 100644 --- a/src/vm/jit/i386/emit.c +++ b/src/vm/jit/i386/emit.c @@ -33,7 +33,7 @@ #include "vm/jit/i386/emit.h" #include "vm/jit/i386/md-abi.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "threads/lock.hpp" diff --git a/src/vm/jit/i386/freebsd/md-os.c b/src/vm/jit/i386/freebsd/md-os.c index 9a1dc9d5e..9a1883147 100644 --- a/src/vm/jit/i386/freebsd/md-os.c +++ b/src/vm/jit/i386/freebsd/md-os.c @@ -36,7 +36,7 @@ #include "threads/thread.hpp" #include "vm/jit/builtin.hpp" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/jit/asmpart.h" #include "vm/jit/executionstate.h" diff --git a/src/vm/jit/i386/linux/md-os.c b/src/vm/jit/i386/linux/md-os.c index f046f37d6..19be0e4b7 100644 --- a/src/vm/jit/i386/linux/md-os.c +++ b/src/vm/jit/i386/linux/md-os.c @@ -38,7 +38,7 @@ #include "threads/thread.hpp" #include "vm/jit/builtin.hpp" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/jit/asmpart.h" #include "vm/jit/executionstate.h" diff --git a/src/vm/jit/i386/md-abi.c b/src/vm/jit/i386/md-abi.c index dbaf089b8..f304686bc 100644 --- a/src/vm/jit/i386/md-abi.c +++ b/src/vm/jit/i386/md-abi.c @@ -28,7 +28,7 @@ #include "vm/jit/i386/md-abi.h" -#include "vm/descriptor.h" +#include "vm/descriptor.hpp" #include "vm/global.h" #include "vm/jit/abi.h" diff --git a/src/vm/jit/i386/patcher.c b/src/vm/jit/i386/patcher.c index 3eecac97e..fb04b86c4 100644 --- a/src/vm/jit/i386/patcher.c +++ b/src/vm/jit/i386/patcher.c @@ -32,7 +32,7 @@ #include "vm/jit/i386/codegen.h" #include "vm/jit/i386/md.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/native.hpp" diff --git a/src/vm/jit/i386/solaris/md-os.c b/src/vm/jit/i386/solaris/md-os.c index 67363ec8d..16e649d6d 100644 --- a/src/vm/jit/i386/solaris/md-os.c +++ b/src/vm/jit/i386/solaris/md-os.c @@ -36,7 +36,7 @@ #include "threads/thread.hpp" #include "vm/jit/builtin.hpp" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/jit/asmpart.h" #include "vm/jit/executionstate.h" diff --git a/src/vm/jit/inline/inline.cpp b/src/vm/jit/inline/inline.cpp index 73c8667d2..721e143d4 100644 --- a/src/vm/jit/inline/inline.cpp +++ b/src/vm/jit/inline/inline.cpp @@ -32,13 +32,13 @@ #include "vm/types.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "threads/lock.hpp" #include "threads/mutex.hpp" #include "threads/thread.hpp" -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" #include "vm/jit/builtin.hpp" #include "vm/class.hpp" diff --git a/src/vm/jit/intrp/codegen.c b/src/vm/jit/intrp/codegen.c index 4fbca4a70..0e477cc37 100644 --- a/src/vm/jit/intrp/codegen.c +++ b/src/vm/jit/intrp/codegen.c @@ -43,7 +43,7 @@ #include "vm/jit/intrp/codegen.h" #include "vm/jit/intrp/intrp.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/native.hpp" diff --git a/src/vm/jit/intrp/dynamic-super.c b/src/vm/jit/intrp/dynamic-super.c index 78f75df02..db0baf5ba 100644 --- a/src/vm/jit/intrp/dynamic-super.c +++ b/src/vm/jit/intrp/dynamic-super.c @@ -36,12 +36,12 @@ #include "vm/types.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "threads/lock.hpp" #include "toolbox/hashtable.h" -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" #include "vm/options.h" diff --git a/src/vm/jit/intrp/engine.c b/src/vm/jit/intrp/engine.c index a09239243..118883f72 100644 --- a/src/vm/jit/intrp/engine.c +++ b/src/vm/jit/intrp/engine.c @@ -37,7 +37,7 @@ #include "md-abi.h" /* required for TRACE_ARGS_NUM */ -#include "mm/memory.h" +#include "mm/memory.hpp" #include "threads/thread.hpp" diff --git a/src/vm/jit/intrp/patcher.c b/src/vm/jit/intrp/patcher.c index 518c757b1..530e38e96 100644 --- a/src/vm/jit/intrp/patcher.c +++ b/src/vm/jit/intrp/patcher.c @@ -26,7 +26,7 @@ #include "config.h" #include "vm/types.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/native.hpp" diff --git a/src/vm/jit/ir/instruction.cpp b/src/vm/jit/ir/instruction.cpp index 9be1a6fdf..027ff1502 100644 --- a/src/vm/jit/ir/instruction.cpp +++ b/src/vm/jit/ir/instruction.cpp @@ -27,7 +27,7 @@ #include -#include "vm/descriptor.h" +#include "vm/descriptor.hpp" #include "vm/jit/ir/instruction.hpp" diff --git a/src/vm/jit/ir/instruction.hpp b/src/vm/jit/ir/instruction.hpp index c9f3e3075..cfbaead66 100644 --- a/src/vm/jit/ir/instruction.hpp +++ b/src/vm/jit/ir/instruction.hpp @@ -35,7 +35,7 @@ typedef struct insinfo_inline insinfo_inline; #include -#include "vm/descriptor.h" +#include "vm/descriptor.hpp" #include "vm/jit/jit.hpp" #include "vm/jit/replace.hpp" diff --git a/src/vm/jit/jit.cpp b/src/vm/jit/jit.cpp index baaf5900f..2da94922a 100644 --- a/src/vm/jit/jit.cpp +++ b/src/vm/jit/jit.cpp @@ -32,11 +32,11 @@ #include "md.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/native.hpp" -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" #include "threads/mutex.hpp" diff --git a/src/vm/jit/linenumbertable.cpp b/src/vm/jit/linenumbertable.cpp index 379f6de8a..7a19b1dfb 100644 --- a/src/vm/jit/linenumbertable.cpp +++ b/src/vm/jit/linenumbertable.cpp @@ -30,7 +30,7 @@ #include -#include "mm/memory.h" +#include "mm/memory.hpp" #include "toolbox/list.hpp" diff --git a/src/vm/jit/loop/analyze.c b/src/vm/jit/loop/analyze.c index 211e492bd..4bf02301d 100644 --- a/src/vm/jit/loop/analyze.c +++ b/src/vm/jit/loop/analyze.c @@ -32,8 +32,8 @@ #include "vm/types.h" -#include "mm/memory.h" -#include "toolbox/logging.h" +#include "mm/memory.hpp" +#include "toolbox/logging.hpp" #include "vm/jit/jit.hpp" #include "vm/jit/stack.h" diff --git a/src/vm/jit/loop/graph.c b/src/vm/jit/loop/graph.c index 91f580d4b..9c420e5b8 100644 --- a/src/vm/jit/loop/graph.c +++ b/src/vm/jit/loop/graph.c @@ -36,8 +36,8 @@ #include -#include "mm/memory.h" -#include "toolbox/logging.h" +#include "mm/memory.hpp" +#include "toolbox/logging.hpp" #include "vm/jit/jit.hpp" #include "vm/jit/loop/graph.h" #include "vm/jit/loop/loop.h" diff --git a/src/vm/jit/loop/loop.c b/src/vm/jit/loop/loop.c index 56d4ee09f..2a50956f0 100644 --- a/src/vm/jit/loop/loop.c +++ b/src/vm/jit/loop/loop.c @@ -40,8 +40,8 @@ /* #include */ #include -#include "mm/memory.h" -#include "toolbox/logging.h" +#include "mm/memory.hpp" +#include "toolbox/logging.hpp" #include "vm/global.h" #include "vm/jit/jit.hpp" #include "vm/jit/loop/loop.h" diff --git a/src/vm/jit/loop/tracing.c b/src/vm/jit/loop/tracing.c index b2e295e6b..78c4fab34 100644 --- a/src/vm/jit/loop/tracing.c +++ b/src/vm/jit/loop/tracing.c @@ -34,7 +34,7 @@ */ -#include "mm/memory.h" +#include "mm/memory.hpp" #include "vm/jit/builtin.hpp" #include "vm/resolve.hpp" #include "vm/jit/loop/loop.h" diff --git a/src/vm/jit/m68k/codegen.c b/src/vm/jit/m68k/codegen.c index a6ad45abe..5c4689403 100644 --- a/src/vm/jit/m68k/codegen.c +++ b/src/vm/jit/m68k/codegen.c @@ -34,7 +34,7 @@ #include "vm/jit/m68k/codegen.h" #include "vm/jit/m68k/emit.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/localref.hpp" #include "native/native.hpp" diff --git a/src/vm/jit/m68k/emit.c b/src/vm/jit/m68k/emit.c index 81fc1288f..63d74a8e6 100644 --- a/src/vm/jit/m68k/emit.c +++ b/src/vm/jit/m68k/emit.c @@ -30,7 +30,7 @@ #include "vm/jit/m68k/codegen.h" #include "vm/jit/m68k/emit.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "vm/jit/builtin.hpp" diff --git a/src/vm/jit/m68k/emit.h b/src/vm/jit/m68k/emit.h index c0358ea8d..6980ad21f 100644 --- a/src/vm/jit/m68k/emit.h +++ b/src/vm/jit/m68k/emit.h @@ -1,9 +1,7 @@ /* src/vm/jit/m68k/emit.h - Copyright (C) 1996-2005, 2006, 2007 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 + Copyright (C) 1996-2005, 2006, 2007, 2008 + CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO This file is part of CACAO. @@ -24,8 +22,9 @@ */ -#ifndef _EMIT_H_ -#define _EMIT_H_ + +#ifndef _EMIT_H +#define _EMIT_H #include "config.h" @@ -35,7 +34,20 @@ void emit_mov_imm_reg (codegendata *cd, s4 imm, s4 dreg); void emit_mov_imm_areg(codegendata *cd, s4 imm, s4 dreg); -void emit_verbosecall_enter(jitdata* jd); -void emit_verbosecall_exit(jitdata* jd); -#endif +#endif /* _EMIT_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: + * vim:noexpandtab:sw=4:ts=4: + */ diff --git a/src/vm/jit/m68k/linux/md-os.c b/src/vm/jit/m68k/linux/md-os.c index 21c54f56d..36e85035d 100644 --- a/src/vm/jit/m68k/linux/md-os.c +++ b/src/vm/jit/m68k/linux/md-os.c @@ -28,7 +28,7 @@ #include "vm/jit/m68k/md.h" #include "vm/jit/m68k/linux/md-abi.h" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/vm.hpp" #include "vm/jit/asmpart.h" diff --git a/src/vm/jit/m68k/patcher.c b/src/vm/jit/m68k/patcher.c index 186e7dcdf..1bea411e7 100644 --- a/src/vm/jit/m68k/patcher.c +++ b/src/vm/jit/m68k/patcher.c @@ -31,7 +31,7 @@ #include "vm/jit/m68k/md.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/native.hpp" #include "vm/jit/builtin.hpp" diff --git a/src/vm/jit/methodtree.c b/src/vm/jit/methodtree.c index 0cb513794..2d125364a 100644 --- a/src/vm/jit/methodtree.c +++ b/src/vm/jit/methodtree.c @@ -27,7 +27,7 @@ #include -#include "mm/memory.h" +#include "mm/memory.hpp" #include "toolbox/avl.h" diff --git a/src/vm/jit/mips/codegen.c b/src/vm/jit/mips/codegen.c index e81137a70..7fac72391 100644 --- a/src/vm/jit/mips/codegen.c +++ b/src/vm/jit/mips/codegen.c @@ -35,7 +35,7 @@ #include "vm/jit/mips/arch.h" #include "vm/jit/mips/codegen.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/localref.hpp" #include "native/native.hpp" diff --git a/src/vm/jit/mips/emit.c b/src/vm/jit/mips/emit.c index fb41435eb..98e9b451f 100644 --- a/src/vm/jit/mips/emit.c +++ b/src/vm/jit/mips/emit.c @@ -32,7 +32,7 @@ #include "vm/jit/mips/codegen.h" #include "vm/jit/mips/md-abi.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "threads/lock.hpp" diff --git a/src/vm/jit/mips/irix/md-os.c b/src/vm/jit/mips/irix/md-os.c index 39117af25..9f6a87cbf 100644 --- a/src/vm/jit/mips/irix/md-os.c +++ b/src/vm/jit/mips/irix/md-os.c @@ -38,7 +38,7 @@ #include "mm/gc.hpp" #include "vm/global.h" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/jit/asmpart.h" #include "vm/jit/codegen-common.hpp" diff --git a/src/vm/jit/mips/linux/md-os.c b/src/vm/jit/mips/linux/md-os.c index f7b6601de..e707d6ee2 100644 --- a/src/vm/jit/mips/linux/md-os.c +++ b/src/vm/jit/mips/linux/md-os.c @@ -38,9 +38,9 @@ #include "vm/jit/mips/md-abi.h" #include "mm/gc.hpp" -#include "mm/memory.h" +#include "mm/memory.hpp" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/os.hpp" #include "vm/jit/asmpart.h" diff --git a/src/vm/jit/mips/md-abi.c b/src/vm/jit/mips/md-abi.c index 3b4be869c..da2af84aa 100644 --- a/src/vm/jit/mips/md-abi.c +++ b/src/vm/jit/mips/md-abi.c @@ -32,9 +32,9 @@ #include "vm/jit/mips/md-abi.h" -#include "mm/memory.h" +#include "mm/memory.hpp" -#include "vm/descriptor.h" +#include "vm/descriptor.hpp" #include "vm/global.h" #include "vm/method.hpp" diff --git a/src/vm/jit/mips/patcher.c b/src/vm/jit/mips/patcher.c index a5a5785b1..d36ea67f3 100644 --- a/src/vm/jit/mips/patcher.c +++ b/src/vm/jit/mips/patcher.c @@ -31,7 +31,7 @@ #include "vm/jit/mips/codegen.h" #include "vm/jit/mips/md.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/native.hpp" diff --git a/src/vm/jit/oprofile-agent.cpp b/src/vm/jit/oprofile-agent.cpp index 36e97a77f..9c6f44ee4 100644 --- a/src/vm/jit/oprofile-agent.cpp +++ b/src/vm/jit/oprofile-agent.cpp @@ -24,7 +24,7 @@ #include "config.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "vm/jit/code.hpp" #include "vm/jit/oprofile-agent.hpp" diff --git a/src/vm/jit/optimizing/bytecode_escape.c b/src/vm/jit/optimizing/bytecode_escape.c index 2d7044bc6..722e2f041 100644 --- a/src/vm/jit/optimizing/bytecode_escape.c +++ b/src/vm/jit/optimizing/bytecode_escape.c @@ -28,12 +28,12 @@ #include #include "mm/dumpmemory.hpp" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "toolbox/bitvector.h" #include "vm/class.hpp" -#include "vm/descriptor.h" +#include "vm/descriptor.hpp" #include "vm/global.h" #include "vm/references.h" #include "vm/resolve.hpp" diff --git a/src/vm/jit/optimizing/dominators.cpp b/src/vm/jit/optimizing/dominators.cpp index 9fe830b3f..f2cb5c9c4 100644 --- a/src/vm/jit/optimizing/dominators.cpp +++ b/src/vm/jit/optimizing/dominators.cpp @@ -27,7 +27,7 @@ #include "config.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "toolbox/bitvector.h" diff --git a/src/vm/jit/optimizing/graph.c b/src/vm/jit/optimizing/graph.c index fdde38c0c..12a8ecfbd 100644 --- a/src/vm/jit/optimizing/graph.c +++ b/src/vm/jit/optimizing/graph.c @@ -26,7 +26,7 @@ #include "config.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "toolbox/bitvector.h" diff --git a/src/vm/jit/optimizing/lifetimes.c b/src/vm/jit/optimizing/lifetimes.c index 8abc25741..317ae077f 100644 --- a/src/vm/jit/optimizing/lifetimes.c +++ b/src/vm/jit/optimizing/lifetimes.c @@ -28,7 +28,7 @@ #include #include -#include "mm/memory.h" +#include "mm/memory.hpp" #include "toolbox/bitvector.h" #include "toolbox/worklist.h" diff --git a/src/vm/jit/optimizing/lsra.c b/src/vm/jit/optimizing/lsra.c index 5ea6e55d1..0c43e2c45 100644 --- a/src/vm/jit/optimizing/lsra.c +++ b/src/vm/jit/optimizing/lsra.c @@ -31,7 +31,7 @@ #include "arch.h" #include "md-abi.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "toolbox/bitvector.h" @@ -49,7 +49,7 @@ #include "vm/jit/optimizing/lsra.h" -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" extern const char *string_java_lang_InternalError; /* function prototypes */ diff --git a/src/vm/jit/optimizing/profile.c b/src/vm/jit/optimizing/profile.c index e397be602..ea8101067 100644 --- a/src/vm/jit/optimizing/profile.c +++ b/src/vm/jit/optimizing/profile.c @@ -30,7 +30,7 @@ #include "vm/types.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "threads/threadlist.hpp" #include "threads/thread.hpp" diff --git a/src/vm/jit/optimizing/recompiler.cpp b/src/vm/jit/optimizing/recompiler.cpp index 4f3d52426..29fdc80d9 100644 --- a/src/vm/jit/optimizing/recompiler.cpp +++ b/src/vm/jit/optimizing/recompiler.cpp @@ -28,7 +28,7 @@ #include #include -#include "mm/memory.h" +#include "mm/memory.hpp" #include "threads/condition.hpp" #include "threads/mutex.hpp" diff --git a/src/vm/jit/optimizing/reorder.c b/src/vm/jit/optimizing/reorder.c index 2b135943f..3dd181933 100644 --- a/src/vm/jit/optimizing/reorder.c +++ b/src/vm/jit/optimizing/reorder.c @@ -37,7 +37,7 @@ #include "vm/types.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "vm/jit/jit.hpp" diff --git a/src/vm/jit/optimizing/ssa.c b/src/vm/jit/optimizing/ssa.c index 357f323f6..dd70dac52 100644 --- a/src/vm/jit/optimizing/ssa.c +++ b/src/vm/jit/optimizing/ssa.c @@ -28,7 +28,7 @@ #include #include -#include "mm/memory.h" +#include "mm/memory.hpp" #include "toolbox/bitvector.h" #include "toolbox/worklist.h" diff --git a/src/vm/jit/optimizing/ssa2.c b/src/vm/jit/optimizing/ssa2.c index ad1038a85..07c89e324 100644 --- a/src/vm/jit/optimizing/ssa2.c +++ b/src/vm/jit/optimizing/ssa2.c @@ -26,7 +26,7 @@ #include "config.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "toolbox/bitvector.h" #include "toolbox/set.h" diff --git a/src/vm/jit/optimizing/ssa3.c b/src/vm/jit/optimizing/ssa3.c index 3391d41dd..88d9f95f5 100644 --- a/src/vm/jit/optimizing/ssa3.c +++ b/src/vm/jit/optimizing/ssa3.c @@ -43,7 +43,7 @@ #include "vm/jit/jit.hpp" #include "vm/global.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "mm/dumpmemory.hpp" #include "toolbox/list.hpp" diff --git a/src/vm/jit/optimizing/ssa_phi.c b/src/vm/jit/optimizing/ssa_phi.c index e79b1654d..c21c06a96 100644 --- a/src/vm/jit/optimizing/ssa_phi.c +++ b/src/vm/jit/optimizing/ssa_phi.c @@ -28,7 +28,7 @@ #include #include -#include "mm/memory.h" +#include "mm/memory.hpp" #include "toolbox/bitvector.h" #include "toolbox/worklist.h" diff --git a/src/vm/jit/optimizing/ssa_rename.c b/src/vm/jit/optimizing/ssa_rename.c index 87fdd130f..98ae0d4c0 100644 --- a/src/vm/jit/optimizing/ssa_rename.c +++ b/src/vm/jit/optimizing/ssa_rename.c @@ -28,7 +28,7 @@ #include #include -#include "mm/memory.h" +#include "mm/memory.hpp" #include "toolbox/bitvector.h" #include "toolbox/worklist.h" diff --git a/src/vm/jit/parse.cpp b/src/vm/jit/parse.cpp index 63a15bb89..49fa5c2bc 100644 --- a/src/vm/jit/parse.cpp +++ b/src/vm/jit/parse.cpp @@ -30,13 +30,13 @@ #include "vm/types.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/native.hpp" #include "threads/lock.hpp" -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" #include "vm/jit/builtin.hpp" #include "vm/exceptions.hpp" diff --git a/src/vm/jit/patcher-common.cpp b/src/vm/jit/patcher-common.cpp index b4799b313..146e52834 100644 --- a/src/vm/jit/patcher-common.cpp +++ b/src/vm/jit/patcher-common.cpp @@ -35,12 +35,12 @@ #include "codegen.h" /* for PATCHER_NOPS */ #include "md.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/native.hpp" #include "toolbox/list.hpp" -#include "toolbox/logging.h" /* XXX remove me! */ +#include "toolbox/logging.hpp" /* XXX remove me! */ #include "vm/exceptions.hpp" #include "vm/initialize.hpp" @@ -247,7 +247,13 @@ bool patcher_is_patched(patchref_t* pr) // instruction as the patcher structure contains. uint32_t mcode = *((uint32_t*) pr->mpc); +#if PATCHER_CALL_SIZE == 4 if (mcode != pr->mcode) { +#elif PATCHER_CALL_SIZE == 2 + if ((uint16_t) mcode != (uint16_t) pr->mcode) { +#else +#error Unknown PATCHER_CALL_SIZE +#endif // The code differs. return false; } @@ -301,7 +307,6 @@ java_handle_t *patcher_handler(u1 *pc) codeinfo *code; patchref_t *pr; bool result; - java_handle_t *e; #if !defined(NDEBUG) patcher_function_list_t *l; int i; @@ -387,10 +392,13 @@ java_handle_t *patcher_handler(u1 *pc) } #endif - /* check for return value and exit accordingly */ - + // Check for return value and exit accordingly. if (result == false) { - e = exceptions_get_and_clear_exception(); + // Mangle the pending exception. + resolve_handle_pending_exception(true); + + // Get the exception and return it. + java_handle_t* e = exceptions_get_and_clear_exception(); code->patchers->unlock(); diff --git a/src/vm/jit/powerpc/codegen.c b/src/vm/jit/powerpc/codegen.c index dcfc0482e..555f0cf83 100644 --- a/src/vm/jit/powerpc/codegen.c +++ b/src/vm/jit/powerpc/codegen.c @@ -36,7 +36,7 @@ #include "vm/jit/powerpc/arch.h" #include "vm/jit/powerpc/codegen.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/localref.hpp" #include "native/native.hpp" diff --git a/src/vm/jit/powerpc/darwin/md-abi.c b/src/vm/jit/powerpc/darwin/md-abi.c index 68899b4ee..35b7c4822 100644 --- a/src/vm/jit/powerpc/darwin/md-abi.c +++ b/src/vm/jit/powerpc/darwin/md-abi.c @@ -29,7 +29,7 @@ #include "vm/jit/powerpc/darwin/md-abi.h" -#include "vm/descriptor.h" +#include "vm/descriptor.hpp" #include "vm/global.h" #include "vm/jit/abi.h" diff --git a/src/vm/jit/powerpc/darwin/md-os.c b/src/vm/jit/powerpc/darwin/md-os.c index d2e6bf231..a809cfef2 100644 --- a/src/vm/jit/powerpc/darwin/md-os.c +++ b/src/vm/jit/powerpc/darwin/md-os.c @@ -39,7 +39,7 @@ #include "vm/jit/builtin.hpp" #include "vm/global.h" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/jit/asmpart.h" diff --git a/src/vm/jit/powerpc/emit.c b/src/vm/jit/powerpc/emit.c index 66221d67d..9569377aa 100644 --- a/src/vm/jit/powerpc/emit.c +++ b/src/vm/jit/powerpc/emit.c @@ -34,7 +34,7 @@ #include "vm/jit/powerpc/codegen.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "threads/lock.hpp" diff --git a/src/vm/jit/powerpc/linux/md-abi.c b/src/vm/jit/powerpc/linux/md-abi.c index df5af31db..1282c5ee5 100644 --- a/src/vm/jit/powerpc/linux/md-abi.c +++ b/src/vm/jit/powerpc/linux/md-abi.c @@ -30,7 +30,7 @@ #include "vm/jit/powerpc/linux/md-abi.h" -#include "vm/descriptor.h" +#include "vm/descriptor.hpp" #include "vm/global.h" #include "vm/jit/abi.h" diff --git a/src/vm/jit/powerpc/linux/md-os.c b/src/vm/jit/powerpc/linux/md-os.c index e59a84cbb..5d2bf98e4 100644 --- a/src/vm/jit/powerpc/linux/md-os.c +++ b/src/vm/jit/powerpc/linux/md-os.c @@ -39,7 +39,7 @@ #include "threads/thread.hpp" #include "vm/jit/builtin.hpp" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/os.hpp" #include "vm/jit/asmpart.h" diff --git a/src/vm/jit/powerpc/netbsd/md-abi.c b/src/vm/jit/powerpc/netbsd/md-abi.c index aa9caeb42..36dd169c3 100644 --- a/src/vm/jit/powerpc/netbsd/md-abi.c +++ b/src/vm/jit/powerpc/netbsd/md-abi.c @@ -28,7 +28,7 @@ #include "vm/jit/powerpc/netbsd/md-abi.h" -#include "vm/descriptor.h" +#include "vm/descriptor.hpp" #include "vm/global.h" #include "vm/jit/abi.h" diff --git a/src/vm/jit/powerpc/netbsd/md-os.c b/src/vm/jit/powerpc/netbsd/md-os.c index a18683ef7..0fde3887c 100644 --- a/src/vm/jit/powerpc/netbsd/md-os.c +++ b/src/vm/jit/powerpc/netbsd/md-os.c @@ -31,7 +31,7 @@ #include "vm/jit/powerpc/netbsd/md-abi.h" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/jit/asmpart.h" #include "vm/jit/stacktrace.hpp" diff --git a/src/vm/jit/powerpc/patcher.c b/src/vm/jit/powerpc/patcher.c index a4fc722b1..b62294b5d 100644 --- a/src/vm/jit/powerpc/patcher.c +++ b/src/vm/jit/powerpc/patcher.c @@ -33,7 +33,7 @@ #include "vm/jit/powerpc/md.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/native.hpp" diff --git a/src/vm/jit/powerpc64/codegen.c b/src/vm/jit/powerpc64/codegen.c index 6de89aaf0..7c609638f 100644 --- a/src/vm/jit/powerpc64/codegen.c +++ b/src/vm/jit/powerpc64/codegen.c @@ -37,7 +37,7 @@ #include "vm/jit/powerpc64/arch.h" #include "vm/jit/powerpc64/codegen.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/localref.hpp" #include "native/native.hpp" diff --git a/src/vm/jit/powerpc64/emit.c b/src/vm/jit/powerpc64/emit.c index 4e7a37f71..0888baefe 100644 --- a/src/vm/jit/powerpc64/emit.c +++ b/src/vm/jit/powerpc64/emit.c @@ -29,7 +29,7 @@ #include "vm/types.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "md-abi.h" #include "vm/jit/powerpc64/codegen.h" diff --git a/src/vm/jit/powerpc64/linux/md-abi.c b/src/vm/jit/powerpc64/linux/md-abi.c index 68f1ae5e7..e77ff4806 100644 --- a/src/vm/jit/powerpc64/linux/md-abi.c +++ b/src/vm/jit/powerpc64/linux/md-abi.c @@ -31,7 +31,7 @@ #include "vm/jit/powerpc64/linux/md-abi.h" -#include "vm/descriptor.h" +#include "vm/descriptor.hpp" #include "vm/global.h" #include "vm/jit/abi.h" diff --git a/src/vm/jit/powerpc64/linux/md-os.c b/src/vm/jit/powerpc64/linux/md-os.c index ebb284b44..203cb007c 100644 --- a/src/vm/jit/powerpc64/linux/md-os.c +++ b/src/vm/jit/powerpc64/linux/md-os.c @@ -39,7 +39,7 @@ #include "threads/thread.hpp" #include "vm/jit/builtin.hpp" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/os.hpp" #include "vm/jit/asmpart.h" diff --git a/src/vm/jit/powerpc64/patcher.c b/src/vm/jit/powerpc64/patcher.c index 9e1799c22..c923f8448 100644 --- a/src/vm/jit/powerpc64/patcher.c +++ b/src/vm/jit/powerpc64/patcher.c @@ -33,7 +33,7 @@ #include "vm/jit/powerpc64/md.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/native.hpp" diff --git a/src/vm/jit/reg.c b/src/vm/jit/reg.c index 3829d9865..8dff24251 100644 --- a/src/vm/jit/reg.c +++ b/src/vm/jit/reg.c @@ -34,7 +34,7 @@ #include "arch.h" #include "md-abi.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "vm/jit/abi.h" #include "vm/jit/reg.h" diff --git a/src/vm/jit/replace.cpp b/src/vm/jit/replace.cpp index 427f0746a..94b0b1edb 100644 --- a/src/vm/jit/replace.cpp +++ b/src/vm/jit/replace.cpp @@ -38,11 +38,11 @@ #endif #include "mm/dumpmemory.hpp" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "threads/thread.hpp" -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" #include "vm/classcache.hpp" #include "vm/globals.hpp" diff --git a/src/vm/jit/s390/codegen.c b/src/vm/jit/s390/codegen.c index f69e661fb..b2780c05b 100644 --- a/src/vm/jit/s390/codegen.c +++ b/src/vm/jit/s390/codegen.c @@ -37,7 +37,7 @@ #include "native/localref.hpp" #include "native/native.hpp" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "threads/lock.hpp" diff --git a/src/vm/jit/s390/emit.c b/src/vm/jit/s390/emit.c index ef5c2289c..f4ed94218 100644 --- a/src/vm/jit/s390/emit.c +++ b/src/vm/jit/s390/emit.c @@ -31,7 +31,7 @@ #include "vm/jit/s390/emit.h" #include "vm/jit/s390/md-abi.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "threads/lock.hpp" diff --git a/src/vm/jit/s390/md-abi.c b/src/vm/jit/s390/md-abi.c index 95ad22ac5..474b7ff2a 100644 --- a/src/vm/jit/s390/md-abi.c +++ b/src/vm/jit/s390/md-abi.c @@ -25,7 +25,7 @@ #include "config.h" -#include "vm/descriptor.h" +#include "vm/descriptor.hpp" #include "vm/global.h" #include "vm/types.h" diff --git a/src/vm/jit/s390/md.c b/src/vm/jit/s390/md.c index 5e11280ac..0788e45a1 100644 --- a/src/vm/jit/s390/md.c +++ b/src/vm/jit/s390/md.c @@ -37,7 +37,7 @@ #include "threads/thread.hpp" #include "vm/exceptions.hpp" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/jit/asmpart.h" #include "vm/jit/abi.h" diff --git a/src/vm/jit/s390/patcher.c b/src/vm/jit/s390/patcher.c index 1add83719..21054fd8a 100644 --- a/src/vm/jit/s390/patcher.c +++ b/src/vm/jit/s390/patcher.c @@ -28,7 +28,7 @@ #include #include -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/native.hpp" #include "vm/jit/builtin.hpp" diff --git a/src/vm/jit/schedule/schedule.c b/src/vm/jit/schedule/schedule.c index 894821011..294e4d802 100644 --- a/src/vm/jit/schedule/schedule.c +++ b/src/vm/jit/schedule/schedule.c @@ -40,7 +40,7 @@ #include "disass.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "vm/options.h" #include "vm/statistics.h" #include "vm/jit/schedule/schedule.h" diff --git a/src/vm/jit/show.cpp b/src/vm/jit/show.cpp index e0ba2a3cf..2019644e4 100644 --- a/src/vm/jit/show.cpp +++ b/src/vm/jit/show.cpp @@ -30,7 +30,7 @@ #include "vm/types.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "threads/lock.hpp" diff --git a/src/vm/jit/sparc64/codegen.c b/src/vm/jit/sparc64/codegen.c index b048fbe32..1de656e74 100644 --- a/src/vm/jit/sparc64/codegen.c +++ b/src/vm/jit/sparc64/codegen.c @@ -37,7 +37,7 @@ #include "vm/jit/sparc64/codegen.h" #include "vm/jit/sparc64/emit.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/localref.hpp" #include "native/native.hpp" diff --git a/src/vm/jit/sparc64/emit.c b/src/vm/jit/sparc64/emit.c index e7f8f379e..0c71d11a7 100644 --- a/src/vm/jit/sparc64/emit.c +++ b/src/vm/jit/sparc64/emit.c @@ -33,7 +33,7 @@ #include "vm/jit/sparc64/md-abi.h" #include "vm/jit/sparc64/emit.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "vm/jit/builtin.hpp" #include "vm/options.h" diff --git a/src/vm/jit/sparc64/linux/md-os.c b/src/vm/jit/sparc64/linux/md-os.c index e1cdfdb9f..97c10e3f6 100644 --- a/src/vm/jit/sparc64/linux/md-os.c +++ b/src/vm/jit/sparc64/linux/md-os.c @@ -34,7 +34,7 @@ #include "vm/jit/sparc64/codegen.h" #include "vm/jit/sparc64/md-abi.h" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/jit/asmpart.h" #include "vm/jit/stacktrace.hpp" diff --git a/src/vm/jit/sparc64/md-abi.c b/src/vm/jit/sparc64/md-abi.c index cc12be598..3218d4228 100644 --- a/src/vm/jit/sparc64/md-abi.c +++ b/src/vm/jit/sparc64/md-abi.c @@ -28,14 +28,14 @@ #include "vm/jit/sparc64/md-abi.h" -#include "vm/descriptor.h" +#include "vm/descriptor.hpp" #include "vm/global.h" #include "vm/jit/abi.h" #include "vm/jit/stack.h" /* temp */ -#include "mm/memory.h" +#include "mm/memory.hpp" #include diff --git a/src/vm/jit/sparc64/patcher.c b/src/vm/jit/sparc64/patcher.c index c36a5abc7..61043c3c2 100644 --- a/src/vm/jit/sparc64/patcher.c +++ b/src/vm/jit/sparc64/patcher.c @@ -30,7 +30,7 @@ #include "vm/types.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "vm/jit/sparc64/codegen.h" #include "vm/jit/sparc64/md.h" diff --git a/src/vm/jit/sparc64/solaris/md-os.c b/src/vm/jit/sparc64/solaris/md-os.c index 7c4c802a8..8b13aa3f8 100644 --- a/src/vm/jit/sparc64/solaris/md-os.c +++ b/src/vm/jit/sparc64/solaris/md-os.c @@ -37,7 +37,7 @@ #include "vm/jit/sparc64/codegen.h" #include "vm/jit/sparc64/md-abi.h" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/jit/asmpart.h" #include "vm/jit/stacktrace.hpp" diff --git a/src/vm/jit/stack.c b/src/vm/jit/stack.c index 8c7ad97c3..06ff37115 100644 --- a/src/vm/jit/stack.c +++ b/src/vm/jit/stack.c @@ -33,11 +33,11 @@ #include "arch.h" #include "md-abi.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/native.hpp" -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" #include "vm/jit/builtin.hpp" #include "vm/exceptions.hpp" diff --git a/src/vm/jit/stacktrace.cpp b/src/vm/jit/stacktrace.cpp index 9b63c7e17..8efa4b25b 100644 --- a/src/vm/jit/stacktrace.cpp +++ b/src/vm/jit/stacktrace.cpp @@ -35,7 +35,7 @@ #include "md.h" #include "mm/gc.hpp" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "vm/jit/stacktrace.hpp" @@ -43,7 +43,7 @@ #include "threads/thread.hpp" -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" #include "vm/array.hpp" #include "vm/jit/builtin.hpp" @@ -674,6 +674,129 @@ java_handle_bytearray_t *stacktrace_get_current(void) } +/** + * Creates a java.lang.StackTraceElement for one element of the given + * stacktrace. + * + * @param st Given stacktrace. + * @param index Index of element inside stacktrace. + * @return The filled StackTraceElement object. + */ +#if defined(ENABLE_JAVASE) +java_handle_t* stacktrace_get_StackTraceElement(stacktrace_t* st, int32_t index) +{ + assert(st != NULL); + + if ((index < 0) || (index >= st->length)) { + /* XXX This should be an IndexOutOfBoundsException (check this + again). */ + exceptions_throw_arrayindexoutofboundsexception(); + return NULL; + } + + // Get the stacktrace entry. + stacktrace_entry_t* ste = &(st->entries[index]); + + // Get the codeinfo, methodinfo and classinfo. + codeinfo* code = ste->code; + methodinfo* m = code->m; + classinfo* c = m->clazz; + + // Get filename. + java_handle_t* filename; + + if (!(m->flags & ACC_NATIVE)) { + if (c->sourcefile != NULL) + filename = javastring_new(c->sourcefile); + else + filename = NULL; + } + else + filename = NULL; + + // Get line number. + int32_t linenumber; + + if (m->flags & ACC_NATIVE) { +#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH) + linenumber = -1; +#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) + linenumber = -2; +#else +# error unknown classpath configuration +#endif + } + else { + // FIXME linenumbertable->find could change the methodinfo + // pointer when hitting an inlined method. + linenumber = code->linenumbertable->find(&m, ste->pc); + linenumber = (linenumber == 0) ? -1 : linenumber; + } + + // Get declaring class name. + java_handle_t* declaringclass = class_get_classname(c); + +#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH) + // Allocate a new StackTraceElement object. + java_handle_t* h = builtin_new(class_java_lang_StackTraceElement); + + if (h == NULL) + return NULL; + + java_lang_StackTraceElement jlste(h, filename, linenumber, declaringclass, javastring_new(m->name), ((m->flags & ACC_NATIVE) ? 1 : 0)); +#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) + // Allocate a new StackTraceElement object. + java_lang_StackTraceElement jlste(declaringclass, javastring_new(m->name), filename, linenumber); + + if (jlste.is_null()) + return NULL; +#else +# error unknown classpath configuration +#endif + + return jlste.get_handle(); +} +#endif + + +/** + * Creates a complete array of java.lang.StackTraceElement objects + * for the given stacktrace. + * + * @param st Given stacktrace. + * @return Array of filled StackTraceElement objects. + */ +#if defined(ENABLE_JAVASE) +java_handle_objectarray_t* stacktrace_get_StackTraceElements(stacktrace_t* st) +{ + // Get length of stacktrace. If stacktrace is not available + // an empty array should be returned. + int32_t length = (st != NULL) ? st->length : 0; + + // Create the stacktrace element array. + java_handle_objectarray_t* oa = builtin_anewarray(length, class_java_lang_StackTraceElement); + + if (oa == NULL) + return NULL; + + // Iterate over all stacktrace elements. + for (int i = 0; i < length; i++) { + + // Get stacktrace element at current index. + java_handle_t* h = stacktrace_get_StackTraceElement(st, i); + + if (h == NULL) + return NULL; + + // Store stacktrace element in array. + array_objectarray_element_set(oa, i, h); + } + + return oa; +} +#endif + + /* stacktrace_get_caller_class ************************************************* Get the class on the stack at the given depth. This function skips @@ -1187,6 +1310,36 @@ void stacktrace_print_current(void) } +/** + * Creates a stacktrace for the given thread. + * + * @param t Given thread. + * @return Current stacktrace of the given thread. + * + * XXX: Creation of the stacktrace starts at the most recent + * stackframeinfo block. If the thread is not inside the native + * world, the created stacktrace is not complete! + */ +#if defined(ENABLE_THREADS) +stacktrace_t* stacktrace_get_of_thread(threadobject* t) +{ + stackframeinfo_t* sfi; + java_handle_bytearray_t* ba; + stacktrace_t* st; + + sfi = t->_stackframeinfo; + ba = stacktrace_get(sfi); + + if (ba == NULL) + return NULL; + + st = (stacktrace_t*) LLNI_array_data(ba); + + return st; +} +#endif + + /* stacktrace_print_of_thread ************************************************** Print the current stacktrace of the given thread. diff --git a/src/vm/jit/stacktrace.hpp b/src/vm/jit/stacktrace.hpp index 6aa0ecf5b..2c2920c82 100644 --- a/src/vm/jit/stacktrace.hpp +++ b/src/vm/jit/stacktrace.hpp @@ -106,6 +106,8 @@ java_handle_bytearray_t *stacktrace_get(stackframeinfo_t *sfi); java_handle_bytearray_t *stacktrace_get_current(void); #if defined(ENABLE_JAVASE) +java_handle_t* stacktrace_get_StackTraceElement(stacktrace_t *st, int32_t index); +java_handle_objectarray_t* stacktrace_get_StackTraceElements(stacktrace_t *st); classinfo *stacktrace_get_caller_class(int depth); classloader_t *stacktrace_first_nonnull_classloader(void); java_handle_objectarray_t *stacktrace_getClassContext(void); @@ -117,6 +119,7 @@ void stacktrace_print(stacktrace_t *st); void stacktrace_print_current(void); #if defined(ENABLE_THREADS) +stacktrace_t* stacktrace_get_of_thread(threadobject *t); void stacktrace_print_of_thread(threadobject *t); #endif diff --git a/src/vm/jit/trace.cpp b/src/vm/jit/trace.cpp index 91a365573..98667f76c 100644 --- a/src/vm/jit/trace.cpp +++ b/src/vm/jit/trace.cpp @@ -30,13 +30,13 @@ #include "arch.h" #include "md-abi.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/llni.h" #include "threads/thread.hpp" -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" #include "vm/global.h" #include "vm/globals.hpp" diff --git a/src/vm/jit/trap.c b/src/vm/jit/trap.c index 1ac7ffe7e..a5ab45182 100644 --- a/src/vm/jit/trap.c +++ b/src/vm/jit/trap.c @@ -32,11 +32,11 @@ #include "md.h" #include "md-trap.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/llni.h" -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" #include "vm/exceptions.hpp" #include "vm/options.h" diff --git a/src/vm/jit/verify/typecheck-stackbased.cpp b/src/vm/jit/verify/typecheck-stackbased.cpp index 8ac6267b8..6d0566268 100644 --- a/src/vm/jit/verify/typecheck-stackbased.cpp +++ b/src/vm/jit/verify/typecheck-stackbased.cpp @@ -30,7 +30,7 @@ #include "vm/types.h" #include "vm/jit/builtin.hpp" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "vm/array.hpp" #include "vm/exceptions.hpp" diff --git a/src/vm/jit/verify/typecheck-typeinferer.cpp b/src/vm/jit/verify/typecheck-typeinferer.cpp index 762689076..4f69f8e3e 100644 --- a/src/vm/jit/verify/typecheck-typeinferer.cpp +++ b/src/vm/jit/verify/typecheck-typeinferer.cpp @@ -29,11 +29,11 @@ #include #include -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/native.hpp" -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" #include "vm/access.hpp" #include "vm/array.hpp" diff --git a/src/vm/jit/verify/typecheck.cpp b/src/vm/jit/verify/typecheck.cpp index d63c42200..d4687166a 100644 --- a/src/vm/jit/verify/typecheck.cpp +++ b/src/vm/jit/verify/typecheck.cpp @@ -141,11 +141,11 @@ error reporting. #ifdef ENABLE_VERIFIER -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/native.hpp" -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" #include "vm/access.hpp" #include "vm/array.hpp" diff --git a/src/vm/jit/verify/typeinfo.cpp b/src/vm/jit/verify/typeinfo.cpp index 4df771a9d..0e6f46dc8 100644 --- a/src/vm/jit/verify/typeinfo.cpp +++ b/src/vm/jit/verify/typeinfo.cpp @@ -28,13 +28,13 @@ #include #include -#include "mm/memory.h" +#include "mm/memory.hpp" -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" #include "vm/array.hpp" #include "vm/class.hpp" -#include "vm/descriptor.h" +#include "vm/descriptor.hpp" #include "vm/exceptions.hpp" #include "vm/globals.hpp" #include "vm/loader.hpp" @@ -44,9 +44,6 @@ #include "vm/jit/jit.hpp" #include "vm/jit/verify/typeinfo.hpp" -#if defined(__cplusplus) -extern "C" { -#endif /* check if a linked class is an array class. Only use for linked classes! */ #define CLASSINFO_IS_ARRAY(clsinfo) ((clsinfo)->vftbl->arraydesc != NULL) @@ -2550,10 +2547,6 @@ typevector_print(FILE *file,varinfo *vec,int size) } } -#if defined(__cplusplus) -} -#endif - #endif /* TYPEINFO_DEBUG */ diff --git a/src/vm/jit/x86_64/codegen.c b/src/vm/jit/x86_64/codegen.c index 96f4967bc..80c81af88 100644 --- a/src/vm/jit/x86_64/codegen.c +++ b/src/vm/jit/x86_64/codegen.c @@ -37,7 +37,7 @@ #include "vm/jit/x86_64/codegen.h" #include "vm/jit/x86_64/emit.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/localref.hpp" #include "native/native.hpp" diff --git a/src/vm/jit/x86_64/emit.c b/src/vm/jit/x86_64/emit.c index 9c777fb54..5f6f0d87a 100644 --- a/src/vm/jit/x86_64/emit.c +++ b/src/vm/jit/x86_64/emit.c @@ -33,7 +33,7 @@ #include "vm/jit/x86_64/codegen.h" #include "vm/jit/x86_64/emit.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "threads/lock.hpp" diff --git a/src/vm/jit/x86_64/freebsd/md-os.c b/src/vm/jit/x86_64/freebsd/md-os.c index 4b683342a..fd9244d33 100644 --- a/src/vm/jit/x86_64/freebsd/md-os.c +++ b/src/vm/jit/x86_64/freebsd/md-os.c @@ -31,7 +31,7 @@ #include "threads/thread.hpp" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/jit/asmpart.h" #include "vm/jit/stacktrace.hpp" diff --git a/src/vm/jit/x86_64/linux/md-os.c b/src/vm/jit/x86_64/linux/md-os.c index 5036ff2ef..1c30b8bbf 100644 --- a/src/vm/jit/x86_64/linux/md-os.c +++ b/src/vm/jit/x86_64/linux/md-os.c @@ -40,7 +40,7 @@ #include "threads/thread.hpp" #include "vm/jit/builtin.hpp" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/jit/asmpart.h" #include "vm/jit/executionstate.h" @@ -260,6 +260,22 @@ void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p) xpc = (u1 *) _mc->gregs[REG_RIP]; ra = xpc; /* return address is equal to xpc */ + // Check if the trap instruction is valid. + // TODO Move this into patcher_handler. + if (patcher_is_valid_trap_instruction_at(xpc) == false) { + // Check if the PC has been patched during our way to this + // signal handler (see PR85). + if (patcher_is_patched_at(xpc) == true) + return; + + // We have a problem... + log_println("md_signal_handler_sigill: Unknown illegal instruction at 0x%lx", xpc); +#if defined(ENABLE_DISASSEMBLER) + (void) disassinstr(xpc); +#endif + vm_abort("Aborting..."); + } + /* This is a patcher. */ type = TRAP_PATCHER; diff --git a/src/vm/jit/x86_64/md-abi.c b/src/vm/jit/x86_64/md-abi.c index fd248a596..10dd05b45 100644 --- a/src/vm/jit/x86_64/md-abi.c +++ b/src/vm/jit/x86_64/md-abi.c @@ -28,7 +28,7 @@ #include "vm/jit/x86_64/md-abi.h" -#include "vm/descriptor.h" +#include "vm/descriptor.hpp" #include "vm/global.h" #include "vm/jit/abi.h" diff --git a/src/vm/jit/x86_64/patcher.c b/src/vm/jit/x86_64/patcher.c index 32008300e..ae4b7aa21 100644 --- a/src/vm/jit/x86_64/patcher.c +++ b/src/vm/jit/x86_64/patcher.c @@ -32,7 +32,7 @@ #include "vm/jit/x86_64/codegen.h" #include "vm/jit/x86_64/md.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/native.hpp" @@ -59,6 +59,21 @@ void patcher_patch_code(patchref_t *pr) md_icacheflush((void*) pr->mpc, PATCHER_CALL_SIZE); } +/** + * Check if the trap instruction at the given PC is valid. + * + * @param pc Program counter. + * + * @return true if valid, false otherwise. + */ +bool patcher_is_valid_trap_instruction_at(void* pc) +{ + uint16_t mcode = *((uint16_t*) pc); + + // Check for the undefined instruction we use. + return (mcode == 0x0b0f); +} + /* patcher_resolve_classref_to_classinfo *************************************** diff --git a/src/vm/jit/x86_64/solaris/md-os.c b/src/vm/jit/x86_64/solaris/md-os.c index 14824a49e..cce569be9 100644 --- a/src/vm/jit/x86_64/solaris/md-os.c +++ b/src/vm/jit/x86_64/solaris/md-os.c @@ -38,7 +38,7 @@ #include "threads/thread.hpp" #include "vm/jit/builtin.hpp" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/jit/asmpart.h" #include "vm/jit/executionstate.h" diff --git a/src/vm/linker.cpp b/src/vm/linker.cpp index 50639b736..b1bd60a42 100644 --- a/src/vm/linker.cpp +++ b/src/vm/linker.cpp @@ -30,14 +30,14 @@ #include "vm/types.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/native.hpp" #include "threads/lock.hpp" #include "threads/mutex.hpp" -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" #include "vm/access.hpp" #include "vm/array.hpp" @@ -1108,8 +1108,8 @@ static arraydescriptor *link_array(classinfo *c) desc->elementvftbl = compvftbl->arraydesc->elementvftbl; if (compvftbl->arraydesc->dimension >= 255) { - log_text("Creating array of dimension >255"); - assert(0); + exceptions_throw_illegalargumentexception(); + return NULL; } desc->dimension = compvftbl->arraydesc->dimension + 1; diff --git a/src/vm/loader.cpp b/src/vm/loader.cpp index 81ab0ad85..7bc8ff4a1 100644 --- a/src/vm/loader.cpp +++ b/src/vm/loader.cpp @@ -32,14 +32,14 @@ #include "vm/types.h" #include "mm/dumpmemory.hpp" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/llni.h" #include "threads/mutex.hpp" #include "toolbox/hashtable.h" -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" #include "vm/jit/builtin.hpp" #include "vm/classcache.hpp" @@ -61,7 +61,7 @@ #if defined(ENABLE_JAVASE) -# include "vm/annotation.h" +# include "vm/annotation.hpp" # include "vm/stackmap.h" #endif diff --git a/src/vm/loader.hpp b/src/vm/loader.hpp index 3e30e4a27..b452176cb 100644 --- a/src/vm/loader.hpp +++ b/src/vm/loader.hpp @@ -37,7 +37,7 @@ typedef struct classbuffer classbuffer; #include "vm/types.h" -#include "vm/descriptor.h" +#include "vm/descriptor.hpp" #include "vm/class.hpp" #include "vm/global.h" #include "vm/method.hpp" diff --git a/src/vm/method.cpp b/src/vm/method.cpp index 59cafe934..21f542400 100644 --- a/src/vm/method.cpp +++ b/src/vm/method.cpp @@ -31,7 +31,7 @@ #include "vm/types.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/llni.h" diff --git a/src/vm/method.hpp b/src/vm/method.hpp index b7e12c8d6..6fbc0c153 100644 --- a/src/vm/method.hpp +++ b/src/vm/method.hpp @@ -41,7 +41,7 @@ typedef struct codeinfo codeinfo; #include "threads/mutex.hpp" #include "vm/jit/builtin.hpp" -#include "vm/descriptor.h" +#include "vm/descriptor.hpp" #include "vm/global.h" #include "vm/linker.hpp" #include "vm/loader.hpp" diff --git a/src/vm/options.c b/src/vm/options.c index 3c3bace70..b5b88a710 100644 --- a/src/vm/options.c +++ b/src/vm/options.c @@ -30,7 +30,7 @@ #include #include -#include "mm/memory.h" +#include "mm/memory.hpp" #include "vm/options.h" #include "vm/os.hpp" diff --git a/src/vm/os.hpp b/src/vm/os.hpp index 66de93d51..052c0a370 100644 --- a/src/vm/os.hpp +++ b/src/vm/os.hpp @@ -145,6 +145,7 @@ public: static inline int mprotect(void* addr, size_t len, int prot); static inline ssize_t readlink(const char* path, char* buf, size_t bufsiz); static inline int scandir(const char* dir, struct dirent*** namelist, int(*filter)(const struct dirent*), int(*compar)(const void*, const void*)); + static inline ssize_t send(int s, const void* buf, size_t len, int flags); static inline int setsockopt(int s, int level, int optname, const void* optval, socklen_t optlen); static inline int shutdown(int s, int how); static inline int socket(int domain, int type, int protocol); @@ -527,6 +528,16 @@ inline int os::scandir(const char *dir, struct dirent ***namelist, int(*filter)( #endif } +inline ssize_t os::send(int s, const void* buf, size_t len, int flags) +{ + // TODO Should be restartable on Linux and interruptible on Solaris. +#if defined(HAVE_SEND) + return ::send(s, buf, len, flags); +#else +# error send not available +#endif +} + inline int os::setsockopt(int s, int level, int optname, const void* optval, socklen_t optlen) { #if defined(HAVE_SETSOCKOPT) diff --git a/src/vm/package.cpp b/src/vm/package.cpp index a112aca2f..f5287bf15 100644 --- a/src/vm/package.cpp +++ b/src/vm/package.cpp @@ -27,7 +27,7 @@ #include -#include "mm/memory.h" +#include "mm/memory.hpp" #include "vm/options.h" #include "vm/package.hpp" diff --git a/src/vm/properties.cpp b/src/vm/properties.cpp index f5b66db4d..e2f385838 100644 --- a/src/vm/properties.cpp +++ b/src/vm/properties.cpp @@ -34,7 +34,7 @@ #include #include -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/llni.h" diff --git a/src/vm/references.h b/src/vm/references.h index be2455b00..f880b7913 100644 --- a/src/vm/references.h +++ b/src/vm/references.h @@ -62,7 +62,7 @@ typedef union parseddesc { #include "vm/types.h" #include "vm/class.hpp" -#include "vm/descriptor.h" +#include "vm/descriptor.hpp" #include "vm/field.hpp" #include "vm/global.h" #include "vm/method.hpp" diff --git a/src/vm/resolve.cpp b/src/vm/resolve.cpp index d4b4e9699..80d8a4a11 100644 --- a/src/vm/resolve.cpp +++ b/src/vm/resolve.cpp @@ -29,11 +29,11 @@ #include "vm/types.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "vm/access.hpp" #include "vm/classcache.hpp" -#include "vm/descriptor.h" +#include "vm/descriptor.hpp" #include "vm/exceptions.hpp" #include "vm/global.h" #include "vm/globals.hpp" diff --git a/src/vm/rt-timing.c b/src/vm/rt-timing.c index 2064de2d0..04384f853 100644 --- a/src/vm/rt-timing.c +++ b/src/vm/rt-timing.c @@ -32,7 +32,7 @@ #include "vm/types.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "vm/global.h" #include "vm/rt-timing.h" diff --git a/src/vm/rt-timing.h b/src/vm/rt-timing.h index 26d31a41b..0c18ac0a5 100644 --- a/src/vm/rt-timing.h +++ b/src/vm/rt-timing.h @@ -34,7 +34,7 @@ #include "vm/types.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "vm/global.h" diff --git a/src/vm/signal.c b/src/vm/signal.c deleted file mode 100644 index ed7d495e4..000000000 --- a/src/vm/signal.c +++ /dev/null @@ -1,401 +0,0 @@ -/* src/vm/signal.c - machine independent signal functions - - Copyright (C) 1996-2005, 2006, 2007, 2008 - CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO - - 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. - -*/ - - -#include "config.h" - -#include -#include -#include -#include - -#if defined(__DARWIN__) -/* If we compile with -ansi on darwin, is not - included. So let's do it here. */ -# include -# include -#endif - -#include "arch.h" - -#if defined(ENABLE_GC_BOEHM) -# include "mm/memory.h" -#endif - -#include "threads/thread.hpp" -#include "threads/threadlist.hpp" - -#include "vm/exceptions.hpp" -#include "vm/globals.hpp" -#include "vm/method.hpp" -#include "vm/options.h" -#include "vm/signallocal.h" -#include "vm/vm.hpp" - -#if defined(ENABLE_STATISTICS) -# include "vm/statistics.h" -#endif - - -/* function prototypes ********************************************************/ - -void signal_handler_sighup(int sig, siginfo_t *siginfo, void *_p); - - -/* signal_init ***************************************************************** - - Initializes the signal subsystem and installs the signal handler. - -*******************************************************************************/ - -bool signal_init(void) -{ -#if !defined(__CYGWIN__) - sigset_t mask; - - TRACESUBSYSTEMINITIALIZATION("signal_init"); - -#if defined(__LINUX__) && defined(ENABLE_THREADS) - /* XXX Remove for exact-GC. */ - if (threads_pthreads_implementation_nptl) { -#endif - - /* Block the following signals (SIGINT for -c, SIGQUIT for - -\). We enable them later in signal_thread, but only for - this thread. */ - - if (sigemptyset(&mask) != 0) - vm_abort_errno("signal_init: sigemptyset failed"); - -#if !defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) - /* Let OpenJDK handle SIGINT itself. */ - - if (sigaddset(&mask, SIGINT) != 0) - vm_abort_errno("signal_init: sigaddset failed"); -#endif - -#if !defined(__FREEBSD__) - if (sigaddset(&mask, SIGQUIT) != 0) - vm_abort_errno("signal_init: sigaddset failed"); -#endif - - if (sigprocmask(SIG_BLOCK, &mask, NULL) != 0) - vm_abort_errno("signal_init: sigprocmask failed"); - -#if defined(__LINUX__) && defined(ENABLE_THREADS) - /* XXX Remove for exact-GC. */ - } -#endif - -#if defined(ENABLE_GC_BOEHM) - /* Allocate something so the garbage collector's signal handlers - are installed. */ - - (void) GCNEW(int); -#endif - - /* Install signal handlers for signals we want to catch in all - threads. */ - -#if defined(ENABLE_JIT) -# if defined(ENABLE_INTRP) - if (!opt_intrp) { -# endif - /* SIGSEGV handler */ - - signal_register_signal(SIGSEGV, (functionptr) md_signal_handler_sigsegv, - SA_NODEFER | SA_SIGINFO); - -# if defined(SIGBUS) - signal_register_signal(SIGBUS, (functionptr) md_signal_handler_sigsegv, - SA_NODEFER | SA_SIGINFO); -# endif - -# if SUPPORT_HARDWARE_DIVIDE_BY_ZERO - /* SIGFPE handler */ - - signal_register_signal(SIGFPE, (functionptr) md_signal_handler_sigfpe, - SA_NODEFER | SA_SIGINFO); -# endif - -# if defined(__ALPHA__) || defined(__ARM__) || defined(__I386__) || defined(__MIPS__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__) || defined(__M68K__) - /* XXX use better defines for that (in arch.h) */ - /* SIGILL handler */ - - signal_register_signal(SIGILL, (functionptr) md_signal_handler_sigill, - SA_NODEFER | SA_SIGINFO); -# endif - -# if defined(__POWERPC__) - /* XXX use better defines for that (in arch.h) */ - /* SIGTRAP handler */ - - signal_register_signal(SIGTRAP, (functionptr) md_signal_handler_sigtrap, - SA_NODEFER | SA_SIGINFO); -# endif -# if defined(ENABLE_INTRP) - } -# endif - -#if defined(__DARWIN__) - do { - struct utsname name; - kern_return_t kr; - - /* Check if we're on 10.4 (Tiger/8.x) or earlier */ - if (uname(&name) != 0) - break; - - /* Make sure the string is large enough */ - /* Check the major number (ascii comparison) */ - /* Verify that we're not looking at '10.' by checking for a trailing period. */ - if (name.release[0] == '\0' || name.release[0] > '8' || name.release[1] != '.') - break; - - /* Reset CrashReporter's task signal handler */ - kr = task_set_exception_ports(mach_task_self(), - EXC_MASK_BAD_ACCESS -# if defined(__I386__) - | EXC_MASK_BAD_INSTRUCTION -#endif - , MACH_PORT_NULL, - EXCEPTION_STATE_IDENTITY, - MACHINE_THREAD_STATE); - - assert(kr == KERN_SUCCESS); - } while (false); -#endif -#endif /* !defined(ENABLE_JIT) */ - -#if defined(ENABLE_THREADS) - /* SIGHUP handler for threads_thread_interrupt */ - - signal_register_signal(Signal_INTERRUPT_SYSTEM_CALL, (functionptr) signal_handler_sighup, 0); -#endif - -#if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO) - /* SIGUSR1 handler for the exact GC to suspend threads */ - - signal_register_signal(SIGUSR1, (functionptr) md_signal_handler_sigusr1, - SA_SIGINFO); -#endif - -#if defined(ENABLE_THREADS) && defined(ENABLE_PROFILING) - /* SIGUSR2 handler for profiling sampling */ - - signal_register_signal(SIGUSR2, (functionptr) md_signal_handler_sigusr2, - SA_SIGINFO); -#endif - -#endif /* !defined(__CYGWIN__) */ - - return true; -} - - -/* signal_register_signal ****************************************************** - - Register the specified handler with the specified signal. - -*******************************************************************************/ - -void signal_register_signal(int signum, functionptr handler, int flags) -{ - struct sigaction act; - - void (*function)(int, siginfo_t *, void *); - - function = (void (*)(int, siginfo_t *, void *)) handler; - - if (sigemptyset(&act.sa_mask) != 0) - vm_abort_errno("signal_register_signal: sigemptyset failed"); - - act.sa_sigaction = function; - act.sa_flags = flags; - - if (sigaction(signum, &act, NULL) != 0) - vm_abort_errno("signal_register_signal: sigaction failed"); -} - - -/* signal_thread ************************************************************ - - This thread sets the signal mask to catch the user input signals - (SIGINT, SIGQUIT). We use such a thread, so we don't get the - signals on every single thread running. - -*******************************************************************************/ - -static void signal_thread(void) -{ - threadobject *t; - sigset_t mask; - int sig; - int result; - - t = THREADOBJECT; - - if (sigemptyset(&mask) != 0) - vm_abort_errno("signal_thread: sigemptyset failed"); - -#if !defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) - /* Let OpenJDK handle SIGINT itself. */ - - if (sigaddset(&mask, SIGINT) != 0) - vm_abort_errno("signal_thread: sigaddset failed"); -#endif - -#if !defined(__FREEBSD__) - if (sigaddset(&mask, SIGQUIT) != 0) - vm_abort_errno("signal_thread: sigaddset failed"); -#endif - - for (;;) { - /* just wait for a signal */ - -#if defined(ENABLE_THREADS) - thread_set_state_waiting(t); -#endif - - // sigwait can return EINTR (unlike what the Linux man-page - // says). - do { - result = sigwait(&mask, &sig); - } while (result == EINTR); - - if (result != 0) - vm_abort_errnum(result, "signal_thread: sigwait failed"); - -#if defined(ENABLE_THREADS) - thread_set_state_runnable(t); -#endif - - /* Handle the signal. */ - - signal_thread_handler(sig); - } -} - - -/* signal_thread_handler ******************************************************* - - Handles the signals caught in the signal handler thread. Also used - from sun.misc.Signal with OpenJDK. - -*******************************************************************************/ - -void signal_thread_handler(int sig) -{ - switch (sig) { - case SIGINT: - /* exit the vm properly */ - - vm_exit(1); - break; - - case SIGQUIT: - /* print a thread dump */ -#if defined(ENABLE_THREADS) - ThreadList_dump_threads(); -#endif - -#if defined(ENABLE_STATISTICS) - if (opt_stat) - statistics_print_memory_usage(); -#endif - break; - -#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) - default: { - // For OpenJDK we dispatch all unknown signals to Java. - methodinfo* m = class_resolvemethod(class_sun_misc_Signal, utf_dispatch, utf_int__void); - (void) vm_call_method(m, NULL, sig); - - if (exceptions_get_exception()) { - log_println("signal_thread_handler: Java signal handler throw an exception while dispatching signal %d:", sig); - exceptions_print_stacktrace(); - vm_abort("signal_thread_handler: Aborting..."); - } - break; - } -#else - default: - vm_abort("signal_thread_handler: Unknown signal %d", sig); -#endif - } -} - - -/* signal_start_thread ********************************************************* - - Starts the signal handler thread. - -*******************************************************************************/ - -bool signal_start_thread(void) -{ -#if defined(ENABLE_THREADS) - utf *name; - - name = utf_new_char("Signal Handler"); - - if (!threads_thread_start_internal(name, signal_thread)) - return false; - - /* everything's ok */ - - return true; -#else -#warning FIX ME! -#endif -} - - -/* signal_handler_sighup ******************************************************* - - This handler is required by threads_thread_interrupt and does - nothing. - -*******************************************************************************/ - -#if defined(ENABLE_THREADS) -void signal_handler_sighup(int sig, siginfo_t *siginfo, void *_p) -{ - /* do nothing */ -} -#endif - - -/* - * 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/signal.cpp b/src/vm/signal.cpp new file mode 100644 index 000000000..15d6263b6 --- /dev/null +++ b/src/vm/signal.cpp @@ -0,0 +1,401 @@ +/* src/vm/signal.c - machine independent signal functions + + Copyright (C) 1996-2005, 2006, 2007, 2008 + CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO + + 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. + +*/ + + +#include "config.h" + +#include +#include +#include +#include + +#if defined(__DARWIN__) +/* If we compile with -ansi on darwin, is not + included. So let's do it here. */ +# include +# include +#endif + +#include "arch.h" + +#if defined(ENABLE_GC_BOEHM) +# include "mm/memory.hpp" +#endif + +#include "threads/thread.hpp" +#include "threads/threadlist.hpp" + +#include "vm/exceptions.hpp" +#include "vm/globals.hpp" +#include "vm/method.hpp" +#include "vm/options.h" +#include "vm/signallocal.hpp" +#include "vm/vm.hpp" + +#if defined(ENABLE_STATISTICS) +# include "vm/statistics.h" +#endif + + +/* function prototypes ********************************************************/ + +void signal_handler_sighup(int sig, siginfo_t *siginfo, void *_p); + + +/* signal_init ***************************************************************** + + Initializes the signal subsystem and installs the signal handler. + +*******************************************************************************/ + +bool signal_init(void) +{ +#if !defined(__CYGWIN__) + sigset_t mask; + + TRACESUBSYSTEMINITIALIZATION("signal_init"); + +#if defined(__LINUX__) && defined(ENABLE_THREADS) + /* XXX Remove for exact-GC. */ + if (threads_pthreads_implementation_nptl) { +#endif + + /* Block the following signals (SIGINT for -c, SIGQUIT for + -\). We enable them later in signal_thread, but only for + this thread. */ + + if (sigemptyset(&mask) != 0) + vm_abort_errno("signal_init: sigemptyset failed"); + +#if !defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) + /* Let OpenJDK handle SIGINT itself. */ + + if (sigaddset(&mask, SIGINT) != 0) + vm_abort_errno("signal_init: sigaddset failed"); +#endif + +#if !defined(__FREEBSD__) + if (sigaddset(&mask, SIGQUIT) != 0) + vm_abort_errno("signal_init: sigaddset failed"); +#endif + + if (sigprocmask(SIG_BLOCK, &mask, NULL) != 0) + vm_abort_errno("signal_init: sigprocmask failed"); + +#if defined(__LINUX__) && defined(ENABLE_THREADS) + /* XXX Remove for exact-GC. */ + } +#endif + +#if defined(ENABLE_GC_BOEHM) + /* Allocate something so the garbage collector's signal handlers + are installed. */ + + (void) GCNEW(int); +#endif + + /* Install signal handlers for signals we want to catch in all + threads. */ + +#if defined(ENABLE_JIT) +# if defined(ENABLE_INTRP) + if (!opt_intrp) { +# endif + /* SIGSEGV handler */ + + signal_register_signal(SIGSEGV, (functionptr) md_signal_handler_sigsegv, + SA_NODEFER | SA_SIGINFO); + +# if defined(SIGBUS) + signal_register_signal(SIGBUS, (functionptr) md_signal_handler_sigsegv, + SA_NODEFER | SA_SIGINFO); +# endif + +# if SUPPORT_HARDWARE_DIVIDE_BY_ZERO + /* SIGFPE handler */ + + signal_register_signal(SIGFPE, (functionptr) md_signal_handler_sigfpe, + SA_NODEFER | SA_SIGINFO); +# endif + +# if defined(__ALPHA__) || defined(__ARM__) || defined(__I386__) || defined(__MIPS__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__) || defined(__M68K__) + /* XXX use better defines for that (in arch.h) */ + /* SIGILL handler */ + + signal_register_signal(SIGILL, (functionptr) md_signal_handler_sigill, + SA_NODEFER | SA_SIGINFO); +# endif + +# if defined(__POWERPC__) + /* XXX use better defines for that (in arch.h) */ + /* SIGTRAP handler */ + + signal_register_signal(SIGTRAP, (functionptr) md_signal_handler_sigtrap, + SA_NODEFER | SA_SIGINFO); +# endif +# if defined(ENABLE_INTRP) + } +# endif + +#if defined(__DARWIN__) + do { + struct utsname name; + kern_return_t kr; + + /* Check if we're on 10.4 (Tiger/8.x) or earlier */ + if (uname(&name) != 0) + break; + + /* Make sure the string is large enough */ + /* Check the major number (ascii comparison) */ + /* Verify that we're not looking at '10.' by checking for a trailing period. */ + if (name.release[0] == '\0' || name.release[0] > '8' || name.release[1] != '.') + break; + + /* Reset CrashReporter's task signal handler */ + kr = task_set_exception_ports(mach_task_self(), + EXC_MASK_BAD_ACCESS +# if defined(__I386__) + | EXC_MASK_BAD_INSTRUCTION +#endif + , MACH_PORT_NULL, + EXCEPTION_STATE_IDENTITY, + MACHINE_THREAD_STATE); + + assert(kr == KERN_SUCCESS); + } while (false); +#endif +#endif /* !defined(ENABLE_JIT) */ + +#if defined(ENABLE_THREADS) + /* SIGHUP handler for threads_thread_interrupt */ + + signal_register_signal(Signal_INTERRUPT_SYSTEM_CALL, (functionptr) signal_handler_sighup, 0); +#endif + +#if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO) + /* SIGUSR1 handler for the exact GC to suspend threads */ + + signal_register_signal(SIGUSR1, (functionptr) md_signal_handler_sigusr1, + SA_SIGINFO); +#endif + +#if defined(ENABLE_THREADS) && defined(ENABLE_PROFILING) + /* SIGUSR2 handler for profiling sampling */ + + signal_register_signal(SIGUSR2, (functionptr) md_signal_handler_sigusr2, + SA_SIGINFO); +#endif + +#endif /* !defined(__CYGWIN__) */ + + return true; +} + + +/* signal_register_signal ****************************************************** + + Register the specified handler with the specified signal. + +*******************************************************************************/ + +void signal_register_signal(int signum, functionptr handler, int flags) +{ + struct sigaction act; + + void (*function)(int, siginfo_t *, void *); + + function = (void (*)(int, siginfo_t *, void *)) handler; + + if (sigemptyset(&act.sa_mask) != 0) + vm_abort_errno("signal_register_signal: sigemptyset failed"); + + act.sa_sigaction = function; + act.sa_flags = flags; + + if (sigaction(signum, &act, NULL) != 0) + vm_abort_errno("signal_register_signal: sigaction failed"); +} + + +/* signal_thread ************************************************************ + + This thread sets the signal mask to catch the user input signals + (SIGINT, SIGQUIT). We use such a thread, so we don't get the + signals on every single thread running. + +*******************************************************************************/ + +static void signal_thread(void) +{ + threadobject *t; + sigset_t mask; + int sig; + int result; + + t = THREADOBJECT; + + if (sigemptyset(&mask) != 0) + vm_abort_errno("signal_thread: sigemptyset failed"); + +#if !defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) + /* Let OpenJDK handle SIGINT itself. */ + + if (sigaddset(&mask, SIGINT) != 0) + vm_abort_errno("signal_thread: sigaddset failed"); +#endif + +#if !defined(__FREEBSD__) + if (sigaddset(&mask, SIGQUIT) != 0) + vm_abort_errno("signal_thread: sigaddset failed"); +#endif + + for (;;) { + /* just wait for a signal */ + +#if defined(ENABLE_THREADS) + thread_set_state_waiting(t); +#endif + + // sigwait can return EINTR (unlike what the Linux man-page + // says). + do { + result = sigwait(&mask, &sig); + } while (result == EINTR); + + if (result != 0) + vm_abort_errnum(result, "signal_thread: sigwait failed"); + +#if defined(ENABLE_THREADS) + thread_set_state_runnable(t); +#endif + + /* Handle the signal. */ + + signal_thread_handler(sig); + } +} + + +/* signal_thread_handler ******************************************************* + + Handles the signals caught in the signal handler thread. Also used + from sun.misc.Signal with OpenJDK. + +*******************************************************************************/ + +void signal_thread_handler(int sig) +{ + switch (sig) { + case SIGINT: + /* exit the vm properly */ + + vm_exit(1); + break; + + case SIGQUIT: + /* print a thread dump */ +#if defined(ENABLE_THREADS) + ThreadList::dump_threads(); +#endif + +#if defined(ENABLE_STATISTICS) + if (opt_stat) + statistics_print_memory_usage(); +#endif + break; + +#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) + default: { + // For OpenJDK we dispatch all unknown signals to Java. + methodinfo* m = class_resolvemethod(class_sun_misc_Signal, utf_dispatch, utf_int__void); + (void) vm_call_method(m, NULL, sig); + + if (exceptions_get_exception()) { + log_println("signal_thread_handler: Java signal handler throw an exception while dispatching signal %d:", sig); + exceptions_print_stacktrace(); + vm_abort("signal_thread_handler: Aborting..."); + } + break; + } +#else + default: + vm_abort("signal_thread_handler: Unknown signal %d", sig); +#endif + } +} + + +/* signal_start_thread ********************************************************* + + Starts the signal handler thread. + +*******************************************************************************/ + +bool signal_start_thread(void) +{ +#if defined(ENABLE_THREADS) + utf *name; + + name = utf_new_char("Signal Handler"); + + if (!threads_thread_start_internal(name, signal_thread)) + return false; + + /* everything's ok */ + + return true; +#else +#warning FIX ME! +#endif +} + + +/* signal_handler_sighup ******************************************************* + + This handler is required by threads_thread_interrupt and does + nothing. + +*******************************************************************************/ + +#if defined(ENABLE_THREADS) +void signal_handler_sighup(int sig, siginfo_t *siginfo, void *_p) +{ + /* do nothing */ +} +#endif + + +/* + * 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/signallocal.h b/src/vm/signallocal.h deleted file mode 100644 index 469d949a4..000000000 --- a/src/vm/signallocal.h +++ /dev/null @@ -1,99 +0,0 @@ -/* src/vm/signallocal.h - machine independent signal functions - - Copyright (C) 1996-2005, 2006, 2007, 2008 - CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO - - 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. - -*/ - - -#ifndef _CACAO_SIGNAL_H -#define _CACAO_SIGNAL_H - -#include "config.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#include "vm/global.h" - - -// Signal defines. - -#if defined(__LINUX__) -// See openjdk/jdk/src/solaris/native/java/net/linux_close.c (sigWakeup) -// See openjdk/jdk/src/solaris/native/sun/nio/ch/NativeThread.c (INTERRUPT_SIGNAL) -# define Signal_INTERRUPT_SYSTEM_CALL (__SIGRTMAX - 2) -#else -# define Signal_INTERRUPT_SYSTEM_CALL SIGHUP -#endif - - -/* function prototypes ********************************************************/ - -bool signal_init(void); -void signal_register_signal(int signum, functionptr handler, int flags); - -void signal_thread_handler(int sig); -bool signal_start_thread(void); - -/* machine dependent signal handler */ - -void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p); - -#if SUPPORT_HARDWARE_DIVIDE_BY_ZERO -void md_signal_handler_sigfpe(int sig, siginfo_t *siginfo, void *_p); -#endif - -#if defined(__ALPHA__) || defined(__ARM__) || defined(__I386__) || defined(__MIPS__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__) || defined(__M68K__) -/* XXX use better defines for that (in arch.h) */ -void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p); -#endif - -#if defined(__POWERPC__) -/* XXX use better defines for that (in arch.h) */ -void md_signal_handler_sigtrap(int sig, siginfo_t *siginfo, void *_p); -#endif - -void md_signal_handler_sigusr1(int sig, siginfo_t *siginfo, void *_p); - -void md_signal_handler_sigusr2(int sig, siginfo_t *siginfo, void *_p); - -#ifdef __cplusplus -} -#endif - -#endif /* _CACAO_SIGNAL_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: - */ diff --git a/src/vm/signallocal.hpp b/src/vm/signallocal.hpp new file mode 100644 index 000000000..94d1727cc --- /dev/null +++ b/src/vm/signallocal.hpp @@ -0,0 +1,99 @@ +/* src/vm/signallocal.h - machine independent signal functions + + Copyright (C) 1996-2005, 2006, 2007, 2008 + CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO + + 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. + +*/ + + +#ifndef _CACAO_SIGNAL_H +#define _CACAO_SIGNAL_H + +#include "config.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include "vm/global.h" + + +// Signal defines. + +#if defined(__LINUX__) +// See openjdk/jdk/src/solaris/native/java/net/linux_close.c (sigWakeup) +// See openjdk/jdk/src/solaris/native/sun/nio/ch/NativeThread.c (INTERRUPT_SIGNAL) +# define Signal_INTERRUPT_SYSTEM_CALL (__SIGRTMAX - 2) +#else +# define Signal_INTERRUPT_SYSTEM_CALL SIGHUP +#endif + + +/* function prototypes ********************************************************/ + +bool signal_init(void); +void signal_register_signal(int signum, functionptr handler, int flags); + +void signal_thread_handler(int sig); +bool signal_start_thread(void); + +/* machine dependent signal handler */ + +void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p); + +#if SUPPORT_HARDWARE_DIVIDE_BY_ZERO +void md_signal_handler_sigfpe(int sig, siginfo_t *siginfo, void *_p); +#endif + +#if defined(__ALPHA__) || defined(__ARM__) || defined(__I386__) || defined(__MIPS__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__) || defined(__M68K__) +/* XXX use better defines for that (in arch.h) */ +void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p); +#endif + +#if defined(__POWERPC__) +/* XXX use better defines for that (in arch.h) */ +void md_signal_handler_sigtrap(int sig, siginfo_t *siginfo, void *_p); +#endif + +void md_signal_handler_sigusr1(int sig, siginfo_t *siginfo, void *_p); + +void md_signal_handler_sigusr2(int sig, siginfo_t *siginfo, void *_p); + +#ifdef __cplusplus +} +#endif + +#endif /* _CACAO_SIGNAL_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: + */ diff --git a/src/vm/stackmap.c b/src/vm/stackmap.c index 87117d05e..d4886be34 100644 --- a/src/vm/stackmap.c +++ b/src/vm/stackmap.c @@ -26,7 +26,7 @@ #include "config.h" #include "vm/types.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "vm/class.hpp" #include "vm/exceptions.hpp" diff --git a/src/vm/statistics.c b/src/vm/statistics.c index 27926b52e..9c07ef78b 100644 --- a/src/vm/statistics.c +++ b/src/vm/statistics.c @@ -44,7 +44,7 @@ #include "mm/gc.hpp" -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" #include "vm/class.hpp" #include "vm/field.hpp" diff --git a/src/vm/string.cpp b/src/vm/string.cpp index 184f8f66c..632f69e04 100644 --- a/src/vm/string.cpp +++ b/src/vm/string.cpp @@ -33,7 +33,7 @@ #include "vm/global.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/llni.h" diff --git a/src/vm/suck.cpp b/src/vm/suck.cpp index 1c1664a7e..1c801c563 100644 --- a/src/vm/suck.cpp +++ b/src/vm/suck.cpp @@ -32,12 +32,12 @@ #include "arch.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "threads/mutex.hpp" #include "toolbox/list.hpp" -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" #include "toolbox/util.h" #include "vm/exceptions.hpp" diff --git a/src/vm/utf8.c b/src/vm/utf8.c index 1d7d7605f..ccc5e0f74 100644 --- a/src/vm/utf8.c +++ b/src/vm/utf8.c @@ -30,7 +30,7 @@ #include "vm/types.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "threads/mutex.hpp" diff --git a/src/vm/vm.cpp b/src/vm/vm.cpp index 3cd7343b5..448e4a7e9 100644 --- a/src/vm/vm.cpp +++ b/src/vm/vm.cpp @@ -43,7 +43,7 @@ #include "mm/codememory.h" #include "mm/dumpmemory.hpp" #include "mm/gc.hpp" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/jni.hpp" #include "native/llni.h" @@ -55,7 +55,7 @@ #include "threads/lock.hpp" #include "threads/thread.hpp" -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" #include "vm/array.hpp" @@ -66,7 +66,7 @@ #include "vm/jit/builtin.hpp" #include "vm/classcache.hpp" #include "vm/exceptions.hpp" -#include "vm/finalizer.h" +#include "vm/finalizer.hpp" #include "vm/global.h" #include "vm/globals.hpp" #include "vm/initialize.hpp" @@ -74,7 +74,7 @@ #include "vm/os.hpp" #include "vm/primitive.hpp" #include "vm/properties.hpp" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/statistics.h" #include "vm/string.hpp" #include "vm/suck.hpp" @@ -189,6 +189,8 @@ enum { OPT_MS, OPT_MX, + OPT_XCHECK_JNI, + /* CACAO options */ OPT_VERBOSE1, @@ -212,6 +214,8 @@ enum { #if defined(ENABLE_VERIFIER) OPT_NOVERIFY, + OPT_XVERIFY_ALL, + OPT_XVERIFY_NONE, #if defined(TYPECHECK_VERBOSE) OPT_VERBOSETC, #endif @@ -304,7 +308,8 @@ opt_struct opts[] = { { "noasyncgc", false, OPT_IGNORE }, #if defined(ENABLE_VERIFIER) { "noverify", false, OPT_NOVERIFY }, - { "Xverify:none", false, OPT_NOVERIFY }, + { "Xverify:all", false, OPT_XVERIFY_ALL }, + { "Xverify:none", false, OPT_XVERIFY_NONE }, #endif { "v", false, OPT_VERBOSE1 }, { "verbose:", true, OPT_VERBOSE }, @@ -376,6 +381,8 @@ opt_struct opts[] = { { "Xss", true, OPT_SS }, { "ss", true, OPT_SS }, + { "Xcheck:jni", false, OPT_XCHECK_JNI }, + #if defined(ENABLE_PROFILING) { "Xprof:", true, OPT_PROF_OPTION }, { "Xprof", false, OPT_PROF }, @@ -976,6 +983,10 @@ VM::VM(JavaVMInitArgs* vm_args) } break; + case OPT_XCHECK_JNI: + // HotSpot compatibility option. + break; + case OPT_VERBOSE1: opt_verbose = true; break; @@ -1028,7 +1039,12 @@ VM::VM(JavaVMInitArgs* vm_args) break; #if defined(ENABLE_VERIFIER) + case OPT_XVERIFY_ALL: + opt_verify = true; + break; + case OPT_NOVERIFY: + case OPT_XVERIFY_NONE: opt_verify = false; break; #endif diff --git a/src/vm/zip.cpp b/src/vm/zip.cpp index b9c870c9e..601e31d08 100644 --- a/src/vm/zip.cpp +++ b/src/vm/zip.cpp @@ -34,10 +34,10 @@ #include "vm/types.h" -#include "vm/descriptor.h" /* needed to prevent circular dependency */ +#include "vm/descriptor.hpp" /* needed to prevent circular dependency */ #include "toolbox/hashtable.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "vm/global.h" #include "vm/suck.hpp" diff --git a/tests/regression/bugzilla/All.java b/tests/regression/bugzilla/All.java index 94e7d3d33..cdc16f1d5 100644 --- a/tests/regression/bugzilla/All.java +++ b/tests/regression/bugzilla/All.java @@ -34,7 +34,11 @@ PR57.class, PR58.class, PR65.class, PR80.class, -PR89.class +PR89.class, +PR112.class, +PR113.class, +PR114.class, +PR116.class }) public class All { diff --git a/tests/regression/bugzilla/PR112.java b/tests/regression/bugzilla/PR112.java new file mode 100644 index 000000000..7611ddd43 --- /dev/null +++ b/tests/regression/bugzilla/PR112.java @@ -0,0 +1,44 @@ +/* tests/regression/bugzilla/PR112.java + + Copyright (C) 2008 + CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO + + 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. + +*/ + + +import org.junit.Test; +import static org.junit.Assert.*; + +import java.lang.reflect.*; + +public class PR112 { + @Test ( expected = IllegalArgumentException.class ) + public void test() throws IllegalArgumentException { + // Derived from OpenJDK's jdk jtreg test + // java/lang/reflect/Array/ExceedMaxDim.java + Object o = Array.newInstance(Integer.TYPE, 0); + + for (int i = 1; i <= 254; i++) { + o = Array.newInstance(o.getClass(), 1); + } + + o = Array.newInstance(o.getClass(), 1); + } +} diff --git a/tests/regression/bugzilla/PR113.java b/tests/regression/bugzilla/PR113.java new file mode 100644 index 000000000..68662ab0b --- /dev/null +++ b/tests/regression/bugzilla/PR113.java @@ -0,0 +1,37 @@ +/* tests/regression/bugzilla/PR112.java + + Copyright (C) 2008 + CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO + + 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. + +*/ + + +import org.junit.Test; +import static org.junit.Assert.*; + +public class PR113 { + @Test + public void test() { + // Derived from OpenJDK's jdk jtreg test + // java/lang/Class/getModifiers/StripACC_SUPER.java + int modifiers = PR113.class.getModifiers(); + assertFalse(java.lang.reflect.Modifier.isSynchronized(modifiers)); + } +} diff --git a/tests/regression/bugzilla/PR114.java b/tests/regression/bugzilla/PR114.java new file mode 100644 index 000000000..84d6fa728 --- /dev/null +++ b/tests/regression/bugzilla/PR114.java @@ -0,0 +1,43 @@ +/* tests/regression/bugzilla/PR114.java + + Copyright (C) 2008 + CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO + + 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. + +*/ + + +import org.junit.Test; +import static org.junit.Assert.*; + +import java.io.File; + +public class PR114 { + @Test ( expected = NoClassDefFoundError.class ) + public void test() throws NoClassDefFoundError { + // Delete the class file which is extended. + new File("PR114$A.class").delete(); + + new A().sub(); + } + + class A { + public void sub() {} + } +} diff --git a/tests/regression/bugzilla/PR116.java b/tests/regression/bugzilla/PR116.java new file mode 100644 index 000000000..61cdbc2cf --- /dev/null +++ b/tests/regression/bugzilla/PR116.java @@ -0,0 +1,49 @@ +/* tests/regression/bugzilla/PR116.java + + Copyright (C) 2008 + CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO + + 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. + +*/ + + +import org.junit.Test; +import static org.junit.Assert.*; + +import java.lang.reflect.Array; + +public class PR116 { + private static final int N = 5; + private static class Foo {} + + @Test + public void test() { + for (int i = 1; i <= N; i++) { + int[] dim = new int[i]; + for (int j = 0; j < i; j++) + dim[j] = 23; + + Object o = Array.newInstance(Foo.class, dim); + //System.out.println("PR116: dim=" + i + ", class='" + o.getClass() + "'"); + + assertNotNull(o); + assertTrue(o.getClass().isArray()); + } + } +}