Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
gluon-bot committed Nov 2, 2023
2 parents bad7b12 + 635d2d0 commit 43bb6b3
Show file tree
Hide file tree
Showing 24 changed files with 892 additions and 370 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,7 @@ private static String readFully(final Reader reader) throws IOException {

try {
int numChars;
while ((numChars = reader.read(arr, 0, arr.length)) > 0) {
while ((numChars = reader.read(arr, 0, arr.length)) >= 0) {
sb.append(arr, 0, numChars);
}
} finally {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import java.util.Map;
import java.util.Set;

import com.oracle.truffle.espresso.impl.ArrayKlass;
import org.graalvm.collections.EconomicMap;
import org.graalvm.collections.UnmodifiableEconomicMap;
import org.graalvm.options.OptionMap;
Expand Down Expand Up @@ -141,6 +142,14 @@ private void addInternalConverters(Meta meta) {
} else {
warn(current, meta.getContext());
}
converters.put("byte[]", new PrimitiveArrayConverter(meta._byte_array));
converters.put("boolean[]", new PrimitiveArrayConverter(meta._boolean_array));
converters.put("char[]", new PrimitiveArrayConverter(meta._char_array));
converters.put("short[]", new PrimitiveArrayConverter(meta._short_array));
converters.put("int[]", new PrimitiveArrayConverter(meta._int_array));
converters.put("long[]", new PrimitiveArrayConverter(meta._long_array));
converters.put("float[]", new PrimitiveArrayConverter(meta._float_array));
converters.put("double[]", new PrimitiveArrayConverter(meta._double_array));
internalTypeConverterFunctions = EconomicMap.create(converters);
}

Expand Down Expand Up @@ -331,4 +340,21 @@ private StaticObject toByteArray(BigInteger bigInteger, Meta meta) {
return StaticObject.wrap(bigInteger.toByteArray(), meta);
}
}

public final class PrimitiveArrayConverter implements InternalTypeConverter {

private final ArrayKlass klass;

public PrimitiveArrayConverter(ArrayKlass klass) {
this.klass = klass;
}

@Override
public StaticObject convertInternal(InteropLibrary interop, Object value, Meta meta, ToReference.DynamicToReference toEspresso) {
if (!interop.hasArrayElements(value)) {
throw new ClassCastException();
}
return StaticObject.createForeign(toEspresso.getLanguage(), klass, value, interop);
}
}
}

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ public int getArrayInt(EspressoLanguage language, int index, @JavaType(int[].cla
}

@TruffleBoundary
private static String outOfBoundsMessage(int index, int length) {
public static String outOfBoundsMessage(int index, int length) {
return "Index " + index + " out of bounds for length " + length;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2531,15 +2531,31 @@ private Map<String, String> buildPropertiesMap() {

@VmImpl(isJni = true)
public int JVM_GetArrayLength(@JavaType(Object.class) StaticObject array, @Inject EspressoLanguage language, @Inject SubstitutionProfiler profiler) {
try {
return Array.getLength(MetaUtil.unwrapArrayOrNull(language, array));
} catch (IllegalArgumentException e) {
profiler.profile(0);
Meta meta = getMeta();
throw meta.throwExceptionWithMessage(meta.java_lang_IllegalArgumentException, e.getMessage());
} catch (NullPointerException e) {
profiler.profile(1);
throw getMeta().throwNullPointerException();
if (array.isForeignObject()) {
try {
Object foreignObject = array.rawForeignObject(language);
InteropLibrary library = InteropLibrary.getUncached(foreignObject);
long arrayLength = library.getArraySize(foreignObject);
if (arrayLength > Integer.MAX_VALUE) {
return Integer.MAX_VALUE;
}
return (int) arrayLength;
} catch (UnsupportedMessageException e) {
profiler.profile(0);
Meta meta = getMeta();
throw meta.throwExceptionWithMessage(meta.java_lang_IllegalArgumentException, "can't get array length because foreign object is not an array");
}
} else {
try {
return Array.getLength(MetaUtil.unwrapArrayOrNull(language, array));
} catch (IllegalArgumentException e) {
profiler.profile(1);
Meta meta = getMeta();
throw meta.throwExceptionWithMessage(meta.java_lang_IllegalArgumentException, e.getMessage());
} catch (NullPointerException e) {
profiler.profile(2);
throw getMeta().throwNullPointerException();
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,31 +187,37 @@ private boolean verifyFieldValue(JavaConstant receiver, AnalysisField field, Jav
if (field.isStatic()) {
TypeData typeData = field.getDeclaringClass().getOrComputeData();
JavaConstant fieldSnapshot = typeData.readFieldValue(field);
verifyStaticFieldValue(typeData, field, maybeUnwrapSnapshot(fieldSnapshot, fieldValue instanceof ImageHeapConstant), fieldValue, reason);
verifyStaticFieldValue(typeData, field, fieldSnapshot, fieldValue, reason);
} else {
ImageHeapInstance receiverObject = (ImageHeapInstance) getReceiverObject(receiver, reason);
ImageHeapInstance receiverObject = (ImageHeapInstance) getSnapshot(receiver, reason);
JavaConstant fieldSnapshot = receiverObject.readFieldValue(field);
verifyInstanceFieldValue(field, receiver, receiverObject, maybeUnwrapSnapshot(fieldSnapshot, fieldValue instanceof ImageHeapConstant), fieldValue, reason);
verifyInstanceFieldValue(field, receiver, receiverObject, fieldSnapshot, fieldValue, reason);
}
return false;
}

private void verifyStaticFieldValue(TypeData typeData, AnalysisField field, JavaConstant fieldSnapshot, JavaConstant fieldValue, ScanReason reason) {
if (!Objects.equals(fieldSnapshot, fieldValue)) {
JavaConstant result = fieldSnapshot;
JavaConstant unwrappedSnapshot = maybeUnwrapSnapshot(fieldSnapshot, fieldValue instanceof ImageHeapConstant);
if (!Objects.equals(unwrappedSnapshot, fieldValue)) {
String format = "Value mismatch for static field %s %n snapshot: %s %n new value: %s %n";
Consumer<ScanReason> onAnalysisModified = analysisModified(reason, format, field, fieldSnapshot, fieldValue);
scanner.patchStaticField(typeData, field, fieldValue, reason, onAnalysisModified).ensureDone();
Consumer<ScanReason> onAnalysisModified = analysisModified(reason, format, field, unwrappedSnapshot, fieldValue);
result = scanner.patchStaticField(typeData, field, fieldValue, reason, onAnalysisModified).ensureDone();
heapPatched = true;
}
ImageHeapScanner.ensureReaderInstalled(result);
}

private void verifyInstanceFieldValue(AnalysisField field, JavaConstant receiver, ImageHeapInstance receiverObject, JavaConstant fieldSnapshot, JavaConstant fieldValue, ScanReason reason) {
if (!Objects.equals(fieldSnapshot, fieldValue)) {
JavaConstant result = fieldSnapshot;
JavaConstant unwrappedSnapshot = maybeUnwrapSnapshot(fieldSnapshot, fieldValue instanceof ImageHeapConstant);
if (!Objects.equals(unwrappedSnapshot, fieldValue)) {
String format = "Value mismatch for instance field %s of %s %n snapshot: %s %n new value: %s %n";
Consumer<ScanReason> onAnalysisModified = analysisModified(reason, format, field, asString(receiver), fieldSnapshot, fieldValue);
scanner.patchInstanceField(receiverObject, field, fieldValue, reason, onAnalysisModified).ensureDone();
Consumer<ScanReason> onAnalysisModified = analysisModified(reason, format, field, asString(receiver), unwrappedSnapshot, fieldValue);
result = scanner.patchInstanceField(receiverObject, field, fieldValue, reason, onAnalysisModified).ensureDone();
heapPatched = true;
}
ImageHeapScanner.ensureReaderInstalled(result);
}

private Consumer<ScanReason> analysisModified(ScanReason reason, String format, Object... args) {
Expand Down Expand Up @@ -249,40 +255,48 @@ public boolean forNonNullArrayElement(JavaConstant array, AnalysisType arrayType
* fields that become available but may have not yet been consumed. We simply execute
* the future, then compare the produced value.
*/
ImageHeapObjectArray arrayObject = (ImageHeapObjectArray) getReceiverObject(array, reason);
ImageHeapObjectArray arrayObject = (ImageHeapObjectArray) getSnapshot(array, reason);
JavaConstant elementSnapshot = arrayObject.readElementValue(index);
verifyArrayElementValue(elementValue, index, reason, array, arrayObject, elementSnapshot);
return false;
}

private void verifyArrayElementValue(JavaConstant elementValue, int index, ScanReason reason, JavaConstant array, ImageHeapObjectArray arrayObject, JavaConstant elementSnapshot) {
JavaConstant result = elementSnapshot;
if (!Objects.equals(maybeUnwrapSnapshot(elementSnapshot, elementValue instanceof ImageHeapConstant), elementValue)) {
String format = "Value mismatch for array element at index %s of %s %n snapshot: %s %n new value: %s %n";
Consumer<ScanReason> onAnalysisModified = analysisModified(reason, format, index, asString(array), elementSnapshot, elementValue);
scanner.patchArrayElement(arrayObject, index, elementValue, reason, onAnalysisModified).ensureDone();
result = scanner.patchArrayElement(arrayObject, index, elementValue, reason, onAnalysisModified).ensureDone();
heapPatched = true;
}
ImageHeapScanner.ensureReaderInstalled(result);
}

@SuppressWarnings({"unchecked", "rawtypes"})
private ImageHeapConstant getReceiverObject(JavaConstant constant, ScanReason reason) {
private ImageHeapConstant getSnapshot(JavaConstant constant, ScanReason reason) {
ImageHeapConstant result;
if (constant instanceof ImageHeapConstant) {
/* This is a simulated constant. */
return (ImageHeapConstant) constant;
}
Object task = imageHeap.getSnapshot(constant);
if (task == null) {
throw error(reason, "Task is null for constant %s.", constant);
} else if (task instanceof ImageHeapConstant) {
return (ImageHeapConstant) task;
result = (ImageHeapConstant) constant;
} else {
AnalysisFuture<ImageHeapConstant> future = ((AnalysisFuture<ImageHeapConstant>) task);
if (future.isDone()) {
return future.guardedGet();
Object task = imageHeap.getSnapshot(constant);
if (task == null) {
throw error(reason, "Task is null for constant %s.", constant);
} else if (task instanceof ImageHeapConstant) {
result = (ImageHeapConstant) task;
} else {
throw error(reason, "Task not yet executed for constant %s.", constant);
AnalysisFuture<ImageHeapConstant> future = ((AnalysisFuture<ImageHeapConstant>) task);
if (future.isDone()) {
result = future.guardedGet();
} else {
throw error(reason, "Task not yet executed for constant %s.", constant);
}
}
}
if (!result.isReaderInstalled()) {
throw error(reason, "Reader not yet installed for constant %s.", constant);
}
return result;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
import com.oracle.graal.pointsto.meta.AnalysisType;

import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.ResolvedJavaType;

public abstract class ImageHeapArray extends ImageHeapConstant {

Expand All @@ -36,9 +35,9 @@ public static ImageHeapArray create(AnalysisType type, int length) {
return type.getComponentType().getStorageKind().isPrimitive() ? new ImageHeapPrimitiveArray(type, length) : new ImageHeapObjectArray(type, length);
}

protected ImageHeapArray(ResolvedJavaType type, JavaConstant object, int identityHashCode, boolean compressed) {
super(type, object, identityHashCode, compressed);
assert type.isArray() : type;
protected ImageHeapArray(ConstantData constantData, boolean compressed) {
super(constantData, compressed);
assert constantData.type.isArray() : constantData.type;
}

public abstract Object getElement(int idx);
Expand Down
Loading

0 comments on commit 43bb6b3

Please sign in to comment.