XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFESystem

【Rust】XFE系统,基于Rust和汇编

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Diagnostics;
using System.Reflection;
using Jint;
using Jint.Native;
using Jint.Runtime.Interop;
using XFESystem.Browser;

// Host-only diagnostic. Calls the original intrinsic directly, under the
// existing evaluation budget; never replaces regex results or resets limits.
internal sealed class MonacoRegexProfile
{
    private sealed class Work
    {
        public long Calls, Ticks, InputCharacters, FailedSuffixHits;
    }
    private readonly Dictionary<string, Work> patterns = new(StringComparer.Ordinal);
    internal void Install(BrowserService browser)
    {
        var runtime = (JavaScriptRuntime)typeof(BrowserService).GetField("runtime", BindingFlags.Instance | BindingFlags.NonPublic)!.GetValue(browser)!;
        var engine = (Engine)typeof(JavaScriptRuntime).GetField("engine", BindingFlags.Instance | BindingFlags.NonPublic)!.GetValue(runtime)!;
        var prototype = engine.GetValue("RegExp").AsObject().Get("prototype").AsObject();
        var original = (Func<JsValue, JsValue[], JsValue>)prototype.Get("exec").ToObject()!;
        var hitCounter = typeof(Jint.Native.JsRegExp).GetField("_xfeNoMatchHits", BindingFlags.Instance | BindingFlags.NonPublic);
        prototype.Set("exec", new ClrFunction(engine, "exec", (receiver, arguments) =>
        {
            var regex = receiver.AsObject();
            string key = regex.Get("source").AsString() + "/" + regex.Get("flags").AsString();
            if (!patterns.TryGetValue(key, out var work)) patterns.Add(key, work = new());
            work.Calls++;
            if (arguments.Length > 0 && arguments[0].IsString()) work.InputCharacters += arguments[0].AsString().Length;
            long started = Stopwatch.GetTimestamp();
            long beforeHits = (long?)hitCounter?.GetValue(regex) ?? 0;
            var result = original(receiver, arguments);
            work.Ticks += Stopwatch.GetTimestamp() - started;
            work.FailedSuffixHits += ((long?)hitCounter?.GetValue(regex) ?? 0) - beforeHits;
            return result;
        }), false);
    }
    internal object[] Results() => patterns.OrderByDescending(pair => pair.Value.Ticks).Take(20).Select(pair => (object)new
    {
        Pattern = pair.Key, pair.Value.Calls, pair.Value.InputCharacters, pair.Value.FailedSuffixHits,
        Milliseconds = pair.Value.Ticks * 1000.0 / Stopwatch.Frequency
    }).ToArray();
}