Skip to content

Commit dfb18b1

Browse files
committed
Merge remote-tracking branch 'origin/master' into native-tls
* origin/master: updated NEWS PowerPC64 support for add and sub with overflow check PowerPC64 support for operators with overflow check Fixed bug #68583 Crash in timeout thread Reduced size of zend_op on 64-bit systems. Make ZEND_INIT_FCALL keep predcalculted size of necessary stack space in opline->op1.num to avoid its recalculation on each execution. Removed unused variables Improved array_merge() and array_replace() (1-st array may be added using simple procedure). Replaced zendi_convert_to_long() with _zval_get_long_func() Moved zend_is_true() from zend_execute.h/zend_execute_API.c into zend_operators.h/zend_operators.c. Splited the most expensive part of inline i_zend_is_true() into a separate zend_object_is_true(). Replaced zendi_convert_to_long() with cals to zend_is_true(). Revert "Save one xor instr" Save one xor instr Conflicts: Zend/zend_execute_API.c
2 parents de99a94 + f431168 commit dfb18b1

21 files changed

+1831
-1631
lines changed

Zend/zend.c

-3
Original file line numberDiff line numberDiff line change
@@ -731,9 +731,6 @@ void zend_shutdown(TSRMLS_D) /* {{{ */
731731
{
732732
#ifdef ZEND_SIGNALS
733733
zend_signal_shutdown(TSRMLS_C);
734-
#endif
735-
#ifdef ZEND_WIN32
736-
zend_shutdown_timeout_thread();
737734
#endif
738735
zend_destroy_rsrc_list(&EG(persistent_list) TSRMLS_CC);
739736
if (EG(active))

Zend/zend_compile.c

+29-31
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,6 @@
3232
#include "zend_language_scanner.h"
3333
#include "zend_inheritance.h"
3434

35-
#define CONSTANT_EX(op_array, op) \
36-
(op_array)->literals[op]
37-
38-
#define CONSTANT(op) \
39-
CONSTANT_EX(CG(active_op_array), op)
40-
4135
#define SET_NODE(target, src) do { \
4236
target ## _type = (src)->op_type; \
4337
if ((src)->op_type == IS_CONST) { \
@@ -50,7 +44,7 @@
5044
#define GET_NODE(target, src) do { \
5145
(target)->op_type = src ## _type; \
5246
if ((target)->op_type == IS_CONST) { \
53-
(target)->u.constant = CONSTANT(src.constant); \
47+
ZVAL_COPY_VALUE(&(target)->u.constant, CT_CONSTANT(src)); \
5448
} else { \
5549
(target)->u.op = src; \
5650
} \
@@ -291,11 +285,11 @@ static int lookup_cv(zend_op_array *op_array, zend_string* name TSRMLS_DC) /* {{
291285

292286
void zend_del_literal(zend_op_array *op_array, int n) /* {{{ */
293287
{
294-
zval_dtor(&CONSTANT_EX(op_array, n));
288+
zval_dtor(CT_CONSTANT_EX(op_array, n));
295289
if (n + 1 == op_array->last_literal) {
296290
op_array->last_literal--;
297291
} else {
298-
ZVAL_UNDEF(&CONSTANT_EX(op_array, n));
292+
ZVAL_UNDEF(CT_CONSTANT_EX(op_array, n));
299293
}
300294
}
301295
/* }}} */
@@ -310,7 +304,7 @@ static inline void zend_insert_literal(zend_op_array *op_array, zval *zv, int li
310304
Z_TYPE_FLAGS_P(zv) &= ~ (IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE);
311305
}
312306
}
313-
ZVAL_COPY_VALUE(&CONSTANT_EX(op_array, literal_position), zv);
307+
ZVAL_COPY_VALUE(CT_CONSTANT_EX(op_array, literal_position), zv);
314308
Z_CACHE_SLOT(op_array->literals[literal_position]) = -1;
315309
}
316310
/* }}} */
@@ -752,13 +746,13 @@ static void str_dtor(zval *zv) /* {{{ */ {
752746
void zend_resolve_goto_label(zend_op_array *op_array, zend_op *opline, int pass2 TSRMLS_DC) /* {{{ */
753747
{
754748
zend_label *dest;
755-
zend_long current, distance;
749+
int current, distance;
756750
zval *label;
757751

758752
if (pass2) {
759-
label = opline->op2.zv;
753+
label = RT_CONSTANT(op_array, opline->op2);
760754
} else {
761-
label = &CONSTANT_EX(op_array, opline->op2.constant);
755+
label = CT_CONSTANT_EX(op_array, opline->op2.constant);
762756
}
763757
if (CG(context).labels == NULL ||
764758
(dest = zend_hash_find_ptr(CG(context).labels, Z_STR_P(label))) == NULL) {
@@ -888,11 +882,11 @@ ZEND_API int do_bind_function(const zend_op_array *op_array, const zend_op *opli
888882
zval *op1, *op2;
889883

890884
if (compile_time) {
891-
op1 = &CONSTANT_EX(op_array, opline->op1.constant);
892-
op2 = &CONSTANT_EX(op_array, opline->op2.constant);
885+
op1 = CT_CONSTANT_EX(op_array, opline->op1.constant);
886+
op2 = CT_CONSTANT_EX(op_array, opline->op2.constant);
893887
} else {
894-
op1 = opline->op1.zv;
895-
op2 = opline->op2.zv;
888+
op1 = RT_CONSTANT(op_array, opline->op1);
889+
op2 = RT_CONSTANT(op_array, opline->op2);
896890
}
897891

898892
function = zend_hash_find_ptr(function_table, Z_STR_P(op1));
@@ -928,11 +922,11 @@ ZEND_API zend_class_entry *do_bind_class(const zend_op_array* op_array, const ze
928922
zval *op1, *op2;
929923

930924
if (compile_time) {
931-
op1 = &CONSTANT_EX(op_array, opline->op1.constant);
932-
op2 = &CONSTANT_EX(op_array, opline->op2.constant);
925+
op1 = CT_CONSTANT_EX(op_array, opline->op1.constant);
926+
op2 = CT_CONSTANT_EX(op_array, opline->op2.constant);
933927
} else {
934-
op1 = opline->op1.zv;
935-
op2 = opline->op2.zv;
928+
op1 = RT_CONSTANT(op_array, opline->op1);
929+
op2 = RT_CONSTANT(op_array, opline->op2);
936930
}
937931
if ((ce = zend_hash_find_ptr(class_table, Z_STR_P(op1))) == NULL) {
938932
zend_error_noreturn(E_COMPILE_ERROR, "Internal Zend error - Missing class information for %s", Z_STRVAL_P(op1));
@@ -965,11 +959,11 @@ ZEND_API zend_class_entry *do_bind_inherited_class(const zend_op_array *op_array
965959
zval *op1, *op2;
966960

967961
if (compile_time) {
968-
op1 = &CONSTANT_EX(op_array, opline->op1.constant);
969-
op2 = &CONSTANT_EX(op_array, opline->op2.constant);
962+
op1 = CT_CONSTANT_EX(op_array, opline->op1.constant);
963+
op2 = CT_CONSTANT_EX(op_array, opline->op2.constant);
970964
} else {
971-
op1 = opline->op1.zv;
972-
op2 = opline->op2.zv;
965+
op1 = RT_CONSTANT(op_array, opline->op1);
966+
op2 = RT_CONSTANT(op_array, opline->op2);
973967
}
974968

975969
ce = zend_hash_find_ptr(class_table, Z_STR_P(op1));
@@ -1032,7 +1026,7 @@ void zend_do_early_binding(TSRMLS_D) /* {{{ */
10321026
zval *parent_name;
10331027
zend_class_entry *ce;
10341028

1035-
parent_name = &CONSTANT(fetch_class_opline->op2.constant);
1029+
parent_name = CT_CONSTANT(fetch_class_opline->op2);
10361030
if (((ce = zend_lookup_class(Z_STR_P(parent_name) TSRMLS_CC)) == NULL) ||
10371031
((CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_CLASSES) &&
10381032
(ce->type == ZEND_INTERNAL_CLASS))) {
@@ -1071,7 +1065,7 @@ void zend_do_early_binding(TSRMLS_D) /* {{{ */
10711065
return;
10721066
}
10731067

1074-
zend_hash_del(table, Z_STR(CONSTANT(opline->op1.constant)));
1068+
zend_hash_del(table, Z_STR_P(CT_CONSTANT(opline->op1)));
10751069
zend_del_literal(CG(active_op_array), opline->op1.constant);
10761070
zend_del_literal(CG(active_op_array), opline->op2.constant);
10771071
MAKE_NOP(opline);
@@ -1087,7 +1081,7 @@ ZEND_API void zend_do_delayed_early_binding(const zend_op_array *op_array TSRMLS
10871081

10881082
CG(in_compilation) = 1;
10891083
while (opline_num != -1) {
1090-
if ((ce = zend_lookup_class(Z_STR_P(op_array->opcodes[opline_num-1].op2.zv) TSRMLS_CC)) != NULL) {
1084+
if ((ce = zend_lookup_class(Z_STR_P(RT_CONSTANT(op_array, op_array->opcodes[opline_num-1].op2)) TSRMLS_CC)) != NULL) {
10911085
do_bind_inherited_class(op_array, &op_array->opcodes[opline_num], EG(class_table), ce, 0 TSRMLS_CC);
10921086
}
10931087
opline_num = op_array->opcodes[opline_num].result.opline_num;
@@ -2112,7 +2106,7 @@ static zend_op *zend_delayed_compile_prop(znode *result, zend_ast *ast, uint32_t
21122106

21132107
opline = zend_delayed_emit_op(result, ZEND_FETCH_OBJ_R, &obj_node, &prop_node TSRMLS_CC);
21142108
if (opline->op2_type == IS_CONST) {
2115-
convert_to_string(&CONSTANT(opline->op2.constant));
2109+
convert_to_string(CT_CONSTANT(opline->op2));
21162110
zend_alloc_polymorphic_cache_slot(opline->op2.constant TSRMLS_CC);
21172111
}
21182112

@@ -2509,6 +2503,10 @@ void zend_compile_call_common(znode *result, zend_ast *args_ast, zend_function *
25092503
opline = &CG(active_op_array)->opcodes[opnum_init];
25102504
opline->extended_value = arg_count;
25112505

2506+
if (opline->opcode == ZEND_INIT_FCALL) {
2507+
opline->op1.num = zend_vm_calc_used_stack(arg_count, fbc);
2508+
}
2509+
25122510
call_flags = (opline->opcode == ZEND_NEW ? ZEND_CALL_CTOR : 0);
25132511
opline = zend_emit_op(result, ZEND_DO_FCALL, NULL, NULL TSRMLS_CC);
25142512
opline->op1.num = call_flags;
@@ -2662,7 +2660,7 @@ static int zend_try_compile_ct_bound_init_user_func(zend_ast *name_ast, uint32_t
26622660

26632661
opline = zend_emit_op(NULL, ZEND_INIT_FCALL, NULL, NULL TSRMLS_CC);
26642662
opline->extended_value = num_args;
2665-
2663+
opline->op1.num = zend_vm_calc_used_stack(num_args, fbc);
26662664
opline->op2_type = IS_CONST;
26672665
LITERAL_STR(opline->op2, lcname);
26682666
zend_alloc_cache_slot(opline->op2.constant TSRMLS_CC);
@@ -3515,7 +3513,7 @@ void zend_compile_switch(zend_ast *ast TSRMLS_DC) /* {{{ */
35153513
opline = zend_emit_op(NULL, ZEND_CASE, &expr_node, &cond_node TSRMLS_CC);
35163514
SET_NODE(opline->result, &case_node);
35173515
if (opline->op1_type == IS_CONST) {
3518-
zval_copy_ctor(&CONSTANT(opline->op1.constant));
3516+
zval_copy_ctor(CT_CONSTANT(opline->op1));
35193517
}
35203518

35213519
jmpnz_opnums[i] = zend_emit_cond_jump(ZEND_JMPNZ, &case_node, 0 TSRMLS_CC);

Zend/zend_compile.h

+160-4
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,34 @@ typedef struct _zend_compiler_context {
5656
HashTable *labels;
5757
} zend_compiler_context;
5858

59+
/* On 64-bi systems less optimal, but more compact VM code leads to better
60+
* performance. So on 32-bit systems we use absolute addresses for jump
61+
* targets and constants, but on 64-bit systems realtive 32-bit offsets */
62+
#if SIZEOF_SIZE_T == 4
63+
# define ZEND_USE_ABS_JMP_ADDR 1
64+
# define ZEND_USE_ABS_CONST_ADDR 1
65+
# define ZEND_EX_USE_LITERALS 0
66+
# define ZEND_EX_USE_RUN_TIME_CACHE 1
67+
#else
68+
# define ZEND_USE_ABS_JMP_ADDR 0
69+
# define ZEND_USE_ABS_CONST_ADDR 0
70+
# define ZEND_EX_USE_LITERALS 1
71+
# define ZEND_EX_USE_RUN_TIME_CACHE 1
72+
#endif
73+
5974
typedef union _znode_op {
6075
uint32_t constant;
6176
uint32_t var;
6277
uint32_t num;
6378
uint32_t opline_num; /* Needs to be signed */
79+
#if ZEND_USE_ABS_JMP_ADDR
6480
zend_op *jmp_addr;
81+
#else
82+
uint32_t jmp_offset;
83+
#endif
84+
#if ZEND_USE_ABS_CONST_ADDR
6585
zval *zv;
86+
#endif
6687
} znode_op;
6788

6889
typedef struct _znode { /* used only during compilation */
@@ -112,8 +133,8 @@ struct _zend_op {
112133
znode_op op1;
113134
znode_op op2;
114135
znode_op result;
115-
zend_ulong extended_value;
116-
uint lineno;
136+
uint32_t extended_value;
137+
uint32_t lineno;
117138
zend_uchar opcode;
118139
zend_uchar op1_type;
119140
zend_uchar op2_type;
@@ -374,12 +395,17 @@ typedef enum _zend_call_kind {
374395
struct _zend_execute_data {
375396
const zend_op *opline; /* executed opline */
376397
zend_execute_data *call; /* current call */
377-
void **run_time_cache;
398+
zval *return_value;
378399
zend_function *func; /* executed op_array */
379400
zval This;
401+
#if ZEND_EX_USE_RUN_TIME_CACHE
402+
void **run_time_cache;
403+
#endif
404+
#if ZEND_EX_USE_LITERALS
405+
zval *literals;
406+
#endif
380407
zend_class_entry *called_scope;
381408
zend_execute_data *prev_execute_data;
382-
zval *return_value;
383409
zend_array *symbol_table;
384410
};
385411

@@ -430,6 +456,136 @@ struct _zend_execute_data {
430456

431457
#define EX_VAR_TO_NUM(n) (ZEND_CALL_VAR(NULL, n) - ZEND_CALL_VAR_NUM(NULL, 0))
432458

459+
#define ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, opline_num) \
460+
((char*)&(op_array)->opcodes[opline_num] - (char*)(opline))
461+
462+
#define ZEND_OFFSET_TO_OPLINE(base, offset) \
463+
((zend_op*)(((char*)(base)) + (int)offset))
464+
465+
#define ZEND_OFFSET_TO_OPLINE_NUM(op_array, base, offset) \
466+
(ZEND_OFFSET_TO_OPLINE(base, offset) - op_array->opcodes)
467+
468+
#if ZEND_USE_ABS_JMP_ADDR
469+
470+
/* run-time jump target */
471+
# define OP_JMP_ADDR(opline, node) \
472+
(node).jmp_addr
473+
474+
/* convert jump target from compile-time to run-time */
475+
# define ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, node) do { \
476+
(node).jmp_addr = (op_array)->opcodes + (node).opline_num; \
477+
} while (0)
478+
479+
/* convert jump target back from run-time to compile-time */
480+
# define ZEND_PASS_TWO_UNDO_JMP_TARGET(op_array, opline, node) do { \
481+
(node).opline_num = (node).jmp_addr - (op_array)->opcodes; \
482+
} while (0)
483+
484+
#else
485+
486+
/* run-time jump target */
487+
# define OP_JMP_ADDR(opline, node) \
488+
ZEND_OFFSET_TO_OPLINE(opline, (node).jmp_offset)
489+
490+
/* convert jump target from compile-time to run-time */
491+
# define ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, node) do { \
492+
(node).jmp_offset = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, (node).opline_num); \
493+
} while (0)
494+
495+
/* convert jump target back from run-time to compile-time */
496+
# define ZEND_PASS_TWO_UNDO_JMP_TARGET(op_array, opline, node) do { \
497+
(node).opline_num = ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, (node).jmp_offset); \
498+
} while (0)
499+
500+
#endif
501+
502+
/* constant-time constant */
503+
# define CT_CONSTANT_EX(op_array, num) \
504+
((op_array)->literals + (num))
505+
506+
# define CT_CONSTANT(node) \
507+
CT_CONSTANT_EX(CG(active_op_array), (node).constant)
508+
509+
#if ZEND_USE_ABS_CONST_ADDR
510+
511+
/* run-time constant */
512+
# define RT_CONSTANT_EX(base, node) \
513+
(node).zv
514+
515+
/* convert constant from compile-time to run-time */
516+
# define ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, node) do { \
517+
(node).zv = CT_CONSTANT_EX(op_array, (node).constant); \
518+
} while (0)
519+
520+
/* convert constant back from run-time to compile-time */
521+
# define ZEND_PASS_TWO_UNDO_CONSTANT(op_array, node) do { \
522+
(node).constant = (node).zv - (op_array)->literals; \
523+
} while (0)
524+
525+
#else
526+
527+
/* run-time constant */
528+
# define RT_CONSTANT_EX(base, node) \
529+
((zval*)(((char*)(base)) + (node).constant))
530+
531+
/* convert constant from compile-time to run-time */
532+
# define ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, node) do { \
533+
(node).constant *= sizeof(zval); \
534+
} while (0)
535+
536+
/* convert constant back from run-time to compile-time (do nothing) */
537+
# define ZEND_PASS_TWO_UNDO_CONSTANT(op_array, node) do { \
538+
(node).constant /= sizeof(zval); \
539+
} while (0)
540+
541+
#endif
542+
543+
#if ZEND_EX_USE_LITERALS
544+
545+
# define EX_LITERALS() \
546+
EX(literals)
547+
548+
# define EX_LOAD_LITERALS(op_array) do { \
549+
EX(literals) = (op_array)->literals; \
550+
} while (0)
551+
552+
#else
553+
554+
# define EX_LITERALS() \
555+
EX(func)->op_array.literals
556+
557+
# define EX_LOAD_LITERALS(op_array) do { \
558+
} while (0)
559+
560+
#endif
561+
562+
/* run-time constant */
563+
#define RT_CONSTANT(op_array, node) \
564+
RT_CONSTANT_EX((op_array)->literals, node)
565+
566+
/* constant in currently executed function */
567+
#define EX_CONSTANT(node) \
568+
RT_CONSTANT_EX(EX_LITERALS(), node)
569+
570+
#if ZEND_EX_USE_RUN_TIME_CACHE
571+
572+
# define EX_RUN_TIME_CACHE() \
573+
EX(run_time_cache)
574+
575+
# define EX_LOAD_RUN_TIME_CACHE(op_array) do { \
576+
EX(run_time_cache) = (op_array)->run_time_cache; \
577+
} while (0)
578+
579+
#else
580+
581+
# define EX_RUN_TIME_CACHE() \
582+
EX(func)->op_array.run_time_cache
583+
584+
# define EX_LOAD_RUN_TIME_CACHE(op_array) do { \
585+
} while (0)
586+
587+
#endif
588+
433589
#define IS_CONST (1<<0)
434590
#define IS_TMP_VAR (1<<1)
435591
#define IS_VAR (1<<2)

0 commit comments

Comments
 (0)