Proposed Change to gnu/gcj/runtime/StackTrace.java

Angelo Corsaro corsaro@cse.wustl.edu
Sat Mar 15 02:45:00 GMT 2003


Hello All,
 
   I am extending the GCJ compiler to support the Real-Time 
Specification for Java (RTSJ), and recently while finishing up the
implementation of memory reference checking I found out that the
<update> method in  gnu/gcc/runtime/natStackTrace.cc  did the following:

   // ...
   gnu::gcj::runtime::MethodRef *ref
     = new gnu::gcj::runtime::MethodRef 
      ((gnu::gcj::RawData *)meth, klass);
   gnu::gcj::runtime::AddressHolder *holder
     = new gnu::gcj::runtime::AddressHolder
      ((gnu::gcj::RawData *)(meth->ncode));
   
   map->put (holder, ref);
   
  // ...

This fragment of code adds a reference to a method to an
IdentityHashMap, using meth->ncode as key. The issues I had to struggle
with is that meth->ncode is not a "real" Java object, and this caused
check on the store for the array used by map to fail.


[ For those of you which are not familiar with the RTSJ, field store,
  and array store have to be checked to enforce certain reference rules
  between objects allocated in different memory areas (yes, the RTSJ  
  supports memory areas other than the Heap).]


Right now I have changed the implementation of natStackTrace.cc and
StackTrace.java as shown by the following diff


Index: gnu/gcj/runtime/StackTrace.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/gcj/runtime/StackTrace.java,v
retrieving revision 1.1
diff -u -w -r1.1 StackTrace.java
--- gnu/gcj/runtime/StackTrace.java	3 Dec 2002 13:53:27 -0000	1.1
+++ gnu/gcj/runtime/StackTrace.java	14 Mar 2003 16:51:04 -0000
@@ -40,7 +40,7 @@
 
 import gnu.gcj.RawData;
 import java.util.TreeMap;
-import java.util.IdentityHashMap;
+import java.util.HashMap;
 import java.util.SortedMap;
 import gnu.gcj.runtime.NameFinder;
 import java.util.NoSuchElementException;
@@ -145,7 +145,8 @@
     update();
     synchronized (map)
       {
-	return (MethodRef) map.get (addr);
+        addrHolder.setAddress(addr);
+	return (MethodRef) map.get (addrHolder);
       }
   }
 
@@ -157,8 +158,8 @@
   private native void fillInStackTrace(int n, int offset);
 
   private static native MethodRef getCompiledMethodRef(RawData addr);
-  private static IdentityHashMap map = new IdentityHashMap();
-
+  private static HashMap map = new HashMap();
+  private static AddressHolder addrHolder = new AddressHolder();
   private gnu.gcj.RawData addrs;
   private int len;
 }
Index: gnu/gcj/runtime/natStackTrace.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/gcj/runtime/natStackTrace.cc,v
retrieving revision 1.2.6.3
diff -u -w -r1.2.6.3 natStackTrace.cc
--- gnu/gcj/runtime/natStackTrace.cc	19 Feb 2003 16:27:22 -0000	1.2.6.3
+++ gnu/gcj/runtime/natStackTrace.cc	14 Mar 2003 16:51:04 -0000
@@ -27,9 +27,10 @@
 #include <java-threads.h>
 #include <gnu/gcj/runtime/MethodRef.h>
 #include <gnu/gcj/runtime/StackTrace.h>
+#include <gnu/gcj/runtime/AddressHolder.h>
 #include <java/lang/Thread.h>
 #include <java-interp.h>
-#include <java/util/IdentityHashMap.h>
+#include <java/util/HashMap.h>
 #include <java/lang/ArrayIndexOutOfBoundsException.h>
 
 #include <sys/types.h>
@@ -189,7 +190,9 @@
 	      gnu::gcj::runtime::MethodRef *ref
 		= new gnu::gcj::runtime::MethodRef 
 		((gnu::gcj::RawData *)meth, klass);
-	      map->put ((java::lang::Object*)(meth->ncode), ref);
+              gnu::gcj::runtime::AddressHolder *holder
+                = new
gnu::gcj::runtime::AddressHolder((gnu::gcj::RawData *)(meth->ncode));
+              map->put (holder, ref);
 	    }
 	}
     }



This code relies on the AddressHolder which is reported below:


package gnu.gcj.runtime;

import gnu.gcj.RawData;

/**
 * This class encapsulates a raw address into a Java object.
 *
 * @author <a href="mailto:corsaro@cse.wustl.edu">Angelo Corsaro</a>
 * @version 1.0
 */
public class AddressHolder {

    private RawData address;

    public AddressHolder() { }

    public AddressHolder(RawData address) {
        this.address = address;
    }

    public void setAddress(RawData address) {
        this.address = address;
    }

    public RawData getAddress() {
        return this.address;
    }
    
    public boolean equals(AddressHolder obj) {
        return obj.address == this.address;
    }

    public boolean equals(Object obj) {
        boolean retVal = false;
        try {
            AddressHolder tmp = (AddressHolder)obj;
            retVal = this.equals(tmp);
        } catch (ClassCastException e) { }
        return retVal;
    }
    
    public int  hashCode() {
        return System.identityHashCode(this.address);
    }
}


The change seems to work fine, and avoids the nastiness of adding a non
Java object inside a map. I guess that the additional new in the update 
method should not be an issue since there are already two allocations.


Does anyone see any problem with this? Should the StackTrace class be
changed to use this scheme?


Cheers,
   Angelo 

 
-- 
Angelo Corsaro
Department of Computer Science
Washington University
http://tao.doc.wustl.edu/~corsaro



More information about the Java mailing list