示例#1
0
  @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;
  }