tor-browser

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

StencilXdr.h (8190B)


      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 frontend_StencilXdr_h
      8 #define frontend_StencilXdr_h
      9 
     10 #include "mozilla/RefPtr.h"  // RefPtr
     11 
     12 #include "frontend/ParserAtom.h"  // ParserAtom, ParserAtomSpan
     13 #include "frontend/Stencil.h"  // BitIntStencil, ScopeStencil, BaseParserScopeData
     14 #include "js/CompileOptions.h"  // JS::ReadOnlyDecodeOptions, JS::ReadOnlyDecodeOptions
     15 #include "js/Transcoding.h"  // JS::TranscodeBuffer, JS::TranscodeRange, JS::TranscodeResult
     16 #include "vm/Xdr.h"  // XDRMode, XDRResult, XDRState
     17 
     18 namespace JS {
     19 
     20 class ReadOnlyDecodeOptions;
     21 
     22 }  // namespace JS
     23 
     24 namespace js {
     25 
     26 class LifoAlloc;
     27 class ObjLiteralStencil;
     28 class ScriptSource;
     29 class SharedImmutableScriptData;
     30 
     31 class XDRStencilDecoder;
     32 class XDRStencilEncoder;
     33 
     34 namespace frontend {
     35 
     36 struct CompilationStencil;
     37 struct ExtensibleCompilationStencil;
     38 struct SharedDataContainer;
     39 
     40 // Check that we can copy data to disk and restore it in another instance of
     41 // the program in a different address space.
     42 template <typename DataT>
     43 struct CanCopyDataToDisk {
     44  // Check that the object is fully packed, to save disk space.
     45 #ifdef __cpp_lib_has_unique_object_representations
     46  static constexpr bool unique_repr =
     47      std::has_unique_object_representations<DataT>();
     48 #else
     49  static constexpr bool unique_repr = true;
     50 #endif
     51 
     52  // Approximation which assumes that 32bits variant of the class would not
     53  // have pointers if the 64bits variant does not have pointer.
     54  static constexpr bool no_pointer =
     55      alignof(DataT) < alignof(void*) || sizeof(void*) == sizeof(uint32_t);
     56 
     57  static constexpr bool value = unique_repr && no_pointer;
     58 };
     59 
     60 // This is just a namespace class that can be used in friend declarations,
     61 // so that the statically declared XDR methods within have access to the
     62 // relevant struct internals.
     63 class StencilXDR {
     64 private:
     65  template <XDRMode mode>
     66  [[nodiscard]] static XDRResult codeSourceUnretrievableUncompressed(
     67      XDRState<mode>* xdr, ScriptSource* ss, uint8_t sourceCharSize,
     68      uint32_t uncompressedLength);
     69 
     70  template <typename Unit,
     71            template <typename U, SourceRetrievable CanRetrieve> class Data,
     72            XDRMode mode>
     73  static void codeSourceRetrievable(ScriptSource* ss);
     74 
     75  template <typename Unit, XDRMode mode>
     76  [[nodiscard]] static XDRResult codeSourceUncompressedData(
     77      XDRState<mode>* const xdr, ScriptSource* const ss);
     78 
     79  template <typename Unit, XDRMode mode>
     80  [[nodiscard]] static XDRResult codeSourceCompressedData(
     81      XDRState<mode>* const xdr, ScriptSource* const ss);
     82 
     83  template <typename Unit, XDRMode mode>
     84  static void codeSourceRetrievableData(ScriptSource* ss);
     85 
     86  template <XDRMode mode>
     87  [[nodiscard]] static XDRResult codeSourceData(XDRState<mode>* const xdr,
     88                                                ScriptSource* const ss);
     89 
     90 public:
     91  template <XDRMode mode>
     92  static XDRResult codeSource(XDRState<mode>* xdr,
     93                              const JS::ReadOnlyDecodeOptions* maybeOptions,
     94                              RefPtr<ScriptSource>& source);
     95 
     96  template <XDRMode mode>
     97  static XDRResult codeBigInt(XDRState<mode>* xdr, LifoAlloc& alloc,
     98                              BigIntStencil& stencil);
     99 
    100  template <XDRMode mode>
    101  static XDRResult codeObjLiteral(XDRState<mode>* xdr, LifoAlloc& alloc,
    102                                  ObjLiteralStencil& stencil);
    103 
    104  template <XDRMode mode>
    105  static XDRResult codeScopeData(XDRState<mode>* xdr, LifoAlloc& alloc,
    106                                 ScopeStencil& stencil,
    107                                 BaseParserScopeData*& baseScopeData);
    108 
    109  template <XDRMode mode>
    110  static XDRResult codeSharedData(XDRState<mode>* xdr,
    111                                  RefPtr<SharedImmutableScriptData>& sisd);
    112 
    113  template <XDRMode mode>
    114  static XDRResult codeSharedDataContainer(XDRState<mode>* xdr,
    115                                           SharedDataContainer& sharedData);
    116 
    117  template <XDRMode mode>
    118  static XDRResult codeParserAtom(XDRState<mode>* xdr, LifoAlloc& alloc,
    119                                  ParserAtom** atomp);
    120 
    121  template <XDRMode mode>
    122  static XDRResult codeParserAtomSpan(XDRState<mode>* xdr, LifoAlloc& alloc,
    123                                      ParserAtomSpan& parserAtomData);
    124 
    125  template <XDRMode mode>
    126  static XDRResult codeModuleRequest(XDRState<mode>* xdr,
    127                                     StencilModuleRequest& stencil);
    128 
    129  template <XDRMode mode>
    130  static XDRResult codeModuleRequestVector(
    131      XDRState<mode>* xdr, StencilModuleMetadata::RequestVector& vector);
    132 
    133  template <XDRMode mode>
    134  static XDRResult codeModuleEntry(XDRState<mode>* xdr,
    135                                   StencilModuleEntry& stencil);
    136 
    137  template <XDRMode mode>
    138  static XDRResult codeModuleEntryVector(
    139      XDRState<mode>* xdr, StencilModuleMetadata::EntryVector& vector);
    140 
    141  template <XDRMode mode>
    142  static XDRResult codeModuleMetadata(XDRState<mode>* xdr,
    143                                      StencilModuleMetadata& stencil);
    144 
    145  static XDRResult checkCompilationStencil(XDRStencilEncoder* encoder,
    146                                           const CompilationStencil& stencil);
    147 
    148  static XDRResult checkCompilationStencil(
    149      const ExtensibleCompilationStencil& stencil);
    150 
    151  template <XDRMode mode>
    152  static XDRResult codeCompilationStencil(XDRState<mode>* xdr,
    153                                          CompilationStencil& stencil);
    154 };
    155 
    156 } /* namespace frontend */
    157 
    158 /*
    159 * The structure of the Stencil XDR buffer is:
    160 *
    161 * 1. Version
    162 * 2. length of content
    163 * 3. checksum of content
    164 * 4. content
    165 *   a. ScriptSource
    166 *   b. CompilationStencil
    167 */
    168 
    169 /*
    170 * The stencil decoder accepts `range` as input.
    171 *
    172 * The decoded stencils are outputted to the default-initialized
    173 * `stencil` parameter of `codeStencil` method.
    174 *
    175 * The decoded stencils borrow the input `buffer`/`range`, and the consumer
    176 * has to keep the buffer alive while the decoded stencils are alive.
    177 */
    178 class XDRStencilDecoder : public XDRState<XDR_DECODE> {
    179  using Base = XDRState<XDR_DECODE>;
    180 
    181 public:
    182  XDRStencilDecoder(FrontendContext* fc, const JS::TranscodeRange& range)
    183      : Base(fc, range) {
    184    MOZ_ASSERT(JS::IsTranscodingBytecodeAligned(range.begin().get()));
    185  }
    186 
    187  XDRResult codeStencil(const JS::ReadOnlyDecodeOptions& options,
    188                        frontend::CompilationStencil& stencil);
    189 
    190  const JS::ReadOnlyDecodeOptions& options() {
    191    MOZ_ASSERT(options_);
    192    return *options_;
    193  }
    194 
    195 private:
    196  const JS::ReadOnlyDecodeOptions* options_ = nullptr;
    197 };
    198 
    199 class XDRStencilEncoder : public XDRState<XDR_ENCODE> {
    200  using Base = XDRState<XDR_ENCODE>;
    201 
    202 public:
    203  XDRStencilEncoder(FrontendContext* fc, JS::TranscodeBuffer& buffer)
    204      : Base(fc, buffer, buffer.length()) {
    205    // NOTE: If buffer is empty, buffer.begin() doesn't point valid buffer.
    206    MOZ_ASSERT_IF(!buffer.empty(),
    207                  JS::IsTranscodingBytecodeAligned(buffer.begin()));
    208    MOZ_ASSERT(JS::IsTranscodingBytecodeOffsetAligned(buffer.length()));
    209  }
    210 
    211  XDRResult codeStencil(const RefPtr<ScriptSource>& source,
    212                        const frontend::CompilationStencil& stencil);
    213 
    214  XDRResult codeStencil(const frontend::CompilationStencil& stencil);
    215 };
    216 
    217 JS::TranscodeResult EncodeStencil(JSContext* cx,
    218                                  frontend::CompilationStencil* stencil,
    219                                  JS::TranscodeBuffer& buffer);
    220 
    221 JS::TranscodeResult EncodeStencil(JS::FrontendContext* fc,
    222                                  frontend::CompilationStencil* stencil,
    223                                  JS::TranscodeBuffer& buffer);
    224 
    225 JS::TranscodeResult DecodeStencil(JS::FrontendContext* fc,
    226                                  const JS::ReadOnlyDecodeOptions& options,
    227                                  const JS::TranscodeRange& range,
    228                                  frontend::CompilationStencil** stencilOut);
    229 
    230 } /* namespace js */
    231 
    232 #endif /* frontend_StencilXdr_h */