diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog
index 922a67d43ddcbdfb8ae9b1bbf0ab251cfd058a6b..93b052684d6cdbbfc899f9c21c3c55a691b7b558 100644
--- a/gcc/java/ChangeLog
+++ b/gcc/java/ChangeLog
@@ -1,3 +1,14 @@
+2002-02-20  Per Bothner  <per@bothner.com>
+
+	* builtins.c (check_for_builtin):  New function.
+	(build_call_or_builtin):  Remove.
+	* java-tree.h:  Update accordingly.
+	* expr.c (expand_invoke):  Use build + check_for_builtin instead
+	of build_call_or_builtin.
+	* parse.y (patch_invoke):  Likewise.  This avoids needlessly creating
+	a new CALL_EXPR node, which means we don't lose the CALL_USING_SUPER
+	flag (which had caused jcf-write to incorrectly emit invokevirtual).
+
 2002-02-17  Tom Tromey  <tromey@redhat.com>
 
 	* java-tree.h (TYPE_STRICTFP): New macro.
diff --git a/gcc/java/builtins.c b/gcc/java/builtins.c
index 41ded8552bf3a7ac22cf207c7bed77e5bf849f7d..1ac37fb52f0bce5f41e97e97e2c1196ab82a606c 100644
--- a/gcc/java/builtins.c
+++ b/gcc/java/builtins.c
@@ -324,42 +324,30 @@ initialize_builtins ()
 #include "builtins.def"
 }
 
-/* Generate a method call.  If the call matches a builtin, return the
+/* If the call matches a builtin, return the
    appropriate builtin expression instead.  */
 tree
-build_call_or_builtin (method, func, method_arguments)
-     tree method, func, method_arguments;
+check_for_builtin (method, call)
+     tree method;
+     tree call;
 {
-  tree method_class = DECL_NAME (TYPE_NAME (DECL_CONTEXT (method)));
-  tree method_name = DECL_NAME (method);
-  tree method_return_type = TREE_TYPE (TREE_TYPE (method));
-  tree call = NULL_TREE;
-
-  /* Only look if we're generating object code and optimizing.  */
-  if (! flag_emit_class_files && optimize)
+  if (! flag_emit_class_files && optimize && TREE_CODE (call) == CALL_EXPR)
     {
       int i;
+      tree method_arguments = TREE_OPERAND (call, 1);
+      tree method_class = DECL_NAME (TYPE_NAME (DECL_CONTEXT (method)));
+      tree method_name = DECL_NAME (method);
+      tree method_return_type = TREE_TYPE (TREE_TYPE (method));
 
       for (i = 0; java_builtins[i].creator != NULL; ++i)
 	{
 	  if (method_class == java_builtins[i].class_name.t
 	      && method_name == java_builtins[i].method_name.t)
 	    {
-	      call = (*java_builtins[i].creator) (method_return_type,
+	      return (*java_builtins[i].creator) (method_return_type,
 						  method_arguments);
-	      break;
 	    }
 	}
     }
-
-  if (call == NULL_TREE)
-    {
-      /* Either nothing matched, or the creator function decided not
-	 to inline.  In either case, emit a call.  */
-      call = build (CALL_EXPR, method_return_type, func, method_arguments,
-		    NULL_TREE);
-      TREE_SIDE_EFFECTS (call) = 1;
-    }
-
   return call;
 }
diff --git a/gcc/java/expr.c b/gcc/java/expr.c
index a7cb59efcc590f9a942d4d4183342712afcfee98..045931079f26b0d79dd8d7adbea9039b0d56be43 100644
--- a/gcc/java/expr.c
+++ b/gcc/java/expr.c
@@ -2112,7 +2112,9 @@ expand_invoke (opcode, method_ref_index, nargs)
     }
   func = build1 (NOP_EXPR, build_pointer_type (method_type), func);
 
-  call = build_call_or_builtin (method, func, arg_list);
+  call = build (CALL_EXPR, TREE_TYPE (method_type), func, arg_list, NULL_TREE);
+  TREE_SIDE_EFFECTS (call) = 1;
+  call = check_for_builtin (method, call);
 
   if (check != NULL_TREE)
     {
diff --git a/gcc/java/java-tree.h b/gcc/java/java-tree.h
index dc5fd35e688933b56760274a2c9199d527bbad2c..8f64ef2e9a485ad71902a487d5faa52a05e9eb03 100644
--- a/gcc/java/java-tree.h
+++ b/gcc/java/java-tree.h
@@ -1090,7 +1090,7 @@ extern HOST_WIDE_INT java_array_type_length PARAMS ((tree));
 extern int read_class PARAMS ((tree));
 extern void load_class PARAMS ((tree, int));
 
-extern tree build_call_or_builtin PARAMS ((tree, tree, tree));
+extern tree check_for_builtin PARAMS ((tree, tree));
 extern void initialize_builtins PARAMS ((void));
 
 extern tree lookup_name PARAMS ((tree));
diff --git a/gcc/java/parse.y b/gcc/java/parse.y
index b3e918994782327e44e0dd5b64476cef1bfb479d..7b900cdf7ddedd237590b53b81855165963433b7 100644
--- a/gcc/java/parse.y
+++ b/gcc/java/parse.y
@@ -10692,14 +10692,10 @@ patch_invoke (patch, method, args)
       func = build1 (NOP_EXPR, build_pointer_type (TREE_TYPE (method)), func);
     }
 
-  if (TREE_CODE (patch) == CALL_EXPR)
-    patch = build_call_or_builtin (method, func, args);
-  else
-    {
-      TREE_TYPE (patch) = TREE_TYPE (TREE_TYPE (method));
-      TREE_OPERAND (patch, 0) = func;
-      TREE_OPERAND (patch, 1) = args;
-    }
+  TREE_TYPE (patch) = TREE_TYPE (TREE_TYPE (method));
+  TREE_OPERAND (patch, 0) = func;
+  TREE_OPERAND (patch, 1) = args;
+  patch = check_for_builtin (method, patch);
   original_call = patch;
 
   /* We're processing a `new TYPE ()' form. New is called and its