From aa15e3095f30c11c90f034e2b1b9ebbe08337c56 Mon Sep 17 00:00:00 2001
From: md_5 <md_5@live.com.au>
Date: Fri, 21 Jun 2013 17:13:47 +1000
Subject: [PATCH] LongHash Tweaks


diff --git a/src/main/java/org/bukkit/craftbukkit/util/LongHashSet.java b/src/main/java/org/bukkit/craftbukkit/util/LongHashSet.java
index 22c96c5..7c3005e 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/LongHashSet.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/LongHashSet.java
@@ -31,6 +31,7 @@ public class LongHashSet {
     private int elements;
     private long[] values;
     private int modCount;
+    private org.spigotmc.FlatMap<Boolean> flat = new org.spigotmc.FlatMap<Boolean>(); // Spigot
 
     public LongHashSet() {
         this(INITIAL_SIZE);
@@ -56,10 +57,22 @@ public class LongHashSet {
     }
 
     public boolean contains(int msw, int lsw) {
+        // Spigot start
+        if ( flat.contains( msw, lsw ) )
+        {
+            return true;
+        }
+        // Spigot end
         return contains(LongHash.toLong(msw, lsw));
     }
 
     public boolean contains(long value) {
+        // Spigot start
+        if ( flat.contains( value ) )
+        {
+            return true;
+        }
+        // Spigot end
         int hash = hash(value);
         int index = (hash & 0x7FFFFFFF) % values.length;
         int offset = 1;
@@ -82,6 +95,7 @@ public class LongHashSet {
     }
 
     public boolean add(long value) {
+        flat.put( value, Boolean.TRUE ); // Spigot
         int hash = hash(value);
         int index = (hash & 0x7FFFFFFF) % values.length;
         int offset = 1;
@@ -125,10 +139,18 @@ public class LongHashSet {
     }
 
     public void remove(int msw, int lsw) {
-        remove(LongHash.toLong(msw, lsw));
+        // Spigot start
+        flat.remove(msw, lsw);
+        remove0(LongHash.toLong(msw, lsw));
     }
 
     public boolean remove(long value) {
+        flat.remove(value);
+        return remove0(value);
+    }
+
+    private boolean remove0(long value) {
+        // Spigot end
         int hash = hash(value);
         int index = (hash & 0x7FFFFFFF) % values.length;
         int offset = 1;
@@ -161,6 +183,7 @@ public class LongHashSet {
 
         freeEntries = values.length;
         modCount++;
+        flat = new org.spigotmc.FlatMap<Boolean>();
     }
 
     public long[] toArray() {
diff --git a/src/main/java/org/bukkit/craftbukkit/util/LongObjectHashMap.java b/src/main/java/org/bukkit/craftbukkit/util/LongObjectHashMap.java
index 01861cc..08b543b 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/LongObjectHashMap.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/LongObjectHashMap.java
@@ -28,6 +28,7 @@ public class LongObjectHashMap<V> implements Cloneable, Serializable {
     private transient V[][]    values;
     private transient int      modCount;
     private transient int      size;
+    private transient org.spigotmc.FlatMap<V> flat = new org.spigotmc.FlatMap<V>(); // Spigot
 
     public LongObjectHashMap() {
         initialize();
@@ -61,6 +62,13 @@ public class LongObjectHashMap<V> implements Cloneable, Serializable {
     }
 
     public V get(long key) {
+        // Spigot start
+        V val = flat.get( key );
+        if ( val != null )
+        {
+            return val;
+        }
+        // Spigot end
         int index = (int) (keyIndex(key) & (BUCKET_SIZE - 1));
         long[] inner = keys[index];
         if (inner == null) return null;
@@ -78,6 +86,7 @@ public class LongObjectHashMap<V> implements Cloneable, Serializable {
     }
 
     public V put(long key, V value) {
+        flat.put(key, value); // Spigot
         int index = (int) (keyIndex(key) & (BUCKET_SIZE - 1));
         long[] innerKeys = keys[index];
         V[] innerValues = values[index];
@@ -124,6 +133,7 @@ public class LongObjectHashMap<V> implements Cloneable, Serializable {
     }
 
     public V remove(long key) {
+        flat.remove(key); // Spigot
         int index = (int) (keyIndex(key) & (BUCKET_SIZE - 1));
         long[] inner = keys[index];
         if (inner == null) {
@@ -174,6 +184,7 @@ public class LongObjectHashMap<V> implements Cloneable, Serializable {
         size = 0;
         Arrays.fill(keys, null);
         Arrays.fill(values, null);
+        flat = new org.spigotmc.FlatMap<V>();
     }
 
     public Set<Long> keySet() {
diff --git a/src/main/java/org/spigotmc/FlatMap.java b/src/main/java/org/spigotmc/FlatMap.java
new file mode 100644
index 0000000..9416f6e
--- /dev/null
+++ b/src/main/java/org/spigotmc/FlatMap.java
@@ -0,0 +1,64 @@
+package org.spigotmc;
+
+import org.bukkit.craftbukkit.util.LongHash;
+
+public class FlatMap<V>
+{
+
+    private static final int FLAT_LOOKUP_SIZE = 512;
+    private final Object[][] flatLookup = new Object[ FLAT_LOOKUP_SIZE * 2 ][ FLAT_LOOKUP_SIZE * 2 ];
+
+    public void put(long msw, long lsw, V value)
+    {
+        long acx = Math.abs( msw );
+        long acz = Math.abs( lsw );
+        if ( acx < FLAT_LOOKUP_SIZE && acz < FLAT_LOOKUP_SIZE )
+        {
+            flatLookup[(int) ( msw + FLAT_LOOKUP_SIZE )][(int) ( lsw + FLAT_LOOKUP_SIZE )] = value;
+        }
+    }
+
+    public void put(long key, V value)
+    {
+        put( LongHash.msw( key ), LongHash.lsw( key ), value );
+
+    }
+
+    public void remove(long key)
+    {
+        put( key, null );
+    }
+
+    public void remove(long msw, long lsw)
+    {
+        put( msw, lsw, null );
+    }
+
+    public boolean contains(long msw, long lsw)
+    {
+        return get( msw, lsw ) != null;
+    }
+
+    public boolean contains(long key)
+    {
+        return get( key ) != null;
+    }
+
+    public V get(long msw, long lsw)
+    {
+        long acx = Math.abs( msw );
+        long acz = Math.abs( lsw );
+        if ( acx < FLAT_LOOKUP_SIZE && acz < FLAT_LOOKUP_SIZE )
+        {
+            return (V) flatLookup[(int) ( msw + FLAT_LOOKUP_SIZE )][(int) ( lsw + FLAT_LOOKUP_SIZE )];
+        } else
+        {
+            return null;
+        }
+    }
+
+    public V get(long key)
+    {
+        return get( LongHash.msw( key ), LongHash.lsw( key ) );
+    }
+}
-- 
1.8.1.2