dumpmemory.hpp \
$(GC_FILE) \
gc.hpp \
- memory.c \
- memory.h
+ memory.cpp \
+ memory.hpp
libmm_la_LIBADD = \
$(GC_LIB)
#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 ***********************************************************/
#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"
#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 ***********************************************************/
#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"
#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"
#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"
#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 *****************************************************************
#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"
#include "threads/thread.hpp"
#include "mm/codememory.h"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "vm/global.h"
#include "vm/options.h"
#include <stdint.h>
#include "mm/dumpmemory.hpp"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "threads/thread.hpp"
// Includes.
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "threads/thread.hpp"
#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"
#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"
+++ /dev/null
-/* 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 <assert.h>
-#include <stdint.h>
-
-#if defined(__DARWIN__)
-/* If we compile with -ansi on darwin, <sys/types.h> is not
- included. So let's do it here. */
-# include <sys/types.h>
-#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:
- */
--- /dev/null
+/* 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 <assert.h>
+#include <stdint.h>
+
+#if defined(__DARWIN__)
+/* If we compile with -ansi on darwin, <sys/types.h> is not
+ included. So let's do it here. */
+# include <sys/types.h>
+#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:
+ */
+++ /dev/null
-/* 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 <stdint.h>
-
-
-// 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:
- */
--- /dev/null
+/* 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 <stdint.h>
+
+
+// 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:
+ */
#include "config.h"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "mm/tlh.h"
#include "vm/global.h"
#include "vm/types.h"
#include "mm/gc.hpp"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "native/jni.hpp"
#include "native/llni.h"
#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"
#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"
#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"
#include <assert.h>
#include <stdint.h>
-#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"
#include <functional>
#include <map>
-#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"
#include <errno.h>
#include <zlib.h>
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "native/jni.hpp"
#include "native/llni.h"
#include "vm/types.h"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "native/jni.hpp"
#include "native/llni.h"
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"
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 }
};
#include <stdint.h>
#include <stdlib.h>
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "native/jni.hpp"
#include "native/native.hpp"
#endif
#include "vm/jit/builtin.hpp"
+#include "vm/javaobjects.hpp"
#include "vm/properties.hpp"
#include "vm/string.hpp"
#include "vm/vm.hpp"
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"
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 }
};
#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"
}
-#if 0
/*
* Class: java/lang/Thread
* Method: activeCount
*/
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
}
*/
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
{ (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 },
#include "vm/types.h"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "native/jni.hpp"
#include "native/native.hpp"
#include "native/include/java_lang_Object.h"
#include "native/include/gnu_classpath_jdwp_VMFrame.h"
-#include "toolbox/logging.h"
+#include "toolbox/logging.hpp"
/*
#include <stdint.h>
#include <string.h>
-#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"
# 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"
# 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"
#include "vm/string.hpp"
#if defined(ENABLE_ANNOTATIONS)
-#include "vm/annotation.h"
+#include "vm/annotation.hpp"
#include "vm/vm.hpp"
#endif
#include <stdint.h>
#include <sys/stat.h>
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "native/jni.hpp"
#include "native/llni.h"
# 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)
# include <mach/mach.h>
#endif
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "mm/gc.hpp"
#include "native/jni.hpp"
#include "config.h"
+#include <assert.h>
#include <stdint.h>
#include "native/jni.hpp"
{
log_println("Java_java_lang_VMThread_countStackFrames: Deprecated. Not implemented.");
- return 0;
+ return 0;
}
h = (java_handle_t *) _this;
t = thread_get_thread(h);
+ assert(t != NULL);
threads_thread_interrupt(t);
#endif
h = (java_handle_t *) _this;
t = thread_get_thread(h);
+ assert(t != NULL);
return thread_is_interrupted(t);
#else
h = (java_handle_t *) _this;
t = thread_get_thread(h);
+ assert(t != NULL);
threads_set_thread_priority(t->tid, priority);
#endif
h = (java_handle_t *) _this;
t = thread_get_thread(h);
+ assert(t != NULL);
state = cacaothread_get_state(t);
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;
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"
# 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"
#include <assert.h>
#include <stdint.h>
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "native/jni.hpp"
#include "native/llni.h"
#include "native/vm/reflection.hpp"
-#include "toolbox/logging.h"
+#include "toolbox/logging.hpp"
#include "vm/class.hpp"
#include "vm/exceptions.hpp"
#include "vm/os.hpp"
#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-# include "mm/memory.h"
+# include "mm/memory.hpp"
# include "native/native.hpp"
// Include this one early.
#include "native/vm/openjdk/hpi.hpp"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "native/native.hpp"
#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"
#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"
#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"
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);
}
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;
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;
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)
/* 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;
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;
}
/* 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;
}
jobjectArray JVM_GetAllThreads(JNIEnv *env, jclass dummy)
{
- log_println("JVM_GetAllThreads: IMPLEMENT ME!");
+ // Get a list of all active threads.
+ list<threadobject*> 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<threadobject*>::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;
}
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;
}
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;
/* 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:
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:
#include "native/vm/openjdk/management.hpp"
-#include "toolbox/logging.h"
+#include "toolbox/logging.hpp"
#include "vm/os.hpp"
#include "vm/vm.hpp"
#include "threads/atomic.hpp"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "native/jni.hpp"
#include "native/llni.h"
}
+/*
+ * 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
}
+/*
+ * 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<int32_t>(o, offset);
+}
+
+
/*
* Class: sun/misc/Unsafe
* Method: getByteVolatile
}
+/*
+ * 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<int32_t>(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<int32_t>(o, offset);
+}
+
+
/*
* Class: sun/misc/Unsafe
* Method: getIntVolatile
{ (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
{ (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 },
#include "vm/types.h"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "native/llni.h"
#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"
}
+/* 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;
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
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;
// Wake the waiting threads.
current->flc_cond->broadcast();
+ current->flc_object = NULL;
current = current->flc_next;
}
#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"
#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"
#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"
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);
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);
// Includes.
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "native/localref.hpp"
#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
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;
}
+/**
+ * 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.
ThreadList::lock();
if (t->state != THREAD_STATE_TERMINATED) {
- t->state = THREAD_STATE_RUNNABLE;
+ thread_set_state(t, THREAD_STATE_RUNNABLE);
DEBUGTHREADS("is RUNNABLE", 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);
}
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);
}
}
+/* 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
ThreadList::lock();
- t->state = THREAD_STATE_TERMINATED;
+ thread_set_state(t, THREAD_STATE_TERMINATED);
DEBUGTHREADS("is TERMINATED", 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:
#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 **********************************************************/
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);
#include "threads/thread.hpp"
#include "toolbox/list.hpp"
-#include "toolbox/logging.h"
+#include "toolbox/logging.hpp"
#include "vm/jit/stacktrace.hpp"
}
+/**
+ * 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<threadobject*> &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.
*
static inline void add_to_active_thread_list(threadobject* t);
static void dump_threads();
+ static void get_active_threads(list<threadobject*> &list);
static inline threadobject* get_main_thread();
static threadobject* get_free_thread();
static int32_t get_free_thread_index();
hashtable.c \
hashtable.h \
list.hpp \
- logging.c \
- logging.h \
+ logging.cpp \
+ logging.hpp \
set.h \
set.c \
util.c \
#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"
#include "config.h"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "toolbox/bitvector.h"
#include "config.h"
#include "vm/types.h"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "threads/mutex.hpp"
+++ /dev/null
-/* 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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#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:
- */
--- /dev/null
+/* 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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:
+ */
+++ /dev/null
-/* 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 <stdio.h>
-#include <stdarg.h>
-
-#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:
- */
--- /dev/null
+/* 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 <stdio.h>
+#include <stdarg.h>
+
+#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:
+ */
#include "toolbox/set.h"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "vm/global.h"
#include "vm/types.h"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "vm/vm.hpp"
*/
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "toolbox/worklist.h"
if ENABLE_JAVASE
if ENABLE_ANNOTATIONS
ANNOTATION_SOURCES = \
- annotation.c \
- annotation.h
+ annotation.cpp \
+ annotation.hpp
endif
STACKMAP_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 \
resolve.cpp \
resolve.hpp \
$(RT_TIMING_SOURCES) \
- signal.c \
- signallocal.h \
+ signal.cpp \
+ signallocal.hpp \
$(STACKMAP_SOURCES) \
$(STATISTICS_SOURCES) \
string.cpp \
#include "vm/types.h"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "native/llni.h"
return true;
}
-#if defined(__cplusplus)
-}
#endif
+#if defined(__cplusplus)
+}
#endif
+++ /dev/null
-/* 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 <assert.h>
-#include <stdint.h>
-
-#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.
-
- <quote cite="http://jcp.org/en/jsr/detail?id=202">
- 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.
- </quote>
-
- 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:
- */
--- /dev/null
+/* 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 <assert.h>
+#include <stdint.h>
+
+#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.
+
+ <quote cite="http://jcp.org/en/jsr/detail?id=202">
+ 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.
+ </quote>
+
+ 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:
+ */
+++ /dev/null
-/* 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:
- */
--- /dev/null
+/* 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:
+ */
#include <cstddef>
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "toolbox/list.hpp"
#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"
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 */
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;
}
#include "vm/types.h"
#if defined(ENABLE_JAVASE)
-# include "vm/annotation.h"
+# include "vm/annotation.hpp"
#endif
#include "vm/field.hpp"
#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"
/* #define CLASSCACHE_VERBOSE */
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
/*============================================================================*/
/* STATISTICS */
/*============================================================================*/
CLASSCACHE_UNLOCK();
}
-#if defined(__cplusplus)
-}
-#endif
-
#endif /* NDEBUG */
/*
+++ /dev/null
-/* 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 <assert.h>
-
-#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; slot<hashsize; ++slot)
- pool->classrefhash.ptr[slot] = NULL;
-
- hashsize = DESCRIPTORHASH_INIT_SIZE;
- pool->descriptorhash.size = hashsize;
- pool->descriptorhash.entries = 0;
- pool->descriptorhash.ptr = DMNEW(void*, hashsize);
- for (slot=0; slot<hashsize; ++slot)
- pool->descriptorhash.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,"<class=NULL>");
- }
- 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,"<m%d>",d->regoff);
- }
- else {
- fprintf(file,"<r%d>",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; i<d->paramcount; ++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("<NOPARAMS>",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; slot<pool->classrefhash.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; slot<pool->descriptorhash.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:
- */
-
--- /dev/null
+/* 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 <assert.h>
+
+#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; slot<hashsize; ++slot)
+ pool->classrefhash.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; slot<hashsize; ++slot)
+ pool->descriptorhash.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,"<class=NULL>");
+ }
+ 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,"<m%d>",d->regoff);
+ }
+ else {
+ fprintf(file,"<r%d>",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; i<d->paramcount; ++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("<NOPARAMS>",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; slot<pool->classrefhash.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; slot<pool->descriptorhash.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:
+ */
+
+++ /dev/null
-/* 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 <stdint.h>
-
-#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:
- */
--- /dev/null
+/* 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 <stdint.h>
+
+#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:
+ */
#include "md-abi.h"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "native/llni.h"
#include "native/native.hpp"
#include <stdint.h>
#include <stdio.h>
-#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"
#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"
+++ /dev/null
-/* 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 <stdlib.h>
-
-#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:
- */
--- /dev/null
+/* 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 <stdlib.h>
+
+#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:
+ */
+++ /dev/null
-/* 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:
- */
--- /dev/null
+/* 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:
+ */
#include <stdint.h>
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "native/llni.h"
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);
};
set(_handle, offset_group, value);
}
+inline void java_lang_Thread::set_threadStatus(int32_t value)
+{
+ set(_handle, offset_threadStatus, value);
+}
+
/**
#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"
#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"
#include "arch.h"
#include "md-abi.h"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "vm/jit/builtin.hpp"
#include "vm/exceptions.hpp"
#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"
#include "vm/jit/alpha/codegen.h"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "threads/lock.hpp"
#include "vm/jit/alpha/md-abi.h"
#include "vm/global.h"
-#include "vm/signallocal.h"
+#include "vm/signallocal.hpp"
#include "vm/jit/asmpart.h"
#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"
#include "vm/jit/alpha/md-abi.h"
-#include "vm/descriptor.h"
+#include "vm/descriptor.hpp"
#include "vm/global.h"
#include "vm/jit/abi.h"
#include "vm/jit/alpha/md.h"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "native/native.hpp"
#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"
#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"
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);
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);
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
#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); \
#include "vm/jit/arm/codegen.h"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "threads/lock.hpp"
#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 *******************************************************************
#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"
#include "vm/jit/arm/md-abi.h"
-#include "vm/descriptor.h"
+#include "vm/descriptor.hpp"
#include "vm/global.h"
#include "vm/jit/abi.h"
#include <assert.h>
#include <stdint.h>
+#include "vm/jit/arm/codegen.h"
#include "vm/jit/arm/md.h"
#include "vm/jit/arm/md-abi.h"
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!)
{
uint32_t *pc;
uint32_t mcode;
- int32_t offset;
+ int32_t disp;
void *pa; /* patch address */
/* Go back to the actual load instruction. */
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)
/* 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;
#include "vm/jit/arm/md.h"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "native/native.hpp"
#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.
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);
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);
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);
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);
#endif
#include "mm/gc.hpp"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "native/llni.h"
#include "threads/mutex.hpp"
#include "threads/thread.hpp"
-#include "toolbox/logging.h"
+#include "toolbox/logging.hpp"
#include "toolbox/util.h"
#include "vm/array.hpp"
#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"
#include <assert.h>
#include <stdint.h>
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "vm/global.h"
#include "arch.h"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "vm/options.h"
#include "vm/vm.hpp"
#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"
#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"
#include "vm/types.h"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "vm/jit/disass.h"
#include "vm/types.h"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "vm/options.h"
#include <assert.h>
#include <stdint.h>
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "vm/jit/code.hpp"
#include "vm/jit/exceptiontable.h"
#include "md-abi.h"
-#include "vm/descriptor.h"
+#include "vm/descriptor.hpp"
#include "vm/os.hpp"
#include "vm/jit/abi.h"
#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"
#include "vm/types.h"
-#include "vm/signallocal.h"
+#include "vm/signallocal.hpp"
#include "vm/jit/asmpart.h"
#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"
#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"
#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"
#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"
#include "vm/jit/i386/md-abi.h"
-#include "vm/descriptor.h"
+#include "vm/descriptor.hpp"
#include "vm/global.h"
#include "vm/jit/abi.h"
#include "vm/jit/i386/codegen.h"
#include "vm/jit/i386/md.h"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "native/native.hpp"
#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"
#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"
#include "vm/jit/intrp/codegen.h"
#include "vm/jit/intrp/intrp.h"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "native/native.hpp"
#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"
#include "md-abi.h" /* required for TRACE_ARGS_NUM */
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "threads/thread.hpp"
#include "config.h"
#include "vm/types.h"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "native/native.hpp"
#include <stdint.h>
-#include "vm/descriptor.h"
+#include "vm/descriptor.hpp"
#include "vm/jit/ir/instruction.hpp"
#include <stdint.h>
-#include "vm/descriptor.h"
+#include "vm/descriptor.hpp"
#include "vm/jit/jit.hpp"
#include "vm/jit/replace.hpp"
#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"
#include <algorithm>
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "toolbox/list.hpp"
#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"
#include <assert.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/loop/graph.h"
#include "vm/jit/loop/loop.h"
/* #include <stdio.h> */
#include <stdlib.h>
-#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"
*/
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "vm/jit/builtin.hpp"
#include "vm/resolve.hpp"
#include "vm/jit/loop/loop.h"
#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"
#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"
/* 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.
*/
-#ifndef _EMIT_H_
-#define _EMIT_H_
+
+#ifndef _EMIT_H
+#define _EMIT_H
#include "config.h"
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:
+ */
#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"
#include "vm/jit/m68k/md.h"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "native/native.hpp"
#include "vm/jit/builtin.hpp"
#include <stdint.h>
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "toolbox/avl.h"
#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"
#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"
#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"
#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"
#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"
#include "vm/jit/mips/codegen.h"
#include "vm/jit/mips/md.h"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "native/native.hpp"
#include "config.h"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "vm/jit/code.hpp"
#include "vm/jit/oprofile-agent.hpp"
#include <stdint.h>
#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"
#include "config.h"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "toolbox/bitvector.h"
#include "config.h"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "toolbox/bitvector.h"
#include <stdio.h>
#include <stdlib.h>
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "toolbox/bitvector.h"
#include "toolbox/worklist.h"
#include "arch.h"
#include "md-abi.h"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "toolbox/bitvector.h"
#include "vm/jit/optimizing/lsra.h"
-#include "toolbox/logging.h"
+#include "toolbox/logging.hpp"
extern const char *string_java_lang_InternalError;
/* function prototypes */
#include "vm/types.h"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "threads/threadlist.hpp"
#include "threads/thread.hpp"
#include <assert.h>
#include <stdint.h>
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "threads/condition.hpp"
#include "threads/mutex.hpp"
#include "vm/types.h"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "vm/jit/jit.hpp"
#include <stdio.h>
#include <stdlib.h>
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "toolbox/bitvector.h"
#include "toolbox/worklist.h"
#include "config.h"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "toolbox/bitvector.h"
#include "toolbox/set.h"
#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"
#include <stdio.h>
#include <stdlib.h>
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "toolbox/bitvector.h"
#include "toolbox/worklist.h"
#include <stdio.h>
#include <stdlib.h>
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "toolbox/bitvector.h"
#include "toolbox/worklist.h"
#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"
#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"
// 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;
}
codeinfo *code;
patchref_t *pr;
bool result;
- java_handle_t *e;
#if !defined(NDEBUG)
patcher_function_list_t *l;
int i;
}
#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();
#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"
#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"
#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/powerpc/codegen.h"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "threads/lock.hpp"
#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"
#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"
#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"
#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"
#include "vm/jit/powerpc/md.h"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "native/native.hpp"
#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"
#include "vm/types.h"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "md-abi.h"
#include "vm/jit/powerpc64/codegen.h"
#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"
#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"
#include "vm/jit/powerpc64/md.h"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "native/native.hpp"
#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"
#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"
#include "native/localref.hpp"
#include "native/native.hpp"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "threads/lock.hpp"
#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"
#include "config.h"
-#include "vm/descriptor.h"
+#include "vm/descriptor.hpp"
#include "vm/global.h"
#include "vm/types.h"
#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"
#include <assert.h>
#include <stdint.h>
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "native/native.hpp"
#include "vm/jit/builtin.hpp"
#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"
#include "vm/types.h"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "threads/lock.hpp"
#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"
#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"
#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"
#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 <assert.h>
#include "vm/types.h"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "vm/jit/sparc64/codegen.h"
#include "vm/jit/sparc64/md.h"
#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"
#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"
#include "md.h"
#include "mm/gc.hpp"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "vm/jit/stacktrace.hpp"
#include "threads/thread.hpp"
-#include "toolbox/logging.h"
+#include "toolbox/logging.hpp"
#include "vm/array.hpp"
#include "vm/jit/builtin.hpp"
}
+/**
+ * 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
}
+/**
+ * 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.
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);
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
#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"
#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"
#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"
#include <assert.h>
#include <string.h>
-#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"
#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"
#include <assert.h>
#include <string.h>
-#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"
#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)
}
}
-#if defined(__cplusplus)
-}
-#endif
-
#endif /* TYPEINFO_DEBUG */
#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"
#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"
#include "threads/thread.hpp"
-#include "vm/signallocal.h"
+#include "vm/signallocal.hpp"
#include "vm/jit/asmpart.h"
#include "vm/jit/stacktrace.hpp"
#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"
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;
#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"
#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"
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 ***************************************
#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"
#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"
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;
#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"
#if defined(ENABLE_JAVASE)
-# include "vm/annotation.h"
+# include "vm/annotation.hpp"
# include "vm/stackmap.h"
#endif
#include "vm/types.h"
-#include "vm/descriptor.h"
+#include "vm/descriptor.hpp"
#include "vm/class.hpp"
#include "vm/global.h"
#include "vm/method.hpp"
#include "vm/types.h"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "native/llni.h"
#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"
#include <stdio.h>
#include <stdlib.h>
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "vm/options.h"
#include "vm/os.hpp"
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);
#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)
#include <stdint.h>
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "vm/options.h"
#include "vm/package.hpp"
#include <unistd.h>
#include <sys/utsname.h>
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "native/llni.h"
#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"
#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"
#include "vm/types.h"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "vm/global.h"
#include "vm/rt-timing.h"
#include "vm/types.h"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "vm/global.h"
+++ /dev/null
-/* 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 <assert.h>
-#include <signal.h>
-#include <stdint.h>
-#include <stdlib.h>
-
-#if defined(__DARWIN__)
-/* If we compile with -ansi on darwin, <sys/types.h> is not
- included. So let's do it here. */
-# include <sys/types.h>
-# include <sys/utsname.h>
-#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 <ctrl>-c, SIGQUIT for
- <ctrl>-\). 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:
- */
--- /dev/null
+/* 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 <assert.h>
+#include <signal.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#if defined(__DARWIN__)
+/* If we compile with -ansi on darwin, <sys/types.h> is not
+ included. So let's do it here. */
+# include <sys/types.h>
+# include <sys/utsname.h>
+#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 <ctrl>-c, SIGQUIT for
+ <ctrl>-\). 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:
+ */
+++ /dev/null
-/* 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 <signal.h>
-
-#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:
- */
--- /dev/null
+/* 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 <signal.h>
+
+#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:
+ */
#include "config.h"
#include "vm/types.h"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "vm/class.hpp"
#include "vm/exceptions.hpp"
#include "mm/gc.hpp"
-#include "toolbox/logging.h"
+#include "toolbox/logging.hpp"
#include "vm/class.hpp"
#include "vm/field.hpp"
#include "vm/global.h"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "native/llni.h"
#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"
#include "vm/types.h"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "threads/mutex.hpp"
#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"
#include "threads/lock.hpp"
#include "threads/thread.hpp"
-#include "toolbox/logging.h"
+#include "toolbox/logging.hpp"
#include "vm/array.hpp"
#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"
#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"
OPT_MS,
OPT_MX,
+ OPT_XCHECK_JNI,
+
/* CACAO options */
OPT_VERBOSE1,
#if defined(ENABLE_VERIFIER)
OPT_NOVERIFY,
+ OPT_XVERIFY_ALL,
+ OPT_XVERIFY_NONE,
#if defined(TYPECHECK_VERBOSE)
OPT_VERBOSETC,
#endif
{ "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 },
{ "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 },
}
break;
+ case OPT_XCHECK_JNI:
+ // HotSpot compatibility option.
+ break;
+
case OPT_VERBOSE1:
opt_verbose = true;
break;
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
#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"
PR58.class,
PR65.class,
PR80.class,
-PR89.class
+PR89.class,
+PR112.class,
+PR113.class,
+PR114.class,
+PR116.class
})
public class All {
--- /dev/null
+/* 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);
+ }
+}
--- /dev/null
+/* 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));
+ }
+}
--- /dev/null
+/* 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() {}
+ }
+}
--- /dev/null
+/* 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());
+ }
+ }
+}