Skip to content

Commit e35ed3a

Browse files
committed
Optimize invalid/indefinite value check in trapping float to integer truncation (i32/i64.trunc_f32/f64_s/u).
Move the NaN check from the fast path into the error handling slow path.
1 parent 4a0f907 commit e35ed3a

File tree

1 file changed

+56
-67
lines changed

1 file changed

+56
-67
lines changed

wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/nodes/WasmFunctionNode.java

Lines changed: 56 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -118,25 +118,6 @@
118118
* instrument gets notified that a certain line in the source code was reached.
119119
*/
120120
public final class WasmFunctionNode extends Node implements BytecodeOSRNode {
121-
private static final float MIN_FLOAT_TRUNCATABLE_TO_INT = Integer.MIN_VALUE;
122-
private static final float MAX_FLOAT_TRUNCATABLE_TO_INT = 2147483520f;
123-
private static final float MIN_FLOAT_TRUNCATABLE_TO_U_INT = -0.99999994f;
124-
private static final float MAX_FLOAT_TRUNCATABLE_TO_U_INT = 4294967040f;
125-
126-
private static final double MIN_DOUBLE_TRUNCATABLE_TO_INT = -2147483648.9999997;
127-
private static final double MAX_DOUBLE_TRUNCATABLE_TO_INT = 2147483647.9999998;
128-
private static final double MIN_DOUBLE_TRUNCATABLE_TO_U_INT = -0.9999999999999999;
129-
private static final double MAX_DOUBLE_TRUNCATABLE_TO_U_INT = 4294967295.9999995;
130-
131-
private static final float MIN_FLOAT_TRUNCATABLE_TO_LONG = Long.MIN_VALUE;
132-
private static final float MAX_FLOAT_TRUNCATABLE_TO_LONG = 9223371487098961900.0f;
133-
private static final float MIN_FLOAT_TRUNCATABLE_TO_U_LONG = MIN_FLOAT_TRUNCATABLE_TO_U_INT;
134-
private static final float MAX_FLOAT_TRUNCATABLE_TO_U_LONG = 18446742974197924000.0f;
135-
136-
private static final double MIN_DOUBLE_TRUNCATABLE_TO_LONG = Long.MIN_VALUE;
137-
private static final double MAX_DOUBLE_TRUNCATABLE_TO_LONG = 9223372036854774800.0;
138-
private static final double MIN_DOUBLE_TRUNCATABLE_TO_U_LONG = MIN_DOUBLE_TRUNCATABLE_TO_U_INT;
139-
private static final double MAX_DOUBLE_TRUNCATABLE_TO_U_LONG = 18446744073709550000.0;
140121

141122
private static final int REPORT_LOOP_STRIDE = 1 << 8;
142123

@@ -4095,55 +4076,67 @@ private static void i32_wrap_i64(VirtualFrame frame, int stackPointer) {
40954076
pushInt(frame, stackPointer - 1, result);
40964077
}
40974078

4079+
private WasmException trunc_f32_trap(float x) {
4080+
if (Float.isNaN(x)) {
4081+
throw WasmException.create(Failure.INVALID_CONVERSION_TO_INT, this);
4082+
} else {
4083+
throw WasmException.create(Failure.INT_OVERFLOW, this);
4084+
}
4085+
}
4086+
4087+
private WasmException trunc_f64_trap(double x) {
4088+
if (Double.isNaN(x)) {
4089+
throw WasmException.create(Failure.INVALID_CONVERSION_TO_INT, this);
4090+
} else {
4091+
throw WasmException.create(Failure.INT_OVERFLOW, this);
4092+
}
4093+
}
4094+
40984095
private void i32_trunc_f32_s(VirtualFrame frame, int stackPointer) {
40994096
final float x = popFloat(frame, stackPointer - 1);
4100-
if (Float.isNaN(x)) {
4101-
enterErrorBranch();
4102-
throw WasmException.create(Failure.INVALID_CONVERSION_TO_INT);
4103-
} else if (x < MIN_FLOAT_TRUNCATABLE_TO_INT || x > MAX_FLOAT_TRUNCATABLE_TO_INT) {
4097+
final int result;
4098+
if (x >= -0x1p31f && x < 0x1p31f) {
4099+
result = (int) x;
4100+
} else {
41044101
enterErrorBranch();
4105-
throw WasmException.create(Failure.INT_OVERFLOW);
4102+
throw trunc_f32_trap(x);
41064103
}
4107-
final int result = (int) x;
41084104
pushInt(frame, stackPointer - 1, result);
41094105
}
41104106

41114107
private void i32_trunc_f32_u(VirtualFrame frame, int stackPointer) {
41124108
final float x = popFloat(frame, stackPointer - 1);
4113-
if (Float.isNaN(x)) {
4114-
enterErrorBranch();
4115-
throw WasmException.create(Failure.INVALID_CONVERSION_TO_INT);
4116-
} else if (x < MIN_FLOAT_TRUNCATABLE_TO_U_INT || x > MAX_FLOAT_TRUNCATABLE_TO_U_INT) {
4109+
final int result;
4110+
if (x > -1.0f && x < 0x1p32f) {
4111+
result = ExactMath.truncateToUnsignedInt(x);
4112+
} else {
41174113
enterErrorBranch();
4118-
throw WasmException.create(Failure.INT_OVERFLOW);
4114+
throw trunc_f32_trap(x);
41194115
}
4120-
final int result = ExactMath.truncateToUnsignedInt(x);
41214116
pushInt(frame, stackPointer - 1, result);
41224117
}
41234118

41244119
private void i32_trunc_f64_s(VirtualFrame frame, int stackPointer) {
41254120
final double x = popDouble(frame, stackPointer - 1);
4126-
if (Double.isNaN(x)) {
4127-
enterErrorBranch();
4128-
throw WasmException.create(Failure.INVALID_CONVERSION_TO_INT);
4129-
} else if (x < MIN_DOUBLE_TRUNCATABLE_TO_INT || x > MAX_DOUBLE_TRUNCATABLE_TO_INT) {
4121+
final int result;
4122+
if (x > -0x1.00000002p31 && x < 0x1p31) { // sic!
4123+
result = (int) x;
4124+
} else {
41304125
enterErrorBranch();
4131-
throw WasmException.create(Failure.INT_OVERFLOW);
4126+
throw trunc_f64_trap(x);
41324127
}
4133-
final int result = (int) x;
41344128
pushInt(frame, stackPointer - 1, result);
41354129
}
41364130

41374131
private void i32_trunc_f64_u(VirtualFrame frame, int stackPointer) {
41384132
final double x = popDouble(frame, stackPointer - 1);
4139-
if (Double.isNaN(x)) {
4140-
enterErrorBranch();
4141-
throw WasmException.create(Failure.INVALID_CONVERSION_TO_INT);
4142-
} else if (x < MIN_DOUBLE_TRUNCATABLE_TO_U_INT || x > MAX_DOUBLE_TRUNCATABLE_TO_U_INT) {
4133+
final int result;
4134+
if (x > -1.0 && x < 0x1p32) {
4135+
result = ExactMath.truncateToUnsignedInt(x);
4136+
} else {
41434137
enterErrorBranch();
4144-
throw WasmException.create(Failure.INT_OVERFLOW);
4138+
throw trunc_f64_trap(x);
41454139
}
4146-
final int result = ExactMath.truncateToUnsignedInt(x);
41474140
pushInt(frame, stackPointer - 1, result);
41484141
}
41494142

@@ -4184,53 +4177,49 @@ private static void i64_extend_i32_u(VirtualFrame frame, int stackPointer) {
41844177

41854178
private void i64_trunc_f32_s(VirtualFrame frame, int stackPointer) {
41864179
final float x = popFloat(frame, stackPointer - 1);
4187-
if (Float.isNaN(x)) {
4188-
enterErrorBranch();
4189-
throw WasmException.create(Failure.INVALID_CONVERSION_TO_INT);
4190-
} else if (x < MIN_FLOAT_TRUNCATABLE_TO_LONG || x > MAX_FLOAT_TRUNCATABLE_TO_LONG) {
4180+
final long result;
4181+
if (x >= -0x1p63f && x < 0x1p63f) {
4182+
result = (long) x;
4183+
} else {
41914184
enterErrorBranch();
4192-
throw WasmException.create(Failure.INT_OVERFLOW);
4185+
throw trunc_f32_trap(x);
41934186
}
4194-
final long result = (long) x;
41954187
pushLong(frame, stackPointer - 1, result);
41964188
}
41974189

41984190
private void i64_trunc_f32_u(VirtualFrame frame, int stackPointer) {
41994191
final float x = popFloat(frame, stackPointer - 1);
4200-
if (Float.isNaN(x)) {
4201-
enterErrorBranch();
4202-
throw WasmException.create(Failure.INVALID_CONVERSION_TO_INT);
4203-
} else if (x < MIN_FLOAT_TRUNCATABLE_TO_U_LONG || x > MAX_FLOAT_TRUNCATABLE_TO_U_LONG) {
4192+
final long result;
4193+
if (x > -1.0f && x < 0x1p64f) {
4194+
result = ExactMath.truncateToUnsignedLong(x);
4195+
} else {
42044196
enterErrorBranch();
4205-
throw WasmException.create(Failure.INT_OVERFLOW);
4197+
throw trunc_f32_trap(x);
42064198
}
4207-
final long result = ExactMath.truncateToUnsignedLong(x);
42084199
pushLong(frame, stackPointer - 1, result);
42094200
}
42104201

42114202
private void i64_trunc_f64_s(VirtualFrame frame, int stackPointer) {
42124203
final double x = popDouble(frame, stackPointer - 1);
4213-
if (Double.isNaN(x)) {
4214-
enterErrorBranch();
4215-
throw WasmException.create(Failure.INVALID_CONVERSION_TO_INT);
4216-
} else if (x < MIN_DOUBLE_TRUNCATABLE_TO_LONG || x > MAX_DOUBLE_TRUNCATABLE_TO_LONG) {
4204+
final long result;
4205+
if (x >= -0x1p63 && x < 0x1p63) {
4206+
result = (long) x;
4207+
} else {
42174208
enterErrorBranch();
4218-
throw WasmException.create(Failure.INT_OVERFLOW);
4209+
throw trunc_f64_trap(x);
42194210
}
4220-
final long result = (long) x;
42214211
pushLong(frame, stackPointer - 1, result);
42224212
}
42234213

42244214
private void i64_trunc_f64_u(VirtualFrame frame, int stackPointer) {
42254215
final double x = popDouble(frame, stackPointer - 1);
4226-
if (Double.isNaN(x)) {
4227-
enterErrorBranch();
4228-
throw WasmException.create(Failure.INVALID_CONVERSION_TO_INT);
4229-
} else if (x < MIN_DOUBLE_TRUNCATABLE_TO_U_LONG || x > MAX_DOUBLE_TRUNCATABLE_TO_U_LONG) {
4216+
final long result;
4217+
if (x > -1.0 && x < 0x1p64) {
4218+
result = ExactMath.truncateToUnsignedLong(x);
4219+
} else {
42304220
enterErrorBranch();
4231-
throw WasmException.create(Failure.INT_OVERFLOW);
4221+
throw trunc_f64_trap(x);
42324222
}
4233-
final long result = ExactMath.truncateToUnsignedLong(x);
42344223
pushLong(frame, stackPointer - 1, result);
42354224
}
42364225

0 commit comments

Comments
 (0)