Reduce size of indirect-dispatch executables

Andrew Haley aph@redhat.com
Wed Jan 17 10:37:00 GMT 2007


I noticed that we were repeatedly reloading from memory this.class and
this.class.constants.  It makes far more sense to read these values at
the start of a method, and that is what this patch does.  It reduces
the text size of 32-bit indirect-dispatch executables by 1.4% and
64-bit by 1.3%.

We need a more general patch to hoist invariants in gcj -- there are a
lot of these -- but this is a good start.

Andrew.


2007-01-16  Andrew Haley  <aph@redhat.com>

	* expr.c (expand_byte_code): Call cache_this_class_ref() and
	cache_cpool_data_ref().
	Set TYPE_CPOOL_DATA_REF.
	(cache_cpool_data_ref): New function.
	* constants.c (build_ref_from_constant_pool): Remove special-case
	code for flag_indirect_classes.
	* decl.c (finish_method): Move class initialization from here to
	cache_this_class_ref.
	* class.c (cache_this_class_ref): New function.
	(build_class_ref): Use this_classdollar to get the
	current class$.

Index: class.c
===================================================================
--- class.c	(revision 120621)
+++ class.c	(working copy)
@@ -110,6 +110,10 @@
 
 static GTY(()) VEC(tree,gc) *registered_class;
 
+/* A tree that returns the address of the class$ of the class
+   currently being compiled.  */
+static GTY(()) tree this_classdollar;
+
 /* Return the node that most closely represents the class whose name
    is IDENT.  Start the search from NODE (followed by its siblings).
    Return NULL if an appropriate node does not exist.  */
@@ -1031,6 +1035,35 @@
   return decl;
 }
 
+/* Create a local variable that holds the the current class$.  */
+
+void
+cache_this_class_ref (tree fndecl)
+{
+  tree classdollar_field = build_classdollar_field (output_class);
+  this_classdollar = build_decl (VAR_DECL, NULL_TREE, 
+				 TREE_TYPE (classdollar_field));
+  
+  java_add_local_var (this_classdollar);
+  java_add_stmt (build2 (MODIFY_EXPR, TREE_TYPE (this_classdollar), 
+			 this_classdollar, classdollar_field));
+
+  /* Prepend class initialization for static methods reachable from
+     other classes.  */
+  if (METHOD_STATIC (fndecl)
+      && (! METHOD_PRIVATE (fndecl)
+          || INNER_CLASS_P (DECL_CONTEXT (fndecl)))
+      && ! DECL_CLINIT_P (fndecl)
+      && ! CLASS_INTERFACE (TYPE_NAME (DECL_CONTEXT (fndecl))))
+    {
+      tree init = build3 (CALL_EXPR, void_type_node,
+			  build_address_of (soft_initclass_node),
+			  build_tree_list (NULL_TREE, this_classdollar),
+			  NULL_TREE);
+      java_add_stmt (init);
+    }
+}
+
 /* Build a reference to the class TYPE.
    Also handles primitive types and array types. */
 
@@ -1050,7 +1083,7 @@
 	return build_indirect_class_ref (type);
 
       if (type == output_class && flag_indirect_classes)
-	return build_classdollar_field (type);
+	return this_classdollar;
       
       if (TREE_CODE (type) == RECORD_TYPE)
 	return build_static_class_ref (type);
@@ -2537,7 +2570,7 @@
 
   if (TYPE_NVIRTUALS (this_class))
     return;
-
+  
   super_class = CLASSTYPE_SUPER (this_class);
 
   if (super_class)
Index: decl.c
===================================================================
--- decl.c	(revision 120621)
+++ decl.c	(working copy)
@@ -2001,22 +2001,6 @@
 		    build2 (TRY_FINALLY_EXPR, void_type_node, *tp, exit));
     }
 
-  /* Prepend class initialization for static methods reachable from
-     other classes.  */
-  if (METHOD_STATIC (fndecl)
-      && (! METHOD_PRIVATE (fndecl)
-          || INNER_CLASS_P (DECL_CONTEXT (fndecl)))
-      && ! DECL_CLINIT_P (fndecl)
-      && ! CLASS_INTERFACE (TYPE_NAME (DECL_CONTEXT (fndecl))))
-    {
-      tree clas = DECL_CONTEXT (fndecl);
-      tree init = build3 (CALL_EXPR, void_type_node,
-			  build_address_of (soft_initclass_node),
-			  build_tree_list (NULL_TREE, build_class_ref (clas)),
-			  NULL_TREE);
-      *tp = build2 (COMPOUND_EXPR, TREE_TYPE (*tp), init, *tp);
-    }
-
   /* Convert function tree to GENERIC prior to inlining.  */
   java_genericize (fndecl);
 
Index: constants.c
===================================================================
--- constants.c	(revision 120621)
+++ constants.c	(working copy)
@@ -448,7 +448,7 @@
       TREE_STATIC (decl) = 1;
       TYPE_CPOOL_DATA_REF (output_class) = decl;
     }
-
+  
   return decl;
 }
 
@@ -459,25 +459,6 @@
 {
   tree d = build_constant_data_ref ();
   tree i = build_int_cst (NULL_TREE, index);
-  if (flag_indirect_classes)
-    {
-      tree decl = build_class_ref (output_class);
-      tree klass = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (decl)),
-			   decl);
-      tree constants = build3 (COMPONENT_REF, 
-			       TREE_TYPE (constants_field_decl_node), klass,
-			       constants_field_decl_node,
-			       NULL_TREE);
-      tree data = build3 (COMPONENT_REF, 
-			  TREE_TYPE (constants_data_field_decl_node), 
-			  constants,
-			  constants_data_field_decl_node,
-			  NULL_TREE);
-      data = fold_convert (build_pointer_type (TREE_TYPE (d)), data);
-      d = build1 (INDIRECT_REF, TREE_TYPE (d), data);
-      /* FIXME: These should be cached.  */
-      TREE_INVARIANT (d) = 1;
-    }
   d = build4 (ARRAY_REF, TREE_TYPE (TREE_TYPE (d)), d, i,
 		 NULL_TREE, NULL_TREE);
   TREE_INVARIANT (d) = 1;
Index: expr.c
===================================================================
--- expr.c	(revision 120621)
+++ expr.c	(working copy)
@@ -87,6 +87,7 @@
 static tree build_java_check_indexed_type (tree, tree); 
 static unsigned char peek_opcode_at_pc (struct JCF *, int, int);
 static void promote_arguments (void);
+static tree cache_cpool_data_ref (void);
 
 static GTY(()) tree operand_type[59];
 
@@ -3133,6 +3134,7 @@
   int dead_code_index = -1;
   unsigned char* byte_ops;
   long length = DECL_CODE_LENGTH (method);
+  tree stash;
 
   stack_pointer = 0;
   JCF_SEEK (jcf, DECL_CODE_OFFSET (method));
@@ -3159,6 +3161,8 @@
     return;
 
   promote_arguments ();
+  cache_this_class_ref (method);
+  stash = cache_cpool_data_ref ();
 
   /* Translate bytecodes.  */
   linenumber_pointer = linenumber_table;
@@ -3231,6 +3235,8 @@
       PC = process_jvm_instruction (PC, byte_ops, length);
       maybe_poplevels (PC);
     } /* for */
+
+  TYPE_CPOOL_DATA_REF (output_class) = stash;
   
   if (dead_code_index != -1)
     {
@@ -3880,4 +3886,50 @@
     }
 }
 
+/* Create a local variable that points to the constant pool.  Return
+   the previous TYPE_CPOOL_DATA_REF.  */
+
+static tree
+cache_cpool_data_ref (void)
+{
+  tree stash = TYPE_CPOOL_DATA_REF (output_class);
+
+  if (flag_indirect_classes)
+    {
+      tree d, cpool_ptr, cpool;
+      tree cpool_type = build_array_type (ptr_type_node, NULL_TREE);
+      tree decl = build_class_ref (output_class);
+      tree klass = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (decl)),
+			   decl);
+      tree constants = build3 (COMPONENT_REF, 
+			       TREE_TYPE (constants_field_decl_node), klass,
+			       constants_field_decl_node,
+			       NULL_TREE);
+      tree data = build3 (COMPONENT_REF, 
+			  TREE_TYPE (constants_data_field_decl_node), 
+			  constants,
+			  constants_data_field_decl_node,
+			  NULL_TREE);
+
+      TREE_THIS_NOTRAP (klass) = 1;
+      data = fold_convert (build_pointer_type (cpool_type), data);
+      d = build1 (INDIRECT_REF, cpool_type, data);
+      TREE_INVARIANT (d) = 1;
+
+      cpool_ptr = build_decl (VAR_DECL, NULL_TREE, 
+			      build_pointer_type (TREE_TYPE (d)));
+      java_add_local_var (cpool_ptr);
+      TREE_INVARIANT (cpool_ptr) = 1;
+      TREE_CONSTANT (cpool_ptr) = 1;
+
+      java_add_stmt (build2 (MODIFY_EXPR, TREE_TYPE (cpool_ptr), 
+			     cpool_ptr, build_address_of (d)));
+      cpool = build1 (INDIRECT_REF, TREE_TYPE (d), cpool_ptr);
+      TREE_THIS_NOTRAP (cpool) = 1;
+      TYPE_CPOOL_DATA_REF (output_class) = cpool;
+    }
+  
+  return stash;
+}
+
 #include "gt-java-expr.h"
Index: java-tree.h
===================================================================
--- java-tree.h	(revision 120621)
+++ java-tree.h	(working copy)
@@ -1162,6 +1162,7 @@
 extern int get_interface_method_index (tree, tree);
 extern tree layout_class_method (tree, tree, tree, tree);
 extern void layout_class_methods (tree);
+extern void cache_this_class_ref (tree);
 extern tree build_class_ref (tree);
 extern tree build_dtable_decl (tree);
 extern tree build_internal_class_name (tree);



More information about the Java-patches mailing list