This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
[BC] RFC: patch for new verifier
- From: Tom Tromey <tromey at redhat dot com>
- To: Java Patch List <java-patches at gcc dot gnu dot org>
- Date: 20 Oct 2004 17:22:55 -0600
- Subject: [BC] RFC: patch for new verifier
- Reply-to: tromey at redhat dot com
Here's the patch I'm using to compile things using the new verifier.
With this in place we can compile things without crashing. I'm not
checking it in; it needs more work. But, I wanted people to see it in
case they wanted to try it out.
Tom
Index: ChangeLog
from Tom Tromey <tromey@redhat.com>
* expr.c (invoke_build_dtable): Don't pass object_type_node as
expression argument to build_java_indirect_ref.
(build_java_check_indexed_type): Do nothing.
(build_java_arraystore_check): Handle case where array doesn't
have array type.
(build_java_array_length_access): Likewise.
(expand_invoke): Handle case where interface overrides a method
from Object.
(pop_type_0): Always succeed for reference types.
Index: expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/expr.c,v
retrieving revision 1.185.2.15
diff -u -r1.185.2.15 expr.c
--- expr.c 18 Oct 2004 22:06:00 -0000 1.185.2.15
+++ expr.c 20 Oct 2004 23:09:39 -0000
@@ -341,20 +341,32 @@
}
if (INTEGRAL_TYPE_P (type) && INTEGRAL_TYPE_P (t)
&& TYPE_PRECISION (type) <= 32 && TYPE_PRECISION (t) <= 32)
- return t;
+ return t;
if (TREE_CODE (type) == POINTER_TYPE && TREE_CODE (t) == POINTER_TYPE)
{
- if (type == ptr_type_node || type == object_ptr_type_node)
- return t;
- else if (t == ptr_type_node) /* Special case for null reference. */
- return type;
- /* This is a kludge, but matches what Sun's verifier does.
- It can be tricked, but is safe as long as type errors
- (i.e. interface method calls) are caught at run-time. */
- else if (CLASS_INTERFACE (TYPE_NAME (TREE_TYPE (type))))
- return object_ptr_type_node;
- else if (can_widen_reference_to (t, type))
- return t;
+ if (flag_new_verifier)
+ {
+ /* Since the verifier has already run, we know that any
+ types we see will be compatible. In BC mode, this fact
+ may be checked at runtime, but if that is so then we can
+ assume its truth here as well. So, we always succeed
+ here, with the expected type. */
+ return type;
+ }
+ else
+ {
+ if (type == ptr_type_node || type == object_ptr_type_node)
+ return t;
+ else if (t == ptr_type_node) /* Special case for null reference. */
+ return type;
+ /* This is a kludge, but matches what Sun's verifier does.
+ It can be tricked, but is safe as long as type errors
+ (i.e. interface method calls) are caught at run-time. */
+ else if (CLASS_INTERFACE (TYPE_NAME (TREE_TYPE (type))))
+ return object_ptr_type_node;
+ else if (can_widen_reference_to (t, type))
+ return t;
+ }
}
if (! flag_verify_invocations && flag_indirect_dispatch
@@ -873,7 +885,12 @@
NULL_TREE, NULL_TREE);
if (!is_array_type_p (type))
- abort ();
+ {
+ /* With the new verifier, we will see an ordinary pointer type
+ here. In this case, we just use an arbitrary array type. */
+ array_type = build_java_array_type (object_ptr_type_node, -1);
+ type = promote_type (array_type);
+ }
length = java_array_type_length (type);
if (length >= 0)
@@ -934,6 +951,13 @@
tree ref;
tree array_type = TREE_TYPE (TREE_TYPE (array));
+ if (!is_array_type_p (TREE_TYPE (array)))
+ {
+ /* With the new verifier, we will see an ordinary pointer type
+ here. In this case, we just use the correct array type. */
+ array_type = build_java_array_type (type, -1);
+ }
+
if (flag_bounds_check)
{
/* Generate:
@@ -983,11 +1007,21 @@
tree array_type_p = TREE_TYPE (array);
tree object_type = TYPE_NAME (TREE_TYPE (TREE_TYPE (object)));
- if (! is_array_type_p (array_type_p))
- abort ();
+ if (! flag_verify_invocations)
+ {
+ /* With the new verifier, we don't track precise types. FIXME:
+ performance regression here. */
+ element_type = TYPE_NAME (object_type_node);
+ }
+ else
+ {
+ if (! is_array_type_p (array_type_p))
+ abort ();
- /* Get the TYPE_DECL for ARRAY's element type. */
- element_type = TYPE_NAME (TREE_TYPE (TREE_TYPE (TREE_TYPE (array_type_p))));
+ /* Get the TYPE_DECL for ARRAY's element type. */
+ element_type
+ = TYPE_NAME (TREE_TYPE (TREE_TYPE (TREE_TYPE (array_type_p))));
+ }
if (TREE_CODE (element_type) != TYPE_DECL
|| TREE_CODE (object_type) != TYPE_DECL)
@@ -999,10 +1033,11 @@
/* No check is needed if the element type is final or is itself an array.
Also check that element_type matches object_type, since in the bytecode
compilation case element_type may be the actual element type of the array
- rather than its declared type. */
+ rather than its declared type. However, if we're doing indirect
+ dispatch, we can't do the `final' optimization. */
if (element_type == object_type
&& (TYPE_ARRAY_P (TREE_TYPE (element_type))
- || CLASS_FINAL (element_type)))
+ || (! flag_indirect_dispatch && CLASS_FINAL (element_type))))
return build1 (NOP_EXPR, array_type_p, array);
/* OBJECT might be wrapped by a SAVE_EXPR. */
@@ -1044,30 +1079,35 @@
ARRAY_NODE. This function is used to retrieve something less vague than
a pointer type when indexing the first dimension of something like [[<t>.
May return a corrected type, if necessary, otherwise INDEXED_TYPE is
- return unchanged.
- As a side effect, it also makes sure that ARRAY_NODE is an array. */
+ return unchanged. */
static tree
build_java_check_indexed_type (tree array_node, tree indexed_type)
{
tree elt_type;
- if (!is_array_type_p (TREE_TYPE (array_node)))
- abort ();
+ /* We used to check to see if ARRAY_NODE really had array type.
+ However, with the new verifier, this is not necessary, as we know
+ that the object will be an array of the appropriate type. */
- elt_type = (TYPE_ARRAY_ELEMENT (TREE_TYPE (TREE_TYPE (array_node))));
+ return indexed_type;
- if (indexed_type == ptr_type_node )
- return promote_type (elt_type);
+/* if (!is_array_type_p (TREE_TYPE (array_node))) */
+/* abort (); */
- /* BYTE/BOOLEAN store and load are used for both type */
- if (indexed_type == byte_type_node && elt_type == boolean_type_node )
- return boolean_type_node;
+/* elt_type = (TYPE_ARRAY_ELEMENT (TREE_TYPE (TREE_TYPE (array_node)))); */
- if (indexed_type != elt_type )
- abort ();
- else
- return indexed_type;
+/* if (indexed_type == ptr_type_node) */
+/* return promote_type (elt_type); */
+
+/* /\* BYTE/BOOLEAN store and load are used for both type *\/ */
+/* if (indexed_type == byte_type_node && elt_type == boolean_type_node) */
+/* return boolean_type_node; */
+
+/* if (indexed_type != elt_type ) */
+/* abort (); */
+/* else */
+/* return indexed_type; */
}
/* newarray triggers a call to _Jv_NewPrimArray. This function should be
@@ -2075,9 +2115,9 @@
argument is an array then get the dispatch table of the class
Object rather than the one from the objectref. */
objectref = (is_invoke_interface
- && is_array_type_p (TREE_TYPE (TREE_VALUE (arg_list))) ?
- object_type_node : TREE_VALUE (arg_list));
-
+ && is_array_type_p (TREE_TYPE (TREE_VALUE (arg_list)))
+ ? build_class_ref (object_type_node) : TREE_VALUE (arg_list));
+
if (dtable_ident == NULL_TREE)
dtable_ident = get_identifier ("vtable");
dtable = build_java_indirect_ref (object_type_node, objectref,
@@ -2238,7 +2278,8 @@
{
tree method_signature
= COMPONENT_REF_SIGNATURE(¤t_jcf->cpool, method_ref_index);
- tree method_name = COMPONENT_REF_NAME (¤t_jcf->cpool, method_ref_index);
+ tree method_name = COMPONENT_REF_NAME (¤t_jcf->cpool,
+ method_ref_index);
tree self_type
= get_class_constant (current_jcf,
COMPONENT_REF_CLASS_INDEX(¤t_jcf->cpool,
@@ -2262,12 +2303,22 @@
else
method = lookup_java_method (self_type, method_name, method_signature);
- /* We've found a method in an interface, but this isn't an interface call. */
+ /* We've found a method in an interface, but this isn't an interface
+ call. */
if (opcode != OPCODE_invokeinterface
&& method
&& (CLASS_INTERFACE (TYPE_NAME (DECL_CONTEXT (method)))))
method = NULL_TREE;
+ /* We've found a non-interface method but we are making an
+ interface call. This can happen if the interface overrides a
+ method in Object. */
+ if (! flag_verify_invocations
+ && opcode == OPCODE_invokeinterface
+ && method
+ && ! CLASS_INTERFACE (TYPE_NAME (DECL_CONTEXT (method))))
+ method = NULL_TREE;
+
if (method == NULL_TREE)
{
if (flag_verify_invocations || ! flag_indirect_dispatch)
@@ -2287,7 +2338,8 @@
flags |= ACC_INTERFACE;
CLASS_INTERFACE (TYPE_NAME (self_type)) = 1;
}
- method = add_method (self_type, flags, method_name, method_signature);
+ method = add_method (self_type, flags, method_name,
+ method_signature);
DECL_ARTIFICIAL (method) = 1;
METHOD_DUMMY (method) = 1;
layout_class_method (self_type, NULL,