1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef nsJSEnvironment_h
7 #define nsJSEnvironment_h
9 #include "nsIScriptContext.h"
10 #include "nsIScriptGlobalObject.h"
13 #include "nsCycleCollectionParticipant.h"
15 #include "mozilla/Attributes.h"
16 #include "mozilla/TimeStamp.h"
17 #include "nsThreadUtils.h"
18 #include "xpcpublic.h"
20 class nsICycleCollectorListener
;
27 struct CycleCollectorResults
;
29 static const uint32_t kMajorForgetSkippableCalls
= 5;
31 } // namespace mozilla
33 class nsJSContext
: public nsIScriptContext
{
35 nsJSContext(bool aGCOnDestruction
, nsIScriptGlobalObject
* aGlobalObject
);
37 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
38 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsJSContext
,
41 virtual nsIScriptGlobalObject
* GetGlobalObject() override
;
42 inline nsIScriptGlobalObject
* GetGlobalObjectRef() {
43 return mGlobalObjectRef
;
46 virtual nsresult
SetProperty(JS::Handle
<JSObject
*> aTarget
,
47 const char* aPropName
,
48 nsISupports
* aVal
) override
;
50 virtual bool GetProcessingScriptTag() override
;
51 virtual void SetProcessingScriptTag(bool aResult
) override
;
53 virtual nsresult
InitClasses(JS::Handle
<JSObject
*> aGlobalObj
) override
;
55 virtual void SetWindowProxy(JS::Handle
<JSObject
*> aWindowProxy
) override
;
56 virtual JSObject
* GetWindowProxy() override
;
58 enum IsShrinking
{ ShrinkingGC
, NonShrinkingGC
};
60 // Setup all the statics etc - safe to call multiple times after Startup().
61 static void EnsureStatics();
63 static void SetLowMemoryState(bool aState
);
65 static void GarbageCollectNow(JS::GCReason reason
,
66 IsShrinking aShrinking
= NonShrinkingGC
);
68 static void RunIncrementalGCSlice(JS::GCReason aReason
,
69 IsShrinking aShrinking
,
70 js::SliceBudget
& aBudget
);
72 static void CycleCollectNow(mozilla::CCReason aReason
,
73 nsICycleCollectorListener
* aListener
= nullptr);
75 // Finish up any in-progress incremental GC.
76 static void PrepareForCycleCollectionSlice(mozilla::CCReason aReason
,
77 mozilla::TimeStamp aDeadline
);
79 // Run a cycle collector slice, using a heuristic to decide how long to run
81 static void RunCycleCollectorSlice(mozilla::CCReason aReason
,
82 mozilla::TimeStamp aDeadline
);
84 // Run a cycle collector slice, using the given work budget.
85 static void RunCycleCollectorWorkSlice(int64_t aWorkBudget
);
87 static void BeginCycleCollectionCallback(mozilla::CCReason aReason
);
88 static void EndCycleCollectionCallback(
89 const mozilla::CycleCollectorResults
& aResults
);
91 // Return the longest CC slice time since ClearMaxCCSliceTime() was last
93 static uint32_t GetMaxCCSliceTimeSinceClear();
94 static void ClearMaxCCSliceTime();
96 // If there is some pending CC or GC timer/runner, this will run it.
97 static void RunNextCollectorTimer(
99 mozilla::TimeStamp aDeadline
= mozilla::TimeStamp());
100 // If user has been idle and aDocShell is for an iframe being loaded in an
101 // already loaded top level docshell, this will run a CC or GC
102 // timer/runner if there is such pending.
103 static void MaybeRunNextCollectorSlice(nsIDocShell
* aDocShell
,
104 JS::GCReason aReason
);
106 // The GC should run soon, in the zone of aObj if given. If aObj is
107 // nullptr, collect all Zones.
108 static void PokeGC(JS::GCReason aReason
, JSObject
* aObj
,
109 mozilla::TimeDuration aDelay
= 0);
111 // If usage is nearing a threshold, request idle-only GC work. (This is called
112 // when a collection would be relatively convenient.)
113 static void MaybePokeGC();
115 // Immediately perform a non-incremental shrinking GC and CC.
116 static void DoLowMemoryGC();
118 // Perform a non-incremental shrinking GC and CC according to
120 static void LowMemoryGC();
122 static void MaybePokeCC();
124 // Calling LikelyShortLivingObjectCreated() makes a GC more likely.
125 static void LikelyShortLivingObjectCreated();
127 static bool HasHadCleanupSinceLastGC();
129 nsIScriptGlobalObject
* GetCachedGlobalObject() {
130 // Verify that we have a global so that this
131 // does always return a null when GetGlobalObject() is null.
132 JSObject
* global
= GetWindowProxy();
133 return global
? mGlobalObjectRef
.get() : nullptr;
137 virtual ~nsJSContext();
139 // Helper to convert xpcom datatypes to jsvals.
140 nsresult
ConvertSupportsTojsvals(JSContext
* aCx
, nsISupports
* aArgs
,
141 JS::Handle
<JSObject
*> aScope
,
142 JS::MutableHandleVector
<JS::Value
> aArgsOut
);
144 nsresult
AddSupportsPrimitiveTojsvals(JSContext
* aCx
, nsISupports
* aArg
,
150 JS::Heap
<JSObject
*> mWindowProxy
;
152 bool mGCOnDestruction
;
153 bool mProcessingScriptTag
;
155 // mGlobalObjectRef ensures that the outer window stays alive as long as the
156 // context does. It is eventually collected by the cycle collector.
157 nsCOMPtr
<nsIScriptGlobalObject
> mGlobalObjectRef
;
159 static bool DOMOperationCallback(JSContext
* cx
);
162 namespace mozilla::dom
{
164 class SerializedStackHolder
;
166 void StartupJSEnvironment();
167 void ShutdownJSEnvironment();
169 // Runnable that's used to do async error reporting
170 class AsyncErrorReporter final
: public mozilla::Runnable
{
172 explicit AsyncErrorReporter(xpc::ErrorReport
* aReport
);
173 // SerializeStack is suitable for main or worklet thread use.
174 // Stacks from worker threads are not supported.
175 // See https://bugzilla.mozilla.org/show_bug.cgi?id=1578968
176 void SerializeStack(JSContext
* aCx
, JS::Handle
<JSObject
*> aStack
);
178 // Set the exception value associated with this error report.
179 // Should only be called from the main thread.
180 void SetException(JSContext
* aCx
, JS::Handle
<JS::Value
> aException
);
183 NS_IMETHOD
Run() override
;
185 // This is only used on main thread!
186 JS::PersistentRooted
<JS::Value
> mException
;
187 bool mHasException
= false;
189 RefPtr
<xpc::ErrorReport
> mReport
;
190 // This may be used to marshal a stack from an arbitrary thread/runtime into
191 // the main thread/runtime where the console service runs.
192 UniquePtr
<SerializedStackHolder
> mStackHolder
;
195 } // namespace mozilla::dom
197 // An interface for fast and native conversion to/from nsIArray. If an object
198 // supports this interface, JS can reach directly in for the argv, and avoid
199 // nsISupports conversion. If this interface is not supported, the object will
200 // be queried for nsIArray, and everything converted via xpcom objects.
201 #define NS_IJSARGARRAY_IID \
203 0xb6acdac8, 0xf5c6, 0x432c, { \
204 0xa8, 0x6e, 0x33, 0xee, 0xb1, 0xb0, 0xcd, 0xdc \
208 class nsIJSArgArray
: public nsIArray
{
210 NS_DECLARE_STATIC_IID_ACCESSOR(NS_IJSARGARRAY_IID
)
211 // Bug 312003 describes why this must be "void **", but after calling argv
212 // may be cast to JS::Value* and the args found at:
213 // ((JS::Value*)argv)[0], ..., ((JS::Value*)argv)[argc - 1]
214 virtual nsresult
GetArgs(uint32_t* argc
, void** argv
) = 0;
217 NS_DEFINE_STATIC_IID_ACCESSOR(nsIJSArgArray
, NS_IJSARGARRAY_IID
)
219 #endif /* nsJSEnvironment_h */