From 79c31a7680e360c45b15f37074d813c446365985 Mon Sep 17 00:00:00 2001 From: "duncan.macgregor" Date: Sat, 30 Nov 2024 19:22:10 +0000 Subject: [PATCH] Add an empty slot map for cases where no slots exist. --- .../mozilla/javascript/SlotMapContainer.java | 50 ++++++++++++++++++- .../ThreadSafeSlotMapContainer.java | 1 + 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/rhino/src/main/java/org/mozilla/javascript/SlotMapContainer.java b/rhino/src/main/java/org/mozilla/javascript/SlotMapContainer.java index ef57146426..40b3d032d1 100644 --- a/rhino/src/main/java/org/mozilla/javascript/SlotMapContainer.java +++ b/rhino/src/main/java/org/mozilla/javascript/SlotMapContainer.java @@ -6,6 +6,7 @@ package org.mozilla.javascript; +import java.util.Collections; import java.util.Iterator; /** @@ -23,6 +24,46 @@ class SlotMapContainer implements SlotMap { private static final int DEFAULT_SIZE = 10; + private static class EmptySlotMap implements SlotMap { + + @Override + public Iterator iterator() { + return Collections.emptyIterator(); + } + + @Override + public int size() { + return 0; + } + + @Override + public boolean isEmpty() { + return true; + } + + @Override + public Slot modify(Object key, int index, int attributes) { + return null; + } + + @Override + public Slot query(Object key, int index) { + return null; + } + + @Override + public void add(Slot newSlot) { + throw new IllegalStateException(); + } + + @Override + public S compute(Object key, int index, SlotComputer compute) { + throw new IllegalStateException(); + } + } + + private static EmptySlotMap EMPTY_SLOT_MAP = new EmptySlotMap(); + protected SlotMap map; SlotMapContainer() { @@ -30,7 +71,9 @@ class SlotMapContainer implements SlotMap { } SlotMapContainer(int initialSize) { - if (initialSize > LARGE_HASH_SIZE) { + if (initialSize == 0) { + map = EMPTY_SLOT_MAP; + } else if (initialSize > LARGE_HASH_SIZE) { map = new HashSlotMap(); } else { map = new EmbeddedSlotMap(); @@ -59,6 +102,7 @@ public Slot modify(Object key, int index, int attributes) { @Override public S compute(Object key, int index, SlotComputer c) { + checkMapSize(); return map.compute(key, index, c); } @@ -92,7 +136,9 @@ public void unlockRead(long stamp) { * map to a HashMap that is more robust against large numbers of hash collisions. */ protected void checkMapSize() { - if ((map instanceof EmbeddedSlotMap) && map.size() >= LARGE_HASH_SIZE) { + if (map == EMPTY_SLOT_MAP) { + map = new EmbeddedSlotMap(); + } else if ((map instanceof EmbeddedSlotMap) && map.size() >= LARGE_HASH_SIZE) { SlotMap newMap = new HashSlotMap(map); map = newMap; } diff --git a/rhino/src/main/java/org/mozilla/javascript/ThreadSafeSlotMapContainer.java b/rhino/src/main/java/org/mozilla/javascript/ThreadSafeSlotMapContainer.java index 8a95301ecc..c2c8d7c3ae 100644 --- a/rhino/src/main/java/org/mozilla/javascript/ThreadSafeSlotMapContainer.java +++ b/rhino/src/main/java/org/mozilla/javascript/ThreadSafeSlotMapContainer.java @@ -77,6 +77,7 @@ public Slot modify(Object key, int index, int attributes) { public S compute(Object key, int index, SlotComputer c) { final long stamp = lock.writeLock(); try { + checkMapSize(); return map.compute(key, index, c); } finally { lock.unlockWrite(stamp);