@@ -15,10 +15,24 @@ namespace Microsoft.ClearScript.V8.SplitProxy
1515 // ReSharper disable once PartialTypeWithSinglePart
1616 internal static partial class V8SplitProxyManaged
1717 {
18- public static IntPtr MethodTable { get ; } = CreateMethodTable ( ) ;
18+ public static IntPtr MethodTable => pFunctionPtrs ;
19+
20+ private static IntPtr pDelegatePtrs ;
21+ private static IntPtr pFunctionPtrs ;
22+ private static int methodCount ;
1923
2024 [ ThreadStatic ] public static Exception ScheduledException ;
2125
26+ public static void Initialize ( )
27+ {
28+ CreateMethodTable ( ) ;
29+ }
30+
31+ public static void Teardown ( )
32+ {
33+ DestroyMethodTable ( ) ;
34+ }
35+
2236 private static void ScheduleHostException ( IntPtr pObject , Exception exception )
2337 {
2438 V8SplitProxyNative . InvokeNoThrow ( instance => instance . HostException_Schedule ( exception . GetBaseException ( ) . Message , V8ProxyHelpers . MarshalExceptionToScript ( pObject , exception ) ) ) ;
@@ -305,110 +319,138 @@ [In] int count
305319
306320 #endregion
307321
308- #region method table construction
322+ #region method table construction and teardown
309323
310- private static IntPtr CreateMethodTable ( )
324+ private static void CreateMethodTable ( )
311325 {
312- IntPtr [ ] methodPtrs =
326+ Debug . Assert ( methodCount == 0 ) ;
327+
328+ ( IntPtr , IntPtr ) [ ] methodPairs =
313329 {
314330 //----------------------------------------------------------------------------
315331 // IMPORTANT: maintain synchronization with V8_SPLIT_PROXY_MANAGED_METHOD_LIST
316332 //----------------------------------------------------------------------------
317333
318- GetMethodPtr < RawScheduleForwardingException > ( ScheduleForwardingException ) ,
319- GetMethodPtr < RawScheduleInvalidOperationException > ( ScheduleInvalidOperationException ) ,
320- GetMethodPtr < RawScheduleScriptEngineException > ( ScheduleScriptEngineException ) ,
321- GetMethodPtr < RawScheduleScriptInterruptedException > ( ScheduleScriptInterruptedException ) ,
334+ GetMethodPair < RawScheduleForwardingException > ( ScheduleForwardingException ) ,
335+ GetMethodPair < RawScheduleInvalidOperationException > ( ScheduleInvalidOperationException ) ,
336+ GetMethodPair < RawScheduleScriptEngineException > ( ScheduleScriptEngineException ) ,
337+ GetMethodPair < RawScheduleScriptInterruptedException > ( ScheduleScriptInterruptedException ) ,
322338
323339 #if NET5_0_OR_GREATER
324- InvokeHostActionFastMethodPtr ,
340+ ( IntPtr . Zero , InvokeHostActionFastMethodPtr ) ,
325341 #else
326- GetMethodPtr < RawInvokeAction > ( InvokeHostAction ) ,
342+ GetMethodPair < RawInvokeAction > ( InvokeHostAction ) ,
327343 #endif
328344
329- GetMethodPtr < RawProcessArrayBufferOrViewData > ( ProcessArrayBufferOrViewData ) ,
330- GetMethodPtr < RawProcessCpuProfile > ( ProcessCpuProfile ) ,
331- GetMethodPtr < RawCreateV8ObjectCache > ( CreateV8ObjectCache ) ,
345+ GetMethodPair < RawProcessArrayBufferOrViewData > ( ProcessArrayBufferOrViewData ) ,
346+ GetMethodPair < RawProcessCpuProfile > ( ProcessCpuProfile ) ,
347+ GetMethodPair < RawCreateV8ObjectCache > ( CreateV8ObjectCache ) ,
332348
333349 #if NET5_0_OR_GREATER
334- CacheV8ObjectFastMethodPtr ,
335- GetCachedV8ObjectFastMethodPtr ,
350+ ( IntPtr . Zero , CacheV8ObjectFastMethodPtr ) ,
351+ ( IntPtr . Zero , GetCachedV8ObjectFastMethodPtr ) ,
336352 #else
337- GetMethodPtr < RawCacheV8Object > ( CacheV8Object ) ,
338- GetMethodPtr < RawGetCachedV8Object > ( GetCachedV8Object ) ,
353+ GetMethodPair < RawCacheV8Object > ( CacheV8Object ) ,
354+ GetMethodPair < RawGetCachedV8Object > ( GetCachedV8Object ) ,
339355 #endif
340356
341- GetMethodPtr < RawGetAllCachedV8Objects > ( GetAllCachedV8Objects ) ,
342- GetMethodPtr < RawRemoveV8ObjectCacheEntry > ( RemoveV8ObjectCacheEntry ) ,
343- GetMethodPtr < RawCreateDebugAgent > ( CreateDebugAgent ) ,
344- GetMethodPtr < RawSendDebugMessage > ( SendDebugMessage ) ,
345- GetMethodPtr < RawDestroyDebugAgent > ( DestroyDebugAgent ) ,
346- GetMethodPtr < RawGetMaxScriptCacheSize > ( GetMaxScriptCacheSize ) ,
347- GetMethodPtr < RawGetMaxModuleCacheSize > ( GetMaxModuleCacheSize ) ,
357+ GetMethodPair < RawGetAllCachedV8Objects > ( GetAllCachedV8Objects ) ,
358+ GetMethodPair < RawRemoveV8ObjectCacheEntry > ( RemoveV8ObjectCacheEntry ) ,
359+ GetMethodPair < RawCreateDebugAgent > ( CreateDebugAgent ) ,
360+ GetMethodPair < RawSendDebugMessage > ( SendDebugMessage ) ,
361+ GetMethodPair < RawDestroyDebugAgent > ( DestroyDebugAgent ) ,
362+ GetMethodPair < RawGetMaxScriptCacheSize > ( GetMaxScriptCacheSize ) ,
363+ GetMethodPair < RawGetMaxModuleCacheSize > ( GetMaxModuleCacheSize ) ,
348364
349365 #if NET5_0_OR_GREATER
350- AddRefHostObjectFastMethodPtr ,
351- ReleaseHostObjectFastMethodPtr ,
352- GetHostObjectInvocabilityFastMethodPtr ,
366+ ( IntPtr . Zero , AddRefHostObjectFastMethodPtr ) ,
367+ ( IntPtr . Zero , ReleaseHostObjectFastMethodPtr ) ,
368+ ( IntPtr . Zero , GetHostObjectInvocabilityFastMethodPtr ) ,
353369 #else
354- GetMethodPtr < RawAddRefHostObject > ( AddRefHostObject ) ,
355- GetMethodPtr < RawReleaseHostObject > ( ReleaseHostObject ) ,
356- GetMethodPtr < RawGetHostObjectInvocability > ( GetHostObjectInvocability ) ,
370+ GetMethodPair < RawAddRefHostObject > ( AddRefHostObject ) ,
371+ GetMethodPair < RawReleaseHostObject > ( ReleaseHostObject ) ,
372+ GetMethodPair < RawGetHostObjectInvocability > ( GetHostObjectInvocability ) ,
357373 #endif
358374
359375 #if NET5_0_OR_GREATER
360- GetHostObjectNamedPropertyFastMethodPtr ,
361- GetHostObjectNamedPropertyWithCacheabilityFastMethodPtr ,
362- SetHostObjectNamedPropertyFastMethodPtr ,
376+ ( IntPtr . Zero , GetHostObjectNamedPropertyFastMethodPtr ) ,
377+ ( IntPtr . Zero , GetHostObjectNamedPropertyWithCacheabilityFastMethodPtr ) ,
378+ ( IntPtr . Zero , SetHostObjectNamedPropertyFastMethodPtr ) ,
363379 #else
364- GetMethodPtr < RawGetHostObjectNamedProperty > ( GetHostObjectNamedProperty ) ,
365- GetMethodPtr < RawGetHostObjectNamedPropertyWithCacheability > ( GetHostObjectNamedPropertyWithCacheability ) ,
366- GetMethodPtr < RawSetHostObjectNamedProperty > ( SetHostObjectNamedProperty ) ,
380+ GetMethodPair < RawGetHostObjectNamedProperty > ( GetHostObjectNamedProperty ) ,
381+ GetMethodPair < RawGetHostObjectNamedPropertyWithCacheability > ( GetHostObjectNamedPropertyWithCacheability ) ,
382+ GetMethodPair < RawSetHostObjectNamedProperty > ( SetHostObjectNamedProperty ) ,
367383 #endif
368384
369- GetMethodPtr < RawDeleteHostObjectNamedProperty > ( DeleteHostObjectNamedProperty ) ,
370- GetMethodPtr < RawGetHostObjectPropertyNames > ( GetHostObjectPropertyNames ) ,
385+ GetMethodPair < RawDeleteHostObjectNamedProperty > ( DeleteHostObjectNamedProperty ) ,
386+ GetMethodPair < RawGetHostObjectPropertyNames > ( GetHostObjectPropertyNames ) ,
371387
372388 #if NET5_0_OR_GREATER
373- GetHostObjectIndexedPropertyFastMethodPtr ,
374- SetHostObjectIndexedPropertyFastMethodPtr ,
389+ ( IntPtr . Zero , GetHostObjectIndexedPropertyFastMethodPtr ) ,
390+ ( IntPtr . Zero , SetHostObjectIndexedPropertyFastMethodPtr ) ,
375391 #else
376- GetMethodPtr < RawGetHostObjectIndexedProperty > ( GetHostObjectIndexedProperty ) ,
377- GetMethodPtr < RawSetHostObjectIndexedProperty > ( SetHostObjectIndexedProperty ) ,
392+ GetMethodPair < RawGetHostObjectIndexedProperty > ( GetHostObjectIndexedProperty ) ,
393+ GetMethodPair < RawSetHostObjectIndexedProperty > ( SetHostObjectIndexedProperty ) ,
378394 #endif
379395
380- GetMethodPtr < RawDeleteHostObjectIndexedProperty > ( DeleteHostObjectIndexedProperty ) ,
381- GetMethodPtr < RawGetHostObjectPropertyIndices > ( GetHostObjectPropertyIndices ) ,
396+ GetMethodPair < RawDeleteHostObjectIndexedProperty > ( DeleteHostObjectIndexedProperty ) ,
397+ GetMethodPair < RawGetHostObjectPropertyIndices > ( GetHostObjectPropertyIndices ) ,
382398
383399 #if NET5_0_OR_GREATER
384- InvokeHostObjectFastMethodPtr ,
385- InvokeHostObjectMethodFastMethodPtr ,
400+ ( IntPtr . Zero , InvokeHostObjectFastMethodPtr ) ,
401+ ( IntPtr . Zero , InvokeHostObjectMethodFastMethodPtr ) ,
386402 #else
387- GetMethodPtr < RawInvokeHostObject > ( InvokeHostObject ) ,
388- GetMethodPtr < RawInvokeHostObjectMethod > ( InvokeHostObjectMethod ) ,
403+ GetMethodPair < RawInvokeHostObject > ( InvokeHostObject ) ,
404+ GetMethodPair < RawInvokeHostObjectMethod > ( InvokeHostObjectMethod ) ,
389405 #endif
390406
391- GetMethodPtr < RawGetHostObjectEnumerator > ( GetHostObjectEnumerator ) ,
392- GetMethodPtr < RawGetHostObjectAsyncEnumerator > ( GetHostObjectAsyncEnumerator ) ,
393- GetMethodPtr < RawQueueNativeCallback > ( QueueNativeCallback ) ,
394- GetMethodPtr < RawCreateNativeCallbackTimer > ( CreateNativeCallbackTimer ) ,
395- GetMethodPtr < RawChangeNativeCallbackTimer > ( ChangeNativeCallbackTimer ) ,
396- GetMethodPtr < RawDestroyNativeCallbackTimer > ( DestroyNativeCallbackTimer ) ,
397- GetMethodPtr < RawLoadModule > ( LoadModule ) ,
398- GetMethodPtr < RawCreateModuleContext > ( CreateModuleContext ) ,
399- GetMethodPtr < RawWriteBytesToStream > ( WriteBytesToStream ) ,
400- GetMethodPtr < RawGetGlobalFlags > ( GetGlobalFlags )
407+ GetMethodPair < RawGetHostObjectEnumerator > ( GetHostObjectEnumerator ) ,
408+ GetMethodPair < RawGetHostObjectAsyncEnumerator > ( GetHostObjectAsyncEnumerator ) ,
409+ GetMethodPair < RawQueueNativeCallback > ( QueueNativeCallback ) ,
410+ GetMethodPair < RawCreateNativeCallbackTimer > ( CreateNativeCallbackTimer ) ,
411+ GetMethodPair < RawChangeNativeCallbackTimer > ( ChangeNativeCallbackTimer ) ,
412+ GetMethodPair < RawDestroyNativeCallbackTimer > ( DestroyNativeCallbackTimer ) ,
413+ GetMethodPair < RawLoadModule > ( LoadModule ) ,
414+ GetMethodPair < RawCreateModuleContext > ( CreateModuleContext ) ,
415+ GetMethodPair < RawWriteBytesToStream > ( WriteBytesToStream ) ,
416+ GetMethodPair < RawGetGlobalFlags > ( GetGlobalFlags )
401417 } ;
402418
403- var pMethodTable = Marshal . AllocCoTaskMem ( IntPtr . Size * methodPtrs . Length ) ;
404- Marshal . Copy ( methodPtrs , 0 , pMethodTable , methodPtrs . Length ) ;
405- return pMethodTable ;
419+ methodCount = methodPairs . Length ;
420+ pDelegatePtrs = Marshal . AllocCoTaskMem ( methodCount * IntPtr . Size ) ;
421+ pFunctionPtrs = Marshal . AllocCoTaskMem ( methodCount * IntPtr . Size ) ;
422+
423+ for ( var index = 0 ; index < methodCount ; index ++ )
424+ {
425+ Marshal . WriteIntPtr ( pDelegatePtrs , index * IntPtr . Size , methodPairs [ index ] . Item1 ) ;
426+ Marshal . WriteIntPtr ( pFunctionPtrs , index * IntPtr . Size , methodPairs [ index ] . Item2 ) ;
427+ }
428+ }
429+
430+ private static void DestroyMethodTable ( )
431+ {
432+ Debug . Assert ( methodCount > 0 ) ;
433+
434+ for ( var index = 0 ; index < methodCount ; index ++ )
435+ {
436+ var pDelegate = Marshal . ReadIntPtr ( pDelegatePtrs , index * IntPtr . Size ) ;
437+ if ( pDelegate != IntPtr . Zero )
438+ {
439+ V8ProxyHelpers . ReleaseHostObject ( pDelegate ) ;
440+ }
441+ }
442+
443+ Marshal . FreeCoTaskMem ( pDelegatePtrs ) ;
444+ Marshal . FreeCoTaskMem ( pFunctionPtrs ) ;
445+
446+ methodCount = 0 ;
447+ pDelegatePtrs = IntPtr . Zero ;
448+ pFunctionPtrs = IntPtr . Zero ;
406449 }
407450
408- private static IntPtr GetMethodPtr < T > ( T del )
451+ private static ( IntPtr , IntPtr ) GetMethodPair < T > ( T del )
409452 {
410- GCHandle . Alloc ( del ) ;
411- return Marshal . GetFunctionPointerForDelegate ( ( Delegate ) ( object ) del ) ;
453+ return ( V8ProxyHelpers . AddRefHostObject ( del ) , Marshal . GetFunctionPointerForDelegate ( ( Delegate ) ( object ) del ) ) ;
412454 }
413455
414456 #endregion
@@ -422,11 +464,11 @@ private static void ScheduleForwardingException(V8Value.Ptr pException)
422464 var exception = V8ProxyHelpers . MarshalExceptionToHost ( V8Value . Get ( pException ) ) ;
423465 if ( exception is ScriptEngineException scriptEngineException )
424466 {
425- ScheduledException = new ScriptEngineException ( scriptEngineException . EngineName , scriptEngineException . Message , scriptEngineException . ErrorDetails , scriptEngineException . HResult , scriptEngineException . IsFatal , scriptEngineException . ExecutionStarted , scriptEngineException . ScriptException , scriptEngineException ) ;
467+ ScheduledException = new ScriptEngineException ( scriptEngineException . EngineName , scriptEngineException . Message , scriptEngineException . ErrorDetails , scriptEngineException . HResult , scriptEngineException . IsFatal , scriptEngineException . ExecutionStarted , scriptEngineException . ScriptExceptionAsObject , scriptEngineException ) ;
426468 }
427469 else if ( exception is ScriptInterruptedException scriptInterruptedException )
428470 {
429- ScheduledException = new ScriptInterruptedException ( scriptInterruptedException . EngineName , scriptInterruptedException . Message , scriptInterruptedException . ErrorDetails , scriptInterruptedException . HResult , scriptInterruptedException . IsFatal , scriptInterruptedException . ExecutionStarted , scriptInterruptedException . ScriptException , scriptInterruptedException ) ;
471+ ScheduledException = new ScriptInterruptedException ( scriptInterruptedException . EngineName , scriptInterruptedException . Message , scriptInterruptedException . ErrorDetails , scriptInterruptedException . HResult , scriptInterruptedException . IsFatal , scriptInterruptedException . ExecutionStarted , scriptInterruptedException . ScriptExceptionAsObject , scriptInterruptedException ) ;
430472 }
431473 else
432474 {
0 commit comments