Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 37 additions & 7 deletions docs/bootstrap-inventory.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ Regenerate: `php script/bootstrap-inventory.php`

| Metric | Count |
|--------|------:|
| PHP files on vm.php path | 8588 |
| Phase A inventory files (M2 ratio SSOT) | 8588 |
| PHP files on vm.php path | 8592 |
| Phase A inventory files (M2 ratio SSOT) | 8592 |
| Phase A ratio-deferred paths | 0 |
| Source constructs flagged (blockers) | 0 |
| Source constructs flagged (warnings) | 26775 |
| Source constructs flagged (warnings) | 26785 |

## Compiler CFG gaps (`lib/Compiler.php`)

Expand Down Expand Up @@ -6722,6 +6722,7 @@ Rank live CFG gaps across inventory files: `php script/bootstrap-inventory-triag
| `lib/JIT/Builtin/WeakRefRegistryRuntime.php` | 0 | 2 |
| `lib/JIT/Builtin/WeakRefRuntime.php` | 0 | 1 |
| `lib/JIT/Builtin/WeakRefSetup.php` | 0 | 1 |
| `lib/JIT/Builtin/ZendCompareLlvm.php` | 0 | 4 |
| `lib/JIT/Builtin/ZendDoubleStringRuntime.php` | 0 | 1 |
| `lib/JIT/Builtin/ZipArchiveEmbedBridge.php` | 0 | 1 |
| `lib/JIT/Builtin/ZlibRuntime.php` | 0 | 1 |
Expand Down Expand Up @@ -7437,6 +7438,7 @@ Rank live CFG gaps across inventory files: `php script/bootstrap-inventory-triag
| `lib/JIT/InstanceOfHelper.php` | 0 | 6 |
| `lib/JIT/InstancePropertyVisibilityJitGuard.php` | 0 | 2 |
| `lib/JIT/InstantiableClassJitGuard.php` | 0 | 1 |
| `lib/JIT/IntRadixSortLlvm.php` | 0 | 2 |
| `lib/JIT/InternalStrictArg.php` | 0 | 1 |
| `lib/JIT/IntersectionParamCheck.php` | 0 | 3 |
| `lib/JIT/IntlExtensionHooks.php` | 0 | 1 |
Expand Down Expand Up @@ -7504,6 +7506,7 @@ Rank live CFG gaps across inventory files: `php script/bootstrap-inventory-triag
| `lib/JIT/MbConvertVariablesLlvm.php` | 0 | 2 |
| `lib/JIT/McjitEmbedHostEcho.php` | 0 | 2 |
| `lib/JIT/McjitEmbedRuntime.php` | 0 | 1 |
| `lib/JIT/MergeSortLlvm.php` | 0 | 1 |
| `lib/JIT/MultipleIteratorZipLlvm.php` | 0 | 4 |
| `lib/JIT/NamedArgs.php` | 0 | 11 |
| `lib/JIT/NamedOptionalCallArgs.php` | 0 | 2 |
Expand Down Expand Up @@ -7628,6 +7631,7 @@ Rank live CFG gaps across inventory files: `php script/bootstrap-inventory-triag
| `lib/JIT/XmlWriterInstanceMethodJit.php` | 0 | 5 |
| `lib/JIT/XslExtensionHooks.php` | 0 | 1 |
| `lib/JIT/XsltInstanceMethodJit.php` | 0 | 2 |
| `lib/JIT/ZendSortLlvm.php` | 0 | 3 |
| `lib/JIT/ZipExtensionHooks.php` | 0 | 1 |
| `lib/JitMcjitEmbed.php` | 0 | 1 |
| `lib/JitVmLoweringPolicy.php` | 0 | 1 |
Expand Down Expand Up @@ -56263,8 +56267,8 @@ Rank live CFG gaps across inventory files: `php script/bootstrap-inventory-triag
### `lib/JIT/Builtin/Type/HashTable.php`

**Warnings** (review for bootstrap subset):
- 77 class method(s)
- 2 closure(s)
- 81 class method(s)
- 14 closure(s)

### `lib/JIT/Builtin/Type/HashTableDtorLlvm.php`

Expand Down Expand Up @@ -56541,6 +56545,14 @@ Rank live CFG gaps across inventory files: `php script/bootstrap-inventory-triag
**Warnings** (review for bootstrap subset):
- 4 class method(s)

### `lib/JIT/Builtin/ZendCompareLlvm.php`

**Warnings** (review for bootstrap subset):
- new self (line 65)
- new self (line 84)
- 26 class method(s)
- 17 closure(s)

### `lib/JIT/Builtin/ZendDoubleStringRuntime.php`

**Warnings** (review for bootstrap subset):
Expand Down Expand Up @@ -60526,8 +60538,8 @@ Rank live CFG gaps across inventory files: `php script/bootstrap-inventory-triag

**Warnings** (review for bootstrap subset):
- trait ContextModuleOptimizationPasses (line 25)
- 7 class method(s)
- 1 closure(s)
- 9 class method(s)
- 3 closure(s)

### `lib/JIT/ContextModuleVerify.php`

Expand Down Expand Up @@ -61314,6 +61326,12 @@ Rank live CFG gaps across inventory files: `php script/bootstrap-inventory-triag
**Warnings** (review for bootstrap subset):
- 3 class method(s)

### `lib/JIT/IntRadixSortLlvm.php`

**Warnings** (review for bootstrap subset):
- 1 class method(s)
- 8 closure(s)

### `lib/JIT/InternalStrictArg.php`

**Warnings** (review for bootstrap subset):
Expand Down Expand Up @@ -61757,6 +61775,11 @@ Rank live CFG gaps across inventory files: `php script/bootstrap-inventory-triag
**Warnings** (review for bootstrap subset):
- 5 class method(s)

### `lib/JIT/MergeSortLlvm.php`

**Warnings** (review for bootstrap subset):
- 3 class method(s)

### `lib/JIT/MultipleIteratorZipLlvm.php`

**Warnings** (review for bootstrap subset):
Expand Down Expand Up @@ -62603,6 +62626,13 @@ Rank live CFG gaps across inventory files: `php script/bootstrap-inventory-triag
- new Call\XsltMethod (line 45)
- 3 class method(s)

### `lib/JIT/ZendSortLlvm.php`

**Warnings** (review for bootstrap subset):
- new self (line 57)
- 17 class method(s)
- 3 closure(s)

### `lib/JIT/ZipExtensionHooks.php`

**Warnings** (review for bootstrap subset):
Expand Down
8 changes: 6 additions & 2 deletions docs/bootstrap-profile.json
Original file line number Diff line number Diff line change
Expand Up @@ -6809,6 +6809,7 @@
"lib/JIT/Builtin/WeakRefRegistryRuntime.php",
"lib/JIT/Builtin/WeakRefRuntime.php",
"lib/JIT/Builtin/WeakRefSetup.php",
"lib/JIT/Builtin/ZendCompareLlvm.php",
"lib/JIT/Builtin/ZendDoubleStringRuntime.php",
"lib/JIT/Builtin/ZipArchiveEmbedBridge.php",
"lib/JIT/Builtin/ZlibRuntime.php",
Expand Down Expand Up @@ -7528,6 +7529,7 @@
"lib/JIT/InstanceOfHelper.php",
"lib/JIT/InstancePropertyVisibilityJitGuard.php",
"lib/JIT/InstantiableClassJitGuard.php",
"lib/JIT/IntRadixSortLlvm.php",
"lib/JIT/InternalStrictArg.php",
"lib/JIT/IntersectionParamCheck.php",
"lib/JIT/IntlExtensionHooks.php",
Expand Down Expand Up @@ -7595,6 +7597,7 @@
"lib/JIT/MbConvertVariablesLlvm.php",
"lib/JIT/McjitEmbedHostEcho.php",
"lib/JIT/McjitEmbedRuntime.php",
"lib/JIT/MergeSortLlvm.php",
"lib/JIT/MultipleIteratorZipLlvm.php",
"lib/JIT/NamedArgs.php",
"lib/JIT/NamedOptionalCallArgs.php",
Expand Down Expand Up @@ -7720,6 +7723,7 @@
"lib/JIT/XmlWriterInstanceMethodJit.php",
"lib/JIT/XslExtensionHooks.php",
"lib/JIT/XsltInstanceMethodJit.php",
"lib/JIT/ZendSortLlvm.php",
"lib/JIT/ZipExtensionHooks.php",
"lib/JitMcjitEmbed.php",
"lib/JitVmLoweringPolicy.php",
Expand Down Expand Up @@ -8822,9 +8826,9 @@
"test/bootstrap-aot/lib_opcode/main.php"
],
"totals": {
"inventory_files": 8588,
"inventory_files": 8592,
"excluded": 0,
"eligible": 8588,
"eligible": 8592,
"aot_lint_targets": 113,
"aot_link_targets": 100,
"aot_link_lib_targets": 1
Expand Down
54 changes: 44 additions & 10 deletions lib/JIT/Builtin/NumericStringLlvm.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@
* IS_LONG, everything else numeric IS_DOUBLE (zend_strtod — libc strtod here, same
* result for the decimal forms this accepts).
*
* Returns {@see self::NUMERIC} (whole string numeric), {@see self::LEADING} (numeric
* prefix followed by garbage — callers emit "A non-numeric value encountered") or
* Returns {@see self::NUMERIC} (whole string numeric), {@see self::NUMERIC_OFLOW_POS} /
* {@see self::NUMERIC_OFLOW_NEG} (whole string numeric, integer-shaped, overflowed
* zend_long — php-src's `oflow` out-param), {@see self::LEADING} (numeric prefix followed
* by garbage — callers emit "A non-numeric value encountered") or
* {@see self::NON_NUMERIC} (out untouched — callers throw the operator's TypeError).
*/
final class NumericStringLlvm
Expand All @@ -33,6 +35,12 @@ final class NumericStringLlvm

public const NON_NUMERIC = 2;

/** Whole string numeric, integer-shaped but beyond ZEND_LONG_MAX (out is IS_DOUBLE). */
public const NUMERIC_OFLOW_POS = 3;

/** Whole string numeric, integer-shaped but below ZEND_LONG_MIN (out is IS_DOUBLE). */
public const NUMERIC_OFLOW_NEG = 4;

/** @return Value i32 status */
public static function call(Context $context, Value $str, Value $out): Value
{
Expand Down Expand Up @@ -80,6 +88,21 @@ private static function ensure(Context $context): Value\Function_
$len = $b->load($b->structGep($str, $map['length']));
$pos = $b->alloca($i64);
$b->store($zero, $pos);
// php-src's fast reject: every byte that can start a numeric string (whitespace,
// sign, '.', digit) is <= '9'.
$scan = $fn->appendBasicBlock('scan');
$reject = $fn->appendBasicBlock('fast_reject');
$b->branchIf(
$b->bitwiseAnd(
$b->icmp(Builder::INT_UGT, $len, $zero),
$b->icmp(Builder::INT_UGT, $b->load($data), $ch('9'))
),
$reject,
$scan
);
$b->positionAtEnd($reject);
$b->returnValue($i32->constInt(self::NON_NUMERIC, false));
$b->positionAtEnd($scan);

// byte at index (caller guarantees idx < len)
$at = static fn (Value $idx): Value => $b->load($b->gep($data, $idx));
Expand Down Expand Up @@ -220,6 +243,12 @@ private static function ensure(Context $context): Value\Function_

// Accumulate negatively so ZEND_LONG_MIN parses; overflow → double (zend_strtod).
$b->positionAtEnd($longPath);
$negative = $b->icmp(
Builder::INT_EQ,
$b->select($b->icmp(Builder::INT_UGT, $digitsStart, $start), $at($start), $ch('+')),
$ch('-')
);
$oflowPath = $fn->appendBasicBlock('oflow_path');
$accSlot = $b->alloca($i64);
$idxSlot = $b->alloca($i64);
$b->store($zero, $accSlot);
Expand All @@ -236,22 +265,17 @@ private static function ensure(Context $context): Value\Function_
$b->positionAtEnd($accBody);
$digit = $b->zExt($b->sub($at($idx), $ch('0')), $i64);
$mul = $b->call($smul, $b->load($accSlot), $i64->constInt(10, false));
$b->branchIf($b->extractValue($mul, 1), $doublePath, $accMulOk);
$b->branchIf($b->extractValue($mul, 1), $oflowPath, $accMulOk);
$b->positionAtEnd($accMulOk);
$sub = $b->call($ssub, $b->extractValue($mul, 0), $digit);
$b->branchIf($b->extractValue($sub, 1), $doublePath, $accStep);
$b->branchIf($b->extractValue($sub, 1), $oflowPath, $accStep);
$b->positionAtEnd($accStep);
$b->store($b->extractValue($sub, 0), $accSlot);
$b->store($b->add($idx, $one), $idxSlot);
$b->branch($accHead);

$b->positionAtEnd($accDone);
$acc = $b->load($accSlot);
$negative = $b->icmp(
Builder::INT_EQ,
$b->select($b->icmp(Builder::INT_UGT, $digitsStart, $start), $at($start), $ch('+')),
$ch('-')
);
$negWrite = $fn->appendBasicBlock('neg_write');
$posCheck = $fn->appendBasicBlock('pos_check');
$posWrite = $fn->appendBasicBlock('pos_write');
Expand All @@ -261,11 +285,21 @@ private static function ensure(Context $context): Value\Function_
$b->returnValue($status);
$b->positionAtEnd($posCheck);
$minLong = $i64->constInt(\PHP_INT_MIN, true);
$b->branchIf($b->icmp(Builder::INT_EQ, $acc, $minLong), $doublePath, $posWrite);
$b->branchIf($b->icmp(Builder::INT_EQ, $acc, $minLong), $oflowPath, $posWrite);
$b->positionAtEnd($posWrite);
$b->call($writeLong, $out, $b->sub($zero, $acc));
$b->returnValue($status);

// Integer-shaped but out of zend_long range: double value + php-src's oflow sign.
$b->positionAtEnd($oflowPath);
$od = $b->call($strtod, $b->gep($data, $start), $context->getTypeFromString('int8**')->constNull());
$b->call($writeDouble, $out, $od);
$b->returnValue($b->select(
$b->icmp(Builder::INT_EQ, $status, $i32->constInt(self::NUMERIC, false)),
$b->select($negative, $i32->constInt(self::NUMERIC_OFLOW_NEG, false), $i32->constInt(self::NUMERIC_OFLOW_POS, false)),
$status
));

// strtod stops at the first byte it cannot use, which is at or before numEnd for
// every form accepted above (no hex/inf/nan can reach here).
$b->positionAtEnd($doublePath);
Expand Down
Loading
Loading