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
16 changes: 11 additions & 5 deletions docs/bootstrap-inventory.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ Regenerate: `php script/bootstrap-inventory.php`

| Metric | Count |
|--------|------:|
| PHP files on vm.php path | 239 |
| PHP files on vm.php path | 240 |
| Source constructs flagged (blockers) | 10 |
| Source constructs flagged (warnings) | 628 |
| Source constructs flagged (warnings) | 629 |

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

Expand All @@ -37,6 +37,7 @@ These `LogicException` messages indicate CFG ops or expressions not yet lowered:
| `ext/standard/JitDate.php` | 0 | 1 |
| `ext/standard/JitEnv.php` | 0 | 1 |
| `ext/standard/JitExplode.php` | 0 | 1 |
| `ext/standard/JitGetallheaders.php` | 0 | 1 |
| `ext/standard/JitHeader.php` | 0 | 1 |
| `ext/standard/JitHex2bin.php` | 0 | 1 |
| `ext/standard/JitHtmlspecialchars.php` | 0 | 1 |
Expand Down Expand Up @@ -292,6 +293,11 @@ These `LogicException` messages indicate CFG ops or expressions not yet lowered:
**Warnings** (review for bootstrap subset):
- 1 class method(s) — PHPCfg Op\Stmt\ClassMethod not lowered in Compiler

### `ext/standard/JitGetallheaders.php`

**Warnings** (review for bootstrap subset):
- 1 class method(s) — PHPCfg Op\Stmt\ClassMethod not lowered in Compiler

### `ext/standard/JitHeader.php`

**Warnings** (review for bootstrap subset):
Expand Down Expand Up @@ -1301,10 +1307,10 @@ These `LogicException` messages indicate CFG ops or expressions not yet lowered:
- new JIT\Call\Native (line 149)
- new ext\standard\boolval (line 268)
- new Variable (line 432)
- new Variable (line 813)
- new Operand\Literal (line 883)
- new Operand\Literal (line 887)
- new Variable (line 821)
- new Operand\Literal (line 891)
- new Operand\Literal (line 895)
- new Operand\Literal (line 899)
- 12 class method(s) — PHPCfg Op\Stmt\ClassMethod not lowered in Compiler

### `lib/JIT/Analyzer.php`
Expand Down
5 changes: 3 additions & 2 deletions docs/bootstrap-profile.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"ext/standard/JitDate.php",
"ext/standard/JitEnv.php",
"ext/standard/JitExplode.php",
"ext/standard/JitGetallheaders.php",
"ext/standard/JitHeader.php",
"ext/standard/JitHex2bin.php",
"ext/standard/JitHtmlspecialchars.php",
Expand Down Expand Up @@ -273,9 +274,9 @@
"test/bootstrap-aot/echo_hello.php"
],
"totals": {
"inventory_files": 239,
"inventory_files": 240,
"excluded": 2,
"eligible": 237,
"eligible": 238,
"aot_lint_targets": 2
}
}
4 changes: 2 additions & 2 deletions docs/capabilities.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Auto-generated by `script/capability-matrix.php`. Do not edit by hand.
| `array_combine` | yes | no | no | standard | doc: VM only; not implemented for JIT in this compiler build |
| `array_fill` | yes | yes | yes | standard | JIT PHPT |
| `array_flip` | yes | no | no | standard | doc: VM only; not implemented for JIT in this compiler build |
| `array_key_exists` | yes | yes | yes | standard | AOT PHPT |
| `array_key_exists` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
| `array_keys` | yes | yes | yes | standard | doc: VM only |
| `array_merge` | yes | yes | yes | standard | doc: VM only |
| `array_pop` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
Expand Down Expand Up @@ -42,7 +42,7 @@ Auto-generated by `script/capability-matrix.php`. Do not edit by hand.
| `floatval` | yes | yes | yes | standard | |
| `floor` | yes | yes | yes | standard | |
| `fmod` | yes | yes | yes | standard | |
| `getallheaders` | yes | no | no | standard | doc: VM only; not implemented for JIT in this compiler build |
| `getallheaders` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
| `getenv` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
| `gettype` | yes | yes | yes | standard | |
| `glob` | yes | yes | yes | standard | |
Expand Down
75 changes: 75 additions & 0 deletions ext/standard/JitGetallheaders.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<?php

declare(strict_types=1);

namespace PHPCompiler\ext\standard;

use PHPCompiler\JIT\Context;
use PHPCompiler\JIT\HashTableHelper;
use PHPCompiler\JIT\SuperglobalInit;
use PHPCompiler\JIT\Variable as JITVariable;
use PHPCompiler\VM\HashTable;
use PHPCompiler\VM\Variable as VMVariable;
use PHPCompiler\Web\Superglobals;
use PHPLLVM\Value;

/**
* LLVM JIT/AOT helper for getallheaders() — copy HTTP_* / CONTENT_* from sg_SERVER.
*/
final class JitGetallheaders
{
public static function invoke(Context $context): Value
{
$result = HashTableHelper::alloc($context);
$serverVar = SuperglobalInit::load($context, '_SERVER');
$serverPtr = $context->helper->loadValue($serverVar);

$vmServer = $context->runtime->vmContext->getSuperglobal('_SERVER');
if (null === $vmServer || VMVariable::TYPE_ARRAY !== $vmServer->type) {
return $result;
}
$table = $vmServer->toArray();
if (!$table instanceof HashTable) {
return $result;
}

foreach ($table->iterateKeyed(true) as [$keyVar, $valueVar]) {
if (VMVariable::TYPE_STRING !== $keyVar->type) {
continue;
}
$serverKey = $keyVar->toString();
$headerName = Superglobals::serverKeyToHeaderName($serverKey);
if (null === $headerName) {
continue;
}
$resolved = $valueVar->resolveIndirect();
if (VMVariable::TYPE_STRING !== $resolved->type) {
continue;
}

$serverKeyStr = $context->builder->load(
$context->constantStringFromString($serverKey)
);
$headerKeyStr = $context->builder->load(
$context->constantStringFromString($headerName)
);
$valueBox = $context->builder->call(
$context->lookupFunction('__hashtable__readStringKeyValue'),
$serverPtr,
$serverKeyStr
);
$valueStr = $context->builder->call(
$context->lookupFunction('__value__readString'),
$valueBox
);
$context->builder->call(
$context->lookupFunction('__hashtable__setStringKeyString'),
$result,
$headerKeyStr,
$valueStr
);
}

return $result;
}
}
8 changes: 6 additions & 2 deletions ext/standard/getallheaders_.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
use PHPLLVM\Value;

/**
* getallheaders() — request headers from $_SERVER HTTP_* entries (VM only; issue #307).
* getallheaders() — request headers from $_SERVER HTTP_* entries (issue #307).
*/
final class getallheaders_ extends Internal
{
Expand All @@ -40,6 +40,10 @@ public function execute(Frame $frame): void

public function call(Context $context, JITVariable ...$args): Value
{
throw new \LogicException('getallheaders() is not implemented for JIT in this compiler build');
if (\count($args) > 0) {
throw new \LogicException('getallheaders() takes no arguments');
}

return JitGetallheaders::invoke($context);
}
}
8 changes: 8 additions & 0 deletions lib/JIT.php
Original file line number Diff line number Diff line change
Expand Up @@ -755,6 +755,14 @@ private function assignOperand(Operand $result, Variable $value): void {
$owned
);

return;
case Variable::TYPE_HASHTABLE:
$this->context->builder->call(
$this->context->lookupFunction('__value__writeHashtable'),
$valueRef,
$this->context->helper->loadValue($value)
);

return;
case Variable::TYPE_VALUE:
$loaded = $this->context->builder->load($this->context->helper->loadValue($value));
Expand Down
14 changes: 14 additions & 0 deletions test/compliance/cases/stdlib/getallheaders_jit.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
--TEST--
stdlib getallheaders() JIT from CGI HTTP_* environment (issue #307)
--ENV--
REQUEST_METHOD=GET
HTTP_X_TEST=1
HTTP_HOST=example.test
--FILE--
<?php
$headers = getallheaders();
echo array_key_exists('X-Test', $headers) ? 'yes' : 'no', "\n";
echo $headers['Host'], "\n";
--EXPECT--
yes
example.test
14 changes: 14 additions & 0 deletions test/fixtures/aot/cases/getallheaders.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
--TEST--
AOT: getallheaders() from CGI HTTP_* environment
--ENV--
REQUEST_METHOD=GET
HTTP_X_TEST=1
HTTP_HOST=example.test
--FILE--
<?php
$headers = getallheaders();
echo array_key_exists('X-Test', $headers) ? 'yes' : 'no', "\n";
echo $headers['Host'], "\n";
--EXPECT--
yes
example.test
Loading