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/. */
7 #ifndef vm_SelfHosting_h_
8 #define vm_SelfHosting_h_
10 #include "NamespaceImports.h"
12 #include "js/CallNonGenericMethod.h"
13 #include "js/RootingAPI.h"
14 #include "js/TypeDecls.h"
16 // [SMDOC] Self-hosted JS
18 // Self-hosted JS allows implementing a part of the JS engine using JavaScript.
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.
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.
28 // Self-hosted JS has several differences between regular JavaScript code,
29 // for performance optimization, security, and some other reasons.
31 // # Always strict mode
33 // Unlike regular JavaScript, self-hosted JS code is always in strict mode.
35 // # Prohibited syntax
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
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`.
50 // # Extended function
52 // Functions with "$"-prefix in their name are allocated as extended function.
53 // See "SetCanonicalName" below.
55 // # Intrinsic helper functions
57 // Self-hosted JS has access to special functions that can interact with
58 // native code or internal representation of JS values and objects.
60 // See `intrinsic_functions` array in SelfHosting.cpp.
64 // Stack frame inside self-hosted JS is hidden from Error.prototype.stack by
65 // default, to hide the internal from user code.
67 // During debugging self-hosted JS code, `MOZ_SHOW_ALL_JS_FRAMES` environment
68 // variable can be used to expose those frames
70 // # Debugger interaction
72 // Self-hosted JS is hidden from debugger, and no source notes or breakpoint
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`
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.
90 // See `JSRuntime::initSelfHostingStencil` function.
92 // # Special functions
94 // Self-hosted JS code has special functions, to emit special bytecode
95 // sequence, or directly operate on internals:
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.
102 // `obj.method(...)` syntax is forbidden in self-hosted JS, to avoid
103 // accidentally exposing the internal, or allowing user code to modify the
106 // If the `callee` can be user-provided, `callContentFunction` must be
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`.
113 // This exposes function calls to debuggers, using `JSOp::CallContent`
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.
120 // This exposes constructs to debuggers, using `JSOp::NewContent` opcode.
122 // allowContentIter(iterable)
123 // Iteration such as for-of and spread on user-provided value is
124 // prohibited inside self-hosted JS by default.
126 // `allowContentIter` marks iteration allowed for given possibly
127 // user-provided iterable.
129 // This exposes implicit function calls around iteration to debuggers,
130 // using `JSOp::CallContentIter` opcode.
132 // Used in the following contexts:
134 // for (var item of allowContentIter(iterable)) { ... }
135 // [...allowContentIter(iterable)]
137 // allowContentIterWith(iterable, iteratorFunc)
138 // Special form of `allowContentIter`, where `iterable[Symbol.iterator]` is
139 // already retrieved.
141 // This directly uses `iteratorFunc` instead of accessing
142 // `iterable[Symbol.iterator]` again inside for-of bytecode.
144 // for (var item of allowContentIterWith(iterable, iteratorFunc)) { ... }
146 // allowContentIterWith(iterator, nextFunc)
147 // Special form of `allowContentIter`, where `iterable[Symbol.iterator]()`
148 // is already called and the iterator's `next` property retrieved.
150 // This form doesn't call `iterable[Symbol.iterator]` and directly uses
151 // `nextFunc` instead of retrieving it inside for-of bytecode.
153 // for (var item of allowContentIterWithNext(iterator, nextFunc)) { ... }
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.
162 // Return `true` if `obj` has an own `key` property, using `JSOp::HasOwn`
165 // getPropertySuper(obj, key, receiver)
166 // Return `obj.[[Get]](key, receiver)`, using `JSOp::GetElemSuper` opcode.
169 // Convert `v` to number, using `JSOp::ToNumeric` opcode
172 // Convert `v` to string, `JSOp::ToString` opcode
174 // GetBuiltinConstructor(name)
175 // Return built-in constructor for `name`, e.g. `"Array"`, using
176 // `JSOp::BuiltinObject` opcode.
178 // GetBuiltinPrototype(name)
179 // Return built-in prototype for `name`, e.g. `"RegExp"`, using
180 // `JSOp::BuiltinObject` opcode.
182 // GetBuiltinSymbol(name)
183 // Return built-in symbol `Symbol[name]`, using `JSOp::Symbol` opcode.
185 // SetIsInlinableLargeFunction(fun)
186 // Mark the large function `fun` inlineable.
187 // `fun` must be the last function declaration before this call.
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.
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
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
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.
213 // forceInterpreter()
214 // Force interpreter execution for this function, using
215 // `JSOp::ForceInterpreter` opcode.
216 // This must be the first statement inside the function.
219 class JS_PUBLIC_API CompileOptions
;
226 class ScriptSourceObject
;
228 ScriptSourceObject
* SelfHostingScriptSourceObject(JSContext
* cx
);
231 * Check whether the given JSFunction or Value is a self-hosted function whose
232 * self-hosted name is the given name.
234 bool IsSelfHostedFunctionWithName(JSFunction
* fun
, JSAtom
* name
);
235 bool IsSelfHostedFunctionWithName(const Value
& v
, JSAtom
* name
);
238 * Returns the name of the cloned function's binding in the self-hosted global.
240 * This returns a non-null value only when this is a top level function
241 * declaration in the self-hosted global.
243 PropertyName
* GetClonedSelfHostedFunctionName(const JSFunction
* fun
);
244 void SetClonedSelfHostedFunctionName(JSFunction
* fun
, PropertyName
* name
);
246 constexpr char ExtendedUnclonedSelfHostedFunctionNamePrefix
= '$';
249 * Uncloned self-hosted functions with `$` prefix are allocated as
250 * extended function, to store the original name in `_SetCanonicalName`.
252 bool IsExtendedUnclonedSelfHostedFunctionName(JSAtom
* name
);
254 void SetUnclonedSelfHostedCanonicalName(JSFunction
* fun
, JSAtom
* name
);
256 bool IsCallSelfHostedNonGenericMethod(NativeImpl impl
);
258 bool ReportIncompatibleSelfHostedMethod(JSContext
* cx
, Handle
<Value
> thisValue
);
260 /* Get the compile options used when compiling self hosted code. */
261 void FillSelfHostingCompileOptions(JS::CompileOptions
& options
);
263 const JSFunctionSpec
* FindIntrinsicSpec(PropertyName
* name
);
267 * Calls a self-hosted function by name.
269 * This function is only available in debug mode, because it always atomizes
270 * its |name| parameter. Use the alternative function below in non-debug code.
272 bool CallSelfHostedFunction(JSContext
* cx
, char const* name
, HandleValue thisv
,
273 const AnyInvokeArgs
& args
, MutableHandleValue rval
);
277 * Calls a self-hosted function by name.
279 bool CallSelfHostedFunction(JSContext
* cx
, Handle
<PropertyName
*> name
,
280 HandleValue thisv
, const AnyInvokeArgs
& args
,
281 MutableHandleValue rval
);
283 bool intrinsic_NewArrayIterator(JSContext
* cx
, unsigned argc
, JS::Value
* vp
);
285 bool intrinsic_NewStringIterator(JSContext
* cx
, unsigned argc
, JS::Value
* vp
);
287 bool intrinsic_NewRegExpStringIterator(JSContext
* cx
, unsigned argc
,
290 #ifdef ENABLE_RECORD_TUPLE
291 bool IsTupleUnchecked(JSContext
* cx
, const CallArgs
& args
);
292 bool intrinsic_IsTuple(JSContext
* cx
, unsigned argc
, JS::Value
* vp
);
297 #endif /* vm_SelfHosting_h_ */