Skip to content
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

Add with statement support #1571

Open
wants to merge 2 commits into
base: static_h
Choose a base branch
from

Conversation

trossimel-sc
Copy link

@trossimel-sc trossimel-sc commented Nov 27, 2024

Summary

This PR introduces support for the with statement via IR

  • Identifiers within a with statement are transformed into a series of conditional chain. Each condition checks the presence of a key in the object properties, and accesses it if present. This is done through createConditionalChainImpl
  • We need to keep track of each with statement depth. Hermes uses a task queue to lazily compile functions, and for this reason, we also need to copy the with depths when adding the declaration to the queue.

The changes are designed to minimize disruption. The logic only activates when a with statement is present, and the bulk of the implementation is located in a separate file, ESTreeIRGen-with.

Test Plan

  • Added a unit test covering most common scenarios
  • Test262 result on with statements tests: 92.98%.

This commit introduces support for the with statement via IR, by replacing the previous AST transformation with a more robust alternative.

**Logic:**
- Identifiers are replaced with a conditional chain that checks the presence of a key in the object properties.
- We need to keep track of each `with` statement depth. Hermes also uses a task queue to lazily compile functions, and for this reason, we also need to copy the `with` depths when adding the declaration to the queue.
- Compared to an AST transformation, `buildConditionalChain` any call to the Builder will be executed in the same called order. This means we cannot generate the nested conditional chain starting from the inner condition.

**Test262 results:**  92.98%.
Cooled by trossimel
@facebook-github-bot
Copy link
Contributor

Hi @trossimel-sc!

Thank you for your pull request and welcome to our community.

Action Required

In 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.

Process

In 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 CLA signed. The tagging process may take up to 1 hour after signing. Please give it that time before contacting us about it.

If you have received this in error or have any questions, please contact us at [email protected]. Thanks!

@trossimel-sc
Copy link
Author

trossimel-sc commented Nov 27, 2024

While the output is correct, I've noticed that when running in debug mode, it occasionally fails with the following message:

Assertion failed: (I->hasOutput() && "Instruction has no output"), function encodeValue, file ISel.cpp, line 264.

And in this case the IR output seems to be incorrectly generated. This issue arises specifically when a store operation is present within the with statement. Here's an example:

let e = 20;
with (obj) {
    e = 30;
}

Is there a straightforward way to handle this case? I'm not very familiar with Hermes IR, so I'm unsure why this failure occurs, while the output is still correct. Thank you for your help!

Please feel free to respond once my CLA is signed, if needed. —I hope this process won't take much longer. 🫤

@trossimel-sc trossimel-sc changed the title [WIP] Add with statement support Add with statement support Nov 27, 2024
@tmikov
Copy link
Contributor

tmikov commented Nov 29, 2024

@trossimel-sc I haven't reviewed the PR, but I compiled it and looked at the IR output of your example:

  %10 = CallInst (:any) %8: any, empty: any, false: boolean, empty: any, undefined: undefined, undefined: undefined, %9: any, "e": string
  %11 = CondBranchInst %10: any, %BB2, %BB1
%BB1:
  %12 = StoreFrameInst %0: environment, 30: number, [%VS0.e]: any
  %13 = BranchInst %BB3
%BB2:
  %14 = LoadFrameInst (:any) %0: environment, [%VS0.with1]: any
  %15 = StorePropertyLooseInst 30: number, %14: any, "e": string
  %16 = BranchInst %BB3
%BB3:
  %17 = PhiInst (:notype) %15: notype, %BB2, %12: notype, %BB1

You are calling a helper method to check if e exists in the object and branching to either a property store %15 or a variable store %12. The problem is that you are treating these stores as if they have a result and in instruction %17 you are reading this result. Stores have no result, they just have side effects.

AFAICT, instruction %17 is incorrect and more importantly, unnecessary. You don't need to combine the stores with Phi, they have already done their side effect.

BTW, I think that we probably want a new bytecode instruction for this instead of calling a helper, but we can do that incrementally. Also, the helper should just be a "builtin", which is safer and easier to call. But these are details that we can address when we start the review.

(We don't want to start reviewing before we know that we can accept the PR, I hope you understand)

@trossimel-sc
Copy link
Author

Thanks for the response and the assistance @tmikov
Just wanted to update, I'm still waiting for my request to be approved by the company. Unfortunately, it's taking longer than expected, and there's not much I can do except wait for now 🫤

@leotm
Copy link

leotm commented Dec 16, 2024

great work 🎉 adding Fixes: #1056 to description should link the issue to this PR (auto-close on merge)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants