Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- diff --git a/core/src/main/java/org/jruby/ObjectFlags.java b/core/src/main/java/org/jruby/ObjectFlags.java
- index 30154d1d6e..3938b1a0cf 100644
- --- a/core/src/main/java/org/jruby/ObjectFlags.java
- +++ b/core/src/main/java/org/jruby/ObjectFlags.java
- @@ -31,4 +31,12 @@ public interface ObjectFlags {
- int COMPARE_BY_IDENTITY_F = registry.newFlag(RubyHash.class);
- int PROCDEFAULT_HASH_F = registry.newFlag(RubyHash.class);
- +
- + /*
- + * This will say whether all keys are symbols or not which makes keyword arguments a bit
- + * simpler to process for calls. This boolean may not strictly cover all hashes which
- + * contain only symbols in cases where non-symbol entries are added and then removed.
- + */
- + int ONLY_SYMBOL_KEYS_F = registry.newFlag(RubyHash.class);
- +
- }
- diff --git a/core/src/main/java/org/jruby/RubyHash.java b/core/src/main/java/org/jruby/RubyHash.java
- index 2f58c0ce70..9c2a126617 100644
- --- a/core/src/main/java/org/jruby/RubyHash.java
- +++ b/core/src/main/java/org/jruby/RubyHash.java
- @@ -70,6 +70,7 @@ import java.util.NoSuchElementException;
- import java.util.Set;
- import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
- +import static org.jruby.ObjectFlags.ONLY_SYMBOL_KEYS_F;
- import static org.jruby.RubyEnumerator.enumeratorizeWithSize;
- import static org.jruby.runtime.Visibility.PRIVATE;
- import static org.jruby.RubyEnumerator.SizeFn;
- @@ -304,11 +305,13 @@ public class RubyHash extends RubyObject implements Map {
- private final void allocFirst() {
- threshold = INITIAL_THRESHOLD;
- + flags |= ONLY_SYMBOL_KEYS_F;
- table = new RubyHashEntry[MRI_HASH_RESIZE ? MRI_INITIAL_CAPACITY : JAVASOFT_INITIAL_CAPACITY];
- }
- private final void allocFirst(int buckets) {
- threshold = INITIAL_THRESHOLD;
- + flags |= ONLY_SYMBOL_KEYS_F;
- table = new RubyHashEntry[buckets];
- }
- @@ -554,6 +557,10 @@ public class RubyHash extends RubyObject implements Map {
- checkIterating();
- + if (!(key instanceof RubySymbol)) {
- + flags &= ~ONLY_SYMBOL_KEYS_F;
- + }
- +
- table[i] = new RubyHashEntry(hash, key, value, table[i], head);
- size++;
- @@ -561,6 +568,13 @@ public class RubyHash extends RubyObject implements Map {
- return null;
- }
- + public void putIKnowWhatIAmDoing(IRubyObject key, IRubyObject value) {
- + int hash = hashValue(key);
- + int i = bucketIndex(hash, table.length);
- + table[i] = new RubyHashEntry(hash, key, value, table[i], head);
- + size++;
- + }
- +
- // get implementation
- protected IRubyObject internalGet(IRubyObject key) { // specialized for value
- @@ -692,23 +706,6 @@ public class RubyHash extends RubyObject implements Map {
- if (count > 0) throw concurrentModification();
- }
- - public <T> boolean allSymbols() {
- - int startGeneration = generation;
- - // visit not more than size entries
- - RubyHashEntry head = this.head;
- - for (RubyHashEntry entry = head.nextAdded; entry != head; entry = entry.nextAdded) {
- - if (startGeneration != generation) {
- - startGeneration = generation;
- - entry = head.nextAdded;
- - if (entry == head) break;
- - }
- - if (entry != null && entry.isLive()) {
- - if (!(entry.key instanceof RubySymbol)) return false;
- - }
- - }
- - return true;
- - }
- -
- /* ============================
- * End of hash internals
- * ============================
- @@ -2161,7 +2158,8 @@ public class RubyHash extends RubyObject implements Map {
- final Ruby runtime = context.runtime;
- RubyHash dup = new RubyHash(runtime, getMetaClass(), this);
- - dup.setComparedByIdentity(this.isComparedByIdentity());
- + dup.flags = flags;
- + //dup.setComparedByIdentity(this.isComparedByIdentity());
- dup.ifNone = this.ifNone;
- @@ -2350,6 +2348,18 @@ public class RubyHash extends RubyObject implements Map {
- return (flags & COMPARE_BY_IDENTITY_F) != 0;
- }
- + /**
- + * Does this hash know whether it contains only symbol keys? This is different than whether
- + * only symbol keys exist in a hash as this flag only tracks symbol additions. If a non-symbol
- + * is added and then later removed the hash may only contain symbols but this flag will not
- + * track that unusual case.
- + *
- + * Motivation for this is for keyword argument processing optimization.
- + */
- + public boolean isOnlySymbolKeys() {
- + return (flags & ONLY_SYMBOL_KEYS_F) != 0;
- + }
- +
- /**
- * Sets whether this object is compared by identity or not. Shortcut for doing
- * setFlag(COMPARE_BY_IDENTITY_F, frozen).
- diff --git a/core/src/main/java/org/jruby/ir/runtime/IRRuntimeHelpers.java b/core/src/main/java/org/jruby/ir/runtime/IRRuntimeHelpers.java
- index 62ed95afcf..d8d02cfbfe 100644
- --- a/core/src/main/java/org/jruby/ir/runtime/IRRuntimeHelpers.java
- +++ b/core/src/main/java/org/jruby/ir/runtime/IRRuntimeHelpers.java
- @@ -545,13 +545,13 @@ public class IRRuntimeHelpers {
- final IRubyObject maybeKwargs = toHash(args[length - 1], context);
- if (maybeKwargs != null) {
- - if (maybeKwargs.isNil()) { // nil on to_hash is supposed to keep itself as real value so we need to make kwargs hash
- + if (!(maybeKwargs instanceof RubyHash)) { // nil on to_hash is supposed to keep itself as real value so we need to make kwargs hash
- return ArraySupport.newCopy(args, RubyHash.newSmallHash(context.runtime));
- }
- RubyHash kwargs = (RubyHash) maybeKwargs;
- - if (kwargs.allSymbols()) {
- + if (kwargs.isOnlySymbolKeys()) {
- args[length - 1] = kwargs;
- } else {
- args = homogenizeKwargs(context, args, kwargs);
Add Comment
Please, Sign In to add comment