Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 3cb08bc

Browse files
Delay GC until safepoint is reached
1 parent 2480362 commit 3cb08bc

File tree

10 files changed

+58
-34
lines changed

10 files changed

+58
-34
lines changed

‎Zend/tests/gc/bug70805.phpt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ $i = 0;
2828
$c = new A;
2929
$array = array($c); //This is used to leave a room for $GLOBALS["a"]
3030
unset($c);
31+
flush(); // handle interrupts
3132

3233
while ($i++ < 9998) {
3334
$t = [];
@@ -37,11 +38,13 @@ while ($i++ < 9998) {
3738
$t = [new C];
3839
$t[] = &$t;
3940
unset($t); // This is used to trigger C::__destruct while doing gc_collect_roots
41+
flush(); // handle interrupts
4042

4143
$e = $a;
4244
unset($a); // This one cannot be put into roots buf because it's full, thus gc_collect_roots will be called,
4345
// but C::__destructor which is called in gc_collect_roots will put $a into buf
4446
// which will make $a be put into gc roots buf twice
47+
flush(); // handle interrupts
4548
var_dump(gc_collect_cycles());
4649
?>
4750
--EXPECT--

‎Zend/tests/gc/bug70805_1.phpt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ $i = 0;
3030
$c = new A;
3131
$array = array($c);
3232
unset($c);
33+
flush(); // handle interrupts
3334

3435
while ($i++ < 9998) {
3536
$t = [];
@@ -39,9 +40,11 @@ while ($i++ < 9998) {
3940
$t = [new C];
4041
$t[] = &$t;
4142
unset($t);
43+
flush(); // handle interrupts
4244
unset($a);
45+
flush(); // handle interrupts
4346

4447
var_dump(gc_collect_cycles());
4548
?>
4649
--EXPECT--
47-
int(2)
50+
int(0)

‎Zend/tests/gc/bug70805_2.phpt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,15 @@ while ($i++ < 9999) {
3131
$t[] = &$t;
3232
unset($t);
3333
}
34+
flush(); // handle interrupts
3435
$t = [new C];
3536
$t[] = &$t;
3637
unset($t);
38+
flush(); // handle interrupts
3739

3840
unset($a);
41+
flush(); // handle interrupts
3942
var_dump(gc_collect_cycles());
4043
?>
4144
--EXPECT--
42-
int(2)
45+
int(0)

‎Zend/tests/gc/gc_023.phpt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,23 @@ for ($i=0; $i < 9999; $i++) {
1111
}
1212
var_dump(gc_collect_cycles());
1313
unset($a);
14+
flush(); // check interrupts
1415
var_dump(gc_collect_cycles());
1516
$a=array();
1617
for ($i=0; $i < 10001; $i++) {
1718
$a[$i] = array(array());
1819
$a[$i][0] = & $a[$i];
1920
}
21+
flush(); // check interrupts
2022
var_dump(gc_collect_cycles());
21-
unset($a); // 10000 zvals collected automatic
23+
unset($a);
24+
flush(); // check interrupts. 10000 zvals collected automatic
2225
var_dump(gc_collect_cycles());
2326
echo "ok\n";
2427
?>
2528
--EXPECT--
2629
int(0)
2730
int(9999)
2831
int(0)
29-
int(1)
32+
int(0)
3033
ok

‎Zend/tests/gc/gc_045.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,9 @@ array(12) {
6060
["threshold"]=>
6161
int(10001)
6262
["buffer_size"]=>
63-
int(16384)
63+
int(%d)
6464
["roots"]=>
65-
int(10000)
65+
int(9999)
6666
["application_time"]=>
6767
float(%f)
6868
["collector_time"]=>

‎Zend/zend_execute.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4269,6 +4269,8 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_fcall_interrupt(zend_execute_data *ca
42694269
zend_atomic_bool_store_ex(&EG(vm_interrupt), false);
42704270
if (zend_atomic_bool_load_ex(&EG(timed_out))) {
42714271
zend_timeout();
4272+
} else if (zend_atomic_bool_load_ex(&EG(gc_requested))) {
4273+
gc_handle_requested_run();
42724274
} else if (zend_interrupt_function) {
42734275
zend_interrupt_function(call);
42744276
}

‎Zend/zend_gc.c

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
*/
6969
#include "zend.h"
7070
#include "zend_API.h"
71+
#include "zend_atomic.h"
7172
#include "zend_compile.h"
7273
#include "zend_errors.h"
7374
#include "zend_fibers.h"
@@ -687,7 +688,19 @@ static void gc_adjust_threshold(int count)
687688
}
688689
}
689690

690-
/* Perform a GC run and then add a node as a possible root. */
691+
static void gc_request_run(void)
692+
{
693+
zend_atomic_bool_store_ex(&EG(gc_requested), true);
694+
zend_atomic_bool_store_ex(&EG(vm_interrupt), true);
695+
}
696+
697+
void gc_handle_requested_run(void)
698+
{
699+
zend_atomic_bool_store_ex(&EG(gc_requested), false);
700+
gc_adjust_threshold(gc_collect_cycles());
701+
}
702+
703+
/* Add a node as a possible root and request a GC run. */
691704
static zend_never_inline void ZEND_FASTCALL gc_possible_root_when_full(zend_refcounted *ref)
692705
{
693706
uint32_t idx;
@@ -696,20 +709,8 @@ static zend_never_inline void ZEND_FASTCALL gc_possible_root_when_full(zend_refc
696709
ZEND_ASSERT(GC_TYPE(ref) == IS_ARRAY || GC_TYPE(ref) == IS_OBJECT);
697710
ZEND_ASSERT(GC_INFO(ref) == 0);
698711

699-
if (GC_G(gc_enabled) && !GC_G(gc_active)) {
700-
GC_ADDREF(ref);
701-
gc_adjust_threshold(gc_collect_cycles());
702-
if (UNEXPECTED(GC_DELREF(ref) == 0)) {
703-
rc_dtor_func(ref);
704-
return;
705-
} else if (UNEXPECTED(GC_INFO(ref))) {
706-
return;
707-
}
708-
}
709-
710-
if (GC_HAS_UNUSED()) {
711-
idx = GC_FETCH_UNUSED();
712-
} else if (EXPECTED(GC_HAS_NEXT_UNUSED())) {
712+
ZEND_ASSERT(!GC_HAS_UNUSED());
713+
if (EXPECTED(GC_HAS_NEXT_UNUSED())) {
713714
idx = GC_FETCH_NEXT_UNUSED();
714715
} else {
715716
gc_grow_root_buffer();
@@ -730,6 +731,10 @@ static zend_never_inline void ZEND_FASTCALL gc_possible_root_when_full(zend_refc
730731
GC_BENCH_INC(zval_buffered);
731732
GC_BENCH_INC(root_buf_length);
732733
GC_BENCH_PEAK(root_buf_peak, root_buf_length);
734+
735+
if (GC_G(gc_enabled) && !GC_G(gc_active)) {
736+
gc_request_run();
737+
}
733738
}
734739

735740
/* Add a possible root node to the buffer.

‎Zend/zend_gc.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ void gc_globals_ctor(void);
7070
void gc_globals_dtor(void);
7171
void gc_reset(void);
7272

73+
void gc_handle_requested_run(void);
74+
7375
#ifdef ZTS
7476
size_t zend_gc_globals_size(void);
7577
#endif

‎Zend/zend_globals.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ struct _zend_executor_globals {
219219

220220
zend_atomic_bool vm_interrupt;
221221
zend_atomic_bool timed_out;
222+
zend_atomic_bool gc_requested;
222223

223224
HashTable *in_autoload;
224225

‎Zend/zend_vm_def.h

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10506,23 +10506,25 @@ ZEND_VM_HELPER(zend_interrupt_helper, ANY, ANY)
1050610506
SAVE_OPLINE();
1050710507
if (zend_atomic_bool_load_ex(&EG(timed_out))) {
1050810508
zend_timeout();
10509+
ZEND_VM_CONTINUE();
10510+
} else if (zend_atomic_bool_load_ex(&EG(gc_requested))) {
10511+
gc_handle_requested_run();
1050910512
} else if (zend_interrupt_function) {
1051010513
zend_interrupt_function(execute_data);
10511-
if (EG(exception)) {
10512-
/* We have to UNDEF result, because ZEND_HANDLE_EXCEPTION is going to free it */
10513-
const zend_op *throw_op = EG(opline_before_exception);
10514+
}
10515+
if (EG(exception)) {
10516+
/* We have to UNDEF result, because ZEND_HANDLE_EXCEPTION is going to free it */
10517+
const zend_op *throw_op = EG(opline_before_exception);
1051410518

10515-
if (throw_op
10516-
&& throw_op->result_type & (IS_TMP_VAR|IS_VAR)
10517-
&& throw_op->opcode != ZEND_ADD_ARRAY_ELEMENT
10518-
&& throw_op->opcode != ZEND_ADD_ARRAY_UNPACK
10519-
&& throw_op->opcode != ZEND_ROPE_INIT
10520-
&& throw_op->opcode != ZEND_ROPE_ADD) {
10521-
ZVAL_UNDEF(ZEND_CALL_VAR(EG(current_execute_data), throw_op->result.var));
10519+
if (throw_op
10520+
&& throw_op->result_type & (IS_TMP_VAR|IS_VAR)
10521+
&& throw_op->opcode != ZEND_ADD_ARRAY_ELEMENT
10522+
&& throw_op->opcode != ZEND_ADD_ARRAY_UNPACK
10523+
&& throw_op->opcode != ZEND_ROPE_INIT
10524+
&& throw_op->opcode != ZEND_ROPE_ADD) {
10525+
ZVAL_UNDEF(ZEND_CALL_VAR(EG(current_execute_data), throw_op->result.var));
1052210526

10523-
}
1052410527
}
10525-
ZEND_VM_ENTER();
1052610528
}
10527-
ZEND_VM_CONTINUE();
10529+
ZEND_VM_ENTER();
1052810530
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /