tor-browser

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

SelfHosting.h (10964B)


      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 vm_SelfHosting_h_
      8 #define vm_SelfHosting_h_
      9 
     10 #include "NamespaceImports.h"
     11 
     12 #include "js/CallNonGenericMethod.h"
     13 #include "js/RootingAPI.h"
     14 #include "js/TypeDecls.h"
     15 
     16 // [SMDOC] Self-hosted JS
     17 //
     18 // Self-hosted JS allows implementing a part of the JS engine using JavaScript.
     19 //
     20 // This allows implementing new feature easily, and also enables JIT
     21 // compilation to achieve better performance, for example with higher order
     22 // functions. Self-hosted functions can be inlined in, and optimized with, the
     23 // JS caller functions.
     24 //
     25 // Self-hosted JS code is compiled into a stencil during the initialization of
     26 // the engine, and each function is instantiated into each global on demand.
     27 //
     28 // Self-hosted JS has several differences between regular JavaScript code,
     29 // for performance optimization, security, and some other reasons.
     30 //
     31 // # Always strict mode
     32 //
     33 // Unlike regular JavaScript, self-hosted JS code is always in strict mode.
     34 //
     35 // # Prohibited syntax
     36 //
     37 //   * Regular expression `/foo/` cannot be used
     38 //   * `obj.method(...)` and `obj[method](...)` style call cannot be used.
     39 //      See `callFunction` below
     40 //   * Object literal cannot contain duplicate property names
     41 //   * `yield*` cannot be used
     42 //
     43 // # No lazy parsing
     44 //
     45 // Self-hosted JS does not use lazy/syntax parsing: bytecode is generated
     46 // eagerly for each function. However, we do instantiate the BaseScript lazily
     47 // from the stencil for JSFunctions created for self-hosted built-ins. See
     48 // `SelfHostedLazyScript` and `JSRuntime::selfHostedLazyScript`.
     49 //
     50 // # Extended function
     51 //
     52 // Functions with "$"-prefix in their name are allocated as extended function.
     53 // See "SetCanonicalName" below.
     54 //
     55 // # Intrinsic helper functions
     56 //
     57 // Self-hosted JS has access to special functions that can interact with
     58 // native code or internal representation of JS values and objects.
     59 //
     60 // See `intrinsic_functions` array in SelfHosting.cpp.
     61 //
     62 // # Stack Frame
     63 //
     64 // Stack frame inside self-hosted JS is hidden from Error.prototype.stack by
     65 // default, to hide the internal from user code.
     66 //
     67 // During debugging self-hosted JS code, `MOZ_SHOW_ALL_JS_FRAMES` environment
     68 // variable can be used to expose those frames
     69 //
     70 // # Debugger interaction
     71 //
     72 // Self-hosted JS is hidden from debugger, and no source notes or breakpoint
     73 // is generated.
     74 //
     75 // Most function calls inside self-hosted JS are hidden from Debugger's
     76 // `onNativeCall` hook, except for the following (see below for each):
     77 //   * `callContentFunction`
     78 //   * `constructContentFunction`
     79 //   * `allowContentIter`
     80 //   * `allowContentIterWith`
     81 //   * `allowContentIterWithNext`
     82 //
     83 // # XDR cache
     84 //
     85 // Compiling self-hosted JS code takes some time.
     86 // To improve the startup performance, the bytecode for self-hosted JS code
     87 // can be saved as XDR, and used by other instance. This is used to speed up
     88 // JS shell tests and Firefox content process startup.
     89 //
     90 // See `JSRuntime::initSelfHostingStencil` function.
     91 //
     92 // # Special functions
     93 //
     94 // Self-hosted JS code has special functions, to emit special bytecode
     95 // sequence, or directly operate on internals:
     96 //
     97 //   callFunction(callee, thisV, arg0, ...)
     98 //     Call `callee` function with `thisV` as "this" value, passing
     99 //     arg0, ..., as arguments.
    100 //     This is used when "this" value is not `undefined.
    101 //
    102 //     `obj.method(...)` syntax is forbidden in self-hosted JS, to avoid
    103 //     accidentally exposing the internal, or allowing user code to modify the
    104 //     behavior.
    105 //
    106 //     If the `callee` can be user-provided, `callContentFunction` must be
    107 //     used instead.
    108 //
    109 //   callContentFunction(callee, thisV, arg0, ...)
    110 //     Same as `callFunction`, but this must be used when calling possibly
    111 //     user-provided functions, even if "this" value is `undefined`.
    112 //
    113 //     This exposes function calls to debuggers, using `JSOp::CallContent`
    114 //     opcode.
    115 //
    116 //   constructContentFunction(callee, newTarget, arg0, ...)
    117 //     Construct `callee` function using `newTarget` as `new.target`.
    118 //     This must be used when constructing possibly user-provided functions.
    119 //
    120 //     This exposes constructs to debuggers, using `JSOp::NewContent` opcode.
    121 //
    122 //   allowContentIter(iterable)
    123 //     Iteration such as for-of and spread on user-provided value is
    124 //     prohibited inside self-hosted JS by default.
    125 //
    126 //     `allowContentIter` marks iteration allowed for given possibly
    127 //     user-provided iterable.
    128 //
    129 //     This exposes implicit function calls around iteration to debuggers,
    130 //     using `JSOp::CallContentIter` opcode.
    131 //
    132 //     Used in the following contexts:
    133 //
    134 //       for (var item of allowContentIter(iterable)) { ... }
    135 //       [...allowContentIter(iterable)]
    136 //
    137 //   allowContentIterWith(iterable, iteratorFunc)
    138 //     Special form of `allowContentIter`, where `iterable[Symbol.iterator]` is
    139 //     already retrieved.
    140 //
    141 //     This directly uses `iteratorFunc` instead of accessing
    142 //     `iterable[Symbol.iterator]` again inside for-of bytecode.
    143 //
    144 //     for (var item of allowContentIterWith(iterable, iteratorFunc)) { ... }
    145 //
    146 //   allowContentIterWith(iterator, nextFunc)
    147 //     Special form of `allowContentIter`, where `iterable[Symbol.iterator]()`
    148 //     is already called and the iterator's `next` property retrieved.
    149 //
    150 //     This form doesn't call `iterable[Symbol.iterator]` and directly uses
    151 //     `nextFunc` instead of retrieving it inside for-of bytecode.
    152 //
    153 //     for (var item of allowContentIterWithNext(iterator, nextFunc)) { ... }
    154 //
    155 //   DefineDataProperty(obj, key, value)
    156 //     Initialize `obj`'s `key` property with `value`, like
    157 //    `Object.defineProperty(obj, key, {value})`, using `JSOp::InitElem`
    158 //     opcode. This is almost always better than `obj[key] = value` because it
    159 //     ignores setters and other properties on the prototype chain.
    160 //
    161 //   hasOwn(key, obj)
    162 //     Return `true` if `obj` has an own `key` property, using `JSOp::HasOwn`
    163 //     opcode.
    164 //
    165 //   getPropertySuper(obj, key, receiver)
    166 //     Return `obj.[[Get]](key, receiver)`, using `JSOp::GetElemSuper` opcode.
    167 //
    168 //   ToNumeric(v)
    169 //     Convert `v` to number, using `JSOp::ToNumeric` opcode
    170 //
    171 //   ToString(v)
    172 //     Convert `v` to string, `JSOp::ToString` opcode
    173 //
    174 //   GetBuiltinConstructor(name)
    175 //     Return built-in constructor for `name`, e.g. `"Array"`, using
    176 //     `JSOp::BuiltinObject` opcode.
    177 //
    178 //   GetBuiltinPrototype(name)
    179 //     Return built-in prototype for `name`, e.g. `"RegExp"`, using
    180 //     `JSOp::BuiltinObject` opcode.
    181 //
    182 //   GetBuiltinSymbol(name)
    183 //     Return built-in symbol `Symbol[name]`, using `JSOp::Symbol` opcode.
    184 //
    185 //   SetIsInlinableLargeFunction(fun)
    186 //     Mark the large function `fun` inlineable.
    187 //     `fun` must be the last function declaration before this call.
    188 //
    189 //   SetCanonicalName(fun)
    190 //     Set canonical name for the function `fun`.
    191 //     `fun` must be the last function declaration before this call, and also
    192 //     its function name must be prefixed with "$", to make it extended
    193 //     function and store the original function name in the extended slot.
    194 //
    195 //   UnsafeGetReservedSlot(obj, slot)
    196 //   UnsafeGetObjectFromReservedSlot(obj, slot)
    197 //   UnsafeGetInt32FromReservedSlot(obj, slot)
    198 //   UnsafeGetStringFromReservedSlot(obj, slot)
    199 //   UnsafeGetBooleanFromReservedSlot(obj, slot)
    200 //     Get `obj`'s reserved slot specified by integer value `slot`.
    201 //     They are intrinsic helper functions, and also optimized during JIT
    202 //     compilation.
    203 //
    204 //   UnsafeSetReservedSlot(obj, slot, value)
    205 //     Set `obj`'s reserved slot specified by integer value `slot` to `value`.
    206 //     This is an intrinsic helper function, and also optimized during JIT
    207 //     compilation.
    208 //
    209 //   resumeGenerator(gen, value, kind)
    210 //     Resume generator `gen`, using `kind`, which is one of "next", "throw",
    211 //     or "return", pasing `value` as parameter, using `JSOp::Resume` opcode.
    212 //
    213 //   forceInterpreter()
    214 //     Force interpreter execution for this function, using
    215 //     `JSOp::ForceInterpreter` opcode.
    216 //     This must be the first statement inside the function.
    217 
    218 namespace JS {
    219 class JS_PUBLIC_API CompileOptions;
    220 }
    221 
    222 namespace js {
    223 
    224 class AnyInvokeArgs;
    225 class PropertyName;
    226 class ScriptSourceObject;
    227 
    228 ScriptSourceObject* SelfHostingScriptSourceObject(JSContext* cx);
    229 
    230 /*
    231 * Check whether the given JSFunction or Value is a self-hosted function whose
    232 * self-hosted name is the given name.
    233 */
    234 bool IsSelfHostedFunctionWithName(JSFunction* fun, JSAtom* name);
    235 bool IsSelfHostedFunctionWithName(const Value& v, JSAtom* name);
    236 
    237 /*
    238 * Returns the name of the cloned function's binding in the self-hosted global.
    239 *
    240 * This returns a non-null value only when this is a top level function
    241 * declaration in the self-hosted global.
    242 */
    243 PropertyName* GetClonedSelfHostedFunctionName(const JSFunction* fun);
    244 void SetClonedSelfHostedFunctionName(JSFunction* fun, PropertyName* name);
    245 
    246 constexpr char ExtendedUnclonedSelfHostedFunctionNamePrefix = '$';
    247 
    248 /*
    249 * Uncloned self-hosted functions with `$` prefix are allocated as
    250 * extended function, to store the original name in `_SetCanonicalName`.
    251 */
    252 bool IsExtendedUnclonedSelfHostedFunctionName(JSAtom* name);
    253 
    254 void SetUnclonedSelfHostedCanonicalName(JSFunction* fun, JSAtom* name);
    255 
    256 bool IsCallSelfHostedNonGenericMethod(NativeImpl impl);
    257 
    258 enum class IncompatibleContext { Regular, RegExpExec };
    259 
    260 bool ReportIncompatibleSelfHostedMethod(
    261    JSContext* cx, Handle<Value> thisValue,
    262    IncompatibleContext incompatibleContext);
    263 
    264 /* Get the compile options used when compiling self hosted code. */
    265 void FillSelfHostingCompileOptions(JS::CompileOptions& options);
    266 
    267 const JSFunctionSpec* FindIntrinsicSpec(PropertyName* name);
    268 
    269 #ifdef DEBUG
    270 /*
    271 * Calls a self-hosted function by name.
    272 *
    273 * This function is only available in debug mode, because it always atomizes
    274 * its |name| parameter. Use the alternative function below in non-debug code.
    275 */
    276 bool CallSelfHostedFunction(JSContext* cx, char const* name, HandleValue thisv,
    277                            const AnyInvokeArgs& args, MutableHandleValue rval);
    278 #endif
    279 
    280 /*
    281 * Calls a self-hosted function by name.
    282 */
    283 bool CallSelfHostedFunction(JSContext* cx, Handle<PropertyName*> name,
    284                            HandleValue thisv, const AnyInvokeArgs& args,
    285                            MutableHandleValue rval);
    286 
    287 bool intrinsic_NewArrayIterator(JSContext* cx, unsigned argc, JS::Value* vp);
    288 
    289 bool intrinsic_NewStringIterator(JSContext* cx, unsigned argc, JS::Value* vp);
    290 
    291 bool intrinsic_NewRegExpStringIterator(JSContext* cx, unsigned argc,
    292                                       JS::Value* vp);
    293 } /* namespace js */
    294 
    295 #endif /* vm_SelfHosting_h_ */