-
Notifications
You must be signed in to change notification settings - Fork 7.8k
JIT: Check exception on exit #18297
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
base: PHP-8.4
Are you sure you want to change the base?
JIT: Check exception on exit #18297
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14476,12 +14476,12 @@ static int zend_jit_fetch_obj(zend_jit_ctx *jit, | |
ZEND_ASSERT(end_inputs == IR_UNUSED); | ||
if ((res_info & MAY_BE_GUARD) && JIT_G(current_frame)) { | ||
uint8_t type = concrete_type(res_info); | ||
uint32_t flags = 0; | ||
uint32_t flags = ZEND_JIT_EXIT_CHECK_EXCEPTION; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can't comment on the line, but maybe it's better to change line 14484 to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh right, that's actually a mistake. Thank you for spotting this. |
||
|
||
if ((opline->op1_type & (IS_VAR|IS_TMP_VAR)) | ||
&& !delayed_fetch_this | ||
&& !op1_avoid_refcounting) { | ||
flags = ZEND_JIT_EXIT_FREE_OP1; | ||
flags |= ZEND_JIT_EXIT_FREE_OP1; | ||
} | ||
|
||
if ((opline->result_type & (IS_VAR|IS_TMP_VAR)) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
--TEST-- | ||
GH-18262 001 (Assertion failure Zend/zend_vm_execute.h JIT) | ||
--CREDITS-- | ||
YuanchengJiang | ||
--FILE-- | ||
<?php | ||
#[AllowDynamicProperties] | ||
class B { | ||
public int $fusion; | ||
} | ||
class C extends B { | ||
} | ||
class D extends C { | ||
public function __destruct() { | ||
} | ||
} | ||
$tests = [ | ||
[C::class, new C()], | ||
[C::class, new B()], | ||
[D::class, new B()], | ||
]; | ||
foreach ($tests as [$class, $instance]) { | ||
$obj = (new ReflectionClass($class))->newLazyProxy(function ($obj) use ($instance) { | ||
$instance->b = 1; | ||
return $instance; | ||
}); | ||
var_dump($obj->b); | ||
} | ||
?> | ||
--EXPECTF-- | ||
int(1) | ||
int(1) | ||
|
||
Fatal error: Uncaught TypeError: %s in %s:%d | ||
Stack trace: | ||
#0 {main} | ||
thrown in %s on line %d |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
--TEST-- | ||
GH-18262 002 (Assertion failure Zend/zend_vm_execute.h JIT) | ||
--FILE-- | ||
<?php | ||
#[AllowDynamicProperties] | ||
class B { | ||
public function __construct($init) { | ||
if ($init) { | ||
$this->b = $init; | ||
} | ||
} | ||
} | ||
|
||
$tests = [ | ||
new B(1), | ||
new B(0), | ||
]; | ||
|
||
set_error_handler(function ($_, $errstr) { | ||
throw new \Exception($errstr); | ||
}); | ||
|
||
foreach ($tests as $obj) { | ||
var_dump($obj->b); | ||
} | ||
?> | ||
--EXPECTF-- | ||
int(1) | ||
|
||
Fatal error: Uncaught Exception: Undefined property: B::$b in %s:%d | ||
Stack trace: | ||
#0 %s(%d): {closure:%s:%d}(2, 'Undefined prope...', '%s', %d) | ||
#1 {main} | ||
thrown in %s on line %d |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
--TEST-- | ||
GH-18262 003 (Assertion failure Zend/zend_vm_execute.h JIT) | ||
--FILE-- | ||
<?php | ||
#[AllowDynamicProperties] | ||
class B { | ||
public function __construct($init) { | ||
if ($init) { | ||
$this->b = $init; | ||
} | ||
} | ||
} | ||
|
||
$tests = [ | ||
new B(1), | ||
new B('str'), // slow deoptimization, create linked side trace | ||
new B(0), // jump to side trace with fast deoptimization | ||
]; | ||
|
||
set_error_handler(function ($_, $errstr) { | ||
throw new \Exception($errstr); | ||
}); | ||
|
||
foreach ($tests as $obj) { | ||
try { | ||
var_dump($obj->b); | ||
} catch (Exception $e) { | ||
printf("%s: %s\n", $e::class, $e->getMessage()); | ||
} | ||
} | ||
?> | ||
--EXPECT-- | ||
int(1) | ||
string(3) "str" | ||
Exception: Undefined property: B::$b |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
--TEST-- | ||
GH-18262 004 (Assertion failure Zend/zend_vm_execute.h JIT) | ||
--FILE-- | ||
<?php | ||
class B { | ||
public function __construct( | ||
public $throw, | ||
) { } | ||
public function __get($name) { | ||
return $this->throw === '1' ? 'str' : 1; | ||
} | ||
public function __destruct() { | ||
if ($this->throw === '1') { | ||
throw new Exception(__METHOD__); | ||
} | ||
} | ||
} | ||
|
||
$tests = [ | ||
'0', | ||
'1', | ||
]; | ||
|
||
foreach ($tests as $test) { | ||
// Second iteration exits, and free op1 throws | ||
var_dump((new B($test))->b); | ||
} | ||
?> | ||
--EXPECTF-- | ||
int(1) | ||
|
||
Fatal error: Uncaught Exception: B::__destruct in %s:%d | ||
Stack trace: | ||
#0 %s(%d): B->__destruct() | ||
#1 {main} | ||
thrown in %s on line %d |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe also make sure this gets printed out in
zend_jit_dump_exit_info
?