From d4113a6744b4399953b9ee851734693f754ab238 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Thu, 28 Sep 2023 17:00:51 +0200 Subject: [PATCH] classlib: improve Math min/max implementations in C and Wasm Follow-up to ihromant's "fix Math min/max functions in JS" --- .../org/teavm/classlib/java/lang/TMath.java | 17 +++++++++++++++++ .../org/teavm/backend/wasm/WasmRuntime.java | 8 ++++++++ .../wasm/intrinsics/WasmRuntimeIntrinsic.java | 8 ++++++++ 3 files changed, 33 insertions(+) diff --git a/classlib/src/main/java/org/teavm/classlib/java/lang/TMath.java b/classlib/src/main/java/org/teavm/classlib/java/lang/TMath.java index a795ac211..01b7b9c23 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/lang/TMath.java +++ b/classlib/src/main/java/org/teavm/classlib/java/lang/TMath.java @@ -16,6 +16,7 @@ package org.teavm.classlib.java.lang; import org.teavm.backend.javascript.spi.GeneratedBy; +import org.teavm.backend.wasm.WasmRuntime; import org.teavm.backend.wasm.runtime.WasmSupport; import org.teavm.classlib.PlatformDetector; import org.teavm.interop.Import; @@ -197,11 +198,15 @@ public final class TMath extends TObject { @GeneratedBy(MathNativeGenerator.class) @NoSideEffects + @Unmanaged private static native float minImpl(double a, double b); + @Unmanaged public static double min(double a, double b) { if (PlatformDetector.isJavaScript()) { return minImpl(a, b); + } else if (PlatformDetector.isWebAssembly()) { + return WasmRuntime.min(a, b); } if (a != a) { return a; @@ -214,11 +219,15 @@ public final class TMath extends TObject { @GeneratedBy(MathNativeGenerator.class) @NoSideEffects + @Unmanaged private static native float maxImpl(double a, double b); + @Unmanaged public static double max(double a, double b) { if (PlatformDetector.isJavaScript()) { return maxImpl(a, b); + } else if (PlatformDetector.isWebAssembly()) { + return WasmRuntime.max(a, b); } if (a != a) { return a; @@ -231,11 +240,15 @@ public final class TMath extends TObject { @GeneratedBy(MathNativeGenerator.class) @NoSideEffects + @Unmanaged private static native float minImpl(float a, float b); + @Unmanaged public static float min(float a, float b) { if (PlatformDetector.isJavaScript()) { return minImpl(a, b); + } else if (PlatformDetector.isWebAssembly()) { + return WasmRuntime.min(a, b); } if (a != a) { return a; @@ -248,11 +261,15 @@ public final class TMath extends TObject { @GeneratedBy(MathNativeGenerator.class) @NoSideEffects + @Unmanaged private static native float maxImpl(float a, float b); + @Unmanaged public static float max(float a, float b) { if (PlatformDetector.isJavaScript()) { return maxImpl(a, b); + } else if (PlatformDetector.isWebAssembly()) { + return WasmRuntime.max(a, b); } if (a != a) { return a; diff --git a/core/src/main/java/org/teavm/backend/wasm/WasmRuntime.java b/core/src/main/java/org/teavm/backend/wasm/WasmRuntime.java index 8e78e53ca..fb0f4278a 100644 --- a/core/src/main/java/org/teavm/backend/wasm/WasmRuntime.java +++ b/core/src/main/java/org/teavm/backend/wasm/WasmRuntime.java @@ -51,6 +51,14 @@ public final class WasmRuntime { return gt(a, b) ? 1 : lt(a, b) ? -1 : 0; } + public static native float min(float a, float b); + + public static native double min(double a, double b); + + public static native float max(float a, float b); + + public static native double max(double a, double b); + public static float remainder(float a, float b) { return a - (float) (int) (a / b) * b; } diff --git a/core/src/main/java/org/teavm/backend/wasm/intrinsics/WasmRuntimeIntrinsic.java b/core/src/main/java/org/teavm/backend/wasm/intrinsics/WasmRuntimeIntrinsic.java index 09d8d07bf..0acc58f10 100644 --- a/core/src/main/java/org/teavm/backend/wasm/intrinsics/WasmRuntimeIntrinsic.java +++ b/core/src/main/java/org/teavm/backend/wasm/intrinsics/WasmRuntimeIntrinsic.java @@ -40,6 +40,8 @@ public class WasmRuntimeIntrinsic implements WasmIntrinsic { case "lt": case "gtu": case "ltu": + case "min": + case "max": case "initStack": case "callFunctionFromTable": return true; @@ -63,6 +65,12 @@ public class WasmRuntimeIntrinsic implements WasmIntrinsic { case "gtu": return comparison(WasmIntBinaryOperation.GT_UNSIGNED, WasmFloatBinaryOperation.GT, invocation, manager); + case "min": + return comparison(WasmIntBinaryOperation.GT_SIGNED, WasmFloatBinaryOperation.MIN, + invocation, manager); + case "max": + return comparison(WasmIntBinaryOperation.GT_SIGNED, WasmFloatBinaryOperation.MAX, + invocation, manager); case "callFunctionFromTable": { var call = new WasmIndirectCall(manager.generate(invocation.getArguments().get(0))); call.getArguments().add(manager.generate(invocation.getArguments().get(1)));