DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Mercurial (7b5b4eed4707)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 * vim: set ts=8 sts=2 et sw=2 tw=80:
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef frontend_BytecodeCompilation_h
#define frontend_BytecodeCompilation_h

#include "mozilla/Assertions.h"  // MOZ_ASSERT
#include "mozilla/Attributes.h"  // MOZ_MUST_USE, MOZ_STACK_CLASS
#include "mozilla/Maybe.h"       // mozilla::Maybe, mozilla::Nothing
#include "mozilla/Utf8.h"        // mozilla::Utf8Unit

#include <stddef.h>  // size_t
#include <stdint.h>  // uint32_t

#include "frontend/ParseContext.h"  // js::frontend::UsedNameTracker
#include "frontend/SharedContext.h"  // js::frontend::Directives, js::frontend::{,Eval,Global}SharedContext
#include "js/CompileOptions.h"  // JS::ReadOnlyCompileOptions
#include "js/RootingAPI.h"      // JS::{,Mutable}Handle, JS::Rooted
#include "js/SourceText.h"      // JS::SourceText
#include "vm/JSContext.h"       // js::AutoKeepAtoms
#include "vm/JSScript.h"  // js::{FunctionAsync,Generator}Kind, js::LazyScript, JSScript, js::ScriptSource, js::ScriptSourceObject
#include "vm/Scope.h"     // js::ScopeKind

class JSFunction;
class JSObject;

namespace js {

namespace frontend {

class EitherParser;

template <typename Unit>
class SourceAwareCompiler;
template <typename Unit>
class ScriptCompiler;
template <typename Unit>
class ModuleCompiler;
template <typename Unit>
class StandaloneFunctionCompiler;

// The BytecodeCompiler class contains resources common to compiling scripts and
// function bodies.
class MOZ_STACK_CLASS BytecodeCompiler {
 protected:
  AutoKeepAtoms keepAtoms;

  JSContext* cx;
  const JS::ReadOnlyCompileOptions& options;

  JS::Rooted<ScriptSourceObject*> sourceObject;
  ScriptSource* scriptSource = nullptr;

  mozilla::Maybe<UsedNameTracker> usedNames;

  Directives directives;

  JS::Rooted<JSScript*> script;

 protected:
  BytecodeCompiler(JSContext* cx, const JS::ReadOnlyCompileOptions& options);

  template <typename Unit>
  friend class SourceAwareCompiler;
  template <typename Unit>
  friend class ScriptCompiler;
  template <typename Unit>
  friend class ModuleCompiler;
  template <typename Unit>
  friend class StandaloneFunctionCompiler;

 public:
  JSContext* context() const { return cx; }

  ScriptSourceObject* sourceObjectPtr() const { return sourceObject.get(); }

 protected:
  void assertSourceCreated() const {
    MOZ_ASSERT(sourceObject != nullptr);
    MOZ_ASSERT(scriptSource != nullptr);
  }

  MOZ_MUST_USE bool createScriptSource(
      const mozilla::Maybe<uint32_t>& parameterListEnd);

  void createUsedNames() { usedNames.emplace(cx); }

  // Create a script for source of the given length, using the explicitly-
  // provided toString offsets as the created script's offsets in the source.
  MOZ_MUST_USE bool internalCreateScript(uint32_t toStringStart,
                                         uint32_t toStringEnd,
                                         uint32_t sourceBufferLength);

  MOZ_MUST_USE bool emplaceEmitter(mozilla::Maybe<BytecodeEmitter>& emitter,
                                   const EitherParser& parser,
                                   SharedContext* sharedContext);

  // This function lives here, not in SourceAwareCompiler, because it mostly
  // uses fields in *this* class.
  template <typename Unit>
  MOZ_MUST_USE bool assignSource(JS::SourceText<Unit>& sourceBuffer) {
    return scriptSource->assignSource(cx, options, sourceBuffer);
  }

  bool canLazilyParse() const;
};

class MOZ_STACK_CLASS GlobalScriptInfo final : public BytecodeCompiler {
  GlobalSharedContext globalsc_;

 public:
  GlobalScriptInfo(JSContext* cx, const JS::ReadOnlyCompileOptions& options,
                   ScopeKind scopeKind)
      : BytecodeCompiler(cx, options),
        globalsc_(cx, scopeKind, directives, options.extraWarningsOption) {
    MOZ_ASSERT(scopeKind == ScopeKind::Global ||
               scopeKind == ScopeKind::NonSyntactic);
  }

  GlobalSharedContext* sharedContext() { return &globalsc_; }
};

extern JSScript* CompileGlobalScript(
    GlobalScriptInfo& info, JS::SourceText<char16_t>& srcBuf,
    ScriptSourceObject** sourceObjectOut = nullptr);

extern JSScript* CompileGlobalScript(
    GlobalScriptInfo& info, JS::SourceText<mozilla::Utf8Unit>& srcBuf,
    ScriptSourceObject** sourceObjectOut = nullptr);

class MOZ_STACK_CLASS EvalScriptInfo final : public BytecodeCompiler {
  JS::Handle<JSObject*> environment_;
  EvalSharedContext evalsc_;

 public:
  EvalScriptInfo(JSContext* cx, const JS::ReadOnlyCompileOptions& options,
                 JS::Handle<JSObject*> environment,
                 JS::Handle<Scope*> enclosingScope)
      : BytecodeCompiler(cx, options),
        environment_(environment),
        evalsc_(cx, environment_, enclosingScope, directives,
                options.extraWarningsOption) {}

  HandleObject environment() { return environment_; }

  EvalSharedContext* sharedContext() { return &evalsc_; }
};

extern JSScript* CompileEvalScript(EvalScriptInfo& info,
                                   JS::SourceText<char16_t>& srcBuf);

class MOZ_STACK_CLASS ModuleInfo final : public BytecodeCompiler {
 public:
  ModuleInfo(JSContext* cx, const JS::ReadOnlyCompileOptions& options)
      : BytecodeCompiler(cx, options) {}
};

class MOZ_STACK_CLASS StandaloneFunctionInfo final : public BytecodeCompiler {
 public:
  StandaloneFunctionInfo(JSContext* cx,
                         const JS::ReadOnlyCompileOptions& options)
      : BytecodeCompiler(cx, options) {}
};

extern MOZ_MUST_USE bool CompileLazyFunction(JSContext* cx,
                                             JS::Handle<LazyScript*> lazy,
                                             const char16_t* units,
                                             size_t length);

extern MOZ_MUST_USE bool CompileLazyFunction(JSContext* cx,
                                             JS::Handle<LazyScript*> lazy,
                                             const mozilla::Utf8Unit* units,
                                             size_t length);

}  // namespace frontend

}  // namespace js

#endif  // frontend_BytecodeCompilation_h