public void innerDefaultReplaceValue(Data<V> newValue) {
    assert s.innerUpdateLock.isHeldByCurrentThread();

    boolean newValueSizeIsDifferent = newValue.size() != this.valueSize;
    if (newValueSizeIsDifferent) {
      long newSizeOfEverythingBeforeValue = newSizeOfEverythingBeforeValue(newValue);
      long entryStartOffset = keySizeOffset;
      VanillaChronicleMap<?, ?, ?, ?, ?, ?, ?> m = mh.m();
      long newValueOffset =
          m.alignment.alignAddr(entryStartOffset + newSizeOfEverythingBeforeValue);
      long newEntrySize = newValueOffset + newValue.size() - entryStartOffset;
      int newSizeInChunks = m.inChunks(newEntrySize);
      newValueDoesNotFit:
      if (newSizeInChunks > entrySizeInChunks) {
        if (newSizeInChunks > m.maxChunksPerEntry) {
          throw new IllegalArgumentException(
              "Value too large: "
                  + "entry takes "
                  + newSizeInChunks
                  + " chunks, "
                  + m.maxChunksPerEntry
                  + " is maximum.");
        }
        if (s.freeList.allClear(pos + entrySizeInChunks, pos + newSizeInChunks)) {
          s.freeList.set(pos + entrySizeInChunks, pos + newSizeInChunks);
          break newValueDoesNotFit;
        }
        relocation(newValue, newSizeOfEverythingBeforeValue);
        return;
      } else if (newSizeInChunks < entrySizeInChunks) {
        // Freeing extra chunks
        s.freeList.clear(pos + newSizeInChunks, pos + entrySizeInChunks);
        // Do NOT reset nextPosToSearchFrom, because if value
        // once was larger it could easily became larger again,
        // But if these chunks will be taken by that time,
        // this entry will need to be relocated.
      }
      // new size != old size => size is not constant => size is actually written =>
      // to prevent (at least) this execution:
      // 1. concurrent reader thread reads the size
      // 2. this thread updates the size and the value
      // 3. concurrent reader reads the value
      // We MUST upgrade to exclusive lock
    } else {
      // TODO to turn the following block on, JLANG-46 is required. Also unclear what happens
      // if the value is DataValue generated with 2, 4 or 8 distinct bytes, putting on-heap
      // implementation of such value is also not atomic currently, however there is a way
      // to make it atomic, we should identify such cases and make a single write:
      // state = UNSAFE.getLong(onHeapValueObject, offsetToTheFirstField);
      // bytes.writeLong(state);
      //            boolean newValueSizeIsPowerOf2 = ((newValueSize - 1L) & newValueSize) != 0;
      //            if (!newValueSizeIsPowerOf2 || newValueSize > 8L) {
      //                // if the new value size is 1, 2, 4, or 8, it is written not atomically only
      // if
      //                // the user provided own marshaller and writes value byte-by-byte, that is
      // very
      //                // unlikely. in this case the user should update acquire write lock before
      // write
      //                // updates himself
      //                upgradeToWriteLock();
      //            }
    }
    s.innerWriteLock.lock();

    if (newValueSizeIsDifferent) {
      initValue(newValue);
    } else {
      writeValue(newValue);
    }
    hashLookup.putValueVolatile(hlp.hashLookupPos, pos);
  }
 public void writeValueAndPutPos(Data<V> value) {
   initValue(value);
   freeExtraAllocatedChunks();
   hashLookup.putValueVolatile(hlp.hashLookupPos, pos);
 }