Cast method arguments to method parameter types
This commit is contained in:
@@ -173,7 +173,7 @@ class SingleInstructionInterpreter(private val eval: Eval) : Interpreter<Value>(
|
|||||||
CHECKCAST -> {
|
CHECKCAST -> {
|
||||||
val targetType = Type.getObjectType((insn as TypeInsnNode).desc)
|
val targetType = Type.getObjectType((insn as TypeInsnNode).desc)
|
||||||
if (eval.isInstanceOf(value, targetType)) {
|
if (eval.isInstanceOf(value, targetType)) {
|
||||||
ObjectValue(value.obj, targetType)
|
ObjectValue(value.obj(), targetType)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throwEvalException(ClassCastException("Value '$value' cannot be cast to $targetType"))
|
throwEvalException(ClassCastException("Value '$value' cannot be cast to $targetType"))
|
||||||
@@ -200,8 +200,8 @@ class SingleInstructionInterpreter(private val eval: Eval) : Interpreter<Value>(
|
|||||||
IFGT -> value.int > 0
|
IFGT -> value.int > 0
|
||||||
IFLE -> value.int <= 0
|
IFLE -> value.int <= 0
|
||||||
IFGE -> value.int >= 0
|
IFGE -> value.int >= 0
|
||||||
IFNULL -> value.obj == null
|
IFNULL -> value.obj() == null
|
||||||
IFNONNULL -> value.obj != null
|
IFNONNULL -> value.obj() != null
|
||||||
else -> throw UnsupportedByteCodeException("Unknown opcode: $opcode")
|
else -> throw UnsupportedByteCodeException("Unknown opcode: $opcode")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -310,8 +310,8 @@ class SingleInstructionInterpreter(private val eval: Eval) : Interpreter<Value>(
|
|||||||
IF_ICMPLE -> value1.int <= value2.int
|
IF_ICMPLE -> value1.int <= value2.int
|
||||||
IF_ICMPGE -> value1.int >= value2.int
|
IF_ICMPGE -> value1.int >= value2.int
|
||||||
|
|
||||||
IF_ACMPEQ -> value1.obj == value2.obj
|
IF_ACMPEQ -> value1.obj() == value2.obj()
|
||||||
IF_ACMPNE -> value1.obj != value2.obj
|
IF_ACMPNE -> value1.obj() != value2.obj()
|
||||||
else -> throw UnsupportedByteCodeException("Unknown opcode: $opcode")
|
else -> throw UnsupportedByteCodeException("Unknown opcode: $opcode")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -151,7 +151,7 @@ fun interpreterLoop(
|
|||||||
val expectedType = Type.getReturnType(m.desc)
|
val expectedType = Type.getReturnType(m.desc)
|
||||||
if (expectedType.getSort() == Type.OBJECT) {
|
if (expectedType.getSort() == Type.OBJECT) {
|
||||||
val coerced = if (value != NULL_VALUE && value.asmType != expectedType)
|
val coerced = if (value != NULL_VALUE && value.asmType != expectedType)
|
||||||
ObjectValue(value.obj, expectedType)
|
ObjectValue(value.obj(), expectedType)
|
||||||
else value
|
else value
|
||||||
return ValueReturned(coerced)
|
return ValueReturned(coerced)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ class JDIEval(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun setArrayElement(array: Value, index: Value, newValue: Value) {
|
override fun setArrayElement(array: Value, index: Value, newValue: Value) {
|
||||||
array.array().setValue(index.int, newValue.asJdiValue(vm))
|
array.array().setValue(index.int, newValue.asJdiValue(vm, array.asmType.arrayElementType))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findField(fieldDesc: FieldDescription): jdi.Field {
|
private fun findField(fieldDesc: FieldDescription): jdi.Field {
|
||||||
@@ -131,7 +131,7 @@ class JDIEval(
|
|||||||
throwEvalException(NoSuchFieldError("Can't a field in a non-class: $field"))
|
throwEvalException(NoSuchFieldError("Can't a field in a non-class: $field"))
|
||||||
}
|
}
|
||||||
|
|
||||||
val jdiValue = newValue.asJdiValue(vm)
|
val jdiValue = newValue.asJdiValue(vm, field.`type`().asType())
|
||||||
mayThrow { _class.setValue(field, jdiValue) }
|
mayThrow { _class.setValue(field, jdiValue) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,7 +158,7 @@ class JDIEval(
|
|||||||
val _class = method.declaringType()
|
val _class = method.declaringType()
|
||||||
if (_class !is jdi.ClassType) throwEvalException(NoSuchMethodError("Static method is a non-class type: $method"))
|
if (_class !is jdi.ClassType) throwEvalException(NoSuchMethodError("Static method is a non-class type: $method"))
|
||||||
|
|
||||||
val args = arguments.map { v -> v.asJdiValue(vm) }
|
val args = mapArguments(arguments, method.argumentTypes())
|
||||||
val result = mayThrow { _class.invokeMethod(thread, method, args, 0) }
|
val result = mayThrow { _class.invokeMethod(thread, method, args, 0) }
|
||||||
return result.asValue()
|
return result.asValue()
|
||||||
}
|
}
|
||||||
@@ -174,7 +174,7 @@ class JDIEval(
|
|||||||
val field = findField(fieldDesc)
|
val field = findField(fieldDesc)
|
||||||
val obj = instance.jdiObj.checkNull()
|
val obj = instance.jdiObj.checkNull()
|
||||||
|
|
||||||
val jdiValue = newValue.asJdiValue(vm)
|
val jdiValue = newValue.asJdiValue(vm, field.`type`().asType())
|
||||||
mayThrow { obj.setValue(field, jdiValue) }
|
mayThrow { obj.setValue(field, jdiValue) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,7 +184,7 @@ class JDIEval(
|
|||||||
// Constructor call
|
// Constructor call
|
||||||
val ctor = findMethod(methodDesc)
|
val ctor = findMethod(methodDesc)
|
||||||
val _class = (instance as NewObjectValue).asmType.asReferenceType() as jdi.ClassType
|
val _class = (instance as NewObjectValue).asmType.asReferenceType() as jdi.ClassType
|
||||||
val args = arguments.map { v -> v.asJdiValue(vm) }
|
val args = mapArguments(arguments, ctor.argumentTypes())
|
||||||
val result = mayThrow { _class.newInstance(thread, ctor, args, 0) }
|
val result = mayThrow { _class.newInstance(thread, ctor, args, 0) }
|
||||||
instance.value = result
|
instance.value = result
|
||||||
return result.asValue()
|
return result.asValue()
|
||||||
@@ -197,10 +197,17 @@ class JDIEval(
|
|||||||
val method = findMethod(methodDesc)
|
val method = findMethod(methodDesc)
|
||||||
|
|
||||||
val obj = instance.jdiObj.checkNull()
|
val obj = instance.jdiObj.checkNull()
|
||||||
val args = arguments.map { v -> v.asJdiValue(vm) }
|
val args = mapArguments(arguments, method.argumentTypes())
|
||||||
val result = mayThrow { obj.invokeMethod(thread, method, args, 0) }
|
val result = mayThrow { obj.invokeMethod(thread, method, args, 0) }
|
||||||
return result.asValue()
|
return result.asValue()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun mapArguments(arguments: List<Value>, expecetedTypes: List<jdi.Type>): List<jdi.Value?> {
|
||||||
|
return arguments.zip(expecetedTypes).map {
|
||||||
|
val (arg, expectedType) = it
|
||||||
|
arg.asJdiValue(vm, expectedType.asType())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T> mayThrow(f: () -> T): T {
|
fun <T> mayThrow(f: () -> T): T {
|
||||||
|
|||||||
@@ -52,16 +52,16 @@ fun jdi.Value?.asValue(): Value {
|
|||||||
fun jdi.Type.asType(): Type = Type.getType(this.signature())
|
fun jdi.Type.asType(): Type = Type.getType(this.signature())
|
||||||
|
|
||||||
val Value.jdiObj: jdi.ObjectReference?
|
val Value.jdiObj: jdi.ObjectReference?
|
||||||
get() = this.obj as jdi.ObjectReference?
|
get() = this.obj() as jdi.ObjectReference?
|
||||||
|
|
||||||
val Value.jdiClass: jdi.ClassObjectReference?
|
val Value.jdiClass: jdi.ClassObjectReference?
|
||||||
get() = this.jdiObj as jdi.ClassObjectReference?
|
get() = this.jdiObj as jdi.ClassObjectReference?
|
||||||
|
|
||||||
fun Value.asJdiValue(vm: jdi.VirtualMachine): jdi.Value? {
|
fun Value.asJdiValue(vm: jdi.VirtualMachine, expectedType: Type): jdi.Value? {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
NULL_VALUE -> null
|
NULL_VALUE -> null
|
||||||
VOID_VALUE -> vm.mirrorOfVoid()
|
VOID_VALUE -> vm.mirrorOfVoid()
|
||||||
is IntValue -> when (asmType) {
|
is IntValue -> when (expectedType) {
|
||||||
Type.BOOLEAN_TYPE -> vm.mirrorOf(boolean)
|
Type.BOOLEAN_TYPE -> vm.mirrorOf(boolean)
|
||||||
Type.BYTE_TYPE -> vm.mirrorOf(int.toByte())
|
Type.BYTE_TYPE -> vm.mirrorOf(int.toByte())
|
||||||
Type.SHORT_TYPE -> vm.mirrorOf(int.toShort())
|
Type.SHORT_TYPE -> vm.mirrorOf(int.toShort())
|
||||||
@@ -73,7 +73,7 @@ fun Value.asJdiValue(vm: jdi.VirtualMachine): jdi.Value? {
|
|||||||
is FloatValue -> vm.mirrorOf(value)
|
is FloatValue -> vm.mirrorOf(value)
|
||||||
is DoubleValue -> vm.mirrorOf(value)
|
is DoubleValue -> vm.mirrorOf(value)
|
||||||
is ObjectValue -> value as jdi.ObjectReference
|
is ObjectValue -> value as jdi.ObjectReference
|
||||||
is NewObjectValue -> this.obj as jdi.ObjectReference
|
is NewObjectValue -> this.obj() as jdi.ObjectReference
|
||||||
else -> throw JDIFailureException("Unknown value: $this")
|
else -> throw JDIFailureException("Unknown value: $this")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -89,15 +89,21 @@ val Value.int: Int get() = (this as IntValue).value
|
|||||||
val Value.long: Long get() = (this as LongValue).value
|
val Value.long: Long get() = (this as LongValue).value
|
||||||
val Value.float: Float get() = (this as FloatValue).value
|
val Value.float: Float get() = (this as FloatValue).value
|
||||||
val Value.double: Double get() = (this as DoubleValue).value
|
val Value.double: Double get() = (this as DoubleValue).value
|
||||||
val Value.obj: Any?
|
fun Value.obj(expectedType: Type = asmType): Any? {
|
||||||
get(): Any? {
|
if (this is NewObjectValue) {
|
||||||
if (this is NewObjectValue) {
|
val v = value
|
||||||
val v = value
|
if (v == null) throw IllegalStateException("Trying to access an unitialized object: $this")
|
||||||
if (v == null) throw IllegalStateException("Trying to access an unitialized object: $this")
|
return v
|
||||||
return v
|
|
||||||
}
|
|
||||||
return (this as AbstractValue<*>).value
|
|
||||||
}
|
}
|
||||||
|
return when {
|
||||||
|
expectedType == asmType -> (this as AbstractValue<*>).value
|
||||||
|
expectedType == Type.BOOLEAN_TYPE -> this.boolean
|
||||||
|
expectedType == Type.SHORT_TYPE -> (this as IntValue).int.toShort()
|
||||||
|
expectedType == Type.BYTE_TYPE -> (this as IntValue).int.toByte()
|
||||||
|
expectedType == Type.CHAR_TYPE -> (this as IntValue).int.toChar()
|
||||||
|
else -> (this as AbstractValue<*>).value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun <T: Any> T?.checkNull(): T {
|
fun <T: Any> T?.checkNull(): T {
|
||||||
if (this == null) {
|
if (this == null) {
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ fun suite(): TestSuite {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (expected is ValueReturned && value is ValueReturned && value.result is ObjectValue) {
|
if (expected is ValueReturned && value is ValueReturned && value.result is ObjectValue) {
|
||||||
assertEquals(expected.result.obj.toString(), value.result.jdiObj.callToString())
|
assertEquals(expected.result.obj().toString(), value.result.jdiObj.callToString())
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assertEquals(expected, value)
|
assertEquals(expected, value)
|
||||||
|
|||||||
@@ -48,6 +48,91 @@ class TestData {
|
|||||||
return "str";
|
return "str";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Integer integerValueOf() { return 1; }
|
||||||
|
|
||||||
|
static Byte byteValueOf() { return 1; }
|
||||||
|
|
||||||
|
static Short shortValueOf() { return 1; }
|
||||||
|
|
||||||
|
static Long longValueOf() { return 1L; }
|
||||||
|
|
||||||
|
static Float floatValueOf() { return 1.0f; }
|
||||||
|
|
||||||
|
static Double doubleValueOf() { return 1.0; }
|
||||||
|
|
||||||
|
static Character charValueOf() { return 1; }
|
||||||
|
|
||||||
|
static Boolean booleanValueOf() { return true; }
|
||||||
|
|
||||||
|
static void castFieldTypes() {
|
||||||
|
CastFieldType.i = 1;
|
||||||
|
CastFieldType.b = 1;
|
||||||
|
CastFieldType.s = 1;
|
||||||
|
CastFieldType.c = 1;
|
||||||
|
CastFieldType.bool = true;
|
||||||
|
CastFieldType.l = 1;
|
||||||
|
CastFieldType.f = 1.0f;
|
||||||
|
CastFieldType.d = 1.0;
|
||||||
|
|
||||||
|
CastFieldType klass = new CastFieldType();
|
||||||
|
klass.im = 1;
|
||||||
|
klass.bm = 1;
|
||||||
|
klass.sm = 1;
|
||||||
|
klass.cm = 1;
|
||||||
|
klass.boolm = true;
|
||||||
|
klass.lm = 1;
|
||||||
|
klass.fm = 1;
|
||||||
|
klass.dm = 1;
|
||||||
|
|
||||||
|
Integer i = klass.im;
|
||||||
|
Byte b = klass.bm;
|
||||||
|
Short s = klass.sm;
|
||||||
|
Character c = klass.cm;
|
||||||
|
Boolean bool = klass.boolm;
|
||||||
|
Long l = klass.lm;
|
||||||
|
Float f = klass.fm;
|
||||||
|
Double d = klass.dm;
|
||||||
|
}
|
||||||
|
|
||||||
|
static class CastFieldType {
|
||||||
|
static int i = 1;
|
||||||
|
static byte b = 1;
|
||||||
|
static short s = 1;
|
||||||
|
static char c = 1;
|
||||||
|
static boolean bool = true;
|
||||||
|
static long l = 1;
|
||||||
|
static float f = 1;
|
||||||
|
static double d = 1;
|
||||||
|
|
||||||
|
int im = 1;
|
||||||
|
byte bm = 1;
|
||||||
|
short sm = 1;
|
||||||
|
char cm = 1;
|
||||||
|
boolean boolm = true;
|
||||||
|
long lm = 1;
|
||||||
|
float fm = 1;
|
||||||
|
double dm = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void castArrayElementType() {
|
||||||
|
int[] i = new int[1];
|
||||||
|
i[0] = 1;
|
||||||
|
short[] s = new short[1];
|
||||||
|
s[0] = 1;
|
||||||
|
byte[] b = new byte[1];
|
||||||
|
b[0] = 1;
|
||||||
|
char[] c = new char[1];
|
||||||
|
c[0] = 1;
|
||||||
|
boolean[] bool = new boolean[1];
|
||||||
|
bool[0] = true;
|
||||||
|
long[] l = new long[1];
|
||||||
|
l[0] = 1;
|
||||||
|
float[] f = new float[1];
|
||||||
|
f[0] = 1;
|
||||||
|
double[] d = new double[1];
|
||||||
|
d[0] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int variable() {
|
static int variable() {
|
||||||
int i = 153;
|
int i = 153;
|
||||||
return i;
|
return i;
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ object REFLECTION_EVAL : Eval {
|
|||||||
|
|
||||||
override fun isInstanceOf(value: Value, targetType: Type): Boolean {
|
override fun isInstanceOf(value: Value, targetType: Type): Boolean {
|
||||||
val _class = findClass(targetType)
|
val _class = findClass(targetType)
|
||||||
return _class.isInstance(value.obj)
|
return _class.isInstance(value.obj())
|
||||||
}
|
}
|
||||||
|
|
||||||
[suppress("UNCHECKED_CAST")]
|
[suppress("UNCHECKED_CAST")]
|
||||||
@@ -109,13 +109,13 @@ object REFLECTION_EVAL : Eval {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getArrayLength(array: Value): Value {
|
override fun getArrayLength(array: Value): Value {
|
||||||
return int(JArray.getLength(array.obj.checkNull()))
|
return int(JArray.getLength(array.obj().checkNull()))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getArrayElement(array: Value, index: Value): Value {
|
override fun getArrayElement(array: Value, index: Value): Value {
|
||||||
val asmType = array.asmType
|
val asmType = array.asmType
|
||||||
val elementType = if (asmType.getDimensions() == 1) asmType.getElementType() else Type.getType(asmType.getDescriptor().substring(1))
|
val elementType = if (asmType.getDimensions() == 1) asmType.getElementType() else Type.getType(asmType.getDescriptor().substring(1))
|
||||||
val arr = array.obj.checkNull()
|
val arr = array.obj().checkNull()
|
||||||
val ind = index.int
|
val ind = index.int
|
||||||
return when (elementType.getSort()) {
|
return when (elementType.getSort()) {
|
||||||
Type.BOOLEAN -> boolean(JArray.getBoolean(arr, ind))
|
Type.BOOLEAN -> boolean(JArray.getBoolean(arr, ind))
|
||||||
@@ -136,10 +136,10 @@ object REFLECTION_EVAL : Eval {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun setArrayElement(array: Value, index: Value, newValue: Value) {
|
override fun setArrayElement(array: Value, index: Value, newValue: Value) {
|
||||||
val arr = array.obj.checkNull()
|
val arr = array.obj().checkNull()
|
||||||
val ind = index.int
|
val ind = index.int
|
||||||
if (array.asmType.getDimensions() > 1) {
|
if (array.asmType.getDimensions() > 1) {
|
||||||
JArray.set(arr, ind, newValue.obj)
|
JArray.set(arr, ind, newValue.obj())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val elementType = array.asmType.getElementType()
|
val elementType = array.asmType.getElementType()
|
||||||
@@ -154,7 +154,7 @@ object REFLECTION_EVAL : Eval {
|
|||||||
Type.DOUBLE -> JArray.setDouble(arr, ind, newValue.double)
|
Type.DOUBLE -> JArray.setDouble(arr, ind, newValue.double)
|
||||||
Type.OBJECT,
|
Type.OBJECT,
|
||||||
Type.ARRAY -> {
|
Type.ARRAY -> {
|
||||||
JArray.set(arr, ind, newValue.obj)
|
JArray.set(arr, ind, newValue.obj())
|
||||||
}
|
}
|
||||||
else -> throw UnsupportedOperationException("Unsupported array element type: $elementType")
|
else -> throw UnsupportedOperationException("Unsupported array element type: $elementType")
|
||||||
}
|
}
|
||||||
@@ -183,7 +183,7 @@ object REFLECTION_EVAL : Eval {
|
|||||||
|
|
||||||
override fun setStaticField(fieldDesc: FieldDescription, newValue: Value) {
|
override fun setStaticField(fieldDesc: FieldDescription, newValue: Value) {
|
||||||
val field = findStaticField(fieldDesc)
|
val field = findStaticField(fieldDesc)
|
||||||
val obj = newValue.obj
|
val obj = newValue.obj(fieldDesc.fieldType)
|
||||||
mayThrow {field.set(null, obj)}
|
mayThrow {field.set(null, obj)}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,7 +199,7 @@ object REFLECTION_EVAL : Eval {
|
|||||||
assertTrue(methodDesc.isStatic)
|
assertTrue(methodDesc.isStatic)
|
||||||
val method = findClass(methodDesc).findMethod(methodDesc)
|
val method = findClass(methodDesc).findMethod(methodDesc)
|
||||||
assertNotNull("Method not found: $methodDesc", method)
|
assertNotNull("Method not found: $methodDesc", method)
|
||||||
val args = arguments.map { v -> v.obj }.copyToArray()
|
val args = mapArguments(arguments, methodDesc.parameterTypes).copyToArray()
|
||||||
val result = mayThrow {method!!.invoke(null, *args)}
|
val result = mayThrow {method!!.invoke(null, *args)}
|
||||||
return objectToValue(result, methodDesc.returnType)
|
return objectToValue(result, methodDesc.returnType)
|
||||||
}
|
}
|
||||||
@@ -213,17 +213,17 @@ object REFLECTION_EVAL : Eval {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getField(instance: Value, fieldDesc: FieldDescription): Value {
|
override fun getField(instance: Value, fieldDesc: FieldDescription): Value {
|
||||||
val obj = instance.obj.checkNull()
|
val obj = instance.obj().checkNull()
|
||||||
val field = findInstanceField(obj, fieldDesc)
|
val field = findInstanceField(obj, fieldDesc)
|
||||||
|
|
||||||
return objectToValue(mayThrow {field.get(obj)}, fieldDesc.fieldType)
|
return objectToValue(mayThrow {field.get(obj)}, fieldDesc.fieldType)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setField(instance: Value, fieldDesc: FieldDescription, newValue: Value) {
|
override fun setField(instance: Value, fieldDesc: FieldDescription, newValue: Value) {
|
||||||
val obj = instance.obj.checkNull()
|
val obj = instance.obj().checkNull()
|
||||||
val field = findInstanceField(obj, fieldDesc)
|
val field = findInstanceField(obj, fieldDesc)
|
||||||
|
|
||||||
val newObj = newValue.obj
|
val newObj = newValue.obj(fieldDesc.fieldType)
|
||||||
mayThrow {field.set(obj, newObj)}
|
mayThrow {field.set(obj, newObj)}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,7 +242,7 @@ object REFLECTION_EVAL : Eval {
|
|||||||
val _class = findClass((instance as NewObjectValue).asmType)
|
val _class = findClass((instance as NewObjectValue).asmType)
|
||||||
val ctor = _class.findConstructor(methodDesc)
|
val ctor = _class.findConstructor(methodDesc)
|
||||||
assertNotNull("Constructor not found: $methodDesc", ctor)
|
assertNotNull("Constructor not found: $methodDesc", ctor)
|
||||||
val args = arguments.map { v -> v.obj }.copyToArray()
|
val args = mapArguments(arguments, methodDesc.parameterTypes).copyToArray()
|
||||||
val result = mayThrow {ctor!!.newInstance(*args)}
|
val result = mayThrow {ctor!!.newInstance(*args)}
|
||||||
instance.value = result
|
instance.value = result
|
||||||
return objectToValue(result, instance.asmType)
|
return objectToValue(result, instance.asmType)
|
||||||
@@ -252,13 +252,20 @@ object REFLECTION_EVAL : Eval {
|
|||||||
throw UnsupportedOperationException("invokespecial is not suported yet")
|
throw UnsupportedOperationException("invokespecial is not suported yet")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val obj = instance.obj.checkNull()
|
val obj = instance.obj().checkNull()
|
||||||
val method = obj.javaClass.findMethod(methodDesc)
|
val method = obj.javaClass.findMethod(methodDesc)
|
||||||
assertNotNull("Method not found: $methodDesc", method)
|
assertNotNull("Method not found: $methodDesc", method)
|
||||||
val args = arguments.map { v -> v.obj }.copyToArray()
|
val args = mapArguments(arguments, methodDesc.parameterTypes).copyToArray()
|
||||||
val result = mayThrow {method!!.invoke(obj, *args)}
|
val result = mayThrow {method!!.invoke(obj, *args)}
|
||||||
return objectToValue(result, methodDesc.returnType)
|
return objectToValue(result, methodDesc.returnType)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun mapArguments(arguments: List<Value>, expecetedTypes: List<Type>): List<Any?> {
|
||||||
|
return arguments.zip(expecetedTypes).map {
|
||||||
|
val (arg, expectedType) = it
|
||||||
|
arg.obj(expectedType)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ReflectionLookup(val classLoader: ClassLoader) {
|
class ReflectionLookup(val classLoader: ClassLoader) {
|
||||||
|
|||||||
Reference in New Issue
Block a user