* src/vm/jit/oprofile-agent.cpp: Set source formatting to c++.
[cacao.git] / src / vmcore / method.c
index 349bea811e3cb4f4f9831e21fee5edca91a31986..1882270c1d7e28e1c4c3980aacb1298c41f0f986 100644 (file)
@@ -1,9 +1,7 @@
 /* src/vmcore/method.c - method functions
 
-   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
-   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
-   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
-   J. Wenninger, Institut f. Computersprachen - TU Wien
+   Copyright (C) 1996-2005, 2006, 2007, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 
@@ -22,8 +20,6 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: method.c 8322 2007-08-16 15:54:38Z twisti $
-
 */
 
 
 
 #include "threads/lock-common.h"
 
+#include "vm/array.h"
 #include "vm/builtin.h"
-#include "vm/exceptions.h"
+#include "vm/exceptions.hpp"
 #include "vm/global.h"
 #include "vm/resolve.h"
+#include "vm/vm.hpp"
 
+#include "vm/jit/code.h"
 #include "vm/jit/methodheader.h"
 
 #include "vm/jit_interface.h"
 
 #include "vmcore/class.h"
+#include "vmcore/globals.hpp"
 #include "vmcore/linker.h"
 #include "vmcore/loader.h"
 #include "vmcore/method.h"
 #include "vmcore/options.h"
 #include "vmcore/suck.h"
+#include "vmcore/utf8.h"
 
 
 #if !defined(NDEBUG) && defined(ENABLE_INLINING)
-#define INLINELOG(code)  do { if (opt_inline_debug_log) { code } } while (0)
+#define INLINELOG(code)  do { if (opt_TraceInlining) { code } } while (0)
 #else
 #define INLINELOG(code)
 #endif
 
 
+/* global variables ***********************************************************/
+
+methodinfo *method_java_lang_reflect_Method_invoke;
+
+
+/* method_init *****************************************************************
+
+   Initialize method subsystem.
+
+*******************************************************************************/
+
+void method_init(void)
+{
+#if defined(ENABLE_JAVASE)
+       /* Sanity check. */
+
+       if (class_java_lang_reflect_Method == NULL)
+               vm_abort("method_init: class_java_lang_reflect_Method is NULL");
+
+       /* Cache java.lang.reflect.Method.invoke() */
+
+       method_java_lang_reflect_Method_invoke =
+               class_findmethod(class_java_lang_reflect_Method, utf_invoke, NULL);
+
+       if (method_java_lang_reflect_Method_invoke == NULL)
+               vm_abort("method_init: Could not resolve method java.lang.reflect.Method.invoke().");
+#endif
+}
+
+
 /* method_load *****************************************************************
 
    Loads a method from the class file and fills an existing methodinfo
@@ -113,7 +144,7 @@ bool method_load(classbuffer *cb, methodinfo *m, descriptor_pool *descpool)
 
        /* get classinfo */
 
-       c = cb->class;
+       c = cb->clazz;
 
        LOCK_INIT_OBJECT_LOCK(&(m->header));
 
@@ -124,7 +155,7 @@ bool method_load(classbuffer *cb, methodinfo *m, descriptor_pool *descpool)
 
        /* all fields of m have been zeroed in load_class_from_classbuffer */
 
-       m->class = c;
+       m->clazz = c;
        
        if (!suck_check_classbuffer_size(cb, 2 + 2 + 2))
                return false;
@@ -540,6 +571,37 @@ bool method_canoverwrite(methodinfo *m, methodinfo *old)
 }
 
 
+/* method_new_builtin **********************************************************
+
+   Creates a minimal methodinfo structure for builtins. This comes handy
+   when dealing with builtin stubs or stacktraces.
+
+*******************************************************************************/
+
+methodinfo *method_new_builtin(builtintable_entry *bte)
+{
+       methodinfo *m;
+
+       /* allocate the methodinfo structure */
+
+       m = NEW(methodinfo);
+
+       /* initialize methodinfo structure */
+
+       MZERO(m, methodinfo, 1);
+       LOCK_INIT_OBJECT_LOCK(&(m->header));
+
+       m->flags      = ACC_METHOD_BUILTIN;
+       m->parseddesc = bte->md;
+       m->name       = bte->name;
+       m->descriptor = bte->descriptor;
+
+       /* return the newly created methodinfo */
+
+       return m;
+}
+
+
 /* method_vftbl_lookup *********************************************************
 
    Does a method lookup in the passed virtual function table.  This
@@ -565,9 +627,9 @@ methodinfo *method_vftbl_lookup(vftbl_t *vftbl, methodinfo* m)
        /* 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)];
+       if (m->clazz->flags & ACC_INTERFACE) {
+               pmptr = vftbl->interfacetable[-(m->clazz->index)];
+               mptr  = pmptr[(m - m->clazz->methods)];
        }
        else {
                mptr = vftbl->table[m->vftblindex];
@@ -586,20 +648,24 @@ methodinfo *method_vftbl_lookup(vftbl_t *vftbl, methodinfo* m)
    Use the descriptor of a method to determine the number of parameters
    of the method. The this pointer of non-static methods is not counted.
 
-   Returns -1 on error.
+   IN:
+       m........the method of which the parameters should be counted
+
+   RETURN VALUE:
+       The parameter count or -1 on error.
 
 *******************************************************************************/
 
 int32_t method_get_parametercount(methodinfo *m)
 {
-       methoddesc *md;
-       int32_t     paramcount = 0;
+       methoddesc *md;             /* method descriptor of m   */
+       int32_t     paramcount = 0; /* the parameter count of m */
 
        md = m->parseddesc;
        
        /* is the descriptor fully parsed? */
 
-       if (m->parseddesc->params == NULL) {
+       if (md->params == NULL) {
                if (!descriptor_params_from_paramtypes(md, m->flags)) {
                        return -1;
                }
@@ -778,35 +844,41 @@ s4 method_count_implementations(methodinfo *m, classinfo *c, methodinfo **found)
 
 /* method_get_annotations ******************************************************
 
-   Gets a methods' annotations (or NULL if none).
+   Get a methods' unparsed annotations in a byte array.
+
+   IN:
+       m........the method of which the annotations should be returned
+
+   RETURN VALUE:
+       The unparsed annotations in a byte array (or NULL if there aren't any).
 
 *******************************************************************************/
 
 java_handle_bytearray_t *method_get_annotations(methodinfo *m)
 {
 #if defined(ENABLE_ANNOTATIONS)
-       classinfo               *c;
-       int                      slot;
-       annotation_bytearray_t  *ba;
-       java_handle_bytearray_t *annotations;
+       classinfo     *c;                  /* methods' declaring class          */
+       int            slot;               /* methods' slot                     */
+       java_handle_t *annotations;        /* methods' unparsed annotations     */
+       java_handle_t *method_annotations; /* all methods' unparsed annotations */
+                                          /* of the declaring class            */
 
-       c           = m->class;
+       c           = m->clazz;
        slot        = m - c->methods;
        annotations = NULL;
-       
-       if (c->method_annotations != NULL && c->method_annotations->size > slot) {
-               ba = c->method_annotations->data[slot];
-               
-               if (ba != NULL) {
-                       annotations = builtin_newarray_byte(ba->size);
-                       
-                       if (annotations != NULL) {
-                               MCOPY(annotations->data, ba->data, uint8_t, ba->size);
-                       }
-               }
+
+       LLNI_classinfo_field_get(c, method_annotations, method_annotations);
+
+       /* the method_annotations array might be shorter then the method
+        * count if the methods above a certain index have no annotations.
+        */     
+       if (method_annotations != NULL &&
+               array_length_get(method_annotations) > slot) {
+               annotations = array_objectarray_element_get(
+                       (java_handle_objectarray_t*)method_annotations, slot);
        }
        
-       return annotations;
+       return (java_handle_bytearray_t*)annotations;
 #else
        return NULL;
 #endif
@@ -815,36 +887,48 @@ java_handle_bytearray_t *method_get_annotations(methodinfo *m)
 
 /* method_get_parameterannotations ********************************************
 
-   Gets a methods' parameter annotations (or NULL if none).
+   Get a methods' unparsed parameter annotations in an array of byte
+   arrays.
+
+   IN:
+       m........the method of which the parameter annotations should be
+                   returned
+
+   RETURN VALUE:
+       The unparsed parameter annotations in a byte array (or NULL if
+          there aren't any).
 
 *******************************************************************************/
 
 java_handle_bytearray_t *method_get_parameterannotations(methodinfo *m)
 {
 #if defined(ENABLE_ANNOTATIONS)
-       classinfo               *c;
-       int                      slot;
-       annotation_bytearray_t  *ba;
-       java_handle_bytearray_t *parameterAnnotations;
-
-       c                    = m->class;
+       classinfo     *c;                           /* methods' declaring class */
+       int            slot;                        /* methods' slot            */
+       java_handle_t *parameterAnnotations;        /* methods' unparsed        */
+                                                   /* parameter annotations    */
+       java_handle_t *method_parameterannotations; /* all methods' unparsed    */
+                                                   /* parameter annotations of */
+                                                   /* the declaring class      */
+
+       c                    = m->clazz;
        slot                 = m - c->methods;
        parameterAnnotations = NULL;
 
-       if (c->method_parameterannotations != NULL &&
-               c->method_parameterannotations->size > slot) {
-               ba = c->method_parameterannotations->data[slot];
-               
-               if (ba != NULL) {
-                       parameterAnnotations = builtin_newarray_byte(ba->size);
-                       
-                       if (parameterAnnotations != NULL) {
-                               MCOPY(parameterAnnotations->data, ba->data, uint8_t, ba->size);
-                       }
-               }
+       LLNI_classinfo_field_get(
+               c, method_parameterannotations, method_parameterannotations);
+
+       /* the method_annotations array might be shorter then the method
+        * count if the methods above a certain index have no annotations.
+        */     
+       if (method_parameterannotations != NULL &&
+               array_length_get(method_parameterannotations) > slot) {
+               parameterAnnotations = array_objectarray_element_get(
+                               (java_handle_objectarray_t*)method_parameterannotations,
+                               slot);
        }
        
-       return parameterAnnotations;
+       return (java_handle_bytearray_t*)parameterAnnotations;
 #else
        return NULL;
 #endif
@@ -853,36 +937,46 @@ java_handle_bytearray_t *method_get_parameterannotations(methodinfo *m)
 
 /* method_get_annotationdefault ***********************************************
 
-   Gets a methods' annotation default value (or NULL if none).
+   Get a methods' unparsed annotation default value in a byte array.
+   
+   IN:
+       m........the method of which the annotation default value should be
+                   returned
+
+   RETURN VALUE:
+       The unparsed annotation default value in a byte array (or NULL if
+          there isn't one).
 
 *******************************************************************************/
 
 java_handle_bytearray_t *method_get_annotationdefault(methodinfo *m)
 {
 #if defined(ENABLE_ANNOTATIONS)
-       classinfo               *c;
-       int                      slot;
-       annotation_bytearray_t  *ba;
-       java_handle_bytearray_t *annotationDefault;
-
-       c                 = m->class;
+       classinfo     *c;                         /* methods' declaring class     */
+       int            slot;                      /* methods' slot                */
+       java_handle_t *annotationDefault;         /* methods' unparsed            */
+                                                 /* annotation default value     */
+       java_handle_t *method_annotationdefaults; /* all methods' unparsed        */
+                                                 /* annotation default values of */
+                                                 /* the declaring class          */
+
+       c                 = m->clazz;
        slot              = m - c->methods;
        annotationDefault = NULL;
 
-       if (c->method_annotationdefaults != NULL &&
-               c->method_annotationdefaults->size > slot) {
-               ba = c->method_annotationdefaults->data[slot];
-               
-               if (ba != NULL) {
-                       annotationDefault = builtin_newarray_byte(ba->size);
-                       
-                       if (annotationDefault != NULL) {
-                               MCOPY(annotationDefault->data, ba->data, uint8_t, ba->size);
-                       }
-               }
+       LLNI_classinfo_field_get(
+               c, method_annotationdefaults, method_annotationdefaults);
+
+       /* the method_annotations array might be shorter then the method
+        * count if the methods above a certain index have no annotations.
+        */     
+       if (method_annotationdefaults != NULL &&
+               array_length_get(method_annotationdefaults) > slot) {
+               annotationDefault = array_objectarray_element_get(
+                               (java_handle_objectarray_t*)method_annotationdefaults, slot);
        }
        
-       return annotationDefault;
+       return (java_handle_bytearray_t*)annotationDefault;
 #else
        return NULL;
 #endif
@@ -944,7 +1038,6 @@ void method_add_assumption_monomorphic(methodinfo *m, methodinfo *caller)
        m->assumptions = as;
 }
 
-
 /* method_break_assumption_monomorphic *****************************************
 
    Break the assumption that this method is monomorphic. All callers that
@@ -971,10 +1064,21 @@ void method_break_assumption_monomorphic(methodinfo *m, method_worklist **wl)
                );
 
                method_add_to_worklist(as->context, wl);
+
+#if defined(ENABLE_TLH) && 0
+               /* XXX hack */
+               method_assumption *as2;
+               as2 = m->assumptions;
+               m->assumptions = NULL;
+               method_break_assumption_monomorphic(as->context, wl);
+               /*
+               assert(m->assumptions == NULL);
+               m->assumptions = as2;*/
+#endif
+
        }
 }
 
-
 /* method_printflags ***********************************************************
 
    Prints the flags of a method to stdout like.
@@ -989,19 +1093,20 @@ void method_printflags(methodinfo *m)
                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)");
+       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_BUILTIN)     printf(" (builtin)");
+       if (m->flags & ACC_METHOD_MONOMORPHIC) printf(" (mono)");
+       if (m->flags & ACC_METHOD_IMPLEMENTED) printf(" (impl)");
 }
 #endif /* !defined(NDEBUG) */
 
@@ -1022,7 +1127,10 @@ void method_print(methodinfo *m)
                return;
        }
 
-       utf_display_printable_ascii_classname(m->class->name);
+       if (m->clazz != NULL)
+               utf_display_printable_ascii_classname(m->clazz->name);
+       else
+               printf("NULL");
        printf(".");
        utf_display_printable_ascii(m->name);
        utf_display_printable_ascii(m->descriptor);