From e6b7893e348494a1fe572cc149d5044998d55a19 Mon Sep 17 00:00:00 2001
From: Andrew Haley <aph@redhat.com>
Date: Fri, 31 Mar 2006 11:43:43 +0000
Subject: [PATCH] re PR libgcj/26858 (NullPointerException not generated for
 large classes...)

2006-03-30  Andrew Haley  <aph@redhat.com>

        PR java/26858
        * lang.c (java_attribute_table): New.
        (LANG_HOOKS_ATTRIBUTE_TABLE): Define.
        * expr.c (build_field_ref): Add a null pointer check for all
        fields of offset > 4k.  Don't do so for accesses via the this
        pointer, which we know can never be null.
        * class.c (build_java_method_type): Mark arg 1 of all nonstatic
        methods nonnull.

From-SVN: r112574
---
 gcc/java/ChangeLog | 11 +++++++++++
 gcc/java/class.c   | 12 +++++++++++-
 gcc/java/expr.c    | 30 ++++++++++++++++++++++++++----
 gcc/java/lang.c    | 11 +++++++++++
 4 files changed, 59 insertions(+), 5 deletions(-)

diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog
index 6d705fb54313..e40d443b2142 100644
--- a/gcc/java/ChangeLog
+++ b/gcc/java/ChangeLog
@@ -1,3 +1,14 @@
+2006-03-30  Andrew Haley  <aph@redhat.com>
+
+	PR java/26858
+	* lang.c (java_attribute_table): New.
+	(LANG_HOOKS_ATTRIBUTE_TABLE): Define.
+	* expr.c (build_field_ref): Add a null pointer check for all
+	fields of offset > 4k.  Don't do so for accesses via the this
+	pointer, which we know can never be null.
+	* class.c (build_java_method_type): Mark arg 1 of all nonstatic
+	methods nonnull.
+
 2006-03-30  Carlos O'Donell  <carlos@codesourcery.com>
 
 	* Make-lang.in: Rename docdir to gcc_docdir.
diff --git a/gcc/java/class.c b/gcc/java/class.c
index bce16779b757..a6074518f59f 100644
--- a/gcc/java/class.c
+++ b/gcc/java/class.c
@@ -681,7 +681,17 @@ build_java_method_type (tree fntype, tree this_class, int access_flags)
 {
   if (access_flags & ACC_STATIC)
     return fntype;
-  return build_method_type (this_class, fntype);
+  fntype = build_method_type (this_class, fntype);
+
+  /* We know that arg 1 of every nonstatic method is non-null; tell
+     the back-end so.  */
+  TYPE_ATTRIBUTES (fntype) = (tree_cons 
+			      (get_identifier ("nonnull"),
+			       tree_cons (NULL_TREE, 
+					  build_int_cst (NULL_TREE, 1),
+					  NULL_TREE),
+			       TYPE_ATTRIBUTES (fntype)));
+  return fntype;
 }
 
 tree
diff --git a/gcc/java/expr.c b/gcc/java/expr.c
index 785ccc485bf6..c178552904dd 100644
--- a/gcc/java/expr.c
+++ b/gcc/java/expr.c
@@ -130,6 +130,10 @@ static GTY(()) tree quick_stack;
 /* A free-list of unused permanent TREE_LIST nodes.  */
 static GTY((deletable)) tree tree_list_free_list;
 
+/* The physical memory page size used in this computer.  See
+   build_field_ref().  */
+static GTY(()) tree page_size;
+
 /* The stack pointer of the Java virtual machine.
    This does include the size of the quick_stack. */
 
@@ -1678,11 +1682,28 @@ build_field_ref (tree self_value, tree self_class, tree name)
     }
   else
     {
-      int check = (flag_check_references
-		   && ! (DECL_P (self_value)
-			 && DECL_NAME (self_value) == this_identifier_node));
-
       tree base_type = promote_type (base_class);
+
+      /* CHECK is true if self_value is not the this pointer.  */
+      int check = (! (DECL_P (self_value)
+		      && DECL_NAME (self_value) == this_identifier_node));
+
+      /* Determine whether a field offset from NULL will lie within
+	 Page 0: this is necessary on those GNU/Linux/BSD systems that
+	 trap SEGV to generate NullPointerExceptions.  
+
+	 We assume that Page 0 will be mapped with NOPERM, and that
+	 memory may be allocated from any other page, so only field
+	 offsets < pagesize are guaratneed to trap.  We also assume
+	 the smallest page size we'll encounter is 4k bytes.  */
+      if (check && ! flag_check_references && ! flag_indirect_dispatch)
+	{
+	  tree field_offset = byte_position (field_decl);
+	  if (! page_size)
+	    page_size = size_int (4096); 	      
+	  check = ! INT_CST_LT_UNSIGNED (field_offset, page_size);
+	}
+
       if (base_type != TREE_TYPE (self_value))
 	self_value = fold_build1 (NOP_EXPR, base_type, self_value);
       if (! flag_syntax_only && flag_indirect_dispatch)
@@ -1708,6 +1729,7 @@ build_field_ref (tree self_value, tree self_class, tree name)
 			field_offset);
 	  
 	  field_offset = fold (convert (sizetype, field_offset));
+	  self_value = java_check_reference (self_value, check);
 	  address 
 	    = fold_build2 (PLUS_EXPR, 
 			   build_pointer_type (TREE_TYPE (field_decl)),
diff --git a/gcc/java/lang.c b/gcc/java/lang.c
index e1f822ea3a31..58f23e9e0e52 100644
--- a/gcc/java/lang.c
+++ b/gcc/java/lang.c
@@ -108,6 +108,14 @@ const char *const tree_code_name[] = {
 };
 #undef DEFTREECODE
 
+/* Table of machine-independent attributes.  */
+const struct attribute_spec java_attribute_table[] =
+{
+ { "nonnull",                0, -1, false, true, true,
+			      NULL },
+  { NULL,                     0, 0, false, false, false, NULL }
+};
+
 /* Used to avoid printing error messages with bogus function
    prototypes.  Starts out false.  */
 static bool inhibit_error_function_printing;
@@ -213,6 +221,9 @@ struct language_function GTY(())
 #undef LANG_HOOKS_SET_DECL_ASSEMBLER_NAME
 #define LANG_HOOKS_SET_DECL_ASSEMBLER_NAME java_mangle_decl
 
+#undef LANG_HOOKS_ATTRIBUTE_TABLE
+#define LANG_HOOKS_ATTRIBUTE_TABLE java_attribute_table
+
 /* Each front end provides its own.  */
 const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
 
-- 
GitLab