From 6aa69bcaa29a88ff69c566a2bd1cbc62a520c98f Mon Sep 17 00:00:00 2001 From: Kevin Gadd Date: Sat, 23 Mar 2013 10:12:38 -0700 Subject: [PATCH] If a JSReplacement method is also JSIsPure, treat it as constant if all its arguments are constant. Mark the Math proxies as pure. --- JSIL/AST/JSLiteralTypes.cs | 13 ++++++++++++- JSIL/ILBlockTranslator.cs | 4 +++- Meta/PackedArray.cs | 5 +++++ Proxies/Math.cs | 17 +++++++++++++++++ build_demos.bat | 1 + 5 files changed, 38 insertions(+), 2 deletions(-) diff --git a/JSIL/AST/JSLiteralTypes.cs b/JSIL/AST/JSLiteralTypes.cs index 312d39ae3..15d70afaa 100644 --- a/JSIL/AST/JSLiteralTypes.cs +++ b/JSIL/AST/JSLiteralTypes.cs @@ -295,14 +295,16 @@ public class JSVerbatimLiteral : JSLiteral { public readonly TypeReference Type; public readonly string Expression; public readonly IDictionary Variables; + public readonly bool IsConstantIfArgumentsAre; - public JSVerbatimLiteral (MethodReference originalMethod, string expression, IDictionary variables, TypeReference type = null) + public JSVerbatimLiteral (MethodReference originalMethod, string expression, IDictionary variables, TypeReference type = null, bool isConstantIfArgumentsAre = false) : base(GetValues(variables)) { OriginalMethod = originalMethod; Type = type; Expression = expression; Variables = variables; + IsConstantIfArgumentsAre = isConstantIfArgumentsAre; } protected static JSExpression[] GetValues (IDictionary variables) { @@ -316,6 +318,15 @@ public override object Literal { get { return Expression; } } + public override bool IsConstant { + get { + if (!IsConstantIfArgumentsAre) + return false; + else + return Variables.Values.All((v) => v.IsConstant); + } + } + public override TypeReference GetActualType (TypeSystem typeSystem) { if (Type != null) return Type; diff --git a/JSIL/ILBlockTranslator.cs b/JSIL/ILBlockTranslator.cs index d1b99c8bb..733c4ec51 100644 --- a/JSIL/ILBlockTranslator.cs +++ b/JSIL/ILBlockTranslator.cs @@ -396,8 +396,10 @@ TypeReference resultType argsDict.Add(kvp.Name, kvp.Value); } + var isConstantIfArgumentsAre = methodInfo.Metadata.HasAttribute("JSIL.Meta.JSIsPure"); + return new JSVerbatimLiteral( - method, (string)parms[0].Value, argsDict, resultType + method, (string)parms[0].Value, argsDict, resultType, isConstantIfArgumentsAre ); } } diff --git a/Meta/PackedArray.cs b/Meta/PackedArray.cs index f5a3f4687..e5d70ad59 100644 --- a/Meta/PackedArray.cs +++ b/Meta/PackedArray.cs @@ -15,11 +15,14 @@ public LinkedTypeAttribute (Type type) { public unsafe interface IPackedArray { [JSResultIsNew] + [JSIsPure] T Get (int index); + [JSResultIsNew] void* GetReference (int index); [JSEscapingArguments("value")] [JSMutatedArguments()] void Set (int index, T value); + [JSIsPure] int Length { get; } } @@ -28,6 +31,7 @@ public static class TypedArrayExtensionMethods { /// If the specified array is backed by a typed array, returns its backing array buffer. /// [JSReplacement("JSIL.GetArrayBuffer($array)")] + [JSIsPure] public static dynamic GetArrayBuffer (this T[] array) where T : struct { @@ -40,6 +44,7 @@ public static class PackedArrayExtensionMethods { /// If the specified array is a packed array, returns its backing typed array. /// [JSReplacement("JSIL.GetBackingTypedArray($array)")] + [JSIsPure] public static byte[] GetBackingTypedArray (this T[] array) where T : struct { diff --git a/Proxies/Math.cs b/Proxies/Math.cs index 6d68c3d89..736da799f 100644 --- a/Proxies/Math.cs +++ b/Proxies/Math.cs @@ -21,86 +21,103 @@ public static AnyType Max (params AnyType[] arguments) { } [JSReplacement("Math.abs($value)")] + [JSIsPure] public static AnyType Abs (AnyType value) { throw new InvalidOperationException(); } [JSReplacement("Math.sqrt($d)")] + [JSIsPure] public static double Sqrt (double d) { throw new InvalidOperationException(); } [JSReplacement("Math.cos($d)")] + [JSIsPure] public static double Cos (double d) { throw new InvalidOperationException(); } [JSReplacement("Math.sin($d)")] + [JSIsPure] public static double Sin (double d) { throw new InvalidOperationException(); } [JSReplacement("Math.acos($d)")] + [JSIsPure] public static double Acos (double d) { throw new InvalidOperationException(); } [JSReplacement("Math.asin($d)")] + [JSIsPure] public static double Asin (double d) { throw new InvalidOperationException(); } [JSReplacement("Math.tan($d)")] + [JSIsPure] public static double Tan (double d) { throw new InvalidOperationException(); } [JSReplacement("Math.atan($d)")] + [JSIsPure] public static double Atan (double d) { throw new InvalidOperationException(); } [JSReplacement("Math.atan2($y, $x)")] + [JSIsPure] public static double Atan2 (double y, double x) { throw new InvalidOperationException(); } [JSReplacement("Math.log($d)")] + [JSIsPure] public static double Log (double d) { throw new InvalidOperationException(); } [JSReplacement("(Math.log($a) / Math.log($newBase))")] + [JSIsPure] public static double Log (double a, double newBase) { throw new InvalidOperationException(); } [JSReplacement("(Math.log($d) / Math.LN10)")] + [JSIsPure] public static double Log10 (double d) { throw new InvalidOperationException(); } [JSReplacement("Math.round($d)")] + [JSIsPure] public static double Round (double d) { throw new InvalidOperationException(); } [JSReplacement("Math.floor($d)")] + [JSIsPure] public static double Floor (double d) { throw new InvalidOperationException(); } [JSReplacement("($d | 0)")] + [JSIsPure] public static double Truncate (double d) { throw new InvalidOperationException(); } [JSReplacement("Math.ceil($d)")] + [JSIsPure] public static double Ceiling (double d) { throw new InvalidOperationException(); } [JSReplacement("Math.pow($base, $exponent)")] + [JSIsPure] public static AnyType Pow (AnyType @base, AnyType exponent) { throw new InvalidOperationException(); } diff --git a/build_demos.bat b/build_demos.bat index 171f3111c..ad189ee1b 100644 --- a/build_demos.bat +++ b/build_demos.bat @@ -9,6 +9,7 @@ title Building Pathtracer bin\JSILc "Examples\SimplePathtracer.sln" title Building WebGL bin\JSILc "Examples\WebGL\WebGL.sln" +bin\JSILc "Examples\WebGL_Vertex_Structs\WebGL_Vertex_Structs.sln" title Building Tetris bin\JSILc "Examples\ThirdParty\Tetris\tetris.sln" "jsil.org\demos\Tetris\Tetris.jsilconfig" --platform=x86 --configuration=Debug title Building Platformer Starter Kit