From 15de759a15a9d12d0af2f2c02375fd25817401ea Mon Sep 17 00:00:00 2001 From: Ansis Date: Wed, 4 Dec 2024 16:12:15 +0100 Subject: [PATCH] Sketch of a non-allocating fast path for compiling code --- ClearScript/Util/MiscHelpers.cs | 52 ++++- .../V8/SplitProxy/IV8SplitProxyNative.cs | 1 + .../V8/SplitProxy/V8ContextProxyImpl.cs | 16 ++ .../SplitProxy/V8SplitProxyNative.Common.tt | 22 ++ .../V8SplitProxyNative.Generated.cs | 205 ++++++++++++++++++ ClearScript/V8/V8ContextProxy.cs | 2 + ClearScript/V8/V8ScriptEngine.cs | 43 ++++ ClearScriptV8/V8SplitProxyNative.cpp | 22 ++ ClearScriptV8/V8SplitProxyNative.h | 1 + 9 files changed, 356 insertions(+), 8 deletions(-) diff --git a/ClearScript/Util/MiscHelpers.cs b/ClearScript/Util/MiscHelpers.cs index 45ce56566..3a115989e 100644 --- a/ClearScript/Util/MiscHelpers.cs +++ b/ClearScript/Util/MiscHelpers.cs @@ -224,17 +224,36 @@ public static UIntPtr GetDigest(this string code) return (UIntPtr.Size == 4) ? (UIntPtr)code.GetDigestAsUInt32() : (UIntPtr)code.GetDigestAsUInt64(); } + public static UIntPtr GetDigest(IntPtr code, int length) + { + return (UIntPtr.Size == 4) ? (UIntPtr)GetDigestAsUInt32(code, length) : (UIntPtr)GetDigestAsUInt64(code, length); + } + public static uint GetDigestAsUInt32(this string code) + { + unsafe + { + fixed (char* charPtr = code) + { + return GetDigestAsUInt32((IntPtr)charPtr, code.Length); + } + } + } + + /// A pointer to a UTF-16 string + /// The length of the code string + public static uint GetDigestAsUInt32(IntPtr code, int length) { var digest = 2166136261U; const uint prime = 16777619U; - unchecked + unsafe { - var bytes = Encoding.Unicode.GetBytes(code); - for (var index = 0; index < bytes.Length; index++) + byte* bytePtr = (byte*)code; + + for (var index = 0; index < length; index++) { - digest ^= bytes[index]; + digest ^= bytePtr[index]; digest *= prime; } } @@ -243,15 +262,32 @@ public static uint GetDigestAsUInt32(this string code) } public static ulong GetDigestAsUInt64(this string code) + { + unsafe + { + fixed (char* charPtr = code) + { + return GetDigestAsUInt64((IntPtr)charPtr, code.Length); + } + } + } + + /// A pointer to a UTF-16 string + /// The length of the code string + public static ulong GetDigestAsUInt64(IntPtr code, int length) { var digest = 14695981039346656037UL; const ulong prime = 1099511628211UL; - var bytes = Encoding.Unicode.GetBytes(code); - for (var index = 0; index < bytes.Length; index++) + unsafe { - digest ^= bytes[index]; - digest *= prime; + byte* bytePtr = (byte*)code; + + for (var index = 0; index < length; index++) + { + digest ^= bytePtr[index]; + digest *= prime; + } } return digest; diff --git a/ClearScript/V8/SplitProxy/IV8SplitProxyNative.cs b/ClearScript/V8/SplitProxy/IV8SplitProxyNative.cs index 6194c103a..ccfa36c5e 100644 --- a/ClearScript/V8/SplitProxy/IV8SplitProxyNative.cs +++ b/ClearScript/V8/SplitProxy/IV8SplitProxyNative.cs @@ -172,6 +172,7 @@ internal interface IV8SplitProxyNative void V8Context_CancelAwaitDebugger(V8Context.Handle hContext); object V8Context_ExecuteCode(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, bool evaluate); V8Script.Handle V8Context_Compile(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code); + V8Script.Handle V8Context_Compile(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, IntPtr code, int length); V8Script.Handle V8Context_CompileProducingCache(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, out byte[] cacheBytes); V8Script.Handle V8Context_CompileConsumingCache(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, byte[] cacheBytes, out bool cacheAccepted); V8Script.Handle V8Context_CompileUpdatingCache(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, ref byte[] cacheBytes, out V8CacheResult cacheResult); diff --git a/ClearScript/V8/SplitProxy/V8ContextProxyImpl.cs b/ClearScript/V8/SplitProxy/V8ContextProxyImpl.cs index a56173e6b..ec15acdbb 100644 --- a/ClearScript/V8/SplitProxy/V8ContextProxyImpl.cs +++ b/ClearScript/V8/SplitProxy/V8ContextProxyImpl.cs @@ -92,6 +92,22 @@ public override V8.V8Script Compile(UniqueDocumentInfo documentInfo, string code V8ProxyHelpers.AddRefHostObject(documentInfo), code ))); + } + + /// Meta-information for a document + /// A pointer to a UTF-16 string + /// The length of the code string + public override V8.V8Script Compile(UniqueDocumentInfo documentInfo, IntPtr code, int length) + { + return new V8ScriptImpl(documentInfo, MiscHelpers.GetDigest(code, length), V8SplitProxyNative.Invoke(instance => instance.V8Context_Compile( + Handle, + MiscHelpers.GetUrlOrPath(documentInfo.Uri, documentInfo.UniqueName), + MiscHelpers.GetUrlOrPath(documentInfo.SourceMapUri, string.Empty), + documentInfo.UniqueId, + documentInfo.Category.Kind, + V8ProxyHelpers.AddRefHostObject(documentInfo), + code, length + ))); } public override V8.V8Script Compile(UniqueDocumentInfo documentInfo, string code, V8CacheKind cacheKind, out byte[] cacheBytes) diff --git a/ClearScript/V8/SplitProxy/V8SplitProxyNative.Common.tt b/ClearScript/V8/SplitProxy/V8SplitProxyNative.Common.tt index 18e1c4e01..1b9d9f944 100644 --- a/ClearScript/V8/SplitProxy/V8SplitProxyNative.Common.tt +++ b/ClearScript/V8/SplitProxy/V8SplitProxyNative.Common.tt @@ -756,6 +756,17 @@ namespace Microsoft.ClearScript.V8.SplitProxy } } + V8Script.Handle IV8SplitProxyNative.V8Context_Compile(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, IntPtr code, int length) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + return V8Context_CompileIntPtr(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, code, length); + } + } + } + V8Script.Handle IV8SplitProxyNative.V8Context_CompileProducingCache(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, out byte[] cacheBytes) { using (var resourceNameScope = StdString.CreateScope(resourceName)) @@ -1848,6 +1859,17 @@ namespace Microsoft.ClearScript.V8.SplitProxy [In] StdString.Ptr pCode ); + [DllImport("<#= fileName #>", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Context_CompileIntPtr( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] IntPtr pCode, [In] int length + ); + [DllImport("<#= fileName #>", CallingConvention = CallingConvention.StdCall)] private static extern V8Script.Handle V8Context_CompileProducingCache( [In] V8Context.Handle hContext, diff --git a/ClearScript/V8/SplitProxy/V8SplitProxyNative.Generated.cs b/ClearScript/V8/SplitProxy/V8SplitProxyNative.Generated.cs index d578dba3c..10377206f 100644 --- a/ClearScript/V8/SplitProxy/V8SplitProxyNative.Generated.cs +++ b/ClearScript/V8/SplitProxy/V8SplitProxyNative.Generated.cs @@ -4,6 +4,11 @@ + + + + + // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. @@ -19,79 +24,95 @@ private static IV8SplitProxyNative CreateInstance() var architecture = RuntimeInformation.ProcessArchitecture; + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { + if (architecture == Architecture.X86) { return new Impl_Windows_X86(); } + if (architecture == Architecture.X64) { return new Impl_Windows_X64(); } + if (architecture == Architecture.Arm64) { return new Impl_Windows_Arm64(); } + throw new PlatformNotSupportedException("Unsupported process architecture"); } + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { + if (architecture == Architecture.X64) { return new Impl_Linux_X64(); } + if (architecture == Architecture.Arm64) { return new Impl_Linux_Arm64(); } + if (architecture == Architecture.Arm) { return new Impl_Linux_Arm(); } + throw new PlatformNotSupportedException("Unsupported process architecture"); } + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { + if (architecture == Architecture.X64) { return new Impl_OSX_X64(); } + if (architecture == Architecture.Arm64) { return new Impl_OSX_Arm64(); } + throw new PlatformNotSupportedException("Unsupported process architecture"); } + throw new PlatformNotSupportedException("Unsupported operating system"); } + #region Nested type: Impl_Windows_X86 private sealed class Impl_Windows_X86 : IV8SplitProxyNative @@ -798,6 +819,17 @@ V8Script.Handle IV8SplitProxyNative.V8Context_Compile(V8Context.Handle hContext, } } + V8Script.Handle IV8SplitProxyNative.V8Context_Compile(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, IntPtr code, int length) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + return V8Context_CompileIntPtr(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, code, length); + } + } + } + V8Script.Handle IV8SplitProxyNative.V8Context_CompileProducingCache(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, out byte[] cacheBytes) { using (var resourceNameScope = StdString.CreateScope(resourceName)) @@ -1890,6 +1922,17 @@ private static extern V8Script.Handle V8Context_Compile( [In] StdString.Ptr pCode ); + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Context_CompileIntPtr( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] IntPtr pCode, [In] int length + ); + [DllImport("ClearScriptV8.win-x86.dll", CallingConvention = CallingConvention.StdCall)] private static extern V8Script.Handle V8Context_CompileProducingCache( [In] V8Context.Handle hContext, @@ -2225,6 +2268,7 @@ [Out] out ulong contextCount #endregion + #region Nested type: Impl_Windows_X64 private sealed class Impl_Windows_X64 : IV8SplitProxyNative @@ -2931,6 +2975,17 @@ V8Script.Handle IV8SplitProxyNative.V8Context_Compile(V8Context.Handle hContext, } } + V8Script.Handle IV8SplitProxyNative.V8Context_Compile(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, IntPtr code, int length) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + return V8Context_CompileIntPtr(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, code, length); + } + } + } + V8Script.Handle IV8SplitProxyNative.V8Context_CompileProducingCache(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, out byte[] cacheBytes) { using (var resourceNameScope = StdString.CreateScope(resourceName)) @@ -4023,6 +4078,17 @@ private static extern V8Script.Handle V8Context_Compile( [In] StdString.Ptr pCode ); + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Context_CompileIntPtr( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] IntPtr pCode, [In] int length + ); + [DllImport("ClearScriptV8.win-x64.dll", CallingConvention = CallingConvention.StdCall)] private static extern V8Script.Handle V8Context_CompileProducingCache( [In] V8Context.Handle hContext, @@ -4358,6 +4424,7 @@ [Out] out ulong contextCount #endregion + #region Nested type: Impl_Windows_Arm64 private sealed class Impl_Windows_Arm64 : IV8SplitProxyNative @@ -5064,6 +5131,17 @@ V8Script.Handle IV8SplitProxyNative.V8Context_Compile(V8Context.Handle hContext, } } + V8Script.Handle IV8SplitProxyNative.V8Context_Compile(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, IntPtr code, int length) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + return V8Context_CompileIntPtr(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, code, length); + } + } + } + V8Script.Handle IV8SplitProxyNative.V8Context_CompileProducingCache(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, out byte[] cacheBytes) { using (var resourceNameScope = StdString.CreateScope(resourceName)) @@ -6156,6 +6234,17 @@ private static extern V8Script.Handle V8Context_Compile( [In] StdString.Ptr pCode ); + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Context_CompileIntPtr( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] IntPtr pCode, [In] int length + ); + [DllImport("ClearScriptV8.win-arm64.dll", CallingConvention = CallingConvention.StdCall)] private static extern V8Script.Handle V8Context_CompileProducingCache( [In] V8Context.Handle hContext, @@ -6491,6 +6580,7 @@ [Out] out ulong contextCount #endregion + #region Nested type: Impl_Linux_X64 private sealed class Impl_Linux_X64 : IV8SplitProxyNative @@ -7197,6 +7287,17 @@ V8Script.Handle IV8SplitProxyNative.V8Context_Compile(V8Context.Handle hContext, } } + V8Script.Handle IV8SplitProxyNative.V8Context_Compile(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, IntPtr code, int length) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + return V8Context_CompileIntPtr(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, code, length); + } + } + } + V8Script.Handle IV8SplitProxyNative.V8Context_CompileProducingCache(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, out byte[] cacheBytes) { using (var resourceNameScope = StdString.CreateScope(resourceName)) @@ -8289,6 +8390,17 @@ private static extern V8Script.Handle V8Context_Compile( [In] StdString.Ptr pCode ); + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Context_CompileIntPtr( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] IntPtr pCode, [In] int length + ); + [DllImport("ClearScriptV8.linux-x64.so", CallingConvention = CallingConvention.StdCall)] private static extern V8Script.Handle V8Context_CompileProducingCache( [In] V8Context.Handle hContext, @@ -8624,6 +8736,7 @@ [Out] out ulong contextCount #endregion + #region Nested type: Impl_Linux_Arm64 private sealed class Impl_Linux_Arm64 : IV8SplitProxyNative @@ -9330,6 +9443,17 @@ V8Script.Handle IV8SplitProxyNative.V8Context_Compile(V8Context.Handle hContext, } } + V8Script.Handle IV8SplitProxyNative.V8Context_Compile(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, IntPtr code, int length) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + return V8Context_CompileIntPtr(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, code, length); + } + } + } + V8Script.Handle IV8SplitProxyNative.V8Context_CompileProducingCache(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, out byte[] cacheBytes) { using (var resourceNameScope = StdString.CreateScope(resourceName)) @@ -10422,6 +10546,17 @@ private static extern V8Script.Handle V8Context_Compile( [In] StdString.Ptr pCode ); + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Context_CompileIntPtr( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] IntPtr pCode, [In] int length + ); + [DllImport("ClearScriptV8.linux-arm64.so", CallingConvention = CallingConvention.StdCall)] private static extern V8Script.Handle V8Context_CompileProducingCache( [In] V8Context.Handle hContext, @@ -10757,6 +10892,7 @@ [Out] out ulong contextCount #endregion + #region Nested type: Impl_Linux_Arm private sealed class Impl_Linux_Arm : IV8SplitProxyNative @@ -11463,6 +11599,17 @@ V8Script.Handle IV8SplitProxyNative.V8Context_Compile(V8Context.Handle hContext, } } + V8Script.Handle IV8SplitProxyNative.V8Context_Compile(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, IntPtr code, int length) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + return V8Context_CompileIntPtr(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, code, length); + } + } + } + V8Script.Handle IV8SplitProxyNative.V8Context_CompileProducingCache(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, out byte[] cacheBytes) { using (var resourceNameScope = StdString.CreateScope(resourceName)) @@ -12555,6 +12702,17 @@ private static extern V8Script.Handle V8Context_Compile( [In] StdString.Ptr pCode ); + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Context_CompileIntPtr( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] IntPtr pCode, [In] int length + ); + [DllImport("ClearScriptV8.linux-arm.so", CallingConvention = CallingConvention.StdCall)] private static extern V8Script.Handle V8Context_CompileProducingCache( [In] V8Context.Handle hContext, @@ -12890,6 +13048,7 @@ [Out] out ulong contextCount #endregion + #region Nested type: Impl_OSX_X64 private sealed class Impl_OSX_X64 : IV8SplitProxyNative @@ -13596,6 +13755,17 @@ V8Script.Handle IV8SplitProxyNative.V8Context_Compile(V8Context.Handle hContext, } } + V8Script.Handle IV8SplitProxyNative.V8Context_Compile(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, IntPtr code, int length) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + return V8Context_CompileIntPtr(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, code, length); + } + } + } + V8Script.Handle IV8SplitProxyNative.V8Context_CompileProducingCache(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, out byte[] cacheBytes) { using (var resourceNameScope = StdString.CreateScope(resourceName)) @@ -14688,6 +14858,17 @@ private static extern V8Script.Handle V8Context_Compile( [In] StdString.Ptr pCode ); + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Context_CompileIntPtr( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] IntPtr pCode, [In] int length + ); + [DllImport("ClearScriptV8.osx-x64.dylib", CallingConvention = CallingConvention.StdCall)] private static extern V8Script.Handle V8Context_CompileProducingCache( [In] V8Context.Handle hContext, @@ -15023,6 +15204,7 @@ [Out] out ulong contextCount #endregion + #region Nested type: Impl_OSX_Arm64 private sealed class Impl_OSX_Arm64 : IV8SplitProxyNative @@ -15729,6 +15911,17 @@ V8Script.Handle IV8SplitProxyNative.V8Context_Compile(V8Context.Handle hContext, } } + V8Script.Handle IV8SplitProxyNative.V8Context_Compile(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, IntPtr code, int length) + { + using (var resourceNameScope = StdString.CreateScope(resourceName)) + { + using (var sourceMapUrlScope = StdString.CreateScope(sourceMapUrl)) + { + return V8Context_CompileIntPtr(hContext, resourceNameScope.Value, sourceMapUrlScope.Value, uniqueId, documentKind, pDocumentInfo, code, length); + } + } + } + V8Script.Handle IV8SplitProxyNative.V8Context_CompileProducingCache(V8Context.Handle hContext, string resourceName, string sourceMapUrl, ulong uniqueId, DocumentKind documentKind, IntPtr pDocumentInfo, string code, V8CacheKind cacheKind, out byte[] cacheBytes) { using (var resourceNameScope = StdString.CreateScope(resourceName)) @@ -16821,6 +17014,17 @@ private static extern V8Script.Handle V8Context_Compile( [In] StdString.Ptr pCode ); + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] + private static extern V8Script.Handle V8Context_CompileIntPtr( + [In] V8Context.Handle hContext, + [In] StdString.Ptr pResourceName, + [In] StdString.Ptr pSourceMapUrl, + [In] ulong uniqueId, + [In] DocumentKind documentKind, + [In] IntPtr pDocumentInfo, + [In] IntPtr pCode, [In] int length + ); + [DllImport("ClearScriptV8.osx-arm64.dylib", CallingConvention = CallingConvention.StdCall)] private static extern V8Script.Handle V8Context_CompileProducingCache( [In] V8Context.Handle hContext, @@ -17156,6 +17360,7 @@ [Out] out ulong contextCount #endregion + } } diff --git a/ClearScript/V8/V8ContextProxy.cs b/ClearScript/V8/V8ContextProxy.cs index b61ef7648..84411e1c2 100644 --- a/ClearScript/V8/V8ContextProxy.cs +++ b/ClearScript/V8/V8ContextProxy.cs @@ -34,6 +34,8 @@ public static V8ContextProxy Create(V8IsolateProxy isolateProxy, string name, V8 public abstract V8Script Compile(UniqueDocumentInfo documentInfo, string code); + public abstract V8Script Compile(UniqueDocumentInfo documentInfo, IntPtr code, int length); + public abstract V8Script Compile(UniqueDocumentInfo documentInfo, string code, V8CacheKind cacheKind, out byte[] cacheBytes); public abstract V8Script Compile(UniqueDocumentInfo documentInfo, string code, V8CacheKind cacheKind, byte[] cacheBytes, out bool cacheAccepted); diff --git a/ClearScript/V8/V8ScriptEngine.cs b/ClearScript/V8/V8ScriptEngine.cs index e88d3209d..ccf912cf4 100644 --- a/ClearScript/V8/V8ScriptEngine.cs +++ b/ClearScript/V8/V8ScriptEngine.cs @@ -493,6 +493,19 @@ public V8Script Compile(DocumentInfo documentInfo, string code) return ScriptInvoke(() => CompileInternal(documentInfo.MakeUnique(this), code)); } + /// + /// Creates a compiled script with the specified document meta-information. + /// + /// A structure containing meta-information for the script document. + /// A pointer to a UTF-16 string + /// The length of the code string + /// A compiled script that can be executed multiple times without recompilation. + public V8Script Compile(DocumentInfo documentInfo, IntPtr code, int length) + { + VerifyNotDisposed(); + return ScriptInvoke(() => CompileInternal(documentInfo.MakeUnique(this), code, length)); + } + /// /// Creates a compiled script, generating cache data for accelerated recompilation. /// @@ -1176,6 +1189,36 @@ private V8Script CompileInternal(UniqueDocumentInfo documentInfo, string code) return script; } + private V8Script CompileInternal(UniqueDocumentInfo documentInfo, IntPtr code, int length) + { + /*if (FormatCode) + { + code = MiscHelpers.FormatCode(code); + }*/ + + CommonJSManager.Module module = null; + if (documentInfo.Category == ModuleCategory.CommonJS) + { + /*module = CommonJSManager.GetOrCreateModule(documentInfo, code); + code = CommonJSManager.Module.GetAugmentedCode(code);*/ + throw new NotImplementedException(); + } + else if ((documentInfo.Category != DocumentCategory.Script) && (documentInfo.Category != ModuleCategory.Standard)) + { + throw new NotSupportedException("The script engine cannot compile documents of type '" + documentInfo.Category + "'"); + } + + // ReSharper disable once LocalVariableHidesMember + var script = proxy.Compile(documentInfo, code, length); + + if (module != null) + { + module.Evaluator = () => proxy.Execute(script, true); + } + + return script; + } + private V8Script CompileInternal(UniqueDocumentInfo documentInfo, string code, V8CacheKind cacheKind, out byte[] cacheBytes) { if (FormatCode) diff --git a/ClearScriptV8/V8SplitProxyNative.cpp b/ClearScriptV8/V8SplitProxyNative.cpp index c6ab68235..1b3f82a50 100644 --- a/ClearScriptV8/V8SplitProxyNative.cpp +++ b/ClearScriptV8/V8SplitProxyNative.cpp @@ -1267,6 +1267,28 @@ NATIVE_ENTRY_POINT(V8ScriptHandle*) V8Context_Compile(const V8ContextHandle& han //----------------------------------------------------------------------------- +NATIVE_ENTRY_POINT(V8ScriptHandle*) V8Context_CompileIntPtr(const V8ContextHandle& handle, StdString&& resourceName, StdString&& sourceMapUrl, uint64_t uniqueId, DocumentKind documentKind, void* pvDocumentInfo, const StdChar* code, int32_t length) noexcept +{ + V8DocumentInfo documentInfo(std::move(resourceName), std::move(sourceMapUrl), uniqueId, documentKind, pvDocumentInfo); + + auto spContext = handle.GetEntity(); + if (!spContext.IsEmpty()) + { + try + { + return new V8ScriptHandle(spContext->Compile(documentInfo, StdString(code, length))); + } + catch (const V8Exception& exception) + { + exception.ScheduleScriptEngineException(); + } + } + + return nullptr; +} + +//----------------------------------------------------------------------------- + NATIVE_ENTRY_POINT(V8ScriptHandle*) V8Context_CompileProducingCache(const V8ContextHandle& handle, StdString&& resourceName, StdString&& sourceMapUrl, uint64_t uniqueId, DocumentKind documentKind, void* pvDocumentInfo, StdString&& code, V8CacheKind cacheKind, std::vector& cacheBytes) noexcept { cacheBytes.clear(); diff --git a/ClearScriptV8/V8SplitProxyNative.h b/ClearScriptV8/V8SplitProxyNative.h index f9e90363f..4556376a1 100644 --- a/ClearScriptV8/V8SplitProxyNative.h +++ b/ClearScriptV8/V8SplitProxyNative.h @@ -271,6 +271,7 @@ NATIVE_ENTRY_POINT(void) V8Context_AwaitDebuggerAndPause(const V8ContextHandle& NATIVE_ENTRY_POINT(void) V8Context_CancelAwaitDebugger(const V8ContextHandle& handle) noexcept; NATIVE_ENTRY_POINT(void) V8Context_ExecuteCode(const V8ContextHandle& handle, StdString&& resourceName, StdString&& sourceMapUrl, uint64_t uniqueId, DocumentKind documentKind, void* pvDocumentInfo, const StdString& code, StdBool evaluate, V8Value& result) noexcept; NATIVE_ENTRY_POINT(V8ScriptHandle*) V8Context_Compile(const V8ContextHandle& handle, StdString&& resourceName, StdString&& sourceMapUrl, uint64_t uniqueId, DocumentKind documentKind, void* pvDocumentInfo, StdString&& code) noexcept; +NATIVE_ENTRY_POINT(V8ScriptHandle*) V8Context_CompileIntPtr(const V8ContextHandle& handle, StdString&& resourceName, StdString&& sourceMapUrl, uint64_t uniqueId, DocumentKind documentKind, void* pvDocumentInfo, const StdChar* code, int32_t length) noexcept; NATIVE_ENTRY_POINT(V8ScriptHandle*) V8Context_CompileProducingCache(const V8ContextHandle& handle, StdString&& resourceName, StdString&& sourceMapUrl, uint64_t uniqueId, DocumentKind documentKind, void* pvDocumentInfo, StdString&& code, V8CacheKind cacheKind, std::vector& cacheBytes) noexcept; NATIVE_ENTRY_POINT(V8ScriptHandle*) V8Context_CompileConsumingCache(const V8ContextHandle& handle, StdString&& resourceName, StdString&& sourceMapUrl, uint64_t uniqueId, DocumentKind documentKind, void* pvDocumentInfo, StdString&& code, V8CacheKind cacheKind, const std::vector& cacheBytes, StdBool& cacheAccepted) noexcept; NATIVE_ENTRY_POINT(V8ScriptHandle*) V8Context_CompileUpdatingCache(const V8ContextHandle& handle, StdString&& resourceName, StdString&& sourceMapUrl, uint64_t uniqueId, DocumentKind documentKind, void* pvDocumentInfo, StdString&& code, V8CacheKind cacheKind, std::vector& cacheBytes, V8CacheResult& cacheResult) noexcept;