aboutsummaryrefslogtreecommitdiff
path: root/gcc/java/expr.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/java/expr.c')
-rw-r--r--gcc/java/expr.c91
1 files changed, 85 insertions, 6 deletions
diff --git a/gcc/java/expr.c b/gcc/java/expr.c
index b417bac..e1a5296 100644
--- a/gcc/java/expr.c
+++ b/gcc/java/expr.c
@@ -1036,17 +1036,96 @@ expand_java_NEW (type)
NULL_TREE));
}
+/* This returns an expression which will extract the class of an
+ object. */
+
+tree
+build_get_class (value)
+ tree value;
+{
+ tree class_field = lookup_field (&dtable_type, get_identifier ("class"));
+ tree vtable_field = lookup_field (&object_type_node,
+ get_identifier ("vtable"));
+ return build (COMPONENT_REF, class_ptr_type,
+ build1 (INDIRECT_REF, dtable_type,
+ build (COMPONENT_REF, dtable_ptr_type,
+ build1 (INDIRECT_REF, object_type_node, value),
+ vtable_field)),
+ class_field);
+}
+
+/* This builds the tree representation of the `instanceof' operator.
+ It tries various tricks to optimize this in cases where types are
+ known. */
+
+tree
+build_instanceof (value, type)
+ tree value, type;
+{
+ tree expr;
+ tree itype = TREE_TYPE (TREE_TYPE (soft_instanceof_node));
+ tree valtype = TREE_TYPE (TREE_TYPE (value));
+ tree valclass = TYPE_NAME (valtype);
+ tree klass;
+
+ /* When compiling from bytecode, we need to ensure that TYPE has
+ been loaded. */
+ if (CLASS_P (type) && ! CLASS_LOADED_P (type))
+ {
+ load_class (type, 1);
+ if (! TYPE_SIZE (type) || TREE_CODE (TYPE_SIZE (type)) == ERROR_MARK)
+ return error_mark_node;
+ }
+ klass = TYPE_NAME (type);
+
+ if (type == object_type_node || inherits_from_p (valtype, type))
+ {
+ /* Anything except `null' is an instance of Object. Likewise,
+ if the object is known to be an instance of the class, then
+ we only need to check for `null'. */
+ expr = build (COND_EXPR, itype,
+ value,
+ boolean_true_node, boolean_false_node);
+ }
+ else if (! CLASS_INTERFACE (valclass)
+ && ! CLASS_INTERFACE (klass)
+ && ! inherits_from_p (type, valtype)
+ && (CLASS_FINAL (klass)
+ || ! inherits_from_p (valtype, type)))
+ {
+ /* The classes are from different branches of the derivation
+ tree, so we immediately know the answer. */
+ expr = boolean_false_node;
+ }
+ else if (CLASS_FINAL (klass))
+ {
+ tree save = save_expr (value);
+ expr = build (COND_EXPR, itype,
+ save,
+ build (EQ_EXPR, itype,
+ build_get_class (save),
+ build_class_ref (type)),
+ boolean_false_node);
+ }
+ else
+ {
+ expr = build (CALL_EXPR, itype,
+ build_address_of (soft_instanceof_node),
+ tree_cons (NULL_TREE, value,
+ build_tree_list (NULL_TREE,
+ build_class_ref (type))),
+ NULL_TREE);
+ }
+ TREE_SIDE_EFFECTS (expr) = TREE_SIDE_EFFECTS (value);
+ return expr;
+}
+
static void
expand_java_INSTANCEOF (type)
tree type;
{
tree value = pop_value (object_ptr_type_node);
- value = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (soft_instanceof_node)),
- build_address_of (soft_instanceof_node),
- tree_cons (NULL_TREE, value,
- build_tree_list (NULL_TREE,
- build_class_ref (type))),
- NULL_TREE);
+ value = build_instanceof (value, type);
push_value (value);
}