/* src/vm/method.c - method functions
- Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
- R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
- C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
- Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+ C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
+ E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
+ J. Wenninger, Institut f. Computersprachen - TU Wien
This file is part of CACAO.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA.
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
- Contact: cacao@complang.tuwien.ac.at
+ Contact: cacao@cacaojvm.org
Authors: Reinhard Grafl
Edwin Steiner
Christian Thalinger
- $Id: method.c 3412 2005-10-12 12:54:02Z twisti $
+ $Id: method.c 7228 2007-01-19 01:13:48Z edwin $
*/
-#include "vm/global.h"
+#include "config.h"
+
+#include <assert.h>
+#include <stdio.h>
+
+#include "vm/types.h"
+
#include "mm/memory.h"
-#include "vm/method.h"
#include "vm/class.h"
+#include "vm/global.h"
+#include "vm/linker.h"
#include "vm/loader.h"
-#include "vm/jit/codegen.inc.h"
+#include "vm/method.h"
+#include "vm/options.h"
+#include "vm/jit/methodheader.h"
+
+
+#if !defined(NDEBUG) && defined(ENABLE_INLINING)
+#define INLINELOG(code) do { if (opt_inline_debug_log) { code } } while (0)
+#else
+#define INLINELOG(code)
+#endif
/* method_free *****************************************************************
if (m->jcode)
MFREE(m->jcode, u1, m->jcodelength);
- if (m->exceptiontable)
- MFREE(m->exceptiontable, exceptiontable, m->exceptiontablelength);
+ if (m->rawexceptiontable)
+ MFREE(m->rawexceptiontable, raw_exception_entry, m->rawexceptiontablelength);
- if (m->mcode)
- CFREE((void *) (ptrint) m->mcode, m->mcodelength);
+ code_free_code_of_method(m);
if (m->stubroutine) {
if (m->flags & ACC_NATIVE) {
return true;
}
-/* method_descriptor2types *****************************************************
- Fills in the following members of the given methodinfo:
- returntype
- paramcount
- paramtypes
+/* method_vftbl_lookup *********************************************************
- Note:
- This function uses dump_alloc functions to allocate memory.
+ Does a method lookup in the passed virtual function table. This
+ function does exactly the same thing as JIT, but additionally
+ relies on the fact, that the methodinfo pointer is at the first
+ data segment slot (even for compiler stubs).
-*******************************************************************************/
+*******************************************************************************/
-void method_descriptor2types(methodinfo *m)
+methodinfo *method_vftbl_lookup(vftbl_t *vftbl, methodinfo* m)
{
- u1 *types, *tptr;
- int pcount, i;
- methoddesc *md = m->parseddesc;
- typedesc *paramtype;
-
- pcount = md->paramcount;
- if ((m->flags & ACC_STATIC) == 0)
- pcount++; /* count this pointer */
-
- types = DMNEW(u1,pcount);
- tptr = types;
-
- if (!(m->flags & ACC_STATIC)) {
- /* this pointer */
- *tptr++ = TYPE_ADR;
+ methodptr mptr;
+ methodptr *pmptr;
+ methodinfo *resm; /* pointer to new resolved method */
+ codeinfo *code;
+
+ /* If the method is not an instance method, just return it. */
+
+ if (m->flags & ACC_STATIC)
+ return m;
+
+ assert(vftbl);
+
+ /* Get the method from the virtual function table. Is this an
+ interface method? */
+
+ if (m->class->flags & ACC_INTERFACE) {
+ pmptr = vftbl->interfacetable[-(m->class->index)];
+ mptr = pmptr[(m - m->class->methods)];
+ }
+ else {
+ mptr = vftbl->table[m->vftblindex];
+ }
+
+ /* and now get the codeinfo pointer from the first data segment slot */
+
+ code = *((codeinfo **) (mptr + CodeinfoPointer));
+
+ resm = code->m;
+
+ return resm;
+}
+
+
+/* method_count_implementations ************************************************
+
+ Count the implementations of a method in a class cone (a class and all its
+ subclasses.)
+
+ IN:
+ m................the method to count
+ c................class at which to start the counting (this class and
+ all its subclasses will be searched)
+
+ OUT:
+ *found...........if found != NULL, *found receives the method
+ implementation that was found. This value is only
+ meaningful if the return value is 1.
+
+ RETURN VALUE:
+ the number of implementations found
+
+*******************************************************************************/
+
+s4 method_count_implementations(methodinfo *m, classinfo *c, methodinfo **found)
+{
+ s4 count;
+ methodinfo *mp;
+ methodinfo *mend;
+ classinfo *child;
+
+ count = 0;
+
+ mp = c->methods;
+ mend = mp + c->methodscount;
+
+ for (; mp < mend; ++mp) {
+ if (method_canoverwrite(mp, m)) {
+ if (found)
+ *found = mp;
+ count++;
+ break;
+ }
+ }
+
+ for (child = c->sub; child != NULL; child = child->nextsub) {
+ count += method_count_implementations(m, child, found);
+ }
+
+ return count;
+}
+
+
+/* method_add_to_worklist ******************************************************
+
+ Add the method to the given worklist. If the method already occurs in
+ the worklist, the worklist remains unchanged.
+
+*******************************************************************************/
+
+static void method_add_to_worklist(methodinfo *m, method_worklist **wl)
+{
+ method_worklist *wi;
+
+ for (wi = *wl; wi != NULL; wi = wi->next)
+ if (wi->m == m)
+ return;
+
+ wi = NEW(method_worklist);
+ wi->next = *wl;
+ wi->m = m;
+
+ *wl = wi;
+}
+
+
+/* method_add_assumption_monomorphic *******************************************
+
+ Record the assumption that the method is monomorphic.
+
+ IN:
+ m.................the method
+ caller............the caller making the assumption
+
+*******************************************************************************/
+
+void method_add_assumption_monomorphic(methodinfo *m, methodinfo *caller)
+{
+ method_assumption *as;
+
+ /* XXX LOCKING FOR THIS FUNCTION? */
+
+ /* check if we already have registered this assumption */
+
+ for (as = m->assumptions; as != NULL; as = as->next) {
+ if (as->context == caller)
+ return;
}
- paramtype = md->paramtypes;
- for (i=0; i<md->paramcount; ++i,++paramtype)
- *tptr++ = paramtype->type;
+ /* register the assumption */
+
+ as = NEW(method_assumption);
+ as->next = m->assumptions;
+ as->context = caller;
+
+ m->assumptions = as;
+}
+
+
+/* method_break_assumption_monomorphic *****************************************
+
+ Break the assumption that this method is monomorphic. All callers that
+ have registered this assumption are added to the worklist.
+
+ IN:
+ m.................the method
+ wl................worklist where to add invalidated callers
+
+*******************************************************************************/
+
+void method_break_assumption_monomorphic(methodinfo *m, method_worklist **wl)
+{
+ method_assumption *as;
+
+ /* XXX LOCKING FOR THIS FUNCTION? */
- m->returntype = md->returntype.type;
- m->paramcount = pcount;
- m->paramtypes = types;
+ for (as = m->assumptions; as != NULL; as = as->next) {
+ INLINELOG(
+ printf("ASSUMPTION BROKEN (monomorphism): ");
+ method_print(m);
+ printf(" in ");
+ method_println(as->context);
+ );
+
+ method_add_to_worklist(as->context, wl);
+ }
}
-/************** Function: method_display (debugging only) **************/
-void method_display(methodinfo *m)
+/* method_printflags ***********************************************************
+
+ Prints the flags of a method to stdout like.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void method_printflags(methodinfo *m)
{
- printf(" ");
- printflags(m->flags);
- printf(" ");
- utf_display(m->name);
- printf(" ");
- utf_display(m->descriptor);
+ if (m == NULL) {
+ printf("NULL");
+ return;
+ }
+
+ if (m->flags & ACC_PUBLIC) printf(" PUBLIC");
+ if (m->flags & ACC_PRIVATE) printf(" PRIVATE");
+ if (m->flags & ACC_PROTECTED) printf(" PROTECTED");
+ if (m->flags & ACC_STATIC) printf(" STATIC");
+ if (m->flags & ACC_FINAL) printf(" FINAL");
+ if (m->flags & ACC_SYNCHRONIZED) printf(" SYNCHRONIZED");
+ if (m->flags & ACC_VOLATILE) printf(" VOLATILE");
+ if (m->flags & ACC_TRANSIENT) printf(" TRANSIENT");
+ if (m->flags & ACC_NATIVE) printf(" NATIVE");
+ if (m->flags & ACC_INTERFACE) printf(" INTERFACE");
+ if (m->flags & ACC_ABSTRACT) printf(" ABSTRACT");
+ if (m->flags & ACC_METHOD_MONOMORPHIC) printf(" (mono)");
+ if (m->flags & ACC_METHOD_IMPLEMENTED) printf(" (impl)");
+}
+#endif /* !defined(NDEBUG) */
+
+
+/* method_print ****************************************************************
+
+ Prints a method to stdout like:
+
+ java.lang.Object.<init>()V
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void method_print(methodinfo *m)
+{
+ if (m == NULL) {
+ printf("NULL");
+ return;
+ }
+
+ utf_display_printable_ascii_classname(m->class->name);
+ printf(".");
+ utf_display_printable_ascii(m->name);
+ utf_display_printable_ascii(m->descriptor);
+
+ method_printflags(m);
+}
+#endif /* !defined(NDEBUG) */
+
+
+/* method_println **************************************************************
+
+ Prints a method plus new line to stdout like:
+
+ java.lang.Object.<init>()V
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void method_println(methodinfo *m)
+{
+ if (opt_debugcolor) printf("\033[31m"); /* red */
+ method_print(m);
+ if (opt_debugcolor) printf("\033[m");
printf("\n");
}
+#endif /* !defined(NDEBUG) */
+
-/************** Function: method_display_w_class (debugging only) **************/
+/* method_methodref_print ******************************************************
-void method_display_w_class(methodinfo *m)
+ Prints a method reference to stdout.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void method_methodref_print(constant_FMIref *mr)
{
- printflags(m->class->flags);
- printf(" "); fflush(stdout);
- utf_display(m->class->name);
- printf(".");fflush(stdout);
-
- printf(" ");
- printflags(m->flags);
- printf(" "); fflush(stdout);
- utf_display(m->name);
- printf(" "); fflush(stdout);
- utf_display(m->descriptor);
- printf("\n"); fflush(stdout);
+ if (!mr) {
+ printf("(constant_FMIref *)NULL");
+ return;
+ }
+
+ if (IS_FMIREF_RESOLVED(mr)) {
+ printf("<method> ");
+ method_print(mr->p.method);
+ }
+ else {
+ printf("<methodref> ");
+ utf_display_printable_ascii_classname(mr->p.classref->name);
+ printf(".");
+ utf_display_printable_ascii(mr->name);
+ utf_display_printable_ascii(mr->descriptor);
+ }
}
+#endif /* !defined(NDEBUG) */
+
+
+/* method_methodref_println ****************************************************
-/************** Function: method_display_flags_last (debugging only) **************/
+ Prints a method reference to stdout, followed by a newline.
-void method_display_flags_last(methodinfo *m)
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void method_methodref_println(constant_FMIref *mr)
{
- printf(" ");
- utf_display(m->name);
- printf(" ");
- utf_display(m->descriptor);
- printf(" ");
- printflags(m->flags);
- printf("\n");
+ method_methodref_print(mr);
+ printf("\n");
}
+#endif /* !defined(NDEBUG) */
/*
* c-basic-offset: 4
* tab-width: 4
* End:
+ * vim:noexpandtab:sw=4:ts=4:
*/