@@ -259,8 +259,6 @@ struct _gc_stack {
259259 zend_refcounted * data [GC_STACK_SEGMENT_SIZE ];
260260};
261261
262- #ifdef PHP_ASYNC_API
263-
264262typedef enum {
265263 GC_ASYNC_STATE_NONE = 0 ,
266264 GC_ASYNC_STATE_INIT , // initial state
@@ -280,7 +278,6 @@ typedef struct {
280278 zend_hrtime_t start_time ; // start of full GC pass
281279 zend_hrtime_t dtor_start_time ; // start of dtor phase
282280} gc_async_context_t ;
283- #endif
284281
285282typedef struct _zend_gc_globals {
286283 gc_root_buffer * buf ; /* preallocated arrays of buffers */
@@ -308,13 +305,11 @@ typedef struct _zend_gc_globals {
308305 uint32_t dtor_end ;
309306 zend_fiber * dtor_fiber ;
310307 bool dtor_fiber_running ;
311- #ifdef PHP_ASYNC_API
312308 gc_async_context_t async_context ; /* async context for gc */
313309 gc_stack * gc_stack ; /* local mark/scan stack */
314310 zend_coroutine_t * dtor_coroutine ;
315311 zend_async_scope_t * dtor_scope ;
316312 zend_async_microtask_t * microtask ;
317- #endif
318313
319314#if GC_BENCH
320315 uint32_t root_buf_length ;
@@ -534,13 +529,11 @@ static void gc_globals_ctor_ex(zend_gc_globals *gc_globals)
534529 gc_globals -> dtor_fiber = NULL ;
535530 gc_globals -> dtor_fiber_running = false;
536531
537- #ifdef PHP_ASYNC_API
538532 gc_globals -> dtor_coroutine = NULL ;
539533 gc_globals -> dtor_scope = NULL ;
540534 gc_globals -> microtask = NULL ;
541535 gc_globals -> async_context .state = GC_ASYNC_STATE_NONE ;
542536 gc_globals -> gc_stack = NULL ;
543- #endif
544537
545538#if GC_BENCH
546539 gc_globals -> root_buf_length = 0 ;
@@ -567,11 +560,9 @@ void gc_globals_dtor(void)
567560 root_buffer_dtor (& gc_globals );
568561#endif
569562
570- #ifdef PHP_ASYNC_API
571563 if (GC_G (dtor_scope )) {
572564 GC_G (dtor_scope ) = NULL ;
573565 }
574- #endif
575566}
576567
577568void gc_reset (void )
@@ -1857,16 +1848,8 @@ static zend_always_inline zend_result gc_call_destructors(uint32_t idx, uint32_t
18571848 gc_root_buffer * current ;
18581849 zend_refcounted * p ;
18591850
1860- #ifdef PHP_ASYNC_API
18611851 const bool in_coroutine = GC_G (dtor_coroutine ) != NULL ;
18621852
1863- #define RESUMED_AFTER_SUSPENSION (fiber != NULL && GC_G(dtor_fiber) != fiber) \
1864- || (in_coroutine && GC_G(dtor_coroutine) != ZEND_ASYNC_CURRENT_COROUTINE)
1865- #else
1866- const bool in_coroutine = false;
1867- #define RESUMED_AFTER_SUSPENSION fiber != NULL && GC_G(dtor_fiber) != fiber
1868- #endif
1869-
18701853 /* The root buffer might be reallocated during destructors calls,
18711854 * make sure to reload pointers as necessary. */
18721855 while (idx != end ) {
@@ -1886,20 +1869,18 @@ static zend_always_inline zend_result gc_call_destructors(uint32_t idx, uint32_t
18861869 GC_TRACE_REF (obj , "calling destructor" );
18871870 GC_ADD_FLAGS (obj , IS_OBJ_DESTRUCTOR_CALLED );
18881871 GC_ADDREF (obj );
1889- #ifdef PHP_ASYNC_API
18901872 if (in_coroutine ) {
18911873 ZEND_ASYNC_CURRENT_COROUTINE -> extended_data = obj ;
18921874 }
1893- #endif
1875+
18941876 obj -> handlers -> dtor_obj (obj );
1895- #ifdef PHP_ASYNC_API
18961877 if (in_coroutine ) {
18971878 ZEND_ASYNC_CURRENT_COROUTINE -> extended_data = NULL ;
18981879 }
1899- #endif
19001880 GC_TRACE_REF (obj , "returned from destructor" );
19011881 GC_DELREF (obj );
1902- if (UNEXPECTED (RESUMED_AFTER_SUSPENSION )) {
1882+ if (UNEXPECTED ((fiber != NULL && GC_G (dtor_fiber ) != fiber )
1883+ || (in_coroutine && GC_G (dtor_coroutine ) != ZEND_ASYNC_CURRENT_COROUTINE ))) {
19031884 /* We resumed after suspension */
19041885 gc_check_possible_root ((zend_refcounted * )& obj -> gc );
19051886 return FAILURE ;
@@ -1974,7 +1955,6 @@ static zend_never_inline void gc_call_destructors_in_fiber(uint32_t end)
19741955 }
19751956}
19761957
1977- #ifdef PHP_ASYNC_API
19781958static void zend_gc_collect_cycles_microtask (zend_async_microtask_t * task );
19791959
19801960static void zend_gc_collect_cycles_microtask_dtor (zend_async_microtask_t * task )
@@ -2134,12 +2114,9 @@ static zend_always_inline void start_gc_in_coroutine(void)
21342114 zend_error_noreturn (E_ERROR , "Unable to spawn destructor coroutine" );
21352115 }
21362116}
2137- #endif
21382117
21392118ZEND_API int zend_gc_collect_cycles (void )
21402119{
2141- #ifdef PHP_ASYNC_API
2142-
21432120 if (UNEXPECTED (ZEND_ASYNC_IS_ACTIVE && ZEND_ASYNC_CURRENT_COROUTINE != GC_G (dtor_coroutine ))) {
21442121
21452122 if (GC_G (dtor_coroutine )) {
@@ -2150,24 +2127,8 @@ ZEND_API int zend_gc_collect_cycles(void)
21502127 return 0 ;
21512128 }
21522129
2153- #endif
2154-
21552130 zend_hrtime_t dtor_start_time = 0 ;
21562131
2157- #ifdef PHP_ASYNC_API
2158- #define GC_COLLECT_TOTAL_COUNT (context->total_count)
2159- #define GC_COLLECT_COUNT (context->count)
2160- #define GC_COLLECT_START_TIME (context->start_time)
2161- #define GC_COLLECT_SHOULD_RERUN_GC (context->should_rerun_gc)
2162- #define GC_COLLECT_DID_RERUN_GC (context->did_rerun_gc)
2163- #define GC_COLLECT_GC_FLAGS (context->gc_flags)
2164- #define GC_COLLECT_STACK (stack)
2165- #define GC_COLLECT_FREE_STACK GC_G(gc_stack) = NULL;\
2166- gc_stack_free(stack); \
2167- efree(stack)
2168- #define GC_COLLECT_FINISH_0 GC_G(async_context).state = GC_ASYNC_STATE_NONE; \
2169- return 0
2170-
21712132 // Someone is trying to invoke GC from within a destructor?
21722133 // We don’t know what that is, but we have nothing to do here.
21732134 if (UNEXPECTED (GC_G (async_context ).state == GC_ASYNC_STATE_RUNNING )) {
@@ -2225,23 +2186,6 @@ ZEND_API int zend_gc_collect_cycles(void)
22252186
22262187 context -> state = GC_ASYNC_STATE_RUNNING ;
22272188
2228- #else
2229- #define GC_COLLECT_COUNT count
2230- #define GC_COLLECT_TOTAL_COUNT total_count
2231- #define GC_COLLECT_START_TIME start_time
2232- #define GC_COLLECT_SHOULD_RERUN_GC should_rerun_gc
2233- #define GC_COLLECT_DID_RERUN_GC did_rerun_gc
2234- #define GC_COLLECT_GC_FLAGS gc_flags
2235- #define GC_COLLECT_STACK (&stack)
2236- #define GC_COLLECT_FREE_STACK gc_stack_free(&stack);
2237- #define GC_COLLECT_FINISH_0 return 0
2238-
2239- int total_count = 0 ;
2240- bool should_rerun_gc = 0 ;
2241- bool did_rerun_gc = 0 ;
2242-
2243- zend_hrtime_t start_time = zend_hrtime ();
2244- #endif
22452189
22462190 if (GC_G (num_roots ) && !GC_G (gc_active )) {
22472191 zend_gc_remove_root_tmpvars ();
@@ -2252,38 +2196,35 @@ ZEND_API int zend_gc_collect_cycles(void)
22522196 gc_root_buffer * current , * last ;
22532197 zend_refcounted * p ;
22542198 uint32_t gc_flags = 0 ;
2255- uint32_t idx , end ;
2256- #ifdef PHP_ASYNC_API
2199+ uint32_t idx , end = 0 ;
2200+
22572201 stack -> next = NULL ;
22582202 stack -> prev = NULL ;
2259- #else
2260- int count ;
2261- gc_stack stack ;
2262- stack .prev = NULL ;
2263- stack .next = NULL ;
2264- #endif
22652203
22662204 if (GC_G (gc_active )) {
2267- GC_G (collector_time ) += zend_hrtime () - GC_COLLECT_START_TIME ;
2268- GC_COLLECT_FINISH_0 ;
2205+ GC_G (collector_time ) += zend_hrtime () - context -> start_time ;
2206+ GC_G (async_context ).state = GC_ASYNC_STATE_NONE ;
2207+ return 0 ;
22692208 }
22702209
22712210 GC_TRACE ("Collecting cycles" );
22722211 GC_G (gc_runs )++ ;
22732212 GC_G (gc_active ) = 1 ;
22742213
22752214 GC_TRACE ("Marking roots" );
2276- gc_mark_roots (GC_COLLECT_STACK );
2215+ gc_mark_roots (stack );
22772216 GC_TRACE ("Scanning roots" );
2278- gc_scan_roots (GC_COLLECT_STACK );
2217+ gc_scan_roots (stack );
22792218
22802219 GC_TRACE ("Collecting roots" );
2281- GC_COLLECT_COUNT = gc_collect_roots (& gc_flags , GC_COLLECT_STACK );
2220+ context -> count = gc_collect_roots (& gc_flags , stack );
22822221
22832222 if (!GC_G (num_roots )) {
22842223 /* nothing to free */
22852224 GC_TRACE ("Nothing to free" );
2286- GC_COLLECT_FREE_STACK ;
2225+ GC_G (gc_stack ) = NULL ;
2226+ gc_stack_free (stack );
2227+ efree (stack );
22872228 GC_G (gc_active ) = 0 ;
22882229 goto finish ;
22892230 }
@@ -2298,7 +2239,7 @@ ZEND_API int zend_gc_collect_cycles(void)
22982239 * modify any refcounts, so we have no real way to detect this situation
22992240 * short of rerunning full GC tracing. What we do instead is to only run
23002241 * destructors at this point and automatically re-run GC afterwards. */
2301- GC_COLLECT_SHOULD_RERUN_GC = 1 ;
2242+ context -> should_rerun_gc = 1 ;
23022243
23032244 /* Mark all roots for which a dtor will be invoked as DTOR_GARBAGE. Additionally
23042245 * color them purple. This serves a double purpose: First, they should be
@@ -2332,7 +2273,7 @@ ZEND_API int zend_gc_collect_cycles(void)
23322273 while (idx != end ) {
23332274 if (GC_IS_DTOR_GARBAGE (current -> ref )) {
23342275 p = GC_GET_PTR (current -> ref );
2335- GC_COLLECT_COUNT -= gc_remove_nested_data_from_buffer (p , current , GC_COLLECT_STACK );
2276+ context -> count -= gc_remove_nested_data_from_buffer (p , current , stack );
23362277 }
23372278 current ++ ;
23382279 idx ++ ;
@@ -2341,9 +2282,7 @@ ZEND_API int zend_gc_collect_cycles(void)
23412282 /* Actually call destructors. */
23422283 dtor_start_time = zend_hrtime ();
23432284 if (EXPECTED (!EG (active_fiber ))) {
2344- #ifdef PHP_ASYNC_API
23452285continue_calling_destructors :
2346- end = GC_G (first_unused );
23472286 if (UNEXPECTED (FAILURE == gc_call_destructors (GC_G (dtor_idx ), GC_G (first_unused ), NULL ))) {
23482287 //
23492288 // gc_call_destructors returns FAILURE when a destructor interrupts execution,
@@ -2352,11 +2291,8 @@ ZEND_API int zend_gc_collect_cycles(void)
23522291 // because the process continues elsewhere.
23532292 //
23542293 GC_G (dtor_time ) += zend_hrtime () - dtor_start_time ;
2355- return GC_COLLECT_TOTAL_COUNT ;
2294+ return context -> total_count ;
23562295 }
2357- #else
2358- gc_call_destructors (GC_FIRST_ROOT , end , NULL );
2359- #endif
23602296 } else {
23612297 gc_call_destructors_in_fiber (end );
23622298 }
@@ -2365,18 +2301,17 @@ ZEND_API int zend_gc_collect_cycles(void)
23652301 if (GC_G (gc_protected )) {
23662302 /* something went wrong */
23672303 zend_get_gc_buffer_release ();
2368- GC_G (collector_time ) += zend_hrtime () - GC_COLLECT_START_TIME ;
2369- GC_COLLECT_FINISH_0 ;
2304+ GC_G (collector_time ) += zend_hrtime () - context -> start_time ;
2305+ GC_G (async_context ).state = GC_ASYNC_STATE_NONE ;
2306+ return 0 ;
23702307 }
23712308 }
23722309
2373- gc_stack_free (GC_COLLECT_STACK );
2310+ gc_stack_free (stack );
23742311
2375- #ifdef PHP_ASYNC_API
23762312 if (false == in_fiber ) {
23772313 end = GC_G (first_unused );
23782314 }
2379- #endif
23802315
23812316 /* Destroy zvals. The root buffer may be reallocated. */
23822317 GC_TRACE ("Destroying zvals" );
@@ -2434,8 +2369,8 @@ ZEND_API int zend_gc_collect_cycles(void)
24342369 GC_G (free_time ) += zend_hrtime () - free_start_time ;
24352370
24362371 GC_TRACE ("Collection finished" );
2437- GC_G (collected ) += GC_COLLECT_COUNT ;
2438- GC_COLLECT_TOTAL_COUNT += GC_COLLECT_COUNT ;
2372+ GC_G (collected ) += context -> count ;
2373+ context -> total_count += context -> count ;
24392374 GC_G (gc_active ) = 0 ;
24402375 }
24412376
@@ -2444,8 +2379,8 @@ ZEND_API int zend_gc_collect_cycles(void)
24442379 /* Objects with destructors were removed from this GC run. Rerun GC right away to clean them
24452380 * up. We do this only once: If we encounter more destructors on the second run, we'll not
24462381 * run GC another time. */
2447- if (GC_COLLECT_SHOULD_RERUN_GC && !GC_COLLECT_DID_RERUN_GC ) {
2448- GC_COLLECT_DID_RERUN_GC = 1 ;
2382+ if (context -> should_rerun_gc && !context -> did_rerun_gc ) {
2383+ context -> did_rerun_gc = 1 ;
24492384 goto rerun_gc ;
24502385 }
24512386
@@ -2458,10 +2393,10 @@ ZEND_API int zend_gc_collect_cycles(void)
24582393 zend_gc_check_root_tmpvars ();
24592394 GC_G (gc_active ) = 0 ;
24602395
2461- GC_G (collector_time ) += zend_hrtime () - GC_COLLECT_START_TIME ;
2462- #ifdef PHP_ASYNC_API
2396+ GC_G (collector_time ) += zend_hrtime () - context -> start_time ;
2397+
24632398 if (in_fiber ) {
2464- const int total_count = GC_COLLECT_TOTAL_COUNT ;
2399+ const int total_count = context -> total_count ;
24652400 efree (context );
24662401 efree (stack );
24672402 return total_count ;
@@ -2472,8 +2407,8 @@ ZEND_API int zend_gc_collect_cycles(void)
24722407 efree (stack );
24732408 }
24742409 }
2475- #endif
2476- return GC_COLLECT_TOTAL_COUNT ;
2410+
2411+ return context -> total_count ;
24772412}
24782413
24792414ZEND_API void zend_gc_get_status (zend_gc_status * status )
0 commit comments