Skip to content

Commit f250180

Browse files
Huxprofacebook-github-bot
authored andcommitted
Extend Builtins with JSFunction and register
Summary: This diff extend the builtins with JSFunction. In summary, 1. `builtins_` in `Runtime` need to be generalized to a vector of `Callable *` so it can potentially take a `JSFunction`. 2. Defined JSBuiltin the same way as the other 2. 3. Have a `initJSBuiltins` to register JSFunctions returned from internal bytecode. `spawnAsync` is the first of them. 4. Made clear in the `Builtins.def` comments the 3 different types of builtins: (Public Native) Builtins, Private (Native) Builtins, and the newly added (Private) JS Builtins. Updated some of the occurences of such names to reduce confusion. We'll use the functionality of JSBuiltin in later diffs. Reviewed By: tmikov Differential Revision: D23801672 fbshipit-source-id: e0b827c43f3fbacd75f81bf353c949f595e7d548
1 parent c623db7 commit f250180

11 files changed

Lines changed: 176 additions & 75 deletions

File tree

include/hermes/FrontEndDefs/Builtins.def

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,31 @@
77

88
///===----------------------------------------------------------------------===
99
/// \file
10-
/// Define global objects and methods which the compiler can assume have not
11-
/// been overwritten and can be treated as builtins.
10+
/// Define Hermes builtin functions.
11+
///
12+
/// All builtin functions in Hermes are registered in a vector of `Callable *`
13+
/// in the runtime with an index as its builtin method id.
14+
///
15+
/// There are 3 kinds of builtins in Hermes:
16+
/// 1. (Public Native) Builtins: those are global objects and methods of JSLib
17+
/// implemented natively which the compiler can assume have not been
18+
/// overwritten and can be treated as builtins under the "static builtin"
19+
/// optimizations (`-fstatic-builtins` flag).
20+
///
21+
/// 2. Private (Native) Builtins: those are native functions meant to be only
22+
/// called internally by the compiler to help with implementing JS features
23+
/// without introducing extra opcodes. They are notationally written as
24+
/// `HermesBuiltin_name`.
25+
///
26+
/// 3. (Private) JS Builtins: those are JS functions returned from the result of
27+
/// executing internal bytecode. They are also there to help with implementing
28+
/// JS features.
29+
///
30+
/// At this moment,
31+
/// Native builtins are invoked via `CallBuiltin` instruction.
32+
/// JS builtins are invoked via `GetBuiltinClosure` followed by a `Call`.
33+
///
34+
/// We might separate them in the future.
1235
///
1336
/// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1437
/// IMPORTANT: DO NOT FORGET TO INCREASE THE BYTECODE FILE FORMAT VERSION IF
@@ -28,6 +51,12 @@
2851
#ifndef MARK_FIRST_PRIVATE_BUILTIN
2952
#define MARK_FIRST_PRIVATE_BUILTIN(name)
3053
#endif
54+
#ifndef JS_BUILTIN
55+
#define JS_BUILTIN(name)
56+
#endif
57+
#ifndef MARK_FIRST_JS_BUILTIN
58+
#define MARK_FIRST_JS_BUILTIN(name)
59+
#endif
3160

3261
BUILTIN_OBJECT(Array)
3362
// BUILTIN_METHOD(Array, from)
@@ -109,7 +138,12 @@ PRIVATE_BUILTIN(apply)
109138
PRIVATE_BUILTIN(exportAll)
110139
PRIVATE_BUILTIN(exponentiationOperator)
111140

141+
JS_BUILTIN(spawnAsync)
142+
MARK_FIRST_JS_BUILTIN(spawnAsync)
143+
112144
#undef BUILTIN_OBJECT
113145
#undef BUILTIN_METHOD
114146
#undef PRIVATE_BUILTIN
115147
#undef MARK_FIRST_PRIVATE_BUILTIN
148+
#undef JS_BUILTIN
149+
#undef MARK_FIRST_JS_BUILTIN

include/hermes/FrontEndDefs/Builtins.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,22 @@
88
#ifndef HERMES_INST_BUILTINS_H
99
#define HERMES_INST_BUILTINS_H
1010

11+
#include <cassert>
12+
1113
namespace hermes {
1214

1315
namespace BuiltinMethod {
1416
enum Enum : unsigned char {
1517
#define BUILTIN_METHOD(object, name) object##_##name,
1618
#define PRIVATE_BUILTIN(name) BUILTIN_METHOD(HermesBuiltin, name)
1719
#define MARK_FIRST_PRIVATE_BUILTIN(name) _firstPrivate = PRIVATE_BUILTIN(name)
20+
#define JS_BUILTIN(name) PRIVATE_BUILTIN(name)
21+
#define MARK_FIRST_JS_BUILTIN(name) _firstJS = JS_BUILTIN(name)
1822
#include "Builtins.def"
1923
_count,
2024
_publicCount = _firstPrivate,
21-
_privateCount = _count - _firstPrivate,
25+
_privateCount = _firstJS - _firstPrivate,
26+
_jsCount = _count - _firstJS,
2227
};
2328

2429
} // namespace BuiltinMethod
@@ -28,6 +33,15 @@ static_assert(BuiltinMethod::_count <= 256, "More than 256 builtin methods");
2833
/// Return a string representation of the builtin method name.
2934
const char *getBuiltinMethodName(int method);
3035

36+
/// Return whether a builtin method is a Native builtin.
37+
/// Otherwise, it is a JS builtin (as of the only two cases today).
38+
/// This is more efficient than consulting the GCKind. It only need to perform
39+
/// a simple comparison between the method index and the JS section offset.
40+
inline bool isNativeBuiltin(unsigned method) {
41+
assert(method < BuiltinMethod::_count && "out of bound BuiltinMethod index");
42+
return method < BuiltinMethod::_firstJS;
43+
};
44+
3145
} // namespace hermes
3246

3347
#endif // HERMES_BCGEN_HBC_BUILTINS_H

include/hermes/VM/Callable.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ struct CallableVTable {
133133

134134
/// The abstract base for callable entities, specifically NativeFunction and
135135
/// Function. It presents the ability to call a function with arguments already
136-
/// on the stack. Subclasses implement this for native funcitions and
136+
/// on the stack. Subclasses implement this for native functions and
137137
/// interpreted functions.
138138
class Callable : public JSObject {
139139
using Super = JSObject;

include/hermes/VM/JSLib.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ void initGlobalObject(Runtime *runtime, const JSLibFlags &jsLibFlags);
4242
/// \c BuiltinMethod::xxx index.
4343
void createHermesBuiltins(
4444
Runtime *runtime,
45-
llvh::MutableArrayRef<NativeFunction *> builtins);
45+
llvh::MutableArrayRef<Callable *> builtins);
4646

4747
std::shared_ptr<RuntimeCommonStorage> createRuntimeCommonStorage(
4848
bool shouldTrace);

include/hermes/VM/PredefinedStrings.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,7 @@ STR(virtualOffset, "virtualOffset")
430430
STR(fileName, "fileName")
431431
STR(setPromiseRejectionTrackingHook, "setPromiseRejectionTrackingHook")
432432
STR(enablePromiseRejectionTracker, "enablePromiseRejectionTracker")
433+
STR(spawnAsync, "spawnAsync") /* NOLINT */
433434

434435
STR(require, "require")
435436
STR(requireFast, "requireFast")

include/hermes/VM/Runtime-inline.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@
1414
namespace hermes {
1515
namespace vm {
1616

17-
inline NativeFunction *Runtime::getBuiltinNativeFunction(
18-
unsigned builtinMethodID) {
19-
assert(builtinMethodID < BuiltinMethod::_count && "invalid builtinMethodID");
17+
inline Callable *Runtime::getBuiltinCallable(unsigned builtinMethodID) {
18+
assert(
19+
builtinMethodID < BuiltinMethod::_count &&
20+
"out of bound builtinMethodID");
2021
return builtins_[builtinMethodID];
2122
}
2223

include/hermes/VM/Runtime.h

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -314,10 +314,10 @@ class Runtime : public HandleRootOwner,
314314

315315
/// @}
316316

317-
/// Return a pointer to a builtin native function builtin identified by id.
317+
/// Return a pointer to a callable builtin identified by id.
318318
/// Unfortunately we can't use the enum here, since we don't want to include
319319
/// the builtins header header.
320-
inline NativeFunction *getBuiltinNativeFunction(unsigned builtinMethodID);
320+
inline Callable *getBuiltinCallable(unsigned builtinMethodID);
321321

322322
IdentifierTable &getIdentifierTable() {
323323
return identifierTable_;
@@ -937,19 +937,27 @@ class Runtime : public HandleRootOwner,
937937
/// \param object is the object where the builtin method is defined as a
938938
/// property.
939939
/// \param methodID is the SymbolID for the name of the method.
940-
using ForEachBuiltinCallback = ExecutionStatus(
940+
using ForEachPublicNativeBuiltinCallback = ExecutionStatus(
941941
unsigned methodIndex,
942942
Predefined::Str objectName,
943943
Handle<JSObject> &object,
944944
SymbolID methodID);
945945

946-
/// Enumerate the builtin methods, and invoke the callback on each method.
947-
ExecutionStatus forEachBuiltin(
948-
const std::function<ForEachBuiltinCallback> &callback);
946+
/// Enumerate all public native builtin methods, and invoke the callback on
947+
/// each method.
948+
ExecutionStatus forEachPublicNativeBuiltin(
949+
const std::function<ForEachPublicNativeBuiltinCallback> &callback);
949950

950-
/// Populate the builtins table by extracting the values from the global
951-
/// object.
952-
void initBuiltinTable();
951+
/// Populate native builtins into the builtins table.
952+
/// Public native builtins are added by extracting the values from the global
953+
/// object. Private native builtins are added by \c createHermesBuiltins().
954+
void initNativeBuiltins();
955+
956+
/// Populate JS builtins into the builtins table, after verifying they do
957+
/// exist from the result of running internal bytecode.
958+
void initJSBuiltins(
959+
llvh::MutableArrayRef<Callable *> builtins,
960+
Handle<JSObject> jsBuiltins);
953961

954962
/// Walk all the builtin methods, assert that they are not overridden. If they
955963
/// are, throw an exception. This will be called at most once, before freezing
@@ -1151,8 +1159,8 @@ class Runtime : public HandleRootOwner,
11511159
/// to be scanned as roots in young-gen collections.
11521160
std::vector<PinnedHermesValue> charStrings_{};
11531161

1154-
/// Pointers to native implementations of builtins.
1155-
std::vector<NativeFunction *> builtins_{};
1162+
/// Pointers to callable implementations of builtins.
1163+
std::vector<Callable *> builtins_{};
11561164

11571165
/// True if the builtins are all frozen (non-writable, non-configurable).
11581166
bool builtinsFrozen_{false};

lib/FrontEndDefs/Builtins.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ namespace hermes {
1414
static const char *builtinName[] = {
1515
#define BUILTIN_METHOD(object, name) #object "." #name,
1616
#define PRIVATE_BUILTIN(name) BUILTIN_METHOD(HermesBuiltin, name)
17+
#define JS_BUILTIN(name) BUILTIN_METHOD(HermesBuiltin, name)
1718
#include "hermes/FrontEndDefs/Builtins.def"
1819
};
1920

lib/VM/Interpreter-slowpaths.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,12 @@ ExecutionStatus Interpreter::implCallBuiltin(
304304
CodeBlock *curCodeBlock,
305305
uint32_t op3) {
306306
const Inst *ip = runtime->getCurrentIP();
307-
NativeFunction *nf = runtime->getBuiltinNativeFunction(ip->iCallBuiltin.op2);
307+
uint8_t methodIndex = ip->iCallBuiltin.op2;
308+
Callable *callable = runtime->getBuiltinCallable(methodIndex);
309+
assert(
310+
isNativeBuiltin(methodIndex) &&
311+
"CallBuiltin must take a native builtin.");
312+
NativeFunction *nf = vmcast<NativeFunction>(callable);
308313

309314
auto newFrame = StackFramePtr::initFrame(
310315
runtime->stackPointer_, FRAME, ip, curCodeBlock, op3 - 1, nf, false);

lib/VM/JSLib/HermesBuiltin.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -762,7 +762,7 @@ hermesBuiltinExportAll(void *, Runtime *runtime, NativeArgs args) {
762762

763763
void createHermesBuiltins(
764764
Runtime *runtime,
765-
llvh::MutableArrayRef<NativeFunction *> builtins) {
765+
llvh::MutableArrayRef<Callable *> builtins) {
766766
auto defineInternMethod = [&](BuiltinMethod::Enum builtinIndex,
767767
Predefined::Str symID,
768768
NativeFunctionPtr func,

0 commit comments

Comments
 (0)