Skip to content

Comments

fix: nullish coalescing operator precedence#240

Merged
Boshen merged 1 commit intooxc-project:mainfrom
ashsearle:fix/nullish-coalescing-precedence
Apr 1, 2023
Merged

fix: nullish coalescing operator precedence#240
Boshen merged 1 commit intooxc-project:mainfrom
ashsearle:fix/nullish-coalescing-precedence

Conversation

@ashsearle
Copy link
Contributor

Fix one error copying operator precedence values from MDN's table

The mistake gave in and ?? the same precedence. Add a test that should have failed (and with this PR it now does.)

@Boshen
Copy link
Member

Boshen commented Apr 1, 2023

Neat! Did you find this from a real codebase?

@Boshen Boshen merged commit ab2ef4f into oxc-project:main Apr 1, 2023
@Boshen Boshen added first-pr A-linter Area - Linter labels Apr 1, 2023
@Boshen Boshen added this to the 0.0.3 milestone Apr 1, 2023
@Boshen
Copy link
Member

Boshen commented Apr 1, 2023

Thank you for your first PR and trying out oxc!

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

A-linter Area - Linter

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants