Mercurial > hg > graal-compiler
diff graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/array/BaseArrayStore.java @ 13514:0fbee3eb71f0
Ruby: import project.
author | Chris Seaton <chris.seaton@oracle.com> |
---|---|
date | Mon, 06 Jan 2014 17:12:09 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/array/BaseArrayStore.java Mon Jan 06 17:12:09 2014 +0000 @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.core.array; + +/** + * Contains implementations of as much of the array stores that we could easily share. Much of the + * rest depends on static types in method signatures, so is lexically almost the same, but isn't the + * same in type, and as the whole point is to avoid boxing, we can't use Java's generics. + */ +public abstract class BaseArrayStore implements ArrayStore { + + protected int capacity; + protected int size; + + @Override + public int size() { + return size; + } + + /** + * Set a range in the array to be another range. You must ensure that the otherValues array is + * of the same type as your values array. + */ + protected void setRangeArrayMatchingTypes(int normalisedBegin, int normalisedExclusiveEnd, Object otherValues, int otherSize) { + // Is the range the whole array? + + if (normalisedBegin == 0 && normalisedExclusiveEnd == size) { + // Do we already have enough space? + + if (otherSize <= capacity) { + // Copy to our existing array. + final Object values = getValuesArrayObject(); + System.arraycopy(otherValues, 0, values, 0, otherSize); + } else { + // Create a new copy of their array. + setCapacityWithNewArray(otherSize); + final Object values = getValuesArrayObject(); + System.arraycopy(otherValues, 0, values, 0, otherSize); + } + + size = otherSize; + } else { + final int rangeLength = normalisedExclusiveEnd - normalisedBegin; + + // Create extra space - might be negative if the new range is shorter, or zero. + + final int extraSpaceNeeded = otherSize - rangeLength; + + if (extraSpaceNeeded > 0) { + createSpace(normalisedBegin, extraSpaceNeeded); + } else if (extraSpaceNeeded < 0) { + deleteSpace(normalisedBegin, -extraSpaceNeeded); + } + + // Copy across the new values. + final Object values = getValuesArrayObject(); + System.arraycopy(otherValues, 0, values, normalisedBegin, otherSize); + } + } + + protected void createSpace(int normalisedBegin, int count) { + /* + * Is this space at the end or in the middle? + */ + + if (normalisedBegin == size) { + createSpaceAtEnd(count); + } else { + /* + * Create space in the middle - is the array already big enough? + */ + + final int elementsToMove = size - normalisedBegin; + + if (size + count > capacity) { + /* + * The array isn't big enough. We don't want to use Arrays.copyOf because that will + * do wasted copying of the elements we are about to move. However - is + * Arrays.copyOf clever enough to see that only one instance of Array is using the + * block and use realloc, potentially avoiding a malloc and winning? + */ + + final Object values = getValuesArrayObject(); + setCapacityWithNewArray(ArrayUtilities.capacityFor(size + count)); + final Object newValues = getValuesArrayObject(); + System.arraycopy(values, 0, newValues, 0, normalisedBegin); + System.arraycopy(values, normalisedBegin, newValues, normalisedBegin + count, elementsToMove); + } else { + /* + * The array is already big enough - we can copy elements already in the array to + * make space. + */ + + final Object values = getValuesArrayObject(); + System.arraycopy(values, normalisedBegin, values, normalisedBegin + count, elementsToMove); + } + + size += count; + } + } + + protected void createSpaceAtEnd(int count) { + /* + * Create space at the end - we can do this by creating a copy of the array if needed. + */ + + if (size + count > capacity) { + setCapacityByCopying(ArrayUtilities.capacityFor(size + count)); + } + + size += count; + } + + protected void deleteSpace(int normalisedBegin, int count) { + final Object values = getValuesArrayObject(); + final int elementsToMove = size - normalisedBegin - count; + + if (elementsToMove > 0) { + System.arraycopy(values, normalisedBegin + count, values, normalisedBegin, elementsToMove); + } + + size -= count; + } + + protected abstract void setCapacityByCopying(int newCapacity); + + protected abstract void setCapacityWithNewArray(int newCapacity); + + protected abstract Object getValuesArrayObject(); + + @Override + public boolean equals(ArrayStore other) { + for (int n = 0; n < size; n++) { + if (!other.get(n).equals(get(n))) { + return false; + } + } + + return true; + } + +}