@Specialization(guards = {"isBucketHash(hash)", "!isRubyString(key)"}) public Object setBuckets( VirtualFrame frame, DynamicObject hash, Object key, Object value, boolean byIdentity) { assert HashNodes.verifyStore(hash); if (lookupEntryNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); lookupEntryNode = insert(new LookupEntryNode(getContext(), getEncapsulatingSourceSection())); } final HashLookupResult result = lookupEntryNode.lookup(frame, hash, key); final Entry entry = result.getEntry(); if (foundProfile.profile(entry == null)) { final Entry[] entries = (Entry[]) Layouts.HASH.getStore(hash); final Entry newEntry = new Entry(result.getHashed(), key, value); if (bucketCollisionProfile.profile(result.getPreviousEntry() == null)) { entries[result.getIndex()] = newEntry; } else { result.getPreviousEntry().setNextInLookup(newEntry); } final Entry lastInSequence = Layouts.HASH.getLastInSequence(hash); if (appendingProfile.profile(lastInSequence == null)) { Layouts.HASH.setFirstInSequence(hash, newEntry); } else { lastInSequence.setNextInSequence(newEntry); newEntry.setPreviousInSequence(lastInSequence); } Layouts.HASH.setLastInSequence(hash, newEntry); final int newSize = Layouts.HASH.getSize(hash) + 1; Layouts.HASH.setSize(hash, newSize); // TODO CS 11-May-15 could store the next size for resize instead of doing a float operation // each time if (resizeProfile.profile(newSize / (double) entries.length > BucketsStrategy.LOAD_FACTOR)) { BucketsStrategy.resize(hash); } } else { entry.setKeyValue(result.getHashed(), key, value); } assert HashNodes.verifyStore(hash); return value; }