-
Notifications
You must be signed in to change notification settings - Fork 35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Primitive, non boxing, long array based MStack #531
Conversation
update: I benchmarked the interpreter and got good improvements on this branch, I think it's in the right direction! |
emitBoxArguments(asm, type.params()); | ||
// emitBoxArguments(asm, type.params()); | ||
// asm.visitLdcInsn(LONG); | ||
for (int i = 0; i < type.params().size(); i++) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs to use slotCount()
to compute the slot parameter correctly, as long/double use two slots in JVM bytecode. This annoyance means you always need to know the type you are dealing with.
The incoming parameters to this method are a native Java value: int, long, float, double
cf3c868
to
22226f5
Compare
I did a little benchmarking on my super noisy machine(take the results with a lot of salt):
|
CI is green, ready for final review! And thanks to @evacchi that paired and kept me sane in getting there with the AOT! |
this is exciting! |
Begging for review here 🙏 cc. @bhelx @electrum @danielperano |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should be fine, but I think it would be better to have another pair of eyes on it :)
default: | ||
throw new IllegalArgumentException("Unsupported ValueType: " + type.name()); | ||
} | ||
} | ||
|
||
public static Method boxer(ValueType type) { | ||
public static Method convertToLong(ValueType type) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
public static void emitJvmToLong(MethodVisitor asm, ValueType type) {
switch (type) {
case I32:
case ExternRef:
case FuncRef:
asm.visitInsn(Opcodes.I2L);
return;
case I64:
return;
case F32:
emitInvokeStatic(asm, F32_TO_LONG);
return;
case F64:
emitInvokeStatic(asm, F64_TO_LONG);
return;
}
}
default: | ||
throw new IllegalArgumentException("Unsupported ValueType: " + type.name()); | ||
} | ||
} | ||
|
||
public static MethodHandle unboxerHandle(ValueType type) { | ||
public static MethodHandle convertFromLongHandle(ValueType type) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
longToJvmHandle
} catch (IllegalAccessException e) { | ||
throw new AssertionError(e); | ||
} | ||
} | ||
|
||
public static MethodHandle boxerHandle(ValueType type) { | ||
public static MethodHandle convertToLongHandle(ValueType type) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
jvmToLongHandle
aot-tests/pom.xml
Outdated
@@ -50,6 +50,12 @@ | |||
<artifactId>junit-jupiter-engine</artifactId> | |||
<scope>test</scope> | |||
</dependency> | |||
<!-- Enable better debugging --> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we simply remove the <optional>true</optional>
from AOT, so that this is always available? The only downside is the additional size of the asm-util
JAR.
// From long | ||
public static int toInt(long val) { | ||
return (int) val; | ||
} | ||
|
||
public static long toLong(long val) { | ||
return val; | ||
} | ||
|
||
public static float toFloat(long val) { | ||
return Value.longToFloat(val); | ||
} | ||
|
||
public static double toDouble(long val) { | ||
return Value.longToDouble(val); | ||
} | ||
|
||
// To Long | ||
public static long asLong(int val) { | ||
return val; | ||
} | ||
|
||
public static long asLong(long val) { | ||
return val; | ||
} | ||
|
||
public static long asLong(float val) { | ||
return Value.floatToLong(val); | ||
} | ||
|
||
public static long asLong(double val) { | ||
return Value.doubleToLong(val); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's name these the same as the method constants. I find the overloads hard to read.
// From long | |
public static int toInt(long val) { | |
return (int) val; | |
} | |
public static long toLong(long val) { | |
return val; | |
} | |
public static float toFloat(long val) { | |
return Value.longToFloat(val); | |
} | |
public static double toDouble(long val) { | |
return Value.longToDouble(val); | |
} | |
// To Long | |
public static long asLong(int val) { | |
return val; | |
} | |
public static long asLong(long val) { | |
return val; | |
} | |
public static long asLong(float val) { | |
return Value.floatToLong(val); | |
} | |
public static long asLong(double val) { | |
return Value.doubleToLong(val); | |
} | |
public static int longToI32(long val) { | |
return (int) val; | |
} | |
public static long longToI64(long val) { | |
return val; | |
} | |
public static float longToF32(long val) { | |
return Value.longToFloat(val); | |
} | |
public static double longToF64(long val) { | |
return Value.longToDouble(val); | |
} | |
public static long i32ToLong(int val) { | |
return val; | |
} | |
public static long i64ToLong(long val) { | |
return val; | |
} | |
public static long f32ToLong(float val) { | |
return Value.floatToLong(val); | |
} | |
public static long f64ToLong(double val) { | |
return Value.doubleToLong(val); | |
} |
I64_2_LONG = ValueConversions.class.getMethod("asLong", long.class); | ||
F32_2_LONG = ValueConversions.class.getMethod("asLong", float.class); | ||
F64_2_LONG = ValueConversions.class.getMethod("asLong", double.class); | ||
EXTREF_2_LONG = ValueConversions.class.getMethod("asLong", int.class); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need for these anymore, as they are the same as the i32
version.
try { | ||
return publicLookup().unreflect(unboxer(type)); | ||
return publicLookup().unreflect(convertFromLong(type)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we no longer have the Method
version of the conversion functions, we'll probably want to add constants for the method handles and make this a switch statement.
arguments.add(new MethodCallExpr(argExpr, "asFloat")); | ||
arguments.add( | ||
new MethodCallExpr( | ||
new NameExpr("Float"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should these use the new methods in Value
?
@@ -567,6 +567,7 @@ | |||
<ignoredUnusedDeclaredDependencies> | |||
<dependency>com.dylibso.chicory:wasm-corpus</dependency> | |||
<dependency>org.junit.jupiter:junit-jupiter-engine</dependency> | |||
<dependency>org.ow2.asm:asm-util</dependency> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's make this a non-optional dependency in AOT
} | ||
if (type.returns().size() > 1) { | ||
return result; | ||
} | ||
result = filterReturnValue(result, boxerHandle(type.returns().get(0))); | ||
return filterReturnValue(result, ValueWrapper.HANDLE); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think ValueWrapper
is unused now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
now it's a LongArrayWrapper
to: long -> long[]
4dffefe
to
c6f1cd6
Compare
ok, let's merge this, any follow up comment will be fixed on top. |
Supersede #447 this is a complete implementation, already passing all the tests up to the interpreter, can be tested with something like:
I started, but got a bit confused about the changes necessary in "aot", @electrum or @danielperano I would love some help in finalizing this PR 🙏 and learning a bit more how
asm
works ...This is a prerequisite to avoid arrays construction here, the plan is to open up the underlying array so that we can perform operations just using the offset 🤞