This is the mail archive of the java-patches@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Patch: java.util.Hashtable enumerator vs specjvm javac


This patch changes our Hashtable enumerator implementation to work more 
like Sun's, so that the specjvm javac benchmark will run correctly. In 
the event that a new element is added to a table while an enumeration is 
in progress, we previously could possibly throw an exception on 
nextElement() even if hasMoreElements(), called before the table was 
changed, returned true. nextElement() will now always return something 
if the last hasMoreElements() was true. I dont think the old behaviour 
was outside spec, since table modification during enumeration is unsafe 
and has undefined behaviour, but the old javac used in the benchmark 
apparantly expected it.

The "bug" was originally reported (and initial patch proposed) by Gansha Wu.

I've checked this in.

regards

Bryce.


2001-09-06  Bryce McKinlay  <bryce@waitaki.otago.ac.nz>

        * java/util/Hashtable.java (Enumerator): Ensure that if 
	hasMoreElements() returns true, nextElement() will always return
	something even if the table has been modified.

Index: Hashtable.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/util/Hashtable.java,v
retrieving revision 1.12
diff -u -r1.12 Hashtable.java
--- Hashtable.java	2001/03/24 08:05:29	1.12
+++ Hashtable.java	2001/09/06 08:32:35
@@ -833,44 +833,57 @@
     static final int VALUES = 1;
     
     int type;
-    // The total number of elements returned by nextElement(). Used to 
-    // determine if there are more elements remaining.
-    int count;
     // current index in the physical hash table.
     int idx;
-    // the last Entry returned.
+    // the last Entry returned by nextEntry().
     Entry last;
+    // Entry which will be returned by the next nextElement() call.
+    Entry next;
     
     Enumerator(int type)
     {
       this.type = type;
-      this.count = 0;
       this.idx = buckets.length;
     }
+    
+    private Entry nextEntry()
+    {
+      Entry e = null;
 
+      if (last != null)
+        e = last.next;
+
+      while (e == null && idx > 0)
+	{
+	  e = buckets[--idx];
+	}
+      last = e;
+      return e;
+    }
+
     public boolean hasMoreElements()
     {
-      return count < Hashtable.this.size;    
+      if (next != null)
+        return true;
+      next = nextEntry();
+      return (next != null);
     }
 
     public Object nextElement()
     {
-      if (count >= size)
-        throw new NoSuchElementException();
-      count++;
       Entry e = null;
-      if (last != null)
-        e = last.next;
-
-      while (e == null)
+      if (next != null)
         {
-	  e = buckets[--idx];
+          e = next;
+	  next = null;
 	}
-
-      last = e;
+      else
+        e = nextEntry();
+      if (e == null)
+        throw new NoSuchElementException("Hashtable Enumerator");
       if (type == VALUES)
         return e.value;
       return e.key;
     }
-  }  
+  }
 }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]