Skip to content

Commit

Permalink
Support more large array types, improve comments
Browse files Browse the repository at this point in the history
  • Loading branch information
jarrodmoldrich committed Nov 13, 2019
1 parent a720d86 commit 795d927
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 172 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,15 @@ public static GExpr tryCreate(MethodGenerator mv, ResourceWriter resourceWriter,
}

private static Constructors.ConstructorInterface[] instances = {
// mitigate `Method code too large` errors for large constant array expressions
largeShortArray,
largeIntArray,
largeLongArray,
largeFloatArray,
largeDoubleArray,
// store large string arrays either in the string pool, or in a resource for very large arrays
stringArray,
charArray
// store char arrays as a string in the constant pool
charArray // n.b., this should be _after_ `largeShortArray`
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,17 @@ interface BufferConverter {
* streamed into the array at construction.
*/

static ConstructorInterface largeShortArray = (mv, resourceWriter, value) -> {
Predicate<GimpleType> isElementType = c -> isIntegerWithPrecision(c, 16);
static ConstructorInterface largeFloatArray = (mv, resourceWriter, value) -> {
Predicate<GimpleType> isElementType = c -> isRealWithPrecision(c, 32);
BufferConverter converter = (buffer, element) -> {
GimpleIntegerConstant constant = (GimpleIntegerConstant)element.getValue();
short s = constant.getValue().shortValue();
buffer.putShort(s);
GimpleRealConstant constant = (GimpleRealConstant)element.getValue();
float f = constant.getValue().floatValue();
buffer.putFloat(f);
};

ByteBuffer buffer = constantArrayToBuffer(value, isElementType, converter, 2);
ByteBuffer buffer = constantArrayToBuffer(value, isElementType, converter, 4, 128);
if (buffer == null) return null;
LocalVar var = injectLoadableResource(mv, resourceWriter, buffer, "shortArrayFromResource");
LocalVar var = injectLoadableResource(mv, resourceWriter, buffer, "floatArrayFromResource");
GimpleArrayType arrayType = (GimpleArrayType) value.getType();
return new VArrayExpr(arrayType, new VPtrExpr(var));
};
Expand All @@ -71,15 +71,61 @@ interface BufferConverter {
buffer.putDouble(d);
};

ByteBuffer buffer = constantArrayToBuffer(value, isElementType, converter, 8);
ByteBuffer buffer = constantArrayToBuffer(value, isElementType, converter, 8, 128);
if (buffer == null) return null;
LocalVar var = injectLoadableResource(mv, resourceWriter, buffer, "doubleArrayFromResource");
GimpleArrayType arrayType = (GimpleArrayType) value.getType();
return new VArrayExpr(arrayType, new VPtrExpr(var));
};

static ConstructorInterface largeShortArray = (mv, resourceWriter, value) -> {
Predicate<GimpleType> isElementType = c -> isIntegerWithPrecision(c, 16);
BufferConverter converter = (buffer, element) -> {
GimpleIntegerConstant constant = (GimpleIntegerConstant)element.getValue();
short s = constant.getValue().shortValue();
buffer.putShort(s);
};

// using a higher threshold for short arrays, as smaller arrays can be handled by the charArray implementation
ByteBuffer buffer = constantArrayToBuffer(value, isElementType, converter, 2, 1024);
if (buffer == null) return null;
LocalVar var = injectLoadableResource(mv, resourceWriter, buffer, "shortArrayFromResource");
GimpleArrayType arrayType = (GimpleArrayType) value.getType();
return new VArrayExpr(arrayType, new VPtrExpr(var));
};

static ConstructorInterface largeIntArray = (mv, resourceWriter, value) -> {
Predicate<GimpleType> isElementType = c -> isIntegerWithPrecision(c, 32);
BufferConverter converter = (buffer, element) -> {
GimpleIntegerConstant constant = (GimpleIntegerConstant)element.getValue();
int i = constant.getValue().intValue();
buffer.putInt(i);
};

ByteBuffer buffer = constantArrayToBuffer(value, isElementType, converter, 4, 128);
if (buffer == null) return null;
LocalVar var = injectLoadableResource(mv, resourceWriter, buffer, "intArrayFromResource");
GimpleArrayType arrayType = (GimpleArrayType) value.getType();
return new VArrayExpr(arrayType, new VPtrExpr(var));
};

static ConstructorInterface largeLongArray = (mv, resourceWriter, value) -> {
Predicate<GimpleType> isElementType = c -> isIntegerWithPrecision(c, 64);
BufferConverter converter = (buffer, element) -> {
GimpleIntegerConstant constant = (GimpleIntegerConstant)element.getValue();
long l = constant.getValue();
buffer.putLong(l);
};

ByteBuffer buffer = constantArrayToBuffer(value, isElementType, converter, 4, 128);
if (buffer == null) return null;
LocalVar var = injectLoadableResource(mv, resourceWriter, buffer, "intArrayFromResource");
GimpleArrayType arrayType = (GimpleArrayType) value.getType();
return new VArrayExpr(arrayType, new VPtrExpr(var));
};

/**
* Specialised constructors for handling large string arrays
* Specialised constructors for handling large string and char arrays
*/

static ConstructorInterface stringArray = (mv, resourceWriter, value) -> {
Expand Down Expand Up @@ -188,14 +234,15 @@ private static ByteBuffer constantArrayToBuffer(
GimpleConstructor value,
Predicate<GimpleType> isElementType,
BufferConverter converter,
int byteSize
int byteSize,
int threshold
) {
boolean isArrayType = isArrayWithType(value.getType(), isElementType);
if (!isArrayType) {
return null;
}
List<GimpleConstructor.Element> elements = value.getElements();
if (elements.size() < 128) { // only stream large arrays
if (elements.size() < threshold) { // only stream large arrays
return null;
}
ByteBuffer buffer = ByteBuffer.allocate(elements.size() * byteSize).order(ByteOrder.LITTLE_ENDIAN);
Expand Down
Loading

0 comments on commit 795d927

Please sign in to comment.