This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
[BC] Patch: FYI:
- From: Tom Tromey <tromey at redhat dot com>
- To: Java Patch List <java-patches at gcc dot gnu dot org>
- Date: 18 Oct 2004 17:47:05 -0600
- Subject: [BC] Patch: FYI:
- Reply-to: tromey at redhat dot com
I'm checking this in on the BC branch.
This fixes a few bugs.
* We should not set the aux_info field on the class until the class'
name is set. This is the class definer / GC contract. So, this
patch delays setting that field until later.
* We now use _Jv_AllocBytes to allocate the `throws' field. This
completes the last patch I sent.
* When resolving a method reference, we make sure the target class
has its Miranda methods added. Otherwise we can end up caching an
incorrect pointer into the target class' `methods' array.
* Likewise, when adding Miranda methods, we tell the execution engine
about this, in case it caches pointers back to the methods array.
The interpreter does this.
This lets us get much closer to starting Eclipse 3 again.
Now it looks like we're in "ordinary bug" territory, as opposed to
"brain melting VM bug" territory.
Tom
Index: ChangeLog
from Tom Tromey <tromey@redhat.com>
* interpret.cc (do_post_miranda_hook): New method.
* include/execution.h (_Jv_ExecutionEngine::post_miranda_hook):
New field.
(_Jv_CompiledEngine::do_post_miranda_hook): New method.
(_Jv_CompiledEngine): Initialize new field.
(_Jv_InterpreterEngine::do_post_miranda_hook): Declare.
(_Jv_InterpreterEngine): Initialize new field.
* link.cc (resolve_pool_entry): Put Miranda methods in target
class.
(ensure_method_table_complete): Call post_miranda_hook.
* java/lang/natVMClassLoader.cc (defineClass): Don't set class'
aux_info.
* defineclass.cc (read_one_method_attribute): Use _Jv_AllocBytes.
(parse): Set class' aux_info here.
Index: defineclass.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/defineclass.cc,v
retrieving revision 1.35.16.9
diff -u -r1.35.16.9 defineclass.cc
--- defineclass.cc 12 Oct 2004 12:32:28 -0000 1.35.16.9
+++ defineclass.cc 18 Oct 2004 23:38:19 -0000
@@ -230,7 +230,6 @@
def->size_in_bytes = -1;
def->vtable_method_count = -1;
def->engine = &_Jv_soleInterpreterEngine;
- def_interp = (_Jv_InterpClass *) def->aux_info;
}
/** and here goes the parser members defined out-of-line */
@@ -315,8 +314,13 @@
handleClassBegin (access_flags, this_class, super_class);
+ // Allocate our aux_info here, after the name is set, to fulfill our
+ // contract with the collector interface.
+ def->aux_info = (void *) _Jv_AllocBytes (sizeof (_Jv_InterpClass));
+ def_interp = (_Jv_InterpClass *) def->aux_info;
+
int interfaces_count = read2u ();
-
+
handleInterfacesBegin (interfaces_count);
for (int i = 0; i < interfaces_count; i++)
@@ -520,30 +524,20 @@
throw_class_format_error ("only one Exceptions attribute allowed per method");
int num_exceptions = read2u ();
- // We use malloc here because the GC won't scan the method
- // objects. FIXME this means a memory leak if we GC a class.
- // (Currently we never do.)
_Jv_Utf8Const **exceptions =
- (_Jv_Utf8Const **) _Jv_Malloc ((num_exceptions + 1) * sizeof (_Jv_Utf8Const *));
+ (_Jv_Utf8Const **) _Jv_AllocBytes ((num_exceptions + 1)
+ * sizeof (_Jv_Utf8Const *));
int out = 0;
_Jv_word *pool_data = def->constants.data;
for (int i = 0; i < num_exceptions; ++i)
{
- try
- {
- int ndx = read2u ();
- // JLS 2nd Ed. 4.7.5 requires that the tag not be 0.
- if (ndx != 0)
- {
- check_tag (ndx, JV_CONSTANT_Class);
- exceptions[out++] = pool_data[ndx].utf8;
- }
- }
- catch (java::lang::Throwable *exc)
+ int ndx = read2u ();
+ // JLS 2nd Ed. 4.7.5 requires that the tag not be 0.
+ if (ndx != 0)
{
- _Jv_Free (exceptions);
- throw exc;
+ check_tag (ndx, JV_CONSTANT_Class);
+ exceptions[out++] = pool_data[ndx].utf8;
}
}
exceptions[out] = NULL;
@@ -1235,7 +1229,7 @@
// ignore unknown flags
method->accflags = accflags & Modifier::ALL_FLAGS;
- // intialize...
+ // Initialize...
method->ncode = 0;
method->throws = NULL;
Index: interpret.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/interpret.cc,v
retrieving revision 1.40.18.8
diff -u -r1.40.18.8 interpret.cc
--- interpret.cc 18 Oct 2004 14:26:26 -0000 1.40.18.8
+++ interpret.cc 18 Oct 2004 23:38:19 -0000
@@ -3688,6 +3688,7 @@
throw_class_format_error (JvNewStringLatin1 (msg));
}
+
void
_Jv_InterpreterEngine::do_verify (jclass klass)
@@ -3794,4 +3795,23 @@
return result;
}
+void
+_Jv_InterpreterEngine::do_post_miranda_hook (jclass klass)
+{
+ _Jv_InterpClass *iclass = (_Jv_InterpClass *) klass->aux_info;
+ for (int i = 0; i < klass->method_count; i++)
+ {
+ // Just skip abstract methods. This is particularly important
+ // because we don't resize the interpreted_methods array when
+ // miranda methods are added to it.
+ if ((klass->methods[i].accflags
+ & java::lang::reflect::Modifier::ABSTRACT)
+ != 0)
+ continue;
+ // Miranda method additions mean that the `methods' array moves.
+ // We cache a pointer into this array, so we have to update.
+ iclass->interpreted_methods[i]->self = &klass->methods[i];
+ }
+}
+
#endif // INTERPRETER
Index: link.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/Attic/link.cc,v
retrieving revision 1.1.2.5
diff -u -r1.1.2.5 link.cc
--- link.cc 13 Oct 2004 19:44:39 -0000 1.1.2.5
+++ link.cc 18 Oct 2004 23:38:19 -0000
@@ -258,6 +258,12 @@
_Jv_Method *the_method = 0;
jclass found_class = 0;
+ // We're going to cache a pointer to the _Jv_Method object
+ // when we find it. So, to ensure this doesn't get moved from
+ // beneath us, we first put all the needed Miranda methods
+ // into the target class.
+ wait_for_state (klass, JV_STATE_LOADED);
+
// First search the class itself.
the_method = _Jv_SearchMethodInClass (owner, klass,
method_name, method_signature);
@@ -1575,7 +1581,12 @@
// unconditionally, and not just for abstract classes, to correctly
// account for cases where a class is modified to be concrete and
// still incorrectly inherits an abstract method.
+ int pre_count = klass->method_count;
add_miranda_methods (klass, klass);
+
+ // Let the execution engine know that we've added methods.
+ if (klass->method_count != pre_count)
+ klass->engine->post_miranda_hook(klass);
}
// Verify a class. Must be called with class lock held.
Index: include/execution.h
===================================================================
RCS file: /cvs/gcc/gcc/libjava/include/Attic/execution.h,v
retrieving revision 1.1.2.1
diff -u -r1.1.2.1 execution.h
--- include/execution.h 14 Sep 2004 21:12:53 -0000 1.1.2.1
+++ include/execution.h 18 Oct 2004 23:38:19 -0000
@@ -27,6 +27,7 @@
void (*create_ncode) (jclass);
_Jv_ResolvedMethod *(*resolve_method) (_Jv_Method *, jclass,
jboolean, jint);
+ void (*post_miranda_hook) (jclass);
};
// This handles all gcj-compiled code, including BC ABI.
@@ -68,6 +69,11 @@
// Not needed.
}
+ static void do_post_miranda_hook (jclass)
+ {
+ // Not needed.
+ }
+
_Jv_CompiledEngine ()
{
unregister = do_unregister;
@@ -76,6 +82,7 @@
allocate_static_fields = do_allocate_static_fields;
create_ncode = do_create_ncode;
resolve_method = do_resolve_method;
+ post_miranda_hook = do_post_miranda_hook;
}
// These operators make it so we don't have to link in libstdc++.
@@ -111,6 +118,8 @@
_Jv_UnregisterClass(klass);
}
+ static void do_post_miranda_hook (jclass);
+
_Jv_InterpreterEngine ()
{
unregister = do_unregister;
@@ -119,6 +128,7 @@
allocate_static_fields = do_allocate_static_fields;
create_ncode = do_create_ncode;
resolve_method = do_resolve_method;
+ post_miranda_hook = do_post_miranda_hook;
}
// These operators make it so we don't have to link in libstdc++.
Index: java/lang/natVMClassLoader.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/natVMClassLoader.cc,v
retrieving revision 1.1.18.4
diff -u -r1.1.18.4 natVMClassLoader.cc
--- java/lang/natVMClassLoader.cc 29 Sep 2004 21:13:24 -0000 1.1.18.4
+++ java/lang/natVMClassLoader.cc 18 Oct 2004 23:38:19 -0000
@@ -65,7 +65,6 @@
else
{
klass = new java::lang::Class ();
- klass->aux_info = (void *) _Jv_AllocBytes (sizeof (_Jv_InterpClass));
// Synchronize on the class, so that it is not attempted initialized
// until we're done loading.