From: Godmar Back (gback@cs.utah.edu)
Date: Mon Nov 16 1998 - 01:52:17 EST
>
> On Nov 16, 1998, Godmar Back <gback@marker.cs.utah.edu> wrote:
>
> > We decided to go to a classical return code model instead.
> > So, I made the necessary changes (I'm done with the jit, will do the
> > intrp soon).
>
> Why not use the JNIEnv structure for that, instead of inventing a
> different mechanism? The _errorInfo structure does not allow me to
> create my own exception type, with a constructor that does not take
> just a message in String format...
>
> If JNIEnv would be too burdensome, wouldn't it be better to make
> _errorInfo smaller too, such as a single pointer to a Throwable?
>
> The pointer solution would allow us not to tweak with the return types
> of functions. We'd just have to ensure that the pointer to throwable
> is initialized with NULL before calling a function, and check whether
> the pointer remains NULL when the function returns. If not, an
> exception was thrown.
You raise several points here.
First, the question as to whether the combination classname/message is
sufficient or whether the information should be extensible/more flexible.
Second, if it should be extensible, would a pointer to a Throwable
be a good solution.
Third, would the JNIEnv be the place to store the information.
ad 1), should it be extensible: I'd say there's no need for that.
It should certainly cover all possible cases, but it should be minimal.
Keep in mind that this mechanism is only intended for the core parts of
the VM --- similar to how you keep track of errno/return code in the
Unix kernel. There, usually only one integer is used.
ad 2), a Throwable would only work if it was preallocated and initialized.
Otherwise, you would reenter functions below the red line: for instance,
if a NoSuchMethodError is thrown in verifyBasicBlock, you would have to
load, resolve, verify and execute the NoSuchMethodError class. This would
require you to enter verifyBasicBlock, which of course doesn't work.
Preallocating and initializing exception objects might be hard to do:
for instance, a NoSuchMethodError(String msg) constructor will usually
be executed with the name of the method that wasn't found as the msg.
You would have to ensure that all this is possible without reentering
functions that grab locks such as the classLock, the verifierLock, the
translatorLock or any centry lock.
On the other hand, preallocating will be a good -- and the only possible ---
alternative for tackling OutOfMemory exceptions.
ad 3), would storing it in JNIEnv work. I assume you mean the
thread-specific data structure that JNIEnv points to (which doesn't currently
exist in Kaffe as such. People who don't know what I'm talking about should
look at the figure at the beginning of the JNI spec) I guess yes, that
would be equivalent in the sense that you're referring to thread-specific
storage. In one case, you pass a JNIEnv* pointer along, the way I did
it now, I'm passing this errorInfo* pointer.
The question would be: would that make the JNI interface even more seamless
(it's not necessarily clear that would be so, because it's not the same) and
are there really more things we would want to keep track in addition to
the two parameters describing the errorInfo.
[Otherwise, it would only be a naming issue and a question of where to
place it in the list of arguments --- first (JNIEnv*) or last (errorInfo*)]
I'm not willing to tackle that now, but we should keep it in mind for
the future. Related to that are the possible movement of the thread
specific exceptionObject & friends from java.lang.Thread to JNIEnv*.
Ideally, JNIEnv should point to all information pertinent to that thread
and to one instance of a VM. For now, I'm just interesting in fixing
these frequent nasty deadlocks, reenter the verifier aborts, and memory
leaks. I don't want to be able to instantiate multiple Kaffe VMs just
yet, although that would certainly be cool in the future.
I should mention that there is of course an alternative to passing a
pointer along, which is using the second form of thread-local storage
(besides what's stored as arguments to functions of the call stack),
namely thread-specific variables. This is what jni.c does to post
pending exceptions. This second solution has the advantage that you
save one argument for every call to a below the red line function, because
that argument can be "found" using the current thread. You'd still
need to check your return values, though. What this solution would
save would be a push instruction in the common case. I still felt
more comfortable with passing einfo pointers along, because I believe
the overhead is negligible and I feel that a self-contained solution
that doesn't need the support of the threading subsystem is a much
cleaner and easier-to-understand solution. Furthermore, it does not
depend on the threading system already being initialized. For instance,
had I stored the char *classname and char *mess as kaffe.util.Ptr in
the current java.lang.Thread, I would have had hassles in the beginning
before I have the java.lang.Thread of the main thread. I guess I could
have faked one... nevertheless, I like the traditional solution better.
What do others think?
- Godmar
This archive was generated by hypermail 2b29 : Sat Sep 23 2000 - 19:57:03 EDT