-
Notifications
You must be signed in to change notification settings - Fork 639
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Optimize UnicodeICU localeCompare #1186
Conversation
Hi @sujankh! Thank you for your pull request and welcome to our community. Action RequiredIn order to merge any pull request (code, docs, etc.), we require contributors to sign our Contributor License Agreement, and we don't seem to have one on file for you. ProcessIn order for us to review and merge your suggested changes, please sign at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need to sign the corporate CLA. Once the CLA is signed, our tooling will perform checks and validations. Afterwards, the pull request will be tagged with If you have received this in error or have any questions, please contact us at cla@meta.com. Thanks! |
a2fdad8
to
d9adb66
Compare
Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Meta Open Source project. Thanks! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for working on this, I just have some minor comments.
namespace { | ||
struct UCollatorDeleter { | ||
void operator()(UCollator *coll) { | ||
if (coll) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't believe the deleter is invoked if the pointer is null.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed. Thanks, re-read cppreference to make sure.
cacc3c7
to
d57f6f1
Compare
d57f6f1
to
4f6213c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks for working on this!
@neildhar has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator. |
Summary: Original Author: sujan.khadka@live.com Original Git: 16a6e2c Original Reviewed By: avp Original Revision: D51429400 This change eliminates repeated calls to `ucol_open` and `ucol_close` in `hermes::platform_unicode::localeCompare` for HERMES_PLATFORM_UNICODE_ICU. On a sample sort.js(that sorted 30k strings using localeCompare), the runtime goes down from ~500 ms to ~120ms. **Before:** I observed in my trace that ucol_open and ucol_close was called in every localeCompare invocation and each ucol_open took around 500-900 ns. ucol_close is tiny ~100ish ns in each call. Note that the first call to ucol_open, it takes around 100us even after applying this diff. ![image](https://github.com/facebook/hermes/assets/6753926/739edffb-6c7b-4e93-babd-f51f9add4231) Here is localeCompare call stack before the patch: ![image](https://github.com/facebook/hermes/assets/6753926/9b9fbf31-aa5f-4cc6-a594-26c544c6ebcb) **After** After making UCollator construction static, we avoid repeated ucol_open and ucol_close(except during static initialization) thus making the sort.js sorting fast. Here is the localeCompare stack after the patch: ![image](https://github.com/facebook/hermes/assets/6753926/7deeba56-ec64-480d-9cf2-4ddcec10fc8b) Looking at the code, i found out that HERMES_PLATFORM_UNICODE_ICU is not used in Android/iOS but can make desktop usage faster (it it useful??). Here is the sort.js script which i got from one of the issues/posts in hermes. ``` print("gen..."); const randInt = (end, start = 0) => Math.floor(Math.random() * (end - start) + start); const alphabet = 'abcdefghijklmnopqrstuvwxyz'; const names = Array.from({length: 30000}, () => Array.from({length: 8}, () => alphabet[randInt(alphabet.length)]).join(''), ); for(var i = 0; i < 5; ++i){ print(names[i]) } print('sorting...'); const s = Date.now(); names.sort(localeCompare); print(`...done, took ${Date.now() - s}ms`); function localeCompare(a, b) { const s = Date.now(); const result = a.localeCompare(b); const e = Date.now(); if (e - s > 1) { print(`slow localeCompare: ${e - s}ms for '${a}' vs '${b}'`); } return result; } for(var i = 0; i < 5; ++i){ print(names[i]) } ``` Pull Request resolved: #1186 Pulled By: neildhar Reviewed By: tmikov Differential Revision: D52854458 fbshipit-source-id: bebecb56c919811884263e55fe7da4b7ce10cf55
* Add JSI method for setting external memory size Summary: X-link: https://github.com/facebook/react-native/pull/41436 Add a JSI API for associating some native memory with a JS object. This is intended to provide a mechanism to trigger more frequent garbage collection when JS retains large external memory allocations, in order to avoid memory buildup. This diff just adds the JSI method, without any implementations. Changelog: [General][Added] - Added JSI method for reporting native memory to the GC. Reviewed By: tmikov Differential Revision: D50524912 fbshipit-source-id: c8df0e18b0415d9523e0a00f6d0ed2faa648ac68 * Deploy 0.223.0 to fbsource (#41725) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41725 Reviewed By: SamChou19815 Differential Revision: D51713020 fbshipit-source-id: 84dc8c882f7603d642cb4ccb735fad0fb7e25d4d * Pass additional parameters to NativeState finalizer Summary: Pass the GC and `NativeState*` to the finalizer to make it more flexible. This will allow it to be used to manage external memory in the next diff. Reviewed By: tmikov Differential Revision: D50531361 fbshipit-source-id: f5483f0e25d92156bc4f593ffa0f19c6de88a1c0 * Remove asserts in objectFromPropertyDescriptor Summary: It turned out that these assertions hit with test262 tests. These test cases are, for example, passing property descriptor with incomplete attributes. For some tests, this doesn't matter and they are just testing the behavior of trap functions. Few test cases are testing with incorrect attribute set up and checking that the runtime is handling as spec says. Essentially, `objectFromPropertyDescriptor` should create the descriptor object as specified by the code, and Proxy should pass it to the `defineProperty` trap function as is. Each of the case handling is already well implemented in the Proxy code. Reviewed By: tmikov Differential Revision: D51692787 fbshipit-source-id: 340b49007ca7a35eacab07be1c1e40a6e5b7ec7d * Implement setExternalMemoryPressure in Hermes Summary: Add an implementation of `adjustExternalMemoryPressure` in Hermes. It uses an internal property pointing to a `NativeState` to maintain the external memory size. The finalizer of the `NativeState` informs the GC that the memory has been freed. Reviewed By: tmikov Differential Revision: D51241265 fbshipit-source-id: d9be03ee71d34a75fc6a2544e34ca98d08dfa70d * Optimize UnicodeICU localeCompare (#1186) Summary: This change eliminates repeated calls to `ucol_open` and `ucol_close` in `hermes::platform_unicode::localeCompare` for HERMES_PLATFORM_UNICODE_ICU. On a sample sort.js(that sorted 30k strings using localeCompare), the runtime goes down from ~500 ms to ~120ms. **Before:** I observed in my trace that ucol_open and ucol_close was called in every localeCompare invocation and each ucol_open took around 500-900 ns. ucol_close is tiny ~100ish ns in each call. Note that the first call to ucol_open, it takes around 100us even after applying this diff. ![image](https://github.com/facebook/hermes/assets/6753926/739edffb-6c7b-4e93-babd-f51f9add4231) Here is localeCompare call stack before the patch: ![image](https://github.com/facebook/hermes/assets/6753926/9b9fbf31-aa5f-4cc6-a594-26c544c6ebcb) **After** After making UCollator construction static, we avoid repeated ucol_open and ucol_close(except during static initialization) thus making the sort.js sorting fast. Here is the localeCompare stack after the patch: ![image](https://github.com/facebook/hermes/assets/6753926/7deeba56-ec64-480d-9cf2-4ddcec10fc8b) Looking at the code, i found out that HERMES_PLATFORM_UNICODE_ICU is not used in Android/iOS but can make desktop usage faster (it it useful??). Here is the sort.js script which i got from one of the issues/posts in hermes. ``` print("gen..."); const randInt = (end, start = 0) => Math.floor(Math.random() * (end - start) + start); const alphabet = 'abcdefghijklmnopqrstuvwxyz'; const names = Array.from({length: 30000}, () => Array.from({length: 8}, () => alphabet[randInt(alphabet.length)]).join(''), ); for(var i = 0; i < 5; ++i){ print(names[i]) } print('sorting...'); const s = Date.now(); names.sort(localeCompare); print(`...done, took ${Date.now() - s}ms`); function localeCompare(a, b) { const s = Date.now(); const result = a.localeCompare(b); const e = Date.now(); if (e - s > 1) { print(`slow localeCompare: ${e - s}ms for '${a}' vs '${b}'`); } return result; } for(var i = 0; i < 5; ++i){ print(names[i]) } ``` Pull Request resolved: https://github.com/facebook/hermes/pull/1186 Test Plan: **Execute sort.js before applying this patch** ``` hermes (main)$ ../build_release/bin/hermesc -emit-binary -out sort.hbc samples/sort.js hermes (main)$ ../build_release/bin/hvm ./sort.hbc gen... sorting... ...done, took 466ms hermes (main)$ ../build_release/bin/hvm ./sort.hbc gen... sorting... ...done, took 486ms ``` **Execute sort.js after applying this patch** ``` $ ../build_release/bin/hermesc -emit-binary -out sort.hbc samples/sort.js hermes (icu_localecompare_optimize)$ ../build_release/bin/hvm ./sort.hbc gen... sorting... ...done, took 119ms hermes (icu_localecompare_optimize)$ ../build_release/bin/hvm ./sort.hbc gen... sorting... ...done, took 127ms ``` **Run check-hermes:** ``` hermes (icu_localecompare_optimize)$ cmake --build ../build_release/ --target check-hermes [0/1] Running the Hermes regression tests Testing Time: 15.91s Expected Passes : 1773 Unsupported Tests : 66 hermes (icu_localecompare_optimize)$ echo $? 0 ``` Reviewed By: avp Differential Revision: D51429400 Pulled By: neildhar fbshipit-source-id: f5a2f56952ec9bcbaad441df8f2e9c49c8a0b09a * InstSimplify: fix handling of undefined in relational comparisons (#1202) Summary: Pull Request resolved: https://github.com/facebook/hermes/pull/1202 Relational comparisons (<= and >=) are simplified to a true/false when it is known that the operands are the same value with a primitive type. If the value is "undefined", it is converted to NaN, which never equals itself. The optimization was not correctly handling the case where the operand could be "undefined" or another type - it was only checking for "undefined". Example: try {} catch { var v0 = "m"; } return v0 <= v0; The try/catch is necessary to make the optimizer believe `v0` is not a constant. Reported in https://github.com/facebook/hermes/issues/1200. Reviewed By: neildhar Differential Revision: D51555324 fbshipit-source-id: 87a4285166a9e11e96014feae45497d1a30d8307 * Deploy 0.223.2 to xplat Summary: Changelog: [Internal] Reviewed By: pieterv Differential Revision: D51768863 fbshipit-source-id: 716add02d82cdfa56f2d3fc4d4560fcb26e8f426 * Do not apply the plugin for TS files Summary: Hermes parser currently cannot handle TS files as good as Flow ones. However, the plugin will unconditionally override the parser for all files. This will break if we introduce the plugin in a config that must work for both TS and JS. This diff skips the parser override if the filename ends in .ts or .tsx. According to babel's implementation, we need to return undefined to ignore the parserOverride: https://github.com/babel/babel/blob/85e649203b61b7c908eb04c05511a0d35f893e8e/packages/babel-core/src/parser/index.ts#L9-L25 Reviewed By: pieterv Differential Revision: D51771100 fbshipit-source-id: 7564856952c02d5707536c68a835603aaee77de2 * Fix binop side effects with BigInt Summary: `getBinarySideEffect()` wasn't considering that arithmetic operations between BigInt and non-BigInt (except string addition) throw a TypeError. Refactor the code to be explicit about all operators. Add new tests. Curiously, this change revealed a bug in an existing test: t5: string|number|bigint = t1:any + t2:any t6: string|number|bigint = t3:any + t4:any t7: string|number|bigint = t5 + t6 t7 is unused We were incorrectly removing the calculation of t7, because both operands are primitive types. However it might happen, for example, that t5 is biging and t6 is a number, which would throw an exception. Reported in https://github.com/facebook/hermes/issues/1199. This diff was ported from Static Hermes (since this is a bug). Had to fix BigInt dumping to make the Optimizer test pass. Reviewed By: avp Differential Revision: D51555323 fbshipit-source-id: 927f5e6041899f0800c5a641c62d32e18c3d9f18 * Always write result last in the interpreter (#1203) Summary: If an instruction is the last user of one of its operands, the register allocator may reuse one of its operands as the result register. This is typically fine since most operands are only input parameters, and they are always read before the output is written. However, when the operand is both an input and an output, this requires care to ensure that the operand register (whose live range ends with the given instruction) is written before the result. This ensures that even if the register allocator assigns them the same register, the value held in that register after the instruction is the result. Closes #1203 Reviewed By: avp Differential Revision: D51597086 fbshipit-source-id: 14a4f27887d11cbe21bae5b27712b498b48c3f20 * Skip low-signal assert while fuzzing Summary: In debug mode, this assertion is used to catch potential unbounded handle allocations. It offers however very poor signal when fuzzing. Skipping it to unblock stress-testing large GCScopes. Reviewed By: neildhar Differential Revision: D51587303 fbshipit-source-id: 5d373ecee8535bf38ba8f56055ff9efa03cadec3 * Avoid FMA contraction in makeDate Summary: Newer versions of clang will automatically produce FMA instead of separate multiply and add when the multiplication and addition are in the same expression. This is undesirable because it results in non-standard behaviour in makeDate, and breaks an existing test262 test. We can do this in two ways: 1. We can split them into separate expressions 2. We can use `#pragma STDC FP_CONTRACT OFF` Unfortunately, neither of these address the issue with GCC, which uses `-ffp-contract=fast` by default, and cannot be overridden except by using `volatile`. To fix this, add `-ffp-contract=on` to our build flags, and split the expressions. Reviewed By: tmikov Differential Revision: D51725454 fbshipit-source-id: 3d4c91bb32c619c05c53fd8b1962adbc862554aa * Deploy 0.223.3 to xplat Summary: X-link: https://github.com/facebook/react-native/pull/41797 Changelog: [Internal] Reviewed By: gkz Differential Revision: D51839509 fbshipit-source-id: 961fc4e8fc0f7a45c3882753301d027f319b9ea6 * Revert D51839509: Deploy 0.223.3 to xplat Differential Revision: D51839509 Original commit changeset: 961fc4e8fc0f Original Phabricator Diff: D51839509 fbshipit-source-id: 71a97ee1971d5c882cb704f4f9ff42a95e6d52f6 * Deploy 0.223.3 to xplat Summary: X-link: https://github.com/facebook/react-native/pull/41809 Changelog: [Internal] Reviewed By: samwgoldman Differential Revision: D51855821 fbshipit-source-id: 4fe9c937aff925150fb015be2ea93fa120e7f462 * Added support for ES6 classes (#1176) Summary: We are currently experimenting with a Hermes integration as a potential replacement for the QuickJS engine. As part of the migration, we've realized that the lack of support for ES6 classes and block scoped variables within Hermes is a bigger deal than expected for us. We have 3 engine integrations which all support ES2017+, and without support for ES6 classes and block scoped variables we have to either downgrade the ES target to ES5, or integrate Babel in our compilation pipeline which are both invasive and risky changes for us. In order to fix this, I've taken a stab at supporting ES6 classes somewhat natively within Hermes. I've went with the simplest and the less risky approach that could get the job done. This PR doesn't change the IR, it instead transforms the AST at compile time to convert ES6 classes into plain ES5 classes, very much like what the TypeScript and Babel compiler do. A more advanced implementation would likely add support for classes within the IR. This PR ended up to be fairly straightforward to do, as the JS parser implemented within Hermes already supports most of the ES6 syntax, it's only the IR Gen pass which doesn't support it. ## Supported ES6 class features - Define a class with a parent class (`class Child extends Parent {}`) - Method and static method definitions (`method() {}` and `static method() {}`) - Property and static property definitions (`get prop() {}`, `static get prop() {}`, `set prop(v) {}`, `static set prop(p) {}` - Super call expression in method and static method definitions (`super.method()`) - Super member expression in property and static property definitions (`super.property`) - User defined constructor (`constructor() {}`) - Properties that are immediately initialized. (`property = someValue`) - Class expressions (`const MyClass = class {}`) - Class expressions with private named identifier (`const MyClass = class Self { constructor() { Self.hello = 'world' }})`) ## Unsupported ES6 class features - static block initializers (`static { // code to eval at class load time }`). The existing parser is not able to parse these blocks yet. - Private methods and properties (`#privateMethod() {}`) - Inheritance from built-in types like `Error` or `Map` (`class CustomError extends Error {}`) ## Changes - Added a `enableES6Classes` compile flag. When enabled, a new post processing step will occur on the AST which will transform ES6 classes into ES5 functions, similar to what Babel or the TypeScript compiler does. - Added `lib/AST/ES6Class`, an AST visitor which visits the ClassNodeDeclaration and ClassExpressionNode and will turn them into plain ES5 functions. The generated AST relies on a new helper lib that is meant to be available on the global object as `HermesES6Internal`. - Added the `HermesES6Internal` helper module, which implements `defineClass`, `defineClassProperty`, ` defineStaticClassProperty`, `defineClassMethod` and `defineStaticClassMethod`. - Added a few tests Pull Request resolved: https://github.com/facebook/hermes/pull/1176 Test Plan: - All Hermes tests are passing Reviewed By: tmikov Differential Revision: D51713522 Pulled By: avp fbshipit-source-id: 15e5f3cd0762f7ffddb357f1ec9edce9713bbafe * handle Literal properties in flow-to-flowdif conversion Summary: the StringLiteral comparison here doesn't actually work. also NumericLiterals are valid as property keys, so it adds that as well this change effects object and class properties and methods. Reviewed By: pieterv Differential Revision: D51867940 fbshipit-source-id: ad546b7c539d29c80fc83393c2b5b66678d51b43 * Hermes ABI definition skeleton Summary: The initial boilerplate for the WIP Hermes stable ABI. This just creates a directory with the header defining the new interface, which will be used by both the wrapper and the actual implementation of the ABI. Reviewed By: tmikov Differential Revision: D47563699 fbshipit-source-id: b6da43b3f8fdd168d8bda3adee53277d17275325 * ABI implementation skeleton Summary: Create a skeleton for the concrete implementation of our new C-API on top of the Hermes internal APIs. Set up a build that will build either a static or dynamic library depending on the setting of `BUILD_SHARED_LIBS`. Reviewed By: dannysu Differential Revision: D50153971 fbshipit-source-id: e8462f914a076efc575d6ad9cec13cc9c4627e09 * Hermes ABI wrapper skeleton Summary: Add the boilerplate for the C++ wrapper that implements JSI on top of the C-API. Currently, each function is just implemented to throw. Reviewed By: tmikov, avp Differential Revision: D50153972 fbshipit-source-id: bea12505e75549c13a281fe9153875471ccd6ee5 * Remove unnecessary HostObject trackers in TraceInterpreter Summary: It turned out that these maps are holding the HostObjects and HostFunctions created during replay, and never be released until the runtime instance is destroyed. This changes the behavior of GC for the host object during replay compared to tracing time as there objects can never be collected. These maps are used only for assertions to make sure the created IDs are unique, but they are created by the real runtime's function, so such assumptions should be able to be made already. Hence, simply removing these members and usages. Reviewed By: neildhar Differential Revision: D51874351 fbshipit-source-id: 1ca93c35b4abbc78b95e0a24419f820e16946fac * Add fuzzilli profile for Hermes W2C fuzzer Summary: Additional Fuzzilli profile for sandbox memory fuzzing. Differential Revision: D51352212 fbshipit-source-id: 106a4c89704284c0c6c3f99e96f52869f225e3dc * Trace setExternalMemoryPressure Summary: We've added `jsi::Runtime::setExternalMemoryPressure()`. Let's add tracing and replaying for SynthTrace. Note that function call to `setExternalMemoryPressure()` won't affect correctness of the inputs and outputs during replay, but we want to replay for performance effects mostly for GC. Reviewed By: neildhar Differential Revision: D51835433 fbshipit-source-id: 0701bc2d83fe0f724ed3a215ef53ff016b9f5a58 * Minor fixes in HermesABIRuntimeWrapper Summary: Capitalise the macro and fix the include guard. Reviewed By: tmikov, ftanuma Differential Revision: D51923607 fbshipit-source-id: f7f978fb04ee566af2ffce05d29b04a1c1ef2945 * API for getting the list of loaded scripts Summary: CDPHandler needs to know the list of loaded scripts so that when `Debugger.enable` message comes, CDPHandler can emit `Debugger.scriptParsed` notifications. Currently CDPHandler obtains the loaded scripts by requiring that it be instantiated along with HermesRuntime, so that CDPHandler can monitor `PauseReason::ScriptLoaded` and cache the list of scripts. However, this is not a desirable design because it introduces the unnecessary requirement that CDPHandler must be created along with HermesRuntime even though there is no CDP connection. It introduces the question of "what does the msgCallback do when there is no connection?" Further examination revealed that there is actually no need for CDPHandler to be doing this caching. This is a sensible API to expose from DebuggerAPI. By exposing this functionality, we also save memory spent on the cache by not duplicating information already exists in the VM. I also made a change to align CMake with BUCK. The CMake build emits debug info for InternalBytecode whereas the BUCK build doesn't. `hermes_compile` by default builds with `-g0`. When debug info is present, iterating through the RuntimeModules would get InternalBytecode.js included as one of the loaded scripts. That by itself isn't a problem. I just thought it'd be good to be building things the same way. Reviewed By: mattbfb Differential Revision: D51684983 fbshipit-source-id: b838f71674320bd641ce47f43d7bff14a1312ff5 * Fix HostObject tracing for setProperty Summary: I noticed that we don't have test case nor trace record that exercises `HostObject`'s `setProperty`` calls. Adding a test case revealed that thereplay part isn't working, so fixing it here. Here are short description of bugs - `FakeHostObject::set()` was not passing `PropNameID *nativePropNameToConsumeAsDef` to `interpreter.execFunction`, which was actually needed. - `RecordType::GetPropertyNativeReturn` case was using `getObjForUse` when calling `traceValueToJSIValue` even though value can be String, BigInt, etc (non Object). `getObjForUse()` internally calls `jsi::Value::getObject()` without type check so it asserts in debug builds. - `RecordType::SetPropertyNativeReturn` was doing unnecessary operations copied from `RecordType::SetPropertyNative`. Reviewed By: neildhar Differential Revision: D51966162 fbshipit-source-id: 5f4cec2b4db4bd125b36e06ae1d5ec40000b05da * Move hostObjectsCallCount_ to FakeHostObject from TraceInterpreter Summary: There is no good reason to have HostObject's call count as TraceInterpreter's member. We can have it in each FakeHostObject's instance. Reviewed By: neildhar Differential Revision: D51920392 fbshipit-source-id: 50573ae5142efcba90b7c35467cbd268820fa0d4 * Fix build break in SynthTraceTest (#1217) Summary: Previous Diff broke the builds on CircleCI. It was missing include for variant. Pull Request resolved: https://github.com/facebook/hermes/pull/1217 Reviewed By: neildhar Differential Revision: D52045636 fbshipit-source-id: 930f1b3af05b3a80281f6050d36489390a939391 * Move hostObjectsPropertyNamesCallCount_ to FakeHostObject from TraceInterpreter Summary: There is no good reason to have HostObject's getPropertyNames() call count as TraceInterpreter's member. We can have it in each FakeHostObject's instance. Reviewed By: neildhar Differential Revision: D51966363 fbshipit-source-id: fd4155c4c15b18ce94d38570f28d1c614d2835d1 * Move hostFunctionsCallCount_ to HostFunction wrapper Summary: There is no good reason to have HostFunction's call count as TraceInterpreter's member. We can have it in each HostFunction wrapper lambda as a captured variable. Reviewed By: neildhar Differential Revision: D51966364 fbshipit-source-id: 93049829651afebe96b8951f36b9be2622c6c913 * Merge HostObjectInfo's propNameToCalls callsToGetPropertyNames Summary: We do not need to store set/get calls and getPropertyNames calls for a HostObject separately. Merge them into a Call vector simplifies the logic. Reviewed By: neildhar Differential Revision: D51997003 fbshipit-source-id: f0d1297e7a6de54b198066459d8a26f3e1a084e3 * Simplify TraceInterpreter getCalls() Summary: With the previous change, we can simplify the logic inside getCalls() that is using stack. The stack used to contain ObjectId or FunctionId to get Calls vector for each case, but we just need to stack the reference to the Call vector itself. Only for the case of GetNativePropertyNamesRecord, we need ObjectID. Reviewed By: neildhar Differential Revision: D51998012 fbshipit-source-id: b9c43b5e3ec2e0d8e1f79f36cfc4e5cf41239bab * Release version to 0.18.1 Summary: Release version to 0.18.1 Reviewed By: noahlemen, alexmckenley Differential Revision: D52164018 fbshipit-source-id: b819f0935e539d4eaa321b05a81a848819c2a895 * Fix local to utc conversion Summary: Use the same trick as in V8 to fix local to UTC time conversion. Reviewed By: neildhar Differential Revision: D51728232 fbshipit-source-id: 537b57bee65511b2eebfa92f0941ee2b3d64f59d * Replace localtime with localtime_r for thread safety Summary: Fix two things: 1. `localtime()` uses an internal static buffer, so not thread safe, use `localtime_r()` instead. 2. `localtime_r()` internally calls`tzset()`, but only for the first time. Add a wrapper in the unit tests to always explicitly call `tzset()` to update time zone. Reviewed By: neildhar Differential Revision: D51728257 fbshipit-source-id: f05745e01555f3d06ca888a64d65e57e51c0f16f * Deploy 0.224.0 to xplat Summary: X-link: https://github.com/facebook/react-native/pull/41949 Changelog: [internal] Reviewed By: gkz Differential Revision: D52177280 fbshipit-source-id: 37fe478645ad30b40f4fb4e81d7fc467ac971928 * Create yarn script for prettier plugin development Summary: I've added a script to make development of the prettier plugin easier. This script can be run with the following: ``` yarn build-prettier ``` It will do the following things: 1. Clone the remote fork to your devserver if necessary (inside a .gitignored directory) 1. Determine if there are any upstream commits you need to pull to ensure we dont accidentally lose any changes 1. run `yarn install` 1. copy the `dist` folder from local `hermes-parser` dir into node_modules 1. run `yarn build --no-minify` 1. copy the necessary assets to the proper directory in our source tree NOTE: Developers will still need to ensure that they commit any prettier changes to the upstream repo and create and merge a pull request. Reviewed By: SamChou19815 Differential Revision: D52149102 fbshipit-source-id: 5f800835957181fc0837edea8dd5d562ace6101e * Fix bigint side effects for >>>, /, % (#1214) Summary: Pull Request resolved: https://github.com/facebook/hermes/pull/1214 BigInt differs from numbers - several bigint operations can throw an exception, specifically: - >>> is not allowed at all and throws - / and % can result in division by zero Improve the side effect model and add a test. This diff was ported from SH. Closes https://github.com/facebook/hermes/issues/1212 Reviewed By: avp Differential Revision: D52013223 fbshipit-source-id: 746f1180abfbdfff63928a248c05731e782ed0ad * Retain prop types when lowering component syntax Summary: Previously with the component syntax transform we would drop prop type annotations and just output a readonly inexact object. This change ensures all prop types are preserved through the transformation. Reviewed By: alexmckenley Differential Revision: D52208500 fbshipit-source-id: 30fc7c0664ef1a3a1be19224188ad101d78acb78 * Back out "Replace localtime with localtime_r for thread safety" Summary: Backing out the localtime thread safety change since it is broken on Windows. Original commit changeset: f05745e01555 Original Phabricator Diff: D51728257 Reviewed By: lavenzg Differential Revision: D52210979 fbshipit-source-id: 17e0ac1513eb23cc02c091940327d93a69ce06e0 * Build hdb release with static libraries (#1197) Summary: Pull Request resolved: https://github.com/facebook/hermes/pull/1197 `hdb` links against `libhermes` and `libjsi`, so make sure they are built as static libraries when we are building `hdb` for distribution. Reviewed By: dannysu Differential Revision: D51520865 fbshipit-source-id: e123afcffc46873c4b492590262ef0d756a06693 * Fixes for ES6 class support (#1221) Summary: This change provides a few fixes to the ES6 class support which was added in this PR: https://github.com/facebook/hermes/pull/1176 - Added support for class methods and properties being declared using the element expression syntax: ```js const propKey = Symbol(); class Test { [propKey]() { } } ``` This change required that properties are no longer indexed at compile time into a map, as the property keys themselves might be provided from external values. - Fixed class expressions not being processed in array literal expressions: ```js const entries = [0, 1, 2, new (class extends Parent {})] ``` - Methods can now be overwritten as regular properties: ```js class Test { constructor(getter) { if (getter) { this.getMyNumber = getter; } } getMyNumber() { return 42; } } ``` - Method names are now preserved at runtime and can be read through `object.method.name()` - Added more tests Pull Request resolved: https://github.com/facebook/hermes/pull/1221 Test Plan: All tests run Reviewed By: tmikov Differential Revision: D52273463 Pulled By: avp fbshipit-source-id: 273aedb1922ed3dc4a6a5863ae9ce9c7a7ab8da0 * Release version to 0.18.2 Reviewed By: alexmckenley Differential Revision: D52223566 fbshipit-source-id: 5406af0d4ea83676a4929394a45989174f0e56fc * Deploy 0.225.0 to xplat Summary: X-link: https://github.com/facebook/react-native/pull/42004 Changelog: [Internal] Reviewed By: SamChou19815 Differential Revision: D52305312 fbshipit-source-id: b18045c450dc3204b08452ede17b76d1a43cce50 * Deploy 0.225.1 to xplat Summary: X-link: https://github.com/facebook/react-native/pull/42027 Changelog: [Internal] Reviewed By: SamChou19815 Differential Revision: D52353283 fbshipit-source-id: 4f6cefdcfe38d34c8629178823df6b39c5aebbfb * EASY: silence memory leak with GCC ASAN (#1227) Summary: Pull Request resolved: https://github.com/facebook/hermes/pull/1227 The leak was caused by the allocation of the alt signal stack. To prevent leak reporting, it is stored into a global symbol. However, that symbol is unused and can be optimized out. Force it to be considered "used". Closes https://github.com/facebook/hermes/issues/1225 Reviewed By: avp Differential Revision: D52356667 fbshipit-source-id: 1bd7098218f7d3c155f669e975c26ad491fa23bd * Fix date-local-to-utc.js failure Summary: 1. Windows has different TZ name, so allow it to fail. 2. On some old Android devices (e.g. Nexus), the system timezone data is old, so can't handle America/Santiago correctly, use America/New_York instead. Reviewed By: neildhar Differential Revision: D52213926 fbshipit-source-id: 1597e014893274e02d37eb54a2020be29bd73de9 * Revive "Replace localtime with localtime_r for thread safety" (#1231) Summary: Pull Request resolved: https://github.com/facebook/hermes/pull/1231 Fix two things: 1. localtime() uses an internal static buffer, so is not thread safe, use localtime_r() instead. 2. localtime_r() internally calls tzset(), but only for the first time. Add a wrapper in the unit tests to always explicitly call tzset() to update time zone. These changes were committed in 5fdb47a and caused crashes on Windows due to wrong error code check, and were reverted. Now commit again with fix for that. Reviewed By: neildhar Differential Revision: D52358023 fbshipit-source-id: 2529e874ee631887d93edcb807e93c712e0feab5 * Special-casing `int32`-convertible nums in `fromDouble` Summary: Adds a special-case to check for numbers which are storable in an `int32`, and adds a short-circuit if so. It looks like a lot of time is spent in the `abstractEqualityTest_RJS` method, of which the lion's share is in `BigIntPrimitive::fromDouble` This function allocates a big buffer capable of storing 1024-bit values, since doubles can represent ints (though very few) up to that size. We then spend cycles trimming extra bytes that aren't needed until this buffer is shrunk-to-fit. This is a separate thing, and can be optimized separately and probably get big wins for `fromDouble` in general as a follow-up. Instead, if our number fits in a 32-bit int, let's just allocate enough bits for the particular number we're setting, set the value specifically to that number, and return (rather than over-allocating and shrinking). Reviewed By: avp Differential Revision: D52234978 fbshipit-source-id: a097151a71b88e6221bfc5323d38c3fe26dcf0b1 * Passing num digits to represent a double into its BigInt `fromDouble` parsing Summary: Currently, we'll always allocate a buffer of 1024 digits in order to cast a double to a BigInt. This makes sense in the limit, as doubles can represent 1024-bit numbers. In lots of current paths, though, we have access to the number of digits before we actually allocate this buffer. This is *really* expensive in practice. As such, let's just allocate enough space to actually represent the number we're converting rather than the largest possible representible number. Reviewed By: mshamis85 Differential Revision: D52262602 fbshipit-source-id: a02d11f85e39496e159ed5c32a61a278a3ebe4e7 * SimplifyCFG: fix strict equality for literals (#1229) Summary: Pull Request resolved: https://github.com/facebook/hermes/pull/1229 This diff was imported from Static Hermes D52403620. Strict equality for literals was incorrect - it was performing a "bit comparison" for numbers (by comparing pointers to the uniqued literals), while it should be performing a numeric comparison. This caused incorrect switch case optimization. Closes https://github.com/facebook/hermes/issues/1215 Reviewed By: neildhar Differential Revision: D52403687 fbshipit-source-id: a1496a79dd95e333d54ee307086dc9189e09932f * EASY:API/hermes.cpp: enable ES6-classes if enabled in config Summary: The ES6Classes flag wasn't passed to BCProviderFromSrc in the JSI API. Reviewed By: neildhar Differential Revision: D52458224 fbshipit-source-id: 4e1010414940c1a396e0a72f80078cbb7852d6dd * JSLexer: don't auto-register magic comment URLs Summary: These changes were imported from Static Hermes D51795387. ## The problem with auto-registering magic URLs Until now, JSLex would always automatically register `sourceURL=` and `sourceMappingURL=` magic comments in the associated `SourceErrorManager` as soon as detected. That is problematic for a few reasons: - The comment could be encountered at any time or multiple times, leading to inconsistent state, where it is registered for half of the file, or different values are registered for different parts. - Violates separation of concerns: the lexer shouldn't really be concerned with populating state in unrelated components. - The registered sourceMappingURL is usually recorded in the debug information for later use by the debugger. However we might just want to fetch the source map and use it. This decision shouldn't belong to the lexer. - Finally, it is inefficient because SourceErrorManager creates copies of the URLs. In many scenarios we know that the URLs point to the existing source buffer, so we don't need to make a copy. TODO: look into whether SourceErrorManager needs to make copies or it could just hold references. ## Change This diff removes the auto-registration in JSLexer and adds a new function `JSParser::registerMagicURLs()`, which performs the same function, but is invoked only at well defined points. ## Complications with pre-parsing Under certain conditions, which are not important, pre-parsing is invoked first to parses the entire source and record locations of all functions. As such, it encounters all magic comments and other things that we need to keep track of, like "use static builtins". The existing pre-parser API does not expose a parser/lexer instance, it just performs it in one go and discards the parser, which prevents us from querying the magic URLs or calling `registerMagicURLs()`. To solve this, we change pre-parsing to return an instance of the parser, after parsing has finished. This allows users of the API to query the returned parser. For practical reasons the returned instance has to use `std::shared_ptr<>`, which necessitated a change from `std::unique_ptr<>` to the former in one place. It should make no difference - parsers are not created that often. ## Misc other changes Simplify the API of JSParserImpl a bit - a few methods are simply forwarded to the lexer, so they can be implemented directly in JSParser, if the lexer is exported by JSParserImpl. Improve the registration of the magic URLs in SourceErrorManager, so that an empty URL deletes the record instead of storing the empty string. This makes a difference in `getSourceUrl()`, which is treated like an override on top of `getBufferFileName()`. Lastly, I am aware of the difference in case between the old functions which used `Url`, while new functions use `URL`. The latter is correct, but I don't want to perform unrelated stylistic changes in this diff. ## Portability to Hermes The URL registration changes are only enabled in Static Hermes by relying on -DSTATIC_HERMES. Reviewed By: avp Differential Revision: D52190480 fbshipit-source-id: 871c1fd7d889779439d00eda63abce95e77be4fd * Add a new type of WeakRefSlot Summary: Add a new type of WeakRefSlot, which has an additional pinned value field. This value will be marked if the WeakRef object is alive (or it's reached from other objects). This new primitive is intended to be used in new WeakMap implementation. Reviewed By: neildhar Differential Revision: D51435175 fbshipit-source-id: bfe8e2dff98f76c8f5de502281dae6ccd55b2086 * Add weakRefReadBarrier function Summary: Add weakRefReadBarrier for HermesValue Reviewed By: neildhar Differential Revision: D52336308 fbshipit-source-id: 9ef84303e71d02dc21ec2a4df4b27be490b41e24 * Add new WeakRef type Summary: Add a new WeakRef type to manage the new WeakRefSlot. Reviewed By: neildhar Differential Revision: D51605891 fbshipit-source-id: 10bf14bdfb2fcb0fad5e85a8d725ffb0e3215e65 * Mark values in WeakMapRefSlot list Summary: Add a marking function for WeakMapRefSlots in the ManagedChunkedList. Reviewed By: neildhar Differential Revision: D51435851 fbshipit-source-id: b13b11e32c6400e329a4e0f5142425304a8ec0d0 * Re-implement JSWeakMap (#1232) Summary: Pull Request resolved: https://github.com/facebook/hermes/pull/1232 Reimplement JSWeakMap. Each key/value pair is now stored in a WeakMapRefSlot, which is managed by a WeakMapRef, so we no longer need a separate ValueStorage. These slots are freed at three places: 1. of JSWeakMap::deleteValue() (if the key exists). 2. In completeWeakMapMarking(), when the slot has no value or the object is not marked. 3. In the finalizer of JSWeakMap. Currently, WeakRefLock is still used in setValue(), since WeakRef marking is not removed yet. We will do that in separate diffs. Add a lookup key type for this JSWeakMap, and use it for finding matching key. This eliminates allocating temporary WeakMapRefSlots for querying. Reviewed By: neildhar Differential Revision: D51584024 fbshipit-source-id: 34dd65e4e729753a3d279b32f5ee380d2f979a9d * Remove TracingRuntime configs (#1233) Summary: Pull Request resolved: https://github.com/facebook/hermes/pull/1233 Attempt to remove unnecessary configs for TraceRuntime from RuntimeConfig. Naively moved up three params to `makeTracingHermesRuntime` and `HermesExecutorFactory`. Reviewed By: neildhar Differential Revision: D51904121 fbshipit-source-id: 9ac8be2dde48fa4d49dbbb2d6b43e66691aff879 * Implement the ABI value representation Summary: Define the layout of values that will be passed across the C-API. These are largely analagous to `jsi::Value` and the subclasses of `jsi::Pointer`, with the addition of also carrying error information. Reviewed By: tmikov Differential Revision: D47563696 fbshipit-source-id: 921122d2f8705318ea35dd67c6ea64c26f6c1445 * Add pointer types and convenience helpers to ABI implementation Summary: Implement the infrastructure needed to support the types specified in the C-API in `hermes_vtable.cpp`. This includes helper functions that will be needed in upcoming diffs to make it easier to manipulate values. Reviewed By: tmikov Differential Revision: D50396059 fbshipit-source-id: bcca6d615ef5479c178286e8fac438962158b10e * Implement pointer types in wrapper Summary: Implement conversions to and from the ABI and JSI value types. Reviewed By: avp Differential Revision: D50396060 fbshipit-source-id: a2fbf0a6b860e4d773dcfae0259bd03ba2172617 * Implement exception reporting and retrieval Summary: Implement exceptions in both the implementation and wrapper, allowing Hermes VM errors to be converted to C++ JSI exceptions. Reviewed By: tmikov Differential Revision: D50212959 fbshipit-source-id: 1538bba118cae179b23e98ed5ebd606f76cecd3a * Implement cloning values Summary: Add support for cloning references end-to-end. Reviewed By: avp Differential Revision: D50212960 fbshipit-source-id: ea822617309aae7f3a7ec041493e92d91730492c * Implement evaluateJavaScript in the ABI (#1060) Summary: Pull Request resolved: https://github.com/facebook/hermes/pull/1060 Add an API to pass buffers and implement `evaluateJavaScript`. Reviewed By: avp Differential Revision: D47563700 fbshipit-source-id: 85d4f00cbaa1ee441b582fd9272565f38fdad7f3 * Implement basic object and string creation Summary: Implement functions to create objects and strings. Reviewed By: avp Differential Revision: D50798237 fbshipit-source-id: 1aca53e647b01e2e07400beba21336d45f4ea407 * Implement object property manipulation Summary: Implement has/get/set for object properties. Reviewed By: avp Differential Revision: D50798238 fbshipit-source-id: be5620f2a5ffee209d2bbbc14b4cf7d605c2b76f * Implement setting external memory pressure Summary: Implement the new setExternalMemoryPressure API in the C-API. Reviewed By: avp Differential Revision: D51970917 fbshipit-source-id: 9582d0cd418eca8cb515b5683cc0ed05a212a26d * Implement array creation and manipulation Summary: Implement array creation and get/set operations as they exist in JSI. Reviewed By: avp Differential Revision: D51516039 fbshipit-source-id: 9695c514bb016e433a3316ba47f1c9c22fec69a7 * Implement ArrayBuffer manipulation Summary: Implement ArrayBuffer creation from external buffers, as well as functions to obtain the size and underlying data for an ArrayBuffer. Reviewed By: avp Differential Revision: D51535577 fbshipit-source-id: 0fa853958afa77d387f6d2b7c6d1266fe3dd2204 * Implement PropNameID creation Summary: Implement creation of PropNameIDs from Symbol and String. Skip creation of PropNameID from ASCII and UTF-8 buffers for now, since they can be easily implemented on top of other APIs without incurring significant cost. Reviewed By: avp Differential Revision: D51535575 fbshipit-source-id: 175a460815c9466e8c9841b1b2404eeb644a0659 * Implement calls Summary: Implement calling JS functions from native code through the ABI. Reviewed By: avp Differential Revision: D51541197 fbshipit-source-id: fb5df2d3ce6d6c0c19422c511f507d1b29d9c454 * Implement HostFunction Summary: Implement HostFunction in the ABI and JSI. Reviewed By: avp Differential Revision: D51551527 fbshipit-source-id: dd77825de2ae35f53edd1a6c2f53798ac90f118a * Implement HostObject Summary: Implement HostObject in the ABI and JSI. This includes implementing a new `HermesABIPropNameIDList` to pass the result of `HostObject::getPropertyNames`. The ABI method for getting properties from a `HostObject` is named slightly differently than its JSI counterpart (`get_own_keys` vs `getPropertyNames`). This is to align it with `Reflect.ownKeys` and the Proxy `ownKeys` trap, and permit `Symbol`s to be returned from the function. Our implementation doesn't currently deal with such symbols properly, but that is a separate concern. JSI is currently ambiguous on whether this is permissible, but this is something we should address and align the two on before we stabilise the ABI. Reviewed By: avp Differential Revision: D51551526 fbshipit-source-id: ff6e399794af2084d34d5333b4ce21f04a1ed824 * Implement NativeState Summary: Implement NativeState in the ABI and wrapper. Reviewed By: avp Differential Revision: D51551528 fbshipit-source-id: 9d26743e9e11ea2cb77dc9e67fb05f3270ba2af2 * Implement object type checks Summary: Implement type checks for objects in the ABI and wrapper. Reviewed By: avp Differential Revision: D51551529 fbshipit-source-id: 2454644033eb3ee475131e3af2edc0ec48c400f8 * Implement WeakObject Reviewed By: avp Differential Revision: D48052542 fbshipit-source-id: 4f9bb1f982781eaaae7cf42dea0800e9383b787b * Implement getting UTF-8 strings from references Reviewed By: avp Differential Revision: D51535573 fbshipit-source-id: ba7f4631717e648e6491bfba4967dcffa5278eb5 * Implement instance_of and strict equality Reviewed By: avp Differential Revision: D50797413 fbshipit-source-id: 1c5cb6847f838cf9c2dc40b39862d42400edcf28 * Implement drainMicrotasks in the ABI Summary: Implement drainMicrotasks, in the ABI and the wrapper, with the same behaviour as in JSI. Reviewed By: avp Differential Revision: D50797412 fbshipit-source-id: e232c010e331d62454cdf2954af40d8c64f5b709 * Implement BigInt manipulation in the ABI Summary: Implement JSI's BigInt manipulation functionality in the ABI and wrapper. Reviewed By: avp Differential Revision: D50797414 fbshipit-source-id: c34feffe8ac1d3c103b5d4b3af249fc0db60a081 * Run tests against HermesABIRuntime (#1061) Summary: Pull Request resolved: https://github.com/facebook/hermes/pull/1061 Set up the new `HermesABIRuntimeWrapper` to run against our JSI tests, and API tests that use the APITestFactory. We should extend this to cover more of our APITests, since most of them should run correctly against the ABI runtime. Reviewed By: avp Differential Revision: D47563698 fbshipit-source-id: 5a994c708627c19c30000597e4b6068a52de71b1 * Implement native stack checking for Emscripten Reviewed By: avp Differential Revision: D49900200 fbshipit-source-id: cd1785e13a161027aed52808272d576e9b348d71 * Update the Github issue template Summary: The issue template was misleading by implying that we might be able to support non-current versions of Hermes, which is definitely not the case. React Native occasionally backports fixes, but that is only after the fix has been applied to the current version. The stable ABI will improve this, but we are not there yet. I also attempted to address a couple of things that bugged me: - Asking for a Hermes version is nonsensical and has been for a long time. - It made it seem like reporting the OS is optional. Frankly, I am still not very happy with the template, but I hope that at least these are changes in the right direction. Reviewed By: neildhar Differential Revision: D52580926 fbshipit-source-id: dfcd266fbe5a30216018781350026fb62cb887ab * Parse typeof with type arguments Summary: This diff implements the parsing support for typeof with type arguments. Changelog: [Internal] Reviewed By: avp Differential Revision: D52527139 fbshipit-source-id: ca2e4255620fe3d28d1cd5eda3bd89e541140108 * Parse typeof with type arguments JS changes Summary: This is the companion change of the previous diff. Most of the stuff are generated, the only notable change is that I make the babel adapter strip away the type arguments. Reviewed By: alexmckenley Differential Revision: D52527138 fbshipit-source-id: 26affce6151ca40a4aca95e4ea1b9ca3282acb22 * format_code_in_doc_comments=true Summary: D52632085 Reviewed By: zertosh, dtolnay Differential Revision: D52635896 fbshipit-source-id: a0faaa9a24dbc7216c05581e9af4028866bd454c * Fix _snapshotAddEdgesImpl for WeakRef edge Summary: Before adding edges, we should check if WeakRef is freed or empty. Reviewed By: neildhar Differential Revision: D52613241 fbshipit-source-id: 91988b80e12e11eb642bac4b6f3cfaf5f9fb4f8b * Fix NumberFormat SetNumberFormatDigitOptions logic (#1246) Summary: Pull Request resolved: https://github.com/facebook/hermes/pull/1246 The old Android logic was the 2020 version of the [spec](https://402.ecma-international.org/7.0/index.html#sec-setnfdigitoptions). The old logic passes `mnfdDefault` as the fallback to `DefaultNumberOption()` at step 12b. This causes the `mnfd` passed to step 12d to be whatever the default for 'currency' style is. And since `maximumFractionDigits` is set to 0 and 0 is less than `mnfd = 2`, a RangeError was thrown. This problem was already fixed by the 2021 version of the spec. `PlatformIntlApple.mm` already implements the newer spec, so that's why it's an Android-only issue. Since the future plan is to move Intl to use ICU4C on Android, that means much of the Java code becomes obsolete. Still, it's relatively easy to just update the logic to match Apple platform [spec](https://402.ecma-international.org/8.0/index.html#sec-setnfdigitoptions), so I did. In the process, I added tests to catch this bug. The tests are probably the more valuable part as we implement on top of ICU4C. Reviewed By: neildhar Differential Revision: D52641902 fbshipit-source-id: d85a415c3440b2fe81c899d8ad0fd3c6eefc8031 * Deploy 0.226.0 to xplat Summary: X-link: https://github.com/facebook/react-native/pull/42252 Changelog: [Internal] Reviewed By: SamChou19815 Differential Revision: D52708681 fbshipit-source-id: a864d2f5654ce011a4658564ec140aca03fb9ac8 * Doing single-digit fast-path for abstract equality testing Summary: Lots of common Hermes use-cases perform equality checks using `abstractEqualityTest_RJS`. This method compares a `number` against a `BigInt`, which makes total sense. The current implementation creates a `BigInt` from the `double`, which also makes sense (since the BigInt might need to store a value bigger than the max double size). However, lots of use-cases need to compare *specifically* against small numbers. Since we store numbers in our BigInts one digit at a time, we can pretty cheaply compare doubles directly against BigInts in the case that they both represent single digits. This diff adds a fast-path to do that check before performing a BigInt creation from our double. This fast-path *does* incur an extra couple checks on comparisons where the BigInt actually *is* too big to store in an `int64`, but the cost looks negligible next to the BigInt construction cost (plus real-world workloads seem overwhelmingly likely to have more sub-2^64 comparisons). NOTE: The Hermes codebase refers to each `int64` as a "digit" instead of a "word". This is not a big deal, but just wanted to call out that a `digit` can store values up to 2^63 today. Reviewed By: jpporto Differential Revision: D52551370 fbshipit-source-id: 29dd6752dc702c8257daaca5494f51268a93740b * Add wording on security bugs in GitHub issue template Summary: Add a message to the GitHub issue template, reminding users that if they believe they have discovered a security vulnerability in Hermes, they should submit it through the Meta Bug Bounty program rather than filing a public issue. This is important to avoid publicly disclosing security vulnerabilities before a fix. Reviewed By: tmikov Differential Revision: D52626730 fbshipit-source-id: 18e323051daff9a6def50a05444be6c930157b14 * Use builtin yarn version in yarn build-prettier script Summary: I've updated our `yarn build-prettier` build script to use the builtin version of yarn included with prettier to ensure the yarn lockfile is respected. I've also added logic to run `yarn build` if none of the hermes-parser `dist` assets exist to make the development flow easier from ondemand machines. NOTE: My changes to .yarnrc.cjs are needed in order to ensure the fwdproxy config is set correctly. See https://github.com/pieterv/prettier/pull/1/files Reviewed By: SamChou19815 Differential Revision: D52739505 fbshipit-source-id: 4ae67a3ef352b069627b19968fb4ba986f6ad8a1 * Add Hermes wasm2c compilation Summary: Add the ability to compile Hermes with the C-API to wasm, and the resulting wasm to C. Check in the generated artefact for a release and debug build of Hermes, making it easier to build and develop with. Reviewed By: avp Differential Revision: D47065258 fbshipit-source-id: 0de6bc047a6ebc1fdac91a460fefcbf880c4e4b3 * Sandbox runtime skeleton Summary: Create a new JSI runtime that will consume the sandbox's exported interface, and wire up the build. Reviewed By: avp Differential Revision: D52531413 fbshipit-source-id: 58a161591f46d0b7ab1ab795cf4633149beb7fcb * Mirror ABI types and helpers in the sandbox Summary: The layout of data structures in the sandbox is different than that on the host. In order to make it more convenient to consume and create these data structures, create a full mirror of all the `HermesABI*` types such that their layout matches what it would have in the sandbox. When passing/returning a value from the sandbox, it just needs to be cast to one of these types to access its fields. Reviewed By: avp Differential Revision: D52558676 fbshipit-source-id: 2e88e294c7c827959e304381cc135d354bc0dc51 * Store WeakRefSlot in ManagedChunkList Summary: ManagedChunkList can automatically manage free slots, and shrink more effectively than std::deque. It help reduce the necessary work in GC. Reviewed By: neildhar Differential Revision: D51048229 fbshipit-source-id: 10f8c0059fe32dd98eda67db93eeba6f58ea0c6a * Enforce unique ownership of WeakRefs Summary: Each WeakRef uniquely owns a WeakRefSlot, and frees the slot only when destroying the WeakRef. Reviewed By: neildhar Differential Revision: D38065776 fbshipit-source-id: 8283dc22d03e653ccf9d11a9f713cc7ca808b309 * Remove concurrent marking of WeakRefs (#1243) Summary: Pull Request resolved: https://github.com/facebook/hermes/pull/1243 Remove all WeakRef marking functions and weakRefMutex_. Reviewed By: neildhar Differential Revision: D38077265 fbshipit-source-id: 90693c81ce4f5ca168097a3157ccb6ba6da77dd0 * Implement a helper for function type signatures Summary: Function pointers in the sandbox are just indices into a function pointer table. The table also includes a type signature encoded as a `wasm_rt_func_type_t`, which is used to verify that the function being retrieved has the expected type (since it would be unsafe to call it if the types do not match). So whenever we add a function to the table, or we try to retrieve a function, it is necessary to construct its corresponding `wasm_rt_func_type_t` to populate/check the stored type. This results in a lot of boilerplate, and is error prone since we need to manually ensure that the constructed `wasm_rt_func_type_t` matches the actual signature of the function. This diff defines a template that performs the conversion from a function signature to a `wasm_rt_func_type_t` automatically, by decomposing the function type and constructing the right call to `wasm2c_hermes_get_func_type`. Reviewed By: avp Differential Revision: D52558681 fbshipit-source-id: 84f13bdf5a1cbde4a49f89fb70ad4c861892ec87 * Implement utilities for pointers and allocations in sandbox memory Summary: Implement some utilities to make it easier to interact with pointers into the sandbox. Since pointers are just `uint32`s, they convey no type information and are annoying to dereference. This diff defines a `Ptr` template, and subclasses, that allow you to treat the pointer like a reference to the underlying object. Note that this is safer than directly holding a pointer to the underlying memory, because the sandbox heap can move when it grows. The subclasses make it convenient to allocate data on the stack/heap for the duration of the implementation of JSI functions. Reviewed By: avp Differential Revision: D52558679 fbshipit-source-id: 3e189388861a517897288cc90a31f483e25335c6 * Create a sandbox module tied to each runtime Summary: Instantiate the w2c_hermes module for each instance of a `HermesSandboxRuntime`. This is the execution context for the sandbox, providing things like the heap, stack, and tables. While it is technically possible to instantiate multiple runtimes in a single module, for now, just maintain one module per runtime. This uses a base class instead of a field to make it convenient and efficient to obtain the module from a `HermesSandboxRuntime *` and vice versa. Reviewed By: avp Differential Revision: D52558675 fbshipit-source-id: c880f7f4700e1963e0ce3de8a3beff09378b6449 * Create and destroy the sandboxed runtime Summary: Instantiate a runtime object through the ABI by retrieving the vtable and calling `make_hermes_runtime`. The object is owned by the JSI runtime and is released on destruction. Read out the vtable fields as correctly typed function pointers to populate the mirrored vtable `vt_`. These will be the primary mechanism for calling into the sandbox. Reviewed By: avp Differential Revision: D52558677 fbshipit-source-id: 770d97291a6985d2b62f747b0c3b804caef5b56c * Implement GrowableBuffer Summary: Implement `GrowableBuffer`, allowing the sandbox to return variable length data (for now it is just strings). This also requires some general utilities and patterns that are used to perform allocations and expose functionality to the runtime. Reviewed By: avp Differential Revision: D52558678 fbshipit-source-id: 6e1790eb2a6010e10b65a240960ac64f17eb98ba * Implement values and exceptions Summary: Implement passing values to/from the sandbox and retrieving exceptions. This mostly mirrors the equivalent implementation in `HermesABIRuntimeWrapper`. Reviewed By: avp Differential Revision: D52558680 fbshipit-source-id: 834c15604d46458708a696ba54479f4e5e10493f * Expose the time and randomness to the sandbox Summary: Add implementations for the imported time and randomness functions. Reviewed By: avp Differential Revision: D52558753 fbshipit-source-id: fdc8e4c757c24596f18a2e04c6847018e055022b * Implement evaluateJavaScript in the sandbox Summary: Implement the buffer API, and use it to implement `evaluateJavaScript`. Reviewed By: ftanuma Differential Revision: D48086020 fbshipit-source-id: ee9472b7622f5602c5dd42ce11533c08f7c19489 * Implement most JSI functionality Summary: Add basic implementations for most of JSI on top of the sandbox. This excludes things like HostObject, HostFunction, and NativeState which require a little more work. Reviewed By: ftanuma Differential Revision: D52558754 fbshipit-source-id: b323d5d30f3c72f10d636038ed4cff3770a2d420 * Implement NativeState, HostFunction, and HostObject Summary: Add implementations for exposing NativeState, HostFunction, and HostObject to the sandbox. This also adds an indirection mechanism for accessing them with an index, to avoid storing the native pointers in the sandbox heap (which may get corrupted). Reviewed By: avp Differential Revision: D52558752 fbshipit-source-id: fb5be97bccde96374def8594559e78f48dbca84a * Run API tests against the sandbox runtime (#1248) Summary: Pull Request resolved: https://github.com/facebook/hermes/pull/1248 X-link: https://github.com/facebook/react-native/pull/42264 Add a buck build for the sandbox, and run our existing API tests against it. Reviewed By: avp Differential Revision: D48086019 fbshipit-source-id: 2ee2eca93e27557d2609eaaec2fce3218d8b873f * Fix $ReadOnlyMap arity bug, add tests Summary: `flow-api-translator` currently expects `$ReadOnlyMap` to have only one type argument, but it actually takes two. Here we fix that and also add tests for `$ReadOnlyMap` and `$ReadOnlySet`. Reviewed By: pieterv Differential Revision: D52784895 fbshipit-source-id: fa8a3018dfc58e4ca07c797c990c80c275c2407c * Introduce AsyncDebuggerAPI Summary: Adding a new class AsyncDebuggerAPI that wraps the existing DebuggerAPI. This class extracts some core concepts from the existing CDPHandler so that we have a class that's not tied to CDP. The main things that this class enables are: 1) Exposes an interrupt API and guarantees those interrupt callbacks will be called exactly once. 2) Turns the didPause interaction into an asynchronous one. Consumers of this class will register DebuggerEventCallback but isn't expected to decide on a next debugger::Command while handling that callback. 3) Adds an API for unpausing the JavaScript program after a DebuggerEventCallback has been invoked. Together with #2, this allows someone to implement a debugging solution like CDP that's asynchronous in nature. The reason to introduce this class is so that we can contain most of the multithread complexity in one place. Rather than having every function in CDPHandler having to think about multithreading, CDPHandler can be simplified. Reviewed By: mattbfb Differential Revision: D51595285 fbshipit-source-id: f4bfaa9daf13339016e2ee0ac347272eb67e3c54 * Add tests for AsyncDebuggerAPI Summary: Adding tests for AsyncDebuggerAPI. Reviewed By: mattbfb Differential Revision: D51768909 fbshipit-source-id: 17243cca4d4ae0a82337ccb6498b54f4c44628fa * Fix build when HERMES_ENABLE_DEBUGGER=0 (#1254) Summary: Pull Request resolved: https://github.com/facebook/hermes/pull/1254 Taking the same strategy as DebuggerAPI by stubbing out all functionality in AsyncDebuggerAPI when `HERMES_ENABLE_DEBUGGER=0`. Reviewed By: mattbfb Differential Revision: D52812969 fbshipit-source-id: 7fb05dbe3b92738b715e10f66d2e28d59dc42cf5 * btoa implementation (#1255) Summary: Pull Request resolved: https://github.com/facebook/hermes/pull/1255 Implement [btoa](https://html.spec.whatwg.org/multipage/webappapis.html#atob) utility function for encoding a string to base64. This implementation doesn't follow the HTML spec 100% in that for error cases, the code doesn't throw DOMException. Existing alternatives people use with Hermes simply throw Error, which is what this code throws as well. Reviewed By: avp Differential Revision: D51876325 fbshipit-source-id: 085aa069a761d093fd9e504c0478ee18a36e8d34 * atob implementation (#1256) Summary: Pull Request resolved: https://github.com/facebook/hermes/pull/1256 Implement [atob](https://html.spec.whatwg.org/multipage/webappapis.html#atob) utility function for decoding a base64 string. This implementation doesn't follow the HTML spec 100% in that for error cases, the code doesn't throw DOMException. Existing alternatives people use with Hermes simply throw Error, which is what this code throws as well. Reviewed By: avp Differential Revision: D52181353 fbshipit-source-id: c90ec95e1ed3b44a7668a6ae4071df536bb31a71 * Regenerate sandbox code Summary: Re-generate the sandbox from the following: emsdk 3.1.39 wasm2c 1.0.33 git revision: 005897de9ac561b02ace6a61885d75e397491819 Reviewed By: tmikov Differential Revision: D52807947 fbshipit-source-id: 39b6af111ab2104ece6c60a019c115aa33f644ba * Check bounds on data pointer in GrowableBufferImpl::getString Summary: This was missing the third parameter to the `Ptr` constructor, which specifies the size of the memory region being accessed. Adding it ensures that the bounds check applies to the entire region. Reviewed By: tmikov Differential Revision: D52807948 fbshipit-source-id: f4629e001e7bba49ee1670f204d30b93faab2d41 * Remove regex breakpoints Summary: Remove handling of URL regexes. This functionality is not not used in our current configurations. The only reference to regex breakpoints in Chrome DevTools appears to be for debugging a NodeJS target on Windows, when running scripts from local filepaths (it's used to work around the case insensitivity of windows paths). Our use cases only make use of setting breakpoints by URL or by script ID. This change makes the subsequent stack simpler, and removes use of `std::regex`, which is considered problematic. Reviewed By: dannysu Differential Revision: D51674836 fbshipit-source-id: e547738cbe5b0f571f87d8a206002ff2852231f2 * Add end-to-end CI for sandbox (#1252) Summary: Add a CI job that recreates the sandbox from source and tests that it works. Pull Request resolved: https://github.com/facebook/hermes/pull/1252 Reviewed By: avp Differential Revision: D52823512 Pulled By: neildhar fbshipit-source-id: 7c9ef620a78a95db4e7b3608372e513ddb134f3c * Avoid potential overflow in pointer bounds check Summary: This check could overflow on 32 bit platforms if `n` is large. Cast it to `u64` before checking to ensure that the math is done with 64 bit numbers to avoid overflow. Reviewed By: tmikov Differential Revision: D52807946 fbshipit-source-id: 3adc2f898588b046915966f4d97c8377d1a3d75b * Fixed symbol conflicts when using identical function and method names in an ES6 class (#1257) Summary: This change fixes an issue that could occur when calling a function from a method that has the same name. Consider this example: ```js function myMethod() { console.log('Hello from function'); } class MyClass { myMethod() { myMethod(); } } ``` In this scenario, `Hello from function` would not be printed when `instance.myMethod()` is called as the method would be called recursively instead of the function that is available in the outer scope. ## Changes - Added test showcasing the issue - Always create an anonymous function for methods (maybe there is a way to make the identifier private instead?), so that the method body cannot recursively refers to itself by its name. - Insert `method.name` at the JS level when the method is about to be registered into the class. Pull Request resolved: https://github.com/facebook/hermes/pull/1257 Test Plan: All tests passes. <!-- Demonstrate the code is solid. Example: The…
Summary
This change eliminates repeated calls to
ucol_open
anducol_close
inhermes::platform_unicode::localeCompare
for HERMES_PLATFORM_UNICODE_ICU. On a sample sort.js(that sorted 30k strings using localeCompare), the runtime goes down from ~500 ms to ~120ms.Before:
I observed in my trace that ucol_open and ucol_close was called in every localeCompare invocation and each ucol_open took around 500-900 ns. ucol_close is tiny ~100ish ns in each call.
Note that the first call to ucol_open, it takes around 100us even after applying this diff.
Here is localeCompare call stack before the patch:
After
After making UCollator construction static, we avoid repeated ucol_open and ucol_close(except during static initialization) thus making the sort.js sorting fast.
Here is the localeCompare stack after the patch:
Looking at the code, i found out that HERMES_PLATFORM_UNICODE_ICU is not used in Android/iOS but can make desktop usage faster (it it useful??).
Here is the sort.js script which i got from one of the issues/posts in hermes.
Test Plan
Execute sort.js before applying this patch
Execute sort.js after applying this patch
Run check-hermes: