* src/vm/initialize.h: Likewise.
* src/vm/resolve.c: Likewise.
* src/vm/resolve.h: Likewise.
* src/vm/initialize.cpp: Likewise.
* src/vm/initialize.hpp: Likewise.
* src/vm/resolve.cpp: New file.
* src/vm/resolve.hpp: Likewise.
* src/native/jni.cpp,
src/native/native.cpp,
src/native/vm/cldc1.1/java_lang_Class.cpp,
src/native/vm/gnuclasspath/java_lang_VMClass.cpp,
src/native/vm/gnuclasspath/java_lang_VMClassLoader.cpp,
src/native/vm/gnuclasspath/java_lang_reflect_VMField.cpp,
src/native/vm/gnuclasspath/java_lang_reflect_VMMethod.cpp,
src/native/vm/gnuclasspath/sun_reflect_ConstantPool.cpp,
src/native/vm/nativevm.cpp,
src/native/vm/openjdk/jvm.cpp,
src/native/vm/reflection.cpp,
src/native/vm/sun_misc_Unsafe.cpp,
src/vm/Makefile.am,
src/vm/class.c,
src/vm/javaobjects.cpp,
src/vm/jit/allocator/liveness.c,
src/vm/jit/allocator/lsra.c,
src/vm/jit/allocator/simplereg.c,
src/vm/jit/alpha/patcher.c,
src/vm/jit/argument.cpp,
src/vm/jit/arm/patcher.c,
src/vm/jit/builtin.cpp,
src/vm/jit/i386/patcher.c,
src/vm/jit/inline/inline.c,
src/vm/jit/intrp/intrp.h,
src/vm/jit/intrp/patcher.c,
src/vm/jit/jit.cpp,
src/vm/jit/jit.hpp,
src/vm/jit/loop/tracing.c,
src/vm/jit/m68k/patcher.c,
src/vm/jit/mips/patcher.c,
src/vm/jit/optimizing/bytecode_escape.c,
src/vm/jit/optimizing/lifetimes.c,
src/vm/jit/parse.c,
src/vm/jit/patcher-common.cpp,
src/vm/jit/powerpc/patcher.c,
src/vm/jit/powerpc64/patcher.c,
src/vm/jit/s390/patcher.c,
src/vm/jit/sparc64/patcher.c,
src/vm/jit/stack.c,
src/vm/jit/verify/typecheck-typeinferer.c,
src/vm/jit/verify/typecheck.c,
src/vm/jit/verify/typeinfo.c,
src/vm/jit/verify/typeinfo.h,
src/vm/jit/x86_64/patcher.c,
src/vm/linker.c,
src/vm/loader.cpp,
src/vm/method.c,
src/vm/vm.cpp: Adapted to above changes.
--HG--
rename : src/vm/initialize.c => src/vm/initialize.cpp
rename : src/vm/initialize.h => src/vm/initialize.hpp
rename : src/vm/resolve.c => src/vm/resolve.cpp
rename : src/vm/resolve.h => src/vm/resolve.hpp
#include "vm/exceptions.hpp"
#include "vm/global.h"
#include "vm/globals.hpp"
-#include "vm/initialize.h"
+#include "vm/initialize.hpp"
#include "vm/javaobjects.hpp"
#include "vm/loader.hpp"
#include "vm/options.h"
#include "vm/primitive.hpp"
-#include "vm/resolve.h"
+#include "vm/resolve.hpp"
#include "vm/statistics.h"
#include "vm/string.hpp"
#include "vm/vm.hpp"
#include "vm/loader.hpp"
#include "vm/options.h"
#include "vm/os.hpp"
-#include "vm/resolve.h"
+#include "vm/resolve.hpp"
#include "vm/string.hpp"
#include "vm/vm.hpp"
#endif
#include "vm/exceptions.hpp"
-#include "vm/initialize.h"
+#include "vm/initialize.hpp"
// Native functions are exported as C functions.
#include "vm/class.h"
#include "vm/exceptions.hpp"
#include "vm/globals.hpp"
-#include "vm/initialize.h"
+#include "vm/initialize.hpp"
#include "vm/javaobjects.hpp"
#include "vm/string.hpp"
#include "vm/classcache.h"
#include "vm/exceptions.hpp"
#include "vm/globals.hpp"
-#include "vm/initialize.h"
+#include "vm/initialize.hpp"
#include "vm/javaobjects.hpp"
#include "vm/linker.h"
#include "vm/loader.hpp"
#include "vm/jit/builtin.hpp"
#include "vm/exceptions.hpp"
#include "vm/global.h"
-#include "vm/initialize.h"
+#include "vm/initialize.hpp"
#include "vm/javaobjects.hpp"
#include "vm/loader.hpp"
#include "vm/primitive.hpp"
-#include "vm/resolve.h"
+#include "vm/resolve.hpp"
#include "vm/string.hpp"
#include "vm/utf8.h"
#include "vm/exceptions.hpp"
#include "vm/global.h"
#include "vm/globals.hpp"
-#include "vm/initialize.h"
+#include "vm/initialize.hpp"
#include "vm/javaobjects.hpp"
#include "vm/method.h"
-#include "vm/resolve.h"
+#include "vm/resolve.hpp"
#include "vm/string.hpp"
#include "vm/class.h"
#include "vm/exceptions.hpp"
#include "vm/javaobjects.hpp"
-#include "vm/resolve.h"
+#include "vm/resolve.hpp"
#include "vm/string.hpp"
#include "vm/utf8.h"
#include "vm/vm.hpp"
#include "native/vm/nativevm.hpp"
#include "vm/class.h"
-#include "vm/initialize.h"
+#include "vm/initialize.hpp"
#include "vm/method.h"
#include "vm/options.h"
#include "vm/os.hpp"
#include "vm/exceptions.hpp"
#include "vm/global.h"
#include "vm/globals.hpp"
-#include "vm/initialize.h"
+#include "vm/initialize.hpp"
#include "vm/javaobjects.hpp"
#include "vm/options.h"
#include "vm/os.hpp"
#include "vm/package.hpp"
#include "vm/primitive.hpp"
#include "vm/properties.hpp"
-#include "vm/resolve.h"
+#include "vm/resolve.hpp"
#include "vm/signallocal.h"
#include "vm/string.hpp"
#include "vm/vm.hpp"
#include "vm/exceptions.hpp"
#include "vm/global.h"
#include "vm/globals.hpp"
-#include "vm/initialize.h"
+#include "vm/initialize.hpp"
#include "vm/javaobjects.hpp"
#include "vm/method.h"
#include "vm/string.hpp"
#include "vm/jit/builtin.hpp"
#include "vm/exceptions.hpp"
-#include "vm/initialize.h"
+#include "vm/initialize.hpp"
#include "vm/javaobjects.hpp"
#include "vm/os.hpp"
#include "vm/string.hpp"
finalizer.h \
globals.cpp \
globals.hpp \
- initialize.c \
- initialize.h \
+ initialize.cpp \
+ initialize.hpp \
javaobjects.cpp \
javaobjects.hpp \
linker.c \
properties.cpp \
properties.hpp \
references.h \
- resolve.c \
- resolve.h \
+ resolve.cpp \
+ resolve.hpp \
$(RT_TIMING_SOURCES) \
signal.c \
signallocal.h \
#include "vm/linker.h"
#include "vm/loader.hpp"
#include "vm/options.h"
-#include "vm/resolve.h"
+#include "vm/resolve.hpp"
#if defined(ENABLE_STATISTICS)
# include "vm/statistics.h"
+++ /dev/null
-/* src/vm/initialize.c - static class initializer 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 <string.h>
-
-#include "vm/types.h"
-
-#include "threads/lock.hpp"
-
-#include "vm/jit/builtin.hpp"
-#include "vm/class.h"
-#include "vm/exceptions.hpp"
-#include "vm/global.h"
-#include "vm/globals.hpp"
-#include "vm/initialize.h"
-#include "vm/loader.hpp"
-#include "vm/options.h"
-#include "vm/vm.hpp"
-
-#if defined(ENABLE_STATISTICS)
-# include "vm/statistics.h"
-#endif
-
-#include "vm/jit/asmpart.h"
-
-
-/* private functions **********************************************************/
-
-static bool initialize_class_intern(classinfo *c);
-
-
-/* initialize_init *************************************************************
-
- Initialize important system classes.
-
-*******************************************************************************/
-
-void initialize_init(void)
-{
- TRACESUBSYSTEMINITIALIZATION("initialize_init");
-
-#if defined(ENABLE_JAVASE)
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-
- /* Nothing. */
-
-# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-
- if (!initialize_class(class_java_lang_String))
- vm_abort("initialize_init: Initialization failed: java.lang.String");
-
- if (!initialize_class(class_java_lang_System))
- vm_abort("initialize_init: Initialization failed: java.lang.System");
-
- if (!initialize_class(class_java_lang_ThreadGroup))
- vm_abort("initialize_init: Initialization failed: java.lang.ThreadGroup");
-
- if (!initialize_class(class_java_lang_Thread))
- vm_abort("initialize_init: Initialization failed: java.lang.Thread");
-
-# else
-# error unknown classpath configuration
-# endif
-
-#elif defined(ENABLE_JAVAME_CLDC1_1)
-
- /* Nothing. */
-
-#else
-# error unknown Java configuration
-#endif
-}
-
-/* initialize_class ************************************************************
-
- In Java, every class can have a static initialization
- function. This function has to be called BEFORE calling other
- methods or accessing static variables.
-
-*******************************************************************************/
-
-bool initialize_class(classinfo *c)
-{
- bool r;
-
- if (!makeinitializations)
- return true;
-
- LOCK_MONITOR_ENTER(c);
-
- /* maybe the class is already initalized or the current thread, which can
- pass the monitor, is currently initalizing this class */
-
- if (CLASS_IS_OR_ALMOST_INITIALIZED(c)) {
- LOCK_MONITOR_EXIT(c);
-
- return true;
- }
-
- /* if <clinit> throw an Error before, the class was marked with an
- error and we have to throw a NoClassDefFoundError */
-
- if (c->state & CLASS_ERROR) {
- exceptions_throw_noclassdeffounderror(c->name);
-
- LOCK_MONITOR_EXIT(c);
-
- /* ...but return true, this is ok (mauve test) */
-
- return true;
- }
-
- /* this initalizing run begins NOW */
-
- c->state |= CLASS_INITIALIZING;
-
- /* call the internal function */
-
- r = initialize_class_intern(c);
-
- /* if return value is not NULL everything was ok and the class is
- initialized */
-
- if (r)
- c->state |= CLASS_INITIALIZED;
-
- /* this initalizing run is done */
-
- c->state &= ~CLASS_INITIALIZING;
-
- LOCK_MONITOR_EXIT(c);
-
- return r;
-}
-
-
-/* initialize_class_intern *****************************************************
-
- This function MUST NOT be called directly, because of thread
- <clinit> race conditions.
-
-*******************************************************************************/
-
-static bool initialize_class_intern(classinfo *c)
-{
- methodinfo *m;
- java_handle_t *cause;
- classinfo *class;
-
- /* maybe the class is not already linked */
-
- if (!(c->state & CLASS_LINKED))
- if (!link_class(c))
- return false;
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- count_class_inits++;
-#endif
-
- /* Initialize super class. */
-
- if (c->super != NULL) {
- if (!(c->super->state & CLASS_INITIALIZED)) {
-#if !defined(NDEBUG)
- if (initverbose)
- log_message_class_message_class("Initialize super class ",
- c->super,
- " from ",
- c);
-#endif
-
- if (!initialize_class(c->super))
- return false;
- }
- }
-
- /* interfaces implemented need not to be initialized (VM Spec 2.17.4) */
-
- m = class_findmethod(c, utf_clinit, utf_void__void);
-
- if (m == NULL) {
-#if !defined(NDEBUG)
- if (initverbose)
- log_message_class("Class has no static class initializer: ", c);
-#endif
-
- return true;
- }
-
- /* Sun's and IBM's JVM don't care about the static flag */
-/* if (!(m->flags & ACC_STATIC)) { */
-/* log_text("Class initializer is not static!"); */
-
-#if !defined(NDEBUG)
- if (initverbose)
- log_message_class("Starting static class initializer for class: ", c);
-#endif
-
- /* now call the initializer */
-
- (void) vm_call_method(m, NULL);
-
- /* we have an exception or error */
-
- cause = exceptions_get_exception();
-
- if (cause != NULL) {
- /* class is NOT initialized and is marked with error */
-
- c->state |= CLASS_ERROR;
-
- /* Load java/lang/Exception for the instanceof check. */
-
- class = load_class_bootstrap(utf_java_lang_Exception);
-
- if (class == NULL)
- return false;
-
- /* Is this an exception? Yes, than wrap it. */
-
- if (builtin_instanceof(cause, class)) {
- /* clear exception, because we are calling jit code again */
-
- exceptions_clear_exception();
-
- /* wrap the exception */
-
- exceptions_throw_exceptionininitializererror(cause);
- }
-
- return false;
- }
-
-#if !defined(NDEBUG)
- if (initverbose)
- log_message_class("Finished static class initializer for class: ", c);
-#endif
-
- return true;
-}
-
-
-/*
- * 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/initialize.cpp - static class initializer 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 <string.h>
+
+#include "vm/types.h"
+
+#include "threads/lock.hpp"
+
+#include "vm/jit/builtin.hpp"
+#include "vm/class.h"
+#include "vm/exceptions.hpp"
+#include "vm/global.h"
+#include "vm/globals.hpp"
+#include "vm/initialize.hpp"
+#include "vm/loader.hpp"
+#include "vm/options.h"
+#include "vm/vm.hpp"
+
+#if defined(ENABLE_STATISTICS)
+# include "vm/statistics.h"
+#endif
+
+#include "vm/jit/asmpart.h"
+
+
+/* private functions **********************************************************/
+
+static bool initialize_class_intern(classinfo *c);
+
+
+/* initialize_init *************************************************************
+
+ Initialize important system classes.
+
+*******************************************************************************/
+
+void initialize_init(void)
+{
+ TRACESUBSYSTEMINITIALIZATION("initialize_init");
+
+#if defined(ENABLE_JAVASE)
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+
+ /* Nothing. */
+
+# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+
+ if (!initialize_class(class_java_lang_String))
+ vm_abort("initialize_init: Initialization failed: java.lang.String");
+
+ if (!initialize_class(class_java_lang_System))
+ vm_abort("initialize_init: Initialization failed: java.lang.System");
+
+ if (!initialize_class(class_java_lang_ThreadGroup))
+ vm_abort("initialize_init: Initialization failed: java.lang.ThreadGroup");
+
+ if (!initialize_class(class_java_lang_Thread))
+ vm_abort("initialize_init: Initialization failed: java.lang.Thread");
+
+# else
+# error unknown classpath configuration
+# endif
+
+#elif defined(ENABLE_JAVAME_CLDC1_1)
+
+ /* Nothing. */
+
+#else
+# error unknown Java configuration
+#endif
+}
+
+/* initialize_class ************************************************************
+
+ In Java, every class can have a static initialization
+ function. This function has to be called BEFORE calling other
+ methods or accessing static variables.
+
+*******************************************************************************/
+
+bool initialize_class(classinfo *c)
+{
+ bool r;
+
+ if (!makeinitializations)
+ return true;
+
+ LOCK_MONITOR_ENTER(c);
+
+ /* maybe the class is already initalized or the current thread, which can
+ pass the monitor, is currently initalizing this class */
+
+ if (CLASS_IS_OR_ALMOST_INITIALIZED(c)) {
+ LOCK_MONITOR_EXIT(c);
+
+ return true;
+ }
+
+ /* if <clinit> throw an Error before, the class was marked with an
+ error and we have to throw a NoClassDefFoundError */
+
+ if (c->state & CLASS_ERROR) {
+ exceptions_throw_noclassdeffounderror(c->name);
+
+ LOCK_MONITOR_EXIT(c);
+
+ /* ...but return true, this is ok (mauve test) */
+
+ return true;
+ }
+
+ /* this initalizing run begins NOW */
+
+ c->state |= CLASS_INITIALIZING;
+
+ /* call the internal function */
+
+ r = initialize_class_intern(c);
+
+ /* if return value is not NULL everything was ok and the class is
+ initialized */
+
+ if (r)
+ c->state |= CLASS_INITIALIZED;
+
+ /* this initalizing run is done */
+
+ c->state &= ~CLASS_INITIALIZING;
+
+ LOCK_MONITOR_EXIT(c);
+
+ return r;
+}
+
+
+/* initialize_class_intern *****************************************************
+
+ This function MUST NOT be called directly, because of thread
+ <clinit> race conditions.
+
+*******************************************************************************/
+
+static bool initialize_class_intern(classinfo *c)
+{
+ methodinfo *m;
+ java_handle_t *cause;
+ classinfo *clazz;
+
+ /* maybe the class is not already linked */
+
+ if (!(c->state & CLASS_LINKED))
+ if (!link_class(c))
+ return false;
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ count_class_inits++;
+#endif
+
+ /* Initialize super class. */
+
+ if (c->super != NULL) {
+ if (!(c->super->state & CLASS_INITIALIZED)) {
+#if !defined(NDEBUG)
+ if (initverbose)
+ log_message_class_message_class("Initialize super class ",
+ c->super,
+ " from ",
+ c);
+#endif
+
+ if (!initialize_class(c->super))
+ return false;
+ }
+ }
+
+ /* interfaces implemented need not to be initialized (VM Spec 2.17.4) */
+
+ m = class_findmethod(c, utf_clinit, utf_void__void);
+
+ if (m == NULL) {
+#if !defined(NDEBUG)
+ if (initverbose)
+ log_message_class("Class has no static class initializer: ", c);
+#endif
+
+ return true;
+ }
+
+ /* Sun's and IBM's JVM don't care about the static flag */
+/* if (!(m->flags & ACC_STATIC)) { */
+/* log_text("Class initializer is not static!"); */
+
+#if !defined(NDEBUG)
+ if (initverbose)
+ log_message_class("Starting static class initializer for class: ", c);
+#endif
+
+ /* now call the initializer */
+
+ (void) vm_call_method(m, NULL);
+
+ /* we have an exception or error */
+
+ cause = exceptions_get_exception();
+
+ if (cause != NULL) {
+ /* class is NOT initialized and is marked with error */
+
+ c->state |= CLASS_ERROR;
+
+ /* Load java/lang/Exception for the instanceof check. */
+
+ clazz = load_class_bootstrap(utf_java_lang_Exception);
+
+ if (clazz == NULL)
+ return false;
+
+ /* Is this an exception? Yes, than wrap it. */
+
+ if (builtin_instanceof(cause, clazz)) {
+ /* clear exception, because we are calling jit code again */
+
+ exceptions_clear_exception();
+
+ /* wrap the exception */
+
+ exceptions_throw_exceptionininitializererror(cause);
+ }
+
+ return false;
+ }
+
+#if !defined(NDEBUG)
+ if (initverbose)
+ log_message_class("Finished static class initializer for class: ", c);
+#endif
+
+ return true;
+}
+
+
+/*
+ * 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/initialize.h - static class initializer 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 _INITIALIZE_H
-#define _INITIALIZE_H
-
-#include "config.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "vm/class.h"
-#include "vm/global.h"
-
-
-/* function prototypes ********************************************************/
-
-void initialize_init(void);
-bool initialize_class(classinfo *c);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _INITIALIZE_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/initialize.hpp - static class initializer 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 _INITIALIZE_HPP
+#define _INITIALIZE_HPP
+
+#include "config.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "vm/class.h"
+#include "vm/global.h"
+
+
+/* function prototypes ********************************************************/
+
+void initialize_init(void);
+bool initialize_class(classinfo *c);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _INITIALIZE_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:
+ */
#include "vm/jit/builtin.hpp"
#include "vm/global.h"
#include "vm/globals.hpp"
-#include "vm/initialize.h"
+#include "vm/initialize.hpp"
#include "vm/javaobjects.hpp"
#include "vm/exceptions.hpp"
#include "vm/global.h"
#include "vm/method.h"
-#include "vm/resolve.h"
+#include "vm/resolve.hpp"
#include "vm/jit/codegen-common.hpp"
#include "vm/jit/jit.hpp"
#include "vm/jit/allocator/lsra.h"
#include "vm/jit/builtin.hpp"
#include "vm/exceptions.hpp"
-#include "vm/resolve.h"
+#include "vm/resolve.hpp"
#include "vm/options.h"
#include "vm/statistics.h"
#include "vm/exceptions.hpp"
#include "vm/method.h"
#include "vm/options.h"
-#include "vm/resolve.h"
+#include "vm/resolve.hpp"
#include "vm/string.hpp"
#include "vm/jit/abi.h"
#include "vm/jit/builtin.hpp"
#include "vm/class.h"
#include "vm/field.hpp"
-#include "vm/initialize.h"
+#include "vm/initialize.hpp"
#include "vm/options.h"
#include "vm/references.h"
-#include "vm/resolve.h"
+#include "vm/resolve.hpp"
#include "vm/jit/asmpart.h"
#include "vm/jit/patcher-common.hpp"
#include "vm/global.h"
#include "vm/method.h"
#include "vm/primitive.hpp"
-#include "vm/resolve.h"
+#include "vm/resolve.hpp"
#include "vm/vm.hpp"
#include "vm/jit/abi-asm.h"
#include "vm/jit/builtin.hpp"
#include "vm/class.h"
#include "vm/field.hpp"
-#include "vm/initialize.h"
+#include "vm/initialize.hpp"
#include "vm/options.h"
#include "vm/references.h"
-#include "vm/resolve.h"
+#include "vm/resolve.hpp"
#include "vm/jit/asmpart.h"
#include "vm/jit/patcher-common.hpp"
#include "vm/exceptions.hpp"
#include "vm/global.h"
#include "vm/globals.hpp"
-#include "vm/initialize.h"
+#include "vm/initialize.hpp"
#include "vm/linker.h"
#include "vm/loader.hpp"
#include "vm/options.h"
#include "vm/jit/builtin.hpp"
#include "vm/class.h"
#include "vm/field.hpp"
-#include "vm/initialize.h"
+#include "vm/initialize.hpp"
#include "vm/options.h"
#include "vm/references.h"
-#include "vm/resolve.h"
+#include "vm/resolve.hpp"
#include "vm/jit/patcher-common.hpp"
#include "vm/jit/builtin.hpp"
#include "vm/class.h"
#include "vm/global.h"
-#include "vm/initialize.h"
+#include "vm/initialize.hpp"
#include "vm/method.h"
#include "vm/options.h"
#include "vm/statistics.h"
#include "vm/linker.h"
#include "vm/method.h"
#include "vm/references.h"
-#include "vm/resolve.h"
+#include "vm/resolve.hpp"
#include "vm/jit/codegen-common.hpp"
#include "vm/jit/builtin.hpp"
#include "vm/class.h"
#include "vm/field.hpp"
-#include "vm/initialize.h"
+#include "vm/initialize.hpp"
#include "vm/options.h"
#include "vm/references.h"
-#include "vm/resolve.h"
+#include "vm/resolve.hpp"
#include "vm/jit/asmpart.h"
#include "vm/jit/patcher.h"
#include "vm/class.h"
#include "vm/global.h"
#include "vm/globals.hpp"
-#include "vm/initialize.h"
+#include "vm/initialize.hpp"
#include "vm/loader.hpp"
#include "vm/method.h"
#include "vm/options.h"
#include "vm/global.h"
#include "vm/method.h"
#include "vm/references.h"
-#include "vm/resolve.h"
+#include "vm/resolve.hpp"
#if defined(ENABLE_STATISTICS)
# include "vm/statistics.h"
#include "mm/memory.h"
#include "vm/jit/builtin.hpp"
-#include "vm/resolve.h"
+#include "vm/resolve.hpp"
#include "vm/jit/loop/loop.h"
#include "vm/jit/loop/tracing.h"
#include "vm/jit/builtin.hpp"
#include "vm/class.h"
#include "vm/field.hpp"
-#include "vm/initialize.h"
+#include "vm/initialize.hpp"
#include "vm/options.h"
#include "vm/references.h"
-#include "vm/resolve.h"
+#include "vm/resolve.hpp"
#include "vm/jit/asmpart.h"
#include "vm/jit/patcher-common.hpp"
#include "vm/jit/builtin.hpp"
#include "vm/class.h"
#include "vm/field.hpp"
-#include "vm/initialize.h"
+#include "vm/initialize.hpp"
#include "vm/options.h"
#include "vm/references.h"
-#include "vm/resolve.h"
+#include "vm/resolve.hpp"
#include "vm/jit/asmpart.h"
#include "vm/jit/patcher-common.hpp"
#include "vm/descriptor.h"
#include "vm/global.h"
#include "vm/references.h"
-#include "vm/resolve.h"
+#include "vm/resolve.hpp"
#include "vm/jit/ir/bytecode.h"
#include "vm/jit/optimizing/escape.h"
#include "toolbox/worklist.h"
#include "vm/jit/builtin.hpp"
-#include "vm/resolve.h"
+#include "vm/resolve.hpp"
#include "vm/exceptions.hpp"
#include "vm/string.hpp"
#include "vm/linker.h"
#include "vm/loader.hpp"
#include "vm/options.h"
-#include "vm/resolve.h"
+#include "vm/resolve.hpp"
#if defined(ENABLE_STATISTICS)
# include "vm/statistics.h"
#include "toolbox/logging.h" /* XXX remove me! */
#include "vm/exceptions.hpp"
-#include "vm/initialize.h"
+#include "vm/initialize.hpp"
#include "vm/options.h"
-#include "vm/resolve.h"
+#include "vm/resolve.hpp"
#include "vm/vm.hpp" /* for vm_abort */
#include "vm/jit/code.hpp"
#include "vm/jit/builtin.hpp"
#include "vm/class.h"
#include "vm/field.hpp"
-#include "vm/initialize.h"
+#include "vm/initialize.hpp"
#include "vm/options.h"
#include "vm/references.h"
-#include "vm/resolve.h"
+#include "vm/resolve.hpp"
#include "vm/jit/asmpart.h"
#include "vm/jit/methodheader.h"
#include "vm/jit/builtin.hpp"
#include "vm/class.h"
#include "vm/field.hpp"
-#include "vm/initialize.h"
+#include "vm/initialize.hpp"
#include "vm/options.h"
#include "vm/references.h"
-#include "vm/resolve.h"
+#include "vm/resolve.hpp"
#include "vm/jit/asmpart.h"
#include "vm/jit/methodheader.h"
#include "vm/jit/builtin.hpp"
#include "vm/class.h"
#include "vm/field.hpp"
-#include "vm/initialize.h"
+#include "vm/initialize.hpp"
#include "vm/options.h"
#include "vm/references.h"
-#include "vm/resolve.h"
+#include "vm/resolve.hpp"
#include "vm/types.h"
#include "vm/jit/patcher-common.hpp"
#include "vm/class.h"
#include "vm/exceptions.hpp"
#include "vm/field.hpp"
-#include "vm/initialize.h"
+#include "vm/initialize.hpp"
#include "vm/options.h"
#include "vm/references.h"
-#include "vm/resolve.h"
+#include "vm/resolve.hpp"
#include "vm/jit/asmpart.h"
#include "vm/jit/patcher.h"
#include "vm/exceptions.hpp"
#include "vm/global.h"
#include "vm/options.h"
-#include "vm/resolve.h"
+#include "vm/resolve.hpp"
#include "vm/string.hpp"
#include "vm/types.h"
#include "vm/loader.hpp"
#include "vm/options.h"
#include "vm/primitive.hpp"
-#include "vm/resolve.h"
+#include "vm/resolve.hpp"
#include "vm/vm.hpp"
#include "vm/jit/jit.hpp"
#include "vm/loader.hpp"
#include "vm/options.h"
#include "vm/primitive.hpp"
-#include "vm/resolve.h"
+#include "vm/resolve.hpp"
#include "vm/jit/jit.hpp"
#include "vm/jit/parse.h"
#include "vm/globals.hpp"
#include "vm/loader.hpp"
#include "vm/primitive.hpp"
-#include "vm/resolve.h"
+#include "vm/resolve.hpp"
#include "vm/jit/jit.hpp"
#include "vm/jit/verify/typeinfo.h"
/* FUNCTIONS */
/****************************************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* typevector functions *****************************************************/
/* element read-only access */
#endif /* TYPEINFO_DEBUG */
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _TYPEINFO_H */
#include "vm/jit/builtin.hpp"
#include "vm/class.h"
#include "vm/field.hpp"
-#include "vm/initialize.h"
+#include "vm/initialize.hpp"
#include "vm/options.h"
#include "vm/references.h"
-#include "vm/resolve.h"
+#include "vm/resolve.hpp"
#include "vm/jit/patcher-common.hpp"
#endif
-/* #include "vm/resolve.h" */
+/* #include "vm/resolve.hpp" */
/* copied prototype to avoid bootstrapping problem: */
classinfo *resolve_classref_or_classinfo_eager(classref_or_classinfo cls, bool checkaccess);
#include "vm/options.h"
#include "vm/package.hpp"
#include "vm/primitive.hpp"
-#include "vm/resolve.h"
+#include "vm/resolve.hpp"
#include "vm/rt-timing.h"
#include "vm/string.hpp"
#include "vm/suck.hpp"
#include "vm/loader.hpp"
#include "vm/method.h"
#include "vm/options.h"
-#include "vm/resolve.h"
+#include "vm/resolve.hpp"
#include "vm/suck.hpp"
#include "vm/utf8.h"
#include "vm/vm.hpp"
+++ /dev/null
-/* src/vm/resolve.c - resolving classes/interfaces/fields/methods
-
- 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 "mm/memory.h"
-
-#include "vm/access.h"
-#include "vm/classcache.h"
-#include "vm/descriptor.h"
-#include "vm/exceptions.hpp"
-#include "vm/global.h"
-#include "vm/globals.hpp"
-#include "vm/linker.h"
-#include "vm/loader.hpp"
-#include "vm/options.h"
-#include "vm/primitive.hpp"
-#include "vm/resolve.h"
-
-#include "vm/jit/jit.hpp"
-#include "vm/jit/verify/typeinfo.h"
-
-
-/******************************************************************************/
-/* DEBUG HELPERS */
-/******************************************************************************/
-
-/*#define RESOLVE_VERBOSE*/
-
-/* resolve_handle_pending_exception ********************************************
-
- Convert a pending ClassNotFoundException into a
- NoClassDefFoundError if requested.
-
- See: hotspot/src/share/vm/classfile/systemDictionary.cpp
- (handle_resolution_exception)
-
- ARGUMENTS:
- classname .... name of the class currently resolved
- throwError ... if true throw a NoClassDefFoundError instead of
- a ClassNotFoundException
-
-*******************************************************************************/
-
-void resolve_handle_pending_exception(bool throwError)
-{
- java_handle_t *e;
-
- /* Get the current exception. */
-
- e = exceptions_get_exception();
-
- if (e != NULL) {
- if (throwError == true) {
- /* Convert ClassNotFoundException to
- NoClassDefFoundError. */
-
- if (builtin_instanceof(e, class_java_lang_ClassNotFoundException)) {
- /* Clear exception, because we are calling Java code
- again. */
-
- exceptions_clear_exception();
-
- /* create new error */
-
- exceptions_throw_noclassdeffounderror_cause(e);
- }
- else {
- return;
- }
- }
- else {
- /* An exception conversion was not requested. Simply
- return. */
-
- return;
- }
- }
-}
-
-
-/******************************************************************************/
-/* CLASS RESOLUTION */
-/******************************************************************************/
-
-/* resolve_class_from_name *****************************************************
-
- Resolve a symbolic class reference
-
- IN:
- referer..........the class containing the reference
- refmethod........the method from which resolution was triggered
- (may be NULL if not applicable)
- classname........class name to resolve
- mode.............mode of resolution:
- resolveLazy...only resolve if it does not
- require loading classes
- resolveEager..load classes if necessary
- checkaccess......if true, access rights to the class are checked
- link.............if true, guarantee that the returned class, if any,
- has been linked
-
- OUT:
- *result..........set to result of resolution, or to NULL if
- the reference has not been resolved
- In the case of an exception, *result is
- guaranteed to be set to NULL.
-
- RETURN VALUE:
- true.............everything ok
- (*result may still be NULL for resolveLazy)
- false............an exception has been thrown
-
- NOTE:
- The returned class is *not* guaranteed to be linked!
- (It is guaranteed to be loaded, though.)
-
-*******************************************************************************/
-
-bool resolve_class_from_name(classinfo *referer,
- methodinfo *refmethod,
- utf *classname,
- resolve_mode_t mode,
- bool checkaccess,
- bool link,
- classinfo **result)
-{
- classinfo *cls;
- char *utf_ptr;
- int len;
- char *msg;
- s4 msglen;
- utf *u;
-
- assert(result);
- assert(referer);
- assert(classname);
- assert(mode == resolveLazy || mode == resolveEager);
-
- *result = NULL;
-
-#ifdef RESOLVE_VERBOSE
- printf("resolve_class_from_name(");
- utf_fprint_printable_ascii(stdout,referer->name);
- printf(",%p,",(void*)referer->classloader);
- utf_fprint_printable_ascii(stdout,classname);
- printf(",%d,%d)\n",(int)checkaccess,(int)link);
-#endif
-
- /* lookup if this class has already been loaded */
-
- cls = classcache_lookup(referer->classloader, classname);
-
-#ifdef RESOLVE_VERBOSE
- printf(" lookup result: %p\n",(void*)cls);
-#endif
-
- if (!cls) {
- /* resolve array types */
-
- if (classname->text[0] == '[') {
- utf_ptr = classname->text + 1;
- len = classname->blength - 1;
-
- /* classname is an array type name */
-
- switch (*utf_ptr) {
- case 'L':
- utf_ptr++;
- len -= 2;
- /* FALLTHROUGH */
- case '[':
- /* the component type is a reference type */
- /* resolve the component type */
- if (!resolve_class_from_name(referer,refmethod,
- utf_new(utf_ptr,len),
- mode,checkaccess,link,&cls))
- return false; /* exception */
- if (!cls) {
- assert(mode == resolveLazy);
- return true; /* be lazy */
- }
- /* create the array class */
- cls = class_array_of(cls,false);
- if (!cls)
- return false; /* exception */
- }
- }
- else {
- /* the class has not been loaded, yet */
- if (mode == resolveLazy)
- return true; /* be lazy */
- }
-
-#ifdef RESOLVE_VERBOSE
- printf(" loading...\n");
-#endif
-
- /* load the class */
-
- if (cls == NULL) {
- cls = load_class_from_classloader(classname, referer->classloader);
-
- if (cls == NULL)
- return false;
- }
- }
-
- /* the class is now loaded */
- assert(cls);
- assert(cls->state & CLASS_LOADED);
-
-#ifdef RESOLVE_VERBOSE
- printf(" checking access rights...\n");
-#endif
-
- /* check access rights of referer to refered class */
-
- if (checkaccess && !access_is_accessible_class(referer,cls)) {
- msglen =
- utf_bytes(cls->name) +
- utf_bytes(referer->name) +
- 100;
-
- msg = MNEW(char, msglen);
-
- strcpy(msg, "class is not accessible (");
- utf_cat_classname(msg, cls->name);
- strcat(msg, " from ");
- utf_cat_classname(msg, referer->name);
- strcat(msg, ")");
-
- u = utf_new_char(msg);
-
- MFREE(msg, char, msglen);
-
- exceptions_throw_illegalaccessexception(u);
-
- return false; /* exception */
- }
-
- /* link the class if necessary */
- if (link) {
- if (!(cls->state & CLASS_LINKED))
- if (!link_class(cls))
- return false; /* exception */
-
- assert(cls->state & CLASS_LINKED);
- }
-
- /* resolution succeeds */
-#ifdef RESOLVE_VERBOSE
- printf(" success.\n");
-#endif
- *result = cls;
- return true;
-}
-
-/* resolve_classref ************************************************************
-
- Resolve a symbolic class reference
-
- IN:
- refmethod........the method from which resolution was triggered
- (may be NULL if not applicable)
- ref..............class reference
- mode.............mode of resolution:
- resolveLazy...only resolve if it does not
- require loading classes
- resolveEager..load classes if necessary
- checkaccess......if true, access rights to the class are checked
- link.............if true, guarantee that the returned class, if any,
- has been linked
-
- OUT:
- *result..........set to result of resolution, or to NULL if
- the reference has not been resolved
- In the case of an exception, *result is
- guaranteed to be set to NULL.
-
- RETURN VALUE:
- true.............everything ok
- (*result may still be NULL for resolveLazy)
- false............an exception has been thrown
-
-*******************************************************************************/
-
-bool resolve_classref(methodinfo *refmethod,
- constant_classref *ref,
- resolve_mode_t mode,
- bool checkaccess,
- bool link,
- classinfo **result)
-{
- return resolve_classref_or_classinfo(refmethod,CLASSREF_OR_CLASSINFO(ref),mode,checkaccess,link,result);
-}
-
-/* resolve_classref_or_classinfo ***********************************************
-
- Resolve a symbolic class reference if necessary
-
- NOTE: If given, refmethod->clazz is used as the referring class.
- Otherwise, cls.ref->referer is used.
-
- IN:
- refmethod........the method from which resolution was triggered
- (may be NULL if not applicable)
- cls..............class reference or classinfo
- mode.............mode of resolution:
- resolveLazy...only resolve if it does not
- require loading classes
- resolveEager..load classes if necessary
- checkaccess......if true, access rights to the class are checked
- link.............if true, guarantee that the returned class, if any,
- has been linked
-
- OUT:
- *result..........set to result of resolution, or to NULL if
- the reference has not been resolved
- In the case of an exception, *result is
- guaranteed to be set to NULL.
-
- RETURN VALUE:
- true.............everything ok
- (*result may still be NULL for resolveLazy)
- false............an exception has been thrown
-
-*******************************************************************************/
-
-bool resolve_classref_or_classinfo(methodinfo *refmethod,
- classref_or_classinfo cls,
- resolve_mode_t mode,
- bool checkaccess,
- bool link,
- classinfo **result)
-{
- classinfo *c;
- classinfo *referer;
-
- assert(cls.any);
- assert(mode == resolveEager || mode == resolveLazy);
- assert(result);
-
-#ifdef RESOLVE_VERBOSE
- printf("resolve_classref_or_classinfo(");
- utf_fprint_printable_ascii(stdout,(IS_CLASSREF(cls)) ? cls.ref->name : cls.cls->name);
- printf(",%i,%i,%i)\n",mode,(int)checkaccess,(int)link);
-#endif
-
- *result = NULL;
-
- if (IS_CLASSREF(cls)) {
- /* we must resolve this reference */
-
- /* determine which class to use as the referer */
-
- /* Common cases are refmethod == NULL or both referring classes */
- /* being the same, so the referer usually is cls.ref->referer. */
- /* There is one important case where it is not: When we do a */
- /* deferred assignability check to a formal argument of a method, */
- /* we must use refmethod->clazz (the caller's class) to resolve */
- /* the type of the formal argument. */
-
- referer = (refmethod) ? refmethod->clazz : cls.ref->referer;
-
- if (!resolve_class_from_name(referer, refmethod, cls.ref->name,
- mode, checkaccess, link, &c))
- goto return_exception;
-
- } else {
- /* cls has already been resolved */
- c = cls.cls;
- assert(c->state & CLASS_LOADED);
- }
- assert(c || (mode == resolveLazy));
-
- if (!c)
- return true; /* be lazy */
-
- assert(c);
- assert(c->state & CLASS_LOADED);
-
- if (link) {
- if (!(c->state & CLASS_LINKED))
- if (!link_class(c))
- goto return_exception;
-
- assert(c->state & CLASS_LINKED);
- }
-
- /* succeeded */
- *result = c;
- return true;
-
- return_exception:
- *result = NULL;
- return false;
-}
-
-
-/* resolve_classref_or_classinfo_eager *****************************************
-
- Resolve a symbolic class reference eagerly if necessary.
- No attempt is made to link the class.
-
- IN:
- cls..............class reference or classinfo
- checkaccess......if true, access rights to the class are checked
-
- RETURN VALUE:
- classinfo *......the resolved class
- NULL.............an exception has been thrown
-
-*******************************************************************************/
-
-classinfo *resolve_classref_or_classinfo_eager(classref_or_classinfo cls,
- bool checkaccess)
-{
- classinfo *c;
-
- if (!resolve_classref_or_classinfo(NULL, cls, resolveEager, checkaccess, false, &c))
- return NULL;
-
- return c;
-}
-
-
-/* resolve_class_from_typedesc *************************************************
-
- Return a classinfo * for the given type descriptor
-
- IN:
- d................type descriptor
- checkaccess......if true, access rights to the class are checked
- link.............if true, guarantee that the returned class, if any,
- has been linked
- OUT:
- *result..........set to result of resolution, or to NULL if
- the reference has not been resolved
- In the case of an exception, *result is
- guaranteed to be set to NULL.
-
- RETURN VALUE:
- true.............everything ok
- false............an exception has been thrown
-
- NOTE:
- This function always resolves eagerly.
-
-*******************************************************************************/
-
-bool resolve_class_from_typedesc(typedesc *d, bool checkaccess, bool link, classinfo **result)
-{
- classinfo *cls;
-
- assert(d);
- assert(result);
-
- *result = NULL;
-
-#ifdef RESOLVE_VERBOSE
- printf("resolve_class_from_typedesc(");
- descriptor_debug_print_typedesc(stdout,d);
- printf(",%i,%i)\n",(int)checkaccess,(int)link);
-#endif
-
- if (d->type == TYPE_ADR) {
- /* a reference type */
- assert(d->classref);
- if (!resolve_classref_or_classinfo(NULL,CLASSREF_OR_CLASSINFO(d->classref),
- resolveEager,checkaccess,link,&cls))
- return false; /* exception */
- }
- else {
- /* a primitive type */
-
- cls = Primitive_get_class_by_type(d->primitivetype);
-
- assert(cls->state & CLASS_LOADED);
-
- if (!(cls->state & CLASS_LINKED))
- if (!link_class(cls))
- return false; /* exception */
- }
-
- assert(cls);
- assert(cls->state & CLASS_LOADED);
- assert(!link || (cls->state & CLASS_LINKED));
-
-#ifdef RESOLVE_VERBOSE
- printf(" result = ");utf_fprint_printable_ascii(stdout,cls->name);printf("\n");
-#endif
-
- *result = cls;
- return true;
-}
-
-/******************************************************************************/
-/* SUBTYPE SET CHECKS */
-/******************************************************************************/
-
-/* resolve_subtype_check *******************************************************
-
- Resolve the given types lazily and perform a subtype check
-
- IN:
- refmethod........the method triggering the resolution
- subtype..........checked to be a subtype of supertype
- supertype........the super type to check agaings
- mode.............mode of resolution:
- resolveLazy...only resolve if it does not
- require loading classes
- resolveEager..load classes if necessary
- error............which type of exception to throw if
- the test fails. May be:
- resolveLinkageError, or
- resolveIllegalAccessError
- IMPORTANT: If error==resolveIllegalAccessError,
- then array types are not checked.
-
- RETURN VALUE:
- resolveSucceeded.....the check succeeded
- resolveDeferred......the check could not be performed due to
- unresolved types. (This can only happen for
- mode == resolveLazy.)
- resolveFailed........the check failed, an exception has been thrown.
-
- NOTE:
- The types are resolved first, so any
- exception which may occurr during resolution may
- be thrown by this function.
-
-*******************************************************************************/
-
-#if defined(ENABLE_VERIFIER)
-static resolve_result_t resolve_subtype_check(methodinfo *refmethod,
- classref_or_classinfo subtype,
- classref_or_classinfo supertype,
- resolve_mode_t mode,
- resolve_err_t error)
-{
- classinfo *subclass;
- typeinfo_t subti;
- typecheck_result r;
- char *msg;
- s4 msglen;
- utf *u;
-
- assert(refmethod);
- assert(subtype.any);
- assert(supertype.any);
- assert(mode == resolveLazy || mode == resolveEager);
- assert(error == resolveLinkageError || error == resolveIllegalAccessError);
-
- /* resolve the subtype */
-
- if (!resolve_classref_or_classinfo(refmethod,subtype,mode,false,true,&subclass)) {
- /* the subclass could not be resolved. therefore we are sure that */
- /* no instances of this subclass will ever exist -> skip this test */
- /* XXX this assumes that class loading has invariant results (as in JVM spec) */
- exceptions_clear_exception();
- return resolveSucceeded;
- }
- if (!subclass)
- return resolveDeferred; /* be lazy */
-
- assert(subclass->state & CLASS_LINKED);
-
- /* do not check access to protected members of arrays */
-
- if (error == resolveIllegalAccessError && subclass->name->text[0] == '[') {
- return resolveSucceeded;
- }
-
- /* perform the subtype check */
-
- typeinfo_init_classinfo(&subti,subclass);
-check_again:
- r = typeinfo_is_assignable_to_class(&subti,supertype);
- if (r == typecheck_FAIL)
- return resolveFailed; /* failed, exception is already set */
-
- if (r == typecheck_MAYBE) {
- assert(IS_CLASSREF(supertype));
- if (mode == resolveEager) {
- if (!resolve_classref_or_classinfo(refmethod,supertype,
- resolveEager,false,true,
- &supertype.cls))
- {
- return resolveFailed;
- }
- assert(supertype.cls);
- goto check_again;
- }
-
- return resolveDeferred; /* be lazy */
- }
-
- if (!r) {
- /* sub class relationship is false */
-
-#if defined(RESOLVE_VERBOSE)
- printf("SUBTYPE CHECK FAILED!\n");
-#endif
-
- msglen =
- utf_bytes(subclass->name) +
- utf_bytes(CLASSREF_OR_CLASSINFO_NAME(supertype))
- + 200;
-
- msg = MNEW(char, msglen);
-
- strcpy(msg, (error == resolveIllegalAccessError) ?
- "illegal access to protected member (" :
- "subtype constraint violated (");
-
- utf_cat_classname(msg, subclass->name);
- strcat(msg, " is not a subclass of ");
- utf_cat_classname(msg, CLASSREF_OR_CLASSINFO_NAME(supertype));
- strcat(msg, ")");
-
- u = utf_new_char(msg);
-
- if (error == resolveIllegalAccessError)
- exceptions_throw_illegalaccessexception(u);
- else
- exceptions_throw_linkageerror(msg, NULL);
-
- /* ATTENTION: We probably need msg for
- exceptions_throw_linkageerror. */
-
- MFREE(msg, char, msglen);
-
- return resolveFailed; /* exception */
- }
-
- /* everything ok */
-
- return resolveSucceeded;
-}
-#endif /* defined(ENABLE_VERIFIER) */
-
-/* resolve_lazy_subtype_checks *************************************************
-
- Resolve the types to check lazily and perform subtype checks
-
- IN:
- refmethod........the method triggering the resolution
- subtinfo.........the typeinfo containing the subtypes
- supertype........the supertype to test againgst
- mode.............mode of resolution:
- resolveLazy...only resolve if it does not
- require loading classes
- resolveEager..load classes if necessary
- error............which type of exception to throw if
- the test fails. May be:
- resolveLinkageError, or
- resolveIllegalAccessError
- IMPORTANT: If error==resolveIllegalAccessError,
- then array types in the set are skipped.
-
- RETURN VALUE:
- resolveSucceeded.....the check succeeded
- resolveDeferred......the check could not be performed due to
- unresolved types
- resolveFailed........the check failed, an exception has been thrown.
-
- NOTE:
- The references in the set are resolved first, so any
- exception which may occurr during resolution may
- be thrown by this function.
-
-*******************************************************************************/
-
-#if defined(ENABLE_VERIFIER)
-static resolve_result_t resolve_lazy_subtype_checks(methodinfo *refmethod,
- typeinfo_t *subtinfo,
- classref_or_classinfo supertype,
- resolve_err_t error)
-{
- int count;
- int i;
- resolve_result_t result;
-
- assert(refmethod);
- assert(subtinfo);
- assert(supertype.any);
- assert(error == resolveLinkageError || error == resolveIllegalAccessError);
-
- /* returnAddresses are illegal here */
-
- if (TYPEINFO_IS_PRIMITIVE(*subtinfo)) {
- exceptions_throw_verifyerror(refmethod,
- "Invalid use of returnAddress");
- return resolveFailed;
- }
-
- /* uninitialized objects are illegal here */
-
- if (TYPEINFO_IS_NEWOBJECT(*subtinfo)) {
- exceptions_throw_verifyerror(refmethod,
- "Invalid use of uninitialized object");
- return resolveFailed;
- }
-
- /* the nulltype is always assignable */
-
- if (TYPEINFO_IS_NULLTYPE(*subtinfo))
- return resolveSucceeded;
-
- /* every type is assignable to (BOOTSTRAP)java.lang.Object */
-
- if (supertype.cls == class_java_lang_Object
- || (CLASSREF_OR_CLASSINFO_NAME(supertype) == utf_java_lang_Object
- && refmethod->clazz->classloader == NULL))
- {
- return resolveSucceeded;
- }
-
- if (subtinfo->merged) {
-
- /* for a merged type we have to do a series of checks */
-
- count = subtinfo->merged->count;
- for (i=0; i<count; ++i) {
- classref_or_classinfo c = subtinfo->merged->list[i];
- if (subtinfo->dimension > 0) {
- /* a merge of array types */
- /* the merged list contains the possible _element_ types, */
- /* so we have to create array types with these elements. */
- if (IS_CLASSREF(c)) {
- c.ref = class_get_classref_multiarray_of(subtinfo->dimension,c.ref);
- }
- else {
- c.cls = class_multiarray_of(subtinfo->dimension,c.cls,false);
- }
- }
-
- /* do the subtype check against the type c */
-
- result = resolve_subtype_check(refmethod,c,supertype,resolveLazy,error);
- if (result != resolveSucceeded)
- return result;
- }
- }
- else {
-
- /* a single type, this is the common case, hopefully */
-
- if (CLASSREF_OR_CLASSINFO_NAME(subtinfo->typeclass)
- == CLASSREF_OR_CLASSINFO_NAME(supertype))
- {
- /* the class names are the same */
- /* equality is guaranteed by the loading constraints */
- return resolveSucceeded;
- }
- else {
-
- /* some other type name, try to perform the check lazily */
-
- return resolve_subtype_check(refmethod,
- subtinfo->typeclass,supertype,
- resolveLazy,
- error);
- }
- }
-
- /* everything ok */
- return resolveSucceeded;
-}
-#endif /* defined(ENABLE_VERIFIER) */
-
-/* resolve_and_check_subtype_set ***********************************************
-
- Resolve the references in the given set and test subtype relationships
-
- IN:
- refmethod........the method triggering the resolution
- ref..............a set of class/interface references
- (may be empty)
- typeref..........the type to test against the set
- mode.............mode of resolution:
- resolveLazy...only resolve if it does not
- require loading classes
- resolveEager..load classes if necessary
- error............which type of exception to throw if
- the test fails. May be:
- resolveLinkageError, or
- resolveIllegalAccessError
- IMPORTANT: If error==resolveIllegalAccessError,
- then array types in the set are skipped.
-
- RETURN VALUE:
- resolveSucceeded.....the check succeeded
- resolveDeferred......the check could not be performed due to
- unresolved types. (This can only happen if
- mode == resolveLazy.)
- resolveFailed........the check failed, an exception has been thrown.
-
- NOTE:
- The references in the set are resolved first, so any
- exception which may occurr during resolution may
- be thrown by this function.
-
-*******************************************************************************/
-
-#if defined(ENABLE_VERIFIER)
-static resolve_result_t resolve_and_check_subtype_set(methodinfo *refmethod,
- unresolved_subtype_set *ref,
- classref_or_classinfo typeref,
- resolve_mode_t mode,
- resolve_err_t error)
-{
- classref_or_classinfo *setp;
- typecheck_result checkresult;
-
- assert(refmethod);
- assert(ref);
- assert(typeref.any);
- assert(mode == resolveLazy || mode == resolveEager);
- assert(error == resolveLinkageError || error == resolveIllegalAccessError);
-
-#if defined(RESOLVE_VERBOSE)
- printf("resolve_and_check_subtype_set:\n");
- unresolved_subtype_set_debug_dump(ref, stdout);
- if (IS_CLASSREF(typeref))
- class_classref_println(typeref.ref);
- else
- class_println(typeref.cls);
-#endif
-
- setp = ref->subtyperefs;
-
- /* an empty set of tests always succeeds */
- if (!setp || !setp->any) {
- return resolveSucceeded;
- }
-
- /* first resolve the type if necessary */
- if (!resolve_classref_or_classinfo(refmethod,typeref,mode,false,true,&(typeref.cls)))
- return resolveFailed; /* exception */
- if (!typeref.cls)
- return resolveDeferred; /* be lazy */
-
- assert(typeref.cls->state & CLASS_LINKED);
-
- /* iterate over the set members */
-
- for (; setp->any; ++setp) {
- checkresult = resolve_subtype_check(refmethod,*setp,typeref,mode,error);
-#if defined(RESOLVE_VERBOSE)
- if (checkresult != resolveSucceeded)
- printf("SUBTYPE CHECK FAILED!\n");
-#endif
- if (checkresult != resolveSucceeded)
- return checkresult;
- }
-
- /* check succeeds */
- return resolveSucceeded;
-}
-#endif /* defined(ENABLE_VERIFIER) */
-
-/******************************************************************************/
-/* CLASS RESOLUTION */
-/******************************************************************************/
-
-/* resolve_class ***************************************************************
-
- Resolve an unresolved class reference. The class is also linked.
-
- IN:
- ref..............struct containing the reference
- mode.............mode of resolution:
- resolveLazy...only resolve if it does not
- require loading classes
- resolveEager..load classes if necessary
- checkaccess......if true, access rights to the class are checked
-
- OUT:
- *result..........set to the result of resolution, or to NULL if
- the reference has not been resolved
- In the case of an exception, *result is
- guaranteed to be set to NULL.
-
- RETURN VALUE:
- true.............everything ok
- (*result may still be NULL for resolveLazy)
- false............an exception has been thrown
-
-*******************************************************************************/
-
-#ifdef ENABLE_VERIFIER
-bool resolve_class(unresolved_class *ref,
- resolve_mode_t mode,
- bool checkaccess,
- classinfo **result)
-{
- classinfo *cls;
- resolve_result_t checkresult;
-
- assert(ref);
- assert(result);
- assert(mode == resolveLazy || mode == resolveEager);
-
- *result = NULL;
-
-#ifdef RESOLVE_VERBOSE
- unresolved_class_debug_dump(ref,stdout);
-#endif
-
- /* first we must resolve the class */
- if (!resolve_classref(ref->referermethod,
- ref->classref,mode,checkaccess,true,&cls))
- {
- /* the class reference could not be resolved */
- return false; /* exception */
- }
- if (!cls)
- return true; /* be lazy */
-
- assert(cls);
- assert((cls->state & CLASS_LOADED) && (cls->state & CLASS_LINKED));
-
- /* now we check the subtype constraints */
-
- checkresult = resolve_and_check_subtype_set(ref->referermethod,
- &(ref->subtypeconstraints),
- CLASSREF_OR_CLASSINFO(cls),
- mode,
- resolveLinkageError);
- if (checkresult != resolveSucceeded)
- return (bool) checkresult;
-
- /* succeed */
- *result = cls;
- return true;
-}
-#endif /* ENABLE_VERIFIER */
-
-/* resolve_classref_eager ******************************************************
-
- Resolve an unresolved class reference eagerly. The class is also linked and
- access rights to the class are checked.
-
- IN:
- ref..............constant_classref to the class
-
- RETURN VALUE:
- classinfo * to the class, or
- NULL if an exception has been thrown
-
-*******************************************************************************/
-
-classinfo * resolve_classref_eager(constant_classref *ref)
-{
- classinfo *c;
-
- if (!resolve_classref(NULL,ref,resolveEager,true,true,&c))
- return NULL;
-
- return c;
-}
-
-/* resolve_classref_eager_nonabstract ******************************************
-
- Resolve an unresolved class reference eagerly. The class is also linked and
- access rights to the class are checked. A check is performed that the class
- is not abstract.
-
- IN:
- ref..............constant_classref to the class
-
- RETURN VALUE:
- classinfo * to the class, or
- NULL if an exception has been thrown
-
-*******************************************************************************/
-
-classinfo * resolve_classref_eager_nonabstract(constant_classref *ref)
-{
- classinfo *c;
-
- if (!resolve_classref(NULL,ref,resolveEager,true,true,&c))
- return NULL;
-
- /* ensure that the class is not abstract */
-
- if (c->flags & ACC_ABSTRACT) {
- exceptions_throw_verifyerror(NULL,"creating instance of abstract class");
- return NULL;
- }
-
- return c;
-}
-
-/* resolve_class_eager *********************************************************
-
- Resolve an unresolved class reference eagerly. The class is also linked and
- access rights to the class are checked.
-
- IN:
- ref..............struct containing the reference
-
- RETURN VALUE:
- classinfo * to the class, or
- NULL if an exception has been thrown
-
-*******************************************************************************/
-
-#ifdef ENABLE_VERIFIER
-classinfo * resolve_class_eager(unresolved_class *ref)
-{
- classinfo *c;
-
- if (!resolve_class(ref,resolveEager,true,&c))
- return NULL;
-
- return c;
-}
-#endif /* ENABLE_VERIFIER */
-
-/* resolve_class_eager_no_access_check *****************************************
-
- Resolve an unresolved class reference eagerly. The class is also linked.
- Access rights are _not_ checked.
-
- IN:
- ref..............struct containing the reference
-
- RETURN VALUE:
- classinfo * to the class, or
- NULL if an exception has been thrown
-
-*******************************************************************************/
-
-#ifdef ENABLE_VERIFIER
-classinfo * resolve_class_eager_no_access_check(unresolved_class *ref)
-{
- classinfo *c;
-
- if (!resolve_class(ref, resolveEager, false, &c))
- return NULL;
-
- return c;
-}
-#endif /* ENABLE_VERIFIER */
-
-/******************************************************************************/
-/* FIELD RESOLUTION */
-/******************************************************************************/
-
-/* resolve_field_verifier_checks *******************************************
-
- Do the verifier checks necessary after field has been resolved.
-
- IN:
- refmethod........the method containing the reference
- fieldref.........the field reference
- container........the class where the field was found
- fi...............the fieldinfo of the resolved field
- instanceti.......instance typeinfo, if available
- valueti..........value typeinfo, if available
- isstatic.........true if this is a *STATIC* instruction
- isput............true if this is a PUT* instruction
-
- RETURN VALUE:
- resolveSucceeded....everything ok
- resolveDeferred.....tests could not be done, have been deferred
- resolveFailed.......exception has been thrown
-
-*******************************************************************************/
-
-#if defined(ENABLE_VERIFIER)
-resolve_result_t resolve_field_verifier_checks(methodinfo *refmethod,
- constant_FMIref *fieldref,
- classinfo *container,
- fieldinfo *fi,
- typeinfo_t *instanceti,
- typeinfo_t *valueti,
- bool isstatic,
- bool isput)
-{
- classinfo *declarer;
- classinfo *referer;
- resolve_result_t result;
- constant_classref *fieldtyperef;
- char *msg;
- s4 msglen;
- utf *u;
-
- assert(refmethod);
- assert(fieldref);
- assert(container);
- assert(fi);
-
- /* get the classinfos and the field type */
-
- referer = refmethod->clazz;
- assert(referer);
-
- declarer = fi->clazz;
- assert(declarer);
- assert(referer->state & CLASS_LINKED);
-
- fieldtyperef = fieldref->parseddesc.fd->classref;
-
- /* check static */
-
-#if true != 1
-#error This code assumes that `true` is `1`. Otherwise, use the ternary operator below.
-#endif
-
- if (((fi->flags & ACC_STATIC) != 0) != isstatic) {
- /* a static field is accessed via an instance, or vice versa */
- exceptions_throw_incompatibleclasschangeerror(declarer,
- (fi->flags & ACC_STATIC)
- ? "static field accessed via instance"
- : "instance field accessed without instance");
-
- return resolveFailed;
- }
-
- /* check access rights */
-
- if (!access_is_accessible_member(referer,declarer,fi->flags)) {
- msglen =
- utf_bytes(declarer->name) +
- utf_bytes(fi->name) +
- utf_bytes(referer->name) +
- 100;
-
- msg = MNEW(char, msglen);
-
- strcpy(msg, "field is not accessible (");
- utf_cat_classname(msg, declarer->name);
- strcat(msg, ".");
- utf_cat(msg, fi->name);
- strcat(msg, " from ");
- utf_cat_classname(msg, referer->name);
- strcat(msg, ")");
-
- u = utf_new_char(msg);
-
- MFREE(msg, char, msglen);
-
- exceptions_throw_illegalaccessexception(u);
-
- return resolveFailed; /* exception */
- }
-
- /* for non-static methods we have to check the constraints on the */
- /* instance type */
-
- if (instanceti) {
- typeinfo_t *insttip;
- typeinfo_t tinfo;
-
- /* The instanceslot must contain a reference to a non-array type */
-
- if (!TYPEINFO_IS_REFERENCE(*instanceti)) {
- exceptions_throw_verifyerror(refmethod, "illegal instruction: field access on non-reference");
- return resolveFailed;
- }
- if (TYPEINFO_IS_ARRAY(*instanceti)) {
- exceptions_throw_verifyerror(refmethod, "illegal instruction: field access on array");
- return resolveFailed;
- }
-
- if (isput && TYPEINFO_IS_NEWOBJECT(*instanceti))
- {
- /* The instruction writes a field in an uninitialized object. */
- /* This is only allowed when a field of an uninitialized 'this' object is */
- /* written inside an initialization method */
-
- classinfo *initclass;
- instruction *ins = (instruction *) TYPEINFO_NEWOBJECT_INSTRUCTION(*instanceti);
-
- if (ins != NULL) {
- exceptions_throw_verifyerror(refmethod, "accessing field of uninitialized object");
- return resolveFailed;
- }
-
- /* XXX check that class of field == refmethod->clazz */
- initclass = referer; /* XXX classrefs */
- assert(initclass->state & CLASS_LINKED);
-
- typeinfo_init_classinfo(&tinfo, initclass);
- insttip = &tinfo;
- }
- else {
- insttip = instanceti;
- }
-
- result = resolve_lazy_subtype_checks(refmethod,
- insttip,
- CLASSREF_OR_CLASSINFO(container),
- resolveLinkageError);
- if (result != resolveSucceeded)
- return result;
-
- /* check protected access */
-
- if (((fi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer))
- {
- result = resolve_lazy_subtype_checks(refmethod,
- instanceti,
- CLASSREF_OR_CLASSINFO(referer),
- resolveIllegalAccessError);
- if (result != resolveSucceeded)
- return result;
- }
-
- }
-
- /* for PUT* instructions we have to check the constraints on the value type */
-
- if (valueti) {
- assert(fieldtyperef);
-
- /* check subtype constraints */
- result = resolve_lazy_subtype_checks(refmethod,
- valueti,
- CLASSREF_OR_CLASSINFO(fieldtyperef),
- resolveLinkageError);
-
- if (result != resolveSucceeded)
- return result;
- }
-
- /* impose loading constraint on field type */
-
- if (fi->type == TYPE_ADR) {
- assert(fieldtyperef);
- if (!classcache_add_constraint(declarer->classloader,
- referer->classloader,
- fieldtyperef->name))
- return resolveFailed;
- }
-
- /* XXX impose loading constraint on instance? */
-
- /* everything ok */
- return resolveSucceeded;
-}
-#endif /* defined(ENABLE_VERIFIER) */
-
-/* resolve_field_lazy **********************************************************
-
- Resolve an unresolved field reference lazily
-
- NOTE: This function does NOT do any verification checks. In case of a
- successful resolution, you must call resolve_field_verifier_checks
- in order to perform the necessary checks!
-
- IN:
- refmethod........the referer method
- fieldref.........the field reference
-
- RETURN VALUE:
- resolveSucceeded.....the reference has been resolved
- resolveDeferred......the resolving could not be performed lazily
- resolveFailed........resolving failed, an exception has been thrown.
-
-*******************************************************************************/
-
-resolve_result_t resolve_field_lazy(methodinfo *refmethod,
- constant_FMIref *fieldref)
-{
- classinfo *referer;
- classinfo *container;
- fieldinfo *fi;
-
- assert(refmethod);
-
- /* the class containing the reference */
-
- referer = refmethod->clazz;
- assert(referer);
-
- /* check if the field itself is already resolved */
-
- if (IS_FMIREF_RESOLVED(fieldref))
- return resolveSucceeded;
-
- /* first we must resolve the class containg the field */
-
- /* XXX can/may lazyResolving trigger linking? */
-
- if (!resolve_class_from_name(referer, refmethod,
- fieldref->p.classref->name, resolveLazy, true, true, &container))
- {
- /* the class reference could not be resolved */
- return resolveFailed; /* exception */
- }
- if (!container)
- return resolveDeferred; /* be lazy */
-
- assert(container->state & CLASS_LINKED);
-
- /* now we must find the declaration of the field in `container`
- * or one of its superclasses */
-
- fi = class_resolvefield(container,
- fieldref->name, fieldref->descriptor,
- referer);
- if (!fi) {
- /* The field does not exist. But since we were called lazily, */
- /* this error must not be reported now. (It will be reported */
- /* if eager resolving of this field is ever tried.) */
-
- exceptions_clear_exception();
- return resolveDeferred; /* be lazy */
- }
-
- /* cache the result of the resolution */
-
- fieldref->p.field = fi;
-
- /* everything ok */
- return resolveSucceeded;
-}
-
-/* resolve_field ***************************************************************
-
- Resolve an unresolved field reference
-
- IN:
- ref..............struct containing the reference
- mode.............mode of resolution:
- resolveLazy...only resolve if it does not
- require loading classes
- resolveEager..load classes if necessary
-
- OUT:
- *result..........set to the result of resolution, or to NULL if
- the reference has not been resolved
- In the case of an exception, *result is
- guaranteed to be set to NULL.
-
- RETURN VALUE:
- true.............everything ok
- (*result may still be NULL for resolveLazy)
- false............an exception has been thrown
-
-*******************************************************************************/
-
-bool resolve_field(unresolved_field *ref,
- resolve_mode_t mode,
- fieldinfo **result)
-{
- classinfo *referer;
- classinfo *container;
- classinfo *declarer;
- constant_classref *fieldtyperef;
- fieldinfo *fi;
- resolve_result_t checkresult;
-
- assert(ref);
- assert(result);
- assert(mode == resolveLazy || mode == resolveEager);
-
- *result = NULL;
-
-#ifdef RESOLVE_VERBOSE
- unresolved_field_debug_dump(ref,stdout);
-#endif
-
- /* the class containing the reference */
-
- referer = ref->referermethod->clazz;
- assert(referer);
-
- /* check if the field itself is already resolved */
- if (IS_FMIREF_RESOLVED(ref->fieldref)) {
- fi = ref->fieldref->p.field;
- container = fi->clazz;
- goto resolved_the_field;
- }
-
- /* first we must resolve the class containg the field */
- if (!resolve_class_from_name(referer,ref->referermethod,
- ref->fieldref->p.classref->name,mode,true,true,&container))
- {
- /* the class reference could not be resolved */
- return false; /* exception */
- }
- if (!container)
- return true; /* be lazy */
-
- assert(container);
- assert(container->state & CLASS_LOADED);
- assert(container->state & CLASS_LINKED);
-
- /* now we must find the declaration of the field in `container`
- * or one of its superclasses */
-
-#ifdef RESOLVE_VERBOSE
- printf(" resolving field in class...\n");
-#endif
-
- fi = class_resolvefield(container,
- ref->fieldref->name,ref->fieldref->descriptor,
- referer);
- if (!fi) {
- if (mode == resolveLazy) {
- /* The field does not exist. But since we were called lazily, */
- /* this error must not be reported now. (It will be reported */
- /* if eager resolving of this field is ever tried.) */
-
- exceptions_clear_exception();
- return true; /* be lazy */
- }
-
- return false; /* exception */
- }
-
- /* cache the result of the resolution */
- ref->fieldref->p.field = fi;
-
-resolved_the_field:
-
-#ifdef ENABLE_VERIFIER
- /* Checking opt_verify is ok here, because the NULL iptr guarantees */
- /* that no missing parts of an instruction will be accessed. */
- if (opt_verify) {
- checkresult = resolve_field_verifier_checks(
- ref->referermethod,
- ref->fieldref,
- container,
- fi,
- NULL, /* instanceti, handled by constraints below */
- NULL, /* valueti, handled by constraints below */
- (ref->flags & RESOLVE_STATIC) != 0, /* isstatic */
- (ref->flags & RESOLVE_PUTFIELD) != 0 /* isput */);
-
- if (checkresult != resolveSucceeded)
- return (bool) checkresult;
-
- declarer = fi->clazz;
- assert(declarer);
- assert(declarer->state & CLASS_LOADED);
- assert(declarer->state & CLASS_LINKED);
-
- /* for non-static accesses we have to check the constraints on the */
- /* instance type */
-
- if (!(ref->flags & RESOLVE_STATIC)) {
- checkresult = resolve_and_check_subtype_set(ref->referermethod,
- &(ref->instancetypes),
- CLASSREF_OR_CLASSINFO(container),
- mode, resolveLinkageError);
- if (checkresult != resolveSucceeded)
- return (bool) checkresult;
- }
-
- fieldtyperef = ref->fieldref->parseddesc.fd->classref;
-
- /* for PUT* instructions we have to check the constraints on the value type */
- if (((ref->flags & RESOLVE_PUTFIELD) != 0) && fi->type == TYPE_ADR) {
- assert(fieldtyperef);
- if (!SUBTYPESET_IS_EMPTY(ref->valueconstraints)) {
- /* check subtype constraints */
- checkresult = resolve_and_check_subtype_set(ref->referermethod,
- &(ref->valueconstraints),
- CLASSREF_OR_CLASSINFO(fieldtyperef),
- mode, resolveLinkageError);
- if (checkresult != resolveSucceeded)
- return (bool) checkresult;
- }
- }
-
- /* check protected access */
- if (((fi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer)) {
- checkresult = resolve_and_check_subtype_set(ref->referermethod,
- &(ref->instancetypes),
- CLASSREF_OR_CLASSINFO(referer),
- mode,
- resolveIllegalAccessError);
- if (checkresult != resolveSucceeded)
- return (bool) checkresult;
- }
-
- }
-#endif /* ENABLE_VERIFIER */
-
- /* succeed */
- *result = fi;
-
- return true;
-}
-
-/* resolve_field_eager *********************************************************
-
- Resolve an unresolved field reference eagerly.
-
- IN:
- ref..............struct containing the reference
-
- RETURN VALUE:
- fieldinfo * to the field, or
- NULL if an exception has been thrown
-
-*******************************************************************************/
-
-fieldinfo * resolve_field_eager(unresolved_field *ref)
-{
- fieldinfo *fi;
-
- if (!resolve_field(ref,resolveEager,&fi))
- return NULL;
-
- return fi;
-}
-
-/******************************************************************************/
-/* METHOD RESOLUTION */
-/******************************************************************************/
-
-/* resolve_method_invokespecial_lookup *****************************************
-
- Do the special lookup for methods invoked by INVOKESPECIAL
-
- IN:
- refmethod........the method containing the reference
- mi...............the methodinfo of the resolved method
-
- RETURN VALUE:
- a methodinfo *...the result of the lookup,
- NULL.............an exception has been thrown
-
-*******************************************************************************/
-
-methodinfo * resolve_method_invokespecial_lookup(methodinfo *refmethod,
- methodinfo *mi)
-{
- classinfo *declarer;
- classinfo *referer;
-
- assert(refmethod);
- assert(mi);
-
- /* get referer and declarer classes */
-
- referer = refmethod->clazz;
- assert(referer);
-
- declarer = mi->clazz;
- assert(declarer);
- assert(referer->state & CLASS_LINKED);
-
- /* checks for INVOKESPECIAL: */
- /* for <init> and methods of the current class we don't need any */
- /* special checks. Otherwise we must verify that the called method */
- /* belongs to a super class of the current class */
-
- if ((referer != declarer) && (mi->name != utf_init)) {
- /* check that declarer is a super class of the current class */
-
- if (!class_issubclass(referer,declarer)) {
- exceptions_throw_verifyerror(refmethod,
- "INVOKESPECIAL calling non-super class method");
- return NULL;
- }
-
- /* if the referer has ACC_SUPER set, we must do the special */
- /* lookup starting with the direct super class of referer */
-
- if ((referer->flags & ACC_SUPER) != 0) {
- mi = class_resolvemethod(referer->super,
- mi->name,
- mi->descriptor);
-
- if (mi == NULL) {
- /* the spec calls for an AbstractMethodError in this case */
-
- exceptions_throw_abstractmethoderror();
-
- return NULL;
- }
- }
- }
-
- /* everything ok */
- return mi;
-}
-
-/* resolve_method_verifier_checks ******************************************
-
- Do the verifier checks necessary after a method has been resolved.
-
- IN:
- refmethod........the method containing the reference
- methodref........the method reference
- mi...............the methodinfo of the resolved method
- invokestatic.....true if the method is invoked by INVOKESTATIC
-
- RETURN VALUE:
- resolveSucceeded....everything ok
- resolveDeferred.....tests could not be done, have been deferred
- resolveFailed.......exception has been thrown
-
-*******************************************************************************/
-
-#if defined(ENABLE_VERIFIER)
-resolve_result_t resolve_method_verifier_checks(methodinfo *refmethod,
- constant_FMIref *methodref,
- methodinfo *mi,
- bool invokestatic)
-{
- classinfo *declarer;
- classinfo *referer;
- char *msg;
- s4 msglen;
- utf *u;
-
- assert(refmethod);
- assert(methodref);
- assert(mi);
-
-#ifdef RESOLVE_VERBOSE
- printf("resolve_method_verifier_checks\n");
- printf(" flags: %02x\n",mi->flags);
-#endif
-
- /* get the classinfos and the method descriptor */
-
- referer = refmethod->clazz;
- assert(referer);
-
- declarer = mi->clazz;
- assert(declarer);
-
- /* check static */
-
- if (((mi->flags & ACC_STATIC) != 0) != (invokestatic != false)) {
- /* a static method is accessed via an instance, or vice versa */
- exceptions_throw_incompatibleclasschangeerror(declarer,
- (mi->flags & ACC_STATIC)
- ? "static method called via instance"
- : "instance method called without instance");
-
- return resolveFailed;
- }
-
- /* check access rights */
-
- if (!access_is_accessible_member(referer,declarer,mi->flags)) {
- /* XXX clean this up. this should be in exceptions.c */
-
- msglen =
- utf_bytes(declarer->name) +
- utf_bytes(mi->name) +
- utf_bytes(mi->descriptor) +
- utf_bytes(referer->name) +
- 100;
-
- msg = MNEW(char, msglen);
-
- strcpy(msg, "method is not accessible (");
- utf_cat_classname(msg, declarer->name);
- strcat(msg, ".");
- utf_cat(msg, mi->name);
- utf_cat(msg, mi->descriptor);
- strcat(msg, " from ");
- utf_cat_classname(msg, referer->name);
- strcat(msg, ")");
-
- u = utf_new_char(msg);
-
- MFREE(msg, char, msglen);
-
- exceptions_throw_illegalaccessexception(u);
-
- return resolveFailed; /* exception */
- }
-
- /* everything ok */
-
- return resolveSucceeded;
-}
-#endif /* defined(ENABLE_VERIFIER) */
-
-
-/* resolve_method_instance_type_checks *****************************************
-
- Check the instance type of a method invocation.
-
- IN:
- refmethod........the method containing the reference
- mi...............the methodinfo of the resolved method
- instanceti.......typeinfo of the instance slot
- invokespecial....true if the method is invoked by INVOKESPECIAL
-
- RETURN VALUE:
- resolveSucceeded....everything ok
- resolveDeferred.....tests could not be done, have been deferred
- resolveFailed.......exception has been thrown
-
-*******************************************************************************/
-
-#if defined(ENABLE_VERIFIER)
-resolve_result_t resolve_method_instance_type_checks(methodinfo *refmethod,
- methodinfo *mi,
- typeinfo_t *instanceti,
- bool invokespecial)
-{
- typeinfo_t tinfo;
- typeinfo_t *tip;
- resolve_result_t result;
-
- if (invokespecial && TYPEINFO_IS_NEWOBJECT(*instanceti))
- { /* XXX clean up */
- instruction *ins = (instruction *) TYPEINFO_NEWOBJECT_INSTRUCTION(*instanceti);
- classref_or_classinfo initclass = (ins) ? ins[-1].sx.val.c
- : CLASSREF_OR_CLASSINFO(refmethod->clazz);
- tip = &tinfo;
- if (!typeinfo_init_class(tip, initclass))
- return false;
- }
- else {
- tip = instanceti;
- }
-
- result = resolve_lazy_subtype_checks(refmethod,
- tip,
- CLASSREF_OR_CLASSINFO(mi->clazz),
- resolveLinkageError);
- if (result != resolveSucceeded)
- return result;
-
- /* check protected access */
-
- /* XXX use other `declarer` than mi->clazz? */
- if (((mi->flags & ACC_PROTECTED) != 0)
- && !SAME_PACKAGE(mi->clazz, refmethod->clazz))
- {
- result = resolve_lazy_subtype_checks(refmethod,
- tip,
- CLASSREF_OR_CLASSINFO(refmethod->clazz),
- resolveIllegalAccessError);
- if (result != resolveSucceeded)
- return result;
- }
-
- /* everything ok */
-
- return resolveSucceeded;
-}
-#endif /* defined(ENABLE_VERIFIER) */
-
-
-/* resolve_method_param_type_checks ********************************************
-
- Check non-instance parameter types of a method invocation.
-
- IN:
- jd...............jitdata of the method doing the call
- refmethod........the method containing the reference
- iptr.............the invoke instruction
- mi...............the methodinfo of the resolved method
- invokestatic.....true if the method is invoked by INVOKESTATIC
-
- RETURN VALUE:
- resolveSucceeded....everything ok
- resolveDeferred.....tests could not be done, have been deferred
- resolveFailed.......exception has been thrown
-
-*******************************************************************************/
-
-#if defined(ENABLE_VERIFIER)
-resolve_result_t resolve_method_param_type_checks(jitdata *jd,
- methodinfo *refmethod,
- instruction *iptr,
- methodinfo *mi,
- bool invokestatic)
-{
- varinfo *param;
- resolve_result_t result;
- methoddesc *md;
- typedesc *paramtypes;
- s4 type;
- s4 instancecount;
- s4 i;
-
- assert(jd);
-
- instancecount = (invokestatic) ? 0 : 1;
-
- /* check subtype constraints for TYPE_ADR parameters */
-
- md = mi->parseddesc;
- paramtypes = md->paramtypes;
-
- for (i = md->paramcount-1-instancecount; i>=0; --i) {
- param = VAR(iptr->sx.s23.s2.args[i+instancecount]);
- type = md->paramtypes[i+instancecount].type;
-
- assert(param);
- assert(type == param->type);
-
- if (type == TYPE_ADR) {
- result = resolve_lazy_subtype_checks(refmethod,
- &(param->typeinfo),
- CLASSREF_OR_CLASSINFO(paramtypes[i+instancecount].classref),
- resolveLinkageError);
- if (result != resolveSucceeded)
- return result;
- }
- }
-
- /* everything ok */
-
- return resolveSucceeded;
-}
-#endif /* defined(ENABLE_VERIFIER) */
-
-
-/* resolve_method_param_type_checks_stackbased *********************************
-
- Check non-instance parameter types of a method invocation.
-
- IN:
- refmethod........the method containing the reference
- mi...............the methodinfo of the resolved method
- invokestatic.....true if the method is invoked by INVOKESTATIC
- stack............TOS before the INVOKE instruction
-
- RETURN VALUE:
- resolveSucceeded....everything ok
- resolveDeferred.....tests could not be done, have been deferred
- resolveFailed.......exception has been thrown
-
-*******************************************************************************/
-
-#if defined(ENABLE_VERIFIER)
-resolve_result_t resolve_method_param_type_checks_stackbased(
- methodinfo *refmethod,
- methodinfo *mi,
- bool invokestatic,
- typedescriptor_t *stack)
-{
- typedescriptor_t *param;
- resolve_result_t result;
- methoddesc *md;
- typedesc *paramtypes;
- s4 type;
- s4 instancecount;
- s4 i;
-
- instancecount = (invokestatic) ? 0 : 1;
-
- /* check subtype constraints for TYPE_ADR parameters */
-
- md = mi->parseddesc;
- paramtypes = md->paramtypes;
-
- param = stack - (md->paramslots - 1 - instancecount);
-
- for (i = instancecount; i < md->paramcount; ++i) {
- type = md->paramtypes[i].type;
-
- assert(type == param->type);
-
- if (type == TYPE_ADR) {
- result = resolve_lazy_subtype_checks(refmethod,
- &(param->typeinfo),
- CLASSREF_OR_CLASSINFO(paramtypes[i].classref),
- resolveLinkageError);
- if (result != resolveSucceeded)
- return result;
- }
-
- param += (IS_2_WORD_TYPE(type)) ? 2 : 1;
- }
-
- /* everything ok */
-
- return resolveSucceeded;
-}
-#endif /* defined(ENABLE_VERIFIER) */
-
-
-/* resolve_method_loading_constraints ******************************************
-
- Impose loading constraints on the parameters and return type of the
- given method.
-
- IN:
- referer..........the class refering to the method
- mi...............the method
-
- RETURN VALUE:
- true................everything ok
- false...............an exception has been thrown
-
-*******************************************************************************/
-
-#if defined(ENABLE_VERIFIER)
-bool resolve_method_loading_constraints(classinfo *referer,
- methodinfo *mi)
-{
- methoddesc *md;
- typedesc *paramtypes;
- utf *name;
- s4 i;
- s4 instancecount;
-
- /* impose loading constraints on parameters (including instance) */
-
- md = mi->parseddesc;
- paramtypes = md->paramtypes;
- instancecount = (mi->flags & ACC_STATIC) / ACC_STATIC;
-
- for (i = 0; i < md->paramcount; i++) {
- if (i < instancecount || paramtypes[i].type == TYPE_ADR) {
- if (i < instancecount) {
- /* The type of the 'this' pointer is the class containing */
- /* the method definition. Since container is the same as, */
- /* or a subclass of declarer, we also constrain declarer */
- /* by transitivity of loading constraints. */
- name = mi->clazz->name;
- }
- else {
- name = paramtypes[i].classref->name;
- }
-
- /* The caller (referer) and the callee (container) must agree */
- /* on the types of the parameters. */
- if (!classcache_add_constraint(referer->classloader,
- mi->clazz->classloader, name))
- return false; /* exception */
- }
- }
-
- /* impose loading constraint onto return type */
-
- if (md->returntype.type == TYPE_ADR) {
- /* The caller (referer) and the callee (container) must agree */
- /* on the return type. */
- if (!classcache_add_constraint(referer->classloader,
- mi->clazz->classloader,
- md->returntype.classref->name))
- return false; /* exception */
- }
-
- /* everything ok */
-
- return true;
-}
-#endif /* defined(ENABLE_VERIFIER) */
-
-
-/* resolve_method_lazy *********************************************************
-
- Resolve an unresolved method reference lazily
-
- NOTE: This function does NOT do any verification checks. In case of a
- successful resolution, you must call resolve_method_verifier_checks
- in order to perform the necessary checks!
-
- IN:
- refmethod........the referer method
- methodref........the method reference
- invokespecial....true if this is an INVOKESPECIAL instruction
-
- RETURN VALUE:
- resolveSucceeded.....the reference has been resolved
- resolveDeferred......the resolving could not be performed lazily
- resolveFailed........resolving failed, an exception has been thrown.
-
-*******************************************************************************/
-
-resolve_result_t resolve_method_lazy(methodinfo *refmethod,
- constant_FMIref *methodref,
- bool invokespecial)
-{
- classinfo *referer;
- classinfo *container;
- methodinfo *mi;
-
- assert(refmethod);
-
-#ifdef RESOLVE_VERBOSE
- printf("resolve_method_lazy\n");
-#endif
-
- /* the class containing the reference */
-
- referer = refmethod->clazz;
- assert(referer);
-
- /* check if the method itself is already resolved */
-
- if (IS_FMIREF_RESOLVED(methodref))
- return resolveSucceeded;
-
- /* first we must resolve the class containg the method */
-
- if (!resolve_class_from_name(referer, refmethod,
- methodref->p.classref->name, resolveLazy, true, true, &container))
- {
- /* the class reference could not be resolved */
- return resolveFailed; /* exception */
- }
- if (!container)
- return resolveDeferred; /* be lazy */
-
- assert(container->state & CLASS_LINKED);
-
- /* now we must find the declaration of the method in `container`
- * or one of its superclasses */
-
- if (container->flags & ACC_INTERFACE) {
- mi = class_resolveinterfacemethod(container,
- methodref->name,
- methodref->descriptor,
- referer, true);
-
- } else {
- mi = class_resolveclassmethod(container,
- methodref->name,
- methodref->descriptor,
- referer, true);
- }
-
- if (!mi) {
- /* The method does not exist. But since we were called lazily, */
- /* this error must not be reported now. (It will be reported */
- /* if eager resolving of this method is ever tried.) */
-
- exceptions_clear_exception();
- return resolveDeferred; /* be lazy */
- }
-
- if (invokespecial) {
- mi = resolve_method_invokespecial_lookup(refmethod, mi);
- if (!mi)
- return resolveFailed; /* exception */
- }
-
- /* have the method params already been parsed? no, do it. */
-
- if (!mi->parseddesc->params)
- if (!descriptor_params_from_paramtypes(mi->parseddesc, mi->flags))
- return resolveFailed;
-
- /* cache the result of the resolution */
-
- methodref->p.method = mi;
-
- /* succeed */
-
- return resolveSucceeded;
-}
-
-/* resolve_method **************************************************************
-
- Resolve an unresolved method reference
-
- IN:
- ref..............struct containing the reference
- mode.............mode of resolution:
- resolveLazy...only resolve if it does not
- require loading classes
- resolveEager..load classes if necessary
-
- OUT:
- *result..........set to the result of resolution, or to NULL if
- the reference has not been resolved
- In the case of an exception, *result is
- guaranteed to be set to NULL.
-
- RETURN VALUE:
- true.............everything ok
- (*result may still be NULL for resolveLazy)
- false............an exception has been thrown
-
-*******************************************************************************/
-
-bool resolve_method(unresolved_method *ref, resolve_mode_t mode, methodinfo **result)
-{
- classinfo *referer;
- classinfo *container;
- classinfo *declarer;
- methodinfo *mi;
- typedesc *paramtypes;
- int instancecount;
- int i;
- resolve_result_t checkresult;
-
- assert(ref);
- assert(result);
- assert(mode == resolveLazy || mode == resolveEager);
-
-#ifdef RESOLVE_VERBOSE
- unresolved_method_debug_dump(ref,stdout);
-#endif
-
- *result = NULL;
-
- /* the class containing the reference */
-
- referer = ref->referermethod->clazz;
- assert(referer);
-
- /* check if the method itself is already resolved */
-
- if (IS_FMIREF_RESOLVED(ref->methodref)) {
- mi = ref->methodref->p.method;
- container = mi->clazz;
- goto resolved_the_method;
- }
-
- /* first we must resolve the class containing the method */
-
- if (!resolve_class_from_name(referer,ref->referermethod,
- ref->methodref->p.classref->name,mode,true,true,&container))
- {
- /* the class reference could not be resolved */
- return false; /* exception */
- }
- if (!container)
- return true; /* be lazy */
-
- assert(container);
- assert(container->state & CLASS_LINKED);
-
- /* now we must find the declaration of the method in `container`
- * or one of its superclasses */
-
- if (container->flags & ACC_INTERFACE) {
- mi = class_resolveinterfacemethod(container,
- ref->methodref->name,
- ref->methodref->descriptor,
- referer, true);
-
- } else {
- mi = class_resolveclassmethod(container,
- ref->methodref->name,
- ref->methodref->descriptor,
- referer, true);
- }
-
- if (!mi) {
- if (mode == resolveLazy) {
- /* The method does not exist. But since we were called lazily, */
- /* this error must not be reported now. (It will be reported */
- /* if eager resolving of this method is ever tried.) */
-
- exceptions_clear_exception();
- return true; /* be lazy */
- }
-
- return false; /* exception */ /* XXX set exceptionptr? */
- }
-
- /* { the method reference has been resolved } */
-
- if (ref->flags & RESOLVE_SPECIAL) {
- mi = resolve_method_invokespecial_lookup(ref->referermethod,mi);
- if (!mi)
- return false; /* exception */
- }
-
- /* have the method params already been parsed? no, do it. */
-
- if (!mi->parseddesc->params)
- if (!descriptor_params_from_paramtypes(mi->parseddesc, mi->flags))
- return false;
-
- /* cache the resolution */
-
- ref->methodref->p.method = mi;
-
-resolved_the_method:
-
-#ifdef ENABLE_VERIFIER
- if (opt_verify) {
-
- checkresult = resolve_method_verifier_checks(
- ref->referermethod,
- ref->methodref,
- mi,
- (ref->flags & RESOLVE_STATIC));
-
- if (checkresult != resolveSucceeded)
- return (bool) checkresult;
-
- /* impose loading constraints on params and return type */
-
- if (!resolve_method_loading_constraints(referer, mi))
- return false;
-
- declarer = mi->clazz;
- assert(declarer);
- assert(referer->state & CLASS_LINKED);
-
- /* for non-static methods we have to check the constraints on the */
- /* instance type */
-
- if (!(ref->flags & RESOLVE_STATIC)) {
- checkresult = resolve_and_check_subtype_set(ref->referermethod,
- &(ref->instancetypes),
- CLASSREF_OR_CLASSINFO(container),
- mode,
- resolveLinkageError);
- if (checkresult != resolveSucceeded)
- return (bool) checkresult;
- instancecount = 1;
- }
- else {
- instancecount = 0;
- }
-
- /* check subtype constraints for TYPE_ADR parameters */
-
- assert(mi->parseddesc->paramcount == ref->methodref->parseddesc.md->paramcount);
- paramtypes = mi->parseddesc->paramtypes;
-
- for (i = 0; i < mi->parseddesc->paramcount-instancecount; i++) {
- if (paramtypes[i+instancecount].type == TYPE_ADR) {
- if (ref->paramconstraints) {
- checkresult = resolve_and_check_subtype_set(ref->referermethod,
- ref->paramconstraints + i,
- CLASSREF_OR_CLASSINFO(paramtypes[i+instancecount].classref),
- mode,
- resolveLinkageError);
- if (checkresult != resolveSucceeded)
- return (bool) checkresult;
- }
- }
- }
-
- /* check protected access */
-
- if (((mi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer))
- {
- checkresult = resolve_and_check_subtype_set(ref->referermethod,
- &(ref->instancetypes),
- CLASSREF_OR_CLASSINFO(referer),
- mode,
- resolveIllegalAccessError);
- if (checkresult != resolveSucceeded)
- return (bool) checkresult;
- }
- }
-#endif /* ENABLE_VERIFIER */
-
- /* succeed */
- *result = mi;
- return true;
-}
-
-/* resolve_method_eager ********************************************************
-
- Resolve an unresolved method reference eagerly.
-
- IN:
- ref..............struct containing the reference
-
- RETURN VALUE:
- methodinfo * to the method, or
- NULL if an exception has been thrown
-
-*******************************************************************************/
-
-methodinfo * resolve_method_eager(unresolved_method *ref)
-{
- methodinfo *mi;
-
- if (!resolve_method(ref,resolveEager,&mi))
- return NULL;
-
- return mi;
-}
-
-/******************************************************************************/
-/* CREATING THE DATA STRUCTURES */
-/******************************************************************************/
-
-#ifdef ENABLE_VERIFIER
-static bool unresolved_subtype_set_from_typeinfo(classinfo *referer,
- methodinfo *refmethod,
- unresolved_subtype_set *stset,
- typeinfo_t *tinfo,
- utf *declaredclassname)
-{
- int count;
- int i;
-
- assert(stset);
- assert(tinfo);
-
-#ifdef RESOLVE_VERBOSE
- printf("unresolved_subtype_set_from_typeinfo\n");
-#ifdef TYPEINFO_DEBUG
- typeinfo_print(stdout,tinfo,4);
-#endif
- printf(" declared classname:");utf_fprint_printable_ascii(stdout,declaredclassname);
- printf("\n");
-#endif
-
- if (TYPEINFO_IS_PRIMITIVE(*tinfo)) {
- exceptions_throw_verifyerror(refmethod,
- "Invalid use of returnAddress");
- return false;
- }
-
- if (TYPEINFO_IS_NEWOBJECT(*tinfo)) {
- exceptions_throw_verifyerror(refmethod,
- "Invalid use of uninitialized object");
- return false;
- }
-
- /* the nulltype is always assignable */
- if (TYPEINFO_IS_NULLTYPE(*tinfo))
- goto empty_set;
-
- /* every type is assignable to (BOOTSTRAP)java.lang.Object */
- if (declaredclassname == utf_java_lang_Object
- && referer->classloader == NULL) /* XXX do loading constraints make the second check obsolete? */
- {
- goto empty_set;
- }
-
- if (tinfo->merged) {
- count = tinfo->merged->count;
- stset->subtyperefs = MNEW(classref_or_classinfo,count + 1);
- for (i=0; i<count; ++i) {
- classref_or_classinfo c = tinfo->merged->list[i];
- if (tinfo->dimension > 0) {
- /* a merge of array types */
- /* the merged list contains the possible _element_ types, */
- /* so we have to create array types with these elements. */
- if (IS_CLASSREF(c)) {
- c.ref = class_get_classref_multiarray_of(tinfo->dimension,c.ref);
- }
- else {
- c.cls = class_multiarray_of(tinfo->dimension,c.cls,false);
- }
- }
- stset->subtyperefs[i] = c;
- }
- stset->subtyperefs[count].any = NULL; /* terminate */
- }
- else {
- if ((IS_CLASSREF(tinfo->typeclass)
- ? tinfo->typeclass.ref->name
- : tinfo->typeclass.cls->name) == declaredclassname)
- {
- /* the class names are the same */
- /* equality is guaranteed by the loading constraints */
- goto empty_set;
- }
- else {
- stset->subtyperefs = MNEW(classref_or_classinfo,1 + 1);
- stset->subtyperefs[0] = tinfo->typeclass;
- stset->subtyperefs[1].any = NULL; /* terminate */
- }
- }
-
- return true;
-
-empty_set:
- UNRESOLVED_SUBTYPE_SET_EMTPY(*stset);
- return true;
-}
-#endif /* ENABLE_VERIFIER */
-
-/* create_unresolved_class *****************************************************
-
- Create an unresolved_class struct for the given class reference
-
- IN:
- refmethod........the method triggering the resolution (if any)
- classref.........the class reference
- valuetype........value type to check against the resolved class
- may be NULL, if no typeinfo is available
-
- RETURN VALUE:
- a pointer to a new unresolved_class struct, or
- NULL if an exception has been thrown
-
-*******************************************************************************/
-
-#ifdef ENABLE_VERIFIER
-unresolved_class * create_unresolved_class(methodinfo *refmethod,
- constant_classref *classref,
- typeinfo_t *valuetype)
-{
- unresolved_class *ref;
-
-#ifdef RESOLVE_VERBOSE
- printf("create_unresolved_class\n");
- printf(" referer: ");utf_fprint_printable_ascii(stdout,classref->referer->name);fputc('\n',stdout);
- if (refmethod) {
- printf(" rmethod: ");utf_fprint_printable_ascii(stdout,refmethod->name);fputc('\n',stdout);
- printf(" rmdesc : ");utf_fprint_printable_ascii(stdout,refmethod->descriptor);fputc('\n',stdout);
- }
- printf(" name : ");utf_fprint_printable_ascii(stdout,classref->name);fputc('\n',stdout);
-#endif
-
- ref = NEW(unresolved_class);
- ref->classref = classref;
- ref->referermethod = refmethod;
-
- if (valuetype) {
- if (!unresolved_subtype_set_from_typeinfo(classref->referer,refmethod,
- &(ref->subtypeconstraints),valuetype,classref->name))
- return NULL;
- }
- else {
- UNRESOLVED_SUBTYPE_SET_EMTPY(ref->subtypeconstraints);
- }
-
- return ref;
-}
-#endif /* ENABLE_VERIFIER */
-
-/* resolve_create_unresolved_field *********************************************
-
- Create an unresolved_field struct for the given field access instruction
-
- IN:
- referer..........the class containing the reference
- refmethod........the method triggering the resolution (if any)
- iptr.............the {GET,PUT}{FIELD,STATIC}{,CONST} instruction
-
- RETURN VALUE:
- a pointer to a new unresolved_field struct, or
- NULL if an exception has been thrown
-
-*******************************************************************************/
-
-unresolved_field * resolve_create_unresolved_field(classinfo *referer,
- methodinfo *refmethod,
- instruction *iptr)
-{
- unresolved_field *ref;
- constant_FMIref *fieldref = NULL;
-
-#ifdef RESOLVE_VERBOSE
- printf("create_unresolved_field\n");
- printf(" referer: ");utf_fprint_printable_ascii(stdout,referer->name);fputc('\n',stdout);
- printf(" rmethod: ");utf_fprint_printable_ascii(stdout,refmethod->name);fputc('\n',stdout);
- printf(" rmdesc : ");utf_fprint_printable_ascii(stdout,refmethod->descriptor);fputc('\n',stdout);
-#endif
-
- ref = NEW(unresolved_field);
- ref->flags = 0;
- ref->referermethod = refmethod;
- UNRESOLVED_SUBTYPE_SET_EMTPY(ref->valueconstraints);
-
- switch (iptr->opc) {
- case ICMD_PUTFIELD:
- ref->flags |= RESOLVE_PUTFIELD;
- break;
-
- case ICMD_PUTFIELDCONST:
- ref->flags |= RESOLVE_PUTFIELD;
- break;
-
- case ICMD_PUTSTATIC:
- ref->flags |= RESOLVE_PUTFIELD | RESOLVE_STATIC;
- break;
-
- case ICMD_PUTSTATICCONST:
- ref->flags |= RESOLVE_PUTFIELD | RESOLVE_STATIC;
- break;
-
- case ICMD_GETFIELD:
- break;
-
- case ICMD_GETSTATIC:
- ref->flags |= RESOLVE_STATIC;
- break;
-
-#if !defined(NDEBUG)
- default:
- assert(false);
-#endif
- }
-
- fieldref = iptr->sx.s23.s3.fmiref;
-
- assert(fieldref);
-
-#ifdef RESOLVE_VERBOSE
-/* printf(" class : ");utf_fprint_printable_ascii(stdout,fieldref->p.classref->name);fputc('\n',stdout);*/
- printf(" name : ");utf_fprint_printable_ascii(stdout,fieldref->name);fputc('\n',stdout);
- printf(" desc : ");utf_fprint_printable_ascii(stdout,fieldref->descriptor);fputc('\n',stdout);
- printf(" type : ");descriptor_debug_print_typedesc(stdout,fieldref->parseddesc.fd);
- fputc('\n',stdout);
-#endif
-
- ref->fieldref = fieldref;
-
- return ref;
-}
-
-/* resolve_constrain_unresolved_field ******************************************
-
- Record subtype constraints for a field access.
-
- IN:
- ref..............the unresolved_field structure of the access
- referer..........the class containing the reference
- refmethod........the method triggering the resolution (if any)
- instanceti.......instance typeinfo, if available
- valueti..........value typeinfo, if available
-
- RETURN VALUE:
- true.............everything ok
- false............an exception has been thrown
-
-*******************************************************************************/
-
-#if defined(ENABLE_VERIFIER)
-bool resolve_constrain_unresolved_field(unresolved_field *ref,
- classinfo *referer,
- methodinfo *refmethod,
- typeinfo_t *instanceti,
- typeinfo_t *valueti)
-{
- constant_FMIref *fieldref;
- int type;
- typeinfo_t tinfo;
- typedesc *fd;
-
- assert(ref);
-
- fieldref = ref->fieldref;
- assert(fieldref);
-
-#ifdef RESOLVE_VERBOSE
- printf("constrain_unresolved_field\n");
- printf(" referer: ");utf_fprint_printable_ascii(stdout,referer->name);fputc('\n',stdout);
- printf(" rmethod: ");utf_fprint_printable_ascii(stdout,refmethod->name);fputc('\n',stdout);
- printf(" rmdesc : ");utf_fprint_printable_ascii(stdout,refmethod->descriptor);fputc('\n',stdout);
-/* printf(" class : ");utf_fprint_printable_ascii(stdout,fieldref->p.classref->name);fputc('\n',stdout); */
- printf(" name : ");utf_fprint_printable_ascii(stdout,fieldref->name);fputc('\n',stdout);
- printf(" desc : ");utf_fprint_printable_ascii(stdout,fieldref->descriptor);fputc('\n',stdout);
- printf(" type : ");descriptor_debug_print_typedesc(stdout,fieldref->parseddesc.fd);
- fputc('\n',stdout);
-#endif
-
- assert(instanceti || ((ref->flags & RESOLVE_STATIC) != 0));
- fd = fieldref->parseddesc.fd;
- assert(fd);
-
- /* record subtype constraints for the instance type, if any */
- if (instanceti) {
- typeinfo_t *insttip;
-
- /* The instanceslot must contain a reference to a non-array type */
- if (!TYPEINFO_IS_REFERENCE(*instanceti)) {
- exceptions_throw_verifyerror(refmethod,
- "illegal instruction: field access on non-reference");
- return false;
- }
- if (TYPEINFO_IS_ARRAY(*instanceti)) {
- exceptions_throw_verifyerror(refmethod,
- "illegal instruction: field access on array");
- return false;
- }
-
- if (((ref->flags & RESOLVE_PUTFIELD) != 0) &&
- TYPEINFO_IS_NEWOBJECT(*instanceti))
- {
- /* The instruction writes a field in an uninitialized object. */
- /* This is only allowed when a field of an uninitialized 'this' object is */
- /* written inside an initialization method */
-
- classinfo *initclass;
- instruction *ins = (instruction *) TYPEINFO_NEWOBJECT_INSTRUCTION(*instanceti);
-
- if (ins != NULL) {
- exceptions_throw_verifyerror(refmethod,
- "accessing field of uninitialized object");
- return false;
- }
- /* XXX check that class of field == refmethod->clazz */
- initclass = refmethod->clazz; /* XXX classrefs */
- assert(initclass->state & CLASS_LOADED);
- assert(initclass->state & CLASS_LINKED);
-
- typeinfo_init_classinfo(&tinfo, initclass);
- insttip = &tinfo;
- }
- else {
- insttip = instanceti;
- }
- if (!unresolved_subtype_set_from_typeinfo(referer, refmethod,
- &(ref->instancetypes), insttip,
- FIELDREF_CLASSNAME(fieldref)))
- return false;
- }
- else {
- UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
- }
-
- /* record subtype constraints for the value type, if any */
- type = fd->type;
- if (type == TYPE_ADR && ((ref->flags & RESOLVE_PUTFIELD) != 0)) {
- assert(valueti);
- if (!unresolved_subtype_set_from_typeinfo(referer, refmethod,
- &(ref->valueconstraints), valueti,
- fieldref->parseddesc.fd->classref->name))
- return false;
- }
- else {
- UNRESOLVED_SUBTYPE_SET_EMTPY(ref->valueconstraints);
- }
-
- return true;
-}
-#endif /* ENABLE_VERIFIER */
-
-/* resolve_create_unresolved_method ********************************************
-
- Create an unresolved_method struct for the given method invocation
-
- IN:
- referer..........the class containing the reference
- refmethod........the method triggering the resolution (if any)
- iptr.............the INVOKE* instruction
-
- RETURN VALUE:
- a pointer to a new unresolved_method struct, or
- NULL if an exception has been thrown
-
-*******************************************************************************/
-
-unresolved_method * resolve_create_unresolved_method(classinfo *referer,
- methodinfo *refmethod,
- constant_FMIref *methodref,
- bool invokestatic,
- bool invokespecial)
-{
- unresolved_method *ref;
-
- assert(methodref);
-
-#ifdef RESOLVE_VERBOSE
- printf("create_unresolved_method\n");
- printf(" referer: ");utf_fprint_printable_ascii(stdout,referer->name);fputc('\n',stdout);
- printf(" rmethod: ");utf_fprint_printable_ascii(stdout,refmethod->name);fputc('\n',stdout);
- printf(" rmdesc : ");utf_fprint_printable_ascii(stdout,refmethod->descriptor);fputc('\n',stdout);
- printf(" name : ");utf_fprint_printable_ascii(stdout,methodref->name);fputc('\n',stdout);
- printf(" desc : ");utf_fprint_printable_ascii(stdout,methodref->descriptor);fputc('\n',stdout);
-#endif
-
- /* allocate params if necessary */
- if (!methodref->parseddesc.md->params)
- if (!descriptor_params_from_paramtypes(methodref->parseddesc.md,
- (invokestatic) ? ACC_STATIC : ACC_NONE))
- return NULL;
-
- /* create the data structure */
- ref = NEW(unresolved_method);
- ref->flags = ((invokestatic) ? RESOLVE_STATIC : 0)
- | ((invokespecial) ? RESOLVE_SPECIAL : 0);
- ref->referermethod = refmethod;
- ref->methodref = methodref;
- ref->paramconstraints = NULL;
- UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
-
- return ref;
-}
-
-
-/* resolve_constrain_unresolved_method_instance ********************************
-
- Record subtype constraints for the instance argument of a method call.
-
- IN:
- ref..............the unresolved_method structure of the call
- referer..........the class containing the reference
- refmethod........the method triggering the resolution (if any)
- iptr.............the INVOKE* instruction
-
- RETURN VALUE:
- true.............everything ok
- false............an exception has been thrown
-
-*******************************************************************************/
-
-#if defined(ENABLE_VERIFIER)
-bool resolve_constrain_unresolved_method_instance(unresolved_method *ref,
- methodinfo *refmethod,
- typeinfo_t *instanceti,
- bool invokespecial)
-{
- constant_FMIref *methodref;
- constant_classref *instanceref;
- typeinfo_t tinfo;
- typeinfo_t *tip;
-
- assert(ref);
- methodref = ref->methodref;
- assert(methodref);
-
- /* XXX clean this up */
- instanceref = IS_FMIREF_RESOLVED(methodref)
- ? class_get_self_classref(methodref->p.method->clazz)
- : methodref->p.classref;
-
-#ifdef RESOLVE_VERBOSE
- printf("resolve_constrain_unresolved_method_instance\n");
- printf(" rmethod: "); method_println(refmethod);
- printf(" mref : "); method_methodref_println(methodref);
-#endif
-
- /* record subtype constraints for the instance type, if any */
-
- if (invokespecial && TYPEINFO_IS_NEWOBJECT(*instanceti))
- { /* XXX clean up */
- instruction *ins = (instruction *) TYPEINFO_NEWOBJECT_INSTRUCTION(*instanceti);
- classref_or_classinfo initclass = (ins) ? ins[-1].sx.val.c
- : CLASSREF_OR_CLASSINFO(refmethod->clazz);
- tip = &tinfo;
- if (!typeinfo_init_class(tip, initclass))
- return false;
- }
- else {
- tip = instanceti;
- }
-
- if (!unresolved_subtype_set_from_typeinfo(refmethod->clazz, refmethod,
- &(ref->instancetypes),tip,instanceref->name))
- return false;
-
- return true;
-}
-#endif /* defined(ENABLE_VERIFIER) */
-
-
-/* resolve_constrain_unresolved_method_params *********************************
-
- Record subtype constraints for the non-instance arguments of a method call.
-
- IN:
- jd...............current jitdata (for looking up variables)
- ref..............the unresolved_method structure of the call
- refmethod........the method triggering the resolution (if any)
- iptr.............the INVOKE* instruction
-
- RETURN VALUE:
- true.............everything ok
- false............an exception has been thrown
-
-*******************************************************************************/
-
-#if defined(ENABLE_VERIFIER)
-bool resolve_constrain_unresolved_method_params(jitdata *jd,
- unresolved_method *ref,
- methodinfo *refmethod,
- instruction *iptr)
-{
- constant_FMIref *methodref;
- varinfo *param;
- methoddesc *md;
- int i,j;
- int type;
- int instancecount;
-
- assert(ref);
- methodref = ref->methodref;
- assert(methodref);
- md = methodref->parseddesc.md;
- assert(md);
- assert(md->params != NULL);
-
-#ifdef RESOLVE_VERBOSE
- printf("resolve_constrain_unresolved_method_params\n");
- printf(" rmethod: "); method_println(refmethod);
- printf(" mref : "); method_methodref_println(methodref);
-#endif
-
- instancecount = (ref->flags & RESOLVE_STATIC) ? 0 : 1;
-
- /* record subtype constraints for the parameter types, if any */
-
- for (i=md->paramcount-1-instancecount; i>=0; --i) {
- param = VAR(iptr->sx.s23.s2.args[i+instancecount]);
- type = md->paramtypes[i+instancecount].type;
-
- assert(param);
- assert(type == param->type);
-
- if (type == TYPE_ADR) {
- if (!ref->paramconstraints) {
- ref->paramconstraints = MNEW(unresolved_subtype_set,md->paramcount);
- for (j=md->paramcount-1-instancecount; j>i; --j)
- UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[j]);
- }
- assert(ref->paramconstraints);
- if (!unresolved_subtype_set_from_typeinfo(refmethod->clazz, refmethod,
- ref->paramconstraints + i,&(param->typeinfo),
- md->paramtypes[i+instancecount].classref->name))
- return false;
- }
- else {
- if (ref->paramconstraints)
- UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[i]);
- }
- }
-
- return true;
-}
-#endif /* ENABLE_VERIFIER */
-
-
-/* resolve_constrain_unresolved_method_params_stackbased ***********************
-
- Record subtype constraints for the non-instance arguments of a method call.
-
- IN:
- ref..............the unresolved_method structure of the call
- refmethod........the method triggering the resolution (if any)
- stack............TOS before the INVOKE instruction
-
- RETURN VALUE:
- true.............everything ok
- false............an exception has been thrown
-
-*******************************************************************************/
-
-#if defined(ENABLE_VERIFIER)
-bool resolve_constrain_unresolved_method_params_stackbased(
- unresolved_method *ref,
- methodinfo *refmethod,
- typedescriptor_t *stack)
-{
- constant_FMIref *methodref;
- typedescriptor_t *param;
- methoddesc *md;
- int i,j;
- int type;
- int instancecount;
-
- assert(ref);
- methodref = ref->methodref;
- assert(methodref);
- md = methodref->parseddesc.md;
- assert(md);
- assert(md->params != NULL);
-
-#ifdef RESOLVE_VERBOSE
- printf("resolve_constrain_unresolved_method_params_stackbased\n");
- printf(" rmethod: "); method_println(refmethod);
- printf(" mref : "); method_methodref_println(methodref);
-#endif
-
- instancecount = (ref->flags & RESOLVE_STATIC) ? 0 : 1;
-
- /* record subtype constraints for the parameter types, if any */
-
- param = stack - (md->paramslots - 1 - instancecount);
-
- for (i = instancecount; i < md->paramcount; ++i) {
- type = md->paramtypes[i].type;
-
- assert(type == param->type);
-
- if (type == TYPE_ADR) {
- if (!ref->paramconstraints) {
- ref->paramconstraints = MNEW(unresolved_subtype_set,md->paramcount);
- for (j = 0; j < i - instancecount; ++j)
- UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[j]);
- }
- assert(ref->paramconstraints);
- if (!unresolved_subtype_set_from_typeinfo(refmethod->clazz, refmethod,
- ref->paramconstraints + i - instancecount,&(param->typeinfo),
- md->paramtypes[i].classref->name))
- return false;
- }
- else {
- if (ref->paramconstraints)
- UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[i]);
- }
-
- param += (IS_2_WORD_TYPE(type)) ? 2 : 1;
- }
-
- return true;
-}
-#endif /* ENABLE_VERIFIER */
-
-
-/******************************************************************************/
-/* FREEING MEMORY */
-/******************************************************************************/
-
-#ifdef ENABLE_VERIFIER
-inline static void unresolved_subtype_set_free_list(classref_or_classinfo *list)
-{
- if (list) {
- classref_or_classinfo *p = list;
-
- /* this is silly. we *only* need to count the elements for MFREE */
- while ((p++)->any)
- ;
- MFREE(list,classref_or_classinfo,(p - list));
- }
-}
-#endif /* ENABLE_VERIFIER */
-
-/* unresolved_class_free *******************************************************
-
- Free the memory used by an unresolved_class
-
- IN:
- ref..............the unresolved_class
-
-*******************************************************************************/
-
-void unresolved_class_free(unresolved_class *ref)
-{
- assert(ref);
-
-#ifdef ENABLE_VERIFIER
- unresolved_subtype_set_free_list(ref->subtypeconstraints.subtyperefs);
-#endif
- FREE(ref,unresolved_class);
-}
-
-/* unresolved_field_free *******************************************************
-
- Free the memory used by an unresolved_field
-
- IN:
- ref..............the unresolved_field
-
-*******************************************************************************/
-
-void unresolved_field_free(unresolved_field *ref)
-{
- assert(ref);
-
-#ifdef ENABLE_VERIFIER
- unresolved_subtype_set_free_list(ref->instancetypes.subtyperefs);
- unresolved_subtype_set_free_list(ref->valueconstraints.subtyperefs);
-#endif
- FREE(ref,unresolved_field);
-}
-
-/* unresolved_method_free ******************************************************
-
- Free the memory used by an unresolved_method
-
- IN:
- ref..............the unresolved_method
-
-*******************************************************************************/
-
-void unresolved_method_free(unresolved_method *ref)
-{
- assert(ref);
-
-#ifdef ENABLE_VERIFIER
- unresolved_subtype_set_free_list(ref->instancetypes.subtyperefs);
- if (ref->paramconstraints) {
- int i;
- int count = ref->methodref->parseddesc.md->paramcount;
-
- for (i=0; i<count; ++i)
- unresolved_subtype_set_free_list(ref->paramconstraints[i].subtyperefs);
- MFREE(ref->paramconstraints,unresolved_subtype_set,count);
- }
-#endif
- FREE(ref,unresolved_method);
-}
-
-/******************************************************************************/
-/* DEBUG DUMPS */
-/******************************************************************************/
-
-#if !defined(NDEBUG)
-
-/* unresolved_subtype_set_debug_dump *******************************************
-
- Print debug info for unresolved_subtype_set to stream
-
- IN:
- stset............the unresolved_subtype_set
- file.............the stream
-
-*******************************************************************************/
-
-void unresolved_subtype_set_debug_dump(unresolved_subtype_set *stset,FILE *file)
-{
- classref_or_classinfo *p;
-
- if (SUBTYPESET_IS_EMPTY(*stset)) {
- fprintf(file," (empty)\n");
- }
- else {
- p = stset->subtyperefs;
- for (;p->any; ++p) {
- if (IS_CLASSREF(*p)) {
- fprintf(file," ref: ");
- utf_fprint_printable_ascii(file,p->ref->name);
- }
- else {
- fprintf(file," cls: ");
- utf_fprint_printable_ascii(file,p->cls->name);
- }
- fputc('\n',file);
- }
- }
-}
-
-/* unresolved_class_debug_dump *************************************************
-
- Print debug info for unresolved_class to stream
-
- IN:
- ref..............the unresolved_class
- file.............the stream
-
-*******************************************************************************/
-
-void unresolved_class_debug_dump(unresolved_class *ref,FILE *file)
-{
- fprintf(file,"unresolved_class(%p):\n",(void *)ref);
- if (ref) {
- fprintf(file," referer : ");
- utf_fprint_printable_ascii(file,ref->classref->referer->name); fputc('\n',file);
- fprintf(file," refmethod : ");
- utf_fprint_printable_ascii(file,ref->referermethod->name); fputc('\n',file);
- fprintf(file," refmethodd: ");
- utf_fprint_printable_ascii(file,ref->referermethod->descriptor); fputc('\n',file);
- fprintf(file," classname : ");
- utf_fprint_printable_ascii(file,ref->classref->name); fputc('\n',file);
- fprintf(file," subtypeconstraints:\n");
- unresolved_subtype_set_debug_dump(&(ref->subtypeconstraints),file);
- }
-}
-
-/* unresolved_field_debug_dump *************************************************
-
- Print debug info for unresolved_field to stream
-
- IN:
- ref..............the unresolved_field
- file.............the stream
-
-*******************************************************************************/
-
-void unresolved_field_debug_dump(unresolved_field *ref,FILE *file)
-{
- fprintf(file,"unresolved_field(%p):\n",(void *)ref);
- if (ref) {
- fprintf(file," referer : ");
- utf_fprint_printable_ascii(file,ref->referermethod->clazz->name); fputc('\n',file);
- fprintf(file," refmethod : ");
- utf_fprint_printable_ascii(file,ref->referermethod->name); fputc('\n',file);
- fprintf(file," refmethodd: ");
- utf_fprint_printable_ascii(file,ref->referermethod->descriptor); fputc('\n',file);
- fprintf(file," classname : ");
- utf_fprint_printable_ascii(file,FIELDREF_CLASSNAME(ref->fieldref)); fputc('\n',file);
- fprintf(file," name : ");
- utf_fprint_printable_ascii(file,ref->fieldref->name); fputc('\n',file);
- fprintf(file," descriptor: ");
- utf_fprint_printable_ascii(file,ref->fieldref->descriptor); fputc('\n',file);
- fprintf(file," parseddesc: ");
- descriptor_debug_print_typedesc(file,ref->fieldref->parseddesc.fd); fputc('\n',file);
- fprintf(file," flags : %04x\n",ref->flags);
- fprintf(file," instancetypes:\n");
- unresolved_subtype_set_debug_dump(&(ref->instancetypes),file);
- fprintf(file," valueconstraints:\n");
- unresolved_subtype_set_debug_dump(&(ref->valueconstraints),file);
- }
-}
-
-/* unresolved_method_debug_dump ************************************************
-
- Print debug info for unresolved_method to stream
-
- IN:
- ref..............the unresolved_method
- file.............the stream
-
-*******************************************************************************/
-
-void unresolved_method_debug_dump(unresolved_method *ref,FILE *file)
-{
- int i;
-
- fprintf(file,"unresolved_method(%p):\n",(void *)ref);
- if (ref) {
- fprintf(file," referer : ");
- utf_fprint_printable_ascii(file,ref->referermethod->clazz->name); fputc('\n',file);
- fprintf(file," refmethod : ");
- utf_fprint_printable_ascii(file,ref->referermethod->name); fputc('\n',file);
- fprintf(file," refmethodd: ");
- utf_fprint_printable_ascii(file,ref->referermethod->descriptor); fputc('\n',file);
- fprintf(file," classname : ");
- utf_fprint_printable_ascii(file,METHODREF_CLASSNAME(ref->methodref)); fputc('\n',file);
- fprintf(file," name : ");
- utf_fprint_printable_ascii(file,ref->methodref->name); fputc('\n',file);
- fprintf(file," descriptor: ");
- utf_fprint_printable_ascii(file,ref->methodref->descriptor); fputc('\n',file);
- fprintf(file," parseddesc: ");
- descriptor_debug_print_methoddesc(file,ref->methodref->parseddesc.md); fputc('\n',file);
- fprintf(file," flags : %04x\n",ref->flags);
- fprintf(file," instancetypes:\n");
- unresolved_subtype_set_debug_dump(&(ref->instancetypes),file);
- fprintf(file," paramconstraints:\n");
- if (ref->paramconstraints) {
- for (i=0; i<ref->methodref->parseddesc.md->paramcount; ++i) {
- fprintf(file," param %d:\n",i);
- unresolved_subtype_set_debug_dump(ref->paramconstraints + i,file);
- }
- }
- else {
- fprintf(file," (empty)\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/resolve.cpp - resolving classes/interfaces/fields/methods
+
+ 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 "mm/memory.h"
+
+#include "vm/access.h"
+#include "vm/classcache.h"
+#include "vm/descriptor.h"
+#include "vm/exceptions.hpp"
+#include "vm/global.h"
+#include "vm/globals.hpp"
+#include "vm/linker.h"
+#include "vm/loader.hpp"
+#include "vm/options.h"
+#include "vm/primitive.hpp"
+#include "vm/resolve.hpp"
+
+#include "vm/jit/jit.hpp"
+#include "vm/jit/verify/typeinfo.h"
+
+
+/******************************************************************************/
+/* DEBUG HELPERS */
+/******************************************************************************/
+
+/*#define RESOLVE_VERBOSE*/
+
+/* resolve_handle_pending_exception ********************************************
+
+ Convert a pending ClassNotFoundException into a
+ NoClassDefFoundError if requested.
+
+ See: hotspot/src/share/vm/classfile/systemDictionary.cpp
+ (handle_resolution_exception)
+
+ ARGUMENTS:
+ classname .... name of the class currently resolved
+ throwError ... if true throw a NoClassDefFoundError instead of
+ a ClassNotFoundException
+
+*******************************************************************************/
+
+void resolve_handle_pending_exception(bool throwError)
+{
+ java_handle_t *e;
+
+ /* Get the current exception. */
+
+ e = exceptions_get_exception();
+
+ if (e != NULL) {
+ if (throwError == true) {
+ /* Convert ClassNotFoundException to
+ NoClassDefFoundError. */
+
+ if (builtin_instanceof(e, class_java_lang_ClassNotFoundException)) {
+ /* Clear exception, because we are calling Java code
+ again. */
+
+ exceptions_clear_exception();
+
+ /* create new error */
+
+ exceptions_throw_noclassdeffounderror_cause(e);
+ }
+ else {
+ return;
+ }
+ }
+ else {
+ /* An exception conversion was not requested. Simply
+ return. */
+
+ return;
+ }
+ }
+}
+
+
+/******************************************************************************/
+/* CLASS RESOLUTION */
+/******************************************************************************/
+
+/* resolve_class_from_name *****************************************************
+
+ Resolve a symbolic class reference
+
+ IN:
+ referer..........the class containing the reference
+ refmethod........the method from which resolution was triggered
+ (may be NULL if not applicable)
+ classname........class name to resolve
+ mode.............mode of resolution:
+ resolveLazy...only resolve if it does not
+ require loading classes
+ resolveEager..load classes if necessary
+ checkaccess......if true, access rights to the class are checked
+ link.............if true, guarantee that the returned class, if any,
+ has been linked
+
+ OUT:
+ *result..........set to result of resolution, or to NULL if
+ the reference has not been resolved
+ In the case of an exception, *result is
+ guaranteed to be set to NULL.
+
+ RETURN VALUE:
+ true.............everything ok
+ (*result may still be NULL for resolveLazy)
+ false............an exception has been thrown
+
+ NOTE:
+ The returned class is *not* guaranteed to be linked!
+ (It is guaranteed to be loaded, though.)
+
+*******************************************************************************/
+
+bool resolve_class_from_name(classinfo *referer,
+ methodinfo *refmethod,
+ utf *classname,
+ resolve_mode_t mode,
+ bool checkaccess,
+ bool link,
+ classinfo **result)
+{
+ classinfo *cls;
+ char *utf_ptr;
+ int len;
+ char *msg;
+ s4 msglen;
+ utf *u;
+
+ assert(result);
+ assert(referer);
+ assert(classname);
+ assert(mode == resolveLazy || mode == resolveEager);
+
+ *result = NULL;
+
+#ifdef RESOLVE_VERBOSE
+ printf("resolve_class_from_name(");
+ utf_fprint_printable_ascii(stdout,referer->name);
+ printf(",%p,",(void*)referer->classloader);
+ utf_fprint_printable_ascii(stdout,classname);
+ printf(",%d,%d)\n",(int)checkaccess,(int)link);
+#endif
+
+ /* lookup if this class has already been loaded */
+
+ cls = classcache_lookup(referer->classloader, classname);
+
+#ifdef RESOLVE_VERBOSE
+ printf(" lookup result: %p\n",(void*)cls);
+#endif
+
+ if (!cls) {
+ /* resolve array types */
+
+ if (classname->text[0] == '[') {
+ utf_ptr = classname->text + 1;
+ len = classname->blength - 1;
+
+ /* classname is an array type name */
+
+ switch (*utf_ptr) {
+ case 'L':
+ utf_ptr++;
+ len -= 2;
+ /* FALLTHROUGH */
+ case '[':
+ /* the component type is a reference type */
+ /* resolve the component type */
+ if (!resolve_class_from_name(referer,refmethod,
+ utf_new(utf_ptr,len),
+ mode,checkaccess,link,&cls))
+ return false; /* exception */
+ if (!cls) {
+ assert(mode == resolveLazy);
+ return true; /* be lazy */
+ }
+ /* create the array class */
+ cls = class_array_of(cls,false);
+ if (!cls)
+ return false; /* exception */
+ }
+ }
+ else {
+ /* the class has not been loaded, yet */
+ if (mode == resolveLazy)
+ return true; /* be lazy */
+ }
+
+#ifdef RESOLVE_VERBOSE
+ printf(" loading...\n");
+#endif
+
+ /* load the class */
+
+ if (cls == NULL) {
+ cls = load_class_from_classloader(classname, referer->classloader);
+
+ if (cls == NULL)
+ return false;
+ }
+ }
+
+ /* the class is now loaded */
+ assert(cls);
+ assert(cls->state & CLASS_LOADED);
+
+#ifdef RESOLVE_VERBOSE
+ printf(" checking access rights...\n");
+#endif
+
+ /* check access rights of referer to refered class */
+
+ if (checkaccess && !access_is_accessible_class(referer,cls)) {
+ msglen =
+ utf_bytes(cls->name) +
+ utf_bytes(referer->name) +
+ 100;
+
+ msg = MNEW(char, msglen);
+
+ strcpy(msg, "class is not accessible (");
+ utf_cat_classname(msg, cls->name);
+ strcat(msg, " from ");
+ utf_cat_classname(msg, referer->name);
+ strcat(msg, ")");
+
+ u = utf_new_char(msg);
+
+ MFREE(msg, char, msglen);
+
+ exceptions_throw_illegalaccessexception(u);
+
+ return false; /* exception */
+ }
+
+ /* link the class if necessary */
+ if (link) {
+ if (!(cls->state & CLASS_LINKED))
+ if (!link_class(cls))
+ return false; /* exception */
+
+ assert(cls->state & CLASS_LINKED);
+ }
+
+ /* resolution succeeds */
+#ifdef RESOLVE_VERBOSE
+ printf(" success.\n");
+#endif
+ *result = cls;
+ return true;
+}
+
+/* resolve_classref ************************************************************
+
+ Resolve a symbolic class reference
+
+ IN:
+ refmethod........the method from which resolution was triggered
+ (may be NULL if not applicable)
+ ref..............class reference
+ mode.............mode of resolution:
+ resolveLazy...only resolve if it does not
+ require loading classes
+ resolveEager..load classes if necessary
+ checkaccess......if true, access rights to the class are checked
+ link.............if true, guarantee that the returned class, if any,
+ has been linked
+
+ OUT:
+ *result..........set to result of resolution, or to NULL if
+ the reference has not been resolved
+ In the case of an exception, *result is
+ guaranteed to be set to NULL.
+
+ RETURN VALUE:
+ true.............everything ok
+ (*result may still be NULL for resolveLazy)
+ false............an exception has been thrown
+
+*******************************************************************************/
+
+bool resolve_classref(methodinfo *refmethod,
+ constant_classref *ref,
+ resolve_mode_t mode,
+ bool checkaccess,
+ bool link,
+ classinfo **result)
+{
+ return resolve_classref_or_classinfo(refmethod,CLASSREF_OR_CLASSINFO(ref),mode,checkaccess,link,result);
+}
+
+/* resolve_classref_or_classinfo ***********************************************
+
+ Resolve a symbolic class reference if necessary
+
+ NOTE: If given, refmethod->clazz is used as the referring class.
+ Otherwise, cls.ref->referer is used.
+
+ IN:
+ refmethod........the method from which resolution was triggered
+ (may be NULL if not applicable)
+ cls..............class reference or classinfo
+ mode.............mode of resolution:
+ resolveLazy...only resolve if it does not
+ require loading classes
+ resolveEager..load classes if necessary
+ checkaccess......if true, access rights to the class are checked
+ link.............if true, guarantee that the returned class, if any,
+ has been linked
+
+ OUT:
+ *result..........set to result of resolution, or to NULL if
+ the reference has not been resolved
+ In the case of an exception, *result is
+ guaranteed to be set to NULL.
+
+ RETURN VALUE:
+ true.............everything ok
+ (*result may still be NULL for resolveLazy)
+ false............an exception has been thrown
+
+*******************************************************************************/
+
+bool resolve_classref_or_classinfo(methodinfo *refmethod,
+ classref_or_classinfo cls,
+ resolve_mode_t mode,
+ bool checkaccess,
+ bool link,
+ classinfo **result)
+{
+ classinfo *c;
+ classinfo *referer;
+
+ assert(cls.any);
+ assert(mode == resolveEager || mode == resolveLazy);
+ assert(result);
+
+#ifdef RESOLVE_VERBOSE
+ printf("resolve_classref_or_classinfo(");
+ utf_fprint_printable_ascii(stdout,(IS_CLASSREF(cls)) ? cls.ref->name : cls.cls->name);
+ printf(",%i,%i,%i)\n",mode,(int)checkaccess,(int)link);
+#endif
+
+ *result = NULL;
+
+ if (IS_CLASSREF(cls)) {
+ /* we must resolve this reference */
+
+ /* determine which class to use as the referer */
+
+ /* Common cases are refmethod == NULL or both referring classes */
+ /* being the same, so the referer usually is cls.ref->referer. */
+ /* There is one important case where it is not: When we do a */
+ /* deferred assignability check to a formal argument of a method, */
+ /* we must use refmethod->clazz (the caller's class) to resolve */
+ /* the type of the formal argument. */
+
+ referer = (refmethod) ? refmethod->clazz : cls.ref->referer;
+
+ if (!resolve_class_from_name(referer, refmethod, cls.ref->name,
+ mode, checkaccess, link, &c))
+ goto return_exception;
+
+ } else {
+ /* cls has already been resolved */
+ c = cls.cls;
+ assert(c->state & CLASS_LOADED);
+ }
+ assert(c || (mode == resolveLazy));
+
+ if (!c)
+ return true; /* be lazy */
+
+ assert(c);
+ assert(c->state & CLASS_LOADED);
+
+ if (link) {
+ if (!(c->state & CLASS_LINKED))
+ if (!link_class(c))
+ goto return_exception;
+
+ assert(c->state & CLASS_LINKED);
+ }
+
+ /* succeeded */
+ *result = c;
+ return true;
+
+ return_exception:
+ *result = NULL;
+ return false;
+}
+
+
+/* resolve_classref_or_classinfo_eager *****************************************
+
+ Resolve a symbolic class reference eagerly if necessary.
+ No attempt is made to link the class.
+
+ IN:
+ cls..............class reference or classinfo
+ checkaccess......if true, access rights to the class are checked
+
+ RETURN VALUE:
+ classinfo *......the resolved class
+ NULL.............an exception has been thrown
+
+*******************************************************************************/
+
+classinfo *resolve_classref_or_classinfo_eager(classref_or_classinfo cls,
+ bool checkaccess)
+{
+ classinfo *c;
+
+ if (!resolve_classref_or_classinfo(NULL, cls, resolveEager, checkaccess, false, &c))
+ return NULL;
+
+ return c;
+}
+
+
+/* resolve_class_from_typedesc *************************************************
+
+ Return a classinfo * for the given type descriptor
+
+ IN:
+ d................type descriptor
+ checkaccess......if true, access rights to the class are checked
+ link.............if true, guarantee that the returned class, if any,
+ has been linked
+ OUT:
+ *result..........set to result of resolution, or to NULL if
+ the reference has not been resolved
+ In the case of an exception, *result is
+ guaranteed to be set to NULL.
+
+ RETURN VALUE:
+ true.............everything ok
+ false............an exception has been thrown
+
+ NOTE:
+ This function always resolves eagerly.
+
+*******************************************************************************/
+
+bool resolve_class_from_typedesc(typedesc *d, bool checkaccess, bool link, classinfo **result)
+{
+ classinfo *cls;
+
+ assert(d);
+ assert(result);
+
+ *result = NULL;
+
+#ifdef RESOLVE_VERBOSE
+ printf("resolve_class_from_typedesc(");
+ descriptor_debug_print_typedesc(stdout,d);
+ printf(",%i,%i)\n",(int)checkaccess,(int)link);
+#endif
+
+ if (d->type == TYPE_ADR) {
+ /* a reference type */
+ assert(d->classref);
+ if (!resolve_classref_or_classinfo(NULL,CLASSREF_OR_CLASSINFO(d->classref),
+ resolveEager,checkaccess,link,&cls))
+ return false; /* exception */
+ }
+ else {
+ /* a primitive type */
+
+ cls = Primitive::get_class_by_type(d->primitivetype);
+
+ assert(cls->state & CLASS_LOADED);
+
+ if (!(cls->state & CLASS_LINKED))
+ if (!link_class(cls))
+ return false; /* exception */
+ }
+
+ assert(cls);
+ assert(cls->state & CLASS_LOADED);
+ assert(!link || (cls->state & CLASS_LINKED));
+
+#ifdef RESOLVE_VERBOSE
+ printf(" result = ");utf_fprint_printable_ascii(stdout,cls->name);printf("\n");
+#endif
+
+ *result = cls;
+ return true;
+}
+
+/******************************************************************************/
+/* SUBTYPE SET CHECKS */
+/******************************************************************************/
+
+/* resolve_subtype_check *******************************************************
+
+ Resolve the given types lazily and perform a subtype check
+
+ IN:
+ refmethod........the method triggering the resolution
+ subtype..........checked to be a subtype of supertype
+ supertype........the super type to check agaings
+ mode.............mode of resolution:
+ resolveLazy...only resolve if it does not
+ require loading classes
+ resolveEager..load classes if necessary
+ error............which type of exception to throw if
+ the test fails. May be:
+ resolveLinkageError, or
+ resolveIllegalAccessError
+ IMPORTANT: If error==resolveIllegalAccessError,
+ then array types are not checked.
+
+ RETURN VALUE:
+ resolveSucceeded.....the check succeeded
+ resolveDeferred......the check could not be performed due to
+ unresolved types. (This can only happen for
+ mode == resolveLazy.)
+ resolveFailed........the check failed, an exception has been thrown.
+
+ NOTE:
+ The types are resolved first, so any
+ exception which may occurr during resolution may
+ be thrown by this function.
+
+*******************************************************************************/
+
+#if defined(ENABLE_VERIFIER)
+static resolve_result_t resolve_subtype_check(methodinfo *refmethod,
+ classref_or_classinfo subtype,
+ classref_or_classinfo supertype,
+ resolve_mode_t mode,
+ resolve_err_t error)
+{
+ classinfo *subclass;
+ typeinfo_t subti;
+ typecheck_result r;
+ char *msg;
+ s4 msglen;
+ utf *u;
+
+ assert(refmethod);
+ assert(subtype.any);
+ assert(supertype.any);
+ assert(mode == resolveLazy || mode == resolveEager);
+ assert(error == resolveLinkageError || error == resolveIllegalAccessError);
+
+ /* resolve the subtype */
+
+ if (!resolve_classref_or_classinfo(refmethod,subtype,mode,false,true,&subclass)) {
+ /* the subclass could not be resolved. therefore we are sure that */
+ /* no instances of this subclass will ever exist -> skip this test */
+ /* XXX this assumes that class loading has invariant results (as in JVM spec) */
+ exceptions_clear_exception();
+ return resolveSucceeded;
+ }
+ if (!subclass)
+ return resolveDeferred; /* be lazy */
+
+ assert(subclass->state & CLASS_LINKED);
+
+ /* do not check access to protected members of arrays */
+
+ if (error == resolveIllegalAccessError && subclass->name->text[0] == '[') {
+ return resolveSucceeded;
+ }
+
+ /* perform the subtype check */
+
+ typeinfo_init_classinfo(&subti,subclass);
+check_again:
+ r = typeinfo_is_assignable_to_class(&subti,supertype);
+ if (r == typecheck_FAIL)
+ return resolveFailed; /* failed, exception is already set */
+
+ if (r == typecheck_MAYBE) {
+ assert(IS_CLASSREF(supertype));
+ if (mode == resolveEager) {
+ if (!resolve_classref_or_classinfo(refmethod,supertype,
+ resolveEager,false,true,
+ &supertype.cls))
+ {
+ return resolveFailed;
+ }
+ assert(supertype.cls);
+ goto check_again;
+ }
+
+ return resolveDeferred; /* be lazy */
+ }
+
+ if (!r) {
+ /* sub class relationship is false */
+
+#if defined(RESOLVE_VERBOSE)
+ printf("SUBTYPE CHECK FAILED!\n");
+#endif
+
+ msglen =
+ utf_bytes(subclass->name) +
+ utf_bytes(CLASSREF_OR_CLASSINFO_NAME(supertype))
+ + 200;
+
+ msg = MNEW(char, msglen);
+
+ strcpy(msg, (error == resolveIllegalAccessError) ?
+ "illegal access to protected member (" :
+ "subtype constraint violated (");
+
+ utf_cat_classname(msg, subclass->name);
+ strcat(msg, " is not a subclass of ");
+ utf_cat_classname(msg, CLASSREF_OR_CLASSINFO_NAME(supertype));
+ strcat(msg, ")");
+
+ u = utf_new_char(msg);
+
+ if (error == resolveIllegalAccessError)
+ exceptions_throw_illegalaccessexception(u);
+ else
+ exceptions_throw_linkageerror(msg, NULL);
+
+ /* ATTENTION: We probably need msg for
+ exceptions_throw_linkageerror. */
+
+ MFREE(msg, char, msglen);
+
+ return resolveFailed; /* exception */
+ }
+
+ /* everything ok */
+
+ return resolveSucceeded;
+}
+#endif /* defined(ENABLE_VERIFIER) */
+
+/* resolve_lazy_subtype_checks *************************************************
+
+ Resolve the types to check lazily and perform subtype checks
+
+ IN:
+ refmethod........the method triggering the resolution
+ subtinfo.........the typeinfo containing the subtypes
+ supertype........the supertype to test againgst
+ mode.............mode of resolution:
+ resolveLazy...only resolve if it does not
+ require loading classes
+ resolveEager..load classes if necessary
+ error............which type of exception to throw if
+ the test fails. May be:
+ resolveLinkageError, or
+ resolveIllegalAccessError
+ IMPORTANT: If error==resolveIllegalAccessError,
+ then array types in the set are skipped.
+
+ RETURN VALUE:
+ resolveSucceeded.....the check succeeded
+ resolveDeferred......the check could not be performed due to
+ unresolved types
+ resolveFailed........the check failed, an exception has been thrown.
+
+ NOTE:
+ The references in the set are resolved first, so any
+ exception which may occurr during resolution may
+ be thrown by this function.
+
+*******************************************************************************/
+
+#if defined(ENABLE_VERIFIER)
+static resolve_result_t resolve_lazy_subtype_checks(methodinfo *refmethod,
+ typeinfo_t *subtinfo,
+ classref_or_classinfo supertype,
+ resolve_err_t error)
+{
+ int count;
+ int i;
+ resolve_result_t result;
+
+ assert(refmethod);
+ assert(subtinfo);
+ assert(supertype.any);
+ assert(error == resolveLinkageError || error == resolveIllegalAccessError);
+
+ /* returnAddresses are illegal here */
+
+ if (TYPEINFO_IS_PRIMITIVE(*subtinfo)) {
+ exceptions_throw_verifyerror(refmethod,
+ "Invalid use of returnAddress");
+ return resolveFailed;
+ }
+
+ /* uninitialized objects are illegal here */
+
+ if (TYPEINFO_IS_NEWOBJECT(*subtinfo)) {
+ exceptions_throw_verifyerror(refmethod,
+ "Invalid use of uninitialized object");
+ return resolveFailed;
+ }
+
+ /* the nulltype is always assignable */
+
+ if (TYPEINFO_IS_NULLTYPE(*subtinfo))
+ return resolveSucceeded;
+
+ /* every type is assignable to (BOOTSTRAP)java.lang.Object */
+
+ if (supertype.cls == class_java_lang_Object
+ || (CLASSREF_OR_CLASSINFO_NAME(supertype) == utf_java_lang_Object
+ && refmethod->clazz->classloader == NULL))
+ {
+ return resolveSucceeded;
+ }
+
+ if (subtinfo->merged) {
+
+ /* for a merged type we have to do a series of checks */
+
+ count = subtinfo->merged->count;
+ for (i=0; i<count; ++i) {
+ classref_or_classinfo c = subtinfo->merged->list[i];
+ if (subtinfo->dimension > 0) {
+ /* a merge of array types */
+ /* the merged list contains the possible _element_ types, */
+ /* so we have to create array types with these elements. */
+ if (IS_CLASSREF(c)) {
+ c.ref = class_get_classref_multiarray_of(subtinfo->dimension,c.ref);
+ }
+ else {
+ c.cls = class_multiarray_of(subtinfo->dimension,c.cls,false);
+ }
+ }
+
+ /* do the subtype check against the type c */
+
+ result = resolve_subtype_check(refmethod,c,supertype,resolveLazy,error);
+ if (result != resolveSucceeded)
+ return result;
+ }
+ }
+ else {
+
+ /* a single type, this is the common case, hopefully */
+
+ if (CLASSREF_OR_CLASSINFO_NAME(subtinfo->typeclass)
+ == CLASSREF_OR_CLASSINFO_NAME(supertype))
+ {
+ /* the class names are the same */
+ /* equality is guaranteed by the loading constraints */
+ return resolveSucceeded;
+ }
+ else {
+
+ /* some other type name, try to perform the check lazily */
+
+ return resolve_subtype_check(refmethod,
+ subtinfo->typeclass,supertype,
+ resolveLazy,
+ error);
+ }
+ }
+
+ /* everything ok */
+ return resolveSucceeded;
+}
+#endif /* defined(ENABLE_VERIFIER) */
+
+/* resolve_and_check_subtype_set ***********************************************
+
+ Resolve the references in the given set and test subtype relationships
+
+ IN:
+ refmethod........the method triggering the resolution
+ ref..............a set of class/interface references
+ (may be empty)
+ typeref..........the type to test against the set
+ mode.............mode of resolution:
+ resolveLazy...only resolve if it does not
+ require loading classes
+ resolveEager..load classes if necessary
+ error............which type of exception to throw if
+ the test fails. May be:
+ resolveLinkageError, or
+ resolveIllegalAccessError
+ IMPORTANT: If error==resolveIllegalAccessError,
+ then array types in the set are skipped.
+
+ RETURN VALUE:
+ resolveSucceeded.....the check succeeded
+ resolveDeferred......the check could not be performed due to
+ unresolved types. (This can only happen if
+ mode == resolveLazy.)
+ resolveFailed........the check failed, an exception has been thrown.
+
+ NOTE:
+ The references in the set are resolved first, so any
+ exception which may occurr during resolution may
+ be thrown by this function.
+
+*******************************************************************************/
+
+#if defined(ENABLE_VERIFIER)
+static resolve_result_t resolve_and_check_subtype_set(methodinfo *refmethod,
+ unresolved_subtype_set *ref,
+ classref_or_classinfo typeref,
+ resolve_mode_t mode,
+ resolve_err_t error)
+{
+ classref_or_classinfo *setp;
+ resolve_result_t checkresult;
+
+ assert(refmethod);
+ assert(ref);
+ assert(typeref.any);
+ assert(mode == resolveLazy || mode == resolveEager);
+ assert(error == resolveLinkageError || error == resolveIllegalAccessError);
+
+#if defined(RESOLVE_VERBOSE)
+ printf("resolve_and_check_subtype_set:\n");
+ unresolved_subtype_set_debug_dump(ref, stdout);
+ if (IS_CLASSREF(typeref))
+ class_classref_println(typeref.ref);
+ else
+ class_println(typeref.cls);
+#endif
+
+ setp = ref->subtyperefs;
+
+ /* an empty set of tests always succeeds */
+ if (!setp || !setp->any) {
+ return resolveSucceeded;
+ }
+
+ /* first resolve the type if necessary */
+ if (!resolve_classref_or_classinfo(refmethod,typeref,mode,false,true,&(typeref.cls)))
+ return resolveFailed; /* exception */
+ if (!typeref.cls)
+ return resolveDeferred; /* be lazy */
+
+ assert(typeref.cls->state & CLASS_LINKED);
+
+ /* iterate over the set members */
+
+ for (; setp->any; ++setp) {
+ checkresult = resolve_subtype_check(refmethod,*setp,typeref,mode,error);
+#if defined(RESOLVE_VERBOSE)
+ if (checkresult != resolveSucceeded)
+ printf("SUBTYPE CHECK FAILED!\n");
+#endif
+ if (checkresult != resolveSucceeded)
+ return checkresult;
+ }
+
+ /* check succeeds */
+ return resolveSucceeded;
+}
+#endif /* defined(ENABLE_VERIFIER) */
+
+/******************************************************************************/
+/* CLASS RESOLUTION */
+/******************************************************************************/
+
+/* resolve_class ***************************************************************
+
+ Resolve an unresolved class reference. The class is also linked.
+
+ IN:
+ ref..............struct containing the reference
+ mode.............mode of resolution:
+ resolveLazy...only resolve if it does not
+ require loading classes
+ resolveEager..load classes if necessary
+ checkaccess......if true, access rights to the class are checked
+
+ OUT:
+ *result..........set to the result of resolution, or to NULL if
+ the reference has not been resolved
+ In the case of an exception, *result is
+ guaranteed to be set to NULL.
+
+ RETURN VALUE:
+ true.............everything ok
+ (*result may still be NULL for resolveLazy)
+ false............an exception has been thrown
+
+*******************************************************************************/
+
+#ifdef ENABLE_VERIFIER
+bool resolve_class(unresolved_class *ref,
+ resolve_mode_t mode,
+ bool checkaccess,
+ classinfo **result)
+{
+ classinfo *cls;
+ resolve_result_t checkresult;
+
+ assert(ref);
+ assert(result);
+ assert(mode == resolveLazy || mode == resolveEager);
+
+ *result = NULL;
+
+#ifdef RESOLVE_VERBOSE
+ unresolved_class_debug_dump(ref,stdout);
+#endif
+
+ /* first we must resolve the class */
+ if (!resolve_classref(ref->referermethod,
+ ref->classref,mode,checkaccess,true,&cls))
+ {
+ /* the class reference could not be resolved */
+ return false; /* exception */
+ }
+ if (!cls)
+ return true; /* be lazy */
+
+ assert(cls);
+ assert((cls->state & CLASS_LOADED) && (cls->state & CLASS_LINKED));
+
+ /* now we check the subtype constraints */
+
+ checkresult = resolve_and_check_subtype_set(ref->referermethod,
+ &(ref->subtypeconstraints),
+ CLASSREF_OR_CLASSINFO(cls),
+ mode,
+ resolveLinkageError);
+ if (checkresult != resolveSucceeded)
+ return (bool) checkresult;
+
+ /* succeed */
+ *result = cls;
+ return true;
+}
+#endif /* ENABLE_VERIFIER */
+
+/* resolve_classref_eager ******************************************************
+
+ Resolve an unresolved class reference eagerly. The class is also linked and
+ access rights to the class are checked.
+
+ IN:
+ ref..............constant_classref to the class
+
+ RETURN VALUE:
+ classinfo * to the class, or
+ NULL if an exception has been thrown
+
+*******************************************************************************/
+
+classinfo * resolve_classref_eager(constant_classref *ref)
+{
+ classinfo *c;
+
+ if (!resolve_classref(NULL,ref,resolveEager,true,true,&c))
+ return NULL;
+
+ return c;
+}
+
+/* resolve_classref_eager_nonabstract ******************************************
+
+ Resolve an unresolved class reference eagerly. The class is also linked and
+ access rights to the class are checked. A check is performed that the class
+ is not abstract.
+
+ IN:
+ ref..............constant_classref to the class
+
+ RETURN VALUE:
+ classinfo * to the class, or
+ NULL if an exception has been thrown
+
+*******************************************************************************/
+
+classinfo * resolve_classref_eager_nonabstract(constant_classref *ref)
+{
+ classinfo *c;
+
+ if (!resolve_classref(NULL,ref,resolveEager,true,true,&c))
+ return NULL;
+
+ /* ensure that the class is not abstract */
+
+ if (c->flags & ACC_ABSTRACT) {
+ exceptions_throw_verifyerror(NULL,"creating instance of abstract class");
+ return NULL;
+ }
+
+ return c;
+}
+
+/* resolve_class_eager *********************************************************
+
+ Resolve an unresolved class reference eagerly. The class is also linked and
+ access rights to the class are checked.
+
+ IN:
+ ref..............struct containing the reference
+
+ RETURN VALUE:
+ classinfo * to the class, or
+ NULL if an exception has been thrown
+
+*******************************************************************************/
+
+#ifdef ENABLE_VERIFIER
+classinfo * resolve_class_eager(unresolved_class *ref)
+{
+ classinfo *c;
+
+ if (!resolve_class(ref,resolveEager,true,&c))
+ return NULL;
+
+ return c;
+}
+#endif /* ENABLE_VERIFIER */
+
+/* resolve_class_eager_no_access_check *****************************************
+
+ Resolve an unresolved class reference eagerly. The class is also linked.
+ Access rights are _not_ checked.
+
+ IN:
+ ref..............struct containing the reference
+
+ RETURN VALUE:
+ classinfo * to the class, or
+ NULL if an exception has been thrown
+
+*******************************************************************************/
+
+#ifdef ENABLE_VERIFIER
+classinfo * resolve_class_eager_no_access_check(unresolved_class *ref)
+{
+ classinfo *c;
+
+ if (!resolve_class(ref, resolveEager, false, &c))
+ return NULL;
+
+ return c;
+}
+#endif /* ENABLE_VERIFIER */
+
+/******************************************************************************/
+/* FIELD RESOLUTION */
+/******************************************************************************/
+
+/* resolve_field_verifier_checks *******************************************
+
+ Do the verifier checks necessary after field has been resolved.
+
+ IN:
+ refmethod........the method containing the reference
+ fieldref.........the field reference
+ container........the class where the field was found
+ fi...............the fieldinfo of the resolved field
+ instanceti.......instance typeinfo, if available
+ valueti..........value typeinfo, if available
+ isstatic.........true if this is a *STATIC* instruction
+ isput............true if this is a PUT* instruction
+
+ RETURN VALUE:
+ resolveSucceeded....everything ok
+ resolveDeferred.....tests could not be done, have been deferred
+ resolveFailed.......exception has been thrown
+
+*******************************************************************************/
+
+#if defined(ENABLE_VERIFIER)
+resolve_result_t resolve_field_verifier_checks(methodinfo *refmethod,
+ constant_FMIref *fieldref,
+ classinfo *container,
+ fieldinfo *fi,
+ typeinfo_t *instanceti,
+ typeinfo_t *valueti,
+ bool isstatic,
+ bool isput)
+{
+ classinfo *declarer;
+ classinfo *referer;
+ resolve_result_t result;
+ constant_classref *fieldtyperef;
+ char *msg;
+ s4 msglen;
+ utf *u;
+
+ assert(refmethod);
+ assert(fieldref);
+ assert(container);
+ assert(fi);
+
+ /* get the classinfos and the field type */
+
+ referer = refmethod->clazz;
+ assert(referer);
+
+ declarer = fi->clazz;
+ assert(declarer);
+ assert(referer->state & CLASS_LINKED);
+
+ fieldtyperef = fieldref->parseddesc.fd->classref;
+
+ /* check static */
+
+#if true != 1
+#error This code assumes that `true` is `1`. Otherwise, use the ternary operator below.
+#endif
+
+ if (((fi->flags & ACC_STATIC) != 0) != isstatic) {
+ /* a static field is accessed via an instance, or vice versa */
+ exceptions_throw_incompatibleclasschangeerror(declarer,
+ (fi->flags & ACC_STATIC)
+ ? "static field accessed via instance"
+ : "instance field accessed without instance");
+
+ return resolveFailed;
+ }
+
+ /* check access rights */
+
+ if (!access_is_accessible_member(referer,declarer,fi->flags)) {
+ msglen =
+ utf_bytes(declarer->name) +
+ utf_bytes(fi->name) +
+ utf_bytes(referer->name) +
+ 100;
+
+ msg = MNEW(char, msglen);
+
+ strcpy(msg, "field is not accessible (");
+ utf_cat_classname(msg, declarer->name);
+ strcat(msg, ".");
+ utf_cat(msg, fi->name);
+ strcat(msg, " from ");
+ utf_cat_classname(msg, referer->name);
+ strcat(msg, ")");
+
+ u = utf_new_char(msg);
+
+ MFREE(msg, char, msglen);
+
+ exceptions_throw_illegalaccessexception(u);
+
+ return resolveFailed; /* exception */
+ }
+
+ /* for non-static methods we have to check the constraints on the */
+ /* instance type */
+
+ if (instanceti) {
+ typeinfo_t *insttip;
+ typeinfo_t tinfo;
+
+ /* The instanceslot must contain a reference to a non-array type */
+
+ if (!TYPEINFO_IS_REFERENCE(*instanceti)) {
+ exceptions_throw_verifyerror(refmethod, "illegal instruction: field access on non-reference");
+ return resolveFailed;
+ }
+ if (TYPEINFO_IS_ARRAY(*instanceti)) {
+ exceptions_throw_verifyerror(refmethod, "illegal instruction: field access on array");
+ return resolveFailed;
+ }
+
+ if (isput && TYPEINFO_IS_NEWOBJECT(*instanceti))
+ {
+ /* The instruction writes a field in an uninitialized object. */
+ /* This is only allowed when a field of an uninitialized 'this' object is */
+ /* written inside an initialization method */
+
+ classinfo *initclass;
+ instruction *ins = (instruction *) TYPEINFO_NEWOBJECT_INSTRUCTION(*instanceti);
+
+ if (ins != NULL) {
+ exceptions_throw_verifyerror(refmethod, "accessing field of uninitialized object");
+ return resolveFailed;
+ }
+
+ /* XXX check that class of field == refmethod->clazz */
+ initclass = referer; /* XXX classrefs */
+ assert(initclass->state & CLASS_LINKED);
+
+ typeinfo_init_classinfo(&tinfo, initclass);
+ insttip = &tinfo;
+ }
+ else {
+ insttip = instanceti;
+ }
+
+ result = resolve_lazy_subtype_checks(refmethod,
+ insttip,
+ CLASSREF_OR_CLASSINFO(container),
+ resolveLinkageError);
+ if (result != resolveSucceeded)
+ return result;
+
+ /* check protected access */
+
+ if (((fi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer))
+ {
+ result = resolve_lazy_subtype_checks(refmethod,
+ instanceti,
+ CLASSREF_OR_CLASSINFO(referer),
+ resolveIllegalAccessError);
+ if (result != resolveSucceeded)
+ return result;
+ }
+
+ }
+
+ /* for PUT* instructions we have to check the constraints on the value type */
+
+ if (valueti) {
+ assert(fieldtyperef);
+
+ /* check subtype constraints */
+ result = resolve_lazy_subtype_checks(refmethod,
+ valueti,
+ CLASSREF_OR_CLASSINFO(fieldtyperef),
+ resolveLinkageError);
+
+ if (result != resolveSucceeded)
+ return result;
+ }
+
+ /* impose loading constraint on field type */
+
+ if (fi->type == TYPE_ADR) {
+ assert(fieldtyperef);
+ if (!classcache_add_constraint(declarer->classloader,
+ referer->classloader,
+ fieldtyperef->name))
+ return resolveFailed;
+ }
+
+ /* XXX impose loading constraint on instance? */
+
+ /* everything ok */
+ return resolveSucceeded;
+}
+#endif /* defined(ENABLE_VERIFIER) */
+
+/* resolve_field_lazy **********************************************************
+
+ Resolve an unresolved field reference lazily
+
+ NOTE: This function does NOT do any verification checks. In case of a
+ successful resolution, you must call resolve_field_verifier_checks
+ in order to perform the necessary checks!
+
+ IN:
+ refmethod........the referer method
+ fieldref.........the field reference
+
+ RETURN VALUE:
+ resolveSucceeded.....the reference has been resolved
+ resolveDeferred......the resolving could not be performed lazily
+ resolveFailed........resolving failed, an exception has been thrown.
+
+*******************************************************************************/
+
+resolve_result_t resolve_field_lazy(methodinfo *refmethod,
+ constant_FMIref *fieldref)
+{
+ classinfo *referer;
+ classinfo *container;
+ fieldinfo *fi;
+
+ assert(refmethod);
+
+ /* the class containing the reference */
+
+ referer = refmethod->clazz;
+ assert(referer);
+
+ /* check if the field itself is already resolved */
+
+ if (IS_FMIREF_RESOLVED(fieldref))
+ return resolveSucceeded;
+
+ /* first we must resolve the class containg the field */
+
+ /* XXX can/may lazyResolving trigger linking? */
+
+ if (!resolve_class_from_name(referer, refmethod,
+ fieldref->p.classref->name, resolveLazy, true, true, &container))
+ {
+ /* the class reference could not be resolved */
+ return resolveFailed; /* exception */
+ }
+ if (!container)
+ return resolveDeferred; /* be lazy */
+
+ assert(container->state & CLASS_LINKED);
+
+ /* now we must find the declaration of the field in `container`
+ * or one of its superclasses */
+
+ fi = class_resolvefield(container,
+ fieldref->name, fieldref->descriptor,
+ referer);
+ if (!fi) {
+ /* The field does not exist. But since we were called lazily, */
+ /* this error must not be reported now. (It will be reported */
+ /* if eager resolving of this field is ever tried.) */
+
+ exceptions_clear_exception();
+ return resolveDeferred; /* be lazy */
+ }
+
+ /* cache the result of the resolution */
+
+ fieldref->p.field = fi;
+
+ /* everything ok */
+ return resolveSucceeded;
+}
+
+/* resolve_field ***************************************************************
+
+ Resolve an unresolved field reference
+
+ IN:
+ ref..............struct containing the reference
+ mode.............mode of resolution:
+ resolveLazy...only resolve if it does not
+ require loading classes
+ resolveEager..load classes if necessary
+
+ OUT:
+ *result..........set to the result of resolution, or to NULL if
+ the reference has not been resolved
+ In the case of an exception, *result is
+ guaranteed to be set to NULL.
+
+ RETURN VALUE:
+ true.............everything ok
+ (*result may still be NULL for resolveLazy)
+ false............an exception has been thrown
+
+*******************************************************************************/
+
+bool resolve_field(unresolved_field *ref,
+ resolve_mode_t mode,
+ fieldinfo **result)
+{
+ classinfo *referer;
+ classinfo *container;
+ classinfo *declarer;
+ constant_classref *fieldtyperef;
+ fieldinfo *fi;
+ resolve_result_t checkresult;
+
+ assert(ref);
+ assert(result);
+ assert(mode == resolveLazy || mode == resolveEager);
+
+ *result = NULL;
+
+#ifdef RESOLVE_VERBOSE
+ unresolved_field_debug_dump(ref,stdout);
+#endif
+
+ /* the class containing the reference */
+
+ referer = ref->referermethod->clazz;
+ assert(referer);
+
+ /* check if the field itself is already resolved */
+ if (IS_FMIREF_RESOLVED(ref->fieldref)) {
+ fi = ref->fieldref->p.field;
+ container = fi->clazz;
+ goto resolved_the_field;
+ }
+
+ /* first we must resolve the class containg the field */
+ if (!resolve_class_from_name(referer,ref->referermethod,
+ ref->fieldref->p.classref->name,mode,true,true,&container))
+ {
+ /* the class reference could not be resolved */
+ return false; /* exception */
+ }
+ if (!container)
+ return true; /* be lazy */
+
+ assert(container);
+ assert(container->state & CLASS_LOADED);
+ assert(container->state & CLASS_LINKED);
+
+ /* now we must find the declaration of the field in `container`
+ * or one of its superclasses */
+
+#ifdef RESOLVE_VERBOSE
+ printf(" resolving field in class...\n");
+#endif
+
+ fi = class_resolvefield(container,
+ ref->fieldref->name,ref->fieldref->descriptor,
+ referer);
+ if (!fi) {
+ if (mode == resolveLazy) {
+ /* The field does not exist. But since we were called lazily, */
+ /* this error must not be reported now. (It will be reported */
+ /* if eager resolving of this field is ever tried.) */
+
+ exceptions_clear_exception();
+ return true; /* be lazy */
+ }
+
+ return false; /* exception */
+ }
+
+ /* cache the result of the resolution */
+ ref->fieldref->p.field = fi;
+
+resolved_the_field:
+
+#ifdef ENABLE_VERIFIER
+ /* Checking opt_verify is ok here, because the NULL iptr guarantees */
+ /* that no missing parts of an instruction will be accessed. */
+ if (opt_verify) {
+ checkresult = resolve_field_verifier_checks(
+ ref->referermethod,
+ ref->fieldref,
+ container,
+ fi,
+ NULL, /* instanceti, handled by constraints below */
+ NULL, /* valueti, handled by constraints below */
+ (ref->flags & RESOLVE_STATIC) != 0, /* isstatic */
+ (ref->flags & RESOLVE_PUTFIELD) != 0 /* isput */);
+
+ if (checkresult != resolveSucceeded)
+ return (bool) checkresult;
+
+ declarer = fi->clazz;
+ assert(declarer);
+ assert(declarer->state & CLASS_LOADED);
+ assert(declarer->state & CLASS_LINKED);
+
+ /* for non-static accesses we have to check the constraints on the */
+ /* instance type */
+
+ if (!(ref->flags & RESOLVE_STATIC)) {
+ checkresult = resolve_and_check_subtype_set(ref->referermethod,
+ &(ref->instancetypes),
+ CLASSREF_OR_CLASSINFO(container),
+ mode, resolveLinkageError);
+ if (checkresult != resolveSucceeded)
+ return (bool) checkresult;
+ }
+
+ fieldtyperef = ref->fieldref->parseddesc.fd->classref;
+
+ /* for PUT* instructions we have to check the constraints on the value type */
+ if (((ref->flags & RESOLVE_PUTFIELD) != 0) && fi->type == TYPE_ADR) {
+ assert(fieldtyperef);
+ if (!SUBTYPESET_IS_EMPTY(ref->valueconstraints)) {
+ /* check subtype constraints */
+ checkresult = resolve_and_check_subtype_set(ref->referermethod,
+ &(ref->valueconstraints),
+ CLASSREF_OR_CLASSINFO(fieldtyperef),
+ mode, resolveLinkageError);
+ if (checkresult != resolveSucceeded)
+ return (bool) checkresult;
+ }
+ }
+
+ /* check protected access */
+ if (((fi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer)) {
+ checkresult = resolve_and_check_subtype_set(ref->referermethod,
+ &(ref->instancetypes),
+ CLASSREF_OR_CLASSINFO(referer),
+ mode,
+ resolveIllegalAccessError);
+ if (checkresult != resolveSucceeded)
+ return (bool) checkresult;
+ }
+
+ }
+#endif /* ENABLE_VERIFIER */
+
+ /* succeed */
+ *result = fi;
+
+ return true;
+}
+
+/* resolve_field_eager *********************************************************
+
+ Resolve an unresolved field reference eagerly.
+
+ IN:
+ ref..............struct containing the reference
+
+ RETURN VALUE:
+ fieldinfo * to the field, or
+ NULL if an exception has been thrown
+
+*******************************************************************************/
+
+fieldinfo * resolve_field_eager(unresolved_field *ref)
+{
+ fieldinfo *fi;
+
+ if (!resolve_field(ref,resolveEager,&fi))
+ return NULL;
+
+ return fi;
+}
+
+/******************************************************************************/
+/* METHOD RESOLUTION */
+/******************************************************************************/
+
+/* resolve_method_invokespecial_lookup *****************************************
+
+ Do the special lookup for methods invoked by INVOKESPECIAL
+
+ IN:
+ refmethod........the method containing the reference
+ mi...............the methodinfo of the resolved method
+
+ RETURN VALUE:
+ a methodinfo *...the result of the lookup,
+ NULL.............an exception has been thrown
+
+*******************************************************************************/
+
+methodinfo * resolve_method_invokespecial_lookup(methodinfo *refmethod,
+ methodinfo *mi)
+{
+ classinfo *declarer;
+ classinfo *referer;
+
+ assert(refmethod);
+ assert(mi);
+
+ /* get referer and declarer classes */
+
+ referer = refmethod->clazz;
+ assert(referer);
+
+ declarer = mi->clazz;
+ assert(declarer);
+ assert(referer->state & CLASS_LINKED);
+
+ /* checks for INVOKESPECIAL: */
+ /* for <init> and methods of the current class we don't need any */
+ /* special checks. Otherwise we must verify that the called method */
+ /* belongs to a super class of the current class */
+
+ if ((referer != declarer) && (mi->name != utf_init)) {
+ /* check that declarer is a super class of the current class */
+
+ if (!class_issubclass(referer,declarer)) {
+ exceptions_throw_verifyerror(refmethod,
+ "INVOKESPECIAL calling non-super class method");
+ return NULL;
+ }
+
+ /* if the referer has ACC_SUPER set, we must do the special */
+ /* lookup starting with the direct super class of referer */
+
+ if ((referer->flags & ACC_SUPER) != 0) {
+ mi = class_resolvemethod(referer->super,
+ mi->name,
+ mi->descriptor);
+
+ if (mi == NULL) {
+ /* the spec calls for an AbstractMethodError in this case */
+
+ exceptions_throw_abstractmethoderror();
+
+ return NULL;
+ }
+ }
+ }
+
+ /* everything ok */
+ return mi;
+}
+
+/* resolve_method_verifier_checks ******************************************
+
+ Do the verifier checks necessary after a method has been resolved.
+
+ IN:
+ refmethod........the method containing the reference
+ methodref........the method reference
+ mi...............the methodinfo of the resolved method
+ invokestatic.....true if the method is invoked by INVOKESTATIC
+
+ RETURN VALUE:
+ resolveSucceeded....everything ok
+ resolveDeferred.....tests could not be done, have been deferred
+ resolveFailed.......exception has been thrown
+
+*******************************************************************************/
+
+#if defined(ENABLE_VERIFIER)
+resolve_result_t resolve_method_verifier_checks(methodinfo *refmethod,
+ constant_FMIref *methodref,
+ methodinfo *mi,
+ bool invokestatic)
+{
+ classinfo *declarer;
+ classinfo *referer;
+ char *msg;
+ s4 msglen;
+ utf *u;
+
+ assert(refmethod);
+ assert(methodref);
+ assert(mi);
+
+#ifdef RESOLVE_VERBOSE
+ printf("resolve_method_verifier_checks\n");
+ printf(" flags: %02x\n",mi->flags);
+#endif
+
+ /* get the classinfos and the method descriptor */
+
+ referer = refmethod->clazz;
+ assert(referer);
+
+ declarer = mi->clazz;
+ assert(declarer);
+
+ /* check static */
+
+ if (((mi->flags & ACC_STATIC) != 0) != (invokestatic != false)) {
+ /* a static method is accessed via an instance, or vice versa */
+ exceptions_throw_incompatibleclasschangeerror(declarer,
+ (mi->flags & ACC_STATIC)
+ ? "static method called via instance"
+ : "instance method called without instance");
+
+ return resolveFailed;
+ }
+
+ /* check access rights */
+
+ if (!access_is_accessible_member(referer,declarer,mi->flags)) {
+ /* XXX clean this up. this should be in exceptions.c */
+
+ msglen =
+ utf_bytes(declarer->name) +
+ utf_bytes(mi->name) +
+ utf_bytes(mi->descriptor) +
+ utf_bytes(referer->name) +
+ 100;
+
+ msg = MNEW(char, msglen);
+
+ strcpy(msg, "method is not accessible (");
+ utf_cat_classname(msg, declarer->name);
+ strcat(msg, ".");
+ utf_cat(msg, mi->name);
+ utf_cat(msg, mi->descriptor);
+ strcat(msg, " from ");
+ utf_cat_classname(msg, referer->name);
+ strcat(msg, ")");
+
+ u = utf_new_char(msg);
+
+ MFREE(msg, char, msglen);
+
+ exceptions_throw_illegalaccessexception(u);
+
+ return resolveFailed; /* exception */
+ }
+
+ /* everything ok */
+
+ return resolveSucceeded;
+}
+#endif /* defined(ENABLE_VERIFIER) */
+
+
+/* resolve_method_instance_type_checks *****************************************
+
+ Check the instance type of a method invocation.
+
+ IN:
+ refmethod........the method containing the reference
+ mi...............the methodinfo of the resolved method
+ instanceti.......typeinfo of the instance slot
+ invokespecial....true if the method is invoked by INVOKESPECIAL
+
+ RETURN VALUE:
+ resolveSucceeded....everything ok
+ resolveDeferred.....tests could not be done, have been deferred
+ resolveFailed.......exception has been thrown
+
+*******************************************************************************/
+
+#if defined(ENABLE_VERIFIER)
+resolve_result_t resolve_method_instance_type_checks(methodinfo *refmethod,
+ methodinfo *mi,
+ typeinfo_t *instanceti,
+ bool invokespecial)
+{
+ typeinfo_t tinfo;
+ typeinfo_t *tip;
+ resolve_result_t result;
+
+ if (invokespecial && TYPEINFO_IS_NEWOBJECT(*instanceti))
+ { /* XXX clean up */
+ instruction *ins = (instruction *) TYPEINFO_NEWOBJECT_INSTRUCTION(*instanceti);
+ classref_or_classinfo initclass = (ins) ? ins[-1].sx.val.c
+ : CLASSREF_OR_CLASSINFO(refmethod->clazz);
+ tip = &tinfo;
+ if (!typeinfo_init_class(tip, initclass))
+ return resolveFailed;
+ }
+ else {
+ tip = instanceti;
+ }
+
+ result = resolve_lazy_subtype_checks(refmethod,
+ tip,
+ CLASSREF_OR_CLASSINFO(mi->clazz),
+ resolveLinkageError);
+ if (result != resolveSucceeded)
+ return result;
+
+ /* check protected access */
+
+ /* XXX use other `declarer` than mi->clazz? */
+ if (((mi->flags & ACC_PROTECTED) != 0)
+ && !SAME_PACKAGE(mi->clazz, refmethod->clazz))
+ {
+ result = resolve_lazy_subtype_checks(refmethod,
+ tip,
+ CLASSREF_OR_CLASSINFO(refmethod->clazz),
+ resolveIllegalAccessError);
+ if (result != resolveSucceeded)
+ return result;
+ }
+
+ /* everything ok */
+
+ return resolveSucceeded;
+}
+#endif /* defined(ENABLE_VERIFIER) */
+
+
+/* resolve_method_param_type_checks ********************************************
+
+ Check non-instance parameter types of a method invocation.
+
+ IN:
+ jd...............jitdata of the method doing the call
+ refmethod........the method containing the reference
+ iptr.............the invoke instruction
+ mi...............the methodinfo of the resolved method
+ invokestatic.....true if the method is invoked by INVOKESTATIC
+
+ RETURN VALUE:
+ resolveSucceeded....everything ok
+ resolveDeferred.....tests could not be done, have been deferred
+ resolveFailed.......exception has been thrown
+
+*******************************************************************************/
+
+#if defined(ENABLE_VERIFIER)
+resolve_result_t resolve_method_param_type_checks(jitdata *jd,
+ methodinfo *refmethod,
+ instruction *iptr,
+ methodinfo *mi,
+ bool invokestatic)
+{
+ varinfo *param;
+ resolve_result_t result;
+ methoddesc *md;
+ typedesc *paramtypes;
+ s4 type;
+ s4 instancecount;
+ s4 i;
+
+ assert(jd);
+
+ instancecount = (invokestatic) ? 0 : 1;
+
+ /* check subtype constraints for TYPE_ADR parameters */
+
+ md = mi->parseddesc;
+ paramtypes = md->paramtypes;
+
+ for (i = md->paramcount-1-instancecount; i>=0; --i) {
+ param = VAR(iptr->sx.s23.s2.args[i+instancecount]);
+ type = md->paramtypes[i+instancecount].type;
+
+ assert(param);
+ assert(type == param->type);
+
+ if (type == TYPE_ADR) {
+ result = resolve_lazy_subtype_checks(refmethod,
+ &(param->typeinfo),
+ CLASSREF_OR_CLASSINFO(paramtypes[i+instancecount].classref),
+ resolveLinkageError);
+ if (result != resolveSucceeded)
+ return result;
+ }
+ }
+
+ /* everything ok */
+
+ return resolveSucceeded;
+}
+#endif /* defined(ENABLE_VERIFIER) */
+
+
+/* resolve_method_param_type_checks_stackbased *********************************
+
+ Check non-instance parameter types of a method invocation.
+
+ IN:
+ refmethod........the method containing the reference
+ mi...............the methodinfo of the resolved method
+ invokestatic.....true if the method is invoked by INVOKESTATIC
+ stack............TOS before the INVOKE instruction
+
+ RETURN VALUE:
+ resolveSucceeded....everything ok
+ resolveDeferred.....tests could not be done, have been deferred
+ resolveFailed.......exception has been thrown
+
+*******************************************************************************/
+
+#if defined(ENABLE_VERIFIER)
+resolve_result_t resolve_method_param_type_checks_stackbased(
+ methodinfo *refmethod,
+ methodinfo *mi,
+ bool invokestatic,
+ typedescriptor_t *stack)
+{
+ typedescriptor_t *param;
+ resolve_result_t result;
+ methoddesc *md;
+ typedesc *paramtypes;
+ s4 type;
+ s4 instancecount;
+ s4 i;
+
+ instancecount = (invokestatic) ? 0 : 1;
+
+ /* check subtype constraints for TYPE_ADR parameters */
+
+ md = mi->parseddesc;
+ paramtypes = md->paramtypes;
+
+ param = stack - (md->paramslots - 1 - instancecount);
+
+ for (i = instancecount; i < md->paramcount; ++i) {
+ type = md->paramtypes[i].type;
+
+ assert(type == param->type);
+
+ if (type == TYPE_ADR) {
+ result = resolve_lazy_subtype_checks(refmethod,
+ &(param->typeinfo),
+ CLASSREF_OR_CLASSINFO(paramtypes[i].classref),
+ resolveLinkageError);
+ if (result != resolveSucceeded)
+ return result;
+ }
+
+ param += (IS_2_WORD_TYPE(type)) ? 2 : 1;
+ }
+
+ /* everything ok */
+
+ return resolveSucceeded;
+}
+#endif /* defined(ENABLE_VERIFIER) */
+
+
+/* resolve_method_loading_constraints ******************************************
+
+ Impose loading constraints on the parameters and return type of the
+ given method.
+
+ IN:
+ referer..........the class refering to the method
+ mi...............the method
+
+ RETURN VALUE:
+ true................everything ok
+ false...............an exception has been thrown
+
+*******************************************************************************/
+
+#if defined(ENABLE_VERIFIER)
+bool resolve_method_loading_constraints(classinfo *referer,
+ methodinfo *mi)
+{
+ methoddesc *md;
+ typedesc *paramtypes;
+ utf *name;
+ s4 i;
+ s4 instancecount;
+
+ /* impose loading constraints on parameters (including instance) */
+
+ md = mi->parseddesc;
+ paramtypes = md->paramtypes;
+ instancecount = (mi->flags & ACC_STATIC) / ACC_STATIC;
+
+ for (i = 0; i < md->paramcount; i++) {
+ if (i < instancecount || paramtypes[i].type == TYPE_ADR) {
+ if (i < instancecount) {
+ /* The type of the 'this' pointer is the class containing */
+ /* the method definition. Since container is the same as, */
+ /* or a subclass of declarer, we also constrain declarer */
+ /* by transitivity of loading constraints. */
+ name = mi->clazz->name;
+ }
+ else {
+ name = paramtypes[i].classref->name;
+ }
+
+ /* The caller (referer) and the callee (container) must agree */
+ /* on the types of the parameters. */
+ if (!classcache_add_constraint(referer->classloader,
+ mi->clazz->classloader, name))
+ return false; /* exception */
+ }
+ }
+
+ /* impose loading constraint onto return type */
+
+ if (md->returntype.type == TYPE_ADR) {
+ /* The caller (referer) and the callee (container) must agree */
+ /* on the return type. */
+ if (!classcache_add_constraint(referer->classloader,
+ mi->clazz->classloader,
+ md->returntype.classref->name))
+ return false; /* exception */
+ }
+
+ /* everything ok */
+
+ return true;
+}
+#endif /* defined(ENABLE_VERIFIER) */
+
+
+/* resolve_method_lazy *********************************************************
+
+ Resolve an unresolved method reference lazily
+
+ NOTE: This function does NOT do any verification checks. In case of a
+ successful resolution, you must call resolve_method_verifier_checks
+ in order to perform the necessary checks!
+
+ IN:
+ refmethod........the referer method
+ methodref........the method reference
+ invokespecial....true if this is an INVOKESPECIAL instruction
+
+ RETURN VALUE:
+ resolveSucceeded.....the reference has been resolved
+ resolveDeferred......the resolving could not be performed lazily
+ resolveFailed........resolving failed, an exception has been thrown.
+
+*******************************************************************************/
+
+resolve_result_t resolve_method_lazy(methodinfo *refmethod,
+ constant_FMIref *methodref,
+ bool invokespecial)
+{
+ classinfo *referer;
+ classinfo *container;
+ methodinfo *mi;
+
+ assert(refmethod);
+
+#ifdef RESOLVE_VERBOSE
+ printf("resolve_method_lazy\n");
+#endif
+
+ /* the class containing the reference */
+
+ referer = refmethod->clazz;
+ assert(referer);
+
+ /* check if the method itself is already resolved */
+
+ if (IS_FMIREF_RESOLVED(methodref))
+ return resolveSucceeded;
+
+ /* first we must resolve the class containg the method */
+
+ if (!resolve_class_from_name(referer, refmethod,
+ methodref->p.classref->name, resolveLazy, true, true, &container))
+ {
+ /* the class reference could not be resolved */
+ return resolveFailed; /* exception */
+ }
+ if (!container)
+ return resolveDeferred; /* be lazy */
+
+ assert(container->state & CLASS_LINKED);
+
+ /* now we must find the declaration of the method in `container`
+ * or one of its superclasses */
+
+ if (container->flags & ACC_INTERFACE) {
+ mi = class_resolveinterfacemethod(container,
+ methodref->name,
+ methodref->descriptor,
+ referer, true);
+
+ } else {
+ mi = class_resolveclassmethod(container,
+ methodref->name,
+ methodref->descriptor,
+ referer, true);
+ }
+
+ if (!mi) {
+ /* The method does not exist. But since we were called lazily, */
+ /* this error must not be reported now. (It will be reported */
+ /* if eager resolving of this method is ever tried.) */
+
+ exceptions_clear_exception();
+ return resolveDeferred; /* be lazy */
+ }
+
+ if (invokespecial) {
+ mi = resolve_method_invokespecial_lookup(refmethod, mi);
+ if (!mi)
+ return resolveFailed; /* exception */
+ }
+
+ /* have the method params already been parsed? no, do it. */
+
+ if (!mi->parseddesc->params)
+ if (!descriptor_params_from_paramtypes(mi->parseddesc, mi->flags))
+ return resolveFailed;
+
+ /* cache the result of the resolution */
+
+ methodref->p.method = mi;
+
+ /* succeed */
+
+ return resolveSucceeded;
+}
+
+/* resolve_method **************************************************************
+
+ Resolve an unresolved method reference
+
+ IN:
+ ref..............struct containing the reference
+ mode.............mode of resolution:
+ resolveLazy...only resolve if it does not
+ require loading classes
+ resolveEager..load classes if necessary
+
+ OUT:
+ *result..........set to the result of resolution, or to NULL if
+ the reference has not been resolved
+ In the case of an exception, *result is
+ guaranteed to be set to NULL.
+
+ RETURN VALUE:
+ true.............everything ok
+ (*result may still be NULL for resolveLazy)
+ false............an exception has been thrown
+
+*******************************************************************************/
+
+bool resolve_method(unresolved_method *ref, resolve_mode_t mode, methodinfo **result)
+{
+ classinfo *referer;
+ classinfo *container;
+ classinfo *declarer;
+ methodinfo *mi;
+ typedesc *paramtypes;
+ int instancecount;
+ int i;
+ resolve_result_t checkresult;
+
+ assert(ref);
+ assert(result);
+ assert(mode == resolveLazy || mode == resolveEager);
+
+#ifdef RESOLVE_VERBOSE
+ unresolved_method_debug_dump(ref,stdout);
+#endif
+
+ *result = NULL;
+
+ /* the class containing the reference */
+
+ referer = ref->referermethod->clazz;
+ assert(referer);
+
+ /* check if the method itself is already resolved */
+
+ if (IS_FMIREF_RESOLVED(ref->methodref)) {
+ mi = ref->methodref->p.method;
+ container = mi->clazz;
+ goto resolved_the_method;
+ }
+
+ /* first we must resolve the class containing the method */
+
+ if (!resolve_class_from_name(referer,ref->referermethod,
+ ref->methodref->p.classref->name,mode,true,true,&container))
+ {
+ /* the class reference could not be resolved */
+ return false; /* exception */
+ }
+ if (!container)
+ return true; /* be lazy */
+
+ assert(container);
+ assert(container->state & CLASS_LINKED);
+
+ /* now we must find the declaration of the method in `container`
+ * or one of its superclasses */
+
+ if (container->flags & ACC_INTERFACE) {
+ mi = class_resolveinterfacemethod(container,
+ ref->methodref->name,
+ ref->methodref->descriptor,
+ referer, true);
+
+ } else {
+ mi = class_resolveclassmethod(container,
+ ref->methodref->name,
+ ref->methodref->descriptor,
+ referer, true);
+ }
+
+ if (!mi) {
+ if (mode == resolveLazy) {
+ /* The method does not exist. But since we were called lazily, */
+ /* this error must not be reported now. (It will be reported */
+ /* if eager resolving of this method is ever tried.) */
+
+ exceptions_clear_exception();
+ return true; /* be lazy */
+ }
+
+ return false; /* exception */ /* XXX set exceptionptr? */
+ }
+
+ /* { the method reference has been resolved } */
+
+ if (ref->flags & RESOLVE_SPECIAL) {
+ mi = resolve_method_invokespecial_lookup(ref->referermethod,mi);
+ if (!mi)
+ return false; /* exception */
+ }
+
+ /* have the method params already been parsed? no, do it. */
+
+ if (!mi->parseddesc->params)
+ if (!descriptor_params_from_paramtypes(mi->parseddesc, mi->flags))
+ return false;
+
+ /* cache the resolution */
+
+ ref->methodref->p.method = mi;
+
+resolved_the_method:
+
+#ifdef ENABLE_VERIFIER
+ if (opt_verify) {
+
+ checkresult = resolve_method_verifier_checks(
+ ref->referermethod,
+ ref->methodref,
+ mi,
+ (ref->flags & RESOLVE_STATIC));
+
+ if (checkresult != resolveSucceeded)
+ return (bool) checkresult;
+
+ /* impose loading constraints on params and return type */
+
+ if (!resolve_method_loading_constraints(referer, mi))
+ return false;
+
+ declarer = mi->clazz;
+ assert(declarer);
+ assert(referer->state & CLASS_LINKED);
+
+ /* for non-static methods we have to check the constraints on the */
+ /* instance type */
+
+ if (!(ref->flags & RESOLVE_STATIC)) {
+ checkresult = resolve_and_check_subtype_set(ref->referermethod,
+ &(ref->instancetypes),
+ CLASSREF_OR_CLASSINFO(container),
+ mode,
+ resolveLinkageError);
+ if (checkresult != resolveSucceeded)
+ return (bool) checkresult;
+ instancecount = 1;
+ }
+ else {
+ instancecount = 0;
+ }
+
+ /* check subtype constraints for TYPE_ADR parameters */
+
+ assert(mi->parseddesc->paramcount == ref->methodref->parseddesc.md->paramcount);
+ paramtypes = mi->parseddesc->paramtypes;
+
+ for (i = 0; i < mi->parseddesc->paramcount-instancecount; i++) {
+ if (paramtypes[i+instancecount].type == TYPE_ADR) {
+ if (ref->paramconstraints) {
+ checkresult = resolve_and_check_subtype_set(ref->referermethod,
+ ref->paramconstraints + i,
+ CLASSREF_OR_CLASSINFO(paramtypes[i+instancecount].classref),
+ mode,
+ resolveLinkageError);
+ if (checkresult != resolveSucceeded)
+ return (bool) checkresult;
+ }
+ }
+ }
+
+ /* check protected access */
+
+ if (((mi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer))
+ {
+ checkresult = resolve_and_check_subtype_set(ref->referermethod,
+ &(ref->instancetypes),
+ CLASSREF_OR_CLASSINFO(referer),
+ mode,
+ resolveIllegalAccessError);
+ if (checkresult != resolveSucceeded)
+ return (bool) checkresult;
+ }
+ }
+#endif /* ENABLE_VERIFIER */
+
+ /* succeed */
+ *result = mi;
+ return true;
+}
+
+/* resolve_method_eager ********************************************************
+
+ Resolve an unresolved method reference eagerly.
+
+ IN:
+ ref..............struct containing the reference
+
+ RETURN VALUE:
+ methodinfo * to the method, or
+ NULL if an exception has been thrown
+
+*******************************************************************************/
+
+methodinfo * resolve_method_eager(unresolved_method *ref)
+{
+ methodinfo *mi;
+
+ if (!resolve_method(ref,resolveEager,&mi))
+ return NULL;
+
+ return mi;
+}
+
+/******************************************************************************/
+/* CREATING THE DATA STRUCTURES */
+/******************************************************************************/
+
+#ifdef ENABLE_VERIFIER
+static bool unresolved_subtype_set_from_typeinfo(classinfo *referer,
+ methodinfo *refmethod,
+ unresolved_subtype_set *stset,
+ typeinfo_t *tinfo,
+ utf *declaredclassname)
+{
+ int count;
+ int i;
+
+ assert(stset);
+ assert(tinfo);
+
+#ifdef RESOLVE_VERBOSE
+ printf("unresolved_subtype_set_from_typeinfo\n");
+#ifdef TYPEINFO_DEBUG
+ typeinfo_print(stdout,tinfo,4);
+#endif
+ printf(" declared classname:");utf_fprint_printable_ascii(stdout,declaredclassname);
+ printf("\n");
+#endif
+
+ if (TYPEINFO_IS_PRIMITIVE(*tinfo)) {
+ exceptions_throw_verifyerror(refmethod,
+ "Invalid use of returnAddress");
+ return false;
+ }
+
+ if (TYPEINFO_IS_NEWOBJECT(*tinfo)) {
+ exceptions_throw_verifyerror(refmethod,
+ "Invalid use of uninitialized object");
+ return false;
+ }
+
+ /* the nulltype is always assignable */
+ if (TYPEINFO_IS_NULLTYPE(*tinfo))
+ goto empty_set;
+
+ /* every type is assignable to (BOOTSTRAP)java.lang.Object */
+ if (declaredclassname == utf_java_lang_Object
+ && referer->classloader == NULL) /* XXX do loading constraints make the second check obsolete? */
+ {
+ goto empty_set;
+ }
+
+ if (tinfo->merged) {
+ count = tinfo->merged->count;
+ stset->subtyperefs = MNEW(classref_or_classinfo,count + 1);
+ for (i=0; i<count; ++i) {
+ classref_or_classinfo c = tinfo->merged->list[i];
+ if (tinfo->dimension > 0) {
+ /* a merge of array types */
+ /* the merged list contains the possible _element_ types, */
+ /* so we have to create array types with these elements. */
+ if (IS_CLASSREF(c)) {
+ c.ref = class_get_classref_multiarray_of(tinfo->dimension,c.ref);
+ }
+ else {
+ c.cls = class_multiarray_of(tinfo->dimension,c.cls,false);
+ }
+ }
+ stset->subtyperefs[i] = c;
+ }
+ stset->subtyperefs[count].any = NULL; /* terminate */
+ }
+ else {
+ if ((IS_CLASSREF(tinfo->typeclass)
+ ? tinfo->typeclass.ref->name
+ : tinfo->typeclass.cls->name) == declaredclassname)
+ {
+ /* the class names are the same */
+ /* equality is guaranteed by the loading constraints */
+ goto empty_set;
+ }
+ else {
+ stset->subtyperefs = MNEW(classref_or_classinfo,1 + 1);
+ stset->subtyperefs[0] = tinfo->typeclass;
+ stset->subtyperefs[1].any = NULL; /* terminate */
+ }
+ }
+
+ return true;
+
+empty_set:
+ UNRESOLVED_SUBTYPE_SET_EMTPY(*stset);
+ return true;
+}
+#endif /* ENABLE_VERIFIER */
+
+/* create_unresolved_class *****************************************************
+
+ Create an unresolved_class struct for the given class reference
+
+ IN:
+ refmethod........the method triggering the resolution (if any)
+ classref.........the class reference
+ valuetype........value type to check against the resolved class
+ may be NULL, if no typeinfo is available
+
+ RETURN VALUE:
+ a pointer to a new unresolved_class struct, or
+ NULL if an exception has been thrown
+
+*******************************************************************************/
+
+#ifdef ENABLE_VERIFIER
+unresolved_class * create_unresolved_class(methodinfo *refmethod,
+ constant_classref *classref,
+ typeinfo_t *valuetype)
+{
+ unresolved_class *ref;
+
+#ifdef RESOLVE_VERBOSE
+ printf("create_unresolved_class\n");
+ printf(" referer: ");utf_fprint_printable_ascii(stdout,classref->referer->name);fputc('\n',stdout);
+ if (refmethod) {
+ printf(" rmethod: ");utf_fprint_printable_ascii(stdout,refmethod->name);fputc('\n',stdout);
+ printf(" rmdesc : ");utf_fprint_printable_ascii(stdout,refmethod->descriptor);fputc('\n',stdout);
+ }
+ printf(" name : ");utf_fprint_printable_ascii(stdout,classref->name);fputc('\n',stdout);
+#endif
+
+ ref = NEW(unresolved_class);
+ ref->classref = classref;
+ ref->referermethod = refmethod;
+
+ if (valuetype) {
+ if (!unresolved_subtype_set_from_typeinfo(classref->referer,refmethod,
+ &(ref->subtypeconstraints),valuetype,classref->name))
+ return NULL;
+ }
+ else {
+ UNRESOLVED_SUBTYPE_SET_EMTPY(ref->subtypeconstraints);
+ }
+
+ return ref;
+}
+#endif /* ENABLE_VERIFIER */
+
+/* resolve_create_unresolved_field *********************************************
+
+ Create an unresolved_field struct for the given field access instruction
+
+ IN:
+ referer..........the class containing the reference
+ refmethod........the method triggering the resolution (if any)
+ iptr.............the {GET,PUT}{FIELD,STATIC}{,CONST} instruction
+
+ RETURN VALUE:
+ a pointer to a new unresolved_field struct, or
+ NULL if an exception has been thrown
+
+*******************************************************************************/
+
+unresolved_field * resolve_create_unresolved_field(classinfo *referer,
+ methodinfo *refmethod,
+ instruction *iptr)
+{
+ unresolved_field *ref;
+ constant_FMIref *fieldref = NULL;
+
+#ifdef RESOLVE_VERBOSE
+ printf("create_unresolved_field\n");
+ printf(" referer: ");utf_fprint_printable_ascii(stdout,referer->name);fputc('\n',stdout);
+ printf(" rmethod: ");utf_fprint_printable_ascii(stdout,refmethod->name);fputc('\n',stdout);
+ printf(" rmdesc : ");utf_fprint_printable_ascii(stdout,refmethod->descriptor);fputc('\n',stdout);
+#endif
+
+ ref = NEW(unresolved_field);
+ ref->flags = 0;
+ ref->referermethod = refmethod;
+ UNRESOLVED_SUBTYPE_SET_EMTPY(ref->valueconstraints);
+
+ switch (iptr->opc) {
+ case ICMD_PUTFIELD:
+ ref->flags |= RESOLVE_PUTFIELD;
+ break;
+
+ case ICMD_PUTFIELDCONST:
+ ref->flags |= RESOLVE_PUTFIELD;
+ break;
+
+ case ICMD_PUTSTATIC:
+ ref->flags |= RESOLVE_PUTFIELD | RESOLVE_STATIC;
+ break;
+
+ case ICMD_PUTSTATICCONST:
+ ref->flags |= RESOLVE_PUTFIELD | RESOLVE_STATIC;
+ break;
+
+ case ICMD_GETFIELD:
+ break;
+
+ case ICMD_GETSTATIC:
+ ref->flags |= RESOLVE_STATIC;
+ break;
+
+#if !defined(NDEBUG)
+ default:
+ assert(false);
+#endif
+ }
+
+ fieldref = iptr->sx.s23.s3.fmiref;
+
+ assert(fieldref);
+
+#ifdef RESOLVE_VERBOSE
+/* printf(" class : ");utf_fprint_printable_ascii(stdout,fieldref->p.classref->name);fputc('\n',stdout);*/
+ printf(" name : ");utf_fprint_printable_ascii(stdout,fieldref->name);fputc('\n',stdout);
+ printf(" desc : ");utf_fprint_printable_ascii(stdout,fieldref->descriptor);fputc('\n',stdout);
+ printf(" type : ");descriptor_debug_print_typedesc(stdout,fieldref->parseddesc.fd);
+ fputc('\n',stdout);
+#endif
+
+ ref->fieldref = fieldref;
+
+ return ref;
+}
+
+/* resolve_constrain_unresolved_field ******************************************
+
+ Record subtype constraints for a field access.
+
+ IN:
+ ref..............the unresolved_field structure of the access
+ referer..........the class containing the reference
+ refmethod........the method triggering the resolution (if any)
+ instanceti.......instance typeinfo, if available
+ valueti..........value typeinfo, if available
+
+ RETURN VALUE:
+ true.............everything ok
+ false............an exception has been thrown
+
+*******************************************************************************/
+
+#if defined(ENABLE_VERIFIER)
+bool resolve_constrain_unresolved_field(unresolved_field *ref,
+ classinfo *referer,
+ methodinfo *refmethod,
+ typeinfo_t *instanceti,
+ typeinfo_t *valueti)
+{
+ constant_FMIref *fieldref;
+ int type;
+ typeinfo_t tinfo;
+ typedesc *fd;
+
+ assert(ref);
+
+ fieldref = ref->fieldref;
+ assert(fieldref);
+
+#ifdef RESOLVE_VERBOSE
+ printf("constrain_unresolved_field\n");
+ printf(" referer: ");utf_fprint_printable_ascii(stdout,referer->name);fputc('\n',stdout);
+ printf(" rmethod: ");utf_fprint_printable_ascii(stdout,refmethod->name);fputc('\n',stdout);
+ printf(" rmdesc : ");utf_fprint_printable_ascii(stdout,refmethod->descriptor);fputc('\n',stdout);
+/* printf(" class : ");utf_fprint_printable_ascii(stdout,fieldref->p.classref->name);fputc('\n',stdout); */
+ printf(" name : ");utf_fprint_printable_ascii(stdout,fieldref->name);fputc('\n',stdout);
+ printf(" desc : ");utf_fprint_printable_ascii(stdout,fieldref->descriptor);fputc('\n',stdout);
+ printf(" type : ");descriptor_debug_print_typedesc(stdout,fieldref->parseddesc.fd);
+ fputc('\n',stdout);
+#endif
+
+ assert(instanceti || ((ref->flags & RESOLVE_STATIC) != 0));
+ fd = fieldref->parseddesc.fd;
+ assert(fd);
+
+ /* record subtype constraints for the instance type, if any */
+ if (instanceti) {
+ typeinfo_t *insttip;
+
+ /* The instanceslot must contain a reference to a non-array type */
+ if (!TYPEINFO_IS_REFERENCE(*instanceti)) {
+ exceptions_throw_verifyerror(refmethod,
+ "illegal instruction: field access on non-reference");
+ return false;
+ }
+ if (TYPEINFO_IS_ARRAY(*instanceti)) {
+ exceptions_throw_verifyerror(refmethod,
+ "illegal instruction: field access on array");
+ return false;
+ }
+
+ if (((ref->flags & RESOLVE_PUTFIELD) != 0) &&
+ TYPEINFO_IS_NEWOBJECT(*instanceti))
+ {
+ /* The instruction writes a field in an uninitialized object. */
+ /* This is only allowed when a field of an uninitialized 'this' object is */
+ /* written inside an initialization method */
+
+ classinfo *initclass;
+ instruction *ins = (instruction *) TYPEINFO_NEWOBJECT_INSTRUCTION(*instanceti);
+
+ if (ins != NULL) {
+ exceptions_throw_verifyerror(refmethod,
+ "accessing field of uninitialized object");
+ return false;
+ }
+ /* XXX check that class of field == refmethod->clazz */
+ initclass = refmethod->clazz; /* XXX classrefs */
+ assert(initclass->state & CLASS_LOADED);
+ assert(initclass->state & CLASS_LINKED);
+
+ typeinfo_init_classinfo(&tinfo, initclass);
+ insttip = &tinfo;
+ }
+ else {
+ insttip = instanceti;
+ }
+ if (!unresolved_subtype_set_from_typeinfo(referer, refmethod,
+ &(ref->instancetypes), insttip,
+ FIELDREF_CLASSNAME(fieldref)))
+ return false;
+ }
+ else {
+ UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
+ }
+
+ /* record subtype constraints for the value type, if any */
+ type = fd->type;
+ if (type == TYPE_ADR && ((ref->flags & RESOLVE_PUTFIELD) != 0)) {
+ assert(valueti);
+ if (!unresolved_subtype_set_from_typeinfo(referer, refmethod,
+ &(ref->valueconstraints), valueti,
+ fieldref->parseddesc.fd->classref->name))
+ return false;
+ }
+ else {
+ UNRESOLVED_SUBTYPE_SET_EMTPY(ref->valueconstraints);
+ }
+
+ return true;
+}
+#endif /* ENABLE_VERIFIER */
+
+/* resolve_create_unresolved_method ********************************************
+
+ Create an unresolved_method struct for the given method invocation
+
+ IN:
+ referer..........the class containing the reference
+ refmethod........the method triggering the resolution (if any)
+ iptr.............the INVOKE* instruction
+
+ RETURN VALUE:
+ a pointer to a new unresolved_method struct, or
+ NULL if an exception has been thrown
+
+*******************************************************************************/
+
+unresolved_method * resolve_create_unresolved_method(classinfo *referer,
+ methodinfo *refmethod,
+ constant_FMIref *methodref,
+ bool invokestatic,
+ bool invokespecial)
+{
+ unresolved_method *ref;
+
+ assert(methodref);
+
+#ifdef RESOLVE_VERBOSE
+ printf("create_unresolved_method\n");
+ printf(" referer: ");utf_fprint_printable_ascii(stdout,referer->name);fputc('\n',stdout);
+ printf(" rmethod: ");utf_fprint_printable_ascii(stdout,refmethod->name);fputc('\n',stdout);
+ printf(" rmdesc : ");utf_fprint_printable_ascii(stdout,refmethod->descriptor);fputc('\n',stdout);
+ printf(" name : ");utf_fprint_printable_ascii(stdout,methodref->name);fputc('\n',stdout);
+ printf(" desc : ");utf_fprint_printable_ascii(stdout,methodref->descriptor);fputc('\n',stdout);
+#endif
+
+ /* allocate params if necessary */
+ if (!methodref->parseddesc.md->params)
+ if (!descriptor_params_from_paramtypes(methodref->parseddesc.md,
+ (invokestatic) ? ACC_STATIC : ACC_NONE))
+ return NULL;
+
+ /* create the data structure */
+ ref = NEW(unresolved_method);
+ ref->flags = ((invokestatic) ? RESOLVE_STATIC : 0)
+ | ((invokespecial) ? RESOLVE_SPECIAL : 0);
+ ref->referermethod = refmethod;
+ ref->methodref = methodref;
+ ref->paramconstraints = NULL;
+ UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
+
+ return ref;
+}
+
+
+/* resolve_constrain_unresolved_method_instance ********************************
+
+ Record subtype constraints for the instance argument of a method call.
+
+ IN:
+ ref..............the unresolved_method structure of the call
+ referer..........the class containing the reference
+ refmethod........the method triggering the resolution (if any)
+ iptr.............the INVOKE* instruction
+
+ RETURN VALUE:
+ true.............everything ok
+ false............an exception has been thrown
+
+*******************************************************************************/
+
+#if defined(ENABLE_VERIFIER)
+bool resolve_constrain_unresolved_method_instance(unresolved_method *ref,
+ methodinfo *refmethod,
+ typeinfo_t *instanceti,
+ bool invokespecial)
+{
+ constant_FMIref *methodref;
+ constant_classref *instanceref;
+ typeinfo_t tinfo;
+ typeinfo_t *tip;
+
+ assert(ref);
+ methodref = ref->methodref;
+ assert(methodref);
+
+ /* XXX clean this up */
+ instanceref = IS_FMIREF_RESOLVED(methodref)
+ ? class_get_self_classref(methodref->p.method->clazz)
+ : methodref->p.classref;
+
+#ifdef RESOLVE_VERBOSE
+ printf("resolve_constrain_unresolved_method_instance\n");
+ printf(" rmethod: "); method_println(refmethod);
+ printf(" mref : "); method_methodref_println(methodref);
+#endif
+
+ /* record subtype constraints for the instance type, if any */
+
+ if (invokespecial && TYPEINFO_IS_NEWOBJECT(*instanceti))
+ { /* XXX clean up */
+ instruction *ins = (instruction *) TYPEINFO_NEWOBJECT_INSTRUCTION(*instanceti);
+ classref_or_classinfo initclass = (ins) ? ins[-1].sx.val.c
+ : CLASSREF_OR_CLASSINFO(refmethod->clazz);
+ tip = &tinfo;
+ if (!typeinfo_init_class(tip, initclass))
+ return false;
+ }
+ else {
+ tip = instanceti;
+ }
+
+ if (!unresolved_subtype_set_from_typeinfo(refmethod->clazz, refmethod,
+ &(ref->instancetypes),tip,instanceref->name))
+ return false;
+
+ return true;
+}
+#endif /* defined(ENABLE_VERIFIER) */
+
+
+/* resolve_constrain_unresolved_method_params *********************************
+
+ Record subtype constraints for the non-instance arguments of a method call.
+
+ IN:
+ jd...............current jitdata (for looking up variables)
+ ref..............the unresolved_method structure of the call
+ refmethod........the method triggering the resolution (if any)
+ iptr.............the INVOKE* instruction
+
+ RETURN VALUE:
+ true.............everything ok
+ false............an exception has been thrown
+
+*******************************************************************************/
+
+#if defined(ENABLE_VERIFIER)
+bool resolve_constrain_unresolved_method_params(jitdata *jd,
+ unresolved_method *ref,
+ methodinfo *refmethod,
+ instruction *iptr)
+{
+ constant_FMIref *methodref;
+ varinfo *param;
+ methoddesc *md;
+ int i,j;
+ int type;
+ int instancecount;
+
+ assert(ref);
+ methodref = ref->methodref;
+ assert(methodref);
+ md = methodref->parseddesc.md;
+ assert(md);
+ assert(md->params != NULL);
+
+#ifdef RESOLVE_VERBOSE
+ printf("resolve_constrain_unresolved_method_params\n");
+ printf(" rmethod: "); method_println(refmethod);
+ printf(" mref : "); method_methodref_println(methodref);
+#endif
+
+ instancecount = (ref->flags & RESOLVE_STATIC) ? 0 : 1;
+
+ /* record subtype constraints for the parameter types, if any */
+
+ for (i=md->paramcount-1-instancecount; i>=0; --i) {
+ param = VAR(iptr->sx.s23.s2.args[i+instancecount]);
+ type = md->paramtypes[i+instancecount].type;
+
+ assert(param);
+ assert(type == param->type);
+
+ if (type == TYPE_ADR) {
+ if (!ref->paramconstraints) {
+ ref->paramconstraints = MNEW(unresolved_subtype_set,md->paramcount);
+ for (j=md->paramcount-1-instancecount; j>i; --j)
+ UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[j]);
+ }
+ assert(ref->paramconstraints);
+ if (!unresolved_subtype_set_from_typeinfo(refmethod->clazz, refmethod,
+ ref->paramconstraints + i,&(param->typeinfo),
+ md->paramtypes[i+instancecount].classref->name))
+ return false;
+ }
+ else {
+ if (ref->paramconstraints)
+ UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[i]);
+ }
+ }
+
+ return true;
+}
+#endif /* ENABLE_VERIFIER */
+
+
+/* resolve_constrain_unresolved_method_params_stackbased ***********************
+
+ Record subtype constraints for the non-instance arguments of a method call.
+
+ IN:
+ ref..............the unresolved_method structure of the call
+ refmethod........the method triggering the resolution (if any)
+ stack............TOS before the INVOKE instruction
+
+ RETURN VALUE:
+ true.............everything ok
+ false............an exception has been thrown
+
+*******************************************************************************/
+
+#if defined(ENABLE_VERIFIER)
+bool resolve_constrain_unresolved_method_params_stackbased(
+ unresolved_method *ref,
+ methodinfo *refmethod,
+ typedescriptor_t *stack)
+{
+ constant_FMIref *methodref;
+ typedescriptor_t *param;
+ methoddesc *md;
+ int i,j;
+ int type;
+ int instancecount;
+
+ assert(ref);
+ methodref = ref->methodref;
+ assert(methodref);
+ md = methodref->parseddesc.md;
+ assert(md);
+ assert(md->params != NULL);
+
+#ifdef RESOLVE_VERBOSE
+ printf("resolve_constrain_unresolved_method_params_stackbased\n");
+ printf(" rmethod: "); method_println(refmethod);
+ printf(" mref : "); method_methodref_println(methodref);
+#endif
+
+ instancecount = (ref->flags & RESOLVE_STATIC) ? 0 : 1;
+
+ /* record subtype constraints for the parameter types, if any */
+
+ param = stack - (md->paramslots - 1 - instancecount);
+
+ for (i = instancecount; i < md->paramcount; ++i) {
+ type = md->paramtypes[i].type;
+
+ assert(type == param->type);
+
+ if (type == TYPE_ADR) {
+ if (!ref->paramconstraints) {
+ ref->paramconstraints = MNEW(unresolved_subtype_set,md->paramcount);
+ for (j = 0; j < i - instancecount; ++j)
+ UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[j]);
+ }
+ assert(ref->paramconstraints);
+ if (!unresolved_subtype_set_from_typeinfo(refmethod->clazz, refmethod,
+ ref->paramconstraints + i - instancecount,&(param->typeinfo),
+ md->paramtypes[i].classref->name))
+ return false;
+ }
+ else {
+ if (ref->paramconstraints)
+ UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[i]);
+ }
+
+ param += (IS_2_WORD_TYPE(type)) ? 2 : 1;
+ }
+
+ return true;
+}
+#endif /* ENABLE_VERIFIER */
+
+
+/******************************************************************************/
+/* FREEING MEMORY */
+/******************************************************************************/
+
+#ifdef ENABLE_VERIFIER
+inline static void unresolved_subtype_set_free_list(classref_or_classinfo *list)
+{
+ if (list) {
+ classref_or_classinfo *p = list;
+
+ /* this is silly. we *only* need to count the elements for MFREE */
+ while ((p++)->any)
+ ;
+ MFREE(list,classref_or_classinfo,(p - list));
+ }
+}
+#endif /* ENABLE_VERIFIER */
+
+/* unresolved_class_free *******************************************************
+
+ Free the memory used by an unresolved_class
+
+ IN:
+ ref..............the unresolved_class
+
+*******************************************************************************/
+
+void unresolved_class_free(unresolved_class *ref)
+{
+ assert(ref);
+
+#ifdef ENABLE_VERIFIER
+ unresolved_subtype_set_free_list(ref->subtypeconstraints.subtyperefs);
+#endif
+ FREE(ref,unresolved_class);
+}
+
+/* unresolved_field_free *******************************************************
+
+ Free the memory used by an unresolved_field
+
+ IN:
+ ref..............the unresolved_field
+
+*******************************************************************************/
+
+void unresolved_field_free(unresolved_field *ref)
+{
+ assert(ref);
+
+#ifdef ENABLE_VERIFIER
+ unresolved_subtype_set_free_list(ref->instancetypes.subtyperefs);
+ unresolved_subtype_set_free_list(ref->valueconstraints.subtyperefs);
+#endif
+ FREE(ref,unresolved_field);
+}
+
+/* unresolved_method_free ******************************************************
+
+ Free the memory used by an unresolved_method
+
+ IN:
+ ref..............the unresolved_method
+
+*******************************************************************************/
+
+void unresolved_method_free(unresolved_method *ref)
+{
+ assert(ref);
+
+#ifdef ENABLE_VERIFIER
+ unresolved_subtype_set_free_list(ref->instancetypes.subtyperefs);
+ if (ref->paramconstraints) {
+ int i;
+ int count = ref->methodref->parseddesc.md->paramcount;
+
+ for (i=0; i<count; ++i)
+ unresolved_subtype_set_free_list(ref->paramconstraints[i].subtyperefs);
+ MFREE(ref->paramconstraints,unresolved_subtype_set,count);
+ }
+#endif
+ FREE(ref,unresolved_method);
+}
+
+/******************************************************************************/
+/* DEBUG DUMPS */
+/******************************************************************************/
+
+#if !defined(NDEBUG)
+
+/* unresolved_subtype_set_debug_dump *******************************************
+
+ Print debug info for unresolved_subtype_set to stream
+
+ IN:
+ stset............the unresolved_subtype_set
+ file.............the stream
+
+*******************************************************************************/
+
+void unresolved_subtype_set_debug_dump(unresolved_subtype_set *stset,FILE *file)
+{
+ classref_or_classinfo *p;
+
+ if (SUBTYPESET_IS_EMPTY(*stset)) {
+ fprintf(file," (empty)\n");
+ }
+ else {
+ p = stset->subtyperefs;
+ for (;p->any; ++p) {
+ if (IS_CLASSREF(*p)) {
+ fprintf(file," ref: ");
+ utf_fprint_printable_ascii(file,p->ref->name);
+ }
+ else {
+ fprintf(file," cls: ");
+ utf_fprint_printable_ascii(file,p->cls->name);
+ }
+ fputc('\n',file);
+ }
+ }
+}
+
+/* unresolved_class_debug_dump *************************************************
+
+ Print debug info for unresolved_class to stream
+
+ IN:
+ ref..............the unresolved_class
+ file.............the stream
+
+*******************************************************************************/
+
+void unresolved_class_debug_dump(unresolved_class *ref,FILE *file)
+{
+ fprintf(file,"unresolved_class(%p):\n",(void *)ref);
+ if (ref) {
+ fprintf(file," referer : ");
+ utf_fprint_printable_ascii(file,ref->classref->referer->name); fputc('\n',file);
+ fprintf(file," refmethod : ");
+ utf_fprint_printable_ascii(file,ref->referermethod->name); fputc('\n',file);
+ fprintf(file," refmethodd: ");
+ utf_fprint_printable_ascii(file,ref->referermethod->descriptor); fputc('\n',file);
+ fprintf(file," classname : ");
+ utf_fprint_printable_ascii(file,ref->classref->name); fputc('\n',file);
+ fprintf(file," subtypeconstraints:\n");
+ unresolved_subtype_set_debug_dump(&(ref->subtypeconstraints),file);
+ }
+}
+
+/* unresolved_field_debug_dump *************************************************
+
+ Print debug info for unresolved_field to stream
+
+ IN:
+ ref..............the unresolved_field
+ file.............the stream
+
+*******************************************************************************/
+
+void unresolved_field_debug_dump(unresolved_field *ref,FILE *file)
+{
+ fprintf(file,"unresolved_field(%p):\n",(void *)ref);
+ if (ref) {
+ fprintf(file," referer : ");
+ utf_fprint_printable_ascii(file,ref->referermethod->clazz->name); fputc('\n',file);
+ fprintf(file," refmethod : ");
+ utf_fprint_printable_ascii(file,ref->referermethod->name); fputc('\n',file);
+ fprintf(file," refmethodd: ");
+ utf_fprint_printable_ascii(file,ref->referermethod->descriptor); fputc('\n',file);
+ fprintf(file," classname : ");
+ utf_fprint_printable_ascii(file,FIELDREF_CLASSNAME(ref->fieldref)); fputc('\n',file);
+ fprintf(file," name : ");
+ utf_fprint_printable_ascii(file,ref->fieldref->name); fputc('\n',file);
+ fprintf(file," descriptor: ");
+ utf_fprint_printable_ascii(file,ref->fieldref->descriptor); fputc('\n',file);
+ fprintf(file," parseddesc: ");
+ descriptor_debug_print_typedesc(file,ref->fieldref->parseddesc.fd); fputc('\n',file);
+ fprintf(file," flags : %04x\n",ref->flags);
+ fprintf(file," instancetypes:\n");
+ unresolved_subtype_set_debug_dump(&(ref->instancetypes),file);
+ fprintf(file," valueconstraints:\n");
+ unresolved_subtype_set_debug_dump(&(ref->valueconstraints),file);
+ }
+}
+
+/* unresolved_method_debug_dump ************************************************
+
+ Print debug info for unresolved_method to stream
+
+ IN:
+ ref..............the unresolved_method
+ file.............the stream
+
+*******************************************************************************/
+
+void unresolved_method_debug_dump(unresolved_method *ref,FILE *file)
+{
+ int i;
+
+ fprintf(file,"unresolved_method(%p):\n",(void *)ref);
+ if (ref) {
+ fprintf(file," referer : ");
+ utf_fprint_printable_ascii(file,ref->referermethod->clazz->name); fputc('\n',file);
+ fprintf(file," refmethod : ");
+ utf_fprint_printable_ascii(file,ref->referermethod->name); fputc('\n',file);
+ fprintf(file," refmethodd: ");
+ utf_fprint_printable_ascii(file,ref->referermethod->descriptor); fputc('\n',file);
+ fprintf(file," classname : ");
+ utf_fprint_printable_ascii(file,METHODREF_CLASSNAME(ref->methodref)); fputc('\n',file);
+ fprintf(file," name : ");
+ utf_fprint_printable_ascii(file,ref->methodref->name); fputc('\n',file);
+ fprintf(file," descriptor: ");
+ utf_fprint_printable_ascii(file,ref->methodref->descriptor); fputc('\n',file);
+ fprintf(file," parseddesc: ");
+ descriptor_debug_print_methoddesc(file,ref->methodref->parseddesc.md); fputc('\n',file);
+ fprintf(file," flags : %04x\n",ref->flags);
+ fprintf(file," instancetypes:\n");
+ unresolved_subtype_set_debug_dump(&(ref->instancetypes),file);
+ fprintf(file," paramconstraints:\n");
+ if (ref->paramconstraints) {
+ for (i=0; i<ref->methodref->parseddesc.md->paramcount; ++i) {
+ fprintf(file," param %d:\n",i);
+ unresolved_subtype_set_debug_dump(ref->paramconstraints + i,file);
+ }
+ }
+ else {
+ fprintf(file," (empty)\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/resolve.h - resolving classes/interfaces/fields/methods
-
- 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 _RESOLVE_H
-#define _RESOLVE_H
-
-/* forward declarations *******************************************************/
-
-typedef struct unresolved_class unresolved_class;
-typedef struct unresolved_field unresolved_field;
-typedef struct unresolved_method unresolved_method;
-typedef struct unresolved_subtype_set unresolved_subtype_set;
-
-
-#include "config.h"
-#include "vm/types.h"
-
-#include "vm/class.h"
-#include "vm/field.hpp"
-#include "vm/global.h"
-#include "vm/method.h"
-#include "vm/references.h"
-
-#include "vm/jit/jit.hpp"
-#include "vm/jit/reg.h"
-
-#include "vm/jit/ir/instruction.hpp"
-#include "vm/jit/verify/typeinfo.h"
-
-
-/* constants ******************************************************************/
-
-#define RESOLVE_STATIC 0x0001 /* ref to static fields/methods */
-#define RESOLVE_PUTFIELD 0x0002 /* field ref inside a PUT{FIELD,STATIC}... */
-#define RESOLVE_SPECIAL 0x0004 /* method ref inside INVOKESPECIAL */
-
-
-/* enums **********************************************************************/
-
-typedef enum {
- resolveLazy,
- resolveEager
-} resolve_mode_t;
-
-typedef enum {
- resolveLinkageError,
- resolveIllegalAccessError
-} resolve_err_t;
-
-typedef enum {
- resolveFailed = false, /* this must be a false value */
- resolveDeferred = true, /* this must be a true value */
- resolveSucceeded
-} resolve_result_t;
-
-/* structs ********************************************************************/
-
-struct unresolved_subtype_set {
- classref_or_classinfo *subtyperefs; /* NULL terminated list */
-};
-
-struct unresolved_class {
- constant_classref *classref;
- methodinfo *referermethod;
- unresolved_subtype_set subtypeconstraints;
-};
-
-/* XXX unify heads of unresolved_field and unresolved_method? */
-
-struct unresolved_field {
- constant_FMIref *fieldref;
- methodinfo *referermethod;
- s4 flags;
-
- unresolved_subtype_set instancetypes;
- unresolved_subtype_set valueconstraints;
-};
-
-struct unresolved_method {
- constant_FMIref *methodref;
- methodinfo *referermethod;
- s4 flags;
-
- unresolved_subtype_set instancetypes;
- unresolved_subtype_set *paramconstraints;
-};
-
-#define SUBTYPESET_IS_EMPTY(stset) \
- ((stset).subtyperefs == NULL)
-
-#define UNRESOLVED_SUBTYPE_SET_EMTPY(stset) \
- do { (stset).subtyperefs = NULL; } while(0)
-
-
-/* function prototypes ********************************************************/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void resolve_handle_pending_exception(bool throwError);
-
-bool resolve_class_from_name(classinfo* referer,methodinfo *refmethod,
- utf *classname,
- resolve_mode_t mode,
- bool checkaccess,
- bool link,
- classinfo **result);
-
-bool resolve_classref(methodinfo *refmethod,
- constant_classref *ref,
- resolve_mode_t mode,
- bool checkaccess,
- bool link,
- classinfo **result);
-
-bool resolve_classref_or_classinfo(methodinfo *refmethod,
- classref_or_classinfo cls,
- resolve_mode_t mode,
- bool checkaccess,
- bool link,
- classinfo **result);
-
-classinfo *resolve_classref_or_classinfo_eager(classref_or_classinfo cls, bool checkaccess);
-
-bool resolve_class_from_typedesc(typedesc *d,bool checkaccess,bool link,classinfo **result);
-
-#ifdef ENABLE_VERIFIER
-bool resolve_class(unresolved_class *ref,
- resolve_mode_t mode,
- bool checkaccess,
- classinfo **result);
-
-classinfo * resolve_class_eager(unresolved_class *ref);
-classinfo * resolve_class_eager_no_access_check(unresolved_class *ref);
-#endif /* ENABLE_VERIFIER */
-
-bool resolve_field(unresolved_field *ref,
- resolve_mode_t mode,
- fieldinfo **result);
-
-bool resolve_method(unresolved_method *ref,
- resolve_mode_t mode,
- methodinfo **result);
-
-classinfo * resolve_classref_eager(constant_classref *ref);
-classinfo * resolve_classref_eager_nonabstract(constant_classref *ref);
-fieldinfo * resolve_field_eager(unresolved_field *ref);
-methodinfo * resolve_method_eager(unresolved_method *ref);
-
-#ifdef ENABLE_VERIFIER
-unresolved_class * create_unresolved_class(methodinfo *refmethod,
- constant_classref *classref,
- typeinfo_t *valuetype);
-#endif
-
-unresolved_field *resolve_create_unresolved_field(classinfo *referer,
- methodinfo *refmethod,
- instruction *iptr);
-
-unresolved_method * resolve_create_unresolved_method(classinfo *referer,
- methodinfo *refmethod,
- constant_FMIref *methodref,
- bool invokestatic,
- bool invokespecial);
-
-void unresolved_class_free(unresolved_class *ref);
-void unresolved_field_free(unresolved_field *ref);
-void unresolved_method_free(unresolved_method *ref);
-
-resolve_result_t resolve_method_lazy(methodinfo *refmethod,
- constant_FMIref *methodref,
- bool invokespecial);
-
-resolve_result_t resolve_field_lazy(methodinfo *refmethod,
- constant_FMIref *fieldref);
-
-#if defined(ENABLE_VERIFIER)
-resolve_result_t resolve_field_verifier_checks(methodinfo *refmethod,
- constant_FMIref *fieldref,
- classinfo *container,
- fieldinfo *fi,
- typeinfo_t *instanceti,
- typeinfo_t *valueti,
- bool isstatic,
- bool isput);
-
-bool resolve_constrain_unresolved_field(unresolved_field *ref,
- classinfo *referer,
- methodinfo *refmethod,
- typeinfo_t *instanceti,
- typeinfo_t *valueti);
-
-resolve_result_t resolve_method_verifier_checks(methodinfo *refmethod,
- constant_FMIref *methodref,
- methodinfo *mi,
- bool invokestatic);
-
-resolve_result_t resolve_method_instance_type_checks(methodinfo *refmethod,
- methodinfo *mi,
- typeinfo_t *instanceti,
- bool invokespecial);
-
-resolve_result_t resolve_method_param_type_checks(jitdata *jd,
- methodinfo *refmethod,
- instruction *iptr,
- methodinfo *mi,
- bool invokestatic);
-
-resolve_result_t resolve_method_param_type_checks_stackbased(
- methodinfo *refmethod,
- methodinfo *mi,
- bool invokestatic,
- typedescriptor_t *stack);
-
-bool resolve_method_loading_constraints(classinfo *referer,
- methodinfo *mi);
-
-bool resolve_constrain_unresolved_method_instance(unresolved_method *ref,
- methodinfo *refmethod,
- typeinfo_t *instanceti,
- bool invokespecial);
-
-bool resolve_constrain_unresolved_method_params(jitdata *jd,
- unresolved_method *ref,
- methodinfo *refmethod,
- instruction *iptr);
-
-bool resolve_constrain_unresolved_method_params_stackbased(
- unresolved_method *ref,
- methodinfo *refmethod,
- typedescriptor_t *stack);
-
-#endif /* defined(ENABLE_VERIFIER) */
-
-#ifndef NDEBUG
-void unresolved_class_debug_dump(unresolved_class *ref,FILE *file);
-void unresolved_field_debug_dump(unresolved_field *ref,FILE *file);
-void unresolved_method_debug_dump(unresolved_method *ref,FILE *file);
-void unresolved_subtype_set_debug_dump(unresolved_subtype_set *stset,FILE *file);
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _RESOLVE_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/resolve.hpp - resolving classes/interfaces/fields/methods
+
+ 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 _RESOLVE_HPP
+#define _RESOLVE_HPP
+
+/* forward declarations *******************************************************/
+
+typedef struct unresolved_class unresolved_class;
+typedef struct unresolved_field unresolved_field;
+typedef struct unresolved_method unresolved_method;
+typedef struct unresolved_subtype_set unresolved_subtype_set;
+
+
+#include "config.h"
+#include "vm/types.h"
+
+#include "vm/class.h"
+#include "vm/field.hpp"
+#include "vm/global.h"
+#include "vm/method.h"
+#include "vm/references.h"
+
+#include "vm/jit/jit.hpp"
+#include "vm/jit/reg.h"
+
+#include "vm/jit/ir/instruction.hpp"
+#include "vm/jit/verify/typeinfo.h"
+
+
+/* constants ******************************************************************/
+
+#define RESOLVE_STATIC 0x0001 /* ref to static fields/methods */
+#define RESOLVE_PUTFIELD 0x0002 /* field ref inside a PUT{FIELD,STATIC}... */
+#define RESOLVE_SPECIAL 0x0004 /* method ref inside INVOKESPECIAL */
+
+
+/* enums **********************************************************************/
+
+typedef enum {
+ resolveLazy,
+ resolveEager
+} resolve_mode_t;
+
+typedef enum {
+ resolveLinkageError,
+ resolveIllegalAccessError
+} resolve_err_t;
+
+typedef enum {
+ resolveFailed = false, /* this must be a false value */
+ resolveDeferred = true, /* this must be a true value */
+ resolveSucceeded
+} resolve_result_t;
+
+/* structs ********************************************************************/
+
+struct unresolved_subtype_set {
+ classref_or_classinfo *subtyperefs; /* NULL terminated list */
+};
+
+struct unresolved_class {
+ constant_classref *classref;
+ methodinfo *referermethod;
+ unresolved_subtype_set subtypeconstraints;
+};
+
+/* XXX unify heads of unresolved_field and unresolved_method? */
+
+struct unresolved_field {
+ constant_FMIref *fieldref;
+ methodinfo *referermethod;
+ s4 flags;
+
+ unresolved_subtype_set instancetypes;
+ unresolved_subtype_set valueconstraints;
+};
+
+struct unresolved_method {
+ constant_FMIref *methodref;
+ methodinfo *referermethod;
+ s4 flags;
+
+ unresolved_subtype_set instancetypes;
+ unresolved_subtype_set *paramconstraints;
+};
+
+#define SUBTYPESET_IS_EMPTY(stset) \
+ ((stset).subtyperefs == NULL)
+
+#define UNRESOLVED_SUBTYPE_SET_EMTPY(stset) \
+ do { (stset).subtyperefs = NULL; } while(0)
+
+
+/* function prototypes ********************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void resolve_handle_pending_exception(bool throwError);
+
+bool resolve_class_from_name(classinfo* referer,methodinfo *refmethod,
+ utf *classname,
+ resolve_mode_t mode,
+ bool checkaccess,
+ bool link,
+ classinfo **result);
+
+bool resolve_classref(methodinfo *refmethod,
+ constant_classref *ref,
+ resolve_mode_t mode,
+ bool checkaccess,
+ bool link,
+ classinfo **result);
+
+bool resolve_classref_or_classinfo(methodinfo *refmethod,
+ classref_or_classinfo cls,
+ resolve_mode_t mode,
+ bool checkaccess,
+ bool link,
+ classinfo **result);
+
+classinfo *resolve_classref_or_classinfo_eager(classref_or_classinfo cls, bool checkaccess);
+
+bool resolve_class_from_typedesc(typedesc *d,bool checkaccess,bool link,classinfo **result);
+
+#ifdef ENABLE_VERIFIER
+bool resolve_class(unresolved_class *ref,
+ resolve_mode_t mode,
+ bool checkaccess,
+ classinfo **result);
+
+classinfo * resolve_class_eager(unresolved_class *ref);
+classinfo * resolve_class_eager_no_access_check(unresolved_class *ref);
+#endif /* ENABLE_VERIFIER */
+
+bool resolve_field(unresolved_field *ref,
+ resolve_mode_t mode,
+ fieldinfo **result);
+
+bool resolve_method(unresolved_method *ref,
+ resolve_mode_t mode,
+ methodinfo **result);
+
+classinfo * resolve_classref_eager(constant_classref *ref);
+classinfo * resolve_classref_eager_nonabstract(constant_classref *ref);
+fieldinfo * resolve_field_eager(unresolved_field *ref);
+methodinfo * resolve_method_eager(unresolved_method *ref);
+
+#ifdef ENABLE_VERIFIER
+unresolved_class * create_unresolved_class(methodinfo *refmethod,
+ constant_classref *classref,
+ typeinfo_t *valuetype);
+#endif
+
+unresolved_field *resolve_create_unresolved_field(classinfo *referer,
+ methodinfo *refmethod,
+ instruction *iptr);
+
+unresolved_method * resolve_create_unresolved_method(classinfo *referer,
+ methodinfo *refmethod,
+ constant_FMIref *methodref,
+ bool invokestatic,
+ bool invokespecial);
+
+void unresolved_class_free(unresolved_class *ref);
+void unresolved_field_free(unresolved_field *ref);
+void unresolved_method_free(unresolved_method *ref);
+
+resolve_result_t resolve_method_lazy(methodinfo *refmethod,
+ constant_FMIref *methodref,
+ bool invokespecial);
+
+resolve_result_t resolve_field_lazy(methodinfo *refmethod,
+ constant_FMIref *fieldref);
+
+#if defined(ENABLE_VERIFIER)
+resolve_result_t resolve_field_verifier_checks(methodinfo *refmethod,
+ constant_FMIref *fieldref,
+ classinfo *container,
+ fieldinfo *fi,
+ typeinfo_t *instanceti,
+ typeinfo_t *valueti,
+ bool isstatic,
+ bool isput);
+
+bool resolve_constrain_unresolved_field(unresolved_field *ref,
+ classinfo *referer,
+ methodinfo *refmethod,
+ typeinfo_t *instanceti,
+ typeinfo_t *valueti);
+
+resolve_result_t resolve_method_verifier_checks(methodinfo *refmethod,
+ constant_FMIref *methodref,
+ methodinfo *mi,
+ bool invokestatic);
+
+resolve_result_t resolve_method_instance_type_checks(methodinfo *refmethod,
+ methodinfo *mi,
+ typeinfo_t *instanceti,
+ bool invokespecial);
+
+resolve_result_t resolve_method_param_type_checks(jitdata *jd,
+ methodinfo *refmethod,
+ instruction *iptr,
+ methodinfo *mi,
+ bool invokestatic);
+
+resolve_result_t resolve_method_param_type_checks_stackbased(
+ methodinfo *refmethod,
+ methodinfo *mi,
+ bool invokestatic,
+ typedescriptor_t *stack);
+
+bool resolve_method_loading_constraints(classinfo *referer,
+ methodinfo *mi);
+
+bool resolve_constrain_unresolved_method_instance(unresolved_method *ref,
+ methodinfo *refmethod,
+ typeinfo_t *instanceti,
+ bool invokespecial);
+
+bool resolve_constrain_unresolved_method_params(jitdata *jd,
+ unresolved_method *ref,
+ methodinfo *refmethod,
+ instruction *iptr);
+
+bool resolve_constrain_unresolved_method_params_stackbased(
+ unresolved_method *ref,
+ methodinfo *refmethod,
+ typedescriptor_t *stack);
+
+#endif /* defined(ENABLE_VERIFIER) */
+
+#ifndef NDEBUG
+void unresolved_class_debug_dump(unresolved_class *ref,FILE *file);
+void unresolved_field_debug_dump(unresolved_field *ref,FILE *file);
+void unresolved_method_debug_dump(unresolved_method *ref,FILE *file);
+void unresolved_subtype_set_debug_dump(unresolved_subtype_set *stset,FILE *file);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RESOLVE_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 "vm/finalizer.h"
#include "vm/global.h"
#include "vm/globals.hpp"
-#include "vm/initialize.h"
+#include "vm/initialize.hpp"
#include "vm/options.h"
#include "vm/os.hpp"
#include "vm/primitive.hpp"