Andrew Haley - Re: Reduce size of indirect-dispatch executables (original) (raw)

This is the mail archive of the gcc-patches@gcc.gnu.orgmailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Andrew Haley writes:

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.

This is a re-written version of the patch. It's slightly more efficient and considerably more sane.

Andrew.

2007-02-02 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.
(build_constant_data_ref): Move special-case code for
flag_indirect_classes here from build_ref_from_constant_pool.
* 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: java/class.c

--- java/class.c (revision 121464) +++ java/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. / @@ -1004,6 +1008,45 @@ return decl; } +/ Create a local variable that holds the the current class$. / + +void +cache_this_class_ref (tree fndecl) +{ + if (optimize) + { + tree classdollar_field; + if (flag_indirect_classes) + classdollar_field = build_classdollar_field (output_class); + else + classdollar_field = build_static_class_ref (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)); + } + else + this_classdollar = build_classdollar_field (output_class); + + /
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. */ @@ -1023,7 +1066,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); @@ -2447,7 +2490,7 @@ if (TYPE_NVIRTUALS (this_class)) return;

Index: java/decl.c

--- java/decl.c (revision 121464) +++ java/decl.c (working copy) @@ -1876,22 +1876,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: java/constants.c

--- java/constants.c (revision 121464) +++ java/constants.c (working copy) @@ -36,7 +36,6 @@ static int find_tree_constant (CPool , int, tree); static int find_name_and_type_constant (CPool , tree, tree); static tree get_tag_node (int); -static tree build_constant_data_ref (void); / Set the INDEX'th constant in CPOOL to have the given TAG and VALUE. / @@ -424,14 +423,36 @@ / Return the decl of the data array of the current constant pool. / -static tree -build_constant_data_ref (void) +tree +build_constant_data_ref (bool indirect) { - tree decl = TYPE_CPOOL_DATA_REF (output_class); + if (indirect) + { + tree d; + 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); - if (decl == 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; + + return d; + } + else { - tree type; + tree type, decl; tree decl_name = mangled_classname ("CD", output_class); / Build a type with unspecified bounds. The will make sure @@ -446,10 +467,9 @@ decl = build_decl (VAR_DECL, decl_name, type); TREE_STATIC (decl) = 1; - TYPE_CPOOL_DATA_REF (output_class) = decl; - } - return decl; + return decl; + } } / Get the pointer value at the INDEX'th element of the constant pool. / @@ -457,27 +477,13 @@ tree build_ref_from_constant_pool (int index) { - 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; - } + tree i; + tree d = TYPE_CPOOL_DATA_REF (output_class); + + if (d == NULL_TREE) + d = build_constant_data_ref (flag_indirect_classes); + + i = build_int_cst (NULL_TREE, index); d = build4 (ARRAY_REF, TREE_TYPE (TREE_TYPE (d)), d, i, NULL_TREE, NULL_TREE); TREE_INVARIANT (d) = 1; @@ -557,7 +563,7 @@ tags_list = tree_cons (NULL_TREE, get_tag_node (0), tags_list); data_list = tree_cons (NULL_TREE, null_pointer_node, data_list);
- data_decl = build_constant_data_ref (); + data_decl = build_constant_data_ref (false); TREE_TYPE (data_decl) = build_array_type (ptr_type_node, index_type); DECL_INITIAL (data_decl) = build_constructor_from_list (TREE_TYPE (data_decl), data_list); Index: java/expr.c

--- java/expr.c (revision 121464) +++ java/expr.c (working copy) @@ -83,6 +83,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 void cache_cpool_data_ref (void); static GTY(()) tree operand_type[59]; @@ -3151,6 +3152,8 @@ return; promote_arguments (); + cache_this_class_ref (method); + cache_cpool_data_ref (); / Translate bytecodes. / linenumber_pointer = linenumber_table; @@ -3223,7 +3226,7 @@ PC = process_jvm_instruction (PC, byte_ops, length); maybe_poplevels (PC); } / for */

@@ -3791,4 +3794,27 @@ } } +/* Create a local variable that points to the constant pool. */ + +static void +cache_cpool_data_ref (void) +{ + if (optimize) + { + tree cpool; + tree d = build_constant_data_ref (flag_indirect_classes); + tree 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; + } +} + #include "gt-java-expr.h" Index: java/java-tree.h

--- java/java-tree.h (revision 121464) +++ java/java-tree.h (working copy) @@ -1129,10 +1129,12 @@ 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); extern tree build_constants_constructor (void); +extern tree build_constant_data_ref (bool); extern tree build_ref_from_constant_pool (int); extern tree build_utf8_ref (tree); extern tree ident_subst (const char *, int, const char *, int, int,


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]