From e30f42499fefe8623f9f2dfff8065371643aad58 Mon Sep 17 00:00:00 2001 From: Akash Kava <39438041+ackava@users.noreply.github.com> Date: Thu, 9 Nov 2023 15:07:18 +0530 Subject: [PATCH] StringSpan Removed from JSString to reduce allocations #96 --- YantraJS.Core/Core/Arguments.cs | 2 +- YantraJS.Core/Core/Clr/ClrProxy.cs | 2 +- YantraJS.Core/Core/Function/JSFunction.cs | 2 +- YantraJS.Core/Core/Global/JSGlobal.cs | 4 +- YantraJS.Core/Core/JSContext.cs | 4 +- YantraJS.Core/Core/JSValue.cs | 8 +-- YantraJS.Core/Core/Json/JSJSON.cs | 2 +- YantraJS.Core/Core/Object/JSObject.cs | 2 +- YantraJS.Core/Core/String/JSString.cs | 50 ++++++++----------- YantraJS.Core/Core/String/JSTemplateString.cs | 30 ++++------- YantraJS.Core/Extensions/StringExtensions.cs | 27 ++++++++++ 11 files changed, 71 insertions(+), 62 deletions(-) diff --git a/YantraJS.Core/Core/Arguments.cs b/YantraJS.Core/Core/Arguments.cs index 891a805c..a1c3828f 100644 --- a/YantraJS.Core/Core/Arguments.cs +++ b/YantraJS.Core/Core/Arguments.cs @@ -740,7 +740,7 @@ public IElementEnumerator GetElementEnumerator() [CallerFilePath] string? filePath = null, [CallerLineNumber] int line = 0) { - return this[index] is JSString s ? s.Value : throw new JSException( + return this[index] is JSString s ? s.value : throw new JSException( name + " is required", function, filePath, line); } diff --git a/YantraJS.Core/Core/Clr/ClrProxy.cs b/YantraJS.Core/Core/Clr/ClrProxy.cs index 027f78ca..bffa57be 100644 --- a/YantraJS.Core/Core/Clr/ClrProxy.cs +++ b/YantraJS.Core/Core/Clr/ClrProxy.cs @@ -259,7 +259,7 @@ public override bool StrictEquals(JSValue value) //if (this.value.ToString() == proxy.value.ToString()) // return true; break; - case JSString @string when @string.Value.Equals(this.value): + case JSString @string when @string.value.Equals(this.value): return true; case JSNumber number: switch (this.value) diff --git a/YantraJS.Core/Core/Function/JSFunction.cs b/YantraJS.Core/Core/Function/JSFunction.cs index 8346bd81..b17ad4d1 100644 --- a/YantraJS.Core/Core/Function/JSFunction.cs +++ b/YantraJS.Core/Core/Function/JSFunction.cs @@ -336,7 +336,7 @@ internal static JSValue Constructor(in Arguments args) } } - var bodyText = body is JSString @string ? @string.Value : body.ToString(); + var bodyText = body is JSString @string ? @string.value : body.ToString(); string location = null; JSContext.Current.DispatchEvalEvent(ref bodyText, ref location); diff --git a/YantraJS.Core/Core/Global/JSGlobal.cs b/YantraJS.Core/Core/Global/JSGlobal.cs index 4b34f4ce..d662ea50 100644 --- a/YantraJS.Core/Core/Global/JSGlobal.cs +++ b/YantraJS.Core/Core/Global/JSGlobal.cs @@ -48,10 +48,10 @@ public static JSValue Eval(in Arguments a) var f = a.Get1(); if (!f.IsString) return f; - var text = (f as JSString).Value; + var text = (f as JSString).value; string location = null; JSContext.Current.DispatchEvalEvent(ref text, ref location); - return CoreScript.Evaluate(text.Value, null); + return CoreScript.Evaluate(text, null); } [JSExport("encodeURI", Length = 1)] diff --git a/YantraJS.Core/Core/JSContext.cs b/YantraJS.Core/Core/JSContext.cs index aec26b86..2da8f335 100644 --- a/YantraJS.Core/Core/JSContext.cs +++ b/YantraJS.Core/Core/JSContext.cs @@ -123,7 +123,7 @@ public class EvalEventArgs: EventArgs { public JSContext Context { get; set; } - public StringSpan Script { get; set; } + public string Script { get; set; } public string Location { get; set; } } @@ -178,7 +178,7 @@ internal Task WaitTask public event EventHandler EvalEvent; - internal void DispatchEvalEvent(ref StringSpan script, ref string location) + internal void DispatchEvalEvent(ref string script, ref string location) { var ee = EvalEvent; if (ee != null) diff --git a/YantraJS.Core/Core/JSValue.cs b/YantraJS.Core/Core/JSValue.cs index e1fe5941..ff0746d7 100644 --- a/YantraJS.Core/Core/JSValue.cs +++ b/YantraJS.Core/Core/JSValue.cs @@ -636,7 +636,7 @@ public virtual bool Less(JSValue value) if (this.DoubleValue < value.DoubleValue) return true; } - else if (this.ToString().CompareTo(value.ToString()) < 0) + else if (this.ToString().Less(value.ToString())) return true; } return false; @@ -651,7 +651,7 @@ public virtual bool LessOrEqual(JSValue value) if (this.DoubleValue <= value.DoubleValue) return true; } - else if (this.ToString().CompareTo(value.ToString()) <= 0) + else if (this.ToString().LessOrEqual(value.ToString())) return true; } return false; @@ -667,7 +667,7 @@ public virtual bool Greater(JSValue value) if (this.DoubleValue > value.DoubleValue) return true; } - else if (this.ToString().CompareTo(value.ToString()) > 0) + else if (this.ToString().Greater(value.ToString())) return true; } return false; @@ -681,7 +681,7 @@ public virtual bool GreaterOrEqual(JSValue value) if (this.DoubleValue >= value.DoubleValue) return true; } - else if (this.ToString().CompareTo(value.ToString()) >= 0) + else if (this.ToString().Greater(value.ToString())) return true; } return false; diff --git a/YantraJS.Core/Core/Json/JSJSON.cs b/YantraJS.Core/Core/Json/JSJSON.cs index d1c398fd..2e2354ce 100644 --- a/YantraJS.Core/Core/Json/JSJSON.cs +++ b/YantraJS.Core/Core/Json/JSJSON.cs @@ -132,7 +132,7 @@ public static string Stringify(JSValue value) sb.Write(n.value.ToString()); return; case JSString str: - QuoteString(str.Value, sb); + QuoteString(str.value, sb); return; case JSFunction _: return; diff --git a/YantraJS.Core/Core/Object/JSObject.cs b/YantraJS.Core/Core/Object/JSObject.cs index ff89f969..f7757a50 100644 --- a/YantraJS.Core/Core/Object/JSObject.cs +++ b/YantraJS.Core/Core/Object/JSObject.cs @@ -963,7 +963,7 @@ public override bool Equals(JSValue value) if (Object.ReferenceEquals(this, value)) return true; if (value is JSString str) - if (str.Value.Equals(this.ToString())) + if (str.value.Equals(this.ToString())) return true; if (DoubleValue == value.DoubleValue) return true; diff --git a/YantraJS.Core/Core/String/JSString.cs b/YantraJS.Core/Core/String/JSString.cs index 3668ea8e..8fac995d 100644 --- a/YantraJS.Core/Core/String/JSString.cs +++ b/YantraJS.Core/Core/String/JSString.cs @@ -24,9 +24,7 @@ public partial class JSString : JSPrimitive internal static JSString Empty = new JSString(string.Empty); - internal StringSpan Value => value; - - private StringSpan value; + internal readonly string value; KeyString _keyString; private double NumberValue = 0; @@ -54,31 +52,31 @@ public override double DoubleValue public override JSValue AddValue(double value) { - if (this.value.IsEmpty) + if (this.value.IsEmpty()) return new JSString(value.ToString()); - return new JSString( StringSpan.Concat(in this.value, value.ToString()) ); + return new JSString( string.Concat(this.value, value.ToString()) ); } public override JSValue AddValue(string value) { - if (this.value.IsEmpty) + if (this.value.IsEmpty()) return new JSString(value); - return new JSString( StringSpan.Concat(in this.value, value)); + return new JSString( string.Concat(this.value, value)); } public override JSValue AddValue(JSValue value) { if (value is JSString vString) { - if (this.value.IsEmpty) + if (this.value.IsEmpty()) { return vString; } - if (vString.value.IsEmpty) + if (vString.value.IsEmpty()) { return this; } - return new JSString(StringSpan.Concat(in this.value, in vString.value)); + return new JSString(string.Concat(this.value, vString.value)); } if (value.IsObject) @@ -86,7 +84,7 @@ public override JSValue AddValue(JSValue value) value = value.ValueOf(); } - if (this.value.IsEmpty) + if (this.value.IsEmpty()) return new JSString(value.StringValue); var v = value.StringValue; @@ -94,19 +92,19 @@ public override JSValue AddValue(JSValue value) { return this; } - return new JSString(StringSpan.Concat(in this.value, v)); + return new JSString(string.Concat(this.value, v)); } public override bool ConvertTo(Type type, out object value) { if (type == typeof(string)) { - value = this.value.Value; + value = this.value; return true; } if (type == typeof(object)) { - value = this.value.Value; + value = this.value; return true; } if(type == typeof(char)) @@ -162,7 +160,7 @@ public JSString(JSObject prototype, string value): base(prototype) public JSString(in StringSpan value) : base() { - this.value = value; + this.value = value.Value; } @@ -190,28 +188,23 @@ public override JSValue TypeOf() public override string ToString() { - if(value.Offset == 0 && value.Length == value.Source.Length) - { - return value.Source; - } - value = new StringSpan(value.Value); - return value.Value; + return value; } public byte[] Encode(System.Text.Encoding encoding) { - return value.Encode(encoding); + return encoding.GetBytes(value); } public override string ToDetailString() { - return value.Value; + return value; } public override string ToLocaleString(string format, CultureInfo culture) { - return value.Value; + return value; } @@ -304,8 +297,7 @@ public override bool Less(JSValue value) { return this.DoubleValue < value.DoubleValue; } - int n = this.value.CompareTo(value.ToString()); - return n < 0; + return this.value.Less(value.ToString()); } @@ -317,7 +309,7 @@ public override bool LessOrEqual(JSValue value) { return (this.DoubleValue <= value.DoubleValue); } - return this.value.CompareTo(value.ToString()) <= 0; + return this.value.LessOrEqual(value.ToString()); } public override bool Greater(JSValue value) @@ -328,7 +320,7 @@ public override bool Greater(JSValue value) { return (this.DoubleValue > value.DoubleValue); } - return this.value.CompareTo(value.ToString()) > 0; + return this.value.Greater(value.ToString()); } public override bool GreaterOrEqual(JSValue value) @@ -339,7 +331,7 @@ public override bool GreaterOrEqual(JSValue value) { return (this.DoubleValue >= value.DoubleValue); } - return this.value.CompareTo(value.ToString()) >= 0; + return this.value.GreaterOrEqual(value.ToString()); } public override bool StrictEquals(JSValue value) diff --git a/YantraJS.Core/Core/String/JSTemplateString.cs b/YantraJS.Core/Core/String/JSTemplateString.cs index cd101bd5..4f70eae5 100644 --- a/YantraJS.Core/Core/String/JSTemplateString.cs +++ b/YantraJS.Core/Core/String/JSTemplateString.cs @@ -19,16 +19,6 @@ public void Add(string t) public unsafe void Add(JSValue value) { - if (value is JSString @string) - { - var span = @string.Value; - fixed (char* start = span.Source) - { - char* ch1 = start + (span.Offset); - sb.Append(ch1, span.Length); - } - return; - } sb.Append(value.ToString()); } @@ -40,16 +30,16 @@ public JSTemplateString AddQuasi(string text) public unsafe JSTemplateString AddExpression(JSValue value) { - if (value is JSString @string) - { - var span = @string.Value; - fixed (char* start = span.Source) - { - char* ch1 = start + (span.Offset); - sb.Append(ch1, span.Length); - } - return this; - } + //if (value is JSString @string) + //{ + // var span = @string.Value; + // fixed (char* start = span.Source) + // { + // char* ch1 = start + (span.Offset); + // sb.Append(ch1, span.Length); + // } + // return this; + //} sb.Append(value.ToString()); return this; } diff --git a/YantraJS.Core/Extensions/StringExtensions.cs b/YantraJS.Core/Extensions/StringExtensions.cs index 5e68804a..05fd3610 100644 --- a/YantraJS.Core/Extensions/StringExtensions.cs +++ b/YantraJS.Core/Extensions/StringExtensions.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Runtime.CompilerServices; using System.Text; using System.Text.RegularExpressions; @@ -7,6 +8,32 @@ namespace YantraJS { internal static class StringExtensions { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsEmpty(this string str) + { + return string.IsNullOrEmpty(str); + } + + public static bool Greater(this string left, string right) { + return string.CompareOrdinal(left, right) > 0; + } + + public static bool GreaterOrEqual(this string left, string right) + { + return string.CompareOrdinal(left, right) >= 0; + } + + + public static bool Less(this string left, string right) + { + return string.CompareOrdinal(left, right) < 0; + } + + public static bool LessOrEqual(this string left, string right) + { + return string.CompareOrdinal(left, right) <= 0; + } + public static string ToCamelCase(this string text) {