Skip to content

fix(oxc_parser): don't parse ambiguous await with parse_await_expression#39

Merged
Boshen merged 1 commit into
oxc-project:mainfrom
jason89521:fix/valid-script-await-as-lhs
Feb 24, 2023
Merged

fix(oxc_parser): don't parse ambiguous await with parse_await_expression#39
Boshen merged 1 commit into
oxc-project:mainfrom
jason89521:fix/valid-script-await-as-lhs

Conversation

@jason89521

@jason89521 jason89521 commented Feb 23, 2023

Copy link
Copy Markdown
Contributor

Description

In js, the await can be used as a variable.In this case, we shouldn't parse the await with the parse_await_expression.

Additional information

In babel's parser, they filter out +, -, (, [, of and so on, but if I filter out the [, our parser cannot pass some of the top-level await in test262's test cases.

Related issue

#36

References

babel/babel#15127
https://github.com/babel/babel/blob/main/packages/babel-parser/src/parser/expression.ts#L2882-L2894

@Boshen

Boshen commented Feb 23, 2023

Copy link
Copy Markdown
Member

but if I filter out the [, our parser cannot pass some of the top-level await in test262's test cases

I think this is because you need to be aware of the [+Await] context here. This grammar only applies for non-await contexts.

We can parse for both contexts, and throw a nicer error message once the linter is ready.

As for the implementation, can you move the check inside is_await_expression?

@Boshen Boshen self-requested a review February 23, 2023 09:27
@jason89521 jason89521 force-pushed the fix/valid-script-await-as-lhs branch from 9610f94 to c934982 Compare February 24, 2023 03:54
@Boshen Boshen merged commit 457e85b into oxc-project:main Feb 24, 2023
@jason89521 jason89521 deleted the fix/valid-script-await-as-lhs branch February 24, 2023 13:14
Boshen added a commit that referenced this pull request Oct 7, 2025
Replace multi-function calls and multiple enum variant checks with simple range checks, reducing assembly instructions in hot paths.

## Changes

**`is_any_keyword()`**:
- Before: Called 4 separate functions (`is_reserved_keyword()`, `is_contextual_keyword()`, `is_strict_mode_contextual_keyword()`, `is_future_reserved_keyword()`) checking 70+ enum variants with early returns
- After: Single range check `Await..=Yield` since all keywords are contiguous in the enum

**`is_number()`**:
- Before: Matched 11 separate enum variants
- After: Single range check `Decimal..=HexBigInt` since all numeric literals are contiguous

## Assembly Impact

Multi-function approach generated **5 instructions** with complex bitmask setup:
```asm
mov   x8, #992
movk  x8, #992, lsl #16
movk  x8, #240, lsl #32
lsr   x8, x8, x0
and   w0, w8, #0x1
```

Range check generates **4 instructions** with simple arithmetic:
```asm
and   w8, w0, #0xff
sub   w8, w8, #5
cmp   w8, #39
cset  w0, lo
```

## Performance

- `is_any_keyword()` is called from `advance()` on **every single token**
- 20% fewer instructions (5 → 4)
- Simpler logic enables better branch prediction
- Eliminates complex constant loading

Added tests to verify enum layout assumptions remain valid.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Boshen added a commit that referenced this pull request Oct 7, 2025
Replace multi-function calls and multiple enum variant checks with simple range checks, reducing assembly instructions in hot paths.

## Changes

**`is_any_keyword()`**:
- Before: Called 4 separate functions (`is_reserved_keyword()`, `is_contextual_keyword()`, `is_strict_mode_contextual_keyword()`, `is_future_reserved_keyword()`) checking 70+ enum variants with early returns
- After: Single range check `Await..=Yield` since all keywords are contiguous in the enum

**`is_number()`**:
- Before: Matched 11 separate enum variants
- After: Single range check `Decimal..=HexBigInt` since all numeric literals are contiguous

## Assembly Impact

Multi-function approach generated **5 instructions** with complex bitmask setup:
```asm
mov   x8, #992
movk  x8, #992, lsl #16
movk  x8, #240, lsl #32
lsr   x8, x8, x0
and   w0, w8, #0x1
```

Range check generates **4 instructions** with simple arithmetic:
```asm
and   w8, w0, #0xff
sub   w8, w8, #5
cmp   w8, #39
cset  w0, lo
```

## Performance

- `is_any_keyword()` is called from `advance()` on **every single token**
- 20% fewer instructions (5 → 4)
- Simpler logic enables better branch prediction
- Eliminates complex constant loading

Added tests to verify enum layout assumptions remain valid.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Boshen added a commit that referenced this pull request Oct 7, 2025
Replace multi-function calls and multiple enum variant checks with simple range checks, reducing assembly instructions in hot paths.

## Changes

**`is_any_keyword()`**:
- Before: Called 4 separate functions (`is_reserved_keyword()`, `is_contextual_keyword()`, `is_strict_mode_contextual_keyword()`, `is_future_reserved_keyword()`) checking 70+ enum variants with early returns
- After: Single range check `Await..=Yield` since all keywords are contiguous in the enum

**`is_number()`**:
- Before: Matched 11 separate enum variants
- After: Single range check `Decimal..=HexBigInt` since all numeric literals are contiguous

## Assembly Impact

Multi-function approach generated **5 instructions** with complex bitmask setup:
```asm
mov   x8, #992
movk  x8, #992, lsl #16
movk  x8, #240, lsl #32
lsr   x8, x8, x0
and   w0, w8, #0x1
```

Range check generates **4 instructions** with simple arithmetic:
```asm
and   w8, w0, #0xff
sub   w8, w8, #5
cmp   w8, #39
cset  w0, lo
```

## Performance

- `is_any_keyword()` is called from `advance()` on **every single token**
- 20% fewer instructions (5 → 4)
- Simpler logic enables better branch prediction
- Eliminates complex constant loading

Added tests to verify enum layout assumptions remain valid.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
graphite-app Bot pushed a commit that referenced this pull request Oct 7, 2025
…14410)

## Summary

Replace multi-function calls and multiple enum variant checks with simple range checks, reducing assembly instructions in hot paths.

## Changes

### `is_any_keyword()`
**Before**: Called 4 separate functions checking 70+ enum variants:
- `is_reserved_keyword()` - 38 variants
- `is_contextual_keyword()` - 39 variants
- `is_strict_mode_contextual_keyword()` - 8 variants
- `is_future_reserved_keyword()` - 7 variants

**After**: Single range check `Await..=Yield` since all keywords are contiguous in the enum

### `is_number()`
**Before**: Matched 11 separate enum variants
**After**: Single range check `Decimal..=HexBigInt` since numeric literals are contiguous

## Assembly Analysis

### Before (with scattered checks)
```asm
mov   x8, #992              ; Load bitmask constant
movk  x8, #992, lsl #16     ; More bitmask setup
movk  x8, #240, lsl #32     ; Even more bitmask setup
lsr   x8, x8, x0            ; Shift by kind value
and   w0, w8, #0x1          ; Extract result bit
```
**5 instructions** with complex constant loading

### After (with range check)
```asm
and   w8, w0, #0xff         ; Extract byte
sub   w8, w8, #5            ; Subtract range start
cmp   w8, #39               ; Compare to range size
cset  w0, lo                ; Set result
```
**4 instructions** with simple arithmetic

## Performance Impact

- **20% fewer instructions** (5 → 4)
- **Simpler logic** = better CPU pipeline utilization
- **No complex constants** = smaller code size
- **Better branch prediction** with single comparison

This is particularly important because:
- `is_any_keyword()` is called from `advance()` on **every single token**
- This is one of the hottest code paths in the entire parser

## Testing

Added unit tests to verify that:
- All keywords remain contiguous in the enum (`Await..=Yield`)
- All numeric literals remain contiguous (`Decimal..=HexBigInt`)

These tests will catch any future enum reordering that would break the optimization.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
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.

2 participants