Line data Source code
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
8 :
9 : #include "nsIScriptContext.h"
10 : #include "nsIScriptGlobalObject.h"
11 : #include "nsCOMPtr.h"
12 : #include "nsIObserver.h"
13 : #include "prtime.h"
14 : #include "nsCycleCollectionParticipant.h"
15 : #include "nsIXPConnect.h"
16 : #include "nsIArray.h"
17 : #include "mozilla/Attributes.h"
18 : #include "mozilla/TimeStamp.h"
19 : #include "nsThreadUtils.h"
20 : #include "xpcpublic.h"
21 :
22 : class nsICycleCollectorListener;
23 : class nsScriptNameSpaceManager;
24 :
25 : namespace JS {
26 : class AutoValueVector;
27 : } // namespace JS
28 :
29 : namespace mozilla {
30 : template <class> class Maybe;
31 : struct CycleCollectorResults;
32 : } // namespace mozilla
33 :
34 : // The amount of time we wait between a request to GC (due to leaving
35 : // a page) and doing the actual GC.
36 : #define NS_GC_DELAY 4000 // ms
37 :
38 : #define NS_MAJOR_FORGET_SKIPPABLE_CALLS 5
39 :
40 : class nsJSContext : public nsIScriptContext
41 : {
42 : public:
43 : nsJSContext(bool aGCOnDestruction, nsIScriptGlobalObject* aGlobalObject);
44 :
45 : NS_DECL_CYCLE_COLLECTING_ISUPPORTS
46 188 : NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsJSContext,
47 : nsIScriptContext)
48 :
49 : virtual nsIScriptGlobalObject *GetGlobalObject() override;
50 : inline nsIScriptGlobalObject *GetGlobalObjectRef() { return mGlobalObjectRef; }
51 :
52 : virtual nsresult InitContext() override;
53 : virtual bool IsContextInitialized() override;
54 :
55 : virtual nsresult SetProperty(JS::Handle<JSObject*> aTarget, const char* aPropName, nsISupports* aVal) override;
56 :
57 : virtual bool GetProcessingScriptTag() override;
58 : virtual void SetProcessingScriptTag(bool aResult) override;
59 :
60 : virtual nsresult InitClasses(JS::Handle<JSObject*> aGlobalObj) override;
61 :
62 : virtual void WillInitializeContext() override;
63 : virtual void DidInitializeContext() override;
64 :
65 : virtual void SetWindowProxy(JS::Handle<JSObject*> aWindowProxy) override;
66 : virtual JSObject* GetWindowProxy() override;
67 :
68 : static void LoadStart();
69 : static void LoadEnd();
70 :
71 : enum IsShrinking {
72 : ShrinkingGC,
73 : NonShrinkingGC
74 : };
75 :
76 : enum IsIncremental {
77 : IncrementalGC,
78 : NonIncrementalGC
79 : };
80 :
81 : // Setup all the statics etc - safe to call multiple times after Startup().
82 : void EnsureStatics();
83 :
84 : static void GarbageCollectNow(JS::gcreason::Reason reason,
85 : IsIncremental aIncremental = NonIncrementalGC,
86 : IsShrinking aShrinking = NonShrinkingGC,
87 : int64_t aSliceMillis = 0);
88 :
89 : static void CycleCollectNow(nsICycleCollectorListener *aListener = nullptr);
90 :
91 : // Run a cycle collector slice, using a heuristic to decide how long to run it.
92 : static void RunCycleCollectorSlice(mozilla::TimeStamp aDeadline);
93 :
94 : // Run a cycle collector slice, using the given work budget.
95 : static void RunCycleCollectorWorkSlice(int64_t aWorkBudget);
96 :
97 : static void BeginCycleCollectionCallback();
98 : static void EndCycleCollectionCallback(mozilla::CycleCollectorResults &aResults);
99 :
100 : // Return the longest CC slice time since ClearMaxCCSliceTime() was last called.
101 : static uint32_t GetMaxCCSliceTimeSinceClear();
102 : static void ClearMaxCCSliceTime();
103 :
104 : static void RunNextCollectorTimer();
105 :
106 : // The GC should probably run soon, in the zone of object aObj (if given).
107 : static void PokeGC(JS::gcreason::Reason aReason, JSObject* aObj, int aDelay = 0);
108 : static void KillGCTimer();
109 :
110 : static void PokeShrinkingGC();
111 : static void KillShrinkingGCTimer();
112 :
113 : static void MaybePokeCC();
114 : static void KillCCRunner();
115 : static void KillICCRunner();
116 : static void KillFullGCTimer();
117 : static void KillInterSliceGCRunner();
118 :
119 : // Calling LikelyShortLivingObjectCreated() makes a GC more likely.
120 : static void LikelyShortLivingObjectCreated();
121 :
122 : static uint32_t CleanupsSinceLastGC();
123 :
124 : nsIScriptGlobalObject* GetCachedGlobalObject()
125 : {
126 : // Verify that we have a global so that this
127 : // does always return a null when GetGlobalObject() is null.
128 : JSObject* global = GetWindowProxy();
129 : return global ? mGlobalObjectRef.get() : nullptr;
130 : }
131 :
132 : protected:
133 : virtual ~nsJSContext();
134 :
135 : // Helper to convert xpcom datatypes to jsvals.
136 : nsresult ConvertSupportsTojsvals(nsISupports *aArgs,
137 : JS::Handle<JSObject*> aScope,
138 : JS::AutoValueVector &aArgsOut);
139 :
140 : nsresult AddSupportsPrimitiveTojsvals(nsISupports *aArg, JS::Value *aArgv);
141 :
142 : private:
143 : void Destroy();
144 :
145 : JS::Heap<JSObject*> mWindowProxy;
146 :
147 : bool mIsInitialized;
148 : bool mGCOnDestruction;
149 : bool mProcessingScriptTag;
150 :
151 : PRTime mModalStateTime;
152 : uint32_t mModalStateDepth;
153 :
154 : // mGlobalObjectRef ensures that the outer window stays alive as long as the
155 : // context does. It is eventually collected by the cycle collector.
156 : nsCOMPtr<nsIScriptGlobalObject> mGlobalObjectRef;
157 :
158 : static bool DOMOperationCallback(JSContext *cx);
159 : };
160 :
161 : namespace mozilla {
162 : namespace dom {
163 :
164 : void StartupJSEnvironment();
165 : void ShutdownJSEnvironment();
166 :
167 : // Get the NameSpaceManager, creating if necessary
168 : nsScriptNameSpaceManager* GetNameSpaceManager();
169 :
170 : // Peek the NameSpaceManager, without creating it.
171 : nsScriptNameSpaceManager* PeekNameSpaceManager();
172 :
173 : // Runnable that's used to do async error reporting
174 0 : class AsyncErrorReporter final : public mozilla::Runnable
175 : {
176 : public:
177 : // aWindow may be null if this error report is not associated with a window
178 0 : explicit AsyncErrorReporter(xpc::ErrorReport* aReport)
179 0 : : Runnable("dom::AsyncErrorReporter")
180 0 : , mReport(aReport)
181 0 : {}
182 :
183 0 : NS_IMETHOD Run() override
184 : {
185 0 : mReport->LogToConsole();
186 0 : return NS_OK;
187 : }
188 :
189 : protected:
190 : RefPtr<xpc::ErrorReport> mReport;
191 : };
192 :
193 : } // namespace dom
194 : } // namespace mozilla
195 :
196 : // An interface for fast and native conversion to/from nsIArray. If an object
197 : // supports this interface, JS can reach directly in for the argv, and avoid
198 : // nsISupports conversion. If this interface is not supported, the object will
199 : // be queried for nsIArray, and everything converted via xpcom objects.
200 : #define NS_IJSARGARRAY_IID \
201 : { 0xb6acdac8, 0xf5c6, 0x432c, \
202 : { 0xa8, 0x6e, 0x33, 0xee, 0xb1, 0xb0, 0xcd, 0xdc } }
203 :
204 0 : class nsIJSArgArray : public nsIArray
205 : {
206 : public:
207 : NS_DECLARE_STATIC_IID_ACCESSOR(NS_IJSARGARRAY_IID)
208 : // Bug 312003 describes why this must be "void **", but after calling argv
209 : // may be cast to JS::Value* and the args found at:
210 : // ((JS::Value*)argv)[0], ..., ((JS::Value*)argv)[argc - 1]
211 : virtual nsresult GetArgs(uint32_t *argc, void **argv) = 0;
212 : };
213 :
214 : NS_DEFINE_STATIC_IID_ACCESSOR(nsIJSArgArray, NS_IJSARGARRAY_IID)
215 :
216 : #endif /* nsJSEnvironment_h */
|