Skip to content

Commit 8daeeb3

Browse files
committed
Merged PR 147332: Batch tracing of the blink wrappers until EndMark. We will then do Chakra GC marking and Blink tracing in a loop until no more Blink tracing work is remaining.
Batch tracing of the blink wrappers until EndMark. We will then do Chakra GC marking and Blink tracing in a loop until no more Blink tracing work is remaining.
2 parents ddcb579 + 80e5ad8 commit 8daeeb3

File tree

10 files changed

+208
-23
lines changed

10 files changed

+208
-23
lines changed

bin/ch/ChakraRtInterface.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ bool ChakraRTInterface::LoadChakraDll(ArgInfo* argInfo, HINSTANCE *outLibrary)
7878
m_jsApiHooks.pfJsrtCreateRuntime = (JsAPIHooks::JsrtCreateRuntimePtr)GetChakraCoreSymbol(library, "JsCreateRuntime");
7979
m_jsApiHooks.pfJsrtCreateContext = (JsAPIHooks::JsrtCreateContextPtr)GetChakraCoreSymbol(library, "JsCreateContext");
8080
m_jsApiHooks.pfJsrtSetObjectBeforeCollectCallback = (JsAPIHooks::JsrtSetObjectBeforeCollectCallbackPtr)GetChakraCoreSymbol(library, "JsSetObjectBeforeCollectCallback");
81+
m_jsApiHooks.pfJsrtSetRuntimeDomWrapperTracingCallbacks = (JsAPIHooks::JsrtSetRuntimeDomWrapperTracingCallbacksPtr)GetChakraCoreSymbol(library, "JsSetRuntimeDomWrapperTracingCallbacks");
8182
m_jsApiHooks.pfJsrtSetRuntimeMemoryLimit = (JsAPIHooks::JsrtSetRuntimeMemoryLimitPtr)GetChakraCoreSymbol(library, "JsSetRuntimeMemoryLimit");
8283
m_jsApiHooks.pfJsrtSetCurrentContext = (JsAPIHooks::JsrtSetCurrentContextPtr)GetChakraCoreSymbol(library, "JsSetCurrentContext");
8384
m_jsApiHooks.pfJsrtGetCurrentContext = (JsAPIHooks::JsrtGetCurrentContextPtr)GetChakraCoreSymbol(library, "JsGetCurrentContext");

bin/ch/ChakraRtInterface.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ struct JsAPIHooks
99
typedef JsErrorCode (WINAPI *JsrtCreateRuntimePtr)(JsRuntimeAttributes attributes, JsThreadServiceCallback threadService, JsRuntimeHandle *runtime);
1010
typedef JsErrorCode (WINAPI *JsrtCreateContextPtr)(JsRuntimeHandle runtime, JsContextRef *newContext);
1111
typedef JsErrorCode (WINAPI *JsrtSetObjectBeforeCollectCallbackPtr)(JsRef ref, void* callbackState, JsObjectBeforeCollectCallback objectBeforeCollectCallback);
12+
typedef JsErrorCode(WINAPI *JsrtSetRuntimeDomWrapperTracingCallbacksPtr)(JsRuntimeHandle runtime, JsRef wrapperTracingState, JsDOMWrapperTracingCallback wrapperTracingCallback, JsDOMWrapperTracingDoneCallback wrapperTracingDoneCallback, JsDOMWrapperTracingEnterFinalPauseCallback enterFinalPauseCallback);
1213
typedef JsErrorCode (WINAPI *JsrtSetRuntimeMemoryLimitPtr)(JsRuntimeHandle runtime, size_t memoryLimit);
1314
typedef JsErrorCode (WINAPI *JsrtSetCurrentContextPtr)(JsContextRef context);
1415
typedef JsErrorCode (WINAPI *JsrtGetCurrentContextPtr)(JsContextRef* context);
@@ -118,6 +119,7 @@ struct JsAPIHooks
118119
JsrtCreateRuntimePtr pfJsrtCreateRuntime;
119120
JsrtCreateContextPtr pfJsrtCreateContext;
120121
JsrtSetObjectBeforeCollectCallbackPtr pfJsrtSetObjectBeforeCollectCallback;
122+
JsrtSetRuntimeDomWrapperTracingCallbacksPtr pfJsrtSetRuntimeDomWrapperTracingCallbacks;
121123
JsrtSetRuntimeMemoryLimitPtr pfJsrtSetRuntimeMemoryLimit;
122124
JsrtSetCurrentContextPtr pfJsrtSetCurrentContext;
123125
JsrtGetCurrentContextPtr pfJsrtGetCurrentContext;
@@ -341,6 +343,7 @@ class ChakraRTInterface
341343
static JsErrorCode WINAPI JsCreateRuntime(JsRuntimeAttributes attributes, JsThreadServiceCallback threadService, JsRuntimeHandle *runtime) { return HOOK_JS_API(CreateRuntime(attributes, threadService, runtime)); }
342344
static JsErrorCode WINAPI JsCreateContext(JsRuntimeHandle runtime, JsContextRef *newContext) { return HOOK_JS_API(CreateContext(runtime, newContext)); }
343345
static JsErrorCode WINAPI JsSetObjectBeforeCollectCallback(JsRef ref, void* callbackState, JsObjectBeforeCollectCallback objectBeforeCollectCallback) { return HOOK_JS_API(SetObjectBeforeCollectCallback(ref, callbackState, objectBeforeCollectCallback)); }
346+
static JsErrorCode WINAPI JsSetRuntimeDomWrapperTracingCallbacks(JsRuntimeHandle runtime, JsRef wrapperTracingState, JsDOMWrapperTracingCallback wrapperTracingCallback, JsDOMWrapperTracingDoneCallback wrapperTracingDoneCallback, JsDOMWrapperTracingEnterFinalPauseCallback enterFinalPauseCallback) { return HOOK_JS_API(SetRuntimeDomWrapperTracingCallbacks(runtime, wrapperTracingState, wrapperTracingCallback, wrapperTracingDoneCallback, enterFinalPauseCallback)); }
344347
static JsErrorCode WINAPI JsSetRuntimeMemoryLimit(JsRuntimeHandle runtime, size_t memory) { return HOOK_JS_API(SetRuntimeMemoryLimit(runtime, memory)); }
345348
static JsErrorCode WINAPI JsSetCurrentContext(JsContextRef context) { return HOOK_JS_API(SetCurrentContext(context)); }
346349
static JsErrorCode WINAPI JsGetCurrentContext(JsContextRef* context) { return HOOK_JS_API(GetCurrentContext(context)); }

lib/Common/Memory/Recycler.cpp

Lines changed: 73 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ Recycler::Recycler(AllocationPolicyManager * policyManager, IdleDecommitPageAllo
192192
inDisposeWrapper(false),
193193
hasDisposableObject(false),
194194
hasNativeGCHost(false),
195+
needExternalWrapperTracing(false),
195196
tickCountNextDispose(0),
196197
transientPinnedObject(nullptr),
197198
pinnedObjectMap(1024, HeapAllocator::GetNoMemProtectInstance()),
@@ -951,6 +952,18 @@ Recycler::SetHasNativeGCHost()
951952
this->hasNativeGCHost = true;
952953
}
953954

955+
void
956+
Recycler::SetNeedExternalWrapperTracing()
957+
{
958+
this->needExternalWrapperTracing = true;
959+
}
960+
961+
void
962+
Recycler::ClearNeedExternalWrapperTracing()
963+
{
964+
this->needExternalWrapperTracing = false;
965+
}
966+
954967
bool
955968
Recycler::NeedOOMRescan() const
956969
{
@@ -2534,6 +2547,7 @@ Recycler::DoParallelMark()
25342547
if (actualSplitCount == 0)
25352548
{
25362549
this->ProcessMark(false);
2550+
25372551
return;
25382552
}
25392553

@@ -2779,6 +2793,23 @@ Recycler::EndMarkCheckOOMRescan()
27792793
return oomRescan;
27802794
}
27812795

2796+
void
2797+
Recycler::FinishWrapperObjectTracing()
2798+
{
2799+
//TODO:akatti:Add ETW event for this.
2800+
// Tracing would have generated more work for mark and marking might generate more work for tracing.
2801+
// We continue until we find no more pending tracing work.
2802+
do
2803+
{
2804+
this->collectionWrapper->EndMarkDomWrapperTracingCallback();
2805+
this->ProcessMark(false);
2806+
} while (!this->collectionWrapper->EndMarkDomWrapperTracingDoneCallback());
2807+
2808+
// This is just to wait until tracing has finished.
2809+
this->collectionWrapper->EndMarkDomWrapperTracingCallback();
2810+
this->ClearNeedExternalWrapperTracing();
2811+
}
2812+
27822813
bool
27832814
Recycler::EndMark()
27842815
{
@@ -2792,6 +2823,12 @@ Recycler::EndMark()
27922823
{
27932824
// We have finished marking
27942825
AUTO_NO_EXCEPTION_REGION;
2826+
if (this->needExternalWrapperTracing)
2827+
{
2828+
this->collectionWrapper->EndMarkDomWrapperTracingEnterFinalPauseCallback();
2829+
this->FinishWrapperObjectTracing();
2830+
}
2831+
27952832
collectionWrapper->EndMarkCallback();
27962833
}
27972834

@@ -2894,8 +2931,15 @@ Recycler::EndMarkOnLowMemory()
28942931
}
28952932
#endif
28962933

2897-
// Drain the mark stack
2898-
ProcessMark(false);
2934+
// Drain the mark stack along with any required DOM wrapper tracing.
2935+
if (this->needExternalWrapperTracing)
2936+
{
2937+
this->FinishWrapperObjectTracing();
2938+
}
2939+
else
2940+
{
2941+
this->ProcessMark(false);
2942+
}
28992943

29002944
#ifdef ENABLE_DEBUG_CONFIG_OPTIONS
29012945
iterations++;
@@ -2943,7 +2987,14 @@ Recycler::PostHeapEnumScan(PostHeapEnumScanCallback callback, void *data)
29432987
this->postHeapEnunScanData = data;
29442988

29452989
FindRoots();
2946-
ProcessMark(false);
2990+
if (this->needExternalWrapperTracing)
2991+
{
2992+
this->FinishWrapperObjectTracing();
2993+
}
2994+
else
2995+
{
2996+
this->ProcessMark(false);
2997+
}
29472998

29482999
this->pfPostHeapEnumScanCallback = NULL;
29493000
this->postHeapEnunScanData = NULL;
@@ -8975,6 +9026,25 @@ void Recycler::SetObjectBeforeCollectCallback(void* object,
89759026
}
89769027
}
89779028

9029+
void Recycler::SetDOMWrapperTracingCallback(void * state, DOMWrapperTracingCallback tracingCallback, DOMWrapperTracingDoneCallback tracingDoneCallback, DOMWrapperTracingEnterFinalPauseCallback enterFinalPauseCallback)
9030+
{
9031+
Assert(state);
9032+
Assert(tracingCallback);
9033+
Assert(enterFinalPauseCallback);
9034+
this->collectionWrapper->SetWrapperTracingCallbackState(state);
9035+
this->collectionWrapper->SetDOMWrapperTracingCallback(tracingCallback);
9036+
this->collectionWrapper->SetDOMWrapperTracingDoneCallback(tracingDoneCallback);
9037+
this->collectionWrapper->SetDOMWrapperTracingEnterFinalPauseCallback(enterFinalPauseCallback);
9038+
}
9039+
9040+
void Recycler::ClearDOMWrapperTracingCallback()
9041+
{
9042+
this->collectionWrapper->SetWrapperTracingCallbackState(nullptr);
9043+
this->collectionWrapper->SetDOMWrapperTracingCallback(nullptr);
9044+
this->collectionWrapper->SetDOMWrapperTracingDoneCallback(nullptr);
9045+
this->collectionWrapper->SetDOMWrapperTracingEnterFinalPauseCallback(nullptr);
9046+
}
9047+
89789048
bool Recycler::ProcessObjectBeforeCollectCallbacks(bool atShutdown/*= false*/)
89799049
{
89809050
if (this->objectBeforeCollectCallbackList == nullptr)

lib/Common/Memory/Recycler.h

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,10 @@ class RecyclerWeakReferenceRegion {
305305

306306
typedef void (__cdecl* ExternalRootMarker)(void *);
307307

308+
typedef void (*DOMWrapperTracingCallback)(_In_opt_ void *data);
309+
typedef bool (*DOMWrapperTracingDoneCallback)(_In_opt_ void *data);
310+
typedef void (*DOMWrapperTracingEnterFinalPauseCallback)(_In_opt_ void *data);
311+
308312
class RecyclerCollectionWrapper
309313
{
310314
public:
@@ -359,8 +363,58 @@ class RecyclerCollectionWrapper
359363
_isScriptContextCloseGCPending = TRUE;
360364
}
361365

366+
void SetDOMWrapperTracingCallback(DOMWrapperTracingCallback callback)
367+
{
368+
wrapperTracingCallback = callback;
369+
}
370+
371+
void SetWrapperTracingCallbackState(void * state)
372+
{
373+
wrapperTracingCallbackState = state;
374+
}
375+
376+
void SetDOMWrapperTracingEnterFinalPauseCallback(DOMWrapperTracingEnterFinalPauseCallback callback)
377+
{
378+
wrapperTracingEnterFinalPauseCallback = callback;
379+
}
380+
381+
void SetDOMWrapperTracingDoneCallback(DOMWrapperTracingDoneCallback callback)
382+
{
383+
wrapperTracingDoneCallback = callback;
384+
}
385+
386+
void EndMarkDomWrapperTracingCallback()
387+
{
388+
if (this->wrapperTracingCallback)
389+
{
390+
this->wrapperTracingCallback(this->wrapperTracingCallbackState);
391+
}
392+
}
393+
394+
bool EndMarkDomWrapperTracingDoneCallback()
395+
{
396+
if (this->wrapperTracingDoneCallback)
397+
{
398+
return this->wrapperTracingDoneCallback(this->wrapperTracingCallbackState);
399+
}
400+
401+
return true;
402+
}
403+
404+
void EndMarkDomWrapperTracingEnterFinalPauseCallback()
405+
{
406+
if (this->wrapperTracingEnterFinalPauseCallback)
407+
{
408+
this->wrapperTracingEnterFinalPauseCallback(this->wrapperTracingCallbackState);
409+
}
410+
}
411+
362412
protected:
363413
BOOL _isScriptContextCloseGCPending;
414+
void * wrapperTracingCallbackState;
415+
DOMWrapperTracingCallback wrapperTracingCallback;
416+
DOMWrapperTracingDoneCallback wrapperTracingDoneCallback;
417+
DOMWrapperTracingEnterFinalPauseCallback wrapperTracingEnterFinalPauseCallback;
364418
};
365419

366420
class DefaultRecyclerCollectionWrapper : public RecyclerCollectionWrapper
@@ -913,6 +967,7 @@ class Recycler
913967
bool allowDispose;
914968
bool inDisposeWrapper;
915969
bool needOOMRescan;
970+
bool needExternalWrapperTracing;
916971
bool hasDisposableObject;
917972
bool hasNativeGCHost;
918973
DWORD tickCountNextDispose;
@@ -1177,6 +1232,8 @@ class Recycler
11771232
void SetIsInScript(bool isInScript);
11781233
bool HasNativeGCHost() const;
11791234
void SetHasNativeGCHost();
1235+
void SetNeedExternalWrapperTracing();
1236+
void ClearNeedExternalWrapperTracing();
11801237
bool ShouldIdleCollectOnExit();
11811238
void ScheduleNextCollection();
11821239

@@ -1601,6 +1658,7 @@ class Recycler
16011658
void DoParallelMark();
16021659
void DoBackgroundParallelMark();
16031660
#endif
1661+
void FinishWrapperObjectTracing();
16041662

16051663
size_t RootMark(CollectionState markState);
16061664

@@ -2041,6 +2099,8 @@ class Recycler
20412099
ObjectBeforeCollectCallbackWrapper callbackWrapper,
20422100
void* threadContext);
20432101
void ClearObjectBeforeCollectCallbacks();
2102+
void SetDOMWrapperTracingCallback(void * state, DOMWrapperTracingCallback tracingCallback, DOMWrapperTracingDoneCallback tracingDoneCallback, DOMWrapperTracingEnterFinalPauseCallback enterFinalPauseCallback);
2103+
void ClearDOMWrapperTracingCallback();
20442104
bool IsInObjectBeforeCollectCallback() const { return objectBeforeCollectCallbackState != ObjectBeforeCollectCallback_None; }
20452105
private:
20462106
struct ObjectBeforeCollectCallbackData

lib/Jsrt/ChakraCommon.h

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -717,26 +717,6 @@ typedef unsigned short uint16_t;
717717
/// </param>
718718
typedef void (CHAKRA_CALLBACK *JsTraceCallback)(_In_opt_ void *data);
719719

720-
/// <summary>
721-
/// A structure containing information about interceptors.
722-
/// </summary>
723-
typedef struct JsGetterSetterInterceptor {
724-
JsValueRef getTrap;
725-
JsValueRef setTrap;
726-
JsValueRef deletePropertyTrap;
727-
JsValueRef enumerateTrap;
728-
JsValueRef ownKeysTrap;
729-
JsValueRef hasTrap;
730-
JsValueRef getOwnPropertyDescriptorTrap;
731-
JsValueRef definePropertyTrap;
732-
733-
explicit JsGetterSetterInterceptor(JsGetterSetterInterceptor * getterSetterInterceptor);
734-
735-
JsGetterSetterInterceptor();
736-
737-
bool AreInterceptorsRequired();
738-
} JsGetterSetterInterceptor;
739-
740720
/// <summary>
741721
/// A finalizer callback.
742722
/// </summary>
@@ -773,6 +753,41 @@ typedef unsigned short uint16_t;
773753
/// <param name="callbackState">The data argument to be passed to the callback.</param>
774754
typedef void (CHAKRA_CALLBACK *JsPromiseContinuationCallback)(_In_ JsValueRef task, _In_opt_ void *callbackState);
775755

756+
/// <summary>
757+
/// A structure containing information about interceptors.
758+
/// </summary>
759+
typedef struct JsGetterSetterInterceptor {
760+
JsValueRef getTrap;
761+
JsValueRef setTrap;
762+
JsValueRef deletePropertyTrap;
763+
JsValueRef enumerateTrap;
764+
JsValueRef ownKeysTrap;
765+
JsValueRef hasTrap;
766+
JsValueRef getOwnPropertyDescriptorTrap;
767+
JsValueRef definePropertyTrap;
768+
769+
explicit JsGetterSetterInterceptor(JsGetterSetterInterceptor * getterSetterInterceptor);
770+
771+
JsGetterSetterInterceptor();
772+
773+
bool AreInterceptorsRequired();
774+
} JsGetterSetterInterceptor;
775+
776+
/// <summary>
777+
/// A callback for tracing references back from Chakra to DOM wrappers.
778+
/// </summary>
779+
typedef void (CHAKRA_CALLBACK *JsDOMWrapperTracingCallback)(_In_opt_ void *data);
780+
781+
/// <summary>
782+
/// A callback for checking whether tracing from Chakra to DOM wrappers has completed.
783+
/// </summary>
784+
typedef bool (CHAKRA_CALLBACK *JsDOMWrapperTracingDoneCallback)(_In_opt_ void *data);
785+
786+
/// <summary>
787+
/// A callback for entering final pause for tracing DOM wrappers.
788+
/// </summary>
789+
typedef void(*JsDOMWrapperTracingEnterFinalPauseCallback)(_In_opt_ void *data);
790+
776791
/// <summary>
777792
/// Creates a new runtime.
778793
/// </summary>

lib/Jsrt/ChakraCore.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1565,6 +1565,14 @@ CHAKRA_API
15651565
_In_opt_ void *callbackState,
15661566
_In_ JsBeforeSweepCallback beforeSweepCallback);
15671567

1568+
CHAKRA_API
1569+
JsSetRuntimeDomWrapperTracingCallbacks(
1570+
_In_ JsRuntimeHandle runtimeHandle,
1571+
_In_ JsRef wrapperTracingState,
1572+
_In_ JsDOMWrapperTracingCallback wrapperTracingCallback,
1573+
_In_ JsDOMWrapperTracingDoneCallback wrapperTracingDoneCallback,
1574+
_In_ JsDOMWrapperTracingEnterFinalPauseCallback enterFinalPauseCallback);
1575+
15681576
CHAKRA_API
15691577
JsTraceExternalReference(
15701578
_In_ JsRuntimeHandle runtimeHandle,

lib/Jsrt/Jsrt.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6141,6 +6141,31 @@ CHAKRA_API JsSetRuntimeBeforeSweepCallback(_In_ JsRuntimeHandle runtimeHandle, _
61416141
});
61426142
}
61436143

6144+
CHAKRA_API
6145+
JsSetRuntimeDomWrapperTracingCallbacks(
6146+
_In_ JsRuntimeHandle runtimeHandle,
6147+
_In_ JsRef wrapperTracingState,
6148+
_In_ JsDOMWrapperTracingCallback wrapperTracingCallback,
6149+
_In_ JsDOMWrapperTracingDoneCallback wrapperTracingDoneCallback,
6150+
_In_ JsDOMWrapperTracingEnterFinalPauseCallback enterFinalPauseCallback)
6151+
{
6152+
return GlobalAPIWrapper_NoRecord([&]() -> JsErrorCode {
6153+
VALIDATE_INCOMING_RUNTIME_HANDLE(runtimeHandle);
6154+
6155+
ThreadContext * threadContext = JsrtRuntime::FromHandle(runtimeHandle)->GetThreadContext();
6156+
ThreadContextScope scope(threadContext);
6157+
6158+
if (!scope.IsValid())
6159+
{
6160+
return JsErrorWrongThread;
6161+
}
6162+
6163+
Recycler * recycler = threadContext->GetRecycler();
6164+
recycler->SetDOMWrapperTracingCallback(wrapperTracingState, reinterpret_cast<DOMWrapperTracingCallback>(wrapperTracingCallback), reinterpret_cast<DOMWrapperTracingDoneCallback>(wrapperTracingDoneCallback), reinterpret_cast<DOMWrapperTracingEnterFinalPauseCallback>(enterFinalPauseCallback));
6165+
return JsNoError;
6166+
});
6167+
}
6168+
61446169
CHAKRA_API JsTraceExternalReference(_In_ JsRuntimeHandle runtimeHandle, _In_ JsValueRef value)
61456170
{
61466171
return GlobalAPIWrapper_NoRecord([&]() -> JsErrorCode {

lib/Jsrt/JsrtCommonExports.inc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
JsSetObjectBeforeCollectCallback
2+
JsSetRuntimeDomWrapperTracingCallbacks
23
JsCreateRuntime
34
JsCollectGarbage
45
JsDisposeRuntime

lib/Jsrt/JsrtExternalObject.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ JsrtExternalObject* JsrtExternalObject::Create(void *data, uint inlineSlotSize,
8080

8181
void JsrtExternalObject::Mark(Recycler * recycler)
8282
{
83+
recycler->SetNeedExternalWrapperTracing();
8384
JsTraceCallback traceCallback = this->GetExternalType()->GetJsTraceCallback();
8485
Assert(nullptr != traceCallback);
8586
JsrtCallbackState scope(nullptr);

0 commit comments

Comments
 (0)