Commit 7b9d54ee95f for php
commit 7b9d54ee95faea25c83c62591be2bf3e2fb57dda
Author: Marc <m@pyc.ac>
Date: Sun Nov 8 20:26:35 2026 +0700
perf: avoid stack accessor calls for output buffering (#25300)
* avoid stack accessor calls for output buffering
* move to header with zend_always_inline instead
* move macro definition
* move other small functions too
diff --git a/Zend/zend_stack.c b/Zend/zend_stack.c
index d999d684d05..0d9e11d9824 100644
--- a/Zend/zend_stack.c
+++ b/Zend/zend_stack.c
@@ -19,8 +19,6 @@
#include "zend.h"
#include "zend_stack.h"
-#define ZEND_STACK_ELEMENT(stack, n) ((void *)((char *) (stack)->elements + (stack)->size * (n)))
-
ZEND_API void zend_stack_init(zend_stack *stack, int size)
{
stack->size = size;
@@ -41,22 +39,6 @@ ZEND_API int zend_stack_push(zend_stack *stack, const void *element)
}
-ZEND_API void *zend_stack_top(const zend_stack *stack)
-{
- if (stack->top > 0) {
- return ZEND_STACK_ELEMENT(stack, stack->top - 1);
- } else {
- return NULL;
- }
-}
-
-
-ZEND_API void zend_stack_del_top(zend_stack *stack)
-{
- --stack->top;
-}
-
-
ZEND_API int zend_stack_int_top(const zend_stack *stack)
{
int *e = zend_stack_top(stack);
@@ -68,12 +50,6 @@ ZEND_API int zend_stack_int_top(const zend_stack *stack)
}
-ZEND_API bool zend_stack_is_empty(const zend_stack *stack)
-{
- return stack->top == 0;
-}
-
-
ZEND_API void zend_stack_destroy(zend_stack *stack)
{
if (stack->elements) {
@@ -83,18 +59,6 @@ ZEND_API void zend_stack_destroy(zend_stack *stack)
}
-ZEND_API void *zend_stack_base(const zend_stack *stack)
-{
- return stack->elements;
-}
-
-
-ZEND_API int zend_stack_count(const zend_stack *stack)
-{
- return stack->top;
-}
-
-
ZEND_API void zend_stack_apply(zend_stack *stack, int type, int (*apply_function)(void *element))
{
int i;
diff --git a/Zend/zend_stack.h b/Zend/zend_stack.h
index 66c90f0b521..7006145ed80 100644
--- a/Zend/zend_stack.h
+++ b/Zend/zend_stack.h
@@ -28,6 +28,7 @@ typedef struct _zend_stack {
#define STACK_BLOCK_SIZE 16
+#define ZEND_STACK_ELEMENT(stack, n) ((void *)((char *) (stack)->elements + (stack)->size * (n)))
typedef enum {
ZEND_STACK_APPLY_TOPDOWN,
@@ -37,16 +38,40 @@ typedef enum {
BEGIN_EXTERN_C()
ZEND_API void zend_stack_init(zend_stack *stack, int size);
ZEND_API int zend_stack_push(zend_stack *stack, const void *element);
-ZEND_API void *zend_stack_top(const zend_stack *stack);
-ZEND_API void zend_stack_del_top(zend_stack *stack);
ZEND_API int zend_stack_int_top(const zend_stack *stack);
-ZEND_API bool zend_stack_is_empty(const zend_stack *stack);
ZEND_API void zend_stack_destroy(zend_stack *stack);
-ZEND_API void *zend_stack_base(const zend_stack *stack);
-ZEND_API int zend_stack_count(const zend_stack *stack);
ZEND_API void zend_stack_apply(zend_stack *stack, int type, int (*apply_function)(void *element));
ZEND_API void zend_stack_apply_with_argument(zend_stack *stack, zend_stack_apply_direction type, int (*apply_function)(void *element, void *arg), void *arg);
ZEND_API void zend_stack_clean(zend_stack *stack, void (*func)(void *), bool free_elements);
END_EXTERN_C()
+static zend_always_inline void *zend_stack_top(const zend_stack *stack)
+{
+ if (stack->top > 0) {
+ return ZEND_STACK_ELEMENT(stack, stack->top - 1);
+ } else {
+ return NULL;
+ }
+}
+
+static zend_always_inline void zend_stack_del_top(zend_stack *stack)
+{
+ --stack->top;
+}
+
+static zend_always_inline bool zend_stack_is_empty(const zend_stack *stack)
+{
+ return stack->top == 0;
+}
+
+static zend_always_inline void *zend_stack_base(const zend_stack *stack)
+{
+ return stack->elements;
+}
+
+static zend_always_inline int zend_stack_count(const zend_stack *stack)
+{
+ return stack->top;
+}
+
#endif /* ZEND_STACK_H */
diff --git a/main/output.c b/main/output.c
index f7e1244a3d9..d56f04e0dae 100644
--- a/main/output.c
+++ b/main/output.c
@@ -1111,7 +1111,7 @@ static inline void php_output_op(int op, const char *str, size_t len)
if (obh_cnt > 1) {
zend_stack_apply_with_argument(&OG(handlers), ZEND_STACK_APPLY_TOPDOWN, php_output_stack_apply_op, &context);
- } else if ((active = zend_stack_top(&OG(handlers))) && (!((*active)->flags & PHP_OUTPUT_HANDLER_DISABLED))) {
+ } else if ((active = zend_stack_base(&OG(handlers))) && (!((*active)->flags & PHP_OUTPUT_HANDLER_DISABLED))) {
php_output_handler_op(*active, &context);
} else {
php_output_context_pass(&context);