]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/java/lang.c
Merge tree-ssa-20020619-branch into mainline.
[thirdparty/gcc.git] / gcc / java / lang.c
index a3ed3276ba4af4b7d40db3e08b17617989d2c569..20f13e5adb24bccb4874f5b787400d05b0dd3870 100644 (file)
@@ -1,5 +1,5 @@
 /* Java(TM) language-specific utility routines.
-   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -66,8 +66,7 @@ static bool java_can_use_bit_fields_p (void);
 static bool java_dump_tree (void *, tree);
 static void dump_compound_expr (dump_info_p, tree);
 static bool java_decl_ok_for_sibcall (tree);
-static int java_estimate_num_insns (tree);
-static int java_start_inlining (tree);
+static tree java_get_callee_fndecl (tree);
 
 #ifndef TARGET_OBJECT_SUFFIX
 # define TARGET_OBJECT_SUFFIX ".o"
@@ -173,7 +172,8 @@ int flag_force_classes_archive_check;
 
 /* When zero, don't optimize static class initialization. This flag shouldn't
    be tested alone, use STATIC_CLASS_INITIALIZATION_OPTIMIZATION_P instead.  */
-int flag_optimize_sci = 1;
+/* FIXME: Make this work with gimplify.  */
+int flag_optimize_sci = 0;
 
 /* When nonzero, use offset tables for virtual method calls
    in order to improve binary compatibility. */
@@ -248,21 +248,21 @@ struct language_function GTY(())
 #undef LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE
 #define LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE java_signed_or_unsigned_type
 
-#undef LANG_HOOKS_TREE_INLINING_WALK_SUBTREES
-#define LANG_HOOKS_TREE_INLINING_WALK_SUBTREES java_tree_inlining_walk_subtrees
-
-#undef LANG_HOOKS_TREE_INLINING_ESTIMATE_NUM_INSNS
-#define LANG_HOOKS_TREE_INLINING_ESTIMATE_NUM_INSNS java_estimate_num_insns
-
-#undef LANG_HOOKS_TREE_INLINING_START_INLINING
-#define LANG_HOOKS_TREE_INLINING_START_INLINING java_start_inlining
-
 #undef LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN
 #define LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN java_dump_tree
 
+#undef LANG_HOOKS_GIMPLIFY_EXPR
+#define LANG_HOOKS_GIMPLIFY_EXPR java_gimplify_expr
+
+#undef LANG_HOOKS_TREE_INLINING_WALK_SUBTREES
+#define LANG_HOOKS_TREE_INLINING_WALK_SUBTREES java_tree_inlining_walk_subtrees
+
 #undef LANG_HOOKS_DECL_OK_FOR_SIBCALL
 #define LANG_HOOKS_DECL_OK_FOR_SIBCALL java_decl_ok_for_sibcall
 
+#undef LANG_HOOKS_GET_CALLEE_FNDECL
+#define LANG_HOOKS_GET_CALLEE_FNDECL java_get_callee_fndecl
+
 #undef LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION
 #define LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION java_expand_body
 
@@ -350,6 +350,22 @@ java_handle_option (size_t scode, const char *arg, int value)
       flag_assert = value;
       break;
 
+    case OPT_fenable_assertions_:
+      add_enable_assert (arg, value);
+      break;
+
+    case OPT_fenable_assertions:
+      add_enable_assert ("", value);
+      break;
+
+    case OPT_fdisable_assertions_:
+      add_enable_assert (arg, !value);
+      break;
+
+    case OPT_fdisable_assertions:
+      add_enable_assert ("", !value);
+      break;
+
     case OPT_fassume_compiled_:
       add_assume_compiled (arg, !value);
       break;
@@ -460,6 +476,11 @@ java_init (void)
   if (flag_inline_functions)
     flag_inline_trees = 1;
 
+  /* FIXME: Indirect dispatch isn't yet compatible with static class
+     init optimization.  */
+  if (flag_indirect_dispatch)
+    always_initialize_class_p = true;
+
   /* Force minimum function alignment if g++ uses the least significant
      bit of function pointers to store the virtual bit. This is required
      to keep vtables compatible.  */
@@ -707,17 +728,13 @@ java_post_options (const char **pfilename)
 {
   const char *filename = *pfilename;
 
- /* Use tree inlining if possible.  Function instrumentation is only
-     done in the RTL level, so we disable tree inlining.  */
-  if (! flag_instrument_function_entry_exit)
+  /* Use tree inlining.  */
+  if (!flag_no_inline)
+    flag_no_inline = 1;
+  if (flag_inline_functions)
     {
-      if (!flag_no_inline)
-       flag_no_inline = 1;
-      if (flag_inline_functions)
-       {
-         flag_inline_trees = 2;
-         flag_inline_functions = 0;
-       }
+      flag_inline_trees = 2;
+      flag_inline_functions = 0;
     }
 
   /* Open input file.  */
@@ -836,21 +853,14 @@ java_tree_inlining_walk_subtrees (tree *tp ATTRIBUTE_UNUSED,
   switch (code)
     {
     case BLOCK:
-      if (BLOCK_EXPR_BODY (t))
-       {
-         tree *prev = &BLOCK_EXPR_BODY (*tp);
-         while (*prev)
-           {
-             WALK_SUBTREE (*prev);
-             prev = &TREE_CHAIN (*prev);
-           }       
-       }
+      WALK_SUBTREE (BLOCK_EXPR_BODY (t));
       return NULL_TREE;
-      break;
 
     default:
       return NULL_TREE;
     }
+
+  #undef WALK_SUBTREE
 }
 
 /* Called from unsafe_for_reeval.  */
@@ -922,6 +932,24 @@ merge_init_test_initialization (void **entry, void *x)
   if (!*init_test_decl)
     *init_test_decl = (tree)n->value;
 
+  /* This fixes a weird case.  
+
+  The front end assumes that once we have called a method that
+  initializes some class, we can assume the class is initialized.  It
+  does this by setting the DECL_INITIAL of the init_test_decl for that
+  class, and no initializations are emitted for that class.
+  
+  However, what if the method that is suppoed to do the initialization
+  is itself inlined in the caller?  When expanding the called method
+  we'll assume that the class initialization has already been done,
+  because the DECL_INITIAL of the init_test_decl is set.
+  
+  To fix this we remove the DECL_INITIAL (in the caller scope) of all
+  the init_test_decls corresponding to classes initialized by the
+  inlined method.  This makes the caller no longer assume that the
+  method being inlined does any class initializations.  */
+  DECL_INITIAL (*init_test_decl) = NULL;
+
   return true;
 }
 
@@ -952,11 +980,9 @@ inline_init_test_initialization (void **entry, void *x)
     (DECL_FUNCTION_INIT_TEST_TABLE (current_function_decl), ite->key);
   if (! h)
     return true;
-
   splay_tree_insert (decl_map,
                     (splay_tree_key) ite->value,
                     (splay_tree_value) h);
-
   return true;
 }
 
@@ -1087,122 +1113,52 @@ java_dump_tree (void *dump_info, tree t)
 static bool
 java_decl_ok_for_sibcall (tree decl)
 {
-  return decl != NULL && DECL_CONTEXT (decl) == current_class;
+  return decl != NULL && DECL_CONTEXT (decl) == output_class;
 }
 
-/* Used by estimate_num_insns.  Estimate number of instructions seen
-   by given statement.  */
+/* Given a call_expr, try to figure out what its target might be.  In
+   the case of an indirection via the atable, search for the decl.  If
+   the decl is external, we return NULL.  If we don't, the optimizer
+   will replace the indirection with a direct call, which undoes the
+   purpose of the atable indirection.  */
 static tree
-java_estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data)
+java_get_callee_fndecl (tree call_expr)
 {
-  int *count = data;
-  tree x = *tp;
+  tree method, table, element, atable_methods;
 
-  if (TYPE_P (x) || DECL_P (x))
-    {
-      *walk_subtrees = 0;
-      return NULL;
-    }
-  /* Assume that constants and references counts nothing.  These should
-     be majorized by amount of operations amoung them we count later
-     and are common target of CSE and similar optimizations.  */
-  if (TREE_CODE_CLASS (TREE_CODE (x)) == 'c'
-      || TREE_CODE_CLASS (TREE_CODE (x)) == 'r')
+  HOST_WIDE_INT index;
+
+  if (TREE_CODE (call_expr) != CALL_EXPR)
+    return NULL;
+  method = TREE_OPERAND (call_expr, 0);
+  STRIP_NOPS (method);
+  if (TREE_CODE (method) != ARRAY_REF)
+    return NULL;
+  table = TREE_OPERAND (method, 0);
+  if (! DECL_LANG_SPECIFIC(table)
+      || !DECL_OWNER (table) 
+      || TYPE_ATABLE_DECL (DECL_OWNER (table)) != table)
     return NULL;
-  switch (TREE_CODE (x))
-    { 
-    /* Reconginze assignments of large structures and constructors of
-       big arrays.  */
-    case MODIFY_EXPR:
-    case CONSTRUCTOR:
-      {
-       int size = int_size_in_bytes (TREE_TYPE (x));
-
-       if (!size || size > MOVE_MAX_PIECES)
-         *count += 10;
-       else
-         *count += 2 * (size + MOVE_MAX - 1) / MOVE_MAX;
-       return NULL;
-      }
-      break;
-    /* Few special cases of expensive operations.  This is usefull
-       to avoid inlining on functions having too many of these.  */
-    case TRUNC_DIV_EXPR:
-    case CEIL_DIV_EXPR:
-    case FLOOR_DIV_EXPR:
-    case ROUND_DIV_EXPR:
-    case TRUNC_MOD_EXPR:
-    case CEIL_MOD_EXPR:
-    case FLOOR_MOD_EXPR:
-    case ROUND_MOD_EXPR:
-    case RDIV_EXPR:
-    case CALL_EXPR:
-
-    case NEW_ARRAY_EXPR:
-    case NEW_ANONYMOUS_ARRAY_EXPR:
-    case NEW_CLASS_EXPR:
-      *count += 10;
-      break;
-    /* Various containers that will produce no code themselves.  */
-    case INIT_EXPR:
-    case TARGET_EXPR:
-    case BIND_EXPR:
-    case BLOCK:
-    case TREE_LIST:
-    case TREE_VEC:
-    case IDENTIFIER_NODE:
-    case PLACEHOLDER_EXPR:
-    case WITH_CLEANUP_EXPR:
-    case CLEANUP_POINT_EXPR:
-    case NOP_EXPR:
-    case VIEW_CONVERT_EXPR:
-    case SAVE_EXPR:
-    case UNSAVE_EXPR:
-    case COMPLEX_EXPR:
-    case REALPART_EXPR:
-    case IMAGPART_EXPR:
-    case TRY_CATCH_EXPR:
-    case TRY_FINALLY_EXPR:
-    case LABEL_EXPR:
-    case EXIT_EXPR:
-    case LABELED_BLOCK_EXPR:
-    case EXIT_BLOCK_EXPR:
-    case EXPR_WITH_FILE_LOCATION:
-    case UNARY_PLUS_EXPR:
-    case THIS_EXPR:
-    case DEFAULT_EXPR:
-    case TRY_EXPR:
 
-      break;
-    case CLASS_LITERAL:
-      *walk_subtrees = 0;
-      break;
-    default:
-      (*count)++;
+  atable_methods = TYPE_ATABLE_METHODS (DECL_OWNER (table));
+  index = TREE_INT_CST_LOW (TREE_OPERAND (method, 1));
+  
+  /* FIXME: Replace this for loop with a hash table lookup.  */
+  for (element = atable_methods; element; element = TREE_CHAIN (element))
+    {
+      if (index == 1)
+       {
+         tree purpose = TREE_PURPOSE (element);
+         if (TREE_CODE (purpose) == FUNCTION_DECL
+             && ! DECL_EXTERNAL (purpose))
+           return purpose;
+         else
+           return NULL;
+       }
+      --index;
     }
-  return NULL;
-}
 
-/*  Estimate number of instructions that will be created by expanding the body.  */
-static int
-java_estimate_num_insns (tree decl)
-{
-  int num = 0;
-  walk_tree_without_duplicates (&DECL_SAVED_TREE (decl),
-                               java_estimate_num_insns_1, &num);
-  return num;
-}
-
-/* Start inlining fn.  Called by the tree inliner via
-   lang_hooks.tree_inlining.cannot_inline_tree_fn.  */
-
-static int
-java_start_inlining (tree fn)
-{
-  /* A java function's body doesn't have a BLOCK structure suitable
-     for debug output until it is expanded.  Prevent inlining functions
-     that are not yet expanded.  */
-  return TREE_ASM_WRITTEN (fn) ? 1 : 0;
+  return NULL;
 }
 
 #include "gt-java-lang.h"