package com.oracle.truffle.js.runtime.array.dyn;
import static com.oracle.truffle.api.CompilerDirectives.FASTPATH_PROBABILITY;
import static com.oracle.truffle.api.CompilerDirectives.injectBranchProbability;
import static com.oracle.truffle.js.runtime.builtins.JSAbstractArray.arrayGetArray;
import static com.oracle.truffle.js.runtime.builtins.JSAbstractArray.arraySetArray;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.js.runtime.JSConfig;
import com.oracle.truffle.js.runtime.JSRuntime;
import com.oracle.truffle.js.runtime.array.ScriptArray;
public abstract class AbstractDoubleArray extends AbstractWritableArray {
protected AbstractDoubleArray(int integrityLevel, DynamicArrayCache cache) {
super(integrityLevel, cache);
}
@Override
AbstractWritableArray sameTypeHolesArray(DynamicObject object, int length, Object array, long indexOffset, int arrayOffset, int usedLength, int holeCount) {
return HolesDoubleArray.makeHolesDoubleArray(object, length, (double[]) array, indexOffset, arrayOffset, usedLength, holeCount, integrityLevel);
}
public abstract void setInBoundsFast(DynamicObject object, int index, double value);
@Override
public final ScriptArray setElementImpl(DynamicObject object, long index, Object value, boolean strict) {
assert index >= 0;
if (injectBranchProbability(FASTPATH_PROBABILITY, (value instanceof Integer || value instanceof Double) && isSupported(object, (int) index))) {
double doubleValue = JSRuntime.doubleValue((Number) value);
assert !HolesDoubleArray.isHoleValue(doubleValue);
setSupported(object, (int) index, doubleValue, ProfileHolder.empty());
return this;
} else {
return rewrite(object, index, value).setElementImpl(object, index, value, strict);
}
}
private ScriptArray rewrite(DynamicObject object, long index, Object value) {
if (value instanceof Integer || value instanceof Double) {
if (isSupportedContiguous(object, index)) {
return toContiguous(object, index, value);
} else if (isSupportedHoles(object, index)) {
return toHoles(object, index, value);
} else {
return toSparse(object, index, value);
}
} else {
return toObject(object, index, value);
}
}
@Override
public Object getInBoundsFast(DynamicObject object, int index) {
return getInBoundsFastDouble(object, index);
}
@Override
public abstract double getInBoundsFastDouble(DynamicObject object, int index);
@Override
int getArrayLength(Object array) {
return ((double[]) array).length;
}
protected static double[] getArray(DynamicObject object) {
Object array = arrayGetArray(object);
if (array.getClass() == double[].class) {
return (double[]) array;
} else {
throw CompilerDirectives.shouldNotReachHere();
}
}
public final void setInBounds(DynamicObject object, int index, double value, ProfileHolder profile) {
getArray(object)[prepareInBounds(object, index, profile)] = value;
if (JSConfig.TraceArrayWrites) {
traceWriteValue("InBounds", index, value);
}
}
public final void setSupported(DynamicObject object, int index, double value, ProfileHolder profile) {
int preparedIndex = prepareSupported(object, index, profile);
getArray(object)[preparedIndex] = value;
if (JSConfig.TraceArrayWrites) {
traceWriteValue("Supported", index, value);
}
}
@Override
void fillWithHoles(Object array, int fromIndex, int toIndex) {
double[] doubleArray = (double[]) array;
for (int i = fromIndex; i < toIndex; i++) {
doubleArray[i] = HolesDoubleArray.HOLE_VALUE_DOUBLE;
}
}
@Override
protected final void setHoleValue(DynamicObject object, int preparedIndex) {
getArray(object)[preparedIndex] = HolesDoubleArray.HOLE_VALUE_DOUBLE;
}
@Override
protected final boolean isHolePrepared(DynamicObject object, int preparedIndex) {
return HolesDoubleArray.isHoleValue(getArray(object)[preparedIndex]);
}
@Override
protected final int getArrayCapacity(DynamicObject object) {
return getArray(object).length;
}
@Override
protected final void resizeArray(DynamicObject object, int newCapacity, int oldCapacity, int offset) {
double[] newArray = new double[newCapacity];
System.arraycopy(getArray(object), 0, newArray, offset, oldCapacity);
arraySetArray(object, newArray);
}
@Override
public abstract AbstractDoubleArray toHoles(DynamicObject object, long index, Object value);
@Override
public final AbstractWritableArray toDouble(DynamicObject object, long index, double value) {
return this;
}
@Override
public ScriptArray deleteElementImpl(DynamicObject object, long index, boolean strict) {
return toHoles(object, index, HolesDoubleArray.HOLE_VALUE).deleteElementImpl(object, index, strict);
}
@Override
protected final void moveRangePrepared(DynamicObject object, int src, int dst, int len) {
double[] array = getArray(object);
System.arraycopy(array, src, array, dst, len);
}
@Override
public final Object allocateArray(int length) {
return new double[length];
}
@Override
public Object cloneArray(DynamicObject object) {
return getArray(object).clone();
}
@Override
protected abstract AbstractDoubleArray withIntegrityLevel(int newIntegrityLevel);
}