tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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