OSDN Git Service

2005-04-28 Andrew Haley <aph@redhat.com>
authoraph <aph@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 29 Apr 2005 18:43:25 +0000 (18:43 +0000)
committeraph <aph@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 29 Apr 2005 18:43:25 +0000 (18:43 +0000)
        PR java/19285
        * java-tree.h (soft_resolvepoolentry_node): New.
        (alloc_constant_fieldref): Declare.
        * expr.c (expand_java_field_op): Don't call class_init for
        accesses to static fields with indirect dispatch.
        * builtins.c (initialize_builtins): Add "__builtin_expect".
        * decl.c (soft_resolvepoolentry_node): New variable.
        (java_init_decl_processing): Create a decl for
        "_Jv_ResolvePoolEntry".
        * class.c (build_fieldref_cache_entry): New function.
        (build_static_field_ref): Rewrite for indirect dispatch.
        * constants.c (find_name_and_type_constant_tree): New function.
        (alloc_constant_fieldref): Likewise.
        (build_constants_constructor): Handle CONSTANT_Fieldref and
        CONSTANT_NameAndType.

        PR java/21115
        * expr.c (force_evaluation_order): Convert outgoing args smaller
        than integer.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@99010 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/java/ChangeLog
gcc/java/builtins.c
gcc/java/class.c
gcc/java/constants.c
gcc/java/decl.c
gcc/java/expr.c
gcc/java/java-tree.h

index 89ec568..deaaa31 100644 (file)
@@ -1,3 +1,25 @@
+2005-04-28  Andrew Haley  <aph@redhat.com>
+
+       PR java/19285
+       * java-tree.h (soft_resolvepoolentry_node): New.
+       (alloc_constant_fieldref): Declare.
+       * expr.c (expand_java_field_op): Don't call class_init for
+       accesses to static fields with indirect dispatch.
+       * builtins.c (initialize_builtins): Add "__builtin_expect".
+       * decl.c (soft_resolvepoolentry_node): New variable.
+       (java_init_decl_processing): Create a decl for
+       "_Jv_ResolvePoolEntry".
+       * class.c (build_fieldref_cache_entry): New function.
+       (build_static_field_ref): Rewrite for indirect dispatch.
+       * constants.c (find_name_and_type_constant_tree): New function.
+       (alloc_constant_fieldref): Likewise.
+       (build_constants_constructor): Handle CONSTANT_Fieldref and
+       CONSTANT_NameAndType.
+
+       PR java/21115
+       * expr.c (force_evaluation_order): Convert outgoing args smaller
+       than integer.
+
 2005-04-27  Bryce McKinlay  <mckinlay@redhat.com>
 
        * gcj.texi (libgcj Runtime Properties): Remove obsolete
index f4a8efb..dcfff1c 100644 (file)
@@ -161,6 +161,7 @@ initialize_builtins (void)
 {
   tree double_ftype_double, double_ftype_double_double;
   tree float_ftype_float, float_ftype_float_float;
+  tree boolean_ftype_boolean_boolean;
   tree t;
   int i;
 
@@ -216,7 +217,14 @@ initialize_builtins (void)
                  double_ftype_double, "_ZN4java4lang4Math4sqrtEd");
   define_builtin (BUILT_IN_TAN, "__builtin_tan",
                  double_ftype_double, "_ZN4java4lang4Math3tanEd");
-
+  
+  t = tree_cons (NULL_TREE, boolean_type_node, end_params_node);
+  t = tree_cons (NULL_TREE, boolean_type_node, t);
+  boolean_ftype_boolean_boolean = build_function_type (boolean_type_node, t);
+  define_builtin (BUILT_IN_EXPECT, "__builtin_expect", 
+                 boolean_ftype_boolean_boolean,
+                 "__builtin_expect");
+                 
   build_common_builtin_nodes ();
 }
 
index 54e310d..321c1e4 100644 (file)
@@ -1037,6 +1037,31 @@ build_class_ref (tree type)
     return build_indirect_class_ref (type);
 }
 
+/* Create a local statically allocated variable that will hold a
+   pointer to a static field.  */
+
+static tree
+build_fieldref_cache_entry (int index, tree fdecl ATTRIBUTE_UNUSED)
+{
+  tree decl, decl_name;
+  const char *name = IDENTIFIER_POINTER (mangled_classname ("_cpool_", output_class));
+  char *buf = alloca (strlen (name) + 20);
+  sprintf (buf, "%s_%d_ref", name, index);
+  decl_name = get_identifier (buf);
+  decl = IDENTIFIER_GLOBAL_VALUE (decl_name);
+  if (decl == NULL_TREE)
+    {
+      decl = build_decl (VAR_DECL, decl_name, ptr_type_node);
+      TREE_STATIC (decl) = 1;
+      TREE_PUBLIC (decl) = 0;
+      DECL_EXTERNAL (decl) = 0;
+      DECL_ARTIFICIAL (decl) = 1;
+      make_decl_rtl (decl);
+      pushdecl_top_level (decl);
+    }
+  return decl;
+}
+
 tree
 build_static_field_ref (tree fdecl)
 {
@@ -1062,59 +1087,47 @@ build_static_field_ref (tree fdecl)
            DECL_EXTERNAL (fdecl) = 1;
          make_decl_rtl (fdecl);
        }
-      return fdecl;
     }
-
-  if (flag_indirect_dispatch)
+  else
     {
-      tree table_index 
-       = build_int_cst (NULL_TREE, get_symbol_table_index 
-                        (fdecl, &TYPE_ATABLE_METHODS (output_class)));
-      tree field_address
-       = build4 (ARRAY_REF, 
-                 TREE_TYPE (TREE_TYPE (TYPE_ATABLE_DECL (output_class))), 
-                 TYPE_ATABLE_DECL (output_class), table_index,
-                 NULL_TREE, NULL_TREE);
-      field_address = convert (build_pointer_type (TREE_TYPE (fdecl)),
-                              field_address);
-      return fold (build1 (INDIRECT_REF, TREE_TYPE (fdecl), 
-                          field_address));
-    }
-  else  
-    {
-      /* Compile as:
-       *(FTYPE*)build_class_ref(FCLASS)->fields[INDEX].info.addr */
-      tree ref = build_class_ref (fclass);
-      tree fld;
-      int field_index = 0;
-      ref = build1 (INDIRECT_REF, class_type_node, ref);
-      ref = build3 (COMPONENT_REF, field_ptr_type_node, ref,
-                   lookup_field (&class_type_node, fields_ident),
-                   NULL_TREE);
-
-      for (fld = TYPE_FIELDS (fclass); ; fld = TREE_CHAIN (fld))
-       {
-         if (fld == fdecl)
-           break;
-         if (fld == NULL_TREE)
-           fatal_error ("field '%s' not found in class",
-                        IDENTIFIER_POINTER (DECL_NAME (fdecl)));
-         if (FIELD_STATIC (fld))
-           field_index++;
-       }
-      field_index *= int_size_in_bytes (field_type_node);
-      ref = fold (build2 (PLUS_EXPR, field_ptr_type_node,
-                         ref, build_int_cst (NULL_TREE, field_index)));
-      ref = build1 (INDIRECT_REF, field_type_node, ref);
-      ref = build3 (COMPONENT_REF, field_info_union_node,
-                   ref, lookup_field (&field_type_node, info_ident), 
-                   NULL_TREE);
-      ref = build3 (COMPONENT_REF, ptr_type_node,
-                   ref, TREE_CHAIN (TYPE_FIELDS (field_info_union_node)),
-                   NULL_TREE);
-      ref = build1 (NOP_EXPR, build_pointer_type (TREE_TYPE (fdecl)), ref);
-      return fold (build1 (INDIRECT_REF, TREE_TYPE(fdecl), ref));
-    }
+      /* Generate a CONSTANT_FieldRef for FDECL in the constant pool
+        and a class local static variable CACHE_ENTRY, then
+      
+      *(fdecl **)((__builtin_expect (cache_entry == null, false)) 
+                 ? cache_entry = _Jv_ResolvePoolEntry (output_class, cpool_index)
+                 : cache_entry)
+
+      This can mostly be optimized away, so that the usual path is a
+      load followed by a test and branch.  _Jv_ResolvePoolEntry is
+      only called once for each constant pool entry.
+
+      There is an optimization that we don't do: at the start of a
+      method, create a local copy of CACHE_ENTRY and use that instead.
+
+      */
+
+      int cpool_index = alloc_constant_fieldref (output_class, fdecl);
+      tree cache_entry = build_fieldref_cache_entry (cpool_index, fdecl);
+      tree test 
+       = build3 (CALL_EXPR, boolean_type_node, 
+                 build_address_of (built_in_decls[BUILT_IN_EXPECT]),
+                 tree_cons (NULL_TREE, build2 (EQ_EXPR, boolean_type_node,
+                                               cache_entry, null_pointer_node),
+                            build_tree_list (NULL_TREE, boolean_false_node)),
+                 NULL_TREE);
+      tree cpool_index_cst = build_int_cst (NULL_TREE, cpool_index);
+      tree init
+       = build3 (CALL_EXPR, ptr_type_node,
+                 build_address_of (soft_resolvepoolentry_node),
+                 tree_cons (NULL_TREE, build_class_ref (output_class),
+                            build_tree_list (NULL_TREE, cpool_index_cst)),
+                 NULL_TREE);
+      init = build2 (MODIFY_EXPR, ptr_type_node, cache_entry, init);
+      init = build3 (COND_EXPR, ptr_type_node, test, init, cache_entry);
+      init = fold_convert (build_pointer_type (TREE_TYPE (fdecl)), init);
+      fdecl = build1 (INDIRECT_REF, TREE_TYPE (fdecl), init);
+    }
+  return fdecl;
 }
 
 int
index a5d9622..ff58b87 100644 (file)
@@ -356,6 +356,41 @@ alloc_name_constant (int tag, tree name)
   return find_tree_constant (outgoing_cpool, tag, name);
 }
 
+/* Create a constant pool entry for a name_and_type.  This one has '.'
+   rather than '/' because it isn't going into a class file, it's
+   going into a compiled object.  We don't use the '/' separator in
+   compiled objects.  */
+
+static int
+find_name_and_type_constant_tree (CPool *cpool, tree name, tree type)
+{
+  int name_index = find_utf8_constant (cpool, name);
+  int type_index 
+    = find_utf8_constant (cpool, 
+                         identifier_subst (build_java_signature (type), 
+                                           "", '/', '.', ""));
+  return find_constant1 (cpool, CONSTANT_NameAndType,
+                        (name_index << 16) | type_index);
+}
+
+/* Look for a field ref that matches DECL in the constant pool of
+   CLASS.  
+   Return the index of the entry.  */
+
+int
+alloc_constant_fieldref (tree class, tree decl)
+{
+  CPool *outgoing_cpool = cpool_for_class (class);
+  int class_index 
+    = find_tree_constant (outgoing_cpool, CONSTANT_Class, 
+                         DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl))));
+  int name_type_index
+    = find_name_and_type_constant_tree (outgoing_cpool, DECL_NAME (decl), 
+                                       TREE_TYPE (decl));
+  return find_constant1 (outgoing_cpool, CONSTANT_Fieldref,
+                        (class_index << 16) | name_type_index);
+}
+
 /* Build an identifier for the internal name of reference type TYPE. */
 
 tree
@@ -442,14 +477,33 @@ build_constants_constructor (void)
   tree data_list = NULL_TREE;
   int i;
   for (i = outgoing_cpool->count;  --i > 0; )
-    {
-      tags_list
-       = tree_cons (NULL_TREE, get_tag_node (outgoing_cpool->tags[i]),
-                    tags_list);
-      data_list
-       = tree_cons (NULL_TREE, build_utf8_ref (outgoing_cpool->data[i].t),
-                    data_list);
-    }
+    switch (outgoing_cpool->tags[i])
+      {
+      case CONSTANT_Fieldref:
+      case CONSTANT_NameAndType:
+       {
+         jword temp = outgoing_cpool->data[i].w;
+
+         tags_list
+           = tree_cons (NULL_TREE, 
+                        build_int_cst (NULL_TREE, outgoing_cpool->tags[i]),
+                        tags_list);
+         data_list
+           = tree_cons (NULL_TREE, 
+                        fold_convert (ptr_type_node, 
+                                      (build_int_cst (NULL_TREE, temp))),
+                        data_list);
+       }
+       break;
+      default:
+       tags_list
+         = tree_cons (NULL_TREE, get_tag_node (outgoing_cpool->tags[i]),
+                      tags_list);
+       data_list
+         = tree_cons (NULL_TREE, build_utf8_ref (outgoing_cpool->data[i].t),
+                      data_list);
+       break;
+      }
   if (outgoing_cpool->count > 0)
     {
       tree data_decl, tags_decl, tags_type;
@@ -461,7 +515,7 @@ build_constants_constructor (void)
       data_list = tree_cons (NULL_TREE, null_pointer_node, data_list);
   
       data_decl = build_constant_data_ref ();
-      TREE_TYPE (data_decl) = build_array_type (ptr_type_node, index_type)
+      TREE_TYPE (data_decl) = build_array_type (ptr_type_node, index_type);
       DECL_INITIAL (data_decl) = build_constructor (TREE_TYPE (data_decl),
                                                    data_list);
       DECL_SIZE (data_decl) = TYPE_SIZE (TREE_TYPE (data_decl));
index 2feac35..204a674 100644 (file)
@@ -104,6 +104,9 @@ static int uniq;
 
 static GTY(()) tree pending_local_decls;
 
+/* The decl for "_Jv_ResolvePoolEntry".  */
+tree soft_resolvepoolentry_node;
+
 #if defined(DEBUG_JAVA_BINDING_LEVELS)
 int binding_depth = 0;
 int is_class_level = 0;
@@ -1015,7 +1018,13 @@ java_init_decl_processing (void)
                                          build_function_type (void_type_node,
                                                               t),
                                          0, NOT_BUILT_IN, NULL, NULL_TREE);
-
+  t = tree_cons (NULL_TREE, class_ptr_type,
+                tree_cons (NULL_TREE, int_type_node, endlink));
+  soft_resolvepoolentry_node 
+    = builtin_function ("_Jv_ResolvePoolEntry", 
+                       build_function_type (ptr_type_node, t),
+                       0,NOT_BUILT_IN, NULL, NULL_TREE);
+  DECL_IS_PURE (soft_resolvepoolentry_node) = 1;
   throw_node = builtin_function ("_Jv_Throw",
                                 build_function_type (void_type_node, t),
                                 0, NOT_BUILT_IN, NULL, NULL_TREE);
index ae1055e..3cc33ae 100644 (file)
@@ -2715,7 +2715,8 @@ expand_java_field_op (int is_static, int is_putting, int field_ref_index)
     }
 
   field_ref = build_field_ref (field_ref, self_type, field_name);
-  if (is_static)
+  if (is_static
+      && ! flag_indirect_dispatch)
     field_ref = build_class_init (self_type, field_ref);
   if (is_putting)
     {
@@ -3484,7 +3485,8 @@ maybe_adjust_start_pc (struct JCF *jcf, int code_offset,
    For method invocation, we modify the arguments so that a
    left-to-right order evaluation is performed. Saved expressions
    will, in CALL_EXPR order, be reused when the call will be expanded.
-*/
+
+   We also promote outgoing args if needed.  */
 
 tree
 force_evaluation_order (tree node)
@@ -3518,6 +3520,15 @@ force_evaluation_order (tree node)
       /* This reverses the evaluation order. This is a desired effect. */
       for (cmp = NULL_TREE; arg; arg = TREE_CHAIN (arg))
        {
+         /* Promote types smaller than integer.  This is required by
+            some ABIs.  */
+         tree type = TREE_TYPE (TREE_VALUE (arg));
+         if (targetm.calls.promote_prototypes (type)
+             && INTEGRAL_TYPE_P (type)
+             && INT_CST_LT_UNSIGNED (TYPE_SIZE (type),
+                                     TYPE_SIZE (integer_type_node)))
+           TREE_VALUE (arg) = fold_convert (integer_type_node, TREE_VALUE (arg));
+
          tree saved = save_expr (force_evaluation_order (TREE_VALUE (arg)));
          cmp = (cmp == NULL_TREE ? saved :
                 build2 (COMPOUND_EXPR, void_type_node, cmp, saved));
index 036fb83..a55e9ab 100644 (file)
@@ -686,6 +686,9 @@ extern GTY(()) tree java_global_trees[JTI_MAX];
 #define wfl_operator \
   java_global_trees[JTI_WFL_OPERATOR]
 
+/* The decl for "_Jv_ResolvePoolEntry".  */
+extern GTY(()) tree soft_resolvepoolentry_node;
+
 extern const char *cyclic_inheritance_report;
 
 struct lang_identifier GTY(())
@@ -1285,6 +1288,7 @@ extern tree get_method_index (tree decl);
 extern void make_class_data (tree);
 extern void register_class (void);
 extern int alloc_name_constant (int, tree);
+extern int alloc_constant_fieldref (tree, tree);
 extern void emit_register_classes (tree *);
 extern tree emit_symbol_table (tree, tree, tree, tree, tree, int);
 extern void lang_init_source (int);