JSStencil.h (10726B)
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 7 #ifndef js_experimental_JSStencil_h 8 #define js_experimental_JSStencil_h 9 10 /* The `JS::Stencil` type holds the output of the JS Parser before it is 11 * allocated on the GC heap as a `JSScript`. This form may be serialized as 12 * part of building a bytecode cache. This `Stencil` is not associated with any 13 * particular Realm and may be generated off-main-thread, making it useful for 14 * building script loaders. 15 */ 16 17 #include "mozilla/MemoryReporting.h" // mozilla::MallocSizeOf 18 #include "mozilla/RefPtr.h" // RefPtr, already_AddRefed 19 #include "mozilla/Utf8.h" // mozilla::Utf8Unit 20 #include "mozilla/Vector.h" // mozilla::Vector 21 22 #include <stddef.h> // size_t 23 24 #include "jstypes.h" // JS_PUBLIC_API 25 26 #include "js/CompileOptions.h" // JS::ReadOnlyCompileOptions, JS::InstantiateOptions, JS::ReadOnlyDecodeOptions 27 #include "js/SourceText.h" // JS::SourceText 28 #include "js/Transcoding.h" // JS::TranscodeBuffer, JS::TranscodeRange 29 30 struct JS_PUBLIC_API JSContext; 31 class JS_PUBLIC_API JSTracer; 32 33 // Underlying opaque type. 34 namespace js { 35 class FrontendContext; 36 namespace frontend { 37 struct CompilationStencil; 38 struct CompilationGCOutput; 39 struct CompilationInput; 40 struct PreallocatedCompilationGCOutput; 41 struct InitialStencilAndDelazifications; 42 } // namespace frontend 43 } // namespace js 44 45 // ************************************************************************ 46 // Types 47 // ************************************************************************ 48 49 namespace JS { 50 51 using Stencil = js::frontend::InitialStencilAndDelazifications; 52 using FrontendContext = js::FrontendContext; 53 54 // Temporary storage used during instantiating Stencil. 55 // 56 // Off-thread APIs can allocate this instance off main thread, and pass it back 57 // to the main thread, in order to reduce the main thread allocation. 58 struct JS_PUBLIC_API InstantiationStorage { 59 private: 60 // Owned CompilationGCOutput. 61 // 62 // This uses raw pointer instead of UniquePtr because 63 // PreallocatedCompilationGCOutput is opaque. 64 js::frontend::PreallocatedCompilationGCOutput* gcOutput_ = nullptr; 65 66 friend JS_PUBLIC_API JSScript* InstantiateGlobalStencil( 67 JSContext* cx, const InstantiateOptions& options, Stencil* stencil, 68 InstantiationStorage* storage); 69 70 friend JS_PUBLIC_API JSObject* InstantiateModuleStencil( 71 JSContext* cx, const InstantiateOptions& options, Stencil* stencil, 72 InstantiationStorage* storage); 73 74 friend JS_PUBLIC_API bool PrepareForInstantiate( 75 JS::FrontendContext* fc, JS::Stencil& stencil, 76 JS::InstantiationStorage& storage); 77 78 public: 79 InstantiationStorage() = default; 80 InstantiationStorage(InstantiationStorage&& other) 81 : gcOutput_(other.gcOutput_) { 82 other.gcOutput_ = nullptr; 83 } 84 85 ~InstantiationStorage(); 86 87 void operator=(InstantiationStorage&& other) { 88 gcOutput_ = other.gcOutput_; 89 other.gcOutput_ = nullptr; 90 } 91 92 private: 93 InstantiationStorage(const InstantiationStorage& other) = delete; 94 void operator=(const InstantiationStorage& aOther) = delete; 95 96 public: 97 bool isValid() const { return !!gcOutput_; } 98 }; 99 100 } // namespace JS 101 102 // ************************************************************************ 103 // Reference Count 104 // ************************************************************************ 105 106 namespace JS { 107 108 // These non-member functions let us manipulate the ref counts of the opaque 109 // Stencil type. The RefPtrTraits below calls these for use when using the 110 // RefPtr type. 111 JS_PUBLIC_API void StencilAddRef(Stencil* stencil); 112 JS_PUBLIC_API void StencilRelease(Stencil* stencil); 113 114 } // namespace JS 115 116 namespace mozilla { 117 template <> 118 struct RefPtrTraits<JS::Stencil> { 119 static void AddRef(JS::Stencil* stencil) { JS::StencilAddRef(stencil); } 120 static void Release(JS::Stencil* stencil) { JS::StencilRelease(stencil); } 121 }; 122 } // namespace mozilla 123 124 // ************************************************************************ 125 // Properties 126 // ************************************************************************ 127 128 namespace JS { 129 130 // Return true if the stencil relies on external data as a result of XDR 131 // decoding. 132 extern JS_PUBLIC_API bool StencilIsBorrowed(Stencil* stencil); 133 134 extern JS_PUBLIC_API size_t SizeOfStencil(Stencil* stencil, 135 mozilla::MallocSizeOf mallocSizeOf); 136 137 } // namespace JS 138 139 // ************************************************************************ 140 // Compilation 141 // ************************************************************************ 142 143 namespace JS { 144 145 // Compile the source text into a JS::Stencil using the provided options. The 146 // resulting stencil may be instantiated into any Realm on the current runtime 147 // and may be used multiple times. 148 // 149 // NOTE: On error, a null will be returned and an exception will be set on the 150 // JSContext. 151 extern JS_PUBLIC_API already_AddRefed<Stencil> CompileGlobalScriptToStencil( 152 JSContext* cx, const ReadOnlyCompileOptions& options, 153 SourceText<mozilla::Utf8Unit>& srcBuf); 154 extern JS_PUBLIC_API already_AddRefed<Stencil> CompileGlobalScriptToStencil( 155 JSContext* cx, const ReadOnlyCompileOptions& options, 156 SourceText<char16_t>& srcBuf); 157 158 // Compile the source text into a JS::Stencil using "module" parse goal. The 159 // ECMAScript spec defines special semantics so we use a seperate entry point 160 // here for clarity. The result is still a JS::Stencil, but should use the 161 // appropriate instantiate API below. 162 extern JS_PUBLIC_API already_AddRefed<Stencil> CompileModuleScriptToStencil( 163 JSContext* cx, const ReadOnlyCompileOptions& options, 164 SourceText<mozilla::Utf8Unit>& srcBuf); 165 extern JS_PUBLIC_API already_AddRefed<Stencil> CompileModuleScriptToStencil( 166 JSContext* cx, const ReadOnlyCompileOptions& options, 167 SourceText<char16_t>& srcBuf); 168 169 } // namespace JS 170 171 // ************************************************************************ 172 // Instantiation 173 // ************************************************************************ 174 175 namespace JS { 176 177 // Instantiate the Stencil into current Realm and return the JSScript. 178 extern JS_PUBLIC_API JSScript* InstantiateGlobalStencil( 179 JSContext* cx, const InstantiateOptions& options, Stencil* stencil, 180 InstantiationStorage* storage = nullptr); 181 182 // Instantiate a module Stencil and return the associated object. Inside the 183 // engine this is a js::ModuleObject. 184 extern JS_PUBLIC_API JSObject* InstantiateModuleStencil( 185 JSContext* cx, const InstantiateOptions& options, Stencil* stencil, 186 InstantiationStorage* storage = nullptr); 187 188 } // namespace JS 189 190 // ************************************************************************ 191 // Transcoding 192 // ************************************************************************ 193 194 namespace JS { 195 196 // Serialize the Stencil into the transcode buffer. 197 // This fails if the stencil contains asm.js. 198 // 199 // If the `buffer` isn't empty, the start of the `buffer` should meet 200 // JS::IsTranscodingBytecodeAligned, and the length should meet 201 // JS::IsTranscodingBytecodeOffsetAligned. 202 // 203 // NOTE: As long as IsTranscodingBytecodeOffsetAligned is met, that means 204 // there's JS::BytecodeOffsetAlignment+extra bytes in the buffer, 205 // IsTranscodingBytecodeAligned should be guaranteed to meet by 206 // malloc, used by MallocAllocPolicy in mozilla::Vector. 207 extern JS_PUBLIC_API TranscodeResult EncodeStencil(JSContext* cx, 208 Stencil* stencil, 209 TranscodeBuffer& buffer); 210 extern JS_PUBLIC_API TranscodeResult EncodeStencil(JS::FrontendContext* fc, 211 Stencil* stencil, 212 TranscodeBuffer& buffer); 213 214 // Deserialize data and create a new Stencil. 215 extern JS_PUBLIC_API TranscodeResult 216 DecodeStencil(JSContext* cx, const ReadOnlyDecodeOptions& options, 217 const TranscodeRange& range, Stencil** stencilOut); 218 extern JS_PUBLIC_API TranscodeResult 219 DecodeStencil(JS::FrontendContext* fc, const ReadOnlyDecodeOptions& options, 220 const TranscodeRange& range, Stencil** stencilOut); 221 222 // ************************************************************************ 223 // Collect delazifications 224 // ************************************************************************ 225 226 // Start collecting delazifications for given script or module's source object. 227 // 228 // If the source object is already collecting delazifications, alreadyStarted is 229 // set to true and returns true. alreadyStarted is set to false otherwise. 230 extern JS_PUBLIC_API bool StartCollectingDelazifications( 231 JSContext* cx, JS::Handle<JSScript*> script, Stencil* stencil, 232 bool& alreadyStarted); 233 234 extern JS_PUBLIC_API bool StartCollectingDelazifications( 235 JSContext* cx, JS::Handle<JSObject*> module, Stencil* stencil, 236 bool& alreadyStarted); 237 238 // Finish collecting delazifications and retrieve the result as a JS::Stencil 239 // that reflects the delazification from the execution. 240 // 241 // The returned stencil is the same thing as what is passed to 242 // JS::StartCollectingDelazifications. 243 extern JS_PUBLIC_API bool FinishCollectingDelazifications( 244 JSContext* cx, Handle<JSScript*> script, JS::Stencil** stencilOut); 245 246 // Similar to |JS::FinishCollectingDelazifications|, but receives module obect. 247 extern JS_PUBLIC_API bool FinishCollectingDelazifications( 248 JSContext* cx, Handle<JSObject*> module, JS::Stencil** stencilOut); 249 250 extern JS_PUBLIC_API void AbortCollectingDelazifications( 251 Handle<JSScript*> script); 252 extern JS_PUBLIC_API void AbortCollectingDelazifications( 253 Handle<JSObject*> module); 254 255 // ************************************************************************ 256 // Cache 257 // ************************************************************************ 258 259 // Returns true if the stencil is compatible with caching. 260 // This returns false if the stencil contains asm.js. 261 extern JS_PUBLIC_API bool IsStencilCacheable(JS::Stencil* stencil); 262 263 // ************************************************************************ 264 // Script Source 265 // ************************************************************************ 266 267 // Returns the uncompressed source text length of given stencil. 268 // Returns 0 if the source is discarded or somehow not accessible. 269 extern JS_PUBLIC_API size_t GetScriptSourceLength(JS::Stencil* stencil); 270 271 } // namespace JS 272 273 #endif // js_experimental_JSStencil_h