summaryrefslogtreecommitdiff
path: root/ext/opcache
diff options
context:
space:
mode:
Diffstat (limited to 'ext/opcache')
-rw-r--r--ext/opcache/Optimizer/block_pass.c564
-rw-r--r--ext/opcache/Optimizer/compact_literals.c210
-rw-r--r--ext/opcache/Optimizer/nop_removal.c59
-rw-r--r--ext/opcache/Optimizer/optimize_func_calls.c131
-rw-r--r--ext/opcache/Optimizer/optimize_temp_vars_5.c212
-rw-r--r--ext/opcache/Optimizer/pass10.c3
-rw-r--r--ext/opcache/Optimizer/pass1_5.c486
-rw-r--r--ext/opcache/Optimizer/pass2.c62
-rw-r--r--ext/opcache/Optimizer/pass3.c95
-rw-r--r--ext/opcache/Optimizer/pass5.c3
-rw-r--r--ext/opcache/Optimizer/pass9.c8
-rw-r--r--ext/opcache/Optimizer/zend_optimizer.c526
-rw-r--r--ext/opcache/Optimizer/zend_optimizer.h6
-rw-r--r--ext/opcache/Optimizer/zend_optimizer_internal.h88
-rw-r--r--ext/opcache/ZendAccelerator.c1400
-rw-r--r--ext/opcache/ZendAccelerator.h191
-rw-r--r--ext/opcache/config.m412
-rw-r--r--ext/opcache/config.w324
-rw-r--r--ext/opcache/shared_alloc_mmap.c18
-rw-r--r--ext/opcache/shared_alloc_posix.c2
-rw-r--r--ext/opcache/shared_alloc_shm.c2
-rw-r--r--ext/opcache/shared_alloc_win32.c7
-rw-r--r--ext/opcache/tests/bug68252.phpt20
-rw-r--r--ext/opcache/zend_accelerator_blacklist.c26
-rw-r--r--ext/opcache/zend_accelerator_blacklist.h6
-rw-r--r--ext/opcache/zend_accelerator_debug.c5
-rw-r--r--ext/opcache/zend_accelerator_debug.h2
-rw-r--r--ext/opcache/zend_accelerator_hash.c14
-rw-r--r--ext/opcache/zend_accelerator_hash.h20
-rw-r--r--ext/opcache/zend_accelerator_module.c394
-rw-r--r--ext/opcache/zend_accelerator_module.h5
-rw-r--r--ext/opcache/zend_accelerator_util_funcs.c1084
-rw-r--r--ext/opcache/zend_accelerator_util_funcs.h11
-rw-r--r--ext/opcache/zend_persist.c674
-rw-r--r--ext/opcache/zend_persist.h6
-rw-r--r--ext/opcache/zend_persist_calc.c372
-rw-r--r--ext/opcache/zend_shared_alloc.c44
-rw-r--r--ext/opcache/zend_shared_alloc.h14
38 files changed, 3128 insertions, 3658 deletions
diff --git a/ext/opcache/Optimizer/block_pass.c b/ext/opcache/Optimizer/block_pass.c
index 649d613317..f861e4d600 100644
--- a/ext/opcache/Optimizer/block_pass.c
+++ b/ext/opcache/Optimizer/block_pass.c
@@ -1,19 +1,48 @@
+/*
+ +----------------------------------------------------------------------+
+ | Zend OPcache |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1998-2014 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Andi Gutmans <andi@zend.com> |
+ | Zeev Suraski <zeev@zend.com> |
+ | Stanislav Malyshev <stas@zend.com> |
+ | Dmitry Stogov <dmitry@zend.com> |
+ +----------------------------------------------------------------------+
+*/
+
+#include "php.h"
+#include "Optimizer/zend_optimizer.h"
+#include "Optimizer/zend_optimizer_internal.h"
+#include "zend_API.h"
+#include "zend_constants.h"
+#include "zend_execute.h"
+#include "zend_vm.h"
+
#define DEBUG_BLOCKPASS 0
/* Checks if a constant (like "true") may be replaced by its value */
-static int zend_get_persistent_constant(char *name, uint name_len, zval *result, int copy TSRMLS_DC ELS_DC)
+int zend_optimizer_get_persistent_constant(zend_string *name, zval *result, int copy)
{
zend_constant *c;
char *lookup_name;
int retval = 1;
ALLOCA_FLAG(use_heap);
- if (zend_hash_find(EG(zend_constants), name, name_len + 1, (void **) &c) == FAILURE) {
- lookup_name = DO_ALLOCA(name_len + 1);
- memcpy(lookup_name, name, name_len + 1);
- zend_str_tolower(lookup_name, name_len);
+ if ((c = zend_hash_find_ptr(EG(zend_constants), name)) == NULL) {
+ lookup_name = DO_ALLOCA(name->len + 1);
+ memcpy(lookup_name, name->val, name->len + 1);
+ zend_str_tolower(lookup_name, name->len);
- if (zend_hash_find(EG(zend_constants), lookup_name, name_len + 1, (void **) &c) == SUCCESS) {
+ if ((c = zend_hash_str_find_ptr(EG(zend_constants), lookup_name, name->len)) != NULL) {
if (!(c->flags & CONST_CT_SUBST) || (c->flags & CONST_CS)) {
retval = 0;
}
@@ -25,7 +54,7 @@ static int zend_get_persistent_constant(char *name, uint name_len, zval *result,
if (retval) {
if (c->flags & CONST_PERSISTENT) {
- *result = c->value;
+ ZVAL_COPY_VALUE(result, &c->value);
if (copy) {
zval_copy_ctor(result);
}
@@ -80,15 +109,15 @@ static inline void print_block(zend_code_block *block, zend_op *opcodes, char *t
/* find code blocks in op_array
code block is a set of opcodes with single flow of control, i.e. without jmps,
branches, etc. */
-static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg)
+static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg, zend_optimizer_ctx *ctx)
{
zend_op *opline;
zend_op *end = op_array->opcodes + op_array->last;
zend_code_block *blocks, *cur_block;
- zend_uint opno = 0;
+ uint32_t opno = 0;
memset(cfg, 0, sizeof(zend_cfg));
- blocks = cfg->blocks = ecalloc(op_array->last + 2, sizeof(zend_code_block));
+ blocks = cfg->blocks = zend_arena_calloc(&ctx->arena, op_array->last + 2, sizeof(zend_code_block));
opline = op_array->opcodes;
blocks[0].start_opline = opline;
blocks[0].start_opline_no = 0;
@@ -96,15 +125,11 @@ static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg)
switch((unsigned)opline->opcode) {
case ZEND_BRK:
case ZEND_CONT:
-#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
case ZEND_GOTO:
-#endif
/* would not optimize non-optimized BRK/CONTs - we cannot
really know where it jumps, so these optimizations are
too dangerous */
- efree(blocks);
return 0;
-#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
case ZEND_FAST_CALL:
START_BLOCK_OP(ZEND_OP1(opline).opline_num);
if (opline->extended_value) {
@@ -118,17 +143,12 @@ static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg)
}
START_BLOCK_OP(opno + 1);
break;
-#endif
case ZEND_JMP:
START_BLOCK_OP(ZEND_OP1(opline).opline_num);
/* break missing intentionally */
case ZEND_RETURN:
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
case ZEND_RETURN_BY_REF:
-#endif
-#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
case ZEND_GENERATOR_RETURN:
-#endif
case ZEND_EXIT:
case ZEND_THROW:
/* start new block from this+1 */
@@ -148,12 +168,8 @@ static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg)
case ZEND_JMPNZ_EX:
case ZEND_FE_RESET:
case ZEND_NEW:
-#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
case ZEND_JMP_SET:
-#endif
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
- case ZEND_JMP_SET_VAR:
-#endif
+ case ZEND_COALESCE:
START_BLOCK_OP(ZEND_OP2(opline).opline_num);
START_BLOCK_OP(opno + 1);
break;
@@ -169,8 +185,8 @@ static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg)
/* first find block start points */
if (op_array->last_try_catch) {
int i;
- cfg->try = ecalloc(op_array->last_try_catch, sizeof(zend_code_block *));
- cfg->catch = ecalloc(op_array->last_try_catch, sizeof(zend_code_block *));
+ cfg->try = zend_arena_calloc(&ctx->arena, op_array->last_try_catch, sizeof(zend_code_block *));
+ cfg->catch = zend_arena_calloc(&ctx->arena, op_array->last_try_catch, sizeof(zend_code_block *));
for (i = 0; i< op_array->last_try_catch; i++) {
cfg->try[i] = &blocks[op_array->try_catch_array[i].try_op];
cfg->catch[i] = &blocks[op_array->try_catch_array[i].catch_op];
@@ -189,13 +205,12 @@ static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg)
for (i = 0; i< op_array->last_brk_cont; i++) {
if (op_array->brk_cont_array[i].start >= 0 &&
(op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_FREE ||
- op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_SWITCH_FREE)) {
+ op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_END_SILENCE)) {
int parent = op_array->brk_cont_array[i].parent;
while (parent >= 0 &&
op_array->brk_cont_array[parent].start < 0 &&
- op_array->opcodes[op_array->brk_cont_array[parent].brk].opcode != ZEND_FREE &&
- op_array->opcodes[op_array->brk_cont_array[parent].brk].opcode != ZEND_SWITCH_FREE) {
+ op_array->opcodes[op_array->brk_cont_array[parent].brk].opcode != ZEND_FREE) {
parent = op_array->brk_cont_array[parent].parent;
}
op_array->brk_cont_array[i].parent = parent;
@@ -203,14 +218,14 @@ static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg)
}
}
if (j) {
- cfg->loop_start = ecalloc(op_array->last_brk_cont, sizeof(zend_code_block *));
- cfg->loop_cont = ecalloc(op_array->last_brk_cont, sizeof(zend_code_block *));
- cfg->loop_brk = ecalloc(op_array->last_brk_cont, sizeof(zend_code_block *));
+ cfg->loop_start = zend_arena_calloc(&ctx->arena, op_array->last_brk_cont, sizeof(zend_code_block *));
+ cfg->loop_cont = zend_arena_calloc(&ctx->arena, op_array->last_brk_cont, sizeof(zend_code_block *));
+ cfg->loop_brk = zend_arena_calloc(&ctx->arena, op_array->last_brk_cont, sizeof(zend_code_block *));
j = 0;
for (i = 0; i< op_array->last_brk_cont; i++) {
if (op_array->brk_cont_array[i].start >= 0 &&
(op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_FREE ||
- op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_SWITCH_FREE)) {
+ op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_END_SILENCE)) {
if (i != j) {
op_array->brk_cont_array[j] = op_array->brk_cont_array[i];
}
@@ -247,16 +262,11 @@ static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg)
}
switch((unsigned)opline->opcode) {
case ZEND_RETURN:
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
case ZEND_RETURN_BY_REF:
-#endif
-#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
case ZEND_GENERATOR_RETURN:
-#endif
case ZEND_EXIT:
case ZEND_THROW:
break;
-#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
case ZEND_FAST_CALL:
if (opline->extended_value) {
cur_block->op2_to = &blocks[ZEND_OP2(opline).opline_num];
@@ -268,7 +278,6 @@ static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg)
cur_block->op2_to = &blocks[ZEND_OP2(opline).opline_num];
}
break;
-#endif
case ZEND_JMP:
cur_block->op1_to = &blocks[ZEND_OP1(opline).opline_num];
break;
@@ -286,12 +295,8 @@ static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg)
case ZEND_JMPNZ_EX:
case ZEND_FE_RESET:
case ZEND_NEW:
-#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
case ZEND_JMP_SET:
-#endif
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
- case ZEND_JMP_SET_VAR:
-#endif
+ case ZEND_COALESCE:
case ZEND_FE_FETCH:
cur_block->op2_to = &blocks[ZEND_OP2(opline).opline_num];
/* break missing intentionally */
@@ -317,18 +322,16 @@ static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg)
zend_block_source *__s = tob->sources; \
while (__s && __s->from != fromb) __s = __s->next; \
if (__s == NULL) { \
- zend_block_source *__t = emalloc(sizeof(zend_block_source)); \
+ zend_block_source *__t = zend_arena_alloc(&ctx->arena, sizeof(zend_block_source)); \
__t->next = tob->sources; \
tob->sources = __t; \
__t->from = fromb; \
} \
}
-#define DEL_SOURCE(cs) { \
- zend_block_source *__ns = (*cs)->next; \
- efree(*cs); \
- *cs = __ns; \
-}
+#define DEL_SOURCE(cs) do { \
+ *(cs) = (*(cs))->next; \
+ } while (0)
static inline void replace_source(zend_block_source *list, zend_code_block *old, zend_code_block *new)
@@ -400,7 +403,6 @@ static inline void del_source(zend_code_block *from, zend_code_block *to)
/* move 'to'`s references to 'from' */
to->start_opline = NULL;
to->access = 0;
- efree(to->sources);
to->sources = NULL;
from_block->follow_to = to->follow_to;
if (to->op1_to) {
@@ -423,7 +425,7 @@ static inline void del_source(zend_code_block *from, zend_code_block *to)
}
}
-static void delete_code_block(zend_code_block *block)
+static void delete_code_block(zend_code_block *block, zend_optimizer_ctx *ctx)
{
if (block->protected) {
return;
@@ -455,7 +457,7 @@ static void delete_code_block(zend_code_block *block)
block->access = 0;
}
-static void zend_access_path(zend_code_block *block)
+static void zend_access_path(zend_code_block *block, zend_optimizer_ctx *ctx)
{
if (block->access) {
return;
@@ -463,25 +465,25 @@ static void zend_access_path(zend_code_block *block)
block->access = 1;
if (block->op1_to) {
- zend_access_path(block->op1_to);
+ zend_access_path(block->op1_to, ctx);
ADD_SOURCE(block, block->op1_to);
}
if (block->op2_to) {
- zend_access_path(block->op2_to);
+ zend_access_path(block->op2_to, ctx);
ADD_SOURCE(block, block->op2_to);
}
if (block->ext_to) {
- zend_access_path(block->ext_to);
+ zend_access_path(block->ext_to, ctx);
ADD_SOURCE(block, block->ext_to);
}
if (block->follow_to) {
- zend_access_path(block->follow_to);
+ zend_access_path(block->follow_to, ctx);
ADD_SOURCE(block, block->follow_to);
}
}
/* Traverse CFG, mark reachable basic blocks and build back references */
-static void zend_rebuild_access_path(zend_cfg *cfg, zend_op_array *op_array, int find_start)
+static void zend_rebuild_access_path(zend_cfg *cfg, zend_op_array *op_array, int find_start, zend_optimizer_ctx *ctx)
{
zend_code_block *blocks = cfg->blocks;
zend_code_block *start = find_start? NULL : blocks;
@@ -490,31 +492,24 @@ static void zend_rebuild_access_path(zend_cfg *cfg, zend_op_array *op_array, int
/* Mark all blocks as unaccessible and destroy back references */
b = blocks;
while (b != NULL) {
- zend_block_source *cs;
if (!start && b->access) {
start = b;
}
b->access = 0;
- cs = b->sources;
- while (cs) {
- zend_block_source *n = cs->next;
- efree(cs);
- cs = n;
- }
b->sources = NULL;
b = b->next;
}
/* Walk thorough all paths */
- zend_access_path(start);
+ zend_access_path(start, ctx);
/* Add brk/cont paths */
if (op_array->last_brk_cont) {
int i;
for (i=0; i< op_array->last_brk_cont; i++) {
- zend_access_path(cfg->loop_start[i]);
- zend_access_path(cfg->loop_cont[i]);
- zend_access_path(cfg->loop_brk[i]);
+ zend_access_path(cfg->loop_start[i], ctx);
+ zend_access_path(cfg->loop_cont[i], ctx);
+ zend_access_path(cfg->loop_brk[i], ctx);
}
}
@@ -523,7 +518,7 @@ static void zend_rebuild_access_path(zend_cfg *cfg, zend_op_array *op_array, int
int i;
for (i=0; i< op_array->last_try_catch; i++) {
if (!cfg->catch[i]->access) {
- zend_access_path(cfg->catch[i]);
+ zend_access_path(cfg->catch[i], ctx);
}
}
}
@@ -531,34 +526,21 @@ static void zend_rebuild_access_path(zend_cfg *cfg, zend_op_array *op_array, int
/* Data dependencies macros */
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
+#define VAR_NUM_EX(op) VAR_NUM((op).var)
-# define VAR_NUM_EX(op) ((op ## _type & (IS_TMP_VAR|IS_VAR))?VAR_NUM((op).var):(op).var)
+#define VAR_SOURCE(op) Tsource[VAR_NUM(op.var)]
+#define SET_VAR_SOURCE(opline) Tsource[VAR_NUM(opline->result.var)] = opline
-# define VAR_SOURCE(op) Tsource[VAR_NUM(op.var)]
-# define SET_VAR_SOURCE(opline) Tsource[VAR_NUM(opline->result.var)] = opline
-
-# define VAR_UNSET(op) do { if (op ## _type & (IS_TMP_VAR|IS_VAR)) {VAR_SOURCE(op) = NULL;}} while (0)
-
-#else
-
-# define VAR_NUM_EX(op) ((op).op_type == IS_TMP_VAR || (op).op_type == IS_VAR? VAR_NUM((op).u.var) : (op).u.var)
-
-# define VAR_SOURCE(op) Tsource[VAR_NUM(op.u.var)]
-# define SET_VAR_SOURCE(opline) Tsource[VAR_NUM(ZEND_RESULT(opline).var)] = opline
-
-# define VAR_UNSET(op) do { if ((op).op_type == IS_TMP_VAR || (op).op_type == IS_VAR) {VAR_SOURCE(op) = NULL;}} while (0)
-
-#endif
+#define VAR_UNSET(op) do { if (op ## _type & (IS_TMP_VAR|IS_VAR)) {VAR_SOURCE(op) = NULL;}} while (0)
#define convert_to_string_safe(v) \
if (Z_TYPE_P((v)) == IS_NULL) { \
- ZVAL_STRINGL((v), "", 0, 1); \
+ ZVAL_STRINGL((v), "", 0); \
} else { \
convert_to_string((v)); \
}
-static void strip_nop(zend_code_block *block)
+static void strip_nop(zend_code_block *block, zend_optimizer_ctx *ctx)
{
zend_op *opline = block->start_opline;
zend_op *end, *new_end;
@@ -568,7 +550,7 @@ static void strip_nop(zend_code_block *block)
if (block->len == 1) {
/* this block is all NOPs, join with following block */
if (block->follow_to) {
- delete_code_block(block);
+ delete_code_block(block, ctx);
}
return;
}
@@ -603,11 +585,11 @@ static void strip_nop(zend_code_block *block)
block->len = new_end - block->start_opline;
}
-static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array, char *used_ext TSRMLS_DC)
+static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array, char *used_ext, zend_cfg *cfg, zend_optimizer_ctx *ctx)
{
zend_op *opline = block->start_opline;
zend_op *end, *last_op = NULL;
- zend_op **Tsource = NULL;
+ zend_op **Tsource = cfg->Tsource;
print_block(block, op_array->opcodes, "Opt ");
@@ -616,7 +598,7 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array,
if (block->len == 1) {
/* this block is all NOPs, join with following block */
if (block->follow_to) {
- delete_code_block(block);
+ delete_code_block(block, ctx);
}
return;
}
@@ -626,19 +608,17 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array,
}
/* we track data dependencies only insight a single basic block */
- if (op_array->T) {
- Tsource = ecalloc(op_array->T, sizeof(zend_op *));
- }
+ memset(Tsource, 0, (op_array->last_var + op_array->T) * sizeof(zend_op *));
opline = block->start_opline;
end = opline + block->len;
while ((op_array->T) && (opline < end)) {
/* strip X = QM_ASSIGN(const) */
- if (ZEND_OP1_TYPE(opline) == IS_TMP_VAR &&
+ if ((ZEND_OP1_TYPE(opline) & (IS_TMP_VAR|IS_VAR)) &&
VAR_SOURCE(opline->op1) &&
VAR_SOURCE(opline->op1)->opcode == ZEND_QM_ASSIGN &&
ZEND_OP1_TYPE(VAR_SOURCE(opline->op1)) == IS_CONST &&
opline->opcode != ZEND_CASE && /* CASE _always_ expects variable */
- opline->opcode != ZEND_FETCH_DIM_TMP_VAR && /* in 5.1, FETCH_DIM_TMP_VAR expects T */
+ opline->opcode != ZEND_FETCH_LIST &&
opline->opcode != ZEND_FE_RESET &&
opline->opcode != ZEND_FREE
) {
@@ -646,13 +626,13 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array,
zval c = ZEND_OP1_LITERAL(src);
VAR_UNSET(opline->op1);
zval_copy_ctor(&c);
- update_op1_const(op_array, opline, &c TSRMLS_CC);
+ zend_optimizer_update_op1_const(op_array, opline, &c);
literal_dtor(&ZEND_OP1_LITERAL(src));
MAKE_NOP(src);
}
/* T = QM_ASSIGN(C), F(T) => NOP, F(C) */
- if (ZEND_OP2_TYPE(opline) == IS_TMP_VAR &&
+ if ((ZEND_OP2_TYPE(opline) & (IS_TMP_VAR|IS_VAR)) &&
VAR_SOURCE(opline->op2) &&
VAR_SOURCE(opline->op2)->opcode == ZEND_QM_ASSIGN &&
ZEND_OP1_TYPE(VAR_SOURCE(opline->op2)) == IS_CONST) {
@@ -660,30 +640,14 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array,
zval c = ZEND_OP1_LITERAL(src);
VAR_UNSET(opline->op2);
zval_copy_ctor(&c);
- update_op2_const(op_array, opline, &c TSRMLS_CC);
+ zend_optimizer_update_op2_const(op_array, opline, &c);
literal_dtor(&ZEND_OP1_LITERAL(src));
MAKE_NOP(src);
}
- /* T = PRINT(X), F(T) => ECHO(X), F(1) */
- if (ZEND_OP1_TYPE(opline) == IS_TMP_VAR &&
- VAR_SOURCE(opline->op1) &&
- VAR_SOURCE(opline->op1)->opcode == ZEND_PRINT &&
- opline->opcode != ZEND_CASE && opline->opcode != ZEND_FREE) {
- ZEND_OP1_TYPE(opline) = IS_CONST;
- LITERAL_LONG(opline->op1, 1);
- }
-
- if (ZEND_OP2_TYPE(opline) == IS_TMP_VAR &&
- VAR_SOURCE(opline->op2) &&
- VAR_SOURCE(opline->op2)->opcode == ZEND_PRINT) {
- ZEND_OP2_TYPE(opline) = IS_CONST;
- LITERAL_LONG(opline->op2, 1);
- }
-
/* T = CAST(X, String), ECHO(T) => NOP, ECHO(X) */
- if ((opline->opcode == ZEND_ECHO || opline->opcode == ZEND_PRINT) &&
- ZEND_OP1_TYPE(opline) == IS_TMP_VAR &&
+ if (opline->opcode == ZEND_ECHO &&
+ ZEND_OP1_TYPE(opline) & (IS_TMP_VAR|IS_VAR) &&
VAR_SOURCE(opline->op1) &&
VAR_SOURCE(opline->op1)->opcode == ZEND_CAST &&
VAR_SOURCE(opline->op1)->extended_value == IS_STRING) {
@@ -692,18 +656,6 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array,
MAKE_NOP(src);
}
- /* T = PRINT(X), FREE(T) => ECHO(X) */
- if (opline->opcode == ZEND_FREE &&
- ZEND_OP1_TYPE(opline) == IS_TMP_VAR &&
- VAR_SOURCE(opline->op1)) {
- zend_op *src = VAR_SOURCE(opline->op1);
- if (src->opcode == ZEND_PRINT) {
- src->opcode = ZEND_ECHO;
- ZEND_RESULT_TYPE(src) = IS_UNUSED;
- MAKE_NOP(opline);
- }
- }
-
/* T = BOOL(X), FREE(T) => NOP */
if (opline->opcode == ZEND_FREE &&
ZEND_OP1_TYPE(opline) == IS_TMP_VAR &&
@@ -740,7 +692,7 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array,
int flen = FUNCTION_CACHE->funcs[Z_LVAL(ZEND_OP1_LITERAL(fcall))].name_len;
if(flen == sizeof("defined")-1 && zend_binary_strcasecmp(fname, flen, "defined", sizeof("defined")-1) == 0) {
zval c;
- if(zend_get_persistent_constant(Z_STRVAL_P(arg), Z_STRLEN_P(arg), &c, 0 TSRMLS_CC ELS_CC) != 0) {
+ if(zend_optimizer_get_persistent_constant(Z_STR_P(arg), &c, 0 ELS_CC) != 0) {
literal_dtor(arg);
MAKE_NOP(sv);
MAKE_NOP(fcall);
@@ -751,7 +703,7 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array,
(flen == sizeof("is_callable")-1 && zend_binary_strcasecmp(fname, flen, "is_callable", sizeof("is_callable")-1) == 0)
) {
zend_function *function;
- if(zend_hash_find(EG(function_table), Z_STRVAL_P(arg), Z_STRLEN_P(arg)+1, (void **)&function) == SUCCESS) {
+ if((function = zend_hash_find_ptr(EG(function_table), Z_STR_P(arg))) != NULL) {
literal_dtor(arg);
MAKE_NOP(sv);
MAKE_NOP(fcall);
@@ -760,16 +712,16 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array,
}
} else if(flen == sizeof("constant")-1 && zend_binary_strcasecmp(fname, flen, "constant", sizeof("constant")-1) == 0) {
zval c;
- if(zend_get_persistent_constant(Z_STRVAL_P(arg), Z_STRLEN_P(arg), &c, 1 TSRMLS_CC ELS_CC) != 0) {
+ if(zend_optimizer_get_persistent_constant(Z_STR_P(arg), &c, 1 ELS_CC) != 0) {
literal_dtor(arg);
MAKE_NOP(sv);
MAKE_NOP(fcall);
- ZEND_OP1_LITERAL(opline) = zend_optimizer_add_literal(op_array, &c TSRMLS_CC);
+ ZEND_OP1_LITERAL(opline) = zend_optimizer_add_literal(op_array, &c);
/* no copy ctor - get already copied it */
ZEND_OP1_TYPE(opline) = IS_CONST;
}
} else if(flen == sizeof("extension_loaded")-1 && zend_binary_strcasecmp(fname, flen, "extension_loaded", sizeof("extension_loaded")-1) == 0) {
- if(zend_hash_exists(&module_registry, Z_STRVAL_P(arg), Z_STRLEN_P(arg)+1)) {
+ if(zend_hash_exists(&module_registry, Z_STR_P(arg))) {
literal_dtor(arg);
MAKE_NOP(sv);
MAKE_NOP(fcall);
@@ -785,20 +737,35 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array,
* IS_EQ(FALSE, X) => BOOL_NOT(X)
* IS_NOT_EQ(TRUE, X) => BOOL_NOT(X)
* IS_NOT_EQ(FALSE, X) => BOOL(X)
+ * CASE(TRUE, X) => BOOL(X)
+ * CASE(FALSE, X) => BOOL_NOT(X)
*/
if (opline->opcode == ZEND_IS_EQUAL ||
- opline->opcode == ZEND_IS_NOT_EQUAL) {
+ opline->opcode == ZEND_IS_NOT_EQUAL ||
+ opline->opcode == ZEND_CASE) {
if (ZEND_OP1_TYPE(opline) == IS_CONST &&
- Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_BOOL) {
+// TODO: Optimization of comparison with null may be not safe ???
+#if 1
+ (Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_FALSE ||
+ Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_TRUE)) {
+#else
+ Z_TYPE(ZEND_OP1_LITERAL(opline)) <= IS_TRUE) {
+#endif
opline->opcode =
- ((opline->opcode == ZEND_IS_EQUAL) == Z_LVAL(ZEND_OP1_LITERAL(opline)))?
+ ((opline->opcode != ZEND_IS_NOT_EQUAL) == ((Z_TYPE(ZEND_OP1_LITERAL(opline))) == IS_TRUE)) ?
ZEND_BOOL : ZEND_BOOL_NOT;
COPY_NODE(opline->op1, opline->op2);
SET_UNUSED(opline->op2);
} else if (ZEND_OP2_TYPE(opline) == IS_CONST &&
- Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_BOOL) {
+// TODO: Optimization of comparison with null may be not safe ???
+#if 1
+ (Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_FALSE ||
+ Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_TRUE)) {
+#else
+ Z_TYPE(ZEND_OP2_LITERAL(opline)) <= IS_TRUE) {
+#endif
opline->opcode =
- ((opline->opcode == ZEND_IS_EQUAL) == Z_LVAL(ZEND_OP2_LITERAL(opline)))?
+ ((opline->opcode != ZEND_IS_NOT_EQUAL) == ((Z_TYPE(ZEND_OP2_LITERAL(opline))) == IS_TRUE)) ?
ZEND_BOOL : ZEND_BOOL_NOT;
SET_UNUSED(opline->op2);
}
@@ -884,10 +851,10 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array,
opline->opcode == ZEND_JMPNZ_EX ||
opline->opcode == ZEND_JMPNZ ||
opline->opcode == ZEND_JMPZNZ) &&
- ZEND_OP1_TYPE(opline) == IS_TMP_VAR &&
+ (ZEND_OP1_TYPE(opline) & (IS_TMP_VAR|IS_VAR)) &&
VAR_SOURCE(opline->op1) != NULL &&
(!used_ext[VAR_NUM(ZEND_OP1(opline).var)] ||
- (ZEND_RESULT_TYPE(opline) == IS_TMP_VAR &&
+ ((ZEND_RESULT_TYPE(opline) & (IS_TMP_VAR|IS_VAR)) &&
ZEND_RESULT(opline).var == ZEND_OP1(opline).var)) &&
(VAR_SOURCE(opline->op1)->opcode == ZEND_BOOL ||
VAR_SOURCE(opline->op1)->opcode == ZEND_QM_ASSIGN)) {
@@ -907,7 +874,7 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array,
* Float to string conversion may be affected by current
* locale setting.
*/
- int l;
+ int l, old_len;
if (Z_TYPE(ZEND_OP1_LITERAL(opline)) != IS_STRING) {
convert_to_string_safe(&ZEND_OP1_LITERAL(opline));
@@ -915,24 +882,24 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array,
if (Z_TYPE(ZEND_OP1_LITERAL(last_op)) != IS_STRING) {
convert_to_string_safe(&ZEND_OP1_LITERAL(last_op));
}
- l = Z_STRLEN(ZEND_OP1_LITERAL(opline)) + Z_STRLEN(ZEND_OP1_LITERAL(last_op));
- if (IS_INTERNED(Z_STRVAL(ZEND_OP1_LITERAL(last_op)))) {
- char *tmp = emalloc(l + 1);
- memcpy(tmp, Z_STRVAL(ZEND_OP1_LITERAL(last_op)), l + 1);
- Z_STRVAL(ZEND_OP1_LITERAL(last_op)) = tmp;
+ old_len = Z_STRLEN(ZEND_OP1_LITERAL(last_op));
+ l = old_len + Z_STRLEN(ZEND_OP1_LITERAL(opline));
+ if (!Z_REFCOUNTED(ZEND_OP1_LITERAL(last_op))) {
+ zend_string *tmp = zend_string_alloc(l, 0);
+ memcpy(tmp->val, Z_STRVAL(ZEND_OP1_LITERAL(last_op)), old_len);
+ Z_STR(ZEND_OP1_LITERAL(last_op)) = tmp;
} else {
- Z_STRVAL(ZEND_OP1_LITERAL(last_op)) = erealloc(Z_STRVAL(ZEND_OP1_LITERAL(last_op)), l + 1);
+ Z_STR(ZEND_OP1_LITERAL(last_op)) = zend_string_realloc(Z_STR(ZEND_OP1_LITERAL(last_op)), l, 0);
}
- memcpy(Z_STRVAL(ZEND_OP1_LITERAL(last_op))+Z_STRLEN(ZEND_OP1_LITERAL(last_op)), Z_STRVAL(ZEND_OP1_LITERAL(opline)), Z_STRLEN(ZEND_OP1_LITERAL(opline)));
+ Z_TYPE_INFO(ZEND_OP1_LITERAL(last_op)) = IS_STRING_EX;
+ memcpy(Z_STRVAL(ZEND_OP1_LITERAL(last_op)) + old_len, Z_STRVAL(ZEND_OP1_LITERAL(opline)), Z_STRLEN(ZEND_OP1_LITERAL(opline)));
Z_STRVAL(ZEND_OP1_LITERAL(last_op))[l] = '\0';
zval_dtor(&ZEND_OP1_LITERAL(opline));
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
- Z_STRVAL(ZEND_OP1_LITERAL(opline)) = (char*)zend_new_interned_string(Z_STRVAL(ZEND_OP1_LITERAL(last_op)), l + 1, 1 TSRMLS_CC);
- Z_TYPE(ZEND_OP1_LITERAL(last_op)) = IS_NULL;
-#else
- Z_STRVAL(ZEND_OP1_LITERAL(opline)) = Z_STRVAL(ZEND_OP1_LITERAL(last_op));
-#endif
- Z_STRLEN(ZEND_OP1_LITERAL(opline)) = l;
+ Z_STR(ZEND_OP1_LITERAL(opline)) = zend_new_interned_string(Z_STR(ZEND_OP1_LITERAL(last_op)));
+ if (!Z_REFCOUNTED(ZEND_OP1_LITERAL(opline))) {
+ Z_TYPE_FLAGS(ZEND_OP1_LITERAL(opline)) &= ~ (IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE);
+ }
+ ZVAL_NULL(&ZEND_OP1_LITERAL(last_op));
MAKE_NOP(last_op);
} else if (opline->opcode == ZEND_CONCAT &&
ZEND_OP2_TYPE(opline) == IS_CONST &&
@@ -944,7 +911,7 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array,
ZEND_RESULT(VAR_SOURCE(opline->op1)).var == ZEND_OP1(opline).var) {
/* compress consecutive CONCATs */
zend_op *src = VAR_SOURCE(opline->op1);
- int l;
+ int l, old_len;
if (Z_TYPE(ZEND_OP2_LITERAL(opline)) != IS_STRING) {
convert_to_string_safe(&ZEND_OP2_LITERAL(opline));
@@ -959,26 +926,24 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array,
opline->opcode = ZEND_ADD_STRING;
}
COPY_NODE(opline->op1, src->op1);
- l = Z_STRLEN(ZEND_OP2_LITERAL(opline)) + Z_STRLEN(ZEND_OP2_LITERAL(src));
- if (IS_INTERNED(Z_STRVAL(ZEND_OP2_LITERAL(src)))) {
- char *tmp = emalloc(l + 1);
- memcpy(tmp, Z_STRVAL(ZEND_OP2_LITERAL(src)), l + 1);
- Z_STRVAL(ZEND_OP2_LITERAL(src)) = tmp;
+ old_len = Z_STRLEN(ZEND_OP2_LITERAL(src));
+ l = old_len + Z_STRLEN(ZEND_OP2_LITERAL(opline));
+ if (!Z_REFCOUNTED(ZEND_OP2_LITERAL(src))) {
+ zend_string *tmp = zend_string_alloc(l, 0);
+ memcpy(tmp->val, Z_STRVAL(ZEND_OP2_LITERAL(src)), old_len);
+ Z_STR(ZEND_OP2_LITERAL(last_op)) = tmp;
} else {
- Z_STRVAL(ZEND_OP2_LITERAL(src)) = erealloc(Z_STRVAL(ZEND_OP2_LITERAL(src)), l + 1);
+ Z_STR(ZEND_OP2_LITERAL(src)) = zend_string_realloc(Z_STR(ZEND_OP2_LITERAL(src)), l, 0);
}
- memcpy(Z_STRVAL(ZEND_OP2_LITERAL(src))+Z_STRLEN(ZEND_OP2_LITERAL(src)), Z_STRVAL(ZEND_OP2_LITERAL(opline)), Z_STRLEN(ZEND_OP2_LITERAL(opline)));
+ Z_TYPE_INFO(ZEND_OP2_LITERAL(last_op)) = IS_STRING_EX;
+ memcpy(Z_STRVAL(ZEND_OP2_LITERAL(src)) + old_len, Z_STRVAL(ZEND_OP2_LITERAL(opline)), Z_STRLEN(ZEND_OP2_LITERAL(opline)));
Z_STRVAL(ZEND_OP2_LITERAL(src))[l] = '\0';
- if (!IS_INTERNED(Z_STRVAL(ZEND_OP2_LITERAL(opline)))) {
- efree(Z_STRVAL(ZEND_OP2_LITERAL(opline)));
+ zend_string_release(Z_STR(ZEND_OP2_LITERAL(opline)));
+ Z_STR(ZEND_OP2_LITERAL(opline)) = zend_new_interned_string(Z_STR(ZEND_OP2_LITERAL(src)));
+ if (!Z_REFCOUNTED(ZEND_OP2_LITERAL(opline))) {
+ Z_TYPE_FLAGS(ZEND_OP2_LITERAL(opline)) &= ~ (IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE);
}
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
- Z_STRVAL(ZEND_OP2_LITERAL(opline)) = (char*)zend_new_interned_string(Z_STRVAL(ZEND_OP2_LITERAL(src)), l + 1, 1 TSRMLS_CC);
- Z_TYPE(ZEND_OP2_LITERAL(src)) = IS_NULL;
-#else
- Z_STRVAL(ZEND_OP2_LITERAL(opline)) = Z_STRVAL(ZEND_OP2_LITERAL(src));
-#endif
- Z_STRLEN(ZEND_OP2_LITERAL(opline)) = l;
+ ZVAL_NULL(&ZEND_OP2_LITERAL(src));
MAKE_NOP(src);
} else if ((opline->opcode == ZEND_ADD_STRING || opline->opcode == ZEND_ADD_VAR) && ZEND_OP1_TYPE(opline) == IS_CONST) {
/* convert ADD_STRING(C1, C2) to CONCAT(C1, C2) */
@@ -987,7 +952,7 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array,
} else if (opline->opcode == ZEND_ADD_CHAR && ZEND_OP1_TYPE(opline) == IS_CONST && ZEND_OP2_TYPE(opline) == IS_CONST) {
/* convert ADD_CHAR(C1, C2) to CONCAT(C1, C2) */
char c = (char)Z_LVAL(ZEND_OP2_LITERAL(opline));
- ZVAL_STRINGL(&ZEND_OP2_LITERAL(opline), &c, 1, 1);
+ ZVAL_STRINGL(&ZEND_OP2_LITERAL(opline), &c, 1);
opline->opcode = ZEND_CONCAT;
continue;
} else if ((opline->opcode == ZEND_ADD ||
@@ -1011,7 +976,7 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array,
ZEND_OP1_TYPE(opline)==IS_CONST &&
ZEND_OP2_TYPE(opline)==IS_CONST) {
/* evaluate constant expressions */
- int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC) = get_binary_op(opline->opcode);
+ int (*binary_op)(zval *result, zval *op1, zval *op2) = get_binary_op(opline->opcode);
zval result;
int er;
@@ -1028,15 +993,12 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array,
}
er = EG(error_reporting);
EG(error_reporting) = 0;
- if (binary_op(&result, &ZEND_OP1_LITERAL(opline), &ZEND_OP2_LITERAL(opline) TSRMLS_CC) == SUCCESS) {
- PZ_SET_REFCOUNT_P(&result, 1);
- PZ_UNSET_ISREF_P(&result);
-
+ if (binary_op(&result, &ZEND_OP1_LITERAL(opline), &ZEND_OP2_LITERAL(opline)) == SUCCESS) {
literal_dtor(&ZEND_OP1_LITERAL(opline));
literal_dtor(&ZEND_OP2_LITERAL(opline));
opline->opcode = ZEND_QM_ASSIGN;
SET_UNUSED(opline->op2);
- update_op1_const(op_array, opline, &result TSRMLS_CC);
+ zend_optimizer_update_op1_const(op_array, opline, &result);
}
EG(error_reporting) = er;
} else if ((opline->opcode == ZEND_BOOL ||
@@ -1047,24 +1009,18 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array,
zval result;
if (unary_op) {
-#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
unary_op(&result, &ZEND_OP1_LITERAL(opline));
-#else
- unary_op(&result, &ZEND_OP1_LITERAL(opline) TSRMLS_CC);
-#endif
literal_dtor(&ZEND_OP1_LITERAL(opline));
} else {
/* BOOL */
result = ZEND_OP1_LITERAL(opline);
convert_to_boolean(&result);
- Z_TYPE(ZEND_OP1_LITERAL(opline)) = IS_NULL;
+ ZVAL_NULL(&ZEND_OP1_LITERAL(opline));
}
- PZ_SET_REFCOUNT_P(&result, 1);
- PZ_UNSET_ISREF_P(&result);
opline->opcode = ZEND_QM_ASSIGN;
- update_op1_const(op_array, opline, &result TSRMLS_CC);
+ zend_optimizer_update_op1_const(op_array, opline, &result);
} else if ((opline->opcode == ZEND_RETURN || opline->opcode == ZEND_EXIT) &&
- ZEND_OP1_TYPE(opline) == IS_TMP_VAR &&
+ (ZEND_OP1_TYPE(opline) & (IS_TMP_VAR|IS_VAR)) &&
VAR_SOURCE(opline->op1) &&
VAR_SOURCE(opline->op1)->opcode == ZEND_QM_ASSIGN) {
/* T = QM_ASSIGN(X), RETURN(T) to RETURN(X) */
@@ -1073,25 +1029,6 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array,
COPY_NODE(opline->op1, src->op1);
MAKE_NOP(src);
} else if ((opline->opcode == ZEND_ADD_STRING ||
- opline->opcode == ZEND_ADD_CHAR) &&
- ZEND_OP1_TYPE(opline) == IS_TMP_VAR &&
- VAR_SOURCE(opline->op1) &&
- VAR_SOURCE(opline->op1)->opcode == ZEND_INIT_STRING) {
- /* convert T = INIT_STRING(), T = ADD_STRING(T, X) to T = QM_ASSIGN(X) */
- /* CHECKME: Remove ZEND_ADD_VAR optimization, since some conversions -
- namely, BOOL(false)->string - don't allocate memory but use empty_string
- and ADD_CHAR fails */
- zend_op *src = VAR_SOURCE(opline->op1);
- VAR_UNSET(opline->op1);
- COPY_NODE(opline->op1, opline->op2);
- if (opline->opcode == ZEND_ADD_CHAR) {
- char c = (char)Z_LVAL(ZEND_OP2_LITERAL(opline));
- ZVAL_STRINGL(&ZEND_OP1_LITERAL(opline), &c, 1, 1);
- }
- SET_UNUSED(opline->op2);
- MAKE_NOP(src);
- opline->opcode = ZEND_QM_ASSIGN;
- } else if ((opline->opcode == ZEND_ADD_STRING ||
opline->opcode == ZEND_ADD_CHAR ||
opline->opcode == ZEND_ADD_VAR ||
opline->opcode == ZEND_CONCAT) &&
@@ -1107,28 +1044,16 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array,
COPY_NODE(opline->op1, src->op1);
if (opline->opcode == ZEND_ADD_CHAR) {
char c = (char)Z_LVAL(ZEND_OP2_LITERAL(opline));
- ZVAL_STRINGL(&ZEND_OP2_LITERAL(opline), &c, 1, 1);
+ ZVAL_STRINGL(&ZEND_OP2_LITERAL(opline), &c, 1);
}
opline->opcode = ZEND_CONCAT;
literal_dtor(&ZEND_OP2_LITERAL(src)); /* will take care of empty_string too */
MAKE_NOP(src);
- } else if (opline->opcode == ZEND_ADD_VAR &&
- ZEND_OP1_TYPE(opline) == IS_TMP_VAR &&
- VAR_SOURCE(opline->op1) &&
- VAR_SOURCE(opline->op1)->opcode == ZEND_INIT_STRING) {
- /* convert T = INIT_STRING(), T = ADD_VAR(T, X) to T = CAST(STRING, X) */
- zend_op *src = VAR_SOURCE(opline->op1);
- VAR_UNSET(opline->op1);
- COPY_NODE(opline->op1, opline->op2);
- SET_UNUSED(opline->op2);
- MAKE_NOP(src);
- opline->opcode = ZEND_CAST;
- opline->extended_value = IS_STRING;
} else if ((opline->opcode == ZEND_ADD_STRING ||
opline->opcode == ZEND_ADD_CHAR ||
opline->opcode == ZEND_ADD_VAR ||
opline->opcode == ZEND_CONCAT) &&
- ZEND_OP1_TYPE(opline) == IS_TMP_VAR &&
+ (ZEND_OP1_TYPE(opline) & (IS_TMP_VAR|IS_VAR)) &&
VAR_SOURCE(opline->op1) &&
VAR_SOURCE(opline->op1)->opcode == ZEND_CAST &&
VAR_SOURCE(opline->op1)->extended_value == IS_STRING) {
@@ -1138,13 +1063,12 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array,
COPY_NODE(opline->op1, src->op1);
if (opline->opcode == ZEND_ADD_CHAR) {
char c = (char)Z_LVAL(ZEND_OP2_LITERAL(opline));
- ZVAL_STRINGL(&ZEND_OP2_LITERAL(opline), &c, 1, 1);
+ ZVAL_STRINGL(&ZEND_OP2_LITERAL(opline), &c, 1);
}
opline->opcode = ZEND_CONCAT;
MAKE_NOP(src);
} else if (opline->opcode == ZEND_QM_ASSIGN &&
- ZEND_OP1_TYPE(opline) == IS_TMP_VAR &&
- ZEND_RESULT_TYPE(opline) == IS_TMP_VAR &&
+ ZEND_OP1_TYPE(opline) == ZEND_RESULT_TYPE(opline) &&
ZEND_OP1(opline).var == ZEND_RESULT(opline).var) {
/* strip T = QM_ASSIGN(T) */
MAKE_NOP(opline);
@@ -1177,11 +1101,7 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array,
opline++;
}
- strip_nop(block);
-
- if (op_array->T) {
- efree(Tsource);
- }
+ strip_nop(block, ctx);
}
/* Rebuild plain (optimized) op_array from CFG */
@@ -1236,12 +1156,6 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array)
opline->lineno = opline[-1].lineno;
opline++;
}
-#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
- MAKE_NOP(opline);
- opline->opcode = ZEND_HANDLE_EXCEPTION;
- opline->lineno = opline[-1].lineno;
- opline++;
-#endif
op_array->last = opline-new_opcodes;
@@ -1256,8 +1170,6 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array)
}
}
op_array->last_try_catch = j;
- efree(cfg->try);
- efree(cfg->catch);
}
/* adjust loop jump targets */
@@ -1268,9 +1180,6 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array)
op_array->brk_cont_array[i].cont = cfg->loop_cont[i]->start_opline - new_opcodes;
op_array->brk_cont_array[i].brk = cfg->loop_brk[i]->start_opline - new_opcodes;
}
- efree(cfg->loop_start);
- efree(cfg->loop_cont);
- efree(cfg->loop_brk);
}
/* adjust jump targets */
@@ -1296,10 +1205,9 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array)
efree(op_array->opcodes);
op_array->opcodes = erealloc(new_opcodes, op_array->last * sizeof(zend_op));
-#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
/* adjust early binding list */
- if (op_array->early_binding != (zend_uint)-1) {
- zend_uint *opline_num = &op_array->early_binding;
+ if (op_array->early_binding != (uint32_t)-1) {
+ uint32_t *opline_num = &op_array->early_binding;
zend_op *end;
opline = op_array->opcodes;
@@ -1313,10 +1221,9 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array)
}
*opline_num = -1;
}
-#endif
}
-static void zend_jmp_optimization(zend_code_block *block, zend_op_array *op_array, zend_code_block *blocks TSRMLS_DC)
+static void zend_jmp_optimization(zend_code_block *block, zend_op_array *op_array, zend_code_block *blocks, zend_cfg *cfg, zend_optimizer_ctx *ctx)
{
/* last_op is the last opcode of the current block */
zend_op *last_op = (block->start_opline + block->len - 1);
@@ -1343,7 +1250,7 @@ static void zend_jmp_optimization(zend_code_block *block, zend_op_array *op_arra
block->len--;
if (block->len == 0) {
/* this block is nothing but NOP now */
- delete_code_block(block);
+ delete_code_block(block, ctx);
}
break;
}
@@ -1355,17 +1262,11 @@ static void zend_jmp_optimization(zend_code_block *block, zend_op_array *op_arra
/* JMP L, L: JMP L1 -> JMP L1 */
/* JMP L, L: JMPZNZ L1,L2 -> JMPZNZ L1,L2 */
*last_op = *target;
-#if ZEND_EXTENSION_API_NO < PHP_5_4_X_API_NO
- if (ZEND_OP1_TYPE(last_op) == IS_CONST) {
- zval_copy_ctor(&ZEND_OP1_LITERAL(last_op));
- }
-#else
if (ZEND_OP1_TYPE(last_op) == IS_CONST) {
zval zv = ZEND_OP1_LITERAL(last_op);
zval_copy_ctor(&zv);
- last_op->op1.constant = zend_optimizer_add_literal(op_array, &zv TSRMLS_CC);
+ last_op->op1.constant = zend_optimizer_add_literal(op_array, &zv);
}
-#endif
del_source(block, block->op1_to);
if (block->op1_to->op2_to) {
block->op2_to = block->op1_to->op2_to;
@@ -1382,26 +1283,16 @@ static void zend_jmp_optimization(zend_code_block *block, zend_op_array *op_arra
block->op1_to = NULL;
}
} else if (target->opcode == ZEND_RETURN ||
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
target->opcode == ZEND_RETURN_BY_REF ||
-#endif
-#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
target->opcode == ZEND_FAST_RET ||
-#endif
target->opcode == ZEND_EXIT) {
/* JMP L, L: RETURN to immediate RETURN */
*last_op = *target;
-#if ZEND_EXTENSION_API_NO < PHP_5_4_X_API_NO
- if (ZEND_OP1_TYPE(last_op) == IS_CONST) {
- zval_copy_ctor(&ZEND_OP1_LITERAL(last_op));
- }
-#else
if (ZEND_OP1_TYPE(last_op) == IS_CONST) {
zval zv = ZEND_OP1_LITERAL(last_op);
zval_copy_ctor(&zv);
- last_op->op1.constant = zend_optimizer_add_literal(op_array, &zv TSRMLS_CC);
+ last_op->op1.constant = zend_optimizer_add_literal(op_array, &zv);
}
-#endif
del_source(block, block->op1_to);
block->op1_to = NULL;
#if 0
@@ -1409,10 +1300,9 @@ static void zend_jmp_optimization(zend_code_block *block, zend_op_array *op_arra
} else if (0&& block->op1_to != block &&
block->op1_to != blocks &&
op_array->last_try_catch == 0 &&
- target->opcode != ZEND_FREE &&
- target->opcode != ZEND_SWITCH_FREE) {
+ target->opcode != ZEND_FREE) {
/* Block Reordering (saves one JMP on each "for" loop iteration)
- * It is disabled for some cases (ZEND_FREE/ZEND_SWITCH_FREE)
+ * It is disabled for some cases (ZEND_FREE)
* which may break register allocation.
*/
zend_bool can_reorder = 0;
@@ -1452,7 +1342,7 @@ static void zend_jmp_optimization(zend_code_block *block, zend_op_array *op_arra
block->len--;
if(block->len == 0) {
/* this block is nothing but NOP now */
- delete_code_block(block);
+ delete_code_block(block, ctx);
}
break;
}
@@ -1467,6 +1357,7 @@ static void zend_jmp_optimization(zend_code_block *block, zend_op_array *op_arra
/* constant conditional JMPs */
if (ZEND_OP1_TYPE(last_op) == IS_CONST) {
int should_jmp = zend_is_true(&ZEND_OP1_LITERAL(last_op));
+
if (last_op->opcode == ZEND_JMPZ) {
should_jmp = !should_jmp;
}
@@ -1491,7 +1382,7 @@ static void zend_jmp_optimization(zend_code_block *block, zend_op_array *op_arra
if (block->op2_to) {
zend_uchar same_type = ZEND_OP1_TYPE(last_op);
- zend_uint same_var = VAR_NUM_EX(last_op->op1);
+ uint32_t same_var = VAR_NUM_EX(last_op->op1);
zend_op *target;
zend_op *target_end;
zend_code_block *target_block = block->op2_to;;
@@ -1610,6 +1501,7 @@ next_target:
/* constant conditional JMPs */
if (ZEND_OP1_TYPE(last_op) == IS_CONST) {
int should_jmp = zend_is_true(&ZEND_OP1_LITERAL(last_op));
+
if (last_op->opcode == ZEND_JMPZ_EX) {
should_jmp = !should_jmp;
}
@@ -1629,19 +1521,13 @@ next_target:
zend_op *target, *target_end;
char *same_t=NULL;
zend_code_block *target_block;
- int var_num = 0;
- if (op_array->T >= (zend_uint)op_array->last_var) {
- var_num = op_array->T;
- } else {
- var_num = op_array->last_var;
- }
+ int var_num = op_array->last_var + op_array->T;
+
if (var_num <= 0) {
return;
}
- same_t = ecalloc(var_num, sizeof(char));
- if (same_t == NULL) {
- return;
- }
+ same_t = cfg->same_t;
+ memset(same_t, 0, var_num);
same_t[VAR_NUM_EX(last_op->op1)] |= ZEND_OP1_TYPE(last_op);
same_t[VAR_NUM_EX(last_op->result)] |= ZEND_RESULT_TYPE(last_op);
target_block = block->op2_to;
@@ -1715,9 +1601,6 @@ next_target_ex:
}
ADD_SOURCE(block, block->op2_to);
}
- if (same_t != NULL) {
- efree(same_t);
- }
}
break;
@@ -1836,47 +1719,34 @@ next_target_znz:
/* Global data dependencies */
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
-
-# define T_USAGE(op) do { \
+#define T_USAGE(op) do { \
if ((op ## _type & (IS_VAR | IS_TMP_VAR)) && \
!defined_here[VAR_NUM(op.var)] && !used_ext[VAR_NUM(op.var)]) { \
used_ext[VAR_NUM(op.var)] = 1; \
} \
} while (0)
-# define NEVER_USED(op) ((op ## _type & (IS_VAR | IS_TMP_VAR)) && !usage[VAR_NUM(op.var)]) /* !used_ext[op.var] && */
-# define RES_NEVER_USED(opline) (opline->result_type == IS_UNUSED || NEVER_USED(opline->result))
-
-#else
-
-# define T_USAGE(op) do { \
- if ((op.op_type == IS_VAR || op.op_type == IS_TMP_VAR) && \
- !defined_here[VAR_NUM(op.u.var)] && !used_ext[VAR_NUM(op.u.var)]) { \
- used_ext[VAR_NUM(op.u.var)] = 1; \
- } \
- } while (0)
-
-# define NEVER_USED(op) ((op.op_type == IS_VAR || op.op_type == IS_TMP_VAR) && !usage[VAR_NUM(op.u.var)]) /* !used_ext[op.u.var] && */
-# define RES_NEVER_USED(opline) (ZEND_RESULT_TYPE(opline) == IS_UNUSED || NEVER_USED(opline->result))
-
-#endif
+#define NEVER_USED(op) ((op ## _type & (IS_VAR | IS_TMP_VAR)) && !usage[VAR_NUM(op.var)]) /* !used_ext[op.var] && */
+#define RES_NEVER_USED(opline) (opline->result_type == IS_UNUSED || NEVER_USED(opline->result))
/* Find a set of variables which are used outside of the block where they are
* defined. We won't apply some optimization patterns for such variables. */
-static void zend_t_usage(zend_code_block *block, zend_op_array *op_array, char *used_ext)
+static void zend_t_usage(zend_code_block *block, zend_op_array *op_array, char *used_ext, zend_optimizer_ctx *ctx)
{
zend_code_block *next_block = block->next;
char *usage;
char *defined_here;
+ void *checkpoint;
if (op_array->T == 0) {
/* shortcut - if no Ts, nothing to do */
return;
}
- usage = ecalloc(op_array->T, 1);
- defined_here = emalloc(op_array->T);
+ checkpoint = zend_arena_checkpoint(ctx->arena);
+ usage = zend_arena_alloc(&ctx->arena, op_array->last_var + op_array->T);
+ memset(usage, 0, op_array->last_var + op_array->T);
+ defined_here = zend_arena_alloc(&ctx->arena, op_array->last_var + op_array->T);
while (next_block) {
zend_op *opline = next_block->start_opline;
@@ -1886,7 +1756,7 @@ static void zend_t_usage(zend_code_block *block, zend_op_array *op_array, char *
next_block = next_block->next;
continue;
}
- memset(defined_here, 0, op_array->T);
+ memset(defined_here, 0, op_array->last_var + op_array->T);
while (opline<end) {
T_USAGE(opline->op1);
@@ -1895,9 +1765,7 @@ static void zend_t_usage(zend_code_block *block, zend_op_array *op_array, char *
if (RESULT_USED(opline)) {
if (!defined_here[VAR_NUM(ZEND_RESULT(opline).var)] && !used_ext[VAR_NUM(ZEND_RESULT(opline).var)] &&
(opline->opcode == ZEND_RECV || opline->opcode == ZEND_RECV_INIT ||
-#if ZEND_EXTENSION_API_NO > PHP_5_5_X_API_NO
opline->opcode == ZEND_RECV_VARIADIC ||
-#endif
(opline->opcode == ZEND_OP_DATA && ZEND_RESULT_TYPE(opline) == IS_TMP_VAR) ||
opline->opcode == ZEND_ADD_ARRAY_ELEMENT)) {
/* these opcodes use the result as argument */
@@ -1913,7 +1781,7 @@ static void zend_t_usage(zend_code_block *block, zend_op_array *op_array, char *
#if DEBUG_BLOCKPASS
{
int i;
- for (i = 0; i< op_array->T; i++) {
+ for (i = op_array->last_var; i< op_array->T; i++) {
fprintf(stderr, "T%d: %c\n", i, used_ext[i] + '0');
}
}
@@ -1927,7 +1795,7 @@ static void zend_t_usage(zend_code_block *block, zend_op_array *op_array, char *
continue;
}
- memcpy(usage, used_ext, op_array->T);
+ memcpy(usage, used_ext, op_array->last_var + op_array->T);
while (opline >= block->start_opline) {
/* usage checks */
@@ -1951,13 +1819,8 @@ static void zend_t_usage(zend_code_block *block, zend_op_array *op_array, char *
case ZEND_ASSIGN:
case ZEND_ASSIGN_REF:
case ZEND_DO_FCALL:
- case ZEND_DO_FCALL_BY_NAME:
if (ZEND_RESULT_TYPE(opline) == IS_VAR) {
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
ZEND_RESULT_TYPE(opline) |= EXT_TYPE_UNUSED;
-#else
- ZEND_RESULT(opline).EA.type |= EXT_TYPE_UNUSED;
-#endif
}
break;
case ZEND_QM_ASSIGN:
@@ -1968,10 +1831,6 @@ static void zend_t_usage(zend_code_block *block, zend_op_array *op_array, char *
}
MAKE_NOP(opline);
break;
- case ZEND_PRINT:
- opline->opcode = ZEND_ECHO;
- ZEND_RESULT_TYPE(opline) = IS_UNUSED;
- break;
case ZEND_JMPZ_EX:
case ZEND_JMPNZ_EX:
opline->opcode -= 3;
@@ -1982,9 +1841,7 @@ static void zend_t_usage(zend_code_block *block, zend_op_array *op_array, char *
if (opline->opcode == ZEND_RECV ||
opline->opcode == ZEND_RECV_INIT ||
-#if ZEND_EXTENSION_API_NO > PHP_5_5_X_API_NO
opline->opcode == ZEND_RECV_VARIADIC ||
-#endif
opline->opcode == ZEND_ADD_ARRAY_ELEMENT) {
if (ZEND_OP1_TYPE(opline) == IS_VAR || ZEND_OP1_TYPE(opline) == IS_TMP_VAR) {
usage[VAR_NUM(ZEND_RESULT(opline).var)] = 1;
@@ -1998,73 +1855,73 @@ static void zend_t_usage(zend_code_block *block, zend_op_array *op_array, char *
if (ZEND_OP1_TYPE(opline) == IS_VAR || ZEND_OP1_TYPE(opline) == IS_TMP_VAR) {
usage[VAR_NUM(ZEND_OP1(opline).var)] = 1;
}
+
if (ZEND_OP2_TYPE(opline) == IS_VAR || ZEND_OP2_TYPE(opline) == IS_TMP_VAR) {
usage[VAR_NUM(ZEND_OP2(opline).var)] = 1;
}
-
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
if ((ZEND_RESULT_TYPE(opline) & IS_VAR) &&
(ZEND_RESULT_TYPE(opline) & EXT_TYPE_UNUSED) &&
usage[VAR_NUM(ZEND_RESULT(opline).var)]) {
ZEND_RESULT_TYPE(opline) &= ~EXT_TYPE_UNUSED;
}
-#else
- if (ZEND_RESULT_TYPE(opline) == IS_VAR &&
- usage[VAR_NUM(ZEND_RESULT(opline).var)] &&
- (ZEND_RESULT(opline).EA.type & EXT_TYPE_UNUSED) != 0) {
- ZEND_RESULT(opline).EA.type &= ~EXT_TYPE_UNUSED;
- }
-#endif
opline--;
}
block = block->next;
} /* end blocks */
- efree(defined_here);
- efree(usage);
+ zend_arena_release(&ctx->arena, checkpoint);
}
#define PASSES 3
-static void zend_block_optimization(zend_op_array *op_array TSRMLS_DC)
+void optimize_cfg(zend_op_array *op_array, zend_optimizer_ctx *ctx)
{
zend_cfg cfg;
zend_code_block *cur_block;
int pass;
char *usage;
+ void *checkpoint;
#if DEBUG_BLOCKPASS
fprintf(stderr, "File %s func %s\n", op_array->filename, op_array->function_name? op_array->function_name : "main");
fflush(stderr);
#endif
-#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
- if (op_array->has_finally_block) {
+ if (op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK) {
return;
}
-#endif
/* Build CFG */
- if (!find_code_blocks(op_array, &cfg)) {
+ checkpoint = zend_arena_checkpoint(ctx->arena);
+ if (!find_code_blocks(op_array, &cfg, ctx)) {
+ zend_arena_release(&ctx->arena, checkpoint);
return;
}
- zend_rebuild_access_path(&cfg, op_array, 0);
+ zend_rebuild_access_path(&cfg, op_array, 0, ctx);
/* full rebuild here to produce correct sources! */
- usage = emalloc(op_array->T);
+ if (op_array->last_var || op_array->T) {
+ cfg.Tsource = zend_arena_calloc(&ctx->arena, op_array->last_var + op_array->T, sizeof(zend_op *));
+ cfg.same_t = zend_arena_alloc(&ctx->arena, op_array->last_var + op_array->T);
+ usage = zend_arena_alloc(&ctx->arena, op_array->last_var + op_array->T);
+ } else {
+ cfg.Tsource = NULL;
+ cfg.same_t = NULL;
+ usage = NULL;
+ }
for (pass = 0; pass < PASSES; pass++) {
/* Compute data dependencies */
- memset(usage, 0, op_array->T);
- zend_t_usage(cfg.blocks, op_array, usage);
+ memset(usage, 0, op_array->last_var + op_array->T);
+ zend_t_usage(cfg.blocks, op_array, usage, ctx);
/* optimize each basic block separately */
for (cur_block = cfg.blocks; cur_block; cur_block = cur_block->next) {
if (!cur_block->access) {
continue;
}
- zend_optimize_block(cur_block, op_array, usage TSRMLS_CC);
+ zend_optimize_block(cur_block, op_array, usage, &cfg, ctx);
}
/* Jump optimization for each block */
@@ -2072,26 +1929,17 @@ static void zend_block_optimization(zend_op_array *op_array TSRMLS_DC)
if (!cur_block->access) {
continue;
}
- zend_jmp_optimization(cur_block, op_array, cfg.blocks TSRMLS_CC);
+ zend_jmp_optimization(cur_block, op_array, cfg.blocks, &cfg, ctx);
}
/* Eliminate unreachable basic blocks */
- zend_rebuild_access_path(&cfg, op_array, 1);
+ zend_rebuild_access_path(&cfg, op_array, 1, ctx);
}
- memset(usage, 0, op_array->T);
- zend_t_usage(cfg.blocks, op_array, usage);
+ memset(usage, 0, op_array->last_var + op_array->T);
+ zend_t_usage(cfg.blocks, op_array, usage, ctx);
assemble_code_blocks(&cfg, op_array);
- efree(usage);
/* Destroy CFG */
- for (cur_block = cfg.blocks; cur_block; cur_block = cur_block->next) {
- zend_block_source *cs = cur_block->sources;
- while (cs) {
- zend_block_source *n = cs->next;
- efree(cs);
- cs = n;
- }
- }
- efree(cfg.blocks);
+ zend_arena_release(&ctx->arena, checkpoint);
}
diff --git a/ext/opcache/Optimizer/compact_literals.c b/ext/opcache/Optimizer/compact_literals.c
index b29241344c..0dee9d6146 100644
--- a/ext/opcache/Optimizer/compact_literals.c
+++ b/ext/opcache/Optimizer/compact_literals.c
@@ -1,7 +1,33 @@
+/*
+ +----------------------------------------------------------------------+
+ | Zend OPcache |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1998-2014 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Dmitry Stogov <dmitry@zend.com> |
+ | Xinchen Hui <laruence@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
/* pass 11
* - compact literals table
*/
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
+
+#include "php.h"
+#include "Optimizer/zend_optimizer.h"
+#include "Optimizer/zend_optimizer_internal.h"
+#include "zend_API.h"
+#include "zend_constants.h"
+#include "zend_execute.h"
+#include "zend_vm.h"
#define DEBUG_COMPACT_LITERALS 0
@@ -14,6 +40,7 @@
#define LITERAL_STATIC_PROPERTY 0x0700
#define LITERAL_METHOD 0x0800
#define LITERAL_PROPERTY 0x0900
+#define LITERAL_GLOBAL 0x0A00
#define LITERAL_EX_CLASS 0x4000
#define LITERAL_EX_OBJ 0x2000
@@ -27,7 +54,7 @@
#define LITERAL_NUM_SLOTS(info) ((info & LITERAL_NUM_SLOTS_MASK) >> LITERAL_NUM_SLOTS_SHIFT)
typedef struct _literal_info {
- zend_uint flags; /* bitmask (see defines above) */
+ uint32_t flags; /* bitmask (see defines above) */
union {
int num; /* variable number or class name literal number */
} u;
@@ -54,16 +81,16 @@ static void optimizer_literal_obj_info(literal_info *info,
zend_uchar op_type,
znode_op op,
int constant,
- zend_uint kind,
- zend_uint slots,
- zend_uint related,
+ uint32_t kind,
+ uint32_t slots,
+ uint32_t related,
zend_op_array *op_array)
{
/* For now we merge only $this object properties and methods.
* In general it's also possible to do it for any CV variable as well,
* but it would require complex dataflow and/or type analysis.
*/
- if (Z_TYPE(op_array->literals[constant].constant) == IS_STRING &&
+ if (Z_TYPE(op_array->literals[constant]) == IS_STRING &&
op_type == IS_UNUSED) {
LITERAL_INFO_OBJ(constant, kind, 1, slots, related, op_array->this_var);
} else {
@@ -75,9 +102,9 @@ static void optimizer_literal_class_info(literal_info *info,
zend_uchar op_type,
znode_op op,
int constant,
- zend_uint kind,
- zend_uint slots,
- zend_uint related,
+ uint32_t kind,
+ uint32_t slots,
+ uint32_t related,
zend_op_array *op_array)
{
if (op_type == IS_CONST) {
@@ -87,29 +114,29 @@ static void optimizer_literal_class_info(literal_info *info,
}
}
-static void optimizer_compact_literals(zend_op_array *op_array TSRMLS_DC)
+void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx *ctx)
{
zend_op *opline, *end;
- int i, j, n, *pos, *map, cache_slots;
- ulong h;
+ int i, j, n, *map, cache_slots;
+ zval zv, *pos;
literal_info *info;
int l_null = -1;
int l_false = -1;
int l_true = -1;
HashTable hash;
- char *key;
- int key_len;
+ zend_string *key = NULL;
+ void *checkpoint = zend_arena_checkpoint(ctx->arena);
if (op_array->last_literal) {
- info = (literal_info*)ecalloc(op_array->last_literal, sizeof(literal_info));
+ info = (literal_info*)zend_arena_calloc(&ctx->arena, op_array->last_literal, sizeof(literal_info));
/* Mark literals of specific types */
opline = op_array->opcodes;
end = opline + op_array->last;
while (opline < end) {
switch (opline->opcode) {
- case ZEND_DO_FCALL:
- LITERAL_INFO(opline->op1.constant, LITERAL_FUNC, 1, 1, 1);
+ case ZEND_INIT_FCALL:
+ LITERAL_INFO(opline->op2.constant, LITERAL_FUNC, 1, 1, 1);
break;
case ZEND_INIT_FCALL_BY_NAME:
if (ZEND_OP2_TYPE(opline) == IS_CONST) {
@@ -147,6 +174,9 @@ static void optimizer_compact_literals(zend_op_array *op_array TSRMLS_DC)
case ZEND_CATCH:
LITERAL_INFO(opline->op1.constant, LITERAL_CLASS, 1, 1, 2);
break;
+ case ZEND_DEFINED:
+ LITERAL_INFO(opline->op1.constant, LITERAL_CONST, 1, 1, 2);
+ break;
case ZEND_FETCH_CONSTANT:
if (ZEND_OP1_TYPE(opline) == IS_UNUSED) {
if ((opline->extended_value & (IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) == (IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) {
@@ -197,10 +227,16 @@ static void optimizer_compact_literals(zend_op_array *op_array TSRMLS_DC)
case ZEND_FETCH_CLASS:
case ZEND_ADD_INTERFACE:
case ZEND_ADD_TRAIT:
+ case ZEND_INSTANCEOF:
if (ZEND_OP2_TYPE(opline) == IS_CONST) {
LITERAL_INFO(opline->op2.constant, LITERAL_CLASS, 1, 1, 2);
}
break;
+ case ZEND_NEW:
+ if (ZEND_OP1_TYPE(opline) == IS_CONST) {
+ LITERAL_INFO(opline->op1.constant, LITERAL_CLASS, 1, 1, 2);
+ }
+ break;
case ZEND_ASSIGN_OBJ:
case ZEND_FETCH_OBJ_R:
case ZEND_FETCH_OBJ_W:
@@ -249,6 +285,9 @@ static void optimizer_compact_literals(zend_op_array *op_array TSRMLS_DC)
}
}
break;
+ case ZEND_BIND_GLOBAL:
+ LITERAL_INFO(opline->op2.constant, LITERAL_GLOBAL, 0, 1, 1);
+ break;
default:
if (ZEND_OP1_TYPE(opline) == IS_CONST) {
LITERAL_INFO(opline->op1.constant, LITERAL_VALUE, 1, 0, 1);
@@ -270,7 +309,7 @@ static void optimizer_compact_literals(zend_op_array *op_array TSRMLS_DC)
for (i = 0; i < op_array->last_literal; i++) {
zval zv = op_array->literals[i].constant;
- zend_make_printable_zval(&op_array->literals[i].constant, &zv, &use_copy);
+ use_copy = zend_make_printable_zval(&op_array->literals[i].constant, &zv);
fprintf(stderr, "Literal %d, val (%d):%s\n", i, Z_STRLEN(zv), Z_STRVAL(zv));
if (use_copy) {
zval_dtor(&zv);
@@ -282,15 +321,16 @@ static void optimizer_compact_literals(zend_op_array *op_array TSRMLS_DC)
/* Merge equal constants */
j = 0; cache_slots = 0;
- zend_hash_init(&hash, 16, NULL, NULL, 0);
- map = (int*)ecalloc(op_array->last_literal, sizeof(int));
+ zend_hash_init(&hash, op_array->last_literal, NULL, NULL, 0);
+ map = (int*)zend_arena_alloc(&ctx->arena, op_array->last_literal * sizeof(int));
+ memset(map, 0, op_array->last_literal * sizeof(int));
for (i = 0; i < op_array->last_literal; i++) {
if (!info[i].flags) {
/* unsed literal */
- zval_dtor(&op_array->literals[i].constant);
+ zval_dtor(&op_array->literals[i]);
continue;
}
- switch (Z_TYPE(op_array->literals[i].constant)) {
+ switch (Z_TYPE(op_array->literals[i])) {
case IS_NULL:
if (l_null < 0) {
l_null = j;
@@ -302,35 +342,35 @@ static void optimizer_compact_literals(zend_op_array *op_array TSRMLS_DC)
}
map[i] = l_null;
break;
- case IS_BOOL:
- if (Z_LVAL(op_array->literals[i].constant)) {
- if (l_true < 0) {
- l_true = j;
- if (i != j) {
- op_array->literals[j] = op_array->literals[i];
- info[j] = info[i];
- }
- j++;
+ case IS_FALSE:
+ if (l_false < 0) {
+ l_false = j;
+ if (i != j) {
+ op_array->literals[j] = op_array->literals[i];
+ info[j] = info[i];
}
- map[i] = l_true;
- } else {
- if (l_false < 0) {
- l_false = j;
- if (i != j) {
- op_array->literals[j] = op_array->literals[i];
- info[j] = info[i];
- }
- j++;
+ j++;
+ }
+ map[i] = l_false;
+ break;
+ case IS_TRUE:
+ if (l_true < 0) {
+ l_true = j;
+ if (i != j) {
+ op_array->literals[j] = op_array->literals[i];
+ info[j] = info[i];
}
- map[i] = l_false;
+ j++;
}
+ map[i] = l_true;
break;
case IS_LONG:
- if (zend_hash_index_find(&hash, Z_LVAL(op_array->literals[i].constant), (void**)&pos) == SUCCESS) {
- map[i] = *pos;
+ if ((pos = zend_hash_index_find(&hash, Z_LVAL(op_array->literals[i]))) != NULL) {
+ map[i] = Z_LVAL_P(pos);
} else {
map[i] = j;
- zend_hash_index_update(&hash, Z_LVAL(op_array->literals[i].constant), (void**)&j, sizeof(int), NULL);
+ ZVAL_LONG(&zv, j);
+ zend_hash_index_add_new(&hash, Z_LVAL(op_array->literals[i]), &zv);
if (i != j) {
op_array->literals[j] = op_array->literals[i];
info[j] = info[i];
@@ -339,11 +379,12 @@ static void optimizer_compact_literals(zend_op_array *op_array TSRMLS_DC)
}
break;
case IS_DOUBLE:
- if (zend_hash_find(&hash, (char*)&Z_DVAL(op_array->literals[i].constant), sizeof(double), (void**)&pos) == SUCCESS) {
- map[i] = *pos;
+ if ((pos = zend_hash_str_find(&hash, (char*)&Z_DVAL(op_array->literals[i]), sizeof(double))) != NULL) {
+ map[i] = Z_LVAL_P(pos);
} else {
map[i] = j;
- zend_hash_add(&hash, (char*)&Z_DVAL(op_array->literals[i].constant), sizeof(double), (void**)&j, sizeof(int), NULL);
+ ZVAL_LONG(&zv, j);
+ zend_hash_str_add(&hash, (char*)&Z_DVAL(op_array->literals[i]), sizeof(double), &zv);
if (i != j) {
op_array->literals[j] = op_array->literals[i];
info[j] = info[i];
@@ -355,62 +396,52 @@ static void optimizer_compact_literals(zend_op_array *op_array TSRMLS_DC)
case IS_CONSTANT:
if (info[i].flags & LITERAL_MAY_MERGE) {
if (info[i].flags & LITERAL_EX_OBJ) {
- key_len = MAX_LENGTH_OF_LONG + sizeof("->") + Z_STRLEN(op_array->literals[i].constant);
- key = emalloc(key_len);
- key_len = snprintf(key, key_len-1, "%d->%s", info[i].u.num, Z_STRVAL(op_array->literals[i].constant));
+ int key_len = MAX_LENGTH_OF_LONG + sizeof("->") + Z_STRLEN(op_array->literals[i]);
+ key = zend_string_alloc(key_len, 0);
+ key->len = snprintf(key->val, key->len-1, "%d->%s", info[i].u.num, Z_STRVAL(op_array->literals[i]));
} else if (info[i].flags & LITERAL_EX_CLASS) {
- zval *class_name = &op_array->literals[(info[i].u.num < i) ? map[info[i].u.num] : info[i].u.num].constant;
- key_len = Z_STRLEN_P(class_name) + sizeof("::") + Z_STRLEN(op_array->literals[i].constant);
- key = emalloc(key_len);
- memcpy(key, Z_STRVAL_P(class_name), Z_STRLEN_P(class_name));
- memcpy(key + Z_STRLEN_P(class_name), "::", sizeof("::") - 1);
- memcpy(key + Z_STRLEN_P(class_name) + sizeof("::") - 1,
- Z_STRVAL(op_array->literals[i].constant),
- Z_STRLEN(op_array->literals[i].constant) + 1);
+ int key_len;
+ zval *class_name = &op_array->literals[(info[i].u.num < i) ? map[info[i].u.num] : info[i].u.num];
+ key_len = Z_STRLEN_P(class_name) + sizeof("::") + Z_STRLEN(op_array->literals[i]);
+ key = zend_string_alloc(key_len, 0);
+ memcpy(key->val, Z_STRVAL_P(class_name), Z_STRLEN_P(class_name));
+ memcpy(key->val + Z_STRLEN_P(class_name), "::", sizeof("::") - 1);
+ memcpy(key->val + Z_STRLEN_P(class_name) + sizeof("::") - 1,
+ Z_STRVAL(op_array->literals[i]),
+ Z_STRLEN(op_array->literals[i]) + 1);
} else {
- key = Z_STRVAL(op_array->literals[i].constant);
- key_len = Z_STRLEN(op_array->literals[i].constant)+1;
+ key = zend_string_init(Z_STRVAL(op_array->literals[i]), Z_STRLEN(op_array->literals[i]), 0);
}
- h = zend_hash_func(key, key_len);
- h += info[i].flags;
+ key->h = zend_hash_func(key->val, key->len);
+ key->h += info[i].flags;
}
if ((info[i].flags & LITERAL_MAY_MERGE) &&
- zend_hash_quick_find(&hash, key, key_len, h, (void**)&pos) == SUCCESS &&
- Z_TYPE(op_array->literals[i].constant) == Z_TYPE(op_array->literals[*pos].constant) &&
- info[i].flags == info[*pos].flags) {
+ (pos = zend_hash_find(&hash, key)) != NULL &&
+ Z_TYPE(op_array->literals[i]) == Z_TYPE(op_array->literals[Z_LVAL_P(pos)]) &&
+ info[i].flags == info[Z_LVAL_P(pos)].flags) {
- if (info[i].flags & (LITERAL_EX_OBJ|LITERAL_EX_CLASS)) {
- efree(key);
- }
- map[i] = *pos;
- zval_dtor(&op_array->literals[i].constant);
+ zend_string_release(key);
+ map[i] = Z_LVAL_P(pos);
+ zval_dtor(&op_array->literals[i]);
n = LITERAL_NUM_RELATED(info[i].flags);
while (n > 1) {
i++;
- zval_dtor(&op_array->literals[i].constant);
+ zval_dtor(&op_array->literals[i]);
n--;
}
} else {
map[i] = j;
if (info[i].flags & LITERAL_MAY_MERGE) {
- zend_hash_quick_add(&hash, key, key_len, h, (void**)&j, sizeof(int), NULL);
- if (info[i].flags & (LITERAL_EX_OBJ|LITERAL_EX_CLASS)) {
- efree(key);
- }
+ ZVAL_LONG(&zv, j);
+ zend_hash_add_new(&hash, key, &zv);
+ zend_string_release(key);
}
if (i != j) {
op_array->literals[j] = op_array->literals[i];
info[j] = info[i];
}
- if (!op_array->literals[j].hash_value) {
- if (IS_INTERNED(Z_STRVAL(op_array->literals[j].constant))) {
- op_array->literals[j].hash_value = INTERNED_HASH(Z_STRVAL(op_array->literals[j].constant));
- } else {
- op_array->literals[j].hash_value = zend_hash_func(Z_STRVAL(op_array->literals[j].constant), Z_STRLEN(op_array->literals[j].constant)+1);
- }
- }
if (LITERAL_NUM_SLOTS(info[i].flags)) {
- op_array->literals[j].cache_slot = cache_slots;
+ Z_CACHE_SLOT(op_array->literals[j]) = cache_slots;
cache_slots += LITERAL_NUM_SLOTS(info[i].flags);
}
j++;
@@ -418,13 +449,6 @@ static void optimizer_compact_literals(zend_op_array *op_array TSRMLS_DC)
while (n > 1) {
i++;
if (i != j) op_array->literals[j] = op_array->literals[i];
- if (!op_array->literals[j].hash_value) {
- if (IS_INTERNED(Z_STRVAL(op_array->literals[j].constant))) {
- op_array->literals[j].hash_value = INTERNED_HASH(Z_STRVAL(op_array->literals[j].constant));
- } else {
- op_array->literals[j].hash_value = zend_hash_func(Z_STRVAL(op_array->literals[j].constant), Z_STRLEN(op_array->literals[j].constant)+1);
- }
- }
j++;
n--;
}
@@ -457,8 +481,7 @@ static void optimizer_compact_literals(zend_op_array *op_array TSRMLS_DC)
}
opline++;
}
- efree(map);
- efree(info);
+ zend_arena_release(&ctx->arena, checkpoint);
#if DEBUG_COMPACT_LITERALS
{
@@ -467,7 +490,7 @@ static void optimizer_compact_literals(zend_op_array *op_array TSRMLS_DC)
for (i = 0; i < op_array->last_literal; i++) {
zval zv = op_array->literals[i].constant;
- zend_make_printable_zval(&op_array->literals[i].constant, &zv, &use_copy);
+ use_copy = zend_make_printable_zval(&op_array->literals[i].constant, &zv);
fprintf(stderr, "Literal %d, val (%d):%s\n", i, Z_STRLEN(zv), Z_STRVAL(zv));
if (use_copy) {
zval_dtor(&zv);
@@ -478,4 +501,3 @@ static void optimizer_compact_literals(zend_op_array *op_array TSRMLS_DC)
#endif
}
}
-#endif
diff --git a/ext/opcache/Optimizer/nop_removal.c b/ext/opcache/Optimizer/nop_removal.c
index b2fb667ed5..651950148c 100644
--- a/ext/opcache/Optimizer/nop_removal.c
+++ b/ext/opcache/Optimizer/nop_removal.c
@@ -1,21 +1,49 @@
+/*
+ +----------------------------------------------------------------------+
+ | Zend OPcache |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1998-2014 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Andi Gutmans <andi@zend.com> |
+ | Zeev Suraski <zeev@zend.com> |
+ | Stanislav Malyshev <stas@zend.com> |
+ | Dmitry Stogov <dmitry@zend.com> |
+ +----------------------------------------------------------------------+
+*/
+
/* pass 10:
* - remove NOPs
*/
-static void nop_removal(zend_op_array *op_array)
+#include "php.h"
+#include "Optimizer/zend_optimizer.h"
+#include "Optimizer/zend_optimizer_internal.h"
+#include "zend_API.h"
+#include "zend_constants.h"
+#include "zend_execute.h"
+#include "zend_vm.h"
+
+void zend_optimizer_nop_removal(zend_op_array *op_array)
{
zend_op *end, *opline;
- zend_uint new_count, i, shift;
+ uint32_t new_count, i, shift;
int j;
- zend_uint *shiftlist;
+ uint32_t *shiftlist;
ALLOCA_FLAG(use_heap);
- shiftlist = (zend_uint *)DO_ALLOCA(sizeof(zend_uint) * op_array->last);
+ shiftlist = (uint32_t *)DO_ALLOCA(sizeof(uint32_t) * op_array->last);
i = new_count = shift = 0;
end = op_array->opcodes + op_array->last;
for (opline = op_array->opcodes; opline < end; opline++) {
-#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
/* GOTO target is unresolved yet. We can't optimize. */
if (opline->opcode == ZEND_GOTO &&
Z_TYPE(ZEND_OP2_LITERAL(opline)) != IS_LONG) {
@@ -23,7 +51,6 @@ static void nop_removal(zend_op_array *op_array)
FREE_ALLOCA(shiftlist);
return;
}
-#endif
/* Kill JMP-over-NOP-s */
if (opline->opcode == ZEND_JMP && ZEND_OP1(opline).opline_num > i) {
@@ -58,12 +85,8 @@ static void nop_removal(zend_op_array *op_array)
for (opline = op_array->opcodes; opline<end; opline++) {
switch (opline->opcode) {
case ZEND_JMP:
-#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
case ZEND_GOTO:
-#endif
-#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
case ZEND_FAST_CALL:
-#endif
ZEND_OP1(opline).opline_num -= shiftlist[ZEND_OP1(opline).opline_num];
break;
case ZEND_JMPZ:
@@ -73,12 +96,8 @@ static void nop_removal(zend_op_array *op_array)
case ZEND_FE_FETCH:
case ZEND_FE_RESET:
case ZEND_NEW:
-#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
case ZEND_JMP_SET:
-#endif
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
- case ZEND_JMP_SET_VAR:
-#endif
+ case ZEND_COALESCE:
ZEND_OP2(opline).opline_num -= shiftlist[ZEND_OP2(opline).opline_num];
break;
case ZEND_JMPZNZ:
@@ -102,25 +121,21 @@ static void nop_removal(zend_op_array *op_array)
for (j = 0; j < op_array->last_try_catch; j++) {
op_array->try_catch_array[j].try_op -= shiftlist[op_array->try_catch_array[j].try_op];
op_array->try_catch_array[j].catch_op -= shiftlist[op_array->try_catch_array[j].catch_op];
-#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
if (op_array->try_catch_array[j].finally_op) {
op_array->try_catch_array[j].finally_op -= shiftlist[op_array->try_catch_array[j].finally_op];
op_array->try_catch_array[j].finally_end -= shiftlist[op_array->try_catch_array[j].finally_end];
}
-#endif
}
-#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
/* update early binding list */
- if (op_array->early_binding != (zend_uint)-1) {
- zend_uint *opline_num = &op_array->early_binding;
+ if (op_array->early_binding != (uint32_t)-1) {
+ uint32_t *opline_num = &op_array->early_binding;
do {
*opline_num -= shiftlist[*opline_num];
opline_num = &ZEND_RESULT(&op_array->opcodes[*opline_num]).opline_num;
- } while (*opline_num != (zend_uint)-1);
+ } while (*opline_num != (uint32_t)-1);
}
-#endif
}
FREE_ALLOCA(shiftlist);
}
diff --git a/ext/opcache/Optimizer/optimize_func_calls.c b/ext/opcache/Optimizer/optimize_func_calls.c
index 14f8255653..66eda55650 100644
--- a/ext/opcache/Optimizer/optimize_func_calls.c
+++ b/ext/opcache/Optimizer/optimize_func_calls.c
@@ -1,34 +1,66 @@
+/*
+ +----------------------------------------------------------------------+
+ | Zend OPcache |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1998-2014 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Dmitry Stogov <dmitry@zend.com> |
+ | Xinchen Hui <laruence@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
/* pass 4
* - optimize INIT_FCALL_BY_NAME to DO_FCALL
*/
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
+
+#include "php.h"
+#include "Optimizer/zend_optimizer.h"
+#include "Optimizer/zend_optimizer_internal.h"
+#include "zend_API.h"
+#include "zend_constants.h"
+#include "zend_execute.h"
+#include "zend_vm.h"
+
+#define ZEND_OP2_IS_CONST_STRING(opline) \
+ (ZEND_OP2_TYPE(opline) == IS_CONST && \
+ Z_TYPE(op_array->literals[(opline)->op2.constant]) == IS_STRING)
typedef struct _optimizer_call_info {
zend_function *func;
zend_op *opline;
} optimizer_call_info;
-static void optimize_func_calls(zend_op_array *op_array, zend_persistent_script *script TSRMLS_DC) {
+void optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx)
+{
zend_op *opline = op_array->opcodes;
zend_op *end = opline + op_array->last;
int call = 0;
-#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
- optimizer_call_info *call_stack = ecalloc(op_array->nested_calls + 1, sizeof(optimizer_call_info));
-#else
- int stack_size = 4;
- optimizer_call_info *call_stack = ecalloc(stack_size, sizeof(optimizer_call_info));
-#endif
+ void *checkpoint;
+ optimizer_call_info *call_stack;
+
+ if (op_array->last < 2) {
+ return;
+ }
+ checkpoint = zend_arena_checkpoint(ctx->arena);
+ call_stack = zend_arena_calloc(&ctx->arena, op_array->last / 2, sizeof(optimizer_call_info));
while (opline < end) {
switch (opline->opcode) {
case ZEND_INIT_FCALL_BY_NAME:
case ZEND_INIT_NS_FCALL_BY_NAME:
- if (ZEND_OP2_TYPE(opline) == IS_CONST) {
+ if (ZEND_OP2_IS_CONST_STRING(opline)) {
zend_function *func;
- zval *function_name = &op_array->literals[opline->op2.constant + 1].constant;
- if ((zend_hash_quick_find(&script->function_table,
- Z_STRVAL_P(function_name), Z_STRLEN_P(function_name) + 1,
- Z_HASH_P(function_name), (void **)&func) == SUCCESS)) {
+ zval *function_name = &op_array->literals[opline->op2.constant + 1];
+ if ((func = zend_hash_find_ptr(&ctx->script->function_table,
+ Z_STR_P(function_name))) != NULL) {
call_stack[call].func = func;
}
}
@@ -36,43 +68,32 @@ static void optimize_func_calls(zend_op_array *op_array, zend_persistent_script
case ZEND_NEW:
case ZEND_INIT_METHOD_CALL:
case ZEND_INIT_STATIC_METHOD_CALL:
+ case ZEND_INIT_FCALL:
+ case ZEND_INIT_USER_CALL:
call_stack[call].opline = opline;
call++;
-#if ZEND_EXTENSION_API_NO < PHP_5_5_X_API_NO
- if (call == stack_size) {
- stack_size += 4;
- call_stack = erealloc(call_stack, sizeof(optimizer_call_info) * stack_size);
- memset(call_stack + 4, 0, 4 * sizeof(optimizer_call_info));
- }
-#endif
break;
- case ZEND_DO_FCALL_BY_NAME:
+ case ZEND_DO_FCALL:
call--;
if (call_stack[call].func && call_stack[call].opline) {
zend_op *fcall = call_stack[call].opline;
- opline->opcode = ZEND_DO_FCALL;
- ZEND_OP1_TYPE(opline) = IS_CONST;
- opline->op1.constant = fcall->op2.constant + 1;
- op_array->literals[fcall->op2.constant + 1].cache_slot = op_array->literals[fcall->op2.constant].cache_slot;
- literal_dtor(&ZEND_OP2_LITERAL(fcall));
- if (fcall->opcode == ZEND_INIT_NS_FCALL_BY_NAME) {
- literal_dtor(&op_array->literals[fcall->op2.constant + 2].constant);
+ if (fcall->opcode == ZEND_INIT_FCALL_BY_NAME) {
+ fcall->opcode = ZEND_INIT_FCALL;
+ fcall->op1.num = zend_vm_calc_used_stack(fcall->extended_value, call_stack[call].func);
+ Z_CACHE_SLOT(op_array->literals[fcall->op2.constant + 1]) = Z_CACHE_SLOT(op_array->literals[fcall->op2.constant]);
+ literal_dtor(&ZEND_OP2_LITERAL(fcall));
+ fcall->op2.constant = fcall->op2.constant + 1;
+ } else if (fcall->opcode == ZEND_INIT_NS_FCALL_BY_NAME) {
+ fcall->opcode = ZEND_INIT_FCALL;
+ fcall->op1.num = zend_vm_calc_used_stack(fcall->extended_value, call_stack[call].func);
+ Z_CACHE_SLOT(op_array->literals[fcall->op2.constant + 1]) = Z_CACHE_SLOT(op_array->literals[fcall->op2.constant]);
+ literal_dtor(&op_array->literals[fcall->op2.constant]);
+ literal_dtor(&op_array->literals[fcall->op2.constant + 2]);
+ fcall->op2.constant = fcall->op2.constant + 1;
+ } else {
+ ZEND_ASSERT(0);
}
- MAKE_NOP(fcall);
- } else if (opline->extended_value == 0 &&
- call_stack[call].opline &&
- call_stack[call].opline->opcode == ZEND_INIT_FCALL_BY_NAME &&
- ZEND_OP2_TYPE(call_stack[call].opline) == IS_CONST) {
-
- zend_op *fcall = call_stack[call].opline;
-
- opline->opcode = ZEND_DO_FCALL;
- ZEND_OP1_TYPE(opline) = IS_CONST;
- opline->op1.constant = fcall->op2.constant + 1;
- op_array->literals[fcall->op2.constant + 1].cache_slot = op_array->literals[fcall->op2.constant].cache_slot;
- literal_dtor(&ZEND_OP2_LITERAL(fcall));
- MAKE_NOP(fcall);
}
call_stack[call].func = NULL;
call_stack[call].opline = NULL;
@@ -90,54 +111,52 @@ static void optimize_func_calls(zend_op_array *op_array, zend_persistent_script
}
}
break;
- case ZEND_SEND_VAL:
- if (opline->extended_value == ZEND_DO_FCALL_BY_NAME && call_stack[call - 1].func) {
+ case ZEND_SEND_VAL_EX:
+ if (call_stack[call - 1].func) {
if (ARG_MUST_BE_SENT_BY_REF(call_stack[call - 1].func, opline->op2.num)) {
/* We won't convert it into_DO_FCALL to emit error at run-time */
call_stack[call - 1].opline = NULL;
} else {
- opline->extended_value = ZEND_DO_FCALL;
+ opline->opcode = ZEND_SEND_VAL;
}
}
break;
- case ZEND_SEND_VAR:
- if (opline->extended_value == ZEND_DO_FCALL_BY_NAME && call_stack[call - 1].func) {
+ case ZEND_SEND_VAR_EX:
+ if (call_stack[call - 1].func) {
if (ARG_SHOULD_BE_SENT_BY_REF(call_stack[call - 1].func, opline->op2.num)) {
opline->opcode = ZEND_SEND_REF;
+ } else {
+ opline->opcode = ZEND_SEND_VAR;
}
- opline->extended_value = ZEND_DO_FCALL;
}
break;
case ZEND_SEND_VAR_NO_REF:
if (!(opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) && call_stack[call - 1].func) {
if (ARG_SHOULD_BE_SENT_BY_REF(call_stack[call - 1].func, opline->op2.num)) {
opline->extended_value |= ZEND_ARG_COMPILE_TIME_BOUND | ZEND_ARG_SEND_BY_REF;
- } else if (opline->extended_value) {
- opline->extended_value |= ZEND_ARG_COMPILE_TIME_BOUND;
} else {
opline->opcode = ZEND_SEND_VAR;
- opline->extended_value = ZEND_DO_FCALL;
+ opline->extended_value = 0;
}
}
break;
+#if 0
case ZEND_SEND_REF:
- if (opline->extended_value == ZEND_DO_FCALL_BY_NAME && call_stack[call - 1].func) {
+ if (opline->extended_value != ZEND_ARG_COMPILE_TIME_BOUND && call_stack[call - 1].func) {
/* We won't handle run-time pass by reference */
call_stack[call - 1].opline = NULL;
}
break;
-#if ZEND_EXTENSION_API_NO > PHP_5_5_X_API_NO
+#endif
case ZEND_SEND_UNPACK:
call_stack[call - 1].func = NULL;
call_stack[call - 1].opline = NULL;
break;
-#endif
default:
break;
}
opline++;
}
- efree(call_stack);
+ zend_arena_release(&ctx->arena, checkpoint);
}
-#endif
diff --git a/ext/opcache/Optimizer/optimize_temp_vars_5.c b/ext/opcache/Optimizer/optimize_temp_vars_5.c
index dc630733fa..a7838cb9dd 100644
--- a/ext/opcache/Optimizer/optimize_temp_vars_5.c
+++ b/ext/opcache/Optimizer/optimize_temp_vars_5.c
@@ -1,63 +1,31 @@
-#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
-
-/* ops that use CLs:
-op1:
-ZEND_FETCH_CONSTANT:
-ZEND_INIT_CTOR_CALL:
-ZEND_INIT_STATIC_METHOD_CALL:
-ZEND_INIT_METHOD_CALL:
-ZEND_IMPORT_CLASS:
-ZEND_IMPORT_FUNCTION:
-ZEND_IMPORT_CONST:
-ZEND_ADD_INTERFACE:
-ZEND_VERIFY_ABSTRACT_CLASS:
-ZEND_NEW:
-ZEND_CATCH:
-ZEND_INIT_FCALL_BY_NAME:
-
-op2:
-ZEND_UNSET_VAR:
-ZEND_ISSET_ISEMPTY_VAR:
-ZEND_FETCH_UNSET:
-ZEND_FETCH_IS:
-ZEND_FETCH_R:
-ZEND_FETCH_W:
-ZEND_FETCH_RW:
-ZEND_FETCH_FUNC_ARG:
-ZEND_ADD_INTERFACE:
-ZEND_INSTANCEOF:
-
-extended_value:
-ZEND_DECLARE_INHERITED_CLASS:
-
-ignore result
-INIT_METHOD_CALL:
+/*
+ +----------------------------------------------------------------------+
+ | Zend OPcache |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1998-2014 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Andi Gutmans <andi@zend.com> |
+ | Zeev Suraski <zeev@zend.com> |
+ | Stanislav Malyshev <stas@zend.com> |
+ | Dmitry Stogov <dmitry@zend.com> |
+ +----------------------------------------------------------------------+
*/
-#define OP1_CONST_IS_CLASS 1
-#define OP2_CONST_IS_CLASS 2
-#define EXT_CONST_IS_CLASS 4
-#define RESULT_IS_UNUSED 8
-
-static const char op_const_means_class[256] = {
- /* 0 */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* 32 */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
- /* 64 */
- 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 0, 0, 2, 0, 0, 2, 0, 0, 2, 0, 0, 2, 0, 0, 2,
- /* 96 */
- 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 9, 1, 2, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* 128 */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 4, 0, 0, 0, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* 160 */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* 192 */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* 224 */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-#endif
+#include "php.h"
+#include "Optimizer/zend_optimizer.h"
+#include "Optimizer/zend_optimizer_internal.h"
+#include "zend_API.h"
+#include "zend_constants.h"
+#include "zend_execute.h"
+#include "zend_vm.h"
#define GET_AVAILABLE_T() \
for (i = 0; i < T; i++) { \
@@ -70,9 +38,10 @@ static const char op_const_means_class[256] = {
max = i; \
}
-static void optimize_temporary_variables(zend_op_array *op_array)
+void optimize_temporary_variables(zend_op_array *op_array, zend_optimizer_ctx *ctx)
{
int T = op_array->T;
+ int offset = op_array->last_var;
char *taken_T; /* T index in use */
zend_op **start_of_T; /* opline where T is first used */
char *valid_T; /* Is the map_T valid */
@@ -82,28 +51,31 @@ static void optimize_temporary_variables(zend_op_array *op_array)
int i;
int max = -1;
int var_to_free = -1;
+ void *checkpoint = zend_arena_checkpoint(ctx->arena);
- taken_T = (char *) emalloc(T);
- start_of_T = (zend_op **) emalloc(T * sizeof(zend_op *));
- valid_T = (char *) emalloc(T);
- map_T = (int *) emalloc(T * sizeof(int));
+ taken_T = (char *) zend_arena_alloc(&ctx->arena, T);
+ start_of_T = (zend_op **) zend_arena_alloc(&ctx->arena, T * sizeof(zend_op *));
+ valid_T = (char *) zend_arena_alloc(&ctx->arena, T);
+ map_T = (int *) zend_arena_alloc(&ctx->arena, T * sizeof(int));
end = op_array->opcodes;
opline = &op_array->opcodes[op_array->last - 1];
/* Find T definition points */
while (opline >= end) {
-#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
- if (ZEND_RESULT_TYPE(opline) & (IS_VAR | IS_TMP_VAR | IS_CONST)) {
- if (!(op_const_means_class[opline->opcode] & RESULT_IS_UNUSED)) {
- start_of_T[VAR_NUM(ZEND_RESULT(opline).var)] = opline;
- }
- }
-#else
if (ZEND_RESULT_TYPE(opline) & (IS_VAR | IS_TMP_VAR)) {
- start_of_T[VAR_NUM(ZEND_RESULT(opline).var)] = opline;
+ start_of_T[VAR_NUM(ZEND_RESULT(opline).var) - offset] = opline;
+ }
+ /* special puprose variable to keep HashPointer on VM stack */
+ if (opline->opcode == ZEND_OP_DATA &&
+ (opline-1)->opcode == ZEND_FE_FETCH &&
+ opline->op1_type == IS_TMP_VAR) {
+ start_of_T[VAR_NUM(ZEND_OP1(opline).var) - offset] = opline;
+ if (sizeof(HashPointer) > sizeof(zval)) {
+ /* Make shure 1 zval is enough for HashPointer (2 must be enough) */
+ start_of_T[VAR_NUM(ZEND_OP1(opline).var) + 1 - offset] = opline;
+ }
}
-#endif
opline--;
}
@@ -114,18 +86,27 @@ static void optimize_temporary_variables(zend_op_array *op_array)
opline = &op_array->opcodes[op_array->last - 1];
while (opline >= end) {
- if ((ZEND_OP1_TYPE(opline) & (IS_VAR | IS_TMP_VAR))
-#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
- || ((op_const_means_class[opline->opcode] & OP1_CONST_IS_CLASS) && ZEND_OP1_TYPE(opline) == IS_CONST)
-#endif
- ) {
- currT = VAR_NUM(ZEND_OP1(opline).var);
- if (!valid_T[currT]) {
- GET_AVAILABLE_T();
- map_T[currT] = i;
- valid_T[currT] = 1;
+ if ((ZEND_OP1_TYPE(opline) & (IS_VAR | IS_TMP_VAR))) {
+
+ /* special puprose variable to keep HashPointer on VM stack */
+ if (opline->opcode == ZEND_OP_DATA &&
+ (opline-1)->opcode == ZEND_FE_FETCH &&
+ opline->op1_type == IS_TMP_VAR) {
+ max++;
+ ZEND_OP1(opline).var = NUM_VAR(max + offset);
+ if (sizeof(HashPointer) > sizeof(zval)) {
+ /* Make shure 1 zval is enough for HashPointer (2 must be enough) */
+ max++;
+ }
+ } else {
+ currT = VAR_NUM(ZEND_OP1(opline).var) - offset;
+ if (!valid_T[currT]) {
+ GET_AVAILABLE_T();
+ map_T[currT] = i;
+ valid_T[currT] = 1;
+ }
+ ZEND_OP1(opline).var = NUM_VAR(map_T[currT] + offset);
}
- ZEND_OP1(opline).var = NUM_VAR(map_T[currT]);
}
/* Skip OP_DATA */
@@ -135,75 +116,59 @@ static void optimize_temporary_variables(zend_op_array *op_array)
continue;
}
- if ((ZEND_OP2_TYPE(opline) & (IS_VAR | IS_TMP_VAR))
-#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
- || ((op_const_means_class[opline->opcode] & OP2_CONST_IS_CLASS) && ZEND_OP2_TYPE(opline) == IS_CONST)
-#endif
- ) {
- currT = VAR_NUM(ZEND_OP2(opline).var);
+ if ((ZEND_OP2_TYPE(opline) & (IS_VAR | IS_TMP_VAR))) {
+ currT = VAR_NUM(ZEND_OP2(opline).var) - offset;
if (!valid_T[currT]) {
GET_AVAILABLE_T();
map_T[currT] = i;
valid_T[currT] = 1;
}
- ZEND_OP2(opline).var = NUM_VAR(map_T[currT]);
+ ZEND_OP2(opline).var = NUM_VAR(map_T[currT] + offset);
}
-#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
- if ((op_const_means_class[opline->opcode] & EXT_CONST_IS_CLASS)) {
-#else
if (opline->opcode == ZEND_DECLARE_INHERITED_CLASS ||
opline->opcode == ZEND_DECLARE_INHERITED_CLASS_DELAYED) {
-#endif
- currT = VAR_NUM(opline->extended_value);
+ currT = VAR_NUM(opline->extended_value) - offset;
if (!valid_T[currT]) {
GET_AVAILABLE_T();
map_T[currT] = i;
valid_T[currT] = 1;
}
- opline->extended_value = NUM_VAR(map_T[currT]);
+ opline->extended_value = NUM_VAR(map_T[currT] + offset);
}
/* Allocate OP_DATA->op2 after "operands", but before "result" */
if (opline->opcode == ZEND_ASSIGN_DIM &&
(opline + 1)->opcode == ZEND_OP_DATA &&
ZEND_OP2_TYPE(opline + 1) & (IS_VAR | IS_TMP_VAR)) {
- currT = VAR_NUM(ZEND_OP2(opline + 1).var);
+ currT = VAR_NUM(ZEND_OP2(opline + 1).var) - offset;
GET_AVAILABLE_T();
map_T[currT] = i;
valid_T[currT] = 1;
taken_T[i] = 0;
- ZEND_OP2(opline + 1).var = NUM_VAR(i);
+ ZEND_OP2(opline + 1).var = NUM_VAR(i + offset);
var_to_free = i;
}
-#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
- if (ZEND_RESULT_TYPE(opline) & (IS_VAR | IS_TMP_VAR | IS_CONST)) {
- if (!(op_const_means_class[opline->opcode] & RESULT_IS_UNUSED)) {
-#else
if (ZEND_RESULT_TYPE(opline) & (IS_VAR | IS_TMP_VAR)) {
-#endif
- currT = VAR_NUM(ZEND_RESULT(opline).var);
- if (valid_T[currT]) {
- if (start_of_T[currT] == opline) {
- taken_T[map_T[currT]] = 0;
- }
- ZEND_RESULT(opline).var = NUM_VAR(map_T[currT]);
- } else { /* Au still needs to be assigned a T which is a bit dumb. Should consider changing Zend */
- GET_AVAILABLE_T();
+ currT = VAR_NUM(ZEND_RESULT(opline).var) - offset;
+ if (valid_T[currT]) {
+ if (start_of_T[currT] == opline) {
+ taken_T[map_T[currT]] = 0;
+ }
+ ZEND_RESULT(opline).var = NUM_VAR(map_T[currT] + offset);
+ } else { /* Au still needs to be assigned a T which is a bit dumb. Should consider changing Zend */
+ GET_AVAILABLE_T();
- if (RESULT_UNUSED(opline)) {
- taken_T[i] = 0;
- } else {
- /* Code which gets here is using a wrongly built opcode such as RECV() */
- map_T[currT] = i;
- valid_T[currT] = 1;
- }
- ZEND_RESULT(opline).var = NUM_VAR(i);
+ if (RESULT_UNUSED(opline)) {
+ taken_T[i] = 0;
+ } else {
+ /* Code which gets here is using a wrongly built opcode such as RECV() */
+ map_T[currT] = i;
+ valid_T[currT] = 1;
}
-#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
+ ZEND_RESULT(opline).var = NUM_VAR(i + offset);
}
-#endif
}
if (var_to_free >= 0) {
@@ -214,9 +179,6 @@ static void optimize_temporary_variables(zend_op_array *op_array)
opline--;
}
- efree(taken_T);
- efree(start_of_T);
- efree(valid_T);
- efree(map_T);
+ zend_arena_release(&ctx->arena, checkpoint);
op_array->T = max + 1;
}
diff --git a/ext/opcache/Optimizer/pass10.c b/ext/opcache/Optimizer/pass10.c
deleted file mode 100644
index 3bfcec643a..0000000000
--- a/ext/opcache/Optimizer/pass10.c
+++ /dev/null
@@ -1,3 +0,0 @@
-if (((ZEND_OPTIMIZER_PASS_10|ZEND_OPTIMIZER_PASS_5) & OPTIMIZATION_LEVEL) == ZEND_OPTIMIZER_PASS_10) {
- nop_removal(op_array);
-}
diff --git a/ext/opcache/Optimizer/pass1_5.c b/ext/opcache/Optimizer/pass1_5.c
index 731040e960..142ccb319b 100644
--- a/ext/opcache/Optimizer/pass1_5.c
+++ b/ext/opcache/Optimizer/pass1_5.c
@@ -1,3 +1,24 @@
+/*
+ +----------------------------------------------------------------------+
+ | Zend OPcache |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1998-2014 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Andi Gutmans <andi@zend.com> |
+ | Zeev Suraski <zeev@zend.com> |
+ | Stanislav Malyshev <stas@zend.com> |
+ | Dmitry Stogov <dmitry@zend.com> |
+ +----------------------------------------------------------------------+
+*/
+
/* pass 1
* - substitute persistent constants (true, false, null, etc)
* - perform compile-time evaluation of constant binary and unary operations
@@ -6,17 +27,22 @@
* - pre-evaluate constant function calls
*/
-#if ZEND_EXTENSION_API_NO > PHP_5_2_X_API_NO
-# define ZEND_IS_CONSTANT_TYPE(t) (((t) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT)
-#else
-# define ZEND_IS_CONSTANT_TYPE(t) ((t) == IS_CONSTANT)
-#endif
+#include "php.h"
+#include "Optimizer/zend_optimizer.h"
+#include "Optimizer/zend_optimizer_internal.h"
+#include "zend_API.h"
+#include "zend_constants.h"
+#include "zend_execute.h"
+#include "zend_vm.h"
+
+#define ZEND_IS_CONSTANT_TYPE(t) ((t) == IS_CONSTANT)
-if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
+void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
+{
int i = 0;
zend_op *opline = op_array->opcodes;
zend_op *end = opline + op_array->last;
- zend_bool collect_constants = (op_array == &script->main_op_array);
+ zend_bool collect_constants = (op_array == &ctx->script->main_op_array);
while (opline < end) {
switch (opline->opcode) {
@@ -25,9 +51,7 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
case ZEND_MUL:
case ZEND_DIV:
case ZEND_MOD:
-#if ZEND_EXTENSION_API_NO >= PHP_5_6_X_API_NO
case ZEND_POW:
-#endif
case ZEND_SL:
case ZEND_SR:
case ZEND_CONCAT:
@@ -44,8 +68,8 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
if (ZEND_OP1_TYPE(opline) == IS_CONST &&
ZEND_OP2_TYPE(opline) == IS_CONST) {
/* binary operation with constant operands */
- int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC) = get_binary_op(opline->opcode);
- zend_uint tv = ZEND_RESULT(opline).var; /* temporary variable */
+ int (*binary_op)(zval *result, zval *op1, zval *op2) = get_binary_op(opline->opcode);
+ uint32_t tv = ZEND_RESULT(opline).var; /* temporary variable */
zval result;
int er;
@@ -58,19 +82,16 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
er = EG(error_reporting);
EG(error_reporting) = 0;
/* evaluate constant expression */
- if (binary_op(&result, &ZEND_OP1_LITERAL(opline), &ZEND_OP2_LITERAL(opline) TSRMLS_CC) != SUCCESS) {
+ if (binary_op(&result, &ZEND_OP1_LITERAL(opline), &ZEND_OP2_LITERAL(opline)) != SUCCESS) {
EG(error_reporting) = er;
break;
}
EG(error_reporting) = er;
- PZ_SET_REFCOUNT_P(&result, 1);
- PZ_UNSET_ISREF_P(&result);
-
literal_dtor(&ZEND_OP1_LITERAL(opline));
literal_dtor(&ZEND_OP2_LITERAL(opline));
MAKE_NOP(opline);
- replace_tmp_by_const(op_array, opline + 1, tv, &result TSRMLS_CC);
+ zend_optimizer_replace_by_const(op_array, opline + 1, IS_TMP_VAR, tv, &result);
}
break;
@@ -80,7 +101,8 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
opline->extended_value != IS_OBJECT &&
opline->extended_value != IS_RESOURCE) {
/* cast of constant operand */
- zend_uint tv = ZEND_RESULT(opline).var; /* temporary variable */
+ zend_uchar type = opline->result_type;
+ uint32_t tv = ZEND_RESULT(opline).var; /* temporary variable */
zval res;
res = ZEND_OP1_LITERAL(opline);
zval_copy_ctor(&res);
@@ -88,7 +110,7 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
case IS_NULL:
convert_to_null(&res);
break;
- case IS_BOOL:
+ case _IS_BOOL:
convert_to_boolean(&res);
break;
case IS_LONG:
@@ -105,8 +127,8 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
literal_dtor(&ZEND_OP1_LITERAL(opline));
MAKE_NOP(opline);
- replace_tmp_by_const(op_array, opline + 1, tv, &res TSRMLS_CC);
- } else if (opline->extended_value == IS_BOOL) {
+ zend_optimizer_replace_by_const(op_array, opline + 1, type, tv, &res);
+ } else if (opline->extended_value == _IS_BOOL) {
/* T = CAST(X, IS_BOOL) => T = BOOL(X) */
opline->opcode = ZEND_BOOL;
opline->extended_value = 0;
@@ -119,27 +141,20 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
/* unary operation on constant operand */
unary_op_type unary_op = get_unary_op(opline->opcode);
zval result;
- zend_uint tv = ZEND_RESULT(opline).var; /* temporary variable */
+ uint32_t tv = ZEND_RESULT(opline).var; /* temporary variable */
int er;
er = EG(error_reporting);
EG(error_reporting) = 0;
-#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
if (unary_op(&result, &ZEND_OP1_LITERAL(opline)) != SUCCESS) {
-#else
- if (unary_op(&result, &ZEND_OP1_LITERAL(opline) TSRMLS_CC) != SUCCESS) {
-#endif
EG(error_reporting) = er;
break;
}
EG(error_reporting) = er;
- PZ_SET_REFCOUNT_P(&result, 1);
- PZ_UNSET_ISREF_P(&result);
-
literal_dtor(&ZEND_OP1_LITERAL(opline));
MAKE_NOP(opline);
- replace_tmp_by_const(op_array, opline + 1, tv, &result TSRMLS_CC);
+ zend_optimizer_replace_by_const(op_array, opline + 1, IS_TMP_VAR, tv, &result);
}
break;
@@ -149,6 +164,7 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
zend_op *next_op = opline + 1;
int requires_conversion = (opline->opcode == ZEND_ADD_CHAR? 1 : 0);
size_t final_length = 0;
+ zend_string *str;
char *ptr;
zend_op *last_op;
@@ -164,7 +180,7 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
if (next_op->opcode == ZEND_ADD_CHAR) {
final_length += 1;
} else { /* ZEND_ADD_STRING */
- final_length += ZEND_OP2_LITERAL(next_op).value.str.len;
+ final_length += Z_STRLEN(ZEND_OP2_LITERAL(next_op));
}
next_op++;
}
@@ -172,34 +188,32 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
break;
}
last_op = next_op;
- final_length += (requires_conversion? 1 : ZEND_OP2_LITERAL(opline).value.str.len);
- ptr = (char *)emalloc(final_length + 1);
+ final_length += (requires_conversion? 1 : Z_STRLEN(ZEND_OP2_LITERAL(opline)));
+ str = zend_string_alloc(final_length, 0);
+ ptr = str->val;
ptr[final_length] = '\0';
if (requires_conversion) { /* ZEND_ADD_CHAR */
- char chval = (char)ZEND_OP2_LITERAL(opline).value.lval;
+ char chval = (char)Z_LVAL(ZEND_OP2_LITERAL(opline));
- ZEND_OP2_LITERAL(opline).value.str.val = ptr;
+ ZVAL_NEW_STR(&ZEND_OP2_LITERAL(opline), str);
ptr[0] = chval;
- ZEND_OP2_LITERAL(opline).type = IS_STRING;
opline->opcode = ZEND_ADD_STRING;
ptr++;
} else { /* ZEND_ADD_STRING */
memcpy(ptr, Z_STRVAL(ZEND_OP2_LITERAL(opline)), Z_STRLEN(ZEND_OP2_LITERAL(opline)));
- if (!IS_INTERNED(Z_STRVAL(ZEND_OP2_LITERAL(opline)))) {
- efree(Z_STRVAL(ZEND_OP2_LITERAL(opline)));
- }
- Z_STRVAL(ZEND_OP2_LITERAL(opline)) = ptr;
+ zend_string_release(Z_STR(ZEND_OP2_LITERAL(opline)));
+ Z_STR(ZEND_OP2_LITERAL(opline)) = str;
ptr += Z_STRLEN(ZEND_OP2_LITERAL(opline));
}
- ZEND_OP2_LITERAL(opline).value.str.len = final_length;
+ Z_STRLEN(ZEND_OP2_LITERAL(opline)) = final_length;
next_op = opline + 1;
while (next_op < last_op) {
if (next_op->opcode == ZEND_ADD_STRING) {
- memcpy(ptr, ZEND_OP2_LITERAL(next_op).value.str.val, ZEND_OP2_LITERAL(next_op).value.str.len);
- ptr += ZEND_OP2_LITERAL(next_op).value.str.len;
+ memcpy(ptr, Z_STRVAL(ZEND_OP2_LITERAL(next_op)), Z_STRLEN(ZEND_OP2_LITERAL(next_op)));
+ ptr += Z_STRLEN(ZEND_OP2_LITERAL(next_op));
literal_dtor(&ZEND_OP2_LITERAL(next_op));
} else { /* ZEND_ADD_CHAR */
- *ptr = (char)ZEND_OP2_LITERAL(next_op).value.lval;
+ *ptr = (char)Z_LVAL(ZEND_OP2_LITERAL(next_op));
ptr++;
}
MAKE_NOP(next_op);
@@ -222,33 +236,33 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
Z_STRLEN(ZEND_OP2_LITERAL(opline)) == sizeof("__COMPILER_HALT_OFFSET__") - 1 &&
memcmp(Z_STRVAL(ZEND_OP2_LITERAL(opline)), "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1) == 0) {
/* substitute __COMPILER_HALT_OFFSET__ constant */
- zend_bool orig_in_execution = EG(in_execution);
- zend_op_array *orig_op_array = EG(active_op_array);
- zval offset;
+ zend_execute_data *orig_execute_data = EG(current_execute_data);
+ zend_execute_data fake_execute_data;
+ zval *offset;
- EG(in_execution) = 1;
- EG(active_op_array) = op_array;
- if (zend_get_constant("__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1, &offset TSRMLS_CC)) {
- zend_uint tv = ZEND_RESULT(opline).var;
+ memset(&fake_execute_data, 0, sizeof(zend_execute_data));
+ fake_execute_data.func = (zend_function*)op_array;
+ EG(current_execute_data) = &fake_execute_data;
+ if ((offset = zend_get_constant_str("__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1)) != NULL) {
+ uint32_t tv = ZEND_RESULT(opline).var;
literal_dtor(&ZEND_OP2_LITERAL(opline));
MAKE_NOP(opline);
- replace_tmp_by_const(op_array, opline, tv, &offset TSRMLS_CC);
+ zend_optimizer_replace_by_const(op_array, opline, IS_TMP_VAR, tv, offset);
}
- EG(active_op_array) = orig_op_array;
- EG(in_execution) = orig_in_execution;
+ EG(current_execute_data) = orig_execute_data;
break;
}
if (ZEND_OP1_TYPE(opline) == IS_UNUSED &&
ZEND_OP2_TYPE(opline) == IS_CONST &&
- ZEND_OP2_LITERAL(opline).type == IS_STRING) {
+ Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING) {
/* substitute persistent constants */
- zend_uint tv = ZEND_RESULT(opline).var;
+ uint32_t tv = ZEND_RESULT(opline).var;
zval c;
- if (!zend_get_persistent_constant(Z_STRVAL(ZEND_OP2_LITERAL(opline)), Z_STRLEN(ZEND_OP2_LITERAL(opline)), &c, 1 TSRMLS_CC)) {
- if (!*constants || !zend_optimizer_get_collected_constant(*constants, &ZEND_OP2_LITERAL(opline), &c)) {
+ if (!zend_optimizer_get_persistent_constant(Z_STR(ZEND_OP2_LITERAL(opline)), &c, 1)) {
+ if (!ctx->constants || !zend_optimizer_get_collected_constant(ctx->constants, &ZEND_OP2_LITERAL(opline), &c)) {
break;
}
}
@@ -257,65 +271,60 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
}
literal_dtor(&ZEND_OP2_LITERAL(opline));
MAKE_NOP(opline);
- replace_tmp_by_const(op_array, opline, tv, &c TSRMLS_CC);
+ zend_optimizer_replace_by_const(op_array, opline, IS_TMP_VAR, tv, &c);
}
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
/* class constant */
if (ZEND_OP1_TYPE(opline) != IS_UNUSED &&
ZEND_OP2_TYPE(opline) == IS_CONST &&
- ZEND_OP2_LITERAL(opline).type == IS_STRING) {
+ Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING) {
- zend_class_entry **pce = NULL;
+ zend_class_entry *ce = NULL;
if (ZEND_OP1_TYPE(opline) == IS_CONST &&
- ZEND_OP1_LITERAL(opline).type == IS_STRING) {
+ Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING) {
/* for A::B */
- if (op_array->scope &&
+ if (op_array->scope &&
!strncasecmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)),
- op_array->scope->name, Z_STRLEN(ZEND_OP1_LITERAL(opline)) + 1)) {
- pce = &op_array->scope;
- } else {
- if (zend_hash_quick_find(EG(class_table),
- Z_STRVAL(op_array->literals[opline->op1.constant + 1].constant),
- Z_STRLEN(op_array->literals[opline->op1.constant].constant) + 1,
- Z_HASH_P(&op_array->literals[opline->op1.constant + 1].constant),
- (void **)&pce) == FAILURE ||
- ((*pce)->type == ZEND_INTERNAL_CLASS &&
- (*pce)->info.internal.module->type != MODULE_PERSISTENT) ||
- ((*pce)->type == ZEND_USER_CLASS &&
- ZEND_CE_FILENAME(*pce) != op_array->filename)) {
+ op_array->scope->name->val, Z_STRLEN(ZEND_OP1_LITERAL(opline)) + 1)) {
+ ce = op_array->scope;
+ } else {
+ if ((ce = zend_hash_find_ptr(EG(class_table),
+ Z_STR(op_array->literals[opline->op1.constant + 1]))) == NULL ||
+ (ce->type == ZEND_INTERNAL_CLASS &&
+ ce->info.internal.module->type != MODULE_PERSISTENT) ||
+ (ce->type == ZEND_USER_CLASS &&
+ ZEND_CE_FILENAME(ce) != op_array->filename)) {
break;
}
}
} else if (op_array->scope &&
ZEND_OP1_TYPE(opline) == IS_VAR &&
- (opline - 1)->opcode == ZEND_FETCH_CLASS &&
+ (opline - 1)->opcode == ZEND_FETCH_CLASS &&
(ZEND_OP1_TYPE(opline - 1) == IS_UNUSED &&
((opline - 1)->extended_value & ~ZEND_FETCH_CLASS_NO_AUTOLOAD) == ZEND_FETCH_CLASS_SELF) &&
ZEND_RESULT((opline - 1)).var == ZEND_OP1(opline).var) {
/* for self::B */
- pce = &op_array->scope;
+ ce = op_array->scope;
}
- if (pce) {
- zend_uint tv = ZEND_RESULT(opline).var;
- zval **c, t;
+ if (ce) {
+ uint32_t tv = ZEND_RESULT(opline).var;
+ zval *c, t;
- if (zend_hash_find(&(*pce)->constants_table,
- Z_STRVAL(ZEND_OP2_LITERAL(opline)),
- Z_STRLEN(ZEND_OP2_LITERAL(opline)) + 1,
- (void **) &c) == SUCCESS) {
- if (Z_TYPE_PP(c) == IS_CONSTANT_AST) {
+ if ((c = zend_hash_find(&ce->constants_table,
+ Z_STR(ZEND_OP2_LITERAL(opline)))) != NULL) {
+ ZVAL_DEREF(c);
+ if (Z_TYPE_P(c) == IS_CONSTANT_AST) {
break;
}
- if (ZEND_IS_CONSTANT_TYPE(Z_TYPE_PP(c))) {
- if (!zend_get_persistent_constant(Z_STRVAL_PP(c), Z_STRLEN_PP(c), &t, 1 TSRMLS_CC) ||
+ if (ZEND_IS_CONSTANT_TYPE(Z_TYPE_P(c))) {
+ if (!zend_optimizer_get_persistent_constant(Z_STR_P(c), &t, 1) ||
ZEND_IS_CONSTANT_TYPE(Z_TYPE(t))) {
break;
}
} else {
- t = **c;
+ ZVAL_COPY_VALUE(&t, c);
zval_copy_ctor(&t);
}
@@ -326,33 +335,81 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
}
literal_dtor(&ZEND_OP2_LITERAL(opline));
MAKE_NOP(opline);
- replace_tmp_by_const(op_array, opline, tv, &t TSRMLS_CC);
+ zend_optimizer_replace_by_const(op_array, opline, IS_TMP_VAR, tv, &t);
}
}
}
-#endif
break;
- case ZEND_DO_FCALL:
- /* define("name", scalar); */
- if (collect_constants &&
- opline->extended_value == 2 &&
- ZEND_OP1_TYPE(opline) == IS_CONST &&
- Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING &&
- Z_STRLEN(ZEND_OP1_LITERAL(opline)) == sizeof("define")-1 &&
- zend_binary_strcasecmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)), Z_STRLEN(ZEND_OP1_LITERAL(opline)), "define", sizeof("define")-1) == 0 &&
- (opline-1)->opcode == ZEND_SEND_VAL &&
- ZEND_OP1_TYPE(opline-1) == IS_CONST &&
- (Z_TYPE(ZEND_OP1_LITERAL(opline-1)) <= IS_BOOL ||
- Z_TYPE(ZEND_OP1_LITERAL(opline-1)) == IS_STRING) &&
- (opline-2)->opcode == ZEND_SEND_VAL &&
- ZEND_OP1_TYPE(opline-2) == IS_CONST &&
- Z_TYPE(ZEND_OP1_LITERAL(opline-2)) == IS_STRING) {
- zend_optimizer_collect_constant(constants, &ZEND_OP1_LITERAL(opline-2), &ZEND_OP1_LITERAL(opline-1));
+ case ZEND_DO_FCALL: {
+ zend_op *send1_opline = opline - 1;
+ zend_op *send2_opline = NULL;
+ zend_op *init_opline = NULL;
+
+ while (send1_opline->opcode == ZEND_NOP) {
+ send1_opline--;
+ }
+ if (send1_opline->opcode != ZEND_SEND_VAL ||
+ ZEND_OP1_TYPE(send1_opline) != IS_CONST) {
+ /* don't colllect constants after unknown function call */
+ collect_constants = 0;
break;
- } else {
- /* don't colllect constants after any other function call */
+ }
+ if (send1_opline->op2.num == 2) {
+ send2_opline = send1_opline;
+ send1_opline--;
+ while (send1_opline->opcode == ZEND_NOP) {
+ send1_opline--;
+ }
+ if (send1_opline->opcode != ZEND_SEND_VAL ||
+ ZEND_OP1_TYPE(send1_opline) != IS_CONST) {
+ /* don't colllect constants after unknown function call */
+ collect_constants = 0;
+ break;
+ }
+ }
+ init_opline = send1_opline - 1;
+ while (init_opline->opcode == ZEND_NOP) {
+ init_opline--;
+ }
+ if (init_opline->opcode != ZEND_INIT_FCALL ||
+ ZEND_OP2_TYPE(init_opline) != IS_CONST ||
+ Z_TYPE(ZEND_OP2_LITERAL(init_opline)) != IS_STRING) {
+ /* don't colllect constants after unknown function call */
collect_constants = 0;
+ break;
+ }
+
+ /* define("name", scalar); */
+ if (Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("define")-1 &&
+ zend_binary_strcasecmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)), Z_STRLEN(ZEND_OP2_LITERAL(init_opline)), "define", sizeof("define")-1) == 0) {
+
+ if (Z_TYPE(ZEND_OP1_LITERAL(send1_opline)) == IS_STRING &&
+ send2_opline &&
+ Z_TYPE(ZEND_OP1_LITERAL(send2_opline)) <= IS_STRING) {
+
+ if (collect_constants) {
+ zend_optimizer_collect_constant(ctx, &ZEND_OP1_LITERAL(send1_opline), &ZEND_OP1_LITERAL(send2_opline));
+ }
+
+ if (RESULT_UNUSED(opline) &&
+ !zend_memnstr(Z_STRVAL(ZEND_OP1_LITERAL(send1_opline)), "::", sizeof("::") - 1, Z_STRVAL(ZEND_OP1_LITERAL(send1_opline)) + Z_STRLEN(ZEND_OP1_LITERAL(send1_opline)))) {
+
+ opline->opcode = ZEND_DECLARE_CONST;
+ opline->op1_type = IS_CONST;
+ opline->op2_type = IS_CONST;
+ opline->result_type = IS_UNUSED;
+ opline->op1.constant = send1_opline->op1.constant;
+ opline->op2.constant = send2_opline->op1.constant;
+ opline->result.num = 0;
+
+ literal_dtor(&ZEND_OP2_LITERAL(init_opline));
+ MAKE_NOP(init_opline);
+ MAKE_NOP(send1_opline);
+ MAKE_NOP(send2_opline);
+ }
+ break;
+ }
}
/* pre-evaluate constant functions:
@@ -362,141 +419,183 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
is_callable(x)
extension_loaded(x)
*/
- if (opline->extended_value == 1 && (opline - 1)->opcode == ZEND_SEND_VAL &&
- ZEND_OP1_TYPE(opline - 1) == IS_CONST && ZEND_OP1_LITERAL(opline - 1).type == IS_STRING &&
- ZEND_OP1_TYPE(opline) == IS_CONST && ZEND_OP1_LITERAL(opline).type == IS_STRING) {
- if ((Z_STRLEN(ZEND_OP1_LITERAL(opline)) == sizeof("function_exists")-1 &&
- !memcmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)),
+ if (!send2_opline &&
+ Z_TYPE(ZEND_OP1_LITERAL(send1_opline)) == IS_STRING) {
+ if ((Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("function_exists")-1 &&
+ !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)),
"function_exists", sizeof("function_exists")-1)) ||
- (Z_STRLEN(ZEND_OP1_LITERAL(opline)) == sizeof("is_callable")-1 &&
- !memcmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)),
+ (Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("is_callable")-1 &&
+ !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)),
"is_callable", sizeof("is_callable")))) {
zend_internal_function *func;
- char *lc_name = zend_str_tolower_dup(
- Z_STRVAL(ZEND_OP1_LITERAL(opline - 1)), Z_STRLEN(ZEND_OP1_LITERAL(opline - 1)));
-
- if (zend_hash_find(EG(function_table), lc_name, Z_STRLEN(ZEND_OP1_LITERAL(opline - 1)) + 1,
- (void *)&func) == SUCCESS &&
+ zend_string *lc_name = zend_string_tolower(
+ Z_STR(ZEND_OP1_LITERAL(send1_opline)));
+
+ if ((func = zend_hash_find_ptr(EG(function_table), lc_name)) != NULL &&
func->type == ZEND_INTERNAL_FUNCTION &&
func->module->type == MODULE_PERSISTENT) {
zval t;
- ZVAL_BOOL(&t, 1);
- if (replace_var_by_const(op_array, opline + 1, ZEND_RESULT(opline).var, &t TSRMLS_CC)) {
- literal_dtor(&ZEND_OP1_LITERAL(opline - 1));
- MAKE_NOP((opline - 1));
- literal_dtor(&ZEND_OP1_LITERAL(opline));
+ ZVAL_TRUE(&t);
+ if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_VAR, ZEND_RESULT(opline).var, &t)) {
+ literal_dtor(&ZEND_OP2_LITERAL(init_opline));
+ MAKE_NOP(init_opline);
+ literal_dtor(&ZEND_OP1_LITERAL(send1_opline));
+ MAKE_NOP(send1_opline);
MAKE_NOP(opline);
+ zend_string_release(lc_name);
+ break;
}
}
- efree(lc_name);
- } else if (Z_STRLEN(ZEND_OP1_LITERAL(opline)) == sizeof("extension_loaded")-1 &&
- !memcmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)),
+ zend_string_release(lc_name);
+ } else if (Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("extension_loaded")-1 &&
+ !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)),
"extension_loaded", sizeof("extension_loaded")-1)) {
zval t;
- zend_module_entry *m;
- char *lc_name = zend_str_tolower_dup(
- Z_STRVAL(ZEND_OP1_LITERAL(opline - 1)), Z_STRLEN(ZEND_OP1_LITERAL(opline - 1)));
- int found = zend_hash_find(&module_registry,
- lc_name, Z_STRLEN(ZEND_OP1_LITERAL(opline - 1)) + 1, (void *)&m) == SUCCESS;
-
- efree(lc_name);
- if (!found) {
+ zend_string *lc_name = zend_string_tolower(
+ Z_STR(ZEND_OP1_LITERAL(send1_opline)));
+ zend_module_entry *m = zend_hash_find_ptr(&module_registry,
+ lc_name);
+
+ zend_string_release(lc_name);
+ if (!m) {
if (!PG(enable_dl)) {
break;
} else {
- ZVAL_BOOL(&t, 0);
+ ZVAL_FALSE(&t);
}
} else {
if (m->type == MODULE_PERSISTENT) {
- ZVAL_BOOL(&t, 1);
+ ZVAL_TRUE(&t);
} else {
break;
}
- }
+ }
- if (replace_var_by_const(op_array, opline + 1, ZEND_RESULT(opline).var, &t TSRMLS_CC)) {
- literal_dtor(&ZEND_OP1_LITERAL(opline - 1));
- MAKE_NOP((opline - 1));
- literal_dtor(&ZEND_OP1_LITERAL(opline));
+ if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_VAR, ZEND_RESULT(opline).var, &t)) {
+ literal_dtor(&ZEND_OP2_LITERAL(init_opline));
+ MAKE_NOP(init_opline);
+ literal_dtor(&ZEND_OP1_LITERAL(send1_opline));
+ MAKE_NOP(send1_opline);
MAKE_NOP(opline);
+ break;
}
- } else if (Z_STRLEN(ZEND_OP1_LITERAL(opline)) == sizeof("defined")-1 &&
- !memcmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)),
+ } else if (Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("defined")-1 &&
+ !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)),
"defined", sizeof("defined")-1)) {
zval t;
- if (zend_get_persistent_constant(Z_STRVAL(ZEND_OP1_LITERAL(opline - 1)),
- Z_STRLEN(ZEND_OP1_LITERAL(opline - 1)), &t, 0 TSRMLS_CC)) {
+ if (zend_optimizer_get_persistent_constant(Z_STR(ZEND_OP1_LITERAL(send1_opline)), &t, 0)) {
- ZVAL_BOOL(&t, 1);
- if (replace_var_by_const(op_array, opline + 1, ZEND_RESULT(opline).var, &t TSRMLS_CC)) {
- literal_dtor(&ZEND_OP1_LITERAL(opline - 1));
- MAKE_NOP((opline - 1));
- literal_dtor(&ZEND_OP1_LITERAL(opline));
+ ZVAL_TRUE(&t);
+ if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_VAR, ZEND_RESULT(opline).var, &t)) {
+ literal_dtor(&ZEND_OP2_LITERAL(init_opline));
+ MAKE_NOP(init_opline);
+ literal_dtor(&ZEND_OP1_LITERAL(send1_opline));
+ MAKE_NOP(send1_opline);
MAKE_NOP(opline);
+ break;
}
}
- } else if (Z_STRLEN(ZEND_OP1_LITERAL(opline)) == sizeof("constant")-1 &&
- !memcmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)),
+ } else if (Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("constant")-1 &&
+ !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)),
"constant", sizeof("constant")-1)) {
zval t;
-
- if (zend_get_persistent_constant(Z_STRVAL(ZEND_OP1_LITERAL(opline - 1)),
- Z_STRLEN(ZEND_OP1_LITERAL(opline - 1)), &t, 1 TSRMLS_CC)) {
- if (replace_var_by_const(op_array, opline + 1, ZEND_RESULT(opline).var, &t TSRMLS_CC)) {
- literal_dtor(&ZEND_OP1_LITERAL(opline - 1));
- MAKE_NOP((opline - 1));
- literal_dtor(&ZEND_OP1_LITERAL(opline));
+
+ if (zend_optimizer_get_persistent_constant(Z_STR(ZEND_OP1_LITERAL(send1_opline)), &t, 1)) {
+ if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_VAR, ZEND_RESULT(opline).var, &t)) {
+ literal_dtor(&ZEND_OP2_LITERAL(init_opline));
+ MAKE_NOP(init_opline);
+ literal_dtor(&ZEND_OP1_LITERAL(send1_opline));
+ MAKE_NOP(send1_opline);
MAKE_NOP(opline);
+ break;
}
}
- } else if ((!zend_hash_exists(&module_registry, "mbstring", sizeof("mbstring")) ||
- zend_ini_long("mbstring.func_overload",
- sizeof("mbstring.func_overload"), 0) < 2 /* MB_OVERLOAD_STRING */) &&
- Z_STRLEN(ZEND_OP1_LITERAL(opline)) == sizeof("strlen") - 1 &&
- !memcmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)), "strlen", sizeof("strlen") - 1)) {
+ } else if ((CG(compiler_options) & ZEND_COMPILE_NO_BUILTIN_STRLEN) == 0 &&
+ Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("strlen") - 1 &&
+ !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)), "strlen", sizeof("strlen") - 1)) {
zval t;
- ZVAL_LONG(&t, Z_STRLEN(ZEND_OP1_LITERAL(opline - 1)));
- if (replace_var_by_const(op_array, opline + 1, ZEND_RESULT(opline).var, &t TSRMLS_CC)) {
- literal_dtor(&ZEND_OP1_LITERAL(opline - 1));
- MAKE_NOP((opline - 1));
- literal_dtor(&ZEND_OP1_LITERAL(opline));
+ ZVAL_LONG(&t, Z_STRLEN(ZEND_OP1_LITERAL(send1_opline)));
+ if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_VAR, ZEND_RESULT(opline).var, &t)) {
+ literal_dtor(&ZEND_OP2_LITERAL(init_opline));
+ MAKE_NOP(init_opline);
+ literal_dtor(&ZEND_OP1_LITERAL(send1_opline));
+ MAKE_NOP(send1_opline);
MAKE_NOP(opline);
+ break;
}
+ /* dirname(IS_CONST/IS_STRING) -> IS_CONST/IS_STRING */
+ } else if (Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("dirname")-1 &&
+ !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)),
+ "dirname", sizeof("dirname")-1) &&
+ IS_ABSOLUTE_PATH(Z_STRVAL(ZEND_OP1_LITERAL(send1_opline)), Z_STRLEN(ZEND_OP1_LITERAL(send1_opline)))) {
+ zend_string *dirname = zend_string_init(Z_STRVAL(ZEND_OP1_LITERAL(send1_opline)), Z_STRLEN(ZEND_OP1_LITERAL(send1_opline)), 0);
+ dirname->len = zend_dirname(dirname->val, dirname->len);
+ if (IS_ABSOLUTE_PATH(dirname->val, dirname->len)) {
+ zval t;
+
+ ZVAL_STR(&t, dirname);
+ if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_VAR, ZEND_RESULT(opline).var, &t)) {
+ literal_dtor(&ZEND_OP2_LITERAL(init_opline));
+ MAKE_NOP(init_opline);
+ literal_dtor(&ZEND_OP1_LITERAL(send1_opline));
+ MAKE_NOP(send1_opline);
+ MAKE_NOP(opline);
+ break;
+ }
+ } else {
+ zend_string_release(dirname);
+ }
+ }
+ }
+ /* don't colllect constants after any other function call */
+ collect_constants = 0;
+ break;
+ }
+ case ZEND_STRLEN:
+ if (ZEND_OP1_TYPE(opline) == IS_CONST &&
+ Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING) {
+ zval t;
+
+ ZVAL_LONG(&t, Z_STRLEN(ZEND_OP1_LITERAL(opline)));
+ zend_optimizer_replace_by_const(op_array, opline + 1, IS_TMP_VAR, ZEND_RESULT(opline).var, &t);
+ literal_dtor(&ZEND_OP1_LITERAL(opline));
+ MAKE_NOP(opline);
+ }
+ break;
+ case ZEND_DEFINED:
+ {
+ zval c;
+ uint32_t tv = ZEND_RESULT(opline).var;
+ if (!zend_optimizer_get_persistent_constant(Z_STR(ZEND_OP1_LITERAL(opline)), &c, 0)) {
+ break;
}
- }
+ ZVAL_TRUE(&c);
+ zend_optimizer_replace_by_const(op_array, opline, IS_TMP_VAR, tv, &c);
+ literal_dtor(&ZEND_OP1_LITERAL(opline));
+ MAKE_NOP(opline);
+ }
break;
-#if ZEND_EXTENSION_API_NO > PHP_5_2_X_API_NO
case ZEND_DECLARE_CONST:
if (collect_constants &&
Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING &&
- (Z_TYPE(ZEND_OP2_LITERAL(opline)) <= IS_BOOL ||
- Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING)) {
- zend_optimizer_collect_constant(constants, &ZEND_OP1_LITERAL(opline), &ZEND_OP2_LITERAL(opline));
+ Z_TYPE(ZEND_OP2_LITERAL(opline)) <= IS_STRING) {
+ zend_optimizer_collect_constant(ctx, &ZEND_OP1_LITERAL(opline), &ZEND_OP2_LITERAL(opline));
}
break;
-#endif
case ZEND_RETURN:
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
case ZEND_RETURN_BY_REF:
-#endif
-#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
case ZEND_GENERATOR_RETURN:
-#endif
case ZEND_EXIT:
case ZEND_THROW:
case ZEND_CATCH:
case ZEND_BRK:
case ZEND_CONT:
-#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
case ZEND_GOTO:
-#endif
-#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
case ZEND_FAST_CALL:
case ZEND_FAST_RET:
-#endif
case ZEND_JMP:
case ZEND_JMPZNZ:
case ZEND_JMPZ:
@@ -506,17 +605,10 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
case ZEND_FE_RESET:
case ZEND_FE_FETCH:
case ZEND_NEW:
- case ZEND_DO_FCALL_BY_NAME:
-#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
case ZEND_JMP_SET:
-#endif
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
- case ZEND_JMP_SET_VAR:
-#endif
+ case ZEND_COALESCE:
collect_constants = 0;
break;
-
-#if ZEND_EXTENSION_API_NO >= PHP_5_5_X_API_NO
case ZEND_FETCH_R:
case ZEND_FETCH_W:
case ZEND_FETCH_RW:
@@ -568,21 +660,17 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
if (use->op1_type == IS_VAR && use->op1.var == var) {
use->op1_type = IS_CV;
use->op1.var = zend_optimizer_lookup_cv(op_array,
- Z_STRVAL(ZEND_OP1_LITERAL(opline)),
- Z_STRLEN(ZEND_OP1_LITERAL(opline)));
+ Z_STR(ZEND_OP1_LITERAL(opline)));
MAKE_NOP(opline);
} else if (use->op2_type == IS_VAR && use->op2.var == var) {
use->op2_type = IS_CV;
use->op2.var = zend_optimizer_lookup_cv(op_array,
- Z_STRVAL(ZEND_OP1_LITERAL(opline)),
- Z_STRLEN(ZEND_OP1_LITERAL(opline)));
+ Z_STR(ZEND_OP1_LITERAL(opline)));
MAKE_NOP(opline);
}
}
}
break;
-#endif
-
}
opline++;
i++;
diff --git a/ext/opcache/Optimizer/pass2.c b/ext/opcache/Optimizer/pass2.c
index 8704b787a9..b1c677237d 100644
--- a/ext/opcache/Optimizer/pass2.c
+++ b/ext/opcache/Optimizer/pass2.c
@@ -1,10 +1,40 @@
+/*
+ +----------------------------------------------------------------------+
+ | Zend OPcache |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1998-2014 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Andi Gutmans <andi@zend.com> |
+ | Zeev Suraski <zeev@zend.com> |
+ | Stanislav Malyshev <stas@zend.com> |
+ | Dmitry Stogov <dmitry@zend.com> |
+ +----------------------------------------------------------------------+
+*/
+
/* pass 2:
* - convert non-numeric constants to numeric constants in numeric operators
* - optimize constant conditional JMPs
* - optimize static BRKs and CONTs
*/
-if (ZEND_OPTIMIZER_PASS_2 & OPTIMIZATION_LEVEL) {
+#include "php.h"
+#include "Optimizer/zend_optimizer.h"
+#include "Optimizer/zend_optimizer_internal.h"
+#include "zend_API.h"
+#include "zend_constants.h"
+#include "zend_execute.h"
+#include "zend_vm.h"
+
+void zend_optimizer_pass2(zend_op_array *op_array)
+{
zend_op *opline;
zend_op *end = op_array->opcodes + op_array->last;
@@ -16,8 +46,8 @@ if (ZEND_OPTIMIZER_PASS_2 & OPTIMIZATION_LEVEL) {
case ZEND_MUL:
case ZEND_DIV:
if (ZEND_OP1_TYPE(opline) == IS_CONST) {
- if (ZEND_OP1_LITERAL(opline).type == IS_STRING) {
- convert_scalar_to_number(&ZEND_OP1_LITERAL(opline) TSRMLS_CC);
+ if (Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING) {
+ convert_scalar_to_number(&ZEND_OP1_LITERAL(opline));
}
}
/* break missing *intentionally* - the assign_op's may only optimize op2 */
@@ -30,8 +60,8 @@ if (ZEND_OPTIMIZER_PASS_2 & OPTIMIZATION_LEVEL) {
break;
}
if (ZEND_OP2_TYPE(opline) == IS_CONST) {
- if (ZEND_OP2_LITERAL(opline).type == IS_STRING) {
- convert_scalar_to_number(&ZEND_OP2_LITERAL(opline) TSRMLS_CC);
+ if (Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING) {
+ convert_scalar_to_number(&ZEND_OP2_LITERAL(opline));
}
}
break;
@@ -40,7 +70,7 @@ if (ZEND_OPTIMIZER_PASS_2 & OPTIMIZATION_LEVEL) {
case ZEND_SL:
case ZEND_SR:
if (ZEND_OP1_TYPE(opline) == IS_CONST) {
- if (ZEND_OP1_LITERAL(opline).type != IS_LONG) {
+ if (Z_TYPE(ZEND_OP1_LITERAL(opline)) != IS_LONG) {
convert_to_long(&ZEND_OP1_LITERAL(opline));
}
}
@@ -53,7 +83,7 @@ if (ZEND_OPTIMIZER_PASS_2 & OPTIMIZATION_LEVEL) {
break;
}
if (ZEND_OP2_TYPE(opline) == IS_CONST) {
- if (ZEND_OP2_LITERAL(opline).type != IS_LONG) {
+ if (Z_TYPE(ZEND_OP2_LITERAL(opline)) != IS_LONG) {
convert_to_long(&ZEND_OP2_LITERAL(opline));
}
}
@@ -61,7 +91,7 @@ if (ZEND_OPTIMIZER_PASS_2 & OPTIMIZATION_LEVEL) {
case ZEND_CONCAT:
if (ZEND_OP1_TYPE(opline) == IS_CONST) {
- if (ZEND_OP1_LITERAL(opline).type != IS_STRING) {
+ if (Z_TYPE(ZEND_OP1_LITERAL(opline)) != IS_STRING) {
convert_to_string(&ZEND_OP1_LITERAL(opline));
}
}
@@ -72,7 +102,7 @@ if (ZEND_OPTIMIZER_PASS_2 & OPTIMIZATION_LEVEL) {
break;
}
if (ZEND_OP2_TYPE(opline) == IS_CONST) {
- if (ZEND_OP2_LITERAL(opline).type != IS_STRING) {
+ if (Z_TYPE(ZEND_OP2_LITERAL(opline)) != IS_STRING) {
convert_to_string(&ZEND_OP2_LITERAL(opline));
}
}
@@ -139,7 +169,6 @@ if (ZEND_OPTIMIZER_PASS_2 & OPTIMIZATION_LEVEL) {
case ZEND_JMPZNZ:
if (ZEND_OP1_TYPE(opline) == IS_CONST) {
int opline_num;
-
if (zend_is_true(&ZEND_OP1_LITERAL(opline))) {
opline_num = opline->extended_value; /* JMPNZ */
} else {
@@ -160,11 +189,10 @@ if (ZEND_OPTIMIZER_PASS_2 & OPTIMIZATION_LEVEL) {
int nest_levels;
int dont_optimize = 0;
- if (ZEND_OP2_TYPE(opline) != IS_CONST) {
- break;
- }
- convert_to_long(&ZEND_OP2_LITERAL(opline));
- nest_levels = ZEND_OP2_LITERAL(opline).value.lval;
+ ZEND_ASSERT(ZEND_OP2_TYPE(opline) == IS_CONST);
+ ZEND_ASSERT(Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_LONG);
+
+ nest_levels = Z_LVAL(ZEND_OP2_LITERAL(opline));
array_offset = ZEND_OP1(opline).opline_num;
while (1) {
@@ -175,9 +203,7 @@ if (ZEND_OPTIMIZER_PASS_2 & OPTIMIZATION_LEVEL) {
jmp_to = &op_array->brk_cont_array[array_offset];
array_offset = jmp_to->parent;
if (--nest_levels > 0) {
- if (op_array->opcodes[jmp_to->brk].opcode == ZEND_FREE ||
- op_array->opcodes[jmp_to->brk].opcode == ZEND_SWITCH_FREE
- ) {
+ if (op_array->opcodes[jmp_to->brk].opcode == ZEND_FREE) {
dont_optimize = 1;
break;
}
diff --git a/ext/opcache/Optimizer/pass3.c b/ext/opcache/Optimizer/pass3.c
index 1ee641ca52..8a4646a595 100644
--- a/ext/opcache/Optimizer/pass3.c
+++ b/ext/opcache/Optimizer/pass3.c
@@ -1,9 +1,38 @@
+/*
+ +----------------------------------------------------------------------+
+ | Zend OPcache |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1998-2014 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Andi Gutmans <andi@zend.com> |
+ | Zeev Suraski <zeev@zend.com> |
+ | Stanislav Malyshev <stas@zend.com> |
+ | Dmitry Stogov <dmitry@zend.com> |
+ +----------------------------------------------------------------------+
+*/
+
/* pass 3:
* - optimize $i = $i+expr to $i+=expr
* - optimize series of JMPs
* - change $i++ to ++$i where possible
*/
+#include "php.h"
+#include "Optimizer/zend_optimizer.h"
+#include "Optimizer/zend_optimizer_internal.h"
+#include "zend_API.h"
+#include "zend_constants.h"
+#include "zend_execute.h"
+#include "zend_vm.h"
+
/* compares opcodes with allowing oc1 be _EX of oc2 */
#define SAME_OPCODE_EX(oc1, oc2) ((oc1 == oc2) || (oc1 == ZEND_JMPZ_EX && oc2 == ZEND_JMPZ) || (oc1 == ZEND_JMPNZ_EX && oc2 == ZEND_JMPNZ))
@@ -24,16 +53,17 @@
} \
jmp_hitlist[jmp_hitlist_count++] = ZEND_OP2(&op_array->opcodes[target]).opline_num;
-if (ZEND_OPTIMIZER_PASS_3 & OPTIMIZATION_LEVEL) {
+void zend_optimizer_pass3(zend_op_array *op_array)
+{
zend_op *opline;
zend_op *end = op_array->opcodes + op_array->last;
- zend_uint *jmp_hitlist;
+ uint32_t *jmp_hitlist;
int jmp_hitlist_count;
int i;
- zend_uint opline_num = 0;
+ uint32_t opline_num = 0;
ALLOCA_FLAG(use_heap);
- jmp_hitlist = (zend_uint *)DO_ALLOCA(sizeof(zend_uint)*op_array->last);
+ jmp_hitlist = (uint32_t *)DO_ALLOCA(sizeof(uint32_t)*op_array->last);
opline = op_array->opcodes;
while (opline < end) {
@@ -45,9 +75,7 @@ if (ZEND_OPTIMIZER_PASS_3 & OPTIMIZATION_LEVEL) {
case ZEND_MUL:
case ZEND_DIV:
case ZEND_MOD:
-#if ZEND_EXTENSION_API_NO >= PHP_5_6_X_API_NO
case ZEND_POW:
-#endif
case ZEND_CONCAT:
case ZEND_SL:
case ZEND_SR:
@@ -75,12 +103,8 @@ if (ZEND_OPTIMIZER_PASS_3 & OPTIMIZATION_LEVEL) {
/* change $i=expr+$i to $i=$i+expr so that the next
* optimization works on it
*/
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
zend_uchar tmp_type = opline->op1_type;
znode_op tmp = opline->op1;
-#else
- znode tmp = opline->op1;
-#endif
if (opline->opcode != ZEND_ADD || ZEND_OP1_TYPE(opline) == IS_CONST) {
/* protection from array add: $a = array + $a is not commutative! */
@@ -107,11 +131,9 @@ if (ZEND_OPTIMIZER_PASS_3 & OPTIMIZATION_LEVEL) {
case ZEND_MOD:
opline->opcode = ZEND_ASSIGN_MOD;
break;
-#if ZEND_EXTENSION_API_NO >= PHP_5_6_X_API_NO
case ZEND_POW:
opline->opcode = ZEND_ASSIGN_POW;
break;
-#endif
case ZEND_CONCAT:
opline->opcode = ZEND_ASSIGN_CONCAT;
break;
@@ -140,11 +162,9 @@ if (ZEND_OPTIMIZER_PASS_3 & OPTIMIZATION_LEVEL) {
break;
case ZEND_JMP:
-#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
- if (op_array->has_finally_block) {
+ if (op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK) {
break;
}
-#endif
/* convert L: JMP L+1 to NOP */
if (ZEND_OP1(opline).opline_num == opline_num + 1) {
@@ -161,17 +181,11 @@ if (ZEND_OPTIMIZER_PASS_3 & OPTIMIZATION_LEVEL) {
}
break;
-#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
case ZEND_JMP_SET:
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
- case ZEND_JMP_SET_VAR:
-#endif
-
-#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
- if (op_array->has_finally_block) {
+ case ZEND_COALESCE:
+ if (op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK) {
break;
}
-#endif
while (ZEND_OP2(opline).opline_num < op_array->last) {
int target = ZEND_OP2(opline).opline_num;
@@ -182,15 +196,11 @@ if (ZEND_OPTIMIZER_PASS_3 & OPTIMIZATION_LEVEL) {
}
}
break;
-#endif
-
case ZEND_JMPZ:
case ZEND_JMPNZ:
-#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
- if (op_array->has_finally_block) {
+ if (op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK) {
break;
}
-#endif
/* convert L: JMPZ L+1 to NOP */
if (ZEND_OP2(opline).opline_num == opline_num + 1) {
@@ -241,17 +251,13 @@ if (ZEND_OPTIMIZER_PASS_3 & OPTIMIZATION_LEVEL) {
case ZEND_JMPZ_EX:
case ZEND_JMPNZ_EX: {
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
zend_uchar T_type = opline->result_type;
znode_op T = opline->result;
-#else
- znode T = opline->result;
-#endif
-#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
- if (op_array->has_finally_block) {
+
+ if (op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK) {
break;
}
-#endif
+
/* convert L: T = JMPZ_EX X,L+1 to T = BOOL(X) */
/* convert L: T = JMPZ_EX T,L+1 to NOP */
if (ZEND_OP2(opline).opline_num == opline_num + 1) {
@@ -320,12 +326,8 @@ continue_jmp_ex_optimization:
op->opcode == ZEND_CONT ||
op->opcode == ZEND_CASE ||
op->opcode == ZEND_RETURN ||
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
op->opcode == ZEND_RETURN_BY_REF ||
-#endif
-#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
op->opcode == ZEND_FAST_RET ||
-#endif
op->opcode == ZEND_FE_FETCH ||
op->opcode == ZEND_EXIT) {
break;
@@ -359,12 +361,8 @@ continue_jmp_ex_optimization:
op->opcode == ZEND_CONT ||
op->opcode == ZEND_CASE ||
op->opcode == ZEND_RETURN ||
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
op->opcode == ZEND_RETURN_BY_REF ||
-#endif
-#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
op->opcode == ZEND_FAST_RET ||
-#endif
op->opcode == ZEND_FE_FETCH ||
op->opcode == ZEND_EXIT) {
break;
@@ -390,11 +388,10 @@ continue_jmp_ex_optimization:
break;
case ZEND_JMPZNZ:
-#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
- if (op_array->has_finally_block) {
+ if (op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK) {
break;
}
-#endif
+
/* JMPZNZ(X,L1,L2), L1: JMP(L3) => JMPZNZ(X,L3,L2), L1: JMP(L3) */
while (ZEND_OP2(opline).opline_num < op_array->last
&& op_array->opcodes[ZEND_OP2(opline).opline_num].opcode == ZEND_JMP) {
@@ -431,13 +428,7 @@ continue_jmpznz_optimization:
opline->opcode = ZEND_PRE_DEC;
break;
}
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
ZEND_RESULT_TYPE(opline) = IS_VAR | EXT_TYPE_UNUSED;
-#else
- ZEND_RESULT_TYPE(opline) = IS_VAR;
- ZEND_RESULT(opline).EA.type = 0;
- ZEND_RESULT(opline).EA.type |= EXT_TYPE_UNUSED;
-#endif
}
}
break;
diff --git a/ext/opcache/Optimizer/pass5.c b/ext/opcache/Optimizer/pass5.c
deleted file mode 100644
index b0d651a5fc..0000000000
--- a/ext/opcache/Optimizer/pass5.c
+++ /dev/null
@@ -1,3 +0,0 @@
-if (ZEND_OPTIMIZER_PASS_5 & OPTIMIZATION_LEVEL) {
- zend_block_optimization(op_array TSRMLS_CC);
-}
diff --git a/ext/opcache/Optimizer/pass9.c b/ext/opcache/Optimizer/pass9.c
deleted file mode 100644
index 586160c14d..0000000000
--- a/ext/opcache/Optimizer/pass9.c
+++ /dev/null
@@ -1,8 +0,0 @@
-/* pass 9
- *
- * - optimize usage of temporary variables
- */
-
-if (ZEND_OPTIMIZER_PASS_9 & OPTIMIZATION_LEVEL) {
- optimize_temporary_variables(op_array);
-}
diff --git a/ext/opcache/Optimizer/zend_optimizer.c b/ext/opcache/Optimizer/zend_optimizer.c
index a41d324e1a..292a2a06d1 100644
--- a/ext/opcache/Optimizer/zend_optimizer.c
+++ b/ext/opcache/Optimizer/zend_optimizer.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| Zend OPcache |
+----------------------------------------------------------------------+
- | Copyright (c) 1998-2015 The PHP Group |
+ | Copyright (c) 1998-2014 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -27,169 +27,139 @@
#include "zend_execute.h"
#include "zend_vm.h"
-#define OPTIMIZATION_LEVEL \
- ZCG(accel_directives).optimization_level
-
static void zend_optimizer_zval_dtor_wrapper(zval *zvalue)
{
zval_dtor(zvalue);
}
-static void zend_optimizer_collect_constant(HashTable **constants, zval *name, zval* value)
+void zend_optimizer_collect_constant(zend_optimizer_ctx *ctx, zval *name, zval* value)
{
zval val;
- if (!*constants) {
- *constants = emalloc(sizeof(HashTable));
- zend_hash_init(*constants, 16, NULL, (void (*)(void *))zend_optimizer_zval_dtor_wrapper, 0);
+ if (!ctx->constants) {
+ ctx->constants = zend_arena_alloc(&ctx->arena, sizeof(HashTable));
+ zend_hash_init(ctx->constants, 16, NULL, zend_optimizer_zval_dtor_wrapper, 0);
}
- val = *value;
- zval_copy_ctor(&val);
- zend_hash_add(*constants, Z_STRVAL_P(name), Z_STRLEN_P(name)+1, (void**)&val, sizeof(zval), NULL);
+ ZVAL_DUP(&val, value);
+ zend_hash_add(ctx->constants, Z_STR_P(name), &val);
}
-static int zend_optimizer_get_collected_constant(HashTable *constants, zval *name, zval* value)
+int zend_optimizer_get_collected_constant(HashTable *constants, zval *name, zval* value)
{
zval *val;
- if (zend_hash_find(constants, Z_STRVAL_P(name), Z_STRLEN_P(name)+1, (void**)&val) == SUCCESS) {
- *value = *val;
- zval_copy_ctor(value);
+ if ((val = zend_hash_find(constants, Z_STR_P(name))) != NULL) {
+ ZVAL_DUP(value, val);
return 1;
}
return 0;
}
-#if ZEND_EXTENSION_API_NO >= PHP_5_5_X_API_NO
-static int zend_optimizer_lookup_cv(zend_op_array *op_array, char* name, int name_len)
+int zend_optimizer_lookup_cv(zend_op_array *op_array, zend_string* name)
{
int i = 0;
- ulong hash_value = zend_inline_hash_func(name, name_len+1);
+ zend_ulong hash_value = zend_string_hash_val(name);
while (i < op_array->last_var) {
- if (op_array->vars[i].name == name ||
- (op_array->vars[i].hash_value == hash_value &&
- op_array->vars[i].name_len == name_len &&
- memcmp(op_array->vars[i].name, name, name_len) == 0)) {
- return i;
+ if (op_array->vars[i] == name ||
+ (op_array->vars[i]->h == hash_value &&
+ op_array->vars[i]->len == name->len &&
+ memcmp(op_array->vars[i]->val, name->val, name->len) == 0)) {
+ return (int)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, i);
}
i++;
}
i = op_array->last_var;
op_array->last_var++;
- op_array->vars = erealloc(op_array->vars, op_array->last_var * sizeof(zend_compiled_variable));
- if (IS_INTERNED(name)) {
- op_array->vars[i].name = name;
- } else {
- op_array->vars[i].name = estrndup(name, name_len);
+ op_array->vars = erealloc(op_array->vars, op_array->last_var * sizeof(zend_string*));
+ op_array->vars[i] = zend_string_dup(name, 0);
+
+ /* all IS_TMP_VAR and IS_VAR variable numbers have to be adjusted */
+ {
+ zend_op *opline = op_array->opcodes;
+ zend_op *end = opline + op_array->last;
+ while (opline < end) {
+ if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) {
+ opline->op1.var += sizeof(zval);
+ }
+ if (opline->op2_type & (IS_TMP_VAR|IS_VAR)) {
+ opline->op2.var += sizeof(zval);
+ }
+ if (opline->result_type & (IS_TMP_VAR|IS_VAR)) {
+ opline->result.var += sizeof(zval);
+ }
+ if (opline->opcode == ZEND_DECLARE_INHERITED_CLASS ||
+ opline->opcode == ZEND_DECLARE_INHERITED_CLASS_DELAYED) {
+ opline->extended_value += sizeof(zval);
+ }
+ opline++;
+ }
}
- op_array->vars[i].name_len = name_len;
- op_array->vars[i].hash_value = hash_value;
- return i;
+
+ return (int)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, i);
}
-#endif
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
-int zend_optimizer_add_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC)
+int zend_optimizer_add_literal(zend_op_array *op_array, zval *zv)
{
int i = op_array->last_literal;
op_array->last_literal++;
- op_array->literals = (zend_literal*)erealloc(op_array->literals, op_array->last_literal * sizeof(zend_literal));
- op_array->literals[i].constant = *zv;
- op_array->literals[i].hash_value = 0;
- op_array->literals[i].cache_slot = -1;
- Z_SET_REFCOUNT(op_array->literals[i].constant, 2);
- Z_SET_ISREF(op_array->literals[i].constant);
+ op_array->literals = (zval*)erealloc(op_array->literals, op_array->last_literal * sizeof(zval));
+ ZVAL_COPY_VALUE(&op_array->literals[i], zv);
+ Z_CACHE_SLOT(op_array->literals[i]) = -1;
+//??? Z_SET_REFCOUNT(op_array->literals[i].constant, 2);
+//??? Z_SET_ISREF(op_array->literals[i].constant);
return i;
}
-# define LITERAL_LONG(op, val) do { \
- zval _c; \
- ZVAL_LONG(&_c, val); \
- op.constant = zend_optimizer_add_literal(op_array, &_c TSRMLS_CC); \
- } while (0)
-
-# define LITERAL_BOOL(op, val) do { \
- zval _c; \
- ZVAL_BOOL(&_c, val); \
- op.constant = zend_optimizer_add_literal(op_array, &_c TSRMLS_CC); \
- } while (0)
-
-# define literal_dtor(zv) do { \
- zval_dtor(zv); \
- Z_TYPE_P(zv) = IS_NULL; \
- } while (0)
-
-#define COPY_NODE(target, src) do { \
- target ## _type = src ## _type; \
- target = src; \
- } while (0)
-
-#else
-
-# define LITERAL_LONG(op, val) ZVAL_LONG(&op.u.constant, val)
-
-# define LITERAL_BOOL(op, val) ZVAL_BOOL(&op.u.constant, val)
-
-# define literal_dtor(zv) zval_dtor(zv)
-
-#define COPY_NODE(target, src) do { \
- target = src; \
- } while (0)
-
-#endif
-
-static void update_op1_const(zend_op_array *op_array,
- zend_op *opline,
- zval *val TSRMLS_DC)
+void zend_optimizer_update_op1_const(zend_op_array *op_array,
+ zend_op *opline,
+ zval *val)
{
if (opline->opcode == ZEND_FREE) {
MAKE_NOP(opline);
zval_dtor(val);
} else {
ZEND_OP1_TYPE(opline) = IS_CONST;
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
if (Z_TYPE_P(val) == IS_STRING) {
switch (opline->opcode) {
case ZEND_INIT_STATIC_METHOD_CALL:
case ZEND_CATCH:
case ZEND_FETCH_CONSTANT:
- opline->op1.constant = zend_optimizer_add_literal(op_array, val TSRMLS_CC);
- Z_HASH_P(&ZEND_OP1_LITERAL(opline)) = zend_hash_func(Z_STRVAL(ZEND_OP1_LITERAL(opline)), Z_STRLEN(ZEND_OP1_LITERAL(opline)) + 1);
- op_array->literals[opline->op1.constant].cache_slot = op_array->last_cache_slot++;
- zend_str_tolower(Z_STRVAL_P(val), Z_STRLEN_P(val));
- zend_optimizer_add_literal(op_array, val TSRMLS_CC);
- op_array->literals[opline->op1.constant+1].hash_value = zend_hash_func(Z_STRVAL(op_array->literals[opline->op1.constant+1].constant), Z_STRLEN(op_array->literals[opline->op1.constant+1].constant) + 1);
- break;
- case ZEND_DO_FCALL:
+ case ZEND_DEFINED:
+ case ZEND_NEW:
+ opline->op1.constant = zend_optimizer_add_literal(op_array, val);
+ zend_string_hash_val(Z_STR(ZEND_OP1_LITERAL(opline)));
+ Z_CACHE_SLOT(op_array->literals[opline->op1.constant]) = op_array->last_cache_slot++;
zend_str_tolower(Z_STRVAL_P(val), Z_STRLEN_P(val));
- opline->op1.constant = zend_optimizer_add_literal(op_array, val TSRMLS_CC);
- Z_HASH_P(&ZEND_OP1_LITERAL(opline)) = zend_hash_func(Z_STRVAL(ZEND_OP1_LITERAL(opline)), Z_STRLEN(ZEND_OP1_LITERAL(opline)) + 1);
- op_array->literals[opline->op1.constant].cache_slot = op_array->last_cache_slot++;
+ zend_optimizer_add_literal(op_array, val);
+ zend_string_hash_val(Z_STR(op_array->literals[opline->op1.constant+1]));
break;
default:
- opline->op1.constant = zend_optimizer_add_literal(op_array, val TSRMLS_CC);
- Z_HASH_P(&ZEND_OP1_LITERAL(opline)) = zend_hash_func(Z_STRVAL(ZEND_OP1_LITERAL(opline)), Z_STRLEN(ZEND_OP1_LITERAL(opline)) + 1);
+ opline->op1.constant = zend_optimizer_add_literal(op_array, val);
+ zend_string_hash_val(Z_STR(ZEND_OP1_LITERAL(opline)));
break;
}
} else {
- opline->op1.constant = zend_optimizer_add_literal(op_array, val TSRMLS_CC);
+ opline->op1.constant = zend_optimizer_add_literal(op_array, val);
}
-#else
- ZEND_OP1_LITERAL(opline) = *val;
-#endif
}
}
-static void update_op2_const(zend_op_array *op_array,
- zend_op *opline,
- zval *val TSRMLS_DC)
+void zend_optimizer_update_op2_const(zend_op_array *op_array,
+ zend_op *opline,
+ zval *val)
{
ZEND_OP2_TYPE(opline) = IS_CONST;
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
- opline->op2.constant = zend_optimizer_add_literal(op_array, val TSRMLS_CC);
+ if (opline->opcode == ZEND_INIT_FCALL) {
+ zend_str_tolower(Z_STRVAL_P(val), Z_STRLEN_P(val));
+ opline->op2.constant = zend_optimizer_add_literal(op_array, val);
+ zend_string_hash_val(Z_STR(ZEND_OP2_LITERAL(opline)));
+ Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) = op_array->last_cache_slot++;
+ return;
+ }
+ opline->op2.constant = zend_optimizer_add_literal(op_array, val);
if (Z_TYPE_P(val) == IS_STRING) {
- Z_HASH_P(&ZEND_OP2_LITERAL(opline)) = zend_hash_func(Z_STRVAL(ZEND_OP2_LITERAL(opline)), Z_STRLEN(ZEND_OP2_LITERAL(opline)) + 1);
+ zend_string_hash_val(Z_STR(ZEND_OP2_LITERAL(opline)));
switch (opline->opcode) {
case ZEND_FETCH_R:
case ZEND_FETCH_W:
@@ -204,17 +174,18 @@ static void update_op2_const(zend_op_array *op_array,
case ZEND_ISSET_ISEMPTY_VAR:
case ZEND_ADD_INTERFACE:
case ZEND_ADD_TRAIT:
- op_array->literals[opline->op2.constant].cache_slot = op_array->last_cache_slot++;
+ case ZEND_INSTANCEOF:
+ Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) = op_array->last_cache_slot++;
zend_str_tolower(Z_STRVAL_P(val), Z_STRLEN_P(val));
- zend_optimizer_add_literal(op_array, val TSRMLS_CC);
- op_array->literals[opline->op2.constant+1].hash_value = zend_hash_func(Z_STRVAL(op_array->literals[opline->op2.constant+1].constant), Z_STRLEN(op_array->literals[opline->op2.constant+1].constant) + 1);
+ zend_optimizer_add_literal(op_array, val);
+ zend_string_hash_val(Z_STR(op_array->literals[opline->op2.constant+1]));
break;
case ZEND_INIT_METHOD_CALL:
case ZEND_INIT_STATIC_METHOD_CALL:
zend_str_tolower(Z_STRVAL_P(val), Z_STRLEN_P(val));
- zend_optimizer_add_literal(op_array, val TSRMLS_CC);
- op_array->literals[opline->op2.constant+1].hash_value = zend_hash_func(Z_STRVAL(op_array->literals[opline->op2.constant+1].constant), Z_STRLEN(op_array->literals[opline->op2.constant+1].constant) + 1);
- /* break missing intentionally */
+ zend_optimizer_add_literal(op_array, val);
+ zend_string_hash_val(Z_STR(op_array->literals[opline->op2.constant+1]));
+ /* break missing intentionally */
/*case ZEND_FETCH_CONSTANT:*/
case ZEND_ASSIGN_OBJ:
case ZEND_FETCH_OBJ_R:
@@ -229,7 +200,7 @@ static void update_op2_const(zend_op_array *op_array,
case ZEND_POST_INC_OBJ:
case ZEND_POST_DEC_OBJ:
case ZEND_ISSET_ISEMPTY_PROP_OBJ:
- op_array->literals[opline->op2.constant].cache_slot = op_array->last_cache_slot;
+ Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) = op_array->last_cache_slot;
op_array->last_cache_slot += 2;
break;
case ZEND_ASSIGN_ADD:
@@ -244,11 +215,10 @@ static void update_op2_const(zend_op_array *op_array,
case ZEND_ASSIGN_BW_AND:
case ZEND_ASSIGN_BW_XOR:
if (opline->extended_value == ZEND_ASSIGN_OBJ) {
- op_array->literals[opline->op2.constant].cache_slot = op_array->last_cache_slot;
+ Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) = op_array->last_cache_slot;
op_array->last_cache_slot += 2;
}
break;
-#if ZEND_EXTENSION_API_NO >= PHP_5_4_X_API_NO
case ZEND_OP_DATA:
if ((opline-1)->opcode == ZEND_ASSIGN_DIM ||
((opline-1)->extended_value == ZEND_ASSIGN_DIM &&
@@ -276,39 +246,34 @@ static void update_op2_const(zend_op_array *op_array,
case ZEND_FETCH_DIM_IS:
case ZEND_FETCH_DIM_FUNC_ARG:
case ZEND_FETCH_DIM_UNSET:
- case ZEND_FETCH_DIM_TMP_VAR:
+ case ZEND_FETCH_LIST:
check_numeric:
{
- ulong index;
- int numeric = 0;
+ zend_ulong index;
- ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(val), Z_STRLEN_P(val)+1, index, numeric = 1);
- if (numeric) {
+ if (ZEND_HANDLE_NUMERIC(Z_STR_P(val), index)) {
zval_dtor(val);
ZVAL_LONG(val, index);
- op_array->literals[opline->op2.constant].constant = *val;
+ op_array->literals[opline->op2.constant] = *val;
}
}
break;
-#endif
default:
break;
}
}
-#else
- ZEND_OP2_LITERAL(opline) = *val;
-#endif
}
-static int replace_var_by_const(zend_op_array *op_array,
- zend_op *opline,
- zend_uint var,
- zval *val TSRMLS_DC)
+int zend_optimizer_replace_by_const(zend_op_array *op_array,
+ zend_op *opline,
+ zend_uchar type,
+ uint32_t var,
+ zval *val)
{
zend_op *end = op_array->opcodes + op_array->last;
while (opline < end) {
- if (ZEND_OP1_TYPE(opline) == IS_VAR &&
+ if (ZEND_OP1_TYPE(opline) == type &&
ZEND_OP1(opline).var == var) {
switch (opline->opcode) {
case ZEND_FETCH_DIM_W:
@@ -316,29 +281,55 @@ static int replace_var_by_const(zend_op_array *op_array,
case ZEND_FETCH_DIM_FUNC_ARG:
case ZEND_FETCH_DIM_UNSET:
case ZEND_ASSIGN_DIM:
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
case ZEND_SEPARATE:
-#endif
return 0;
+ case ZEND_SEND_VAR:
+ opline->extended_value = 0;
+ opline->opcode = ZEND_SEND_VAL;
+ break;
+ case ZEND_SEND_VAR_EX:
+ opline->extended_value = 0;
+ opline->opcode = ZEND_SEND_VAL_EX;
+ break;
case ZEND_SEND_VAR_NO_REF:
if (opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) {
if (opline->extended_value & ZEND_ARG_SEND_BY_REF) {
return 0;
}
- opline->extended_value = ZEND_DO_FCALL;
+ opline->extended_value = 0;
+ opline->opcode = ZEND_SEND_VAL_EX;
} else {
- opline->extended_value = ZEND_DO_FCALL_BY_NAME;
+ opline->extended_value = 0;
+ opline->opcode = ZEND_SEND_VAL;
}
- opline->opcode = ZEND_SEND_VAL;
break;
+ /* In most cases IS_TMP_VAR operand may be used only once.
+ * The operands are usually destroyed by the opcode handler.
+ * ZEND_CASE is an exception, that keeps operand unchanged,
+ * and allows its reuse. The number of ZEND_CASE instructions
+ * usually terminated by ZEND_FREE that finally kills the value.
+ */
+ case ZEND_CASE: {
+ zval old_val;
+ ZVAL_COPY_VALUE(&old_val, val);
+ zval_copy_ctor(val);
+ zend_optimizer_update_op1_const(op_array, opline, val);
+ ZVAL_COPY_VALUE(val, &old_val);
+ opline++;
+ continue;
+ }
+ case ZEND_FREE:
+ MAKE_NOP(opline);
+ zval_dtor(val);
+ return 1;
default:
break;
- }
- update_op1_const(op_array, opline, val TSRMLS_CC);
+ }
+ zend_optimizer_update_op1_const(op_array, opline, val);
break;
}
-
- if (ZEND_OP2_TYPE(opline) == IS_VAR &&
+
+ if (ZEND_OP2_TYPE(opline) == type &&
ZEND_OP2(opline).var == var) {
switch (opline->opcode) {
case ZEND_ASSIGN_REF:
@@ -346,7 +337,7 @@ static int replace_var_by_const(zend_op_array *op_array,
default:
break;
}
- update_op2_const(op_array, opline, val TSRMLS_CC);
+ zend_optimizer_update_op2_const(op_array, opline, val);
break;
}
opline++;
@@ -355,67 +346,10 @@ static int replace_var_by_const(zend_op_array *op_array,
return 1;
}
-static void replace_tmp_by_const(zend_op_array *op_array,
- zend_op *opline,
- zend_uint var,
- zval *val
- TSRMLS_DC)
+static void zend_optimize(zend_op_array *op_array,
+ zend_optimizer_ctx *ctx)
{
- zend_op *end = op_array->opcodes + op_array->last;
-
- while (opline < end) {
- if (ZEND_OP1_TYPE(opline) == IS_TMP_VAR &&
- ZEND_OP1(opline).var == var) {
-
- /* In most cases IS_TMP_VAR operand may be used only once.
- * The operands are usually destroyed by the opcode handler.
- * ZEND_CASE is an exception, that keeps operand unchanged,
- * and allows its reuse. The number of ZEND_CASE instructions
- * usually terminated by ZEND_FREE that finally kills the value.
- */
- if (opline->opcode == ZEND_CASE) {
- zval old_val;
- old_val = *val;
- zval_copy_ctor(val);
- update_op1_const(op_array, opline, val TSRMLS_CC);
- *val = old_val;
- } else if (opline->opcode == ZEND_FREE) {
- MAKE_NOP(opline);
- break;
- } else {
- update_op1_const(op_array, opline, val TSRMLS_CC);
- val = NULL;
- break;
- }
- }
-
- if (ZEND_OP2_TYPE(opline) == IS_TMP_VAR &&
- ZEND_OP2(opline).var == var) {
-
- update_op2_const(op_array, opline, val TSRMLS_CC);
- /* TMP_VAR may be used only once */
- val = NULL;
- break;
- }
- opline++;
- }
- if (val) {
- zval_dtor(val);
- }
-}
-
-#include "Optimizer/nop_removal.c"
-#include "Optimizer/block_pass.c"
-#include "Optimizer/optimize_temp_vars_5.c"
-#include "Optimizer/compact_literals.c"
-#include "Optimizer/optimize_func_calls.c"
-
-static void zend_optimize(zend_op_array *op_array,
- zend_persistent_script *script,
- HashTable **constants TSRMLS_DC)
-{
- if (op_array->type == ZEND_EVAL_CODE ||
- (op_array->fn_flags & ZEND_ACC_INTERACTIVE)) {
+ if (op_array->type == ZEND_EVAL_CODE) {
return;
}
@@ -425,7 +359,9 @@ static void zend_optimize(zend_op_array *op_array,
* - optimize series of ADD_STRING and/or ADD_CHAR
* - convert CAST(IS_BOOL,x) into BOOL(x)
*/
-#include "Optimizer/pass1_5.c"
+ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
+ zend_optimizer_pass1(op_array, ctx);
+ }
/* pass 2:
* - convert non-numeric constants to numeric constants in numeric operators
@@ -433,52 +369,57 @@ static void zend_optimize(zend_op_array *op_array,
* - optimize static BRKs and CONTs
* - pre-evaluate constant function calls
*/
-#include "Optimizer/pass2.c"
+ if (ZEND_OPTIMIZER_PASS_2 & OPTIMIZATION_LEVEL) {
+ zend_optimizer_pass2(op_array);
+ }
/* pass 3:
* - optimize $i = $i+expr to $i+=expr
* - optimize series of JMPs
* - change $i++ to ++$i where possible
*/
-#include "Optimizer/pass3.c"
+ if (ZEND_OPTIMIZER_PASS_3 & OPTIMIZATION_LEVEL) {
+ zend_optimizer_pass3(op_array);
+ }
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
/* pass 4:
* - INIT_FCALL_BY_NAME -> DO_FCALL
*/
if (ZEND_OPTIMIZER_PASS_4 & OPTIMIZATION_LEVEL) {
- optimize_func_calls(op_array, script TSRMLS_CC);
+ optimize_func_calls(op_array, ctx);
}
-#endif
/* pass 5:
* - CFG optimization
*/
-#include "Optimizer/pass5.c"
+ if (ZEND_OPTIMIZER_PASS_5 & OPTIMIZATION_LEVEL) {
+ optimize_cfg(op_array, ctx);
+ }
/* pass 9:
* - Optimize temp variables usage
*/
-#include "Optimizer/pass9.c"
+ if (ZEND_OPTIMIZER_PASS_9 & OPTIMIZATION_LEVEL) {
+ optimize_temporary_variables(op_array, ctx);
+ }
/* pass 10:
* - remove NOPs
*/
-#include "Optimizer/pass10.c"
+ if (((ZEND_OPTIMIZER_PASS_10|ZEND_OPTIMIZER_PASS_5) & OPTIMIZATION_LEVEL) == ZEND_OPTIMIZER_PASS_10) {
+ zend_optimizer_nop_removal(op_array);
+ }
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
/* pass 11:
- * - Compact literals table
+ * - Compact literals table
*/
if (ZEND_OPTIMIZER_PASS_11 & OPTIMIZATION_LEVEL) {
- optimizer_compact_literals(op_array TSRMLS_CC);
+ zend_optimizer_compact_literals(op_array, ctx);
}
-#endif
}
-static void zend_accel_optimize(zend_op_array *op_array,
- zend_persistent_script *script,
- HashTable **constants TSRMLS_DC)
+static void zend_accel_optimize(zend_op_array *op_array,
+ zend_optimizer_ctx *ctx)
{
zend_op *opline, *end;
@@ -486,76 +427,70 @@ static void zend_accel_optimize(zend_op_array *op_array,
opline = op_array->opcodes;
end = opline + op_array->last;
while (opline < end) {
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
if (opline->op1_type == IS_CONST) {
- opline->op1.constant = opline->op1.literal - op_array->literals;
+ ZEND_PASS_TWO_UNDO_CONSTANT(op_array, opline->op1);
}
if (opline->op2_type == IS_CONST) {
- opline->op2.constant = opline->op2.literal - op_array->literals;
+ ZEND_PASS_TWO_UNDO_CONSTANT(op_array, opline->op2);
}
-#endif
switch (opline->opcode) {
case ZEND_JMP:
-#if ZEND_EXTENSION_API_NO > PHP_5_2_X_API_NO
case ZEND_GOTO:
-#endif
-#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
case ZEND_FAST_CALL:
-#endif
- ZEND_OP1(opline).opline_num = ZEND_OP1(opline).jmp_addr - op_array->opcodes;
+ ZEND_PASS_TWO_UNDO_JMP_TARGET(op_array, opline, ZEND_OP1(opline));
break;
+ case ZEND_JMPZNZ:
+ /* relative offset into absolute index */
+ opline->extended_value = ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value);
+ /* break omitted intentionally */
case ZEND_JMPZ:
case ZEND_JMPNZ:
case ZEND_JMPZ_EX:
case ZEND_JMPNZ_EX:
-#if ZEND_EXTENSION_API_NO > PHP_5_2_X_API_NO
case ZEND_JMP_SET:
-#endif
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
- case ZEND_JMP_SET_VAR:
-#endif
- ZEND_OP2(opline).opline_num = ZEND_OP2(opline).jmp_addr - op_array->opcodes;
+ case ZEND_COALESCE:
+ case ZEND_NEW:
+ case ZEND_FE_RESET:
+ case ZEND_FE_FETCH:
+ ZEND_PASS_TWO_UNDO_JMP_TARGET(op_array, opline, ZEND_OP2(opline));
break;
}
opline++;
}
/* Do actual optimizations */
- zend_optimize(op_array, script, constants TSRMLS_CC);
-
+ zend_optimize(op_array, ctx);
+
/* Redo pass_two() */
opline = op_array->opcodes;
end = opline + op_array->last;
while (opline < end) {
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
if (opline->op1_type == IS_CONST) {
- opline->op1.zv = &op_array->literals[opline->op1.constant].constant;
+ ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline->op1);
}
if (opline->op2_type == IS_CONST) {
- opline->op2.zv = &op_array->literals[opline->op2.constant].constant;
+ ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline->op2);
}
-#endif
switch (opline->opcode) {
case ZEND_JMP:
-#if ZEND_EXTENSION_API_NO > PHP_5_2_X_API_NO
case ZEND_GOTO:
-#endif
-#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
case ZEND_FAST_CALL:
-#endif
- ZEND_OP1(opline).jmp_addr = &op_array->opcodes[ZEND_OP1(opline).opline_num];
+ ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, ZEND_OP1(opline));
break;
+ case ZEND_JMPZNZ:
+ /* absolute index to relative offset */
+ opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, opline->extended_value);
+ /* break omitted intentionally */
case ZEND_JMPZ:
case ZEND_JMPNZ:
case ZEND_JMPZ_EX:
case ZEND_JMPNZ_EX:
-#if ZEND_EXTENSION_API_NO > PHP_5_2_X_API_NO
case ZEND_JMP_SET:
-#endif
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
- case ZEND_JMP_SET_VAR:
-#endif
- ZEND_OP2(opline).jmp_addr = &op_array->opcodes[ZEND_OP2(opline).opline_num];
+ case ZEND_COALESCE:
+ case ZEND_NEW:
+ case ZEND_FE_RESET:
+ case ZEND_FE_FETCH:
+ ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, ZEND_OP2(opline));
break;
}
ZEND_VM_SET_OPCODE_HANDLER(opline);
@@ -563,45 +498,104 @@ static void zend_accel_optimize(zend_op_array *op_array,
}
}
-int zend_accel_script_optimize(zend_persistent_script *script TSRMLS_DC)
+static void zend_accel_adjust_fcall_stack_size(zend_op_array *op_array, zend_optimizer_ctx *ctx)
+{
+ zend_function *func;
+ zend_op *opline, *end;
+
+ opline = op_array->opcodes;
+ end = opline + op_array->last;
+ while (opline < end) {
+ if (opline->opcode == ZEND_INIT_FCALL) {
+ func = zend_hash_find_ptr(
+ &ctx->script->function_table,
+ Z_STR_P(RT_CONSTANT(op_array, opline->op2)));
+ if (func) {
+ opline->op1.num = zend_vm_calc_used_stack(opline->extended_value, func);
+ }
+ }
+ opline++;
+ }
+}
+
+int zend_accel_script_optimize(zend_persistent_script *script)
{
+ uint idx, j;
Bucket *p, *q;
- HashTable *constants = NULL;
+ zend_class_entry *ce;
+ zend_op_array *op_array;
+ zend_optimizer_ctx ctx;
- zend_accel_optimize(&script->main_op_array, script, &constants TSRMLS_CC);
+ ctx.arena = zend_arena_create(64 * 1024);
+ ctx.script = script;
+ ctx.constants = NULL;
- p = script->function_table.pListHead;
- while (p) {
- zend_op_array *op_array = (zend_op_array*)p->pData;
- zend_accel_optimize(op_array, script, &constants TSRMLS_CC);
- p = p->pListNext;
+ zend_accel_optimize(&script->main_op_array, &ctx);
+
+ for (idx = 0; idx < script->function_table.nNumUsed; idx++) {
+ p = script->function_table.arData + idx;
+ if (Z_TYPE(p->val) == IS_UNDEF) continue;
+ op_array = (zend_op_array*)Z_PTR(p->val);
+ zend_accel_optimize(op_array, &ctx);
}
- p = script->class_table.pListHead;
- while (p) {
- zend_class_entry *ce = (zend_class_entry*)p->pDataPtr;
- q = ce->function_table.pListHead;
- while (q) {
- zend_op_array *op_array = (zend_op_array*)q->pData;
+ for (idx = 0; idx < script->class_table.nNumUsed; idx++) {
+ p = script->class_table.arData + idx;
+ if (Z_TYPE(p->val) == IS_UNDEF) continue;
+ ce = (zend_class_entry*)Z_PTR(p->val);
+ for (j = 0; j < ce->function_table.nNumUsed; j++) {
+ q = ce->function_table.arData + j;
+ if (Z_TYPE(q->val) == IS_UNDEF) continue;
+ op_array = (zend_op_array*)Z_PTR(q->val);
if (op_array->scope == ce) {
- zend_accel_optimize(op_array, script, &constants TSRMLS_CC);
+ zend_accel_optimize(op_array, &ctx);
} else if (op_array->type == ZEND_USER_FUNCTION) {
zend_op_array *orig_op_array;
- if (zend_hash_find(&op_array->scope->function_table, q->arKey, q->nKeyLength, (void**)&orig_op_array) == SUCCESS) {
+ if ((orig_op_array = zend_hash_find_ptr(&op_array->scope->function_table, q->key)) != NULL) {
HashTable *ht = op_array->static_variables;
*op_array = *orig_op_array;
op_array->static_variables = ht;
}
}
- q = q->pListNext;
}
- p = p->pListNext;
}
- if (constants) {
- zend_hash_destroy(constants);
- efree(constants);
+ if (ZEND_OPTIMIZER_PASS_12 & OPTIMIZATION_LEVEL) {
+ zend_accel_adjust_fcall_stack_size(&script->main_op_array, &ctx);
+
+ for (idx = 0; idx < script->function_table.nNumUsed; idx++) {
+ p = script->function_table.arData + idx;
+ if (Z_TYPE(p->val) == IS_UNDEF) continue;
+ op_array = (zend_op_array*)Z_PTR(p->val);
+ zend_accel_adjust_fcall_stack_size(op_array, &ctx);
+ }
+
+ for (idx = 0; idx < script->class_table.nNumUsed; idx++) {
+ p = script->class_table.arData + idx;
+ if (Z_TYPE(p->val) == IS_UNDEF) continue;
+ ce = (zend_class_entry*)Z_PTR(p->val);
+ for (j = 0; j < ce->function_table.nNumUsed; j++) {
+ q = ce->function_table.arData + j;
+ if (Z_TYPE(q->val) == IS_UNDEF) continue;
+ op_array = (zend_op_array*)Z_PTR(q->val);
+ if (op_array->scope == ce) {
+ zend_accel_adjust_fcall_stack_size(op_array, &ctx);
+ } else if (op_array->type == ZEND_USER_FUNCTION) {
+ zend_op_array *orig_op_array;
+ if ((orig_op_array = zend_hash_find_ptr(&op_array->scope->function_table, q->key)) != NULL) {
+ HashTable *ht = op_array->static_variables;
+ *op_array = *orig_op_array;
+ op_array->static_variables = ht;
+ }
+ }
+ }
+ }
+ }
+
+ if (ctx.constants) {
+ zend_hash_destroy(ctx.constants);
}
+ zend_arena_destroy(ctx.arena);
return 1;
}
diff --git a/ext/opcache/Optimizer/zend_optimizer.h b/ext/opcache/Optimizer/zend_optimizer.h
index fc6ec4357d..9db81bcb9b 100644
--- a/ext/opcache/Optimizer/zend_optimizer.h
+++ b/ext/opcache/Optimizer/zend_optimizer.h
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| Zend OPcache |
+----------------------------------------------------------------------+
- | Copyright (c) 1998-2015 The PHP Group |
+ | Copyright (c) 1998-2014 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -32,11 +32,11 @@
#define ZEND_OPTIMIZER_PASS_5 (1<<4) /* CFG based optimization */
#define ZEND_OPTIMIZER_PASS_6 (1<<5)
#define ZEND_OPTIMIZER_PASS_7 (1<<6)
-#define ZEND_OPTIMIZER_PASS_8 (1<<7)
+#define ZEND_OPTIMIZER_PASS_8 (1<<7)
#define ZEND_OPTIMIZER_PASS_9 (1<<8) /* TMP VAR usage */
#define ZEND_OPTIMIZER_PASS_10 (1<<9) /* NOP removal */
#define ZEND_OPTIMIZER_PASS_11 (1<<10) /* Merge equal constants */
-#define ZEND_OPTIMIZER_PASS_12 (1<<11)
+#define ZEND_OPTIMIZER_PASS_12 (1<<11) /* Adjust used stack */
#define ZEND_OPTIMIZER_PASS_13 (1<<12)
#define ZEND_OPTIMIZER_PASS_14 (1<<13)
diff --git a/ext/opcache/Optimizer/zend_optimizer_internal.h b/ext/opcache/Optimizer/zend_optimizer_internal.h
index 126ab4a8ba..5e86ab84e6 100644
--- a/ext/opcache/Optimizer/zend_optimizer_internal.h
+++ b/ext/opcache/Optimizer/zend_optimizer_internal.h
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| Zend OPcache |
+----------------------------------------------------------------------+
- | Copyright (c) 1998-2015 The PHP Group |
+ | Copyright (c) 1998-2014 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -24,33 +24,24 @@
#include "ZendAccelerator.h"
-#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
-# define VAR_NUM(v) ((zend_uint)(EX_TMP_VAR_NUM(0, 0) - EX_TMP_VAR(0, v)))
-# define NUM_VAR(v) ((zend_uint)(zend_uintptr_t)EX_TMP_VAR_NUM(0, v))
-#elif ZEND_EXTENSION_API_NO > PHP_5_2_X_API_NO
-# define VAR_NUM(v) ((v)/ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable)))
-# define NUM_VAR(v) ((v)*ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable)))
-#else
-# define VAR_NUM(v) ((v)/(sizeof(temp_variable)))
-# define NUM_VAR(v) ((v)*(sizeof(temp_variable)))
-#endif
+#define VAR_NUM(v) EX_VAR_TO_NUM(v)
+#define NUM_VAR(v) ((uint32_t)(zend_uintptr_t)ZEND_CALL_VAR_NUM(0, v))
#define INV_COND(op) ((op) == ZEND_JMPZ ? ZEND_JMPNZ : ZEND_JMPZ)
#define INV_EX_COND(op) ((op) == ZEND_JMPZ_EX ? ZEND_JMPNZ : ZEND_JMPZ)
#define INV_COND_EX(op) ((op) == ZEND_JMPZ ? ZEND_JMPNZ_EX : ZEND_JMPZ_EX)
#define INV_EX_COND_EX(op) ((op) == ZEND_JMPZ_EX ? ZEND_JMPNZ_EX : ZEND_JMPZ_EX)
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
-# define MAKE_NOP(opline) { opline->opcode = ZEND_NOP; memset(&opline->result,0,sizeof(opline->result)); memset(&opline->op1,0,sizeof(opline->op1)); memset(&opline->op2,0,sizeof(opline->op2)); opline->result_type=opline->op1_type=opline->op2_type=IS_UNUSED; opline->handler = zend_opcode_handlers[ZEND_NOP]; }
-# define RESULT_USED(op) (((op->result_type & IS_VAR) && !(op->result_type & EXT_TYPE_UNUSED)) || op->result_type == IS_TMP_VAR)
-# define RESULT_UNUSED(op) ((op->result_type & EXT_TYPE_UNUSED) != 0)
-# define SAME_VAR(op1, op2) ((((op1 ## _type & IS_VAR) && (op2 ## _type & IS_VAR)) || (op1 ## _type == IS_TMP_VAR && op2 ## _type == IS_TMP_VAR)) && op1.var == op2.var)
-#else
-# define MAKE_NOP(opline) { opline->opcode = ZEND_NOP; memset(&opline->result,0,sizeof(znode)); memset(&opline->op1,0,sizeof(znode)); memset(&opline->op2,0,sizeof(znode)); opline->result.op_type=opline->op1.op_type=opline->op2.op_type=IS_UNUSED; opline->handler = zend_opcode_handlers[ZEND_NOP]; }
-# define RESULT_USED(op) ((op->result.op_type == IS_VAR && (op->result.u.EA.type & EXT_TYPE_UNUSED) == 0) || (op->result.op_type == IS_TMP_VAR))
-# define RESULT_UNUSED(op) ((op->result.op_type == IS_VAR) && (op->result.u.EA.type == EXT_TYPE_UNUSED))
-# define SAME_VAR(op1, op2) (((op1.op_type == IS_VAR && op2.op_type == IS_VAR) || (op1.op_type == IS_TMP_VAR && op2.op_type == IS_TMP_VAR)) && op1.u.var == op2.u.var)
-#endif
+#define MAKE_NOP(opline) { (opline)->opcode = ZEND_NOP; memset(&(opline)->result, 0, sizeof((opline)->result)); memset(&(opline)->op1, 0, sizeof((opline)->op1)); memset(&(opline)->op2, 0, sizeof((opline)->op2));(opline)->result_type=(opline)->op1_type=(opline)->op2_type=IS_UNUSED; (opline)->handler = zend_opcode_handlers[ZEND_NOP]; }
+#define RESULT_USED(op) (((op->result_type & IS_VAR) && !(op->result_type & EXT_TYPE_UNUSED)) || op->result_type == IS_TMP_VAR)
+#define RESULT_UNUSED(op) ((op->result_type & EXT_TYPE_UNUSED) != 0)
+#define SAME_VAR(op1, op2) ((((op1 ## _type & IS_VAR) && (op2 ## _type & IS_VAR)) || (op1 ## _type == IS_TMP_VAR && op2 ## _type == IS_TMP_VAR)) && op1.var == op2.var)
+
+typedef struct _zend_optimizer_ctx {
+ zend_arena *arena;
+ zend_persistent_script *script;
+ HashTable *constants;
+} zend_optimizer_ctx;
typedef struct _zend_code_block zend_code_block;
typedef struct _zend_block_source zend_block_source;
@@ -76,6 +67,8 @@ typedef struct _zend_cfg {
zend_code_block **loop_start;
zend_code_block **loop_cont;
zend_code_block **loop_brk;
+ zend_op **Tsource;
+ char *same_t;
} zend_cfg;
struct _zend_block_source {
@@ -83,4 +76,55 @@ struct _zend_block_source {
zend_block_source *next;
};
+#define OPTIMIZATION_LEVEL \
+ ZCG(accel_directives).optimization_level
+
+#define LITERAL_LONG(op, val) do { \
+ zval _c; \
+ ZVAL_LONG(&_c, val); \
+ op.constant = zend_optimizer_add_literal(op_array, &_c); \
+ } while (0)
+
+#define LITERAL_BOOL(op, val) do { \
+ zval _c; \
+ ZVAL_BOOL(&_c, val); \
+ op.constant = zend_optimizer_add_literal(op_array, &_c); \
+ } while (0)
+
+#define literal_dtor(zv) do { \
+ zval_dtor(zv); \
+ ZVAL_NULL(zv); \
+ } while (0)
+
+#define COPY_NODE(target, src) do { \
+ target ## _type = src ## _type; \
+ target = src; \
+ } while (0)
+
+int zend_optimizer_add_literal(zend_op_array *op_array, zval *zv);
+int zend_optimizer_get_persistent_constant(zend_string *name, zval *result, int copy);
+void zend_optimizer_collect_constant(zend_optimizer_ctx *ctx, zval *name, zval* value);
+int zend_optimizer_get_collected_constant(HashTable *constants, zval *name, zval* value);
+int zend_optimizer_lookup_cv(zend_op_array *op_array, zend_string* name);
+void zend_optimizer_update_op1_const(zend_op_array *op_array,
+ zend_op *opline,
+ zval *val);
+void zend_optimizer_update_op2_const(zend_op_array *op_array,
+ zend_op *opline,
+ zval *val);
+int zend_optimizer_replace_by_const(zend_op_array *op_array,
+ zend_op *opline,
+ zend_uchar type,
+ uint32_t var,
+ zval *val);
+
+void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx);
+void zend_optimizer_pass2(zend_op_array *op_array);
+void zend_optimizer_pass3(zend_op_array *op_array);
+void optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx);
+void optimize_cfg(zend_op_array *op_array, zend_optimizer_ctx *ctx);
+void optimize_temporary_variables(zend_op_array *op_array, zend_optimizer_ctx *ctx);
+void zend_optimizer_nop_removal(zend_op_array *op_array);
+void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx *ctx);
+
#endif
diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c
index 7a0bebe428..d671269f19 100644
--- a/ext/opcache/ZendAccelerator.c
+++ b/ext/opcache/ZendAccelerator.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| Zend OPcache |
+----------------------------------------------------------------------+
- | Copyright (c) 1998-2015 The PHP Group |
+ | Copyright (c) 1998-2014 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -36,11 +36,7 @@
#include "main/php_open_temporary_file.h"
#include "zend_API.h"
#include "zend_ini.h"
-#if ZEND_EXTENSION_API_NO > PHP_5_5_X_API_NO
-# include "zend_virtual_cwd.h"
-#else
-# include "TSRM/tsrm_virtual_cwd.h"
-#endif
+#include "zend_virtual_cwd.h"
#include "zend_accelerator_util_funcs.h"
#include "zend_accelerator_hash.h"
@@ -78,13 +74,13 @@ typedef int gid_t;
#define SHM_PROTECT() \
do { \
if (ZCG(accel_directives).protect_memory) { \
- zend_accel_shared_protect(1 TSRMLS_CC); \
+ zend_accel_shared_protect(1); \
} \
} while (0)
#define SHM_UNPROTECT() \
do { \
if (ZCG(accel_directives).protect_memory) { \
- zend_accel_shared_protect(0 TSRMLS_CC); \
+ zend_accel_shared_protect(0); \
} \
} while (0)
@@ -94,6 +90,9 @@ ZEND_EXTENSION();
zend_accel_globals accel_globals;
#else
int accel_globals_id;
+#if defined(COMPILE_DL_OPCACHE)
+ZEND_TSRMLS_CACHE_DEFINE;
+#endif
#endif
/* Points to the structure shared across all PHP processes */
@@ -104,21 +103,15 @@ zend_bool accel_startup_ok = 0;
static char *zps_failure_reason = NULL;
char *zps_api_failure_reason = NULL;
-static zend_op_array *(*accelerator_orig_compile_file)(zend_file_handle *file_handle, int type TSRMLS_DC);
-static int (*accelerator_orig_zend_stream_open_function)(const char *filename, zend_file_handle *handle TSRMLS_DC);
-#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
-static char *(*accelerator_orig_zend_resolve_path)(const char *filename, int filename_len TSRMLS_DC);
-#endif
+static zend_op_array *(*accelerator_orig_compile_file)(zend_file_handle *file_handle, int type);
+static int (*accelerator_orig_zend_stream_open_function)(const char *filename, zend_file_handle *handle );
+static char *(*accelerator_orig_zend_resolve_path)(const char *filename, int filename_len);
static void (*orig_chdir)(INTERNAL_FUNCTION_PARAMETERS) = NULL;
static ZEND_INI_MH((*orig_include_path_on_modify)) = NULL;
-#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
-static char *accel_php_resolve_path(const char *filename, int filename_length, const char *path TSRMLS_DC);
-#endif
-
#ifdef ZEND_WIN32
-# define INCREMENT(v) InterlockedIncrement(&ZCSG(v))
-# define DECREMENT(v) InterlockedDecrement(&ZCSG(v))
+# define INCREMENT(v) InterlockedIncrement64(&ZCSG(v))
+# define DECREMENT(v) InterlockedDecrement64(&ZCSG(v))
# define LOCKVAL(v) (ZCSG(v))
#endif
@@ -171,7 +164,7 @@ static ZEND_FUNCTION(accel_chdir)
}
}
-static inline char* accel_getcwd(int *cwd_len TSRMLS_DC)
+static inline char* accel_getcwd(int *cwd_len)
{
if (ZCG(cwd)) {
*cwd_len = ZCG(cwd_len);
@@ -188,10 +181,10 @@ static inline char* accel_getcwd(int *cwd_len TSRMLS_DC)
}
}
-void zend_accel_schedule_restart_if_necessary(zend_accel_restart_reason reason TSRMLS_DC)
+void zend_accel_schedule_restart_if_necessary(zend_accel_restart_reason reason)
{
if ((((double) ZSMMG(wasted_shared_memory)) / ZCG(accel_directives).memory_consumption) >= ZCG(accel_directives).max_wasted_percentage) {
- zend_accel_schedule_restart(reason TSRMLS_CC);
+ zend_accel_schedule_restart(reason);
}
}
@@ -202,24 +195,24 @@ void zend_accel_schedule_restart_if_necessary(zend_accel_restart_reason reason T
*/
static ZEND_INI_MH(accel_include_path_on_modify)
{
- int ret = orig_include_path_on_modify(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
+ int ret = orig_include_path_on_modify(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
ZCG(include_path_key) = NULL;
if (ret == SUCCESS) {
- ZCG(include_path) = new_value;
+ ZCG(include_path) = new_value->val;
if (ZCG(include_path) && *ZCG(include_path)) {
- ZCG(include_path_len) = new_value_length;
+ ZCG(include_path_len) = new_value->len;
if (ZCG(enabled) && accel_startup_ok &&
(ZCG(counted) || ZCSG(accelerator_enabled))) {
- ZCG(include_path_key) = zend_accel_hash_find(&ZCSG(include_paths), ZCG(include_path), ZCG(include_path_len) + 1);
+ ZCG(include_path_key) = zend_accel_hash_find(&ZCSG(include_paths), ZCG(include_path), ZCG(include_path_len));
if (!ZCG(include_path_key) &&
!zend_accel_hash_is_full(&ZCSG(include_paths))) {
SHM_UNPROTECT();
- zend_shared_alloc_lock(TSRMLS_C);
+ zend_shared_alloc_lock();
- ZCG(include_path_key) = zend_accel_hash_find(&ZCSG(include_paths), ZCG(include_path), ZCG(include_path_len) + 1);
+ ZCG(include_path_key) = zend_accel_hash_find(&ZCSG(include_paths), ZCG(include_path), ZCG(include_path_len));
if (!ZCG(include_path_key) &&
!zend_accel_hash_is_full(&ZCSG(include_paths))) {
char *key;
@@ -229,13 +222,13 @@ static ZEND_INI_MH(accel_include_path_on_modify)
memcpy(key, ZCG(include_path), ZCG(include_path_len) + 1);
key[ZCG(include_path_len) + 1] = 'A' + ZCSG(include_paths).num_entries;
ZCG(include_path_key) = key + ZCG(include_path_len) + 1;
- zend_accel_hash_update(&ZCSG(include_paths), key, ZCG(include_path_len) + 1, 0, ZCG(include_path_key));
+ zend_accel_hash_update(&ZCSG(include_paths), key, ZCG(include_path_len), 0, ZCG(include_path_key));
} else {
- zend_accel_schedule_restart_if_necessary(ACCEL_RESTART_OOM TSRMLS_CC);
+ zend_accel_schedule_restart_if_necessary(ACCEL_RESTART_OOM);
}
}
- zend_shared_alloc_unlock(TSRMLS_C);
+ zend_shared_alloc_unlock();
SHM_PROTECT();
}
} else {
@@ -249,235 +242,236 @@ static ZEND_INI_MH(accel_include_path_on_modify)
return ret;
}
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
/* Interned strings support */
-static char *orig_interned_strings_start;
-static char *orig_interned_strings_end;
-static const char *(*orig_new_interned_string)(const char *str, int len, int free_src TSRMLS_DC);
-static void (*orig_interned_strings_snapshot)(TSRMLS_D);
-static void (*orig_interned_strings_restore)(TSRMLS_D);
+static zend_string *(*orig_new_interned_string)(zend_string *str);
+static void (*orig_interned_strings_snapshot)(void);
+static void (*orig_interned_strings_restore)(void);
/* O+ disables creation of interned strings by regular PHP compiler, instead,
* it creates interned strings in shared memory when saves a script.
* Such interned strings are shared across all PHP processes
*/
-static const char *accel_new_interned_string_for_php(const char *str, int len, int free_src TSRMLS_DC)
+static zend_string *accel_new_interned_string_for_php(zend_string *str)
{
return str;
}
-static void accel_interned_strings_snapshot_for_php(TSRMLS_D)
+static void accel_interned_strings_snapshot_for_php(void)
{
}
-static void accel_interned_strings_restore_for_php(TSRMLS_D)
+static void accel_interned_strings_restore_for_php(void)
{
}
#ifndef ZTS
-static void accel_interned_strings_restore_state(TSRMLS_D)
-{
- unsigned int i;
-
- for (i = 0; i < ZCSG(interned_strings).nTableSize; i++) {
- ZCSG(interned_strings).arBuckets[i] = ZCSG(interned_strings_saved_state).arBuckets[i];
- if (ZCSG(interned_strings).arBuckets[i]) {
- ZCSG(interned_strings).arBuckets[i]->pLast = NULL;
- }
- }
- ZCSG(interned_strings).pListHead = ZCSG(interned_strings_saved_state).pListHead;
- ZCSG(interned_strings).pListTail = ZCSG(interned_strings_saved_state).pListTail;
- if (ZCSG(interned_strings).pListHead) {
- ZCSG(interned_strings).pListHead->pListLast = NULL;
- }
- if (ZCSG(interned_strings).pListTail) {
- ZCSG(interned_strings).pListTail->pListNext = NULL;
+static void accel_interned_strings_restore_state(void)
+{
+ uint idx = ZCSG(interned_strings).nNumUsed;
+ uint nIndex;
+ Bucket *p;
+
+ ZCSG(interned_strings_top) = ZCSG(interned_strings_saved_top);
+ while (idx > 0) {
+ idx--;
+ p = ZCSG(interned_strings).arData + idx;
+ if ((char*)p->key < ZCSG(interned_strings_top)) break;
+ ZCSG(interned_strings).nNumUsed--;
+ ZCSG(interned_strings).nNumOfElements--;
+
+ nIndex = p->h & ZCSG(interned_strings).nTableMask;
+ if (ZCSG(interned_strings).arHash[nIndex] == idx) {
+ ZCSG(interned_strings).arHash[nIndex] = Z_NEXT(p->val);
+ } else {
+ uint prev = ZCSG(interned_strings).arHash[nIndex];
+ while (Z_NEXT(ZCSG(interned_strings).arData[prev].val) != idx) {
+ prev = Z_NEXT(ZCSG(interned_strings).arData[prev].val);
+ }
+ Z_NEXT(ZCSG(interned_strings).arData[prev].val) = Z_NEXT(p->val);
+ }
}
- ZCSG(interned_strings_top) = ZCSG(interned_strings_saved_state).top;
}
-static void accel_interned_strings_save_state(TSRMLS_D)
+static void accel_interned_strings_save_state(void)
{
- ZCSG(interned_strings_saved_state).arBuckets = (Bucket**)zend_shared_alloc(ZCSG(interned_strings).nTableSize * sizeof(Bucket *));
- if (!ZCSG(interned_strings_saved_state).arBuckets) {
- zend_accel_error(ACCEL_LOG_FATAL, "Insufficient shared memory!");
- }
- memcpy(ZCSG(interned_strings_saved_state).arBuckets, ZCSG(interned_strings).arBuckets, ZCSG(interned_strings).nTableSize * sizeof(Bucket *));
- ZCSG(interned_strings_saved_state).pListHead = ZCSG(interned_strings).pListHead;
- ZCSG(interned_strings_saved_state).pListTail = ZCSG(interned_strings).pListTail;
- ZCSG(interned_strings_saved_state).top = ZCSG(interned_strings_top);
+ ZCSG(interned_strings_saved_top) = ZCSG(interned_strings_top);
}
#endif
-const char *accel_new_interned_string(const char *arKey, int nKeyLength, int free_src TSRMLS_DC)
+zend_string *accel_new_interned_string(zend_string *str)
{
/* for now interned strings are supported only for non-ZTS build */
#ifndef ZTS
- ulong h;
+ zend_ulong h;
uint nIndex;
+ uint idx;
Bucket *p;
- if (arKey >= ZCSG(interned_strings_start) && arKey < ZCSG(interned_strings_end)) {
+ if (IS_ACCEL_INTERNED(str)) {
/* this is already an interned string */
- return arKey;
+ return str;
}
- h = zend_inline_hash_func(arKey, nKeyLength);
+ h = zend_string_hash_val(str);
nIndex = h & ZCSG(interned_strings).nTableMask;
/* check for existing interned string */
- p = ZCSG(interned_strings).arBuckets[nIndex];
- while (p != NULL) {
- if ((p->h == h) && (p->nKeyLength == (uint)nKeyLength)) {
- if (!memcmp(p->arKey, arKey, nKeyLength)) {
- if (free_src) {
- efree((char*)arKey);
- }
- return p->arKey;
+ idx = ZCSG(interned_strings).arHash[nIndex];
+ while (idx != INVALID_IDX) {
+ p = ZCSG(interned_strings).arData + idx;
+ if ((p->h == h) && (p->key->len == str->len)) {
+ if (!memcmp(p->key->val, str->val, str->len)) {
+ zend_string_release(str);
+ return p->key;
}
}
- p = p->pNext;
+ idx = Z_NEXT(p->val);
}
- if (ZCSG(interned_strings_top) + ZEND_MM_ALIGNED_SIZE(sizeof(Bucket) + nKeyLength) >=
+ if (ZCSG(interned_strings_top) + ZEND_MM_ALIGNED_SIZE(_STR_HEADER_SIZE + str->len + 1) >=
ZCSG(interned_strings_end)) {
/* no memory, return the same non-interned string */
zend_accel_error(ACCEL_LOG_WARNING, "Interned string buffer overflow");
- return arKey;
+ return str;
}
/* create new interning string in shared interned strings buffer */
- p = (Bucket *) ZCSG(interned_strings_top);
- ZCSG(interned_strings_top) += ZEND_MM_ALIGNED_SIZE(sizeof(Bucket) + nKeyLength);
-
- p->arKey = (char*)(p + 1);
- memcpy((char*)p->arKey, arKey, nKeyLength);
- p->nKeyLength = nKeyLength;
- p->h = h;
- p->pData = &p->pDataPtr;
- p->pDataPtr = p;
-
- p->pNext = ZCSG(interned_strings).arBuckets[nIndex];
- p->pLast = NULL;
- if (p->pNext) {
- p->pNext->pLast = p;
- }
- ZCSG(interned_strings).arBuckets[nIndex] = p;
-
- p->pListLast = ZCSG(interned_strings).pListTail;
- ZCSG(interned_strings).pListTail = p;
- p->pListNext = NULL;
- if (p->pListLast != NULL) {
- p->pListLast->pListNext = p;
- }
- if (!ZCSG(interned_strings).pListHead) {
- ZCSG(interned_strings).pListHead = p;
- }
+ idx = ZCSG(interned_strings).nNumUsed++;
ZCSG(interned_strings).nNumOfElements++;
-
- if (free_src) {
- efree((char*)arKey);
- }
-
- return p->arKey;
+ p = ZCSG(interned_strings).arData + idx;
+ p->key = (zend_string*) ZCSG(interned_strings_top);
+ ZCSG(interned_strings_top) += ZEND_MM_ALIGNED_SIZE(_STR_HEADER_SIZE + str->len + 1);
+ p->h = h;
+ GC_REFCOUNT(p->key) = 1;
+#if 1
+ /* optimized single assignment */
+ GC_TYPE_INFO(p->key) = IS_STRING | ((IS_STR_INTERNED | IS_STR_PERMANENT) << 8);
#else
- return arKey;
+ GC_TYPE(p->key) = IS_STRING;
+ GC_FLAGS(p->key) = IS_STR_INTERNED | IS_STR_PERMANENT;
+#endif
+ p->key->h = str->h;
+ p->key->len = str->len;
+ memcpy(p->key->val, str->val, str->len);
+ ZVAL_STR(&p->val, p->key);
+ Z_NEXT(p->val) = ZCSG(interned_strings).arHash[nIndex];
+ ZCSG(interned_strings).arHash[nIndex] = idx;
+ zend_string_release(str);
+ return p->key;
+#else
+ return str;
#endif
}
#ifndef ZTS
/* Copy PHP interned strings from PHP process memory into the shared memory */
-static void accel_use_shm_interned_strings(TSRMLS_D)
+static void accel_use_shm_interned_strings(void)
{
+ uint idx, j;
Bucket *p, *q;
-#if ZEND_EXTENSION_API_NO > PHP_5_5_X_API_NO
/* empty string */
- CG(interned_empty_string) = accel_new_interned_string("", sizeof(""), 0 TSRMLS_CC);
-#endif
+ CG(empty_string) = accel_new_interned_string(CG(empty_string));
+ for (j = 0; j < 256; j++) {
+ char s[2];
+ s[0] = j;
+ s[1] = 0;
+ CG(one_char_string)[j] = accel_new_interned_string(zend_string_init(s, 1, 0));
+ }
/* function table hash keys */
- p = CG(function_table)->pListHead;
- while (p) {
- if (p->nKeyLength) {
- p->arKey = accel_new_interned_string(p->arKey, p->nKeyLength, 0 TSRMLS_CC);
+ for (idx = 0; idx < CG(function_table)->nNumUsed; idx++) {
+ p = CG(function_table)->arData + idx;
+ if (Z_TYPE(p->val) == IS_UNDEF) continue;
+ if (p->key) {
+ p->key = accel_new_interned_string(p->key);
+ }
+ if (Z_FUNC(p->val)->common.function_name) {
+ Z_FUNC(p->val)->common.function_name = accel_new_interned_string(Z_FUNC(p->val)->common.function_name);
}
- p = p->pListNext;
}
/* class table hash keys, class names, properties, methods, constants, etc */
- p = CG(class_table)->pListHead;
- while (p) {
- zend_class_entry *ce = (zend_class_entry*)(p->pDataPtr);
+ for (idx = 0; idx < CG(class_table)->nNumUsed; idx++) {
+ zend_class_entry *ce;
+
+ p = CG(class_table)->arData + idx;
+ if (Z_TYPE(p->val) == IS_UNDEF) continue;
+ ce = (zend_class_entry*)Z_PTR(p->val);
- if (p->nKeyLength) {
- p->arKey = accel_new_interned_string(p->arKey, p->nKeyLength, 0 TSRMLS_CC);
+ if (p->key) {
+ p->key = accel_new_interned_string(p->key);
}
if (ce->name) {
- ce->name = accel_new_interned_string(ce->name, ce->name_length + 1, 0 TSRMLS_CC);
+ ce->name = accel_new_interned_string(ce->name);
}
- q = ce->properties_info.pListHead;
- while (q) {
- zend_property_info *info = (zend_property_info*)(q->pData);
+ for (j = 0; j < ce->properties_info.nNumUsed; j++) {
+ zend_property_info *info;
- if (q->nKeyLength) {
- q->arKey = accel_new_interned_string(q->arKey, q->nKeyLength, 0 TSRMLS_CC);
+ q = ce->properties_info.arData + j;
+ if (Z_TYPE(q->val) == IS_UNDEF) continue;
+
+ info = (zend_property_info*)Z_PTR(q->val);
+
+ if (q->key) {
+ q->key = accel_new_interned_string(q->key);
}
if (info->name) {
- info->name = accel_new_interned_string(info->name, info->name_length + 1, 0 TSRMLS_CC);
+ info->name = accel_new_interned_string(info->name);
}
-
- q = q->pListNext;
}
- q = ce->function_table.pListHead;
- while (q) {
- if (q->nKeyLength) {
- q->arKey = accel_new_interned_string(q->arKey, q->nKeyLength, 0 TSRMLS_CC);
+ for (j = 0; j < ce->function_table.nNumUsed; j++) {
+ q = ce->function_table.arData + j;
+ if (Z_TYPE(q->val) == IS_UNDEF) continue;
+ if (q->key) {
+ q->key = accel_new_interned_string(q->key);
+ }
+ if (Z_FUNC(q->val)->common.function_name) {
+ Z_FUNC(q->val)->common.function_name = accel_new_interned_string(Z_FUNC(q->val)->common.function_name);
}
- q = q->pListNext;
}
- q = ce->constants_table.pListHead;
- while (q) {
- if (q->nKeyLength) {
- q->arKey = accel_new_interned_string(q->arKey, q->nKeyLength, 0 TSRMLS_CC);
+ for (j = 0; j < ce->constants_table.nNumUsed; j++) {
+ q = ce->constants_table.arData + j;
+ if (!Z_TYPE(q->val) == IS_UNDEF) continue;
+ if (q->key) {
+ q->key = accel_new_interned_string(q->key);
}
- q = q->pListNext;
}
-
- p = p->pListNext;
}
/* constant hash keys */
- p = EG(zend_constants)->pListHead;
- while (p) {
- if (p->nKeyLength) {
- p->arKey = accel_new_interned_string(p->arKey, p->nKeyLength, 0 TSRMLS_CC);
+ for (idx = 0; idx < EG(zend_constants)->nNumUsed; idx++) {
+ p = EG(zend_constants)->arData + idx;
+ if (!Z_TYPE(p->val) == IS_UNDEF) continue;
+ if (p->key) {
+ p->key = accel_new_interned_string(p->key);
}
- p = p->pListNext;
}
/* auto globals hash keys and names */
- p = CG(auto_globals)->pListHead;
- while (p) {
- zend_auto_global *auto_global = (zend_auto_global*)p->pData;
+ for (idx = 0; idx < CG(auto_globals)->nNumUsed; idx++) {
+ zend_auto_global *auto_global;
+
+ p = CG(auto_globals)->arData + idx;
+ if (Z_TYPE(p->val) == IS_UNDEF) continue;
- auto_global->name = accel_new_interned_string(auto_global->name, auto_global->name_len + 1, 0 TSRMLS_CC);
- if (p->nKeyLength) {
- p->arKey = accel_new_interned_string(p->arKey, p->nKeyLength, 0 TSRMLS_CC);
+ auto_global = (zend_auto_global*)Z_PTR(p->val);;
+
+ auto_global->name = accel_new_interned_string(auto_global->name);
+ if (p->key) {
+ p->key = accel_new_interned_string(p->key);
}
- p = p->pListNext;
}
}
#endif
-#endif
-static inline void accel_restart_enter(TSRMLS_D)
+static inline void accel_restart_enter(void)
{
#ifdef ZEND_WIN32
INCREMENT(restart_in);
@@ -491,7 +485,7 @@ static inline void accel_restart_enter(TSRMLS_D)
ZCSG(restart_in_progress) = 1;
}
-static inline void accel_restart_leave(TSRMLS_D)
+static inline void accel_restart_leave(void)
{
#ifdef ZEND_WIN32
ZCSG(restart_in_progress) = 0;
@@ -506,7 +500,7 @@ static inline void accel_restart_leave(TSRMLS_D)
#endif
}
-static inline int accel_restart_is_active(TSRMLS_D)
+static inline int accel_restart_is_active(void)
{
if (ZCSG(restart_in_progress)) {
#ifndef ZEND_WIN32
@@ -530,7 +524,7 @@ static inline int accel_restart_is_active(TSRMLS_D)
}
/* Creates a read lock for SHM access */
-static inline void accel_activate_add(TSRMLS_D)
+static inline void accel_activate_add(void)
{
#ifdef ZEND_WIN32
INCREMENT(mem_usage);
@@ -544,7 +538,7 @@ static inline void accel_activate_add(TSRMLS_D)
}
/* Releases a lock for SHM access */
-static inline void accel_deactivate_sub(TSRMLS_D)
+static inline void accel_deactivate_sub(void)
{
#ifdef ZEND_WIN32
if (ZCG(counted)) {
@@ -560,10 +554,10 @@ static inline void accel_deactivate_sub(TSRMLS_D)
#endif
}
-static inline void accel_unlock_all(TSRMLS_D)
+static inline void accel_unlock_all(void)
{
#ifdef ZEND_WIN32
- accel_deactivate_sub(TSRMLS_C);
+ accel_deactivate_sub();
#else
static const FLOCK_STRUCTURE(mem_usage_unlock_all, F_UNLCK, SEEK_SET, 0, 0);
@@ -616,7 +610,7 @@ static inline void kill_all_lockers(struct flock *mem_usage_check)
}
#endif
-static inline int accel_is_inactive(TSRMLS_D)
+static inline int accel_is_inactive(void)
{
#ifdef ZEND_WIN32
if (LOCKVAL(mem_usage) == 0) {
@@ -647,7 +641,7 @@ static inline int accel_is_inactive(TSRMLS_D)
return FAILURE;
}
-static int zend_get_stream_timestamp(const char *filename, struct stat *statbuf TSRMLS_DC)
+static int zend_get_stream_timestamp(const char *filename, zend_stat_t *statbuf)
{
php_stream_wrapper *wrapper;
php_stream_statbuf stream_statbuf;
@@ -657,7 +651,7 @@ static int zend_get_stream_timestamp(const char *filename, struct stat *statbuf
return FAILURE;
}
- wrapper = php_stream_locate_url_wrapper(filename, NULL, STREAM_LOCATE_WRAPPERS_ONLY TSRMLS_CC);
+ wrapper = php_stream_locate_url_wrapper(filename, NULL, STREAM_LOCATE_WRAPPERS_ONLY);
if (!wrapper) {
return FAILURE;
}
@@ -669,7 +663,7 @@ static int zend_get_stream_timestamp(const char *filename, struct stat *statbuf
er = EG(error_reporting);
EG(error_reporting) = 0;
zend_try {
- ret = wrapper->wops->url_stat(wrapper, (char*)filename, PHP_STREAM_URL_STAT_QUIET, &stream_statbuf, NULL TSRMLS_CC);
+ ret = wrapper->wops->url_stat(wrapper, (char*)filename, PHP_STREAM_URL_STAT_QUIET, &stream_statbuf, NULL);
} zend_catch {
ret = -1;
} zend_end_try();
@@ -720,7 +714,7 @@ static accel_time_t zend_get_file_handle_timestamp_win(zend_file_handle *file_ha
ftime /= 10000000L;
if (size) {
- *size = (size_t)(((unsigned __int64)fdata.nFileSizeHigh) << 32 + (unsigned __int64)fdata.nFileSizeLow);
+ *size = (size_t)((((unsigned __int64)fdata.nFileSizeHigh) << 32) + (unsigned __int64)fdata.nFileSizeLow);
}
return (accel_time_t)ftime;
}
@@ -728,18 +722,18 @@ static accel_time_t zend_get_file_handle_timestamp_win(zend_file_handle *file_ha
}
#endif
-static accel_time_t zend_get_file_handle_timestamp(zend_file_handle *file_handle, size_t *size TSRMLS_DC)
+static accel_time_t zend_get_file_handle_timestamp(zend_file_handle *file_handle, size_t *size)
{
- struct stat statbuf;
+ zend_stat_t statbuf;
#ifdef ZEND_WIN32
accel_time_t res;
#endif
if (sapi_module.get_stat &&
- !EG(opline_ptr) &&
+ !EG(current_execute_data) &&
file_handle->filename == SG(request_info).path_translated) {
- struct stat *tmpbuf = sapi_module.get_stat(TSRMLS_C);
+ zend_stat_t *tmpbuf = sapi_module.get_stat();
if (tmpbuf) {
if (size) {
@@ -758,27 +752,25 @@ static accel_time_t zend_get_file_handle_timestamp(zend_file_handle *file_handle
switch (file_handle->type) {
case ZEND_HANDLE_FD:
- if (fstat(file_handle->handle.fd, &statbuf) == -1) {
+ if (zend_fstat(file_handle->handle.fd, &statbuf) == -1) {
return 0;
}
break;
case ZEND_HANDLE_FP:
- if (fstat(fileno(file_handle->handle.fp), &statbuf) == -1) {
- if (zend_get_stream_timestamp(file_handle->filename, &statbuf TSRMLS_CC) != SUCCESS) {
+ if (zend_fstat(fileno(file_handle->handle.fp), &statbuf) == -1) {
+ if (zend_get_stream_timestamp(file_handle->filename, &statbuf) != SUCCESS) {
return 0;
}
}
break;
case ZEND_HANDLE_FILENAME:
-#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
case ZEND_HANDLE_MAPPED:
-#endif
{
char *file_path = file_handle->opened_path;
if (file_path) {
if (is_stream_path(file_path)) {
- if (zend_get_stream_timestamp(file_path, &statbuf TSRMLS_CC) == SUCCESS) {
+ if (zend_get_stream_timestamp(file_path, &statbuf) == SUCCESS) {
break;
}
}
@@ -787,7 +779,7 @@ static accel_time_t zend_get_file_handle_timestamp(zend_file_handle *file_handle
}
}
- if (zend_get_stream_timestamp(file_handle->filename, &statbuf TSRMLS_CC) != SUCCESS) {
+ if (zend_get_stream_timestamp(file_handle->filename, &statbuf) != SUCCESS) {
return 0;
}
break;
@@ -807,7 +799,7 @@ static accel_time_t zend_get_file_handle_timestamp(zend_file_handle *file_handle
er = EG(error_reporting);
EG(error_reporting) = 0;
zend_try {
- ret = stream->ops->stat(stream, &sb TSRMLS_CC);
+ ret = stream->ops->stat(stream, &sb);
} zend_catch {
ret = -1;
} zend_end_try();
@@ -830,26 +822,22 @@ static accel_time_t zend_get_file_handle_timestamp(zend_file_handle *file_handle
return statbuf.st_mtime;
}
-static inline int do_validate_timestamps(zend_persistent_script *persistent_script, zend_file_handle *file_handle TSRMLS_DC)
+static inline int do_validate_timestamps(zend_persistent_script *persistent_script, zend_file_handle *file_handle)
{
zend_file_handle ps_handle;
char *full_path_ptr = NULL;
- /** check that the persistant script is indeed the same file we cached
+ /** check that the persistent script is indeed the same file we cached
* (if part of the path is a symlink than it possible that the user will change it)
* See bug #15140
*/
if (file_handle->opened_path) {
- if (strcmp(persistent_script->full_path, file_handle->opened_path) != 0) {
+ if (strcmp(persistent_script->full_path->val, file_handle->opened_path) != 0) {
return FAILURE;
}
- } else {
-#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
- full_path_ptr = accel_php_resolve_path(file_handle->filename, strlen(file_handle->filename), ZCG(include_path) TSRMLS_CC);
-#else
- full_path_ptr = accelerator_orig_zend_resolve_path(file_handle->filename, strlen(file_handle->filename) TSRMLS_CC);
-#endif
- if (full_path_ptr && strcmp(persistent_script->full_path, full_path_ptr) != 0) {
+ } else {
+ full_path_ptr = accelerator_orig_zend_resolve_path(file_handle->filename, strlen(file_handle->filename));
+ if (full_path_ptr && strcmp(persistent_script->full_path->val, full_path_ptr) != 0) {
efree(full_path_ptr);
return FAILURE;
}
@@ -864,7 +852,7 @@ static inline int do_validate_timestamps(zend_persistent_script *persistent_scri
return FAILURE;
}
- if (zend_get_file_handle_timestamp(file_handle, NULL TSRMLS_CC) == persistent_script->timestamp) {
+ if (zend_get_file_handle_timestamp(file_handle, NULL) == persistent_script->timestamp) {
if (full_path_ptr) {
efree(full_path_ptr);
file_handle->opened_path = NULL;
@@ -877,22 +865,22 @@ static inline int do_validate_timestamps(zend_persistent_script *persistent_scri
}
ps_handle.type = ZEND_HANDLE_FILENAME;
- ps_handle.filename = persistent_script->full_path;
- ps_handle.opened_path = persistent_script->full_path;
+ ps_handle.filename = persistent_script->full_path->val;
+ ps_handle.opened_path = persistent_script->full_path->val;
- if (zend_get_file_handle_timestamp(&ps_handle, NULL TSRMLS_CC) == persistent_script->timestamp) {
+ if (zend_get_file_handle_timestamp(&ps_handle, NULL) == persistent_script->timestamp) {
return SUCCESS;
}
return FAILURE;
}
-int validate_timestamp_and_record(zend_persistent_script *persistent_script, zend_file_handle *file_handle TSRMLS_DC)
+int validate_timestamp_and_record(zend_persistent_script *persistent_script, zend_file_handle *file_handle)
{
if (ZCG(accel_directives).revalidate_freq &&
persistent_script->dynamic_members.revalidate >= ZCG(request_time)) {
return SUCCESS;
- } else if (do_validate_timestamps(persistent_script, file_handle TSRMLS_CC) == FAILURE) {
+ } else if (do_validate_timestamps(persistent_script, file_handle) == FAILURE) {
return FAILURE;
} else {
persistent_script->dynamic_members.revalidate = ZCG(request_time) + ZCG(accel_directives).revalidate_freq;
@@ -926,7 +914,7 @@ static unsigned int zend_accel_script_checksum(zend_persistent_script *persisten
/* Instead of resolving full real path name each time we need to identify file,
* we create a key that consist from requested file name, current working
* directory, current include_path, etc */
-char *accel_make_persistent_key_ex(zend_file_handle *file_handle, int path_length, int *key_len TSRMLS_DC)
+char *accel_make_persistent_key_ex(zend_file_handle *file_handle, int path_length, int *key_len)
{
int key_length;
@@ -942,7 +930,7 @@ char *accel_make_persistent_key_ex(zend_file_handle *file_handle, int path_lengt
int cwd_len;
char *cwd;
- if ((cwd = accel_getcwd(&cwd_len TSRMLS_CC)) == NULL) {
+ if ((cwd = accel_getcwd(&cwd_len)) == NULL) {
/* we don't handle this well for now. */
zend_accel_error(ACCEL_LOG_INFO, "getcwd() failed for '%s' (%d), please try to set opcache.use_cwd to 0 in ini file", file_handle->filename, errno);
if (file_handle->opened_path) {
@@ -963,13 +951,13 @@ char *accel_make_persistent_key_ex(zend_file_handle *file_handle, int path_lengt
if (ZCG(include_path_check) &&
ZCG(enabled) && accel_startup_ok &&
(ZCG(counted) || ZCSG(accelerator_enabled)) &&
- !zend_accel_hash_find(&ZCSG(include_paths), ZCG(include_path), ZCG(include_path_len) + 1) &&
+ !zend_accel_hash_find(&ZCSG(include_paths), ZCG(include_path), ZCG(include_path_len)) &&
!zend_accel_hash_is_full(&ZCSG(include_paths))) {
SHM_UNPROTECT();
- zend_shared_alloc_lock(TSRMLS_C);
+ zend_shared_alloc_lock();
- ZCG(include_path_key) = zend_accel_hash_find(&ZCSG(include_paths), ZCG(include_path), ZCG(include_path_len) + 1);
+ ZCG(include_path_key) = zend_accel_hash_find(&ZCSG(include_paths), ZCG(include_path), ZCG(include_path_len));
if (ZCG(include_path_key)) {
include_path = ZCG(include_path_key);
include_path_len = 1;
@@ -981,15 +969,15 @@ char *accel_make_persistent_key_ex(zend_file_handle *file_handle, int path_lengt
memcpy(key, ZCG(include_path), ZCG(include_path_len) + 1);
key[ZCG(include_path_len) + 1] = 'A' + ZCSG(include_paths).num_entries;
ZCG(include_path_key) = key + ZCG(include_path_len) + 1;
- zend_accel_hash_update(&ZCSG(include_paths), key, ZCG(include_path_len) + 1, 0, ZCG(include_path_key));
+ zend_accel_hash_update(&ZCSG(include_paths), key, ZCG(include_path_len), 0, ZCG(include_path_key));
include_path = ZCG(include_path_key);
include_path_len = 1;
} else {
- zend_accel_schedule_restart_if_necessary(ACCEL_RESTART_OOM TSRMLS_CC);
+ zend_accel_schedule_restart_if_necessary(ACCEL_RESTART_OOM);
}
}
- zend_shared_alloc_unlock(TSRMLS_C);
+ zend_shared_alloc_unlock();
SHM_PROTECT();
}
}
@@ -998,8 +986,8 @@ char *accel_make_persistent_key_ex(zend_file_handle *file_handle, int path_lengt
since fopen_wrappers from version 4.0.7 use current script's path
in include path too.
*/
- if (EG(in_execution) &&
- (parent_script = zend_get_executed_filename(TSRMLS_C)) != NULL &&
+ if (EG(current_execute_data) &&
+ (parent_script = zend_get_executed_filename()) != NULL &&
parent_script[0] != '[') {
parent_script_len = strlen(parent_script);
@@ -1052,31 +1040,27 @@ char *accel_make_persistent_key_ex(zend_file_handle *file_handle, int path_lengt
return ZCG(key);
}
-static inline char *accel_make_persistent_key(zend_file_handle *file_handle, int *key_len TSRMLS_DC)
+static inline char *accel_make_persistent_key(zend_file_handle *file_handle, int *key_len)
{
- return accel_make_persistent_key_ex(file_handle, strlen(file_handle->filename), key_len TSRMLS_CC);
+ return accel_make_persistent_key_ex(file_handle, strlen(file_handle->filename), key_len);
}
-int zend_accel_invalidate(const char *filename, int filename_len, zend_bool force TSRMLS_DC)
+int zend_accel_invalidate(const char *filename, int filename_len, zend_bool force)
{
char *realpath;
zend_persistent_script *persistent_script;
- if (!ZCG(enabled) || !accel_startup_ok || !ZCSG(accelerator_enabled) || accelerator_shm_read_lock(TSRMLS_C) != SUCCESS) {
+ if (!ZCG(enabled) || !accel_startup_ok || !ZCSG(accelerator_enabled) || accelerator_shm_read_lock() != SUCCESS) {
return FAILURE;
}
-#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
- realpath = accel_php_resolve_path(filename, filename_len, ZCG(include_path) TSRMLS_CC);
-#else
- realpath = accelerator_orig_zend_resolve_path(filename, filename_len TSRMLS_CC);
-#endif
+ realpath = accelerator_orig_zend_resolve_path(filename, filename_len);
if (!realpath) {
return FAILURE;
}
- persistent_script = zend_accel_hash_find(&ZCSG(hash), realpath, strlen(realpath) + 1);
+ persistent_script = zend_accel_hash_find(&ZCSG(hash), realpath, strlen(realpath));
if (persistent_script && !persistent_script->corrupted) {
zend_file_handle file_handle;
@@ -1086,9 +1070,9 @@ int zend_accel_invalidate(const char *filename, int filename_len, zend_bool forc
if (force ||
!ZCG(accel_directives).validate_timestamps ||
- do_validate_timestamps(persistent_script, &file_handle TSRMLS_CC) == FAILURE) {
+ do_validate_timestamps(persistent_script, &file_handle) == FAILURE) {
SHM_UNPROTECT();
- zend_shared_alloc_lock(TSRMLS_C);
+ zend_shared_alloc_lock();
if (!persistent_script->corrupted) {
persistent_script->corrupted = 1;
persistent_script->timestamp = 0;
@@ -1096,43 +1080,43 @@ int zend_accel_invalidate(const char *filename, int filename_len, zend_bool forc
if (ZSMMG(memory_exhausted)) {
zend_accel_restart_reason reason =
zend_accel_hash_is_full(&ZCSG(hash)) ? ACCEL_RESTART_HASH : ACCEL_RESTART_OOM;
- zend_accel_schedule_restart_if_necessary(reason TSRMLS_CC);
+ zend_accel_schedule_restart_if_necessary(reason);
}
}
- zend_shared_alloc_unlock(TSRMLS_C);
+ zend_shared_alloc_unlock();
SHM_PROTECT();
}
}
- accelerator_shm_read_unlock(TSRMLS_C);
+ accelerator_shm_read_unlock();
efree(realpath);
-
+
return SUCCESS;
}
/* Adds another key for existing cached script */
-static void zend_accel_add_key(char *key, unsigned int key_length, zend_accel_hash_entry *bucket TSRMLS_DC)
+static void zend_accel_add_key(char *key, unsigned int key_length, zend_accel_hash_entry *bucket)
{
- if (!zend_accel_hash_find(&ZCSG(hash), key, key_length + 1)) {
+ if (!zend_accel_hash_find(&ZCSG(hash), key, key_length)) {
if (zend_accel_hash_is_full(&ZCSG(hash))) {
zend_accel_error(ACCEL_LOG_DEBUG, "No more entries in hash table!");
ZSMMG(memory_exhausted) = 1;
- zend_accel_schedule_restart_if_necessary(ACCEL_RESTART_HASH TSRMLS_CC);
+ zend_accel_schedule_restart_if_necessary(ACCEL_RESTART_HASH);
} else {
char *new_key = zend_shared_alloc(key_length + 1);
if (new_key) {
memcpy(new_key, key, key_length + 1);
- if (zend_accel_hash_update(&ZCSG(hash), new_key, key_length + 1, 1, bucket)) {
+ if (zend_accel_hash_update(&ZCSG(hash), new_key, key_length, 1, bucket)) {
zend_accel_error(ACCEL_LOG_INFO, "Added key '%s'", new_key);
}
} else {
- zend_accel_schedule_restart_if_necessary(ACCEL_RESTART_OOM TSRMLS_CC);
+ zend_accel_schedule_restart_if_necessary(ACCEL_RESTART_OOM);
}
}
}
}
-static zend_persistent_script *cache_script_in_shared_memory(zend_persistent_script *new_persistent_script, char *key, unsigned int key_length, int *from_shared_memory TSRMLS_DC)
+static zend_persistent_script *cache_script_in_shared_memory(zend_persistent_script *new_persistent_script, char *key, unsigned int key_length, int *from_shared_memory)
{
zend_accel_hash_entry *bucket;
uint memory_used;
@@ -1142,29 +1126,25 @@ static zend_persistent_script *cache_script_in_shared_memory(zend_persistent_scr
return new_persistent_script;
}
- if (!zend_accel_script_optimize(new_persistent_script TSRMLS_CC)) {
- return new_persistent_script;
- }
-
- if (!compact_persistent_script(new_persistent_script)) {
+ if (!zend_accel_script_optimize(new_persistent_script)) {
return new_persistent_script;
}
/* exclusive lock */
- zend_shared_alloc_lock(TSRMLS_C);
+ zend_shared_alloc_lock();
if (zend_accel_hash_is_full(&ZCSG(hash))) {
zend_accel_error(ACCEL_LOG_DEBUG, "No more entries in hash table!");
ZSMMG(memory_exhausted) = 1;
- zend_accel_schedule_restart_if_necessary(ACCEL_RESTART_HASH TSRMLS_CC);
- zend_shared_alloc_unlock(TSRMLS_C);
+ zend_accel_schedule_restart_if_necessary(ACCEL_RESTART_HASH);
+ zend_shared_alloc_unlock();
return new_persistent_script;
}
/* Check if we still need to put the file into the cache (may be it was
* already stored by another process. This final check is done under
* exclusive lock) */
- bucket = zend_accel_hash_find_entry(&ZCSG(hash), new_persistent_script->full_path, new_persistent_script->full_path_len + 1);
+ bucket = zend_accel_hash_find_entry(&ZCSG(hash), new_persistent_script->full_path->val, new_persistent_script->full_path->len);
if (bucket) {
zend_persistent_script *existing_persistent_script = (zend_persistent_script *)bucket->data;
@@ -1172,37 +1152,33 @@ static zend_persistent_script *cache_script_in_shared_memory(zend_persistent_scr
if (!ZCG(accel_directives).revalidate_path &&
(!ZCG(accel_directives).validate_timestamps ||
(new_persistent_script->timestamp == existing_persistent_script->timestamp))) {
- zend_accel_add_key(key, key_length, bucket TSRMLS_CC);
+ zend_accel_add_key(key, key_length, bucket);
}
- zend_shared_alloc_unlock(TSRMLS_C);
+ zend_shared_alloc_unlock();
return new_persistent_script;
}
}
/* Calculate the required memory size */
- memory_used = zend_accel_script_persist_calc(new_persistent_script, key, key_length TSRMLS_CC);
+ memory_used = zend_accel_script_persist_calc(new_persistent_script, key, key_length);
/* Allocate shared memory */
ZCG(mem) = zend_shared_alloc(memory_used);
if (!ZCG(mem)) {
- zend_accel_schedule_restart_if_necessary(ACCEL_RESTART_OOM TSRMLS_CC);
- zend_shared_alloc_unlock(TSRMLS_C);
+ zend_accel_schedule_restart_if_necessary(ACCEL_RESTART_OOM);
+ zend_shared_alloc_unlock();
return new_persistent_script;
}
- /* cleanup after calculation */
- new_persistent_script->mem = ZCG(mem);
- new_persistent_script->size = memory_used;
-
/* Copy into shared memory */
- new_persistent_script = zend_accel_script_persist(new_persistent_script, &key, key_length TSRMLS_CC);
+ new_persistent_script = zend_accel_script_persist(new_persistent_script, &key, key_length);
/* Consistency check */
if ((char*)new_persistent_script->mem + new_persistent_script->size != (char*)ZCG(mem)) {
zend_accel_error(
((char*)new_persistent_script->mem + new_persistent_script->size < (char*)ZCG(mem)) ? ACCEL_LOG_ERROR : ACCEL_LOG_WARNING,
"Internal error: wrong size calculation: %s start=0x%08x, end=0x%08x, real=0x%08x\n",
- new_persistent_script->full_path,
+ new_persistent_script->full_path->val,
new_persistent_script->mem,
(char *)new_persistent_script->mem + new_persistent_script->size,
ZCG(mem));
@@ -1211,28 +1187,28 @@ static zend_persistent_script *cache_script_in_shared_memory(zend_persistent_scr
new_persistent_script->dynamic_members.checksum = zend_accel_script_checksum(new_persistent_script);
/* store script structure in the hash table */
- bucket = zend_accel_hash_update(&ZCSG(hash), new_persistent_script->full_path, new_persistent_script->full_path_len + 1, 0, new_persistent_script);
+ bucket = zend_accel_hash_update(&ZCSG(hash), new_persistent_script->full_path->val, new_persistent_script->full_path->len, 0, new_persistent_script);
if (bucket) {
zend_accel_error(ACCEL_LOG_INFO, "Cached script '%s'", new_persistent_script->full_path);
if (!ZCG(accel_directives).revalidate_path &&
/* key may contain non-persistent PHAR aliases (see issues #115 and #149) */
memcmp(key, "phar://", sizeof("phar://") - 1) != 0 &&
- (new_persistent_script->full_path_len != key_length ||
- memcmp(new_persistent_script->full_path, key, key_length) != 0)) {
+ (new_persistent_script->full_path->len != key_length ||
+ memcmp(new_persistent_script->full_path->val, key, key_length) != 0)) {
/* link key to the same persistent script in hash table */
- if (zend_accel_hash_update(&ZCSG(hash), key, key_length + 1, 1, bucket)) {
+ if (zend_accel_hash_update(&ZCSG(hash), key, key_length, 1, bucket)) {
zend_accel_error(ACCEL_LOG_INFO, "Added key '%s'", key);
} else {
zend_accel_error(ACCEL_LOG_DEBUG, "No more entries in hash table!");
ZSMMG(memory_exhausted) = 1;
- zend_accel_schedule_restart_if_necessary(ACCEL_RESTART_HASH TSRMLS_CC);
+ zend_accel_schedule_restart_if_necessary(ACCEL_RESTART_HASH);
}
}
}
new_persistent_script->dynamic_members.memory_consumption = ZEND_ALIGNED_SIZE(new_persistent_script->size);
- zend_shared_alloc_unlock(TSRMLS_C);
+ zend_shared_alloc_unlock();
*from_shared_memory = 1;
return new_persistent_script;
@@ -1243,22 +1219,22 @@ static const struct jit_auto_global_info
const char *name;
size_t len;
} jit_auto_globals_info[] = {
- { "_SERVER", sizeof("_SERVER")},
- { "_ENV", sizeof("_ENV")},
- { "_REQUEST", sizeof("_REQUEST")},
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
- { "GLOBALS", sizeof("GLOBALS")},
-#endif
+ { "_SERVER", sizeof("_SERVER")-1},
+ { "_ENV", sizeof("_ENV")-1},
+ { "_REQUEST", sizeof("_REQUEST")-1},
+ { "GLOBALS", sizeof("GLOBALS")-1},
};
-static int zend_accel_get_auto_globals(TSRMLS_D)
+static zend_string *jit_auto_globals_str[4];
+
+static int zend_accel_get_auto_globals(void)
{
int i, ag_size = (sizeof(jit_auto_globals_info) / sizeof(jit_auto_globals_info[0]));
int n = 1;
int mask = 0;
for (i = 0; i < ag_size ; i++) {
- if (zend_hash_exists(&EG(symbol_table), jit_auto_globals_info[i].name, jit_auto_globals_info[i].len)) {
+ if (zend_hash_exists(&EG(symbol_table).ht, jit_auto_globals_str[i])) {
mask |= n;
}
n += n;
@@ -1266,45 +1242,53 @@ static int zend_accel_get_auto_globals(TSRMLS_D)
return mask;
}
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
-static int zend_accel_get_auto_globals_no_jit(TSRMLS_D)
+static int zend_accel_get_auto_globals_no_jit(void)
{
- if (zend_hash_exists(&EG(symbol_table), jit_auto_globals_info[3].name, jit_auto_globals_info[3].len)) {
+ if (zend_hash_exists(&EG(symbol_table).ht, jit_auto_globals_str[3])) {
return 8;
}
return 0;
}
-#endif
-static void zend_accel_set_auto_globals(int mask TSRMLS_DC)
+static void zend_accel_set_auto_globals(int mask)
{
int i, ag_size = (sizeof(jit_auto_globals_info) / sizeof(jit_auto_globals_info[0]));
int n = 1;
for (i = 0; i < ag_size ; i++) {
- if (mask & n) {
- zend_is_auto_global(jit_auto_globals_info[i].name, jit_auto_globals_info[i].len - 1 TSRMLS_CC);
+ if ((mask & n) && !(ZCG(auto_globals_mask) & n)) {
+ ZCG(auto_globals_mask) |= n;
+ zend_is_auto_global(jit_auto_globals_str[i]);
}
n += n;
}
}
-static zend_persistent_script *compile_and_cache_file(zend_file_handle *file_handle, int type, char *key, unsigned int key_length, zend_op_array **op_array_p, int *from_shared_memory TSRMLS_DC)
+static void zend_accel_init_auto_globals(void)
+{
+ int i, ag_size = (sizeof(jit_auto_globals_info) / sizeof(jit_auto_globals_info[0]));
+
+ for (i = 0; i < ag_size ; i++) {
+ jit_auto_globals_str[i] = zend_string_init(jit_auto_globals_info[i].name, jit_auto_globals_info[i].len, 1);
+ zend_string_hash_val(jit_auto_globals_str[i]);
+ jit_auto_globals_str[i] = accel_new_interned_string(jit_auto_globals_str[i]);
+ }
+}
+
+static zend_persistent_script *compile_and_cache_file(zend_file_handle *file_handle, int type, char *key, unsigned int key_length, zend_op_array **op_array_p, int *from_shared_memory)
{
zend_persistent_script *new_persistent_script;
zend_op_array *orig_active_op_array;
HashTable *orig_function_table, *orig_class_table;
- zval *orig_user_error_handler;
+ zval orig_user_error_handler;
zend_op_array *op_array;
int do_bailout = 0;
accel_time_t timestamp = 0;
-#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
- zend_uint orig_compiler_options = 0;
-#endif
+ uint32_t orig_compiler_options = 0;
/* Try to open file */
if (file_handle->type == ZEND_HANDLE_FILENAME) {
- if (accelerator_orig_zend_stream_open_function(file_handle->filename, file_handle TSRMLS_CC) == SUCCESS) {
+ if (accelerator_orig_zend_stream_open_function(file_handle->filename, file_handle) == SUCCESS) {
/* key may be changed by zend_stream_open_function() */
if (key == ZCG(key)) {
key_length = ZCG(key_len);
@@ -1312,18 +1296,10 @@ static zend_persistent_script *compile_and_cache_file(zend_file_handle *file_han
} else {
*op_array_p = NULL;
if (type == ZEND_REQUIRE) {
-#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename);
-#else
- zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename TSRMLS_CC);
-#endif
zend_bailout();
} else {
-#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle->filename);
-#else
- zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle->filename TSRMLS_CC);
-#endif
}
return NULL;
}
@@ -1332,11 +1308,10 @@ static zend_persistent_script *compile_and_cache_file(zend_file_handle *file_han
/* check blacklist right after ensuring that file was opened */
if (file_handle->opened_path && zend_accel_blacklist_is_blacklisted(&accel_blacklist, file_handle->opened_path)) {
ZCSG(blacklist_misses)++;
- *op_array_p = accelerator_orig_compile_file(file_handle, type TSRMLS_CC);
+ *op_array_p = accelerator_orig_compile_file(file_handle, type);
return NULL;
}
-#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
if (file_handle->type == ZEND_HANDLE_STREAM &&
(!strstr(file_handle->filename, ".phar") ||
strstr(file_handle->filename, "://"))) {
@@ -1346,12 +1321,11 @@ static zend_persistent_script *compile_and_cache_file(zend_file_handle *file_han
/* Stream callbacks needs to be called in context of original
* function and class tables (see: https://bugs.php.net/bug.php?id=64353)
*/
- if (zend_stream_fixup(file_handle, &buf, &size TSRMLS_CC) == FAILURE) {
+ if (zend_stream_fixup(file_handle, &buf, &size) == FAILURE) {
*op_array_p = NULL;
return NULL;
}
}
-#endif
if (ZCG(accel_directives).validate_timestamps ||
ZCG(accel_directives).file_update_protection ||
@@ -1361,26 +1335,26 @@ static zend_persistent_script *compile_and_cache_file(zend_file_handle *file_han
/* Obtain the file timestamps, *before* actually compiling them,
* otherwise we have a race-condition.
*/
- timestamp = zend_get_file_handle_timestamp(file_handle, ZCG(accel_directives).max_file_size > 0 ? &size : NULL TSRMLS_CC);
+ timestamp = zend_get_file_handle_timestamp(file_handle, ZCG(accel_directives).max_file_size > 0 ? &size : NULL);
/* If we can't obtain a timestamp (that means file is possibly socket)
* we won't cache it
*/
if (timestamp == 0) {
- *op_array_p = accelerator_orig_compile_file(file_handle, type TSRMLS_CC);
+ *op_array_p = accelerator_orig_compile_file(file_handle, type);
return NULL;
}
/* check if file is too new (may be it's not written completely yet) */
if (ZCG(accel_directives).file_update_protection &&
(ZCG(request_time) - ZCG(accel_directives).file_update_protection < timestamp)) {
- *op_array_p = accelerator_orig_compile_file(file_handle, type TSRMLS_CC);
+ *op_array_p = accelerator_orig_compile_file(file_handle, type);
return NULL;
}
if (ZCG(accel_directives).max_file_size > 0 && size > (size_t)ZCG(accel_directives).max_file_size) {
ZCSG(blacklist_misses)++;
- *op_array_p = accelerator_orig_compile_file(file_handle, type TSRMLS_CC);
+ *op_array_p = accelerator_orig_compile_file(file_handle, type);
return NULL;
}
}
@@ -1391,31 +1365,25 @@ static zend_persistent_script *compile_and_cache_file(zend_file_handle *file_han
orig_active_op_array = CG(active_op_array);
orig_function_table = CG(function_table);
orig_class_table = CG(class_table);
- orig_user_error_handler = EG(user_error_handler);
+ ZVAL_COPY_VALUE(&orig_user_error_handler, &EG(user_error_handler));
/* Override them with ours */
CG(function_table) = &ZCG(function_table);
EG(class_table) = CG(class_table) = &new_persistent_script->class_table;
- EG(user_error_handler) = NULL;
+ ZVAL_UNDEF(&EG(user_error_handler));
zend_try {
-#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
orig_compiler_options = CG(compiler_options);
CG(compiler_options) |= ZEND_COMPILE_HANDLE_OP_ARRAY;
CG(compiler_options) |= ZEND_COMPILE_IGNORE_INTERNAL_CLASSES;
CG(compiler_options) |= ZEND_COMPILE_DELAYED_BINDING;
CG(compiler_options) |= ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION;
-#endif
- op_array = *op_array_p = accelerator_orig_compile_file(file_handle, type TSRMLS_CC);
-#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
+ op_array = *op_array_p = accelerator_orig_compile_file(file_handle, type);
CG(compiler_options) = orig_compiler_options;
-#endif
} zend_catch {
op_array = NULL;
do_bailout = 1;
-#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
CG(compiler_options) = orig_compiler_options;
-#endif
} zend_end_try();
/* Restore originals */
@@ -1427,7 +1395,7 @@ static zend_persistent_script *compile_and_cache_file(zend_file_handle *file_han
if (!op_array) {
/* compilation failed */
free_persistent_script(new_persistent_script, 1);
- zend_accel_free_user_functions(&ZCG(function_table) TSRMLS_CC);
+ zend_accel_free_user_functions(&ZCG(function_table));
if (do_bailout) {
zend_bailout();
}
@@ -1438,24 +1406,18 @@ static zend_persistent_script *compile_and_cache_file(zend_file_handle *file_han
Here we aren't sure we would store it, but we will need it
further anyway.
*/
- zend_accel_move_user_functions(&ZCG(function_table), &new_persistent_script->function_table TSRMLS_CC);
+ zend_accel_move_user_functions(&ZCG(function_table), &new_persistent_script->function_table);
new_persistent_script->main_op_array = *op_array;
efree(op_array); /* we have valid persistent_script, so it's safe to free op_array */
/* Fill in the ping_auto_globals_mask for the new script. If jit for auto globals is enabled we
will have to ping the used auto global variables before execution */
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
if (PG(auto_globals_jit)) {
- new_persistent_script->ping_auto_globals_mask = zend_accel_get_auto_globals(TSRMLS_C);
+ new_persistent_script->ping_auto_globals_mask = zend_accel_get_auto_globals();
} else {
- new_persistent_script->ping_auto_globals_mask = zend_accel_get_auto_globals_no_jit(TSRMLS_C);
- }
-#else
- if ((PG(auto_globals_jit) && !PG(register_globals) && !PG(register_long_arrays))) {
- new_persistent_script->ping_auto_globals_mask = zend_accel_get_auto_globals(TSRMLS_C);
+ new_persistent_script->ping_auto_globals_mask = zend_accel_get_auto_globals_no_jit();
}
-#endif
if (ZCG(accel_directives).validate_timestamps) {
/* Obtain the file timestamps, *before* actually compiling them,
@@ -1466,20 +1428,18 @@ static zend_persistent_script *compile_and_cache_file(zend_file_handle *file_han
}
if (file_handle->opened_path) {
- new_persistent_script->full_path_len = strlen(file_handle->opened_path);
- new_persistent_script->full_path = estrndup(file_handle->opened_path, new_persistent_script->full_path_len);
+ new_persistent_script->full_path = zend_string_init(file_handle->opened_path, strlen(file_handle->opened_path), 0);
} else {
- new_persistent_script->full_path_len = strlen(file_handle->filename);
- new_persistent_script->full_path = estrndup(file_handle->filename, new_persistent_script->full_path_len);
+ new_persistent_script->full_path = zend_string_init(file_handle->filename, strlen(file_handle->filename), 0);
}
- new_persistent_script->hash_value = zend_hash_func(new_persistent_script->full_path, new_persistent_script->full_path_len + 1);
+ zend_string_hash_val(new_persistent_script->full_path);
/* Now persistent_script structure is ready in process memory */
- return cache_script_in_shared_memory(new_persistent_script, key, key_length, from_shared_memory TSRMLS_CC);
+ return cache_script_in_shared_memory(new_persistent_script, key, key_length, from_shared_memory);
}
/* zend_compile() replacement */
-zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type TSRMLS_DC)
+zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type)
{
zend_persistent_script *persistent_script = NULL;
char *key = NULL;
@@ -1489,12 +1449,11 @@ zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type T
if (!file_handle->filename ||
!ZCG(enabled) || !accel_startup_ok ||
(!ZCG(counted) && !ZCSG(accelerator_enabled)) ||
- CG(interactive) ||
- (ZCSG(restart_in_progress) && accel_restart_is_active(TSRMLS_C)) ||
- (is_stream_path(file_handle->filename) &&
+ (ZCSG(restart_in_progress) && accel_restart_is_active()) ||
+ (is_stream_path(file_handle->filename) &&
!is_cacheable_stream_path(file_handle->filename))) {
/* The Accelerator is disabled, act as if without the Accelerator */
- return accelerator_orig_compile_file(file_handle, type TSRMLS_CC);
+ return accelerator_orig_compile_file(file_handle, type);
}
/* Make sure we only increase the currently running processes semaphore
@@ -1503,28 +1462,25 @@ zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type T
*/
if (!ZCG(counted)) {
ZCG(counted) = 1;
- accel_activate_add(TSRMLS_C);
+ accel_activate_add();
}
/* In case this callback is called from include_once, require_once or it's
* a main FastCGI request, the key must be already calculated, and cached
* persistent script already found */
- if ((EG(opline_ptr) == NULL &&
+ if ((EG(current_execute_data) == NULL &&
ZCG(cache_opline) == NULL &&
file_handle->filename == SG(request_info).path_translated &&
ZCG(cache_persistent_script)) ||
- (EG(opline_ptr) && *EG(opline_ptr) &&
- *EG(opline_ptr) == ZCG(cache_opline) &&
- (*EG(opline_ptr))->opcode == ZEND_INCLUDE_OR_EVAL &&
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
- ((*EG(opline_ptr))->extended_value == ZEND_INCLUDE_ONCE ||
- (*EG(opline_ptr))->extended_value == ZEND_REQUIRE_ONCE))) {
-#else
- ((*EG(opline_ptr))->op2.u.constant.value.lval == ZEND_INCLUDE_ONCE ||
- (*EG(opline_ptr))->op2.u.constant.value.lval == ZEND_REQUIRE_ONCE))) {
-#endif
+ (EG(current_execute_data) &&
+ EG(current_execute_data)->func &&
+ ZEND_USER_CODE(EG(current_execute_data)->func->common.type) &&
+ EG(current_execute_data)->opline == ZCG(cache_opline) &&
+ EG(current_execute_data)->opline->opcode == ZEND_INCLUDE_OR_EVAL &&
+ (EG(current_execute_data)->opline->extended_value == ZEND_INCLUDE_ONCE ||
+ EG(current_execute_data)->opline->extended_value == ZEND_REQUIRE_ONCE))) {
if (!ZCG(key_len)) {
- return accelerator_orig_compile_file(file_handle, type TSRMLS_CC);
+ return accelerator_orig_compile_file(file_handle, type);
}
/* persistent script was already found by overridden open() or
* resolve_path() callbacks */
@@ -1533,48 +1489,36 @@ zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type T
key_length = ZCG(key_len);
} else {
/* try to find cached script by key */
- if ((key = accel_make_persistent_key(file_handle, &key_length TSRMLS_CC)) == NULL) {
- return accelerator_orig_compile_file(file_handle, type TSRMLS_CC);
+ if ((key = accel_make_persistent_key(file_handle, &key_length)) == NULL) {
+ return accelerator_orig_compile_file(file_handle, type);
}
- persistent_script = zend_accel_hash_find(&ZCSG(hash), key, key_length + 1);
+ persistent_script = zend_accel_hash_find(&ZCSG(hash), key, key_length);
if (!persistent_script) {
/* try to find cached script by full real path */
zend_accel_hash_entry *bucket;
/* open file to resolve the path */
if (file_handle->type == ZEND_HANDLE_FILENAME &&
-#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
- accelerator_orig_zend_stream_open_function(file_handle->filename, file_handle TSRMLS_CC) == FAILURE) {
-#else
- zend_stream_open(file_handle->filename, file_handle TSRMLS_CC) == FAILURE) {
-#endif
+ accelerator_orig_zend_stream_open_function(file_handle->filename, file_handle) == FAILURE) {
if (type == ZEND_REQUIRE) {
-#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename);
-#else
- zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename TSRMLS_CC);
-#endif
zend_bailout();
} else {
-#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle->filename);
-#else
- zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle->filename TSRMLS_CC);
-#endif
}
return NULL;
}
if (file_handle->opened_path &&
- (bucket = zend_accel_hash_find_entry(&ZCSG(hash), file_handle->opened_path, strlen(file_handle->opened_path) + 1)) != NULL) {
+ (bucket = zend_accel_hash_find_entry(&ZCSG(hash), file_handle->opened_path, strlen(file_handle->opened_path))) != NULL) {
persistent_script = (zend_persistent_script *)bucket->data;
if (!ZCG(accel_directives).revalidate_path &&
!persistent_script->corrupted) {
SHM_UNPROTECT();
- zend_shared_alloc_lock(TSRMLS_C);
- zend_accel_add_key(key, key_length, bucket TSRMLS_CC);
- zend_shared_alloc_unlock(TSRMLS_C);
+ zend_shared_alloc_lock();
+ zend_accel_add_key(key, key_length, bucket);
+ zend_shared_alloc_unlock();
SHM_PROTECT();
}
}
@@ -1593,8 +1537,8 @@ zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type T
/* If script is found then validate_timestamps if option is enabled */
if (persistent_script && ZCG(accel_directives).validate_timestamps) {
- if (validate_timestamp_and_record(persistent_script, file_handle TSRMLS_CC) == FAILURE) {
- zend_shared_alloc_lock(TSRMLS_C);
+ if (validate_timestamp_and_record(persistent_script, file_handle) == FAILURE) {
+ zend_shared_alloc_lock();
if (!persistent_script->corrupted) {
persistent_script->corrupted = 1;
persistent_script->timestamp = 0;
@@ -1602,10 +1546,10 @@ zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type T
if (ZSMMG(memory_exhausted)) {
zend_accel_restart_reason reason =
zend_accel_hash_is_full(&ZCSG(hash)) ? ACCEL_RESTART_HASH : ACCEL_RESTART_OOM;
- zend_accel_schedule_restart_if_necessary(reason TSRMLS_CC);
+ zend_accel_schedule_restart_if_necessary(reason);
}
}
- zend_shared_alloc_unlock(TSRMLS_C);
+ zend_shared_alloc_unlock();
persistent_script = NULL;
}
}
@@ -1619,7 +1563,7 @@ zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type T
/* The checksum is wrong */
zend_accel_error(ACCEL_LOG_INFO, "Checksum failed for '%s': expected=0x%0.8X, found=0x%0.8X",
persistent_script->full_path, persistent_script->dynamic_members.checksum, checksum);
- zend_shared_alloc_lock(TSRMLS_C);
+ zend_shared_alloc_lock();
if (!persistent_script->corrupted) {
persistent_script->corrupted = 1;
persistent_script->timestamp = 0;
@@ -1627,16 +1571,17 @@ zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type T
if (ZSMMG(memory_exhausted)) {
zend_accel_restart_reason reason =
zend_accel_hash_is_full(&ZCSG(hash)) ? ACCEL_RESTART_HASH : ACCEL_RESTART_OOM;
- zend_accel_schedule_restart_if_necessary(reason TSRMLS_CC);
+ zend_accel_schedule_restart_if_necessary(reason);
}
}
- zend_shared_alloc_unlock(TSRMLS_C);
+ zend_shared_alloc_unlock();
persistent_script = NULL;
}
}
/* If script was not found or invalidated by validate_timestamps */
if (!persistent_script) {
+ uint32_t old_const_num = zend_hash_next_free_element(EG(zend_constants));
zend_op_array *op_array;
/* Cache miss.. */
@@ -1645,14 +1590,14 @@ zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type T
/* No memory left. Behave like without the Accelerator */
if (ZSMMG(memory_exhausted) || ZCSG(restart_pending)) {
SHM_PROTECT();
- return accelerator_orig_compile_file(file_handle, type TSRMLS_CC);
+ return accelerator_orig_compile_file(file_handle, type);
}
/* Try and cache the script and assume that it is returned from_shared_memory.
* If it isn't compile_and_cache_file() changes the flag to 0
*/
from_shared_memory = 0;
- persistent_script = compile_and_cache_file(file_handle, type, key, key_length, &op_array, &from_shared_memory TSRMLS_CC);
+ persistent_script = compile_and_cache_file(file_handle, type, key, key_length, &op_array, &from_shared_memory);
/* Caching is disabled, returning op_array;
* or something went wrong during compilation, returning NULL
@@ -1661,48 +1606,47 @@ zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type T
SHM_PROTECT();
return op_array;
}
+ if (from_shared_memory) {
+ /* Delete immutable arrays moved into SHM */
+ uint32_t new_const_num = zend_hash_next_free_element(EG(zend_constants));
+ while (new_const_num > old_const_num) {
+ new_const_num--;
+ zend_hash_index_del(EG(zend_constants), new_const_num);
+ }
+ }
} else {
#if !ZEND_WIN32
ZCSG(hits)++; /* TBFixed: may lose one hit */
persistent_script->dynamic_members.hits++; /* see above */
#else
- InterlockedIncrement(&ZCSG(hits));
- InterlockedIncrement(&persistent_script->dynamic_members.hits);
+ INCREMENT(hits);
+ InterlockedIncrement64(&persistent_script->dynamic_members.hits);
#endif
/* see bug #15471 (old BTS) */
if (persistent_script->full_path) {
- if (!EG(opline_ptr) || !*EG(opline_ptr) ||
- (*EG(opline_ptr))->opcode != ZEND_INCLUDE_OR_EVAL ||
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
- ((*EG(opline_ptr))->extended_value != ZEND_INCLUDE_ONCE &&
- (*EG(opline_ptr))->extended_value != ZEND_REQUIRE_ONCE)) {
-#else
- ((*EG(opline_ptr))->op2.u.constant.value.lval != ZEND_INCLUDE_ONCE &&
- (*EG(opline_ptr))->op2.u.constant.value.lval != ZEND_REQUIRE_ONCE)) {
-#endif
- void *dummy = (void *) 1;
-
- if (zend_hash_quick_add(&EG(included_files), persistent_script->full_path, persistent_script->full_path_len + 1, persistent_script->hash_value, &dummy, sizeof(void *), NULL) == SUCCESS) {
+ if (!EG(current_execute_data) || !EG(current_execute_data)->opline ||
+ !EG(current_execute_data)->func ||
+ !ZEND_USER_CODE(EG(current_execute_data)->func->common.type) ||
+ EG(current_execute_data)->opline->opcode != ZEND_INCLUDE_OR_EVAL ||
+ (EG(current_execute_data)->opline->extended_value != ZEND_INCLUDE_ONCE &&
+ EG(current_execute_data)->opline->extended_value != ZEND_REQUIRE_ONCE)) {
+ if (zend_hash_add_empty_element(&EG(included_files), persistent_script->full_path) != NULL) {
/* ext/phar has to load phar's metadata into memory */
- if (strstr(persistent_script->full_path, ".phar") && !strstr(persistent_script->full_path, "://")) {
+ if (strstr(persistent_script->full_path->val, ".phar") && !strstr(persistent_script->full_path->val, "://")) {
php_stream_statbuf ssb;
- char *fname = emalloc(sizeof("phar://") + persistent_script->full_path_len);
+ char *fname = emalloc(sizeof("phar://") + persistent_script->full_path->len);
memcpy(fname, "phar://", sizeof("phar://") - 1);
- memcpy(fname + sizeof("phar://") - 1, persistent_script->full_path, persistent_script->full_path_len + 1);
+ memcpy(fname + sizeof("phar://") - 1, persistent_script->full_path->val, persistent_script->full_path->len + 1);
php_stream_stat_path(fname, &ssb);
efree(fname);
}
}
}
}
-#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
zend_file_handle_dtor(file_handle);
-#else
- zend_file_handle_dtor(file_handle TSRMLS_CC);
-#endif
from_shared_memory = 1;
}
@@ -1712,239 +1656,28 @@ zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type T
/* Fetch jit auto globals used in the script before execution */
if (persistent_script->ping_auto_globals_mask) {
- zend_accel_set_auto_globals(persistent_script->ping_auto_globals_mask TSRMLS_CC);
+ zend_accel_set_auto_globals(persistent_script->ping_auto_globals_mask);
}
- return zend_accel_load_script(persistent_script, from_shared_memory TSRMLS_CC);
+ return zend_accel_load_script(persistent_script, from_shared_memory);
}
-#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
-
-/* Taken from php-5.2.5 because early versions don't have correct version */
-static char *accel_tsrm_realpath(const char *path, int path_len TSRMLS_DC)
-{
- cwd_state new_state;
- char *real_path;
- char *cwd;
- int cwd_len;
-
- /* realpath("") returns CWD */
- if (!*path) {
- new_state.cwd = (char*)malloc(1);
- if (!new_state.cwd) {
- zend_accel_error(ACCEL_LOG_ERROR, "malloc() failed");
- return NULL;
- }
- new_state.cwd[0] = '\0';
- new_state.cwd_length = 0;
- if ((cwd = accel_getcwd(&cwd_len TSRMLS_CC)) != NULL) {
- path = cwd;
- }
- } else if (!IS_ABSOLUTE_PATH(path, path_len) &&
- (cwd = accel_getcwd(&cwd_len TSRMLS_CC)) != NULL) {
- new_state.cwd = zend_strndup(cwd, cwd_len);
- if (!new_state.cwd) {
- zend_accel_error(ACCEL_LOG_ERROR, "malloc() failed");
- return NULL;
- }
- new_state.cwd_length = cwd_len;
- } else {
- new_state.cwd = (char*)malloc(1);
- if (!new_state.cwd) {
- zend_accel_error(ACCEL_LOG_ERROR, "malloc() failed");
- return NULL;
- }
- new_state.cwd[0] = '\0';
- new_state.cwd_length = 0;
- }
-
-#ifndef CWD_REALPATH
-# define CWD_REALPATH 2
-#endif
- if (virtual_file_ex(&new_state, path, NULL, CWD_REALPATH)) {
- free(new_state.cwd);
- return NULL;
- }
-
- real_path = emalloc(new_state.cwd_length + 1);
- memcpy(real_path, new_state.cwd, new_state.cwd_length + 1);
- free(new_state.cwd);
- return real_path;
-}
-
-static char *accel_php_resolve_path(const char *filename, int filename_length, const char *path TSRMLS_DC)
-{
- char *resolved_path;
- char trypath[MAXPATHLEN];
- const char *ptr, *end;
- int len;
-
- if (!filename) {
- return NULL;
- }
-
- if (*filename == '.' ||
- IS_ABSOLUTE_PATH(filename, filename_length) ||
- !path ||
- !*path) {
- return accel_tsrm_realpath(filename, filename_length TSRMLS_CC);
- }
-
- ptr = path;
- while (*ptr) {
- for (end = ptr; *end && *end != DEFAULT_DIR_SEPARATOR; end++);
- len = end - ptr;
- if (*end) end++;
- if (len + 1 + filename_length + 1 >= MAXPATHLEN) {
- ptr = end;
- continue;
- }
- memcpy(trypath, ptr, len);
- trypath[len] = '/';
- memcpy(trypath + len + 1, filename, filename_length + 1);
- ptr = end;
- if ((resolved_path = accel_tsrm_realpath(trypath, len + 1 + filename_length TSRMLS_CC)) != NULL) {
- return resolved_path;
- }
- } /* end provided path */
-
- /* check in calling scripts' current working directory as a fall back case
- */
- if (EG(in_execution)) {
- char *exec_fname = zend_get_executed_filename(TSRMLS_C);
- int exec_fname_length = strlen(exec_fname);
-
- while ((--exec_fname_length >= 0) && !IS_SLASH(exec_fname[exec_fname_length]));
- if (exec_fname && exec_fname[0] != '[' &&
- exec_fname_length > 0 &&
- exec_fname_length + 1 + filename_length + 1 < MAXPATHLEN) {
- memcpy(trypath, exec_fname, exec_fname_length + 1);
- memcpy(trypath + exec_fname_length + 1, filename, filename_length + 1);
- return accel_tsrm_realpath(trypath, exec_fname_length + 1 + filename_length TSRMLS_CC);
- }
- }
-
- return NULL;
-}
-
-/* zend_stream_open_function() replacement for PHP 5.2 */
-static int persistent_stream_open_function(const char *filename, zend_file_handle *handle TSRMLS_DC)
-{
- if (ZCG(enabled) && accel_startup_ok &&
- (ZCG(counted) || ZCSG(accelerator_enabled)) &&
- !CG(interactive) &&
- !ZCSG(restart_in_progress)) {
-
- if (EG(opline_ptr) && *EG(opline_ptr)) {
- zend_op *opline = *EG(opline_ptr);
-
- if (opline->opcode == ZEND_INCLUDE_OR_EVAL &&
- (opline->op2.u.constant.value.lval == ZEND_INCLUDE_ONCE ||
- opline->op2.u.constant.value.lval == ZEND_REQUIRE_ONCE)) {
- /* we are in include_once */
- char *key = NULL;
- int key_length;
- char *resolved_path;
- zend_accel_hash_entry *bucket;
- zend_persistent_script *persistent_script;
- int filename_len;
-
- if (opline->op1.op_type == IS_CONST) {
- filename_len = Z_STRLEN(opline->op1.u.constant);
- } else {
- filename_len = strlen(filename);
- }
- handle->filename = (char*)filename;
- handle->free_filename = 0;
- handle->opened_path = NULL;
-
- /* Check if requested file already cached (by full name) */
- if (IS_ABSOLUTE_PATH(filename, filename_len) &&
- (persistent_script = zend_accel_hash_find(&ZCSG(hash), (char*)filename, filename_len + 1)) != NULL &&
- !persistent_script->corrupted) {
-
- handle->opened_path = estrndup(persistent_script->full_path, persistent_script->full_path_len);
- handle->type = ZEND_HANDLE_FILENAME;
- memcpy(ZCG(key), persistent_script->full_path, persistent_script->full_path_len + 1);
- ZCG(key_len) = persistent_script->full_path_len;
- ZCG(cache_opline) = opline;
- ZCG(cache_persistent_script) = persistent_script;
- return SUCCESS;
- }
-
- /* Check if requested file already cached (by key) */
- key = accel_make_persistent_key_ex(handle, filename_len, &key_length TSRMLS_CC);
- if (!ZCG(accel_directives).revalidate_path &&
- key &&
- (persistent_script = zend_accel_hash_find(&ZCSG(hash), key, key_length + 1)) != NULL &&
- !persistent_script->corrupted) {
-
- handle->opened_path = estrndup(persistent_script->full_path, persistent_script->full_path_len);
- handle->type = ZEND_HANDLE_FILENAME;
- ZCG(cache_opline) = opline;
- ZCG(cache_persistent_script) = persistent_script;
- return SUCCESS;
- }
-
- /* find the full real path */
- resolved_path = accel_php_resolve_path(filename, filename_len, ZCG(include_path) TSRMLS_CC);
-
- /* Check if requested file already cached (by real name) */
- if (resolved_path &&
- (bucket = zend_accel_hash_find_entry(&ZCSG(hash), resolved_path, strlen(resolved_path) + 1)) != NULL) {
-
- persistent_script = (zend_persistent_script *)bucket->data;
- if (persistent_script && !persistent_script->corrupted) {
- handle->opened_path = resolved_path;
- handle->type = ZEND_HANDLE_FILENAME;
- if (key && !ZCG(accel_directives).revalidate_path) {
- /* add another "key" for the same bucket */
- SHM_UNPROTECT();
- zend_shared_alloc_lock(TSRMLS_C);
- zend_accel_add_key(key, key_length, bucket TSRMLS_CC);
- zend_shared_alloc_unlock(TSRMLS_C);
- SHM_PROTECT();
- }
- ZCG(cache_opline) = opline;
- ZCG(cache_persistent_script) = persistent_script;
- return SUCCESS;
- }
- }
- if (resolved_path) {
- efree(resolved_path);
- }
- }
- }
- }
- ZCG(cache_opline) = NULL;
- ZCG(cache_persistent_script) = NULL;
- return accelerator_orig_zend_stream_open_function(filename, handle TSRMLS_CC);
-}
-
-#else
-
/* zend_stream_open_function() replacement for PHP 5.3 and above */
-static int persistent_stream_open_function(const char *filename, zend_file_handle *handle TSRMLS_DC)
+static int persistent_stream_open_function(const char *filename, zend_file_handle *handle)
{
if (ZCG(enabled) && accel_startup_ok &&
(ZCG(counted) || ZCSG(accelerator_enabled)) &&
- !CG(interactive) &&
!ZCSG(restart_in_progress)) {
/* check if callback is called from include_once or it's a main request */
- if ((!EG(opline_ptr) &&
+ if ((!EG(current_execute_data) &&
filename == SG(request_info).path_translated) ||
- (EG(opline_ptr) &&
- *EG(opline_ptr) &&
- (*EG(opline_ptr))->opcode == ZEND_INCLUDE_OR_EVAL &&
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
- ((*EG(opline_ptr))->extended_value == ZEND_INCLUDE_ONCE ||
- (*EG(opline_ptr))->extended_value == ZEND_REQUIRE_ONCE))) {
-#else
- ((*EG(opline_ptr))->op2.u.constant.value.lval == ZEND_INCLUDE_ONCE ||
- (*EG(opline_ptr))->op2.u.constant.value.lval == ZEND_REQUIRE_ONCE))) {
-#endif
-
+ (EG(current_execute_data) &&
+ EG(current_execute_data)->func &&
+ ZEND_USER_CODE(EG(current_execute_data)->func->common.type) &&
+ EG(current_execute_data)->opline->opcode == ZEND_INCLUDE_OR_EVAL &&
+ (EG(current_execute_data)->opline->extended_value == ZEND_INCLUDE_ONCE ||
+ EG(current_execute_data)->opline->extended_value == ZEND_REQUIRE_ONCE))) {
/* we are in include_once or FastCGI request */
zend_persistent_script *persistent_script;
@@ -1952,13 +1685,13 @@ static int persistent_stream_open_function(const char *filename, zend_file_handl
handle->free_filename = 0;
/* check if cached script was already found by resolve_path() */
- if ((EG(opline_ptr) == NULL &&
+ if ((EG(current_execute_data) == NULL &&
ZCG(cache_opline) == NULL &&
ZCG(cache_persistent_script) != NULL) ||
- (EG(opline_ptr) &&
- (ZCG(cache_opline) == *EG(opline_ptr)))) {
+ (EG(current_execute_data) &&
+ (ZCG(cache_opline) == EG(current_execute_data)->opline))) {
persistent_script = ZCG(cache_persistent_script);
- handle->opened_path = estrndup(persistent_script->full_path, persistent_script->full_path_len);
+ handle->opened_path = estrndup(persistent_script->full_path->val, persistent_script->full_path->len);
handle->type = ZEND_HANDLE_FILENAME;
return SUCCESS;
#if 0
@@ -1968,15 +1701,15 @@ static int persistent_stream_open_function(const char *filename, zend_file_handl
if ((IS_ABSOLUTE_PATH(filename, filename_len) ||
is_stream_path(filename)) &&
- (persistent_script = zend_accel_hash_find(&ZCSG(hash), (char*)filename, filename_len + 1)) != NULL &&
+ (persistent_script = zend_accel_hash_find(&ZCSG(hash), (char*)filename, filename_len)) != NULL &&
!persistent_script->corrupted) {
handle->opened_path = estrndup(persistent_script->full_path, persistent_script->full_path_len);
handle->type = ZEND_HANDLE_FILENAME;
memcpy(ZCG(key), persistent_script->full_path, persistent_script->full_path_len + 1);
ZCG(key_len) = persistent_script->full_path_len;
- ZCG(cache_opline) = EG(opline_ptr) ? *EG(opline_ptr) : NULL;
- ZCG(cache_persistent_script) = EG(opline_ptr) ? persistent_script : NULL;
+ ZCG(cache_opline) = EG(current_execute_data) ? EG(current_execute_data)->opline : NULL;
+ ZCG(cache_persistent_script) = EG(current_execute_data) ? persistent_script : NULL;
return SUCCESS;
}
#endif
@@ -1985,31 +1718,25 @@ static int persistent_stream_open_function(const char *filename, zend_file_handl
}
ZCG(cache_opline) = NULL;
ZCG(cache_persistent_script) = NULL;
- return accelerator_orig_zend_stream_open_function(filename, handle TSRMLS_CC);
+ return accelerator_orig_zend_stream_open_function(filename, handle);
}
/* zend_resolve_path() replacement for PHP 5.3 and above */
-static char* persistent_zend_resolve_path(const char *filename, int filename_len TSRMLS_DC)
+static char* persistent_zend_resolve_path(const char *filename, int filename_len)
{
if (ZCG(enabled) && accel_startup_ok &&
(ZCG(counted) || ZCSG(accelerator_enabled)) &&
- !CG(interactive) &&
!ZCSG(restart_in_progress)) {
/* check if callback is called from include_once or it's a main request */
- if ((!EG(opline_ptr) &&
+ if ((!EG(current_execute_data) &&
filename == SG(request_info).path_translated) ||
- (EG(opline_ptr) &&
- *EG(opline_ptr) &&
- (*EG(opline_ptr))->opcode == ZEND_INCLUDE_OR_EVAL &&
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
- ((*EG(opline_ptr))->extended_value == ZEND_INCLUDE_ONCE ||
- (*EG(opline_ptr))->extended_value == ZEND_REQUIRE_ONCE))) {
-#else
- ((*EG(opline_ptr))->op2.u.constant.value.lval == ZEND_INCLUDE_ONCE ||
- (*EG(opline_ptr))->op2.u.constant.value.lval == ZEND_REQUIRE_ONCE))) {
-#endif
-
+ (EG(current_execute_data) &&
+ EG(current_execute_data)->func &&
+ ZEND_USER_CODE(EG(current_execute_data)->func->common.type) &&
+ EG(current_execute_data)->opline->opcode == ZEND_INCLUDE_OR_EVAL &&
+ (EG(current_execute_data)->opline->extended_value == ZEND_INCLUDE_ONCE ||
+ EG(current_execute_data)->opline->extended_value == ZEND_REQUIRE_ONCE))) {
/* we are in include_once or FastCGI request */
zend_file_handle handle;
char *key = NULL;
@@ -2021,14 +1748,14 @@ static char* persistent_zend_resolve_path(const char *filename, int filename_len
/* Check if requested file already cached (by full name) */
if ((IS_ABSOLUTE_PATH(filename, filename_len) ||
is_stream_path(filename)) &&
- (bucket = zend_accel_hash_find_entry(&ZCSG(hash), (char*)filename, filename_len + 1)) != NULL) {
+ (bucket = zend_accel_hash_find_entry(&ZCSG(hash), (char*)filename, filename_len)) != NULL) {
persistent_script = (zend_persistent_script *)bucket->data;
if (persistent_script && !persistent_script->corrupted) {
- memcpy(ZCG(key), persistent_script->full_path, persistent_script->full_path_len + 1);
- ZCG(key_len) = persistent_script->full_path_len;
- ZCG(cache_opline) = EG(opline_ptr) ? *EG(opline_ptr) : NULL;
+ memcpy(ZCG(key), persistent_script->full_path->val, persistent_script->full_path->len + 1);
+ ZCG(key_len) = persistent_script->full_path->len;
+ ZCG(cache_opline) = EG(current_execute_data) ? EG(current_execute_data)->opline : NULL;
ZCG(cache_persistent_script) = persistent_script;
- return estrndup(persistent_script->full_path, persistent_script->full_path_len);
+ return estrndup(persistent_script->full_path->val, persistent_script->full_path->len);
}
}
@@ -2036,36 +1763,36 @@ static char* persistent_zend_resolve_path(const char *filename, int filename_len
handle.filename = (char*)filename;
handle.free_filename = 0;
handle.opened_path = NULL;
- key = accel_make_persistent_key_ex(&handle, filename_len, &key_length TSRMLS_CC);
+ key = accel_make_persistent_key_ex(&handle, filename_len, &key_length);
if (!ZCG(accel_directives).revalidate_path &&
key &&
- (persistent_script = zend_accel_hash_find(&ZCSG(hash), key, key_length + 1)) != NULL &&
+ (persistent_script = zend_accel_hash_find(&ZCSG(hash), key, key_length)) != NULL &&
!persistent_script->corrupted) {
/* we have persistent script */
- ZCG(cache_opline) = EG(opline_ptr) ? *EG(opline_ptr) : NULL;
+ ZCG(cache_opline) = EG(current_execute_data) ? EG(current_execute_data)->opline : NULL;
ZCG(cache_persistent_script) = persistent_script;
- return estrndup(persistent_script->full_path, persistent_script->full_path_len);
+ return estrndup(persistent_script->full_path->val, persistent_script->full_path->len);
}
/* find the full real path */
- resolved_path = accelerator_orig_zend_resolve_path(filename, filename_len TSRMLS_CC);
+ resolved_path = accelerator_orig_zend_resolve_path(filename, filename_len);
/* Check if requested file already cached (by real path) */
if (resolved_path &&
- (bucket = zend_accel_hash_find_entry(&ZCSG(hash), resolved_path, strlen(resolved_path) + 1)) != NULL) {
+ (bucket = zend_accel_hash_find_entry(&ZCSG(hash), resolved_path, strlen(resolved_path))) != NULL) {
persistent_script = (zend_persistent_script *)bucket->data;
if (persistent_script && !persistent_script->corrupted) {
if (key && !ZCG(accel_directives).revalidate_path) {
/* add another "key" for the same bucket */
SHM_UNPROTECT();
- zend_shared_alloc_lock(TSRMLS_C);
- zend_accel_add_key(key, key_length, bucket TSRMLS_CC);
- zend_shared_alloc_unlock(TSRMLS_C);
+ zend_shared_alloc_lock();
+ zend_accel_add_key(key, key_length, bucket);
+ zend_shared_alloc_unlock();
SHM_PROTECT();
}
- ZCG(cache_opline) = (EG(opline_ptr) && key) ? *EG(opline_ptr): NULL;
+ ZCG(cache_opline) = (EG(current_execute_data) && key) ? EG(current_execute_data)->opline : NULL;
ZCG(cache_persistent_script) = key ? persistent_script : NULL;
return resolved_path;
}
@@ -2077,12 +1804,10 @@ static char* persistent_zend_resolve_path(const char *filename, int filename_len
}
ZCG(cache_opline) = NULL;
ZCG(cache_persistent_script) = NULL;
- return accelerator_orig_zend_resolve_path(filename, filename_len TSRMLS_CC);
+ return accelerator_orig_zend_resolve_path(filename, filename_len);
}
-#endif
-
-static void zend_reset_cache_vars(TSRMLS_D)
+static void zend_reset_cache_vars(void)
{
ZSMMG(memory_exhausted) = 0;
ZCSG(hits) = 0;
@@ -2095,7 +1820,6 @@ static void zend_reset_cache_vars(TSRMLS_D)
static void accel_activate(void)
{
- TSRMLS_FETCH();
if (!ZCG(enabled) || !accel_startup_ok) {
return;
@@ -2103,7 +1827,8 @@ static void accel_activate(void)
SHM_UNPROTECT();
/* PHP-5.4 and above return "double", but we use 1 sec precision */
- ZCG(request_time) = (time_t)sapi_get_request_time(TSRMLS_C);
+ ZCG(auto_globals_mask) = 0;
+ ZCG(request_time) = (time_t)sapi_get_request_time();
ZCG(cache_opline) = NULL;
ZCG(cache_persistent_script) = NULL;
ZCG(include_path_check) = !ZCG(include_path_key);
@@ -2114,14 +1839,14 @@ static void accel_activate(void)
#else
zend_accel_error(ACCEL_LOG_WARNING, "Stuck count for pid %d", getpid());
#endif
- accel_unlock_all(TSRMLS_C);
+ accel_unlock_all();
ZCG(counted) = 0;
}
if (ZCSG(restart_pending)) {
- zend_shared_alloc_lock(TSRMLS_C);
+ zend_shared_alloc_lock();
if (ZCSG(restart_pending) != 0) { /* check again, to ensure that the cache wasn't already cleaned by another process */
- if (accel_is_inactive(TSRMLS_C) == SUCCESS) {
+ if (accel_is_inactive() == SUCCESS) {
zend_accel_error(ACCEL_LOG_DEBUG, "Restarting!");
ZCSG(restart_pending) = 0;
switch ZCSG(restart_reason) {
@@ -2135,9 +1860,9 @@ static void accel_activate(void)
ZCSG(manual_restarts)++;
break;
}
- accel_restart_enter(TSRMLS_C);
+ accel_restart_enter();
- zend_reset_cache_vars(TSRMLS_C);
+ zend_reset_cache_vars();
zend_accel_hash_clean(&ZCSG(hash));
/* include_paths keeps only the first path */
@@ -2148,19 +1873,19 @@ static void accel_activate(void)
ZCSG(include_paths).hash_table[zend_inline_hash_func(ZCSG(include_paths).hash_entries[0].key, ZCSG(include_paths).hash_entries[0].key_length) % ZCSG(include_paths).max_num_entries] = &ZCSG(include_paths).hash_entries[0];
}
-#if (ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO) && !defined(ZTS)
+#if !defined(ZTS)
if (ZCG(accel_directives).interned_strings_buffer) {
- accel_interned_strings_restore_state(TSRMLS_C);
+ accel_interned_strings_restore_state();
}
#endif
zend_shared_alloc_restore_state();
ZCSG(accelerator_enabled) = ZCSG(cache_status_before_restart);
ZCSG(last_restart_time) = ZCG(request_time);
- accel_restart_leave(TSRMLS_C);
+ accel_restart_leave();
}
}
- zend_shared_alloc_unlock(TSRMLS_C);
+ zend_shared_alloc_unlock();
}
/* check if ZCG(function_table) wasn't somehow polluted on the way */
@@ -2181,65 +1906,50 @@ static void accel_activate(void)
* allocated block separately, but we like to call all the destructors and
* callbacks in exactly the same order.
*/
+static void accel_fast_zval_dtor(zval *zvalue);
static void accel_fast_hash_destroy(HashTable *ht)
{
- Bucket *p = ht->pListHead;
+ uint idx;
+ Bucket *p;
- while (p != NULL) {
- ht->pDestructor(p->pData);
- p = p->pListNext;
+ for (idx = 0; idx < ht->nNumUsed; idx++) {
+ p = ht->arData + idx;
+ if (Z_TYPE(p->val) == IS_UNDEF) continue;
+ accel_fast_zval_dtor(&p->val);
}
}
-static void accel_fast_zval_ptr_dtor(zval **zval_ptr)
+static void accel_fast_zval_dtor(zval *zvalue)
{
- zval *zvalue = *zval_ptr;
-
- if (Z_DELREF_P(zvalue) == 0) {
-#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
- switch (Z_TYPE_P(zvalue) & IS_CONSTANT_TYPE_MASK) {
-#else
- switch (Z_TYPE_P(zvalue) & ~IS_CONSTANT_INDEX) {
-#endif
-#if ZEND_EXTENSION_API_NO <= PHP_5_5_API_NO
- case IS_CONSTANT_ARRAY:
-#endif
+ if (Z_REFCOUNTED_P(zvalue) && Z_DELREF_P(zvalue) == 0) {
+ switch (Z_TYPE_P(zvalue)) {
case IS_ARRAY: {
- TSRMLS_FETCH();
-
-#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
- GC_REMOVE_ZVAL_FROM_BUFFER(zvalue);
-#endif
- if (zvalue->value.ht && (zvalue->value.ht != &EG(symbol_table))) {
+ GC_REMOVE_FROM_BUFFER(Z_ARR_P(zvalue));
+ if (Z_ARR_P(zvalue) != &EG(symbol_table)) {
/* break possible cycles */
- Z_TYPE_P(zvalue) = IS_NULL;
- zvalue->value.ht->pDestructor = (dtor_func_t)accel_fast_zval_ptr_dtor;
- accel_fast_hash_destroy(zvalue->value.ht);
+ ZVAL_NULL(zvalue);
+ accel_fast_hash_destroy(Z_ARRVAL_P(zvalue));
}
}
break;
case IS_OBJECT:
{
- TSRMLS_FETCH();
-#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
- GC_REMOVE_ZVAL_FROM_BUFFER(zvalue);
-#endif
- Z_OBJ_HT_P(zvalue)->del_ref(zvalue TSRMLS_CC);
+ OBJ_RELEASE(Z_OBJ_P(zvalue));
}
break;
case IS_RESOURCE:
{
- TSRMLS_FETCH();
/* destroy resource */
- zend_list_delete(zvalue->value.lval);
+ zend_list_delete(Z_RES_P(zvalue));
}
break;
case IS_LONG:
case IS_DOUBLE:
- case IS_BOOL:
+ case IS_FALSE:
+ case IS_TRUE:
case IS_NULL:
case IS_STRING:
case IS_CONSTANT:
@@ -2250,108 +1960,112 @@ static void accel_fast_zval_ptr_dtor(zval **zval_ptr)
}
}
-static int accel_clean_non_persistent_function(zend_function *function TSRMLS_DC)
+static int accel_clean_non_persistent_function(zval *zv)
{
+ zend_function *function = Z_PTR_P(zv);
+
if (function->type == ZEND_INTERNAL_FUNCTION) {
return ZEND_HASH_APPLY_STOP;
} else {
if (function->op_array.static_variables) {
- function->op_array.static_variables->pDestructor = (dtor_func_t)accel_fast_zval_ptr_dtor;
- accel_fast_hash_destroy(function->op_array.static_variables);
- function->op_array.static_variables = NULL;
- }
- return (--(*function->op_array.refcount) <= 0) ?
- ZEND_HASH_APPLY_REMOVE :
- ZEND_HASH_APPLY_KEEP;
- }
-}
-
-static int accel_cleanup_function_data(zend_function *function TSRMLS_DC)
-{
- if (function->type == ZEND_USER_FUNCTION) {
- if (function->op_array.static_variables) {
- function->op_array.static_variables->pDestructor = (dtor_func_t)accel_fast_zval_ptr_dtor;
accel_fast_hash_destroy(function->op_array.static_variables);
function->op_array.static_variables = NULL;
}
+ return ZEND_HASH_APPLY_REMOVE;
}
- return 0;
}
-static int accel_clean_non_persistent_class(zend_class_entry **pce TSRMLS_DC)
+static inline void zend_accel_fast_del_bucket(HashTable *ht, uint32_t idx, Bucket *p)
{
- zend_class_entry *ce = *pce;
-
- if (ce->type == ZEND_INTERNAL_CLASS) {
- return ZEND_HASH_APPLY_STOP;
- } else {
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
- if (ce->ce_flags & ZEND_HAS_STATIC_IN_METHODS) {
- zend_hash_apply(&ce->function_table, (apply_func_t) accel_cleanup_function_data TSRMLS_CC);
- }
- if (ce->static_members_table) {
- int i;
+ uint32_t nIndex = p->h & ht->nTableMask;
+ uint32_t i = ht->arHash[nIndex];
- for (i = 0; i < ce->default_static_members_count; i++) {
- if (ce->static_members_table[i]) {
- accel_fast_zval_ptr_dtor(&ce->static_members_table[i]);
- ce->static_members_table[i] = NULL;
- }
- }
- ce->static_members_table = NULL;
- }
-#else
- zend_hash_apply(&ce->function_table, (apply_func_t) accel_cleanup_function_data TSRMLS_CC);
- if (ce->static_members) {
- ce->static_members->pDestructor = (dtor_func_t)accel_fast_zval_ptr_dtor;
- accel_fast_hash_destroy(ce->static_members);
- ce->static_members = NULL;
+ ht->nNumUsed--;
+ ht->nNumOfElements--;
+ if (idx != i) {
+ Bucket *prev = ht->arData + i;
+ while (Z_NEXT(prev->val) != idx) {
+ i = Z_NEXT(prev->val);
+ prev = ht->arData + i;
}
-#endif
- return ZEND_HASH_APPLY_REMOVE;
- }
-}
-
-static int accel_clean_non_persistent_constant(zend_constant *c TSRMLS_DC)
-{
- if (c->flags & CONST_PERSISTENT) {
- return ZEND_HASH_APPLY_STOP;
- } else {
- interned_free(c->name);
- return ZEND_HASH_APPLY_REMOVE;
+ Z_NEXT(prev->val) = Z_NEXT(p->val);
+ } else {
+ ht->arHash[p->h & ht->nTableMask] = Z_NEXT(p->val);
}
}
-static void zend_accel_fast_shutdown(TSRMLS_D)
+static void zend_accel_fast_shutdown(void)
{
if (EG(full_tables_cleanup)) {
- EG(symbol_table).pDestructor = (dtor_func_t)accel_fast_zval_ptr_dtor;
+ EG(symbol_table).ht.pDestructor = accel_fast_zval_dtor;
} else {
dtor_func_t old_destructor;
if (EG(objects_store).top > 1 || zend_hash_num_elements(&EG(regular_list)) > 0) {
/* We don't have to destroy all zvals if they cannot call any destructors */
- old_destructor = EG(symbol_table).pDestructor;
- EG(symbol_table).pDestructor = (dtor_func_t)accel_fast_zval_ptr_dtor;
+ old_destructor = EG(symbol_table).ht.pDestructor;
+ EG(symbol_table).ht.pDestructor = accel_fast_zval_dtor;
zend_try {
- zend_hash_graceful_reverse_destroy(&EG(symbol_table));
+ zend_hash_graceful_reverse_destroy(&EG(symbol_table).ht);
} zend_end_try();
- EG(symbol_table).pDestructor = old_destructor;
+ EG(symbol_table).ht.pDestructor = old_destructor;
}
- zend_hash_init(&EG(symbol_table), 0, NULL, NULL, 0);
- old_destructor = EG(function_table)->pDestructor;
- EG(function_table)->pDestructor = NULL;
- zend_hash_reverse_apply(EG(function_table), (apply_func_t) accel_clean_non_persistent_function TSRMLS_CC);
- EG(function_table)->pDestructor = old_destructor;
- old_destructor = EG(class_table)->pDestructor;
- EG(class_table)->pDestructor = NULL;
- zend_hash_reverse_apply(EG(class_table), (apply_func_t) accel_clean_non_persistent_class TSRMLS_CC);
- EG(class_table)->pDestructor = old_destructor;
- old_destructor = EG(zend_constants)->pDestructor;
- EG(zend_constants)->pDestructor = NULL;
- zend_hash_reverse_apply(EG(zend_constants), (apply_func_t) accel_clean_non_persistent_constant TSRMLS_CC);
- EG(zend_constants)->pDestructor = old_destructor;
+ zend_hash_init(&EG(symbol_table).ht, 8, NULL, NULL, 0);
+
+ ZEND_HASH_REVERSE_FOREACH(EG(function_table), 0) {
+ zend_function *func = Z_PTR(_p->val);
+
+ if (func->type == ZEND_INTERNAL_FUNCTION) {
+ break;
+ } else {
+ if (func->op_array.static_variables) {
+ accel_fast_hash_destroy(func->op_array.static_variables);
+ }
+ zend_accel_fast_del_bucket(EG(function_table), _idx-1, _p);
+ }
+ } ZEND_HASH_FOREACH_END();
+
+ ZEND_HASH_REVERSE_FOREACH(EG(class_table), 0) {
+ zend_class_entry *ce = Z_PTR(_p->val);
+
+ if (ce->type == ZEND_INTERNAL_CLASS) {
+ break;
+ } else {
+ if (ce->ce_flags & ZEND_HAS_STATIC_IN_METHODS) {
+ zend_function *func;
+
+ ZEND_HASH_FOREACH_PTR(&ce->function_table, func) {
+ if (func->type == ZEND_USER_FUNCTION) {
+ if (func->op_array.static_variables) {
+ accel_fast_hash_destroy(func->op_array.static_variables);
+ func->op_array.static_variables = NULL;
+ }
+ }
+ } ZEND_HASH_FOREACH_END();
+ }
+ if (ce->static_members_table) {
+ int i;
+
+ for (i = 0; i < ce->default_static_members_count; i++) {
+ accel_fast_zval_dtor(&ce->static_members_table[i]);
+ ZVAL_UNDEF(&ce->static_members_table[i]);
+ }
+ ce->static_members_table = NULL;
+ }
+ zend_accel_fast_del_bucket(EG(class_table), _idx-1, _p);
+ }
+ } ZEND_HASH_FOREACH_END();
+
+ ZEND_HASH_REVERSE_FOREACH(EG(zend_constants), 0) {
+ zend_constant *c = Z_PTR(_p->val);
+
+ if (c->flags & CONST_PERSISTENT) {
+ break;
+ } else {
+ zend_accel_fast_del_bucket(EG(zend_constants), _idx-1, _p);
+ }
+ } ZEND_HASH_FOREACH_END();
}
CG(unclean_shutdown) = 1;
}
@@ -2363,19 +2077,18 @@ static void accel_deactivate(void)
* In general, they're restored by persistent_compile_file(), but in case
* the script is aborted abnormally, they may become messed up.
*/
- TSRMLS_FETCH();
if (!ZCG(enabled) || !accel_startup_ok) {
return;
}
- zend_shared_alloc_safe_unlock(TSRMLS_C); /* be sure we didn't leave cache locked */
- accel_unlock_all(TSRMLS_C);
+ zend_shared_alloc_safe_unlock(); /* be sure we didn't leave cache locked */
+ accel_unlock_all();
ZCG(counted) = 0;
#if !ZEND_DEBUG
if (ZCG(accel_directives).fast_shutdown) {
- zend_accel_fast_shutdown(TSRMLS_C);
+ zend_accel_fast_shutdown();
}
#endif
@@ -2409,7 +2122,7 @@ static int accelerator_remove_cb(zend_extension *element1, zend_extension *eleme
return 0;
}
-static void zps_startup_failure(char *reason, char *api_reason, int (*cb)(zend_extension *, zend_extension *) TSRMLS_DC)
+static void zps_startup_failure(char *reason, char *api_reason, int (*cb)(zend_extension *, zend_extension *))
{
accel_startup_ok = 0;
zps_failure_reason = reason;
@@ -2417,7 +2130,7 @@ static void zps_startup_failure(char *reason, char *api_reason, int (*cb)(zend_e
zend_llist_del_element(&zend_extensions, NULL, (int (*)(void *, void *))cb);
}
-static inline int accel_find_sapi(TSRMLS_D)
+static inline int accel_find_sapi(void)
{
static const char *supported_sapis[] = {
"apache",
@@ -2448,9 +2161,9 @@ static inline int accel_find_sapi(TSRMLS_D)
return FAILURE;
}
-static int zend_accel_init_shm(TSRMLS_D)
+static int zend_accel_init_shm(void)
{
- zend_shared_alloc_lock(TSRMLS_C);
+ zend_shared_alloc_lock();
accel_shared_globals = zend_shared_alloc(sizeof(zend_accel_shared_globals));
if (!accel_shared_globals) {
@@ -2462,26 +2175,26 @@ static int zend_accel_init_shm(TSRMLS_D)
zend_accel_hash_init(&ZCSG(hash), ZCG(accel_directives).max_accelerated_files);
zend_accel_hash_init(&ZCSG(include_paths), 32);
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
-
ZCSG(interned_strings_start) = ZCSG(interned_strings_end) = NULL;
# ifndef ZTS
zend_hash_init(&ZCSG(interned_strings), (ZCG(accel_directives).interned_strings_buffer * 1024 * 1024) / (sizeof(Bucket) + sizeof(Bucket*) + 8 /* average string length */), NULL, NULL, 1);
if (ZCG(accel_directives).interned_strings_buffer) {
ZCSG(interned_strings).nTableMask = ZCSG(interned_strings).nTableSize - 1;
- ZCSG(interned_strings).arBuckets = zend_shared_alloc(ZCSG(interned_strings).nTableSize * sizeof(Bucket *));
+ ZCSG(interned_strings).arData = zend_shared_alloc(ZCSG(interned_strings).nTableSize * sizeof(Bucket));
+ ZCSG(interned_strings).arHash = (uint32_t*)zend_shared_alloc(ZCSG(interned_strings).nTableSize * sizeof(uint32_t));
ZCSG(interned_strings_start) = zend_shared_alloc((ZCG(accel_directives).interned_strings_buffer * 1024 * 1024));
- if (!ZCSG(interned_strings).arBuckets || !ZCSG(interned_strings_start)) {
+ if (!ZCSG(interned_strings).arData || !ZCSG(interned_strings_start)) {
zend_accel_error(ACCEL_LOG_FATAL, ACCELERATOR_PRODUCT_NAME " cannot allocate buffer for interned strings");
return FAILURE;
}
+ memset(ZCSG(interned_strings).arHash, INVALID_IDX, ZCSG(interned_strings).nTableSize * sizeof(uint32_t));
ZCSG(interned_strings_end) = ZCSG(interned_strings_start) + (ZCG(accel_directives).interned_strings_buffer * 1024 * 1024);
ZCSG(interned_strings_top) = ZCSG(interned_strings_start);
- orig_interned_strings_start = CG(interned_strings_start);
- orig_interned_strings_end = CG(interned_strings_end);
- CG(interned_strings_start) = ZCSG(interned_strings_start);
- CG(interned_strings_end) = ZCSG(interned_strings_end);
+// orig_interned_strings_start = CG(interned_strings_start);
+// orig_interned_strings_end = CG(interned_strings_end);
+// CG(interned_strings_start) = ZCSG(interned_strings_start);
+// CG(interned_strings_end) = ZCSG(interned_strings_end);
}
# endif
@@ -2494,14 +2207,12 @@ static int zend_accel_init_shm(TSRMLS_D)
# ifndef ZTS
if (ZCG(accel_directives).interned_strings_buffer) {
- accel_use_shm_interned_strings(TSRMLS_C);
- accel_interned_strings_save_state(TSRMLS_C);
+ accel_use_shm_interned_strings();
+ accel_interned_strings_save_state();
}
# endif
-#endif
-
- zend_reset_cache_vars(TSRMLS_C);
+ zend_reset_cache_vars();
ZCSG(oom_restarts) = 0;
ZCSG(hash_restarts) = 0;
@@ -2512,21 +2223,29 @@ static int zend_accel_init_shm(TSRMLS_D)
ZCSG(last_restart_time) = 0;
ZCSG(restart_in_progress) = 0;
- zend_shared_alloc_unlock(TSRMLS_C);
+ zend_shared_alloc_unlock();
return SUCCESS;
}
-static void accel_globals_ctor(zend_accel_globals *accel_globals TSRMLS_DC)
+static void accel_globals_ctor(zend_accel_globals *accel_globals)
{
+#if defined(COMPILE_DL_OPCACHE) && defined(ZTS)
+ ZEND_TSRMLS_CACHE_UPDATE;
+#endif
memset(accel_globals, 0, sizeof(zend_accel_globals));
zend_hash_init(&accel_globals->function_table, zend_hash_num_elements(CG(function_table)), NULL, ZEND_FUNCTION_DTOR, 1);
- zend_accel_copy_internal_functions(TSRMLS_C);
+ zend_accel_copy_internal_functions();
+}
+
+static void accel_globals_internal_func_dtor(zval *zv)
+{
+ free(Z_PTR_P(zv));
}
-static void accel_globals_dtor(zend_accel_globals *accel_globals TSRMLS_DC)
+static void accel_globals_dtor(zend_accel_globals *accel_globals)
{
- accel_globals->function_table.pDestructor = NULL;
+ accel_globals->function_table.pDestructor = accel_globals_internal_func_dtor;
zend_hash_destroy(&accel_globals->function_table);
}
@@ -2534,7 +2253,6 @@ static int accel_startup(zend_extension *extension)
{
zend_function *func;
zend_ini_entry *ini_entry;
- TSRMLS_FETCH();
#ifdef ZTS
accel_globals_id = ts_allocate_id(&accel_globals_id, sizeof(zend_accel_globals), (ts_allocate_ctor) accel_globals_ctor, (ts_allocate_dtor) accel_globals_dtor);
@@ -2553,13 +2271,13 @@ static int accel_startup(zend_extension *extension)
}
/* no supported SAPI found - disable acceleration and stop initialization */
- if (accel_find_sapi(TSRMLS_C) == FAILURE) {
+ if (accel_find_sapi() == FAILURE) {
accel_startup_ok = 0;
if (!ZCG(accel_directives).enable_cli &&
strcmp(sapi_module.name, "cli") == 0) {
- zps_startup_failure("Opcode Caching is disabled for CLI", NULL, accelerator_remove_cb TSRMLS_CC);
+ zps_startup_failure("Opcode Caching is disabled for CLI", NULL, accelerator_remove_cb);
} else {
- zps_startup_failure("Opcode Caching is only supported in Apache, ISAPI, FPM, FastCGI and LiteSpeed SAPIs", NULL, accelerator_remove_cb TSRMLS_CC);
+ zps_startup_failure("Opcode Caching is only supported in Apache, ISAPI, FPM, FastCGI and LiteSpeed SAPIs", NULL, accelerator_remove_cb);
}
return SUCCESS;
}
@@ -2572,7 +2290,7 @@ static int accel_startup(zend_extension *extension)
/********************************************/
switch (zend_shared_alloc_startup(ZCG(accel_directives).memory_consumption)) {
case ALLOC_SUCCESS:
- if (zend_accel_init_shm(TSRMLS_C) == FAILURE) {
+ if (zend_accel_init_shm() == FAILURE) {
accel_startup_ok = 0;
return FAILURE;
}
@@ -2583,27 +2301,18 @@ static int accel_startup(zend_extension *extension)
return SUCCESS;
case SUCCESSFULLY_REATTACHED:
accel_shared_globals = (zend_accel_shared_globals *) ZSMMG(app_shared_globals);
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
- zend_shared_alloc_lock(TSRMLS_C);
- orig_interned_strings_start = CG(interned_strings_start);
- orig_interned_strings_end = CG(interned_strings_end);
+ zend_shared_alloc_lock();
orig_new_interned_string = zend_new_interned_string;
orig_interned_strings_snapshot = zend_interned_strings_snapshot;
orig_interned_strings_restore = zend_interned_strings_restore;
- CG(interned_strings_start) = ZCSG(interned_strings_start);
- CG(interned_strings_end) = ZCSG(interned_strings_end);
zend_new_interned_string = accel_new_interned_string_for_php;
zend_interned_strings_snapshot = accel_interned_strings_snapshot_for_php;
zend_interned_strings_restore = accel_interned_strings_restore_for_php;
-
-# ifndef ZTS
- accel_use_shm_interned_strings(TSRMLS_C);
-# endif
-
- zend_shared_alloc_unlock(TSRMLS_C);
+#ifndef ZTS
+ accel_use_shm_interned_strings();
#endif
-
+ zend_shared_alloc_unlock();
break;
case FAILED_REATTACHED:
accel_startup_ok = 0;
@@ -2614,6 +2323,9 @@ static int accel_startup(zend_extension *extension)
/* from this point further, shared memory is supposed to be OK */
+ /* Init auto-global strings */
+ zend_accel_init_auto_globals();
+
/* Override compiler */
accelerator_orig_compile_file = zend_compile_file;
zend_compile_file = persistent_compile_file;
@@ -2623,15 +2335,13 @@ static int accel_startup(zend_extension *extension)
accelerator_orig_zend_stream_open_function = zend_stream_open_function;
zend_stream_open_function = persistent_stream_open_function;
-#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
/* Override path resolver function (to eliminate stat() calls caused by
* include_once/require_once statements */
accelerator_orig_zend_resolve_path = zend_resolve_path;
zend_resolve_path = persistent_zend_resolve_path;
-#endif
/* Override chdir() function */
- if (zend_hash_find(CG(function_table), "chdir", sizeof("chdir"), (void**)&func) == SUCCESS &&
+ if ((func = zend_hash_str_find_ptr(CG(function_table), "chdir", sizeof("chdir")-1)) != NULL &&
func->type == ZEND_INTERNAL_FUNCTION) {
orig_chdir = func->internal_function.handler;
func->internal_function.handler = ZEND_FN(accel_chdir);
@@ -2639,27 +2349,27 @@ static int accel_startup(zend_extension *extension)
ZCG(cwd) = NULL;
/* Override "include_path" modifier callback */
- if (zend_hash_find(EG(ini_directives), "include_path", sizeof("include_path"), (void **) &ini_entry) == SUCCESS) {
+ if ((ini_entry = zend_hash_str_find_ptr(EG(ini_directives), "include_path", sizeof("include_path")-1)) != NULL) {
ZCG(include_path) = INI_STR("include_path");
ZCG(include_path_key) = NULL;
if (ZCG(include_path) && *ZCG(include_path)) {
ZCG(include_path_len) = strlen(ZCG(include_path));
- ZCG(include_path_key) = zend_accel_hash_find(&ZCSG(include_paths), ZCG(include_path), ZCG(include_path_len) + 1);
+ ZCG(include_path_key) = zend_accel_hash_find(&ZCSG(include_paths), ZCG(include_path), ZCG(include_path_len));
if (!ZCG(include_path_key) &&
!zend_accel_hash_is_full(&ZCSG(include_paths))) {
char *key;
- zend_shared_alloc_lock(TSRMLS_C);
+ zend_shared_alloc_lock();
key = zend_shared_alloc(ZCG(include_path_len) + 2);
if (key) {
memcpy(key, ZCG(include_path), ZCG(include_path_len) + 1);
key[ZCG(include_path_len) + 1] = 'A' + ZCSG(include_paths).num_entries;
ZCG(include_path_key) = key + ZCG(include_path_len) + 1;
- zend_accel_hash_update(&ZCSG(include_paths), key, ZCG(include_path_len) + 1, 0, ZCG(include_path_key));
+ zend_accel_hash_update(&ZCSG(include_paths), key, ZCG(include_path_len), 0, ZCG(include_path_key));
} else {
- zend_accel_schedule_restart_if_necessary(ACCEL_RESTART_OOM TSRMLS_CC);
+ zend_accel_schedule_restart_if_necessary(ACCEL_RESTART_OOM);
}
- zend_shared_alloc_unlock(TSRMLS_C);
+ zend_shared_alloc_unlock();
}
} else {
ZCG(include_path) = "";
@@ -2669,29 +2379,29 @@ static int accel_startup(zend_extension *extension)
ini_entry->on_modify = accel_include_path_on_modify;
}
- zend_shared_alloc_lock(TSRMLS_C);
+ zend_shared_alloc_lock();
zend_shared_alloc_save_state();
- zend_shared_alloc_unlock(TSRMLS_C);
+ zend_shared_alloc_unlock();
SHM_PROTECT();
accel_startup_ok = 1;
/* Override file_exists(), is_file() and is_readable() */
- zend_accel_override_file_functions(TSRMLS_C);
+ zend_accel_override_file_functions();
/* Load black list */
accel_blacklist.entries = NULL;
if (ZCG(enabled) && accel_startup_ok &&
- ZCG(accel_directives).user_blacklist_filename &&
+ ZCG(accel_directives).user_blacklist_filename &&
*ZCG(accel_directives.user_blacklist_filename)) {
zend_accel_blacklist_init(&accel_blacklist);
zend_accel_blacklist_load(&accel_blacklist, ZCG(accel_directives.user_blacklist_filename));
}
-
+
#if 0
/* FIXME: We probably don't need it here */
- zend_accel_copy_internal_functions(TSRMLS_C);
+ zend_accel_copy_internal_functions();
#endif
return SUCCESS;
@@ -2706,7 +2416,7 @@ static void accel_free_ts_resources()
#endif
}
-void accel_shutdown(TSRMLS_D)
+void accel_shutdown(void)
{
zend_ini_entry *ini_entry;
@@ -2717,31 +2427,29 @@ void accel_shutdown(TSRMLS_D)
return;
}
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
if (ZCG(accel_directives).interned_strings_buffer) {
-# ifndef ZTS
+#ifndef ZTS
+ zend_hash_clean(CG(auto_globals));
zend_hash_clean(CG(function_table));
zend_hash_clean(CG(class_table));
zend_hash_clean(EG(zend_constants));
-# endif
- CG(interned_strings_start) = orig_interned_strings_start;
- CG(interned_strings_end) = orig_interned_strings_end;
+#endif
}
+
zend_new_interned_string = orig_new_interned_string;
zend_interned_strings_snapshot = orig_interned_strings_snapshot;
zend_interned_strings_restore = orig_interned_strings_restore;
-#endif
accel_free_ts_resources();
zend_shared_alloc_shutdown();
zend_compile_file = accelerator_orig_compile_file;
- if (zend_hash_find(EG(ini_directives), "include_path", sizeof("include_path"), (void **) &ini_entry) == SUCCESS) {
+ if ((ini_entry = zend_hash_str_find_ptr(EG(ini_directives), "include_path", sizeof("include_path")-1)) != NULL) {
ini_entry->on_modify = orig_include_path_on_modify;
}
}
-void zend_accel_schedule_restart(zend_accel_restart_reason reason TSRMLS_DC)
+void zend_accel_schedule_restart(zend_accel_restart_reason reason)
{
if (ZCSG(restart_pending)) {
/* don't schedule twice */
@@ -2765,9 +2473,9 @@ void zend_accel_schedule_restart(zend_accel_restart_reason reason TSRMLS_DC)
/* this is needed because on WIN32 lock is not decreased unless ZCG(counted) is set */
#ifdef ZEND_WIN32
-#define accel_deactivate_now() ZCG(counted) = 1; accel_deactivate_sub(TSRMLS_C)
+#define accel_deactivate_now() ZCG(counted) = 1; accel_deactivate_sub()
#else
-#define accel_deactivate_now() accel_deactivate_sub(TSRMLS_C)
+#define accel_deactivate_now() accel_deactivate_sub()
#endif
/* ensures it is OK to read SHM
@@ -2775,7 +2483,7 @@ void zend_accel_schedule_restart(zend_accel_restart_reason reason TSRMLS_DC)
if OK returns SUCCESS
MUST call accelerator_shm_read_unlock after done lock operations
*/
-int accelerator_shm_read_lock(TSRMLS_D)
+int accelerator_shm_read_lock(void)
{
if (ZCG(counted)) {
/* counted means we are holding read lock for SHM, so that nothing bad can happen */
@@ -2783,7 +2491,7 @@ int accelerator_shm_read_lock(TSRMLS_D)
} else {
/* here accelerator is active but we do not hold SHM lock. This means restart was scheduled
or is in progress now */
- accel_activate_add(TSRMLS_C); /* acquire usage lock */
+ accel_activate_add(); /* acquire usage lock */
/* Now if we weren't inside restart, restart would not begin until we remove usage lock */
if (ZCSG(restart_in_progress)) {
/* we already were inside restart this means it's not safe to touch shm */
@@ -2795,7 +2503,7 @@ int accelerator_shm_read_lock(TSRMLS_D)
}
/* must be called ONLY after SUCCESSFUL accelerator_shm_read_lock */
-void accelerator_shm_read_unlock(TSRMLS_D)
+void accelerator_shm_read_unlock(void)
{
if (!ZCG(counted)) {
/* counted is 0 - meaning we had to readlock manually, release readlock now */
@@ -2808,7 +2516,7 @@ ZEND_EXT_API zend_extension zend_extension_entry = {
ACCELERATOR_VERSION, /* version */
"Zend Technologies", /* author */
"http://www.zend.com/", /* URL */
- "Copyright (c) 1999-2015", /* copyright */
+ "Copyright (c) 1999-2014", /* copyright */
accel_startup, /* startup */
NULL, /* shutdown */
accel_activate, /* per-script activation */
diff --git a/ext/opcache/ZendAccelerator.h b/ext/opcache/ZendAccelerator.h
index cd99fa0781..9b478ae158 100644
--- a/ext/opcache/ZendAccelerator.h
+++ b/ext/opcache/ZendAccelerator.h
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| Zend OPcache |
+----------------------------------------------------------------------+
- | Copyright (c) 1998-2015 The PHP Group |
+ | Copyright (c) 1998-2014 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -127,47 +127,17 @@ extern int lock_file;
# endif
#endif
-#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
- #define Z_REFCOUNT_P(pz) (pz)->refcount
- #define Z_SET_REFCOUNT_P(pz, v) (pz)->refcount = (v)
- #define Z_ADDREF_P(pz) ++((pz)->refcount)
- #define Z_DELREF_P(pz) --((pz)->refcount)
- #define Z_ISREF_P(pz) (pz)->is_ref
- #define Z_SET_ISREF_P(pz) Z_SET_ISREF_TO_P(pz, 1)
- #define Z_UNSET_ISREF_P(pz) Z_SET_ISREF_TO_P(pz, 0)
- #define Z_SET_ISREF_TO_P(pz, isref) (pz)->is_ref = (isref)
- #define PZ_REFCOUNT_P(pz) (pz)->refcount
- #define PZ_SET_REFCOUNT_P(pz, v) (pz)->refcount = (v)
- #define PZ_ADDREF_P(pz) ++((pz)->refcount)
- #define PZ_DELREF_P(pz) --((pz)->refcount)
- #define PZ_ISREF_P(pz) (pz)->is_ref
- #define PZ_SET_ISREF_P(pz) Z_SET_ISREF_TO_P(pz, 1)
- #define PZ_UNSET_ISREF_P(pz) Z_SET_ISREF_TO_P(pz, 0)
- #define PZ_SET_ISREF_TO_P(pz, isref) (pz)->is_ref = (isref)
-#else
- #define PZ_REFCOUNT_P(pz) (pz)->refcount__gc
- #define PZ_SET_REFCOUNT_P(pz, v) (pz)->refcount__gc = (v)
- #define PZ_ADDREF_P(pz) ++((pz)->refcount__gc)
- #define PZ_DELREF_P(pz) --((pz)->refcount__gc)
- #define PZ_ISREF_P(pz) (pz)->is_ref__gc
- #define PZ_SET_ISREF_P(pz) Z_SET_ISREF_TO_P(pz, 1)
- #define PZ_UNSET_ISREF_P(pz) Z_SET_ISREF_TO_P(pz, 0)
- #define PZ_SET_ISREF_TO_P(pz, isref) (pz)->is_ref__gc = (isref)
-#endif
+#define PZ_REFCOUNT_P(pz) (pz)->refcount__gc
+#define PZ_SET_REFCOUNT_P(pz, v) (pz)->refcount__gc = (v)
+#define PZ_ADDREF_P(pz) ++((pz)->refcount__gc)
+#define PZ_DELREF_P(pz) --((pz)->refcount__gc)
+#define PZ_ISREF_P(pz) (pz)->is_ref__gc
+#define PZ_SET_ISREF_P(pz) Z_SET_ISREF_TO_P(pz, 1)
+#define PZ_UNSET_ISREF_P(pz) Z_SET_ISREF_TO_P(pz, 0)
+#define PZ_SET_ISREF_TO_P(pz, isref) (pz)->is_ref__gc = (isref)
-#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
-# ifdef ALLOCA_FLAG
- #define DO_ALLOCA(x) do_alloca_with_limit(x, use_heap)
- #define FREE_ALLOCA(x) free_alloca_with_limit(x, use_heap)
-# else
- #define ALLOCA_FLAG(x)
- #define DO_ALLOCA(x) do_alloca(x)
- #define FREE_ALLOCA(x) free_alloca(x)
-# endif
-#else
- #define DO_ALLOCA(x) do_alloca(x, use_heap)
- #define FREE_ALLOCA(x) free_alloca(x, use_heap)
-#endif
+#define DO_ALLOCA(x) do_alloca(x, use_heap)
+#define FREE_ALLOCA(x) free_alloca(x, use_heap)
#if ZEND_WIN32
@@ -183,29 +153,30 @@ typedef enum _zend_accel_restart_reason {
} zend_accel_restart_reason;
typedef struct _zend_persistent_script {
- ulong hash_value;
- char *full_path; /* full real path with resolved symlinks */
- unsigned int full_path_len;
+ zend_string *full_path; /* full real path with resolved symlinks */
zend_op_array main_op_array;
HashTable function_table;
HashTable class_table;
- long compiler_halt_offset; /* position of __HALT_COMPILER or -1 */
+ zend_long compiler_halt_offset; /* position of __HALT_COMPILER or -1 */
int ping_auto_globals_mask; /* which autoglobals are used by the script */
accel_time_t timestamp; /* the script modification time */
zend_bool corrupted;
-#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
- zend_uint early_binding; /* the linked list of delayed declarations */
-#endif
void *mem; /* shared memory area used by script structures */
size_t size; /* size of used shared memory */
+ void *arena_mem; /* part that should be copied into process */
+ size_t arena_size;
/* All entries that shouldn't be counted in the ADLER32
* checksum must be declared in this struct
*/
struct zend_persistent_script_dynamic_members {
time_t last_used;
- ulong hits;
+#ifdef ZEND_WIN32
+ LONGLONG hits;
+#else
+ zend_ulong hits;
+#endif
unsigned int memory_consumption;
unsigned int checksum;
time_t revalidate;
@@ -213,12 +184,12 @@ typedef struct _zend_persistent_script {
} zend_persistent_script;
typedef struct _zend_accel_directives {
- long memory_consumption;
- long max_accelerated_files;
+ zend_long memory_consumption;
+ zend_long max_accelerated_files;
double max_wasted_percentage;
char *user_blacklist_filename;
- long consistency_checks;
- long force_restart_timeout;
+ zend_long consistency_checks;
+ zend_long force_restart_timeout;
zend_bool use_cwd;
zend_bool ignore_dups;
zend_bool validate_timestamps;
@@ -230,20 +201,18 @@ typedef struct _zend_accel_directives {
zend_bool file_override_enabled;
zend_bool inherited_hack;
zend_bool enable_cli;
- unsigned long revalidate_freq;
- unsigned long file_update_protection;
+ zend_ulong revalidate_freq;
+ zend_ulong file_update_protection;
char *error_log;
#ifdef ZEND_WIN32
char *mmap_base;
#endif
char *memory_model;
- long log_verbosity_level;
+ zend_long log_verbosity_level;
- long optimization_level;
- long max_file_size;
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
- long interned_strings_buffer;
-#endif
+ zend_long optimization_level;
+ zend_long max_file_size;
+ zend_long interned_strings_buffer;
char *restrict_api;
} zend_accel_directives;
@@ -263,11 +232,14 @@ typedef struct _zend_accel_globals {
char *include_path; /* current section of "include_path" directive */
int include_path_len; /* "include_path" string length */
int include_path_check;
+ int auto_globals_mask;
time_t request_time;
/* preallocated shared-memory block to save current script */
void *mem;
+ void *arena_mem;
+ zend_persistent_script *current_persistent_script;
/* cache to save hash lookup on the same INCLUDE opcode */
- zend_op *cache_opline;
+ const zend_op *cache_opline;
zend_persistent_script *cache_persistent_script;
/* preallocated buffer for keys */
int key_len;
@@ -276,12 +248,12 @@ typedef struct _zend_accel_globals {
typedef struct _zend_accel_shared_globals {
/* Cache Data Structures */
- unsigned long hits;
- unsigned long misses;
- unsigned long blacklist_misses;
- unsigned long oom_restarts; /* number of restarts because of out of memory */
- unsigned long hash_restarts; /* number of restarts because of hash overflow */
- unsigned long manual_restarts; /* number of restarts scheduled by opcache_reset() */
+ zend_ulong hits;
+ zend_ulong misses;
+ zend_ulong blacklist_misses;
+ zend_ulong oom_restarts; /* number of restarts because of out of memory */
+ zend_ulong hash_restarts; /* number of restarts because of hash overflow */
+ zend_ulong manual_restarts; /* number of restarts scheduled by opcache_reset() */
zend_accel_hash hash; /* hash table for cached scripts */
zend_accel_hash include_paths; /* used "include_path" values */
@@ -294,23 +266,16 @@ typedef struct _zend_accel_shared_globals {
zend_accel_restart_reason restart_reason;
zend_bool cache_status_before_restart;
#ifdef ZEND_WIN32
- unsigned long mem_usage;
- unsigned long restart_in;
+ LONGLONG mem_usage;
+ LONGLONG restart_in;
#endif
zend_bool restart_in_progress;
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
/* Interned Strings Support */
char *interned_strings_start;
char *interned_strings_top;
char *interned_strings_end;
+ char *interned_strings_saved_top;
HashTable interned_strings;
- struct {
- Bucket **arBuckets;
- Bucket *pListHead;
- Bucket *pListTail;
- char *top;
- } interned_strings_saved_state;
-#endif
} zend_accel_shared_globals;
extern zend_bool accel_startup_ok;
@@ -319,8 +284,11 @@ extern zend_accel_shared_globals *accel_shared_globals;
#define ZCSG(element) (accel_shared_globals->element)
#ifdef ZTS
-# define ZCG(v) TSRMG(accel_globals_id, zend_accel_globals *, v)
+# define ZCG(v) ZEND_TSRMG(accel_globals_id, zend_accel_globals *, v)
extern int accel_globals_id;
+# ifdef COMPILE_DL_OPCACHE
+ZEND_TSRMLS_CACHE_EXTERN;
+# endif
#else
# define ZCG(v) (accel_globals.v)
extern zend_accel_globals accel_globals;
@@ -328,17 +296,17 @@ extern zend_accel_globals accel_globals;
extern char *zps_api_failure_reason;
-void accel_shutdown(TSRMLS_D);
-void zend_accel_schedule_restart(zend_accel_restart_reason reason TSRMLS_DC);
-void zend_accel_schedule_restart_if_necessary(zend_accel_restart_reason reason TSRMLS_DC);
-int validate_timestamp_and_record(zend_persistent_script *persistent_script, zend_file_handle *file_handle TSRMLS_DC);
-int zend_accel_invalidate(const char *filename, int filename_len, zend_bool force TSRMLS_DC);
-int zend_accel_script_optimize(zend_persistent_script *persistent_script TSRMLS_DC);
-int accelerator_shm_read_lock(TSRMLS_D);
-void accelerator_shm_read_unlock(TSRMLS_D);
+void accel_shutdown(void);
+void zend_accel_schedule_restart(zend_accel_restart_reason reason);
+void zend_accel_schedule_restart_if_necessary(zend_accel_restart_reason reason);
+int validate_timestamp_and_record(zend_persistent_script *persistent_script, zend_file_handle *file_handle);
+int zend_accel_invalidate(const char *filename, int filename_len, zend_bool force);
+int zend_accel_script_optimize(zend_persistent_script *persistent_script);
+int accelerator_shm_read_lock(void);
+void accelerator_shm_read_unlock(void);
-char *accel_make_persistent_key_ex(zend_file_handle *file_handle, int path_length, int *key_len TSRMLS_DC);
-zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type TSRMLS_DC);
+char *accel_make_persistent_key_ex(zend_file_handle *file_handle, int path_length, int *key_len);
+zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type);
#if !defined(ZEND_DECLARE_INHERITED_CLASS_DELAYED)
# define ZEND_DECLARE_INHERITED_CLASS_DELAYED 145
@@ -346,55 +314,24 @@ zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type T
#define ZEND_DECLARE_INHERITED_CLASS_DELAYED_FLAG 0x80
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
-
-const char *accel_new_interned_string(const char *arKey, int nKeyLength, int free_src TSRMLS_DC);
-
-# define interned_free(s) do { \
- if (!IS_INTERNED(s)) { \
- free(s); \
- } \
- } while (0)
-# define interned_efree(s) do { \
- if (!IS_INTERNED(s)) { \
- efree(s); \
- } \
- } while (0)
-# define interned_estrndup(s, n) \
- (IS_INTERNED(s) ? (s) : estrndup(s, n))
+#define IS_ACCEL_INTERNED(str) \
+ ((char*)(str) >= ZCSG(interned_strings_start) && (char*)(str) < ZCSG(interned_strings_end))
+
+zend_string *accel_new_interned_string(zend_string *str);
+
# define ZEND_RESULT_TYPE(opline) (opline)->result_type
# define ZEND_RESULT(opline) (opline)->result
# define ZEND_OP1_TYPE(opline) (opline)->op1_type
# define ZEND_OP1(opline) (opline)->op1
# define ZEND_OP1_CONST(opline) (*(opline)->op1.zv)
-# define ZEND_OP1_LITERAL(opline) (op_array)->literals[(opline)->op1.constant].constant
+# define ZEND_OP1_LITERAL(opline) (op_array)->literals[(opline)->op1.constant]
# define ZEND_OP2_TYPE(opline) (opline)->op2_type
# define ZEND_OP2(opline) (opline)->op2
# define ZEND_OP2_CONST(opline) (*(opline)->op2.zv)
-# define ZEND_OP2_LITERAL(opline) (op_array)->literals[(opline)->op2.constant].constant
+# define ZEND_OP2_LITERAL(opline) (op_array)->literals[(opline)->op2.constant]
# define ZEND_DONE_PASS_TWO(op_array) (((op_array)->fn_flags & ZEND_ACC_DONE_PASS_TWO) != 0)
# define ZEND_CE_FILENAME(ce) (ce)->info.user.filename
# define ZEND_CE_DOC_COMMENT(ce) (ce)->info.user.doc_comment
# define ZEND_CE_DOC_COMMENT_LEN(ce) (ce)->info.user.doc_comment_len
-#else
-# define IS_INTERNED(s) 0
-# define interned_free(s) free(s)
-# define interned_efree(s) efree(s)
-# define interned_estrndup(s, n) estrndup(s, n)
-# define ZEND_RESULT_TYPE(opline) (opline)->result.op_type
-# define ZEND_RESULT(opline) (opline)->result.u
-# define ZEND_OP1_TYPE(opline) (opline)->op1.op_type
-# define ZEND_OP1(opline) (opline)->op1.u
-# define ZEND_OP1_CONST(opline) (opline)->op1.u.constant
-# define ZEND_OP1_LITERAL(opline) (opline)->op1.u.constant
-# define ZEND_OP2_TYPE(opline) (opline)->op2.op_type
-# define ZEND_OP2(opline) (opline)->op2.u
-# define ZEND_OP2_CONST(opline) (opline)->op2.u.constant
-# define ZEND_OP2_LITERAL(opline) (opline)->op2.u.constant
-# define ZEND_DONE_PASS_TWO(op_array) ((op_array)->done_pass_two != 0)
-# define ZEND_CE_FILENAME(ce) (ce)->filename
-# define ZEND_CE_DOC_COMMENT(ce) (ce)->doc_comment
-# define ZEND_CE_DOC_COMMENT_LEN(ce) (ce)->doc_comment_len
-#endif
#endif /* ZEND_ACCELERATOR_H */
diff --git a/ext/opcache/config.m4 b/ext/opcache/config.m4
index f6e6ca9444..be2f0feab7 100644
--- a/ext/opcache/config.m4
+++ b/ext/opcache/config.m4
@@ -376,8 +376,16 @@ fi
shared_alloc_shm.c \
shared_alloc_mmap.c \
shared_alloc_posix.c \
- Optimizer/zend_optimizer.c,
- shared,,,,yes)
+ Optimizer/zend_optimizer.c \
+ Optimizer/pass1_5.c \
+ Optimizer/pass2.c \
+ Optimizer/pass3.c \
+ Optimizer/optimize_func_calls.c \
+ Optimizer/block_pass.c \
+ Optimizer/optimize_temp_vars_5.c \
+ Optimizer/nop_removal.c \
+ Optimizer/compact_literals.c,
+ shared,,-DZEND_ENABLE_STATIC_TSRMLS_CACHE=1,,yes)
PHP_ADD_BUILD_DIR([$ext_builddir/Optimizer], 1)
fi
diff --git a/ext/opcache/config.w32 b/ext/opcache/config.w32
index af160b207c..921f0ed9b4 100644
--- a/ext/opcache/config.w32
+++ b/ext/opcache/config.w32
@@ -14,9 +14,9 @@ if (PHP_OPCACHE != "no") {
zend_persist.c \
zend_persist_calc.c \
zend_shared_alloc.c \
- shared_alloc_win32.c", true);
+ shared_alloc_win32.c", true, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1");
- ADD_SOURCES(configure_module_dirname + "/Optimizer", "zend_optimizer.c", "opcache", "OptimizerObj");
+ ADD_SOURCES(configure_module_dirname + "/Optimizer", "zend_optimizer.c pass1_5.c pass2.c pass3.c optimize_func_calls.c block_pass.c optimize_temp_vars_5.c nop_removal.c compact_literals.c", "opcache", "OptimizerObj");
ADD_FLAG('CFLAGS_OPCACHE', "/I " + configure_module_dirname);
diff --git a/ext/opcache/shared_alloc_mmap.c b/ext/opcache/shared_alloc_mmap.c
index 0f06b2c100..5744fc8167 100644
--- a/ext/opcache/shared_alloc_mmap.c
+++ b/ext/opcache/shared_alloc_mmap.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| Zend OPcache |
+----------------------------------------------------------------------+
- | Copyright (c) 1998-2015 The PHP Group |
+ | Copyright (c) 1998-2014 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -46,6 +46,22 @@ static int create_segments(size_t requested_size, zend_shared_segment ***shared_
shared_segment = (zend_shared_segment *)((char *)(*shared_segments_p) + sizeof(void *));
(*shared_segments_p)[0] = shared_segment;
+#ifdef MAP_HUGETLB
+ /* Try to allocate huge pages first to reduce dTLB misses.
+ * OS has to be configured properly
+ * (e.g. https://wiki.debian.org/Hugepages#Enabling_HugeTlbPage)
+ * You may verify huge page usage with the following command:
+ * `grep "Huge" /proc/meminfo`
+ */
+ shared_segment->p = mmap(0, requested_size, PROT_READ | PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS|MAP_HUGETLB, -1, 0);
+ if (shared_segment->p != MAP_FAILED) {
+ shared_segment->pos = 0;
+ shared_segment->size = requested_size;
+
+ return ALLOC_SUCCESS;
+ }
+#endif
+
shared_segment->p = mmap(0, requested_size, PROT_READ | PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
if (shared_segment->p == MAP_FAILED) {
*error_in = "mmap";
diff --git a/ext/opcache/shared_alloc_posix.c b/ext/opcache/shared_alloc_posix.c
index b7197eb6cd..e4a34bd795 100644
--- a/ext/opcache/shared_alloc_posix.c
+++ b/ext/opcache/shared_alloc_posix.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| Zend OPcache |
+----------------------------------------------------------------------+
- | Copyright (c) 1998-2015 The PHP Group |
+ | Copyright (c) 1998-2014 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
diff --git a/ext/opcache/shared_alloc_shm.c b/ext/opcache/shared_alloc_shm.c
index 4ca7924a09..4d9e10fc6f 100644
--- a/ext/opcache/shared_alloc_shm.c
+++ b/ext/opcache/shared_alloc_shm.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| Zend OPcache |
+----------------------------------------------------------------------+
- | Copyright (c) 1998-2015 The PHP Group |
+ | Copyright (c) 1998-2014 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
diff --git a/ext/opcache/shared_alloc_win32.c b/ext/opcache/shared_alloc_win32.c
index ae8917dcf5..83ad3ca9ef 100644
--- a/ext/opcache/shared_alloc_win32.c
+++ b/ext/opcache/shared_alloc_win32.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| Zend OPcache |
+----------------------------------------------------------------------+
- | Copyright (c) 1998-2015 The PHP Group |
+ | Copyright (c) 1998-2014 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -177,8 +177,8 @@ static int create_segments(size_t requested_size, zend_shared_segment ***shared_
zend_shared_segment *shared_segment;
int map_retries = 0;
void *default_mapping_base_set[] = { 0, 0 };
- /* TODO:
- improve fixed addresses on x64. It still makes no sense to do it as Windows addresses are virtual per se and can or should be randomized anyway
+ /* TODO:
+ improve fixed addresses on x64. It still makes no sense to do it as Windows addresses are virtual per se and can or should be randomized anyway
through Address Space Layout Radomization (ASLR). We can still let the OS do its job and be sure that each process gets the same address if
desired. Not done yet, @zend refused but did not remember the exact reason, pls add info here if one of you know why :)
*/
@@ -188,7 +188,6 @@ static int create_segments(size_t requested_size, zend_shared_segment ***shared_
void *vista_mapping_base_set[] = { (void *) 0x20000000, (void *) 0x21000000, (void *) 0x30000000, (void *) 0x31000000, (void *) 0x50000000, 0 };
#endif
void **wanted_mapping_base = default_mapping_base_set;
- TSRMLS_FETCH();
zend_shared_alloc_lock_win32();
/* Mapping retries: When Apache2 restarts, the parent process startup routine
diff --git a/ext/opcache/tests/bug68252.phpt b/ext/opcache/tests/bug68252.phpt
new file mode 100644
index 0000000000..e05467a244
--- /dev/null
+++ b/ext/opcache/tests/bug68252.phpt
@@ -0,0 +1,20 @@
+--TEST--
+Bug #68252 (segfault in Zend/zend_hash.c in function _zend_hash_del_el)
+--INI--
+opcache.enable=1
+opcache.enable_cli=1
+opcache.fast_shutdown=1
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+--FILE--
+<?php
+/* run this test script with valgrind */
+function a() {
+ echo "okey";
+}
+
+create_function('', 'var_dump("22");');
+
+a();
+--EXPECT--
+okey
diff --git a/ext/opcache/zend_accelerator_blacklist.c b/ext/opcache/zend_accelerator_blacklist.c
index 594e56cf78..cbf0ada9bb 100644
--- a/ext/opcache/zend_accelerator_blacklist.c
+++ b/ext/opcache/zend_accelerator_blacklist.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| Zend OPcache |
+----------------------------------------------------------------------+
- | Copyright (c) 1998-2015 The PHP Group |
+ | Copyright (c) 1998-2014 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -23,16 +23,7 @@
#include "main/fopen_wrappers.h"
#include "ZendAccelerator.h"
#include "zend_accelerator_blacklist.h"
-
-#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
-# include "ext/ereg/php_regex.h"
-#else
-# include "main/php_regex.h"
-#endif
-
-#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
-# include "ext/standard/php_string.h"
-#endif
+#include "ext/ereg/php_regex.h"
#ifdef ZEND_WIN32
# define REGEX_MODE (REG_EXTENDED|REG_NOSUB|REG_ICASE)
@@ -246,7 +237,6 @@ void zend_accel_blacklist_load(zend_blacklist *blacklist, char *filename)
char buf[MAXPATHLEN + 1], real_path[MAXPATHLEN + 1], *blacklist_path = NULL;
FILE *fp;
int path_length, blacklist_path_length;
- TSRMLS_FETCH();
if ((fp = fopen(filename, "r")) == NULL) {
zend_accel_error(ACCEL_LOG_WARNING, "Cannot load blacklist file: %s\n", filename);
@@ -256,11 +246,7 @@ void zend_accel_blacklist_load(zend_blacklist *blacklist, char *filename)
zend_accel_error(ACCEL_LOG_DEBUG,"Loading blacklist file: '%s'", filename);
if (VCWD_REALPATH(filename, buf)) {
-#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
- blacklist_path_length = php_dirname(buf, strlen(buf));
-#else
blacklist_path_length = zend_dirname(buf, strlen(buf));
-#endif
blacklist_path = zend_strndup(buf, blacklist_path_length);
}
@@ -301,9 +287,9 @@ void zend_accel_blacklist_load(zend_blacklist *blacklist, char *filename)
path_dup = zend_strndup(pbuf, path_length);
if (blacklist_path) {
- expand_filepath_ex(path_dup, real_path, blacklist_path, blacklist_path_length TSRMLS_CC);
+ expand_filepath_ex(path_dup, real_path, blacklist_path, blacklist_path_length);
} else {
- expand_filepath(path_dup, real_path TSRMLS_CC);
+ expand_filepath(path_dup, real_path);
}
path_length = strlen(real_path);
@@ -371,11 +357,11 @@ zend_bool zend_accel_blacklist_is_blacklisted(zend_blacklist *blacklist, char *v
return ret;
}
-void zend_accel_blacklist_apply(zend_blacklist *blacklist, apply_func_arg_t func, void *argument TSRMLS_DC)
+void zend_accel_blacklist_apply(zend_blacklist *blacklist, blacklist_apply_func_arg_t func, void *argument)
{
int i;
for (i = 0; i < blacklist->pos; i++) {
- func(&blacklist->entries[i], argument TSRMLS_CC);
+ func(&blacklist->entries[i], argument);
}
}
diff --git a/ext/opcache/zend_accelerator_blacklist.h b/ext/opcache/zend_accelerator_blacklist.h
index 48a5ac6f96..60d6cac925 100644
--- a/ext/opcache/zend_accelerator_blacklist.h
+++ b/ext/opcache/zend_accelerator_blacklist.h
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| Zend OPcache |
+----------------------------------------------------------------------+
- | Copyright (c) 1998-2015 The PHP Group |
+ | Copyright (c) 1998-2014 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -37,6 +37,8 @@ typedef struct _zend_blacklist {
zend_regexp_list *regexp_list;
} zend_blacklist;
+typedef int (*blacklist_apply_func_arg_t)(zend_blacklist_entry *, zval *);
+
extern zend_blacklist accel_blacklist;
void zend_accel_blacklist_init(zend_blacklist *blacklist);
@@ -44,6 +46,6 @@ void zend_accel_blacklist_shutdown(zend_blacklist *blacklist);
void zend_accel_blacklist_load(zend_blacklist *blacklist, char *filename);
zend_bool zend_accel_blacklist_is_blacklisted(zend_blacklist *blacklist, char *verify_path);
-void zend_accel_blacklist_apply(zend_blacklist *blacklist, apply_func_arg_t func, void *argument TSRMLS_DC);
+void zend_accel_blacklist_apply(zend_blacklist *blacklist, blacklist_apply_func_arg_t func, void *argument);
#endif /* ZEND_ACCELERATOR_BLACKLIST_H */
diff --git a/ext/opcache/zend_accelerator_debug.c b/ext/opcache/zend_accelerator_debug.c
index 7a8cdad0e3..feed711bf5 100644
--- a/ext/opcache/zend_accelerator_debug.c
+++ b/ext/opcache/zend_accelerator_debug.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| Zend OPcache |
+----------------------------------------------------------------------+
- | Copyright (c) 1998-2015 The PHP Group |
+ | Copyright (c) 1998-2014 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -34,7 +34,6 @@ void zend_accel_error(int type, const char *format, ...)
time_t timestamp;
char *time_string;
FILE * fLog = NULL;
- TSRMLS_FETCH();
if (type > ZCG(accel_directives).log_verbosity_level) {
return;
@@ -57,7 +56,7 @@ void zend_accel_error(int type, const char *format, ...)
}
#ifdef ZTS
- fprintf(fLog, "%s (%lu): ", time_string, (unsigned long)tsrm_thread_id());
+ fprintf(fLog, "%s (" ZEND_ULONG_FMT "): ", time_string, (zend_ulong)tsrm_thread_id());
#else
fprintf(fLog, "%s (%d): ", time_string, getpid());
#endif
diff --git a/ext/opcache/zend_accelerator_debug.h b/ext/opcache/zend_accelerator_debug.h
index 540f4e18cf..f773f6220a 100644
--- a/ext/opcache/zend_accelerator_debug.h
+++ b/ext/opcache/zend_accelerator_debug.h
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| Zend OPcache |
+----------------------------------------------------------------------+
- | Copyright (c) 1998-2015 The PHP Group |
+ | Copyright (c) 1998-2014 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
diff --git a/ext/opcache/zend_accelerator_hash.c b/ext/opcache/zend_accelerator_hash.c
index f979081143..671792239b 100644
--- a/ext/opcache/zend_accelerator_hash.c
+++ b/ext/opcache/zend_accelerator_hash.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| Zend OPcache |
+----------------------------------------------------------------------+
- | Copyright (c) 1998-2015 The PHP Group |
+ | Copyright (c) 1998-2014 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -36,7 +36,7 @@ void zend_accel_hash_clean(zend_accel_hash *accel_hash)
memset(accel_hash->hash_table, 0, sizeof(zend_accel_hash_entry *)*accel_hash->max_num_entries);
}
-void zend_accel_hash_init(zend_accel_hash *accel_hash, zend_uint hash_size)
+void zend_accel_hash_init(zend_accel_hash *accel_hash, uint32_t hash_size)
{
uint i;
@@ -71,7 +71,7 @@ void zend_accel_hash_init(zend_accel_hash *accel_hash, zend_uint hash_size)
* Returns pointer the actual hash entry on success
* key needs to be already allocated as it is not copied
*/
-zend_accel_hash_entry* zend_accel_hash_update(zend_accel_hash *accel_hash, char *key, zend_uint key_length, zend_bool indirect, void *data)
+zend_accel_hash_entry* zend_accel_hash_update(zend_accel_hash *accel_hash, char *key, uint32_t key_length, zend_bool indirect, void *data)
{
zend_ulong hash_value;
zend_ulong index;
@@ -140,7 +140,7 @@ zend_accel_hash_entry* zend_accel_hash_update(zend_accel_hash *accel_hash, char
/* Returns the data associated with key on success
* Returns NULL if data doesn't exist
*/
-void* zend_accel_hash_find(zend_accel_hash *accel_hash, char *key, zend_uint key_length)
+void* zend_accel_hash_find(zend_accel_hash *accel_hash, char *key, uint32_t key_length)
{
zend_ulong hash_value;
zend_ulong index;
@@ -168,7 +168,7 @@ void* zend_accel_hash_find(zend_accel_hash *accel_hash, char *key, zend_uint key
/* Returns the hash entry associated with key on success
* Returns NULL if it doesn't exist
*/
-zend_accel_hash_entry* zend_accel_hash_find_entry(zend_accel_hash *accel_hash, char *key, zend_uint key_length)
+zend_accel_hash_entry* zend_accel_hash_find_entry(zend_accel_hash *accel_hash, char *key, uint32_t key_length)
{
zend_ulong hash_value;
zend_ulong index;
@@ -193,9 +193,9 @@ zend_accel_hash_entry* zend_accel_hash_find_entry(zend_accel_hash *accel_hash, c
return NULL;
}
-int zend_accel_hash_unlink(zend_accel_hash *accel_hash, char *key, zend_uint key_length)
+int zend_accel_hash_unlink(zend_accel_hash *accel_hash, char *key, uint32_t key_length)
{
- zend_ulong hash_value;
+ zend_ulong hash_value;
zend_ulong index;
zend_accel_hash_entry *entry, *last_entry=NULL;
diff --git a/ext/opcache/zend_accelerator_hash.h b/ext/opcache/zend_accelerator_hash.h
index 4ec4fc725d..5c995b43ee 100644
--- a/ext/opcache/zend_accelerator_hash.h
+++ b/ext/opcache/zend_accelerator_hash.h
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| Zend OPcache |
+----------------------------------------------------------------------+
- | Copyright (c) 1998-2015 The PHP Group |
+ | Copyright (c) 1998-2014 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -47,7 +47,7 @@ typedef struct _zend_accel_hash_entry zend_accel_hash_entry;
struct _zend_accel_hash_entry {
zend_ulong hash_value;
char *key;
- zend_uint key_length;
+ uint32_t key_length;
zend_accel_hash_entry *next;
void *data;
zend_bool indirect;
@@ -56,35 +56,35 @@ struct _zend_accel_hash_entry {
typedef struct _zend_accel_hash {
zend_accel_hash_entry **hash_table;
zend_accel_hash_entry *hash_entries;
- zend_uint num_entries;
- zend_uint max_num_entries;
- zend_uint num_direct_entries;
+ uint32_t num_entries;
+ uint32_t max_num_entries;
+ uint32_t num_direct_entries;
} zend_accel_hash;
-void zend_accel_hash_init(zend_accel_hash *accel_hash, zend_uint hash_size);
+void zend_accel_hash_init(zend_accel_hash *accel_hash, uint32_t hash_size);
void zend_accel_hash_clean(zend_accel_hash *accel_hash);
zend_accel_hash_entry* zend_accel_hash_update(
zend_accel_hash *accel_hash,
char *key,
- zend_uint key_length,
+ uint32_t key_length,
zend_bool indirect,
void *data);
void* zend_accel_hash_find(
zend_accel_hash *accel_hash,
char *key,
- zend_uint key_length);
+ uint32_t key_length);
zend_accel_hash_entry* zend_accel_hash_find_entry(
zend_accel_hash *accel_hash,
char *key,
- zend_uint key_length);
+ uint32_t key_length);
int zend_accel_hash_unlink(
zend_accel_hash *accel_hash,
char *key,
- zend_uint key_length);
+ uint32_t key_length);
static inline zend_bool zend_accel_hash_is_full(zend_accel_hash *accel_hash)
{
diff --git a/ext/opcache/zend_accelerator_module.c b/ext/opcache/zend_accelerator_module.c
index 979a730238..8bf6a2e0ab 100644
--- a/ext/opcache/zend_accelerator_module.c
+++ b/ext/opcache/zend_accelerator_module.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| Zend OPcache |
+----------------------------------------------------------------------+
- | Copyright (c) 1998-2015 The PHP Group |
+ | Copyright (c) 1998-2014 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -28,11 +28,7 @@
#include "zend_accelerator_blacklist.h"
#include "php_ini.h"
#include "SAPI.h"
-#if ZEND_EXTENSION_API_NO > PHP_5_5_X_API_NO
-# include "zend_virtual_cwd.h"
-#else
-# include "TSRM/tsrm_virtual_cwd.h"
-#endif
+#include "zend_virtual_cwd.h"
#include "ext/standard/info.h"
#include "ext/standard/php_filestat.h"
@@ -87,7 +83,7 @@ static zend_function_entry accel_functions[] = {
{ NULL, NULL, NULL, 0, 0 }
};
-static int validate_api_restriction(TSRMLS_D)
+static int validate_api_restriction(void)
{
if (ZCG(accel_directives).restrict_api && *ZCG(accel_directives).restrict_api) {
int len = strlen(ZCG(accel_directives).restrict_api);
@@ -98,14 +94,14 @@ static int validate_api_restriction(TSRMLS_D)
zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME " API is restricted by \"restrict_api\" configuration directive");
return 0;
}
- }
+ }
return 1;
}
static ZEND_INI_MH(OnUpdateMemoryConsumption)
{
- long *p;
- long memsize;
+ zend_long *p;
+ zend_long memsize;
#ifndef ZTS
char *base = (char *) mh_arg2;
#else
@@ -113,10 +109,10 @@ static ZEND_INI_MH(OnUpdateMemoryConsumption)
#endif
/* keep the compiler happy */
- (void)entry; (void)new_value_length; (void)mh_arg2; (void)mh_arg3; (void)stage;
+ (void)entry; (void)mh_arg2; (void)mh_arg3; (void)stage;
- p = (long *) (base + (size_t)mh_arg1);
- memsize = atoi(new_value);
+ p = (zend_long *) (base + (size_t)mh_arg1);
+ memsize = atoi(new_value->val);
/* sanity check we must use at least 8 MB */
if (memsize < 8) {
const char *new_new_value = "8";
@@ -126,15 +122,13 @@ static ZEND_INI_MH(OnUpdateMemoryConsumption)
zend_accel_error(ACCEL_LOG_WARNING, "opcache.memory_consumption is set below the required 8MB.\n");
zend_accel_error(ACCEL_LOG_WARNING, ACCELERATOR_PRODUCT_NAME " will use the minimal 8MB configuration.\n");
- if (zend_hash_find(EG(ini_directives),
+ if ((ini_entry = zend_hash_str_find_ptr(EG(ini_directives),
"opcache.memory_consumption",
- sizeof("opcache.memory_consumption"),
- (void *) &ini_entry) == FAILURE) {
+ sizeof("opcache.memory_consumption")-1)) == NULL) {
return FAILURE;
}
- ini_entry->value = strdup(new_new_value);
- ini_entry->value_length = strlen(new_new_value);
+ ini_entry->value = zend_string_init(new_new_value, 1, 1);
}
*p = memsize * (1024 * 1024);
return SUCCESS;
@@ -142,8 +136,8 @@ static ZEND_INI_MH(OnUpdateMemoryConsumption)
static ZEND_INI_MH(OnUpdateMaxAcceleratedFiles)
{
- long *p;
- long size;
+ zend_long *p;
+ zend_long size;
#ifndef ZTS
char *base = (char *) mh_arg2;
#else
@@ -151,10 +145,10 @@ static ZEND_INI_MH(OnUpdateMaxAcceleratedFiles)
#endif
/* keep the compiler happy */
- (void)entry; (void)new_value_length; (void)mh_arg2; (void)mh_arg3; (void)stage;
+ (void)entry; (void)mh_arg2; (void)mh_arg3; (void)stage;
- p = (long *) (base + (size_t)mh_arg1);
- size = atoi(new_value);
+ p = (zend_long *) (base + (size_t)mh_arg1);
+ size = atoi(new_value->val);
/* sanity check we must use a value between MIN_ACCEL_FILES and MAX_ACCEL_FILES */
if (size < MIN_ACCEL_FILES || size > MAX_ACCEL_FILES) {
@@ -173,14 +167,12 @@ static ZEND_INI_MH(OnUpdateMaxAcceleratedFiles)
zend_accel_error(ACCEL_LOG_WARNING, "opcache.max_accelerated_files is set above the limit (%d).\n", MAX_ACCEL_FILES);
zend_accel_error(ACCEL_LOG_WARNING, ACCELERATOR_PRODUCT_NAME " will use the maximal configuration.\n");
}
- if (zend_hash_find(EG(ini_directives),
+ if ((ini_entry = zend_hash_str_find_ptr(EG(ini_directives),
"opcache.max_accelerated_files",
- sizeof("opcache.max_accelerated_files"),
- (void *) &ini_entry) == FAILURE) {
+ sizeof("opcache.max_accelerated_files")-1)) == NULL) {
return FAILURE;
}
- ini_entry->value = strdup(new_new_value);
- ini_entry->value_length = strlen(new_new_value);
+ ini_entry->value = zend_string_init(new_new_value, strlen(new_new_value), 1);
}
*p = size;
return SUCCESS;
@@ -189,7 +181,7 @@ static ZEND_INI_MH(OnUpdateMaxAcceleratedFiles)
static ZEND_INI_MH(OnUpdateMaxWastedPercentage)
{
double *p;
- long percentage;
+ zend_long percentage;
#ifndef ZTS
char *base = (char *) mh_arg2;
#else
@@ -197,10 +189,10 @@ static ZEND_INI_MH(OnUpdateMaxWastedPercentage)
#endif
/* keep the compiler happy */
- (void)entry; (void)new_value_length; (void)mh_arg2; (void)mh_arg3; (void)stage;
+ (void)entry; (void)mh_arg2; (void)mh_arg3; (void)stage;
p = (double *) (base + (size_t)mh_arg1);
- percentage = atoi(new_value);
+ percentage = atoi(new_value->val);
if (percentage <= 0 || percentage > 50) {
const char *new_new_value = "5";
@@ -209,14 +201,12 @@ static ZEND_INI_MH(OnUpdateMaxWastedPercentage)
percentage = 5;
zend_accel_error(ACCEL_LOG_WARNING, "opcache.max_wasted_percentage must be set between 1 and 50.\n");
zend_accel_error(ACCEL_LOG_WARNING, ACCELERATOR_PRODUCT_NAME " will use 5%.\n");
- if (zend_hash_find(EG(ini_directives),
+ if ((ini_entry = zend_hash_str_find_ptr(EG(ini_directives),
"opcache.max_wasted_percentage",
- sizeof("opcache.max_wasted_percentage"),
- (void *) &ini_entry) == FAILURE) {
+ sizeof("opcache.max_wasted_percentage")-1)) == NULL) {
return FAILURE;
}
- ini_entry->value = strdup(new_new_value);
- ini_entry->value_length = strlen(new_new_value);
+ ini_entry->value = zend_string_init(new_new_value, strlen(new_new_value), 1);
}
*p = (double)percentage / 100.0;
return SUCCESS;
@@ -227,7 +217,7 @@ static ZEND_INI_MH(OnEnable)
if (stage == ZEND_INI_STAGE_STARTUP ||
stage == ZEND_INI_STAGE_SHUTDOWN ||
stage == ZEND_INI_STAGE_DEACTIVATE) {
- return OnUpdateBool(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
+ return OnUpdateBool(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
} else {
/* It may be only temporary disabled */
zend_bool *p;
@@ -238,10 +228,10 @@ static ZEND_INI_MH(OnEnable)
#endif
p = (zend_bool *) (base+(size_t) mh_arg1);
- if ((new_value_length == 2 && strcasecmp("on", new_value) == 0) ||
- (new_value_length == 3 && strcasecmp("yes", new_value) == 0) ||
- (new_value_length == 4 && strcasecmp("true", new_value) == 0) ||
- atoi(new_value) != 0) {
+ if ((new_value->len == 2 && strcasecmp("on", new_value->val) == 0) ||
+ (new_value->len == 3 && strcasecmp("yes", new_value->val) == 0) ||
+ (new_value->len == 4 && strcasecmp("true", new_value->val) == 0) ||
+ atoi(new_value->val) != 0) {
zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME " can't be temporary enabled (it may be only disabled till the end of request)");
return FAILURE;
} else {
@@ -252,7 +242,7 @@ static ZEND_INI_MH(OnEnable)
}
ZEND_INI_BEGIN()
- STD_PHP_INI_BOOLEAN("opcache.enable" , "1", PHP_INI_ALL, OnEnable, enabled , zend_accel_globals, accel_globals)
+ STD_PHP_INI_BOOLEAN("opcache.enable" , "1", PHP_INI_ALL, OnEnable, enabled , zend_accel_globals, accel_globals)
STD_PHP_INI_BOOLEAN("opcache.use_cwd" , "1", PHP_INI_SYSTEM, OnUpdateBool, accel_directives.use_cwd , zend_accel_globals, accel_globals)
STD_PHP_INI_BOOLEAN("opcache.validate_timestamps", "1", PHP_INI_ALL , OnUpdateBool, accel_directives.validate_timestamps, zend_accel_globals, accel_globals)
STD_PHP_INI_BOOLEAN("opcache.inherited_hack" , "1", PHP_INI_SYSTEM, OnUpdateBool, accel_directives.inherited_hack , zend_accel_globals, accel_globals)
@@ -261,9 +251,7 @@ ZEND_INI_BEGIN()
STD_PHP_INI_ENTRY("opcache.log_verbosity_level" , "1" , PHP_INI_SYSTEM, OnUpdateLong, accel_directives.log_verbosity_level, zend_accel_globals, accel_globals)
STD_PHP_INI_ENTRY("opcache.memory_consumption" , "64" , PHP_INI_SYSTEM, OnUpdateMemoryConsumption, accel_directives.memory_consumption, zend_accel_globals, accel_globals)
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
STD_PHP_INI_ENTRY("opcache.interned_strings_buffer", "4" , PHP_INI_SYSTEM, OnUpdateLong, accel_directives.interned_strings_buffer, zend_accel_globals, accel_globals)
-#endif
STD_PHP_INI_ENTRY("opcache.max_accelerated_files" , "2000", PHP_INI_SYSTEM, OnUpdateMaxAcceleratedFiles, accel_directives.max_accelerated_files, zend_accel_globals, accel_globals)
STD_PHP_INI_ENTRY("opcache.max_wasted_percentage" , "5" , PHP_INI_SYSTEM, OnUpdateMaxWastedPercentage, accel_directives.max_wasted_percentage, zend_accel_globals, accel_globals)
STD_PHP_INI_ENTRY("opcache.consistency_checks" , "0" , PHP_INI_ALL , OnUpdateLong, accel_directives.consistency_checks, zend_accel_globals, accel_globals)
@@ -290,27 +278,7 @@ ZEND_INI_BEGIN()
#endif
ZEND_INI_END()
-#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
-
-#undef EX
-#define EX(element) execute_data->element
-#define EX_T(offset) (*(temp_variable *)((char *) EX(Ts) + offset))
-
-static int ZEND_DECLARE_INHERITED_CLASS_DELAYED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- zend_class_entry **pce, **pce_orig;
-
- if (zend_hash_find(EG(class_table), Z_STRVAL(EX(opline)->op2.u.constant), Z_STRLEN(EX(opline)->op2.u.constant) + 1, (void **)&pce) == FAILURE ||
- (zend_hash_find(EG(class_table), Z_STRVAL(EX(opline)->op1.u.constant), Z_STRLEN(EX(opline)->op1.u.constant), (void**)&pce_orig) == SUCCESS &&
- *pce != *pce_orig)) {
- do_bind_inherited_class(EX(opline), EG(class_table), EX_T(EX(opline)->extended_value).class_entry, 0 TSRMLS_CC);
- }
- EX(opline)++;
- return ZEND_USER_OPCODE_CONTINUE;
-}
-#endif
-
-static int filename_is_in_cache(char *filename, int filename_len TSRMLS_DC)
+static int filename_is_in_cache(char *filename, int filename_len)
{
char *key;
int key_length;
@@ -321,17 +289,17 @@ static int filename_is_in_cache(char *filename, int filename_len TSRMLS_DC)
handle.type = ZEND_HANDLE_FILENAME;
if (IS_ABSOLUTE_PATH(filename, filename_len)) {
- persistent_script = zend_accel_hash_find(&ZCSG(hash), filename, filename_len + 1);
+ persistent_script = zend_accel_hash_find(&ZCSG(hash), filename, filename_len);
if (persistent_script) {
return !persistent_script->corrupted &&
- validate_timestamp_and_record(persistent_script, &handle TSRMLS_CC) == SUCCESS;
+ validate_timestamp_and_record(persistent_script, &handle) == SUCCESS;
}
}
- if ((key = accel_make_persistent_key_ex(&handle, filename_len, &key_length TSRMLS_CC)) != NULL) {
- persistent_script = zend_accel_hash_find(&ZCSG(hash), key, key_length + 1);
+ if ((key = accel_make_persistent_key_ex(&handle, filename_len, &key_length)) != NULL) {
+ persistent_script = zend_accel_hash_find(&ZCSG(hash), key, key_length);
return persistent_script && !persistent_script->corrupted &&
- validate_timestamp_and_record(persistent_script, &handle TSRMLS_CC) == SUCCESS;
+ validate_timestamp_and_record(persistent_script, &handle) == SUCCESS;
}
return 0;
@@ -339,15 +307,15 @@ static int filename_is_in_cache(char *filename, int filename_len TSRMLS_DC)
static int accel_file_in_cache(INTERNAL_FUNCTION_PARAMETERS)
{
- zval **zfilename;
+ zval zfilename;
if (ZEND_NUM_ARGS() != 1 ||
zend_get_parameters_array_ex(1, &zfilename) == FAILURE ||
- Z_TYPE_PP(zfilename) != IS_STRING ||
- Z_STRLEN_PP(zfilename) == 0) {
+ Z_TYPE(zfilename) != IS_STRING ||
+ Z_STRLEN(zfilename) == 0) {
return 0;
}
- return filename_is_in_cache(Z_STRVAL_PP(zfilename), Z_STRLEN_PP(zfilename) TSRMLS_CC);
+ return filename_is_in_cache(Z_STRVAL(zfilename), Z_STRLEN(zfilename));
}
static void accel_file_exists(INTERNAL_FUNCTION_PARAMETERS)
@@ -382,26 +350,24 @@ static ZEND_MINIT_FUNCTION(zend_accelerator)
(void)type; /* keep the compiler happy */
REGISTER_INI_ENTRIES();
-#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
- zend_set_user_opcode_handler(ZEND_DECLARE_INHERITED_CLASS_DELAYED, ZEND_DECLARE_INHERITED_CLASS_DELAYED_HANDLER);
-#endif
+
return SUCCESS;
}
-void zend_accel_override_file_functions(TSRMLS_D)
+void zend_accel_override_file_functions(void)
{
zend_function *old_function;
if (ZCG(enabled) && accel_startup_ok && ZCG(accel_directives).file_override_enabled) {
/* override file_exists */
- if (zend_hash_find(CG(function_table), "file_exists", sizeof("file_exists"), (void **)&old_function) == SUCCESS) {
+ if ((old_function = zend_hash_str_find_ptr(CG(function_table), "file_exists", sizeof("file_exists")-1)) != NULL) {
orig_file_exists = old_function->internal_function.handler;
old_function->internal_function.handler = accel_file_exists;
}
- if (zend_hash_find(CG(function_table), "is_file", sizeof("is_file"), (void **)&old_function) == SUCCESS) {
+ if ((old_function = zend_hash_str_find_ptr(CG(function_table), "is_file", sizeof("is_file")-1)) != NULL) {
orig_is_file = old_function->internal_function.handler;
old_function->internal_function.handler = accel_is_file;
}
- if (zend_hash_find(CG(function_table), "is_readable", sizeof("is_readable"), (void **)&old_function) == SUCCESS) {
+ if ((old_function = zend_hash_str_find_ptr(CG(function_table), "is_readable", sizeof("is_readable")-1)) != NULL) {
orig_is_readable = old_function->internal_function.handler;
old_function->internal_function.handler = accel_is_readable;
}
@@ -413,7 +379,7 @@ static ZEND_MSHUTDOWN_FUNCTION(zend_accelerator)
(void)type; /* keep the compiler happy */
UNREGISTER_INI_ENTRIES();
- accel_shutdown(TSRMLS_C);
+ accel_shutdown();
return SUCCESS;
}
@@ -438,35 +404,33 @@ void zend_accel_info(ZEND_MODULE_INFO_FUNC_ARGS)
char buf[32];
php_info_print_table_row(2, "Startup", "OK");
php_info_print_table_row(2, "Shared memory model", zend_accel_get_shared_model());
- snprintf(buf, sizeof(buf), "%ld", ZCSG(hits));
+ snprintf(buf, sizeof(buf), "%pd", (zend_ulong)ZCSG(hits));
php_info_print_table_row(2, "Cache hits", buf);
- snprintf(buf, sizeof(buf), "%ld", ZSMMG(memory_exhausted)?ZCSG(misses):ZCSG(misses)-ZCSG(blacklist_misses));
+ snprintf(buf, sizeof(buf), "%pd", ZSMMG(memory_exhausted)?ZCSG(misses):ZCSG(misses)-ZCSG(blacklist_misses));
php_info_print_table_row(2, "Cache misses", buf);
- snprintf(buf, sizeof(buf), "%ld", ZCG(accel_directives).memory_consumption-zend_shared_alloc_get_free_memory()-ZSMMG(wasted_shared_memory));
+ snprintf(buf, sizeof(buf), ZEND_LONG_FMT, ZCG(accel_directives).memory_consumption-zend_shared_alloc_get_free_memory()-ZSMMG(wasted_shared_memory));
php_info_print_table_row(2, "Used memory", buf);
- snprintf(buf, sizeof(buf), "%ld", zend_shared_alloc_get_free_memory());
+ snprintf(buf, sizeof(buf), "%pd", zend_shared_alloc_get_free_memory());
php_info_print_table_row(2, "Free memory", buf);
- snprintf(buf, sizeof(buf), "%ld", ZSMMG(wasted_shared_memory));
+ snprintf(buf, sizeof(buf), "%pd", ZSMMG(wasted_shared_memory));
php_info_print_table_row(2, "Wasted memory", buf);
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
if (ZCSG(interned_strings_start) && ZCSG(interned_strings_end) && ZCSG(interned_strings_top)) {
- snprintf(buf, sizeof(buf), "%ld", ZCSG(interned_strings_top) - ZCSG(interned_strings_start));
+ snprintf(buf, sizeof(buf), "%pd", ZCSG(interned_strings_top) - ZCSG(interned_strings_start));
php_info_print_table_row(2, "Interned Strings Used memory", buf);
- snprintf(buf, sizeof(buf), "%ld", ZCSG(interned_strings_end) - ZCSG(interned_strings_top));
+ snprintf(buf, sizeof(buf), "%pd", ZCSG(interned_strings_end) - ZCSG(interned_strings_top));
php_info_print_table_row(2, "Interned Strings Free memory", buf);
}
-#endif
snprintf(buf, sizeof(buf), "%ld", ZCSG(hash).num_direct_entries);
php_info_print_table_row(2, "Cached scripts", buf);
snprintf(buf, sizeof(buf), "%ld", ZCSG(hash).num_entries);
php_info_print_table_row(2, "Cached keys", buf);
- snprintf(buf, sizeof(buf), "%ld", ZCSG(hash).max_num_entries);
+ snprintf(buf, sizeof(buf), "%pd", ZCSG(hash).max_num_entries);
php_info_print_table_row(2, "Max keys", buf);
- snprintf(buf, sizeof(buf), "%ld", ZCSG(oom_restarts));
+ snprintf(buf, sizeof(buf), "%pd", ZCSG(oom_restarts));
php_info_print_table_row(2, "OOM restarts", buf);
- snprintf(buf, sizeof(buf), "%ld", ZCSG(hash_restarts));
+ snprintf(buf, sizeof(buf), "%pd", ZCSG(hash_restarts));
php_info_print_table_row(2, "Hash keys restarts", buf);
- snprintf(buf, sizeof(buf), "%ld", ZCSG(manual_restarts));
+ snprintf(buf, sizeof(buf), "%pd", ZCSG(manual_restarts));
php_info_print_table_row(2, "Manual restarts", buf);
}
}
@@ -484,7 +448,7 @@ static zend_module_entry accel_module_entry = {
NULL,
NULL,
zend_accel_info,
- ACCELERATOR_VERSION "FE",
+ ACCELERATOR_VERSION "FE",
STANDARD_MODULE_PROPERTIES
};
@@ -495,20 +459,19 @@ int start_accel_module(void)
/* {{{ proto array accelerator_get_scripts()
Get the scripts which are accelerated by ZendAccelerator */
-static zval* accelerator_get_scripts(TSRMLS_D)
+static int accelerator_get_scripts(zval *return_value)
{
uint i;
- zval *return_value,*persistent_script_report;
+ zval persistent_script_report;
zend_accel_hash_entry *cache_entry;
struct tm *ta;
struct timeval exec_time;
struct timeval fetch_time;
- if (!ZCG(enabled) || !accel_startup_ok || !ZCSG(accelerator_enabled) || accelerator_shm_read_lock(TSRMLS_C) != SUCCESS) {
+ if (!ZCG(enabled) || !accel_startup_ok || !ZCSG(accelerator_enabled) || accelerator_shm_read_lock() != SUCCESS) {
return 0;
}
- MAKE_STD_ZVAL(return_value);
array_init(return_value);
for (i = 0; i<ZCSG(hash).max_num_entries; i++) {
for (cache_entry = ZCSG(hash).hash_table[i]; cache_entry; cache_entry = cache_entry->next) {
@@ -520,47 +483,43 @@ static zval* accelerator_get_scripts(TSRMLS_D)
script = (zend_persistent_script *)cache_entry->data;
- MAKE_STD_ZVAL(persistent_script_report);
- array_init(persistent_script_report);
- add_assoc_stringl(persistent_script_report, "full_path", script->full_path, script->full_path_len, 1);
- add_assoc_long(persistent_script_report, "hits", script->dynamic_members.hits);
- add_assoc_long(persistent_script_report, "memory_consumption", script->dynamic_members.memory_consumption);
+ array_init(&persistent_script_report);
+ add_assoc_str(&persistent_script_report, "full_path", zend_string_dup(script->full_path, 0));
+ add_assoc_long(&persistent_script_report, "hits", (zend_long)script->dynamic_members.hits);
+ add_assoc_long(&persistent_script_report, "memory_consumption", script->dynamic_members.memory_consumption);
ta = localtime(&script->dynamic_members.last_used);
str = asctime(ta);
len = strlen(str);
if (len > 0 && str[len - 1] == '\n') len--;
- add_assoc_stringl(persistent_script_report, "last_used", str, len, 1);
- add_assoc_long(persistent_script_report, "last_used_timestamp", script->dynamic_members.last_used);
+ add_assoc_stringl(&persistent_script_report, "last_used", str, len);
+ add_assoc_long(&persistent_script_report, "last_used_timestamp", script->dynamic_members.last_used);
if (ZCG(accel_directives).validate_timestamps) {
- add_assoc_long(persistent_script_report, "timestamp", (long)script->timestamp);
+ add_assoc_long(&persistent_script_report, "timestamp", (zend_long)script->timestamp);
}
timerclear(&exec_time);
timerclear(&fetch_time);
- zend_hash_update(return_value->value.ht, cache_entry->key, cache_entry->key_length, &persistent_script_report, sizeof(zval *), NULL);
+ zend_hash_str_update(Z_ARRVAL_P(return_value), cache_entry->key, cache_entry->key_length, &persistent_script_report);
}
}
- accelerator_shm_read_unlock(TSRMLS_C);
+ accelerator_shm_read_unlock();
- return return_value;
+ return 1;
}
/* {{{ proto array accelerator_get_status([bool fetch_scripts])
Obtain statistics information regarding code acceleration */
static ZEND_FUNCTION(opcache_get_status)
{
- long reqs;
- zval *memory_usage,*statistics,*scripts;
+ zend_long reqs;
+ zval memory_usage, statistics, scripts;
zend_bool fetch_scripts = 1;
- /* keep the compiler happy */
- (void)ht; (void)return_value_ptr; (void)this_ptr; (void)return_value_used;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &fetch_scripts) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &fetch_scripts) == FAILURE) {
return;
}
-
- if (!validate_api_restriction(TSRMLS_C)) {
+
+ if (!validate_api_restriction()) {
RETURN_FALSE;
}
@@ -577,59 +536,53 @@ static ZEND_FUNCTION(opcache_get_status)
add_assoc_bool(return_value, "restart_in_progress", ZCSG(restart_in_progress));
/* Memory usage statistics */
- MAKE_STD_ZVAL(memory_usage);
- array_init(memory_usage);
- add_assoc_long(memory_usage, "used_memory", ZCG(accel_directives).memory_consumption-zend_shared_alloc_get_free_memory()-ZSMMG(wasted_shared_memory));
- add_assoc_long(memory_usage, "free_memory", zend_shared_alloc_get_free_memory());
- add_assoc_long(memory_usage, "wasted_memory", ZSMMG(wasted_shared_memory));
- add_assoc_double(memory_usage, "current_wasted_percentage", (((double) ZSMMG(wasted_shared_memory))/ZCG(accel_directives).memory_consumption)*100.0);
- add_assoc_zval(return_value, "memory_usage", memory_usage);
-
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
+ array_init(&memory_usage);
+ add_assoc_long(&memory_usage, "used_memory", ZCG(accel_directives).memory_consumption-zend_shared_alloc_get_free_memory()-ZSMMG(wasted_shared_memory));
+ add_assoc_long(&memory_usage, "free_memory", zend_shared_alloc_get_free_memory());
+ add_assoc_long(&memory_usage, "wasted_memory", ZSMMG(wasted_shared_memory));
+ add_assoc_double(&memory_usage, "current_wasted_percentage", (((double) ZSMMG(wasted_shared_memory))/ZCG(accel_directives).memory_consumption)*100.0);
+ add_assoc_zval(return_value, "memory_usage", &memory_usage);
+
if (ZCSG(interned_strings_start) && ZCSG(interned_strings_end) && ZCSG(interned_strings_top)) {
- zval *interned_strings_usage;
+ zval interned_strings_usage;
- MAKE_STD_ZVAL(interned_strings_usage);
- array_init(interned_strings_usage);
- add_assoc_long(interned_strings_usage, "buffer_size", ZCSG(interned_strings_end) - ZCSG(interned_strings_start));
- add_assoc_long(interned_strings_usage, "used_memory", ZCSG(interned_strings_top) - ZCSG(interned_strings_start));
- add_assoc_long(interned_strings_usage, "free_memory", ZCSG(interned_strings_end) - ZCSG(interned_strings_top));
- add_assoc_long(interned_strings_usage, "number_of_strings", ZCSG(interned_strings).nNumOfElements);
- add_assoc_zval(return_value, "interned_strings_usage", interned_strings_usage);
+ array_init(&interned_strings_usage);
+ add_assoc_long(&interned_strings_usage, "buffer_size", ZCSG(interned_strings_end) - ZCSG(interned_strings_start));
+ add_assoc_long(&interned_strings_usage, "used_memory", ZCSG(interned_strings_top) - ZCSG(interned_strings_start));
+ add_assoc_long(&interned_strings_usage, "free_memory", ZCSG(interned_strings_end) - ZCSG(interned_strings_top));
+ add_assoc_long(&interned_strings_usage, "number_of_strings", ZCSG(interned_strings).nNumOfElements);
+ add_assoc_zval(return_value, "interned_strings_usage", &interned_strings_usage);
}
-#endif
-
+
/* Accelerator statistics */
- MAKE_STD_ZVAL(statistics);
- array_init(statistics);
- add_assoc_long(statistics, "num_cached_scripts", ZCSG(hash).num_direct_entries);
- add_assoc_long(statistics, "num_cached_keys", ZCSG(hash).num_entries);
- add_assoc_long(statistics, "max_cached_keys", ZCSG(hash).max_num_entries);
- add_assoc_long(statistics, "hits", ZCSG(hits));
- add_assoc_long(statistics, "start_time", ZCSG(start_time));
- add_assoc_long(statistics, "last_restart_time", ZCSG(last_restart_time));
- add_assoc_long(statistics, "oom_restarts", ZCSG(oom_restarts));
- add_assoc_long(statistics, "hash_restarts", ZCSG(hash_restarts));
- add_assoc_long(statistics, "manual_restarts", ZCSG(manual_restarts));
- add_assoc_long(statistics, "misses", ZSMMG(memory_exhausted)?ZCSG(misses):ZCSG(misses)-ZCSG(blacklist_misses));
- add_assoc_long(statistics, "blacklist_misses", ZCSG(blacklist_misses));
+ array_init(&statistics);
+ add_assoc_long(&statistics, "num_cached_scripts", ZCSG(hash).num_direct_entries);
+ add_assoc_long(&statistics, "num_cached_keys", ZCSG(hash).num_entries);
+ add_assoc_long(&statistics, "max_cached_keys", ZCSG(hash).max_num_entries);
+ add_assoc_long(&statistics, "hits", (zend_long)ZCSG(hits));
+ add_assoc_long(&statistics, "start_time", ZCSG(start_time));
+ add_assoc_long(&statistics, "last_restart_time", ZCSG(last_restart_time));
+ add_assoc_long(&statistics, "oom_restarts", ZCSG(oom_restarts));
+ add_assoc_long(&statistics, "hash_restarts", ZCSG(hash_restarts));
+ add_assoc_long(&statistics, "manual_restarts", ZCSG(manual_restarts));
+ add_assoc_long(&statistics, "misses", ZSMMG(memory_exhausted)?ZCSG(misses):ZCSG(misses)-ZCSG(blacklist_misses));
+ add_assoc_long(&statistics, "blacklist_misses", ZCSG(blacklist_misses));
reqs = ZCSG(hits)+ZCSG(misses);
- add_assoc_double(statistics, "blacklist_miss_ratio", reqs?(((double) ZCSG(blacklist_misses))/reqs)*100.0:0);
- add_assoc_double(statistics, "opcache_hit_rate", reqs?(((double) ZCSG(hits))/reqs)*100.0:0);
- add_assoc_zval(return_value, "opcache_statistics", statistics);
+ add_assoc_double(&statistics, "blacklist_miss_ratio", reqs?(((double) ZCSG(blacklist_misses))/reqs)*100.0:0);
+ add_assoc_double(&statistics, "opcache_hit_rate", reqs?(((double) ZCSG(hits))/reqs)*100.0:0);
+ add_assoc_zval(return_value, "opcache_statistics", &statistics);
if (fetch_scripts) {
/* accelerated scripts */
- scripts = accelerator_get_scripts(TSRMLS_C);
- if (scripts) {
- add_assoc_zval(return_value, "scripts", scripts);
+ if (accelerator_get_scripts(&scripts)) {
+ add_assoc_zval(return_value, "scripts", &scripts);
}
}
}
-static int add_blacklist_path(zend_blacklist_entry *p, zval *return_value TSRMLS_DC)
+static int add_blacklist_path(zend_blacklist_entry *p, zval *return_value)
{
- add_next_index_stringl(return_value, p->path, p->path_length, 1);
+ add_next_index_stringl(return_value, p->path, p->path_length);
return 0;
}
@@ -637,86 +590,71 @@ static int add_blacklist_path(zend_blacklist_entry *p, zval *return_value TSRMLS
Obtain configuration information */
static ZEND_FUNCTION(opcache_get_configuration)
{
- zval *directives,*version,*blacklist;
+ zval directives, version, blacklist;
- /* keep the compiler happy */
- (void)ht; (void)return_value_ptr; (void)this_ptr; (void)return_value_used;
-
-#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
if (zend_parse_parameters_none() == FAILURE) {
RETURN_FALSE;
}
-#endif
- if (!validate_api_restriction(TSRMLS_C)) {
+ if (!validate_api_restriction()) {
RETURN_FALSE;
}
array_init(return_value);
/* directives */
- MAKE_STD_ZVAL(directives);
- array_init(directives);
- add_assoc_bool(directives, "opcache.enable", ZCG(enabled));
- add_assoc_bool(directives, "opcache.enable_cli", ZCG(accel_directives).enable_cli);
- add_assoc_bool(directives, "opcache.use_cwd", ZCG(accel_directives).use_cwd);
- add_assoc_bool(directives, "opcache.validate_timestamps", ZCG(accel_directives).validate_timestamps);
- add_assoc_bool(directives, "opcache.inherited_hack", ZCG(accel_directives).inherited_hack);
- add_assoc_bool(directives, "opcache.dups_fix", ZCG(accel_directives).ignore_dups);
- add_assoc_bool(directives, "opcache.revalidate_path", ZCG(accel_directives).revalidate_path);
-
- add_assoc_long(directives, "opcache.log_verbosity_level", ZCG(accel_directives).log_verbosity_level);
- add_assoc_long(directives, "opcache.memory_consumption", ZCG(accel_directives).memory_consumption);
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
- add_assoc_long(directives, "opcache.interned_strings_buffer",ZCG(accel_directives).interned_strings_buffer);
-#endif
- add_assoc_long(directives, "opcache.max_accelerated_files", ZCG(accel_directives).max_accelerated_files);
- add_assoc_double(directives, "opcache.max_wasted_percentage", ZCG(accel_directives).max_wasted_percentage);
- add_assoc_long(directives, "opcache.consistency_checks", ZCG(accel_directives).consistency_checks);
- add_assoc_long(directives, "opcache.force_restart_timeout", ZCG(accel_directives).force_restart_timeout);
- add_assoc_long(directives, "opcache.revalidate_freq", ZCG(accel_directives).revalidate_freq);
- add_assoc_string(directives, "opcache.preferred_memory_model", STRING_NOT_NULL(ZCG(accel_directives).memory_model), 1);
- add_assoc_string(directives, "opcache.blacklist_filename", STRING_NOT_NULL(ZCG(accel_directives).user_blacklist_filename), 1);
- add_assoc_long(directives, "opcache.max_file_size", ZCG(accel_directives).max_file_size);
- add_assoc_string(directives, "opcache.error_log", STRING_NOT_NULL(ZCG(accel_directives).error_log), 1);
-
- add_assoc_bool(directives, "opcache.protect_memory", ZCG(accel_directives).protect_memory);
- add_assoc_bool(directives, "opcache.save_comments", ZCG(accel_directives).save_comments);
- add_assoc_bool(directives, "opcache.load_comments", ZCG(accel_directives).load_comments);
- add_assoc_bool(directives, "opcache.fast_shutdown", ZCG(accel_directives).fast_shutdown);
- add_assoc_bool(directives, "opcache.enable_file_override", ZCG(accel_directives).file_override_enabled);
- add_assoc_long(directives, "opcache.optimization_level", ZCG(accel_directives).optimization_level);
-
- add_assoc_zval(return_value, "directives", directives);
+ array_init(&directives);
+ add_assoc_bool(&directives, "opcache.enable", ZCG(enabled));
+ add_assoc_bool(&directives, "opcache.enable_cli", ZCG(accel_directives).enable_cli);
+ add_assoc_bool(&directives, "opcache.use_cwd", ZCG(accel_directives).use_cwd);
+ add_assoc_bool(&directives, "opcache.validate_timestamps", ZCG(accel_directives).validate_timestamps);
+ add_assoc_bool(&directives, "opcache.inherited_hack", ZCG(accel_directives).inherited_hack);
+ add_assoc_bool(&directives, "opcache.dups_fix", ZCG(accel_directives).ignore_dups);
+ add_assoc_bool(&directives, "opcache.revalidate_path", ZCG(accel_directives).revalidate_path);
+
+ add_assoc_long(&directives, "opcache.log_verbosity_level", ZCG(accel_directives).log_verbosity_level);
+ add_assoc_long(&directives, "opcache.memory_consumption", ZCG(accel_directives).memory_consumption);
+ add_assoc_long(&directives, "opcache.interned_strings_buffer",ZCG(accel_directives).interned_strings_buffer);
+ add_assoc_long(&directives, "opcache.max_accelerated_files", ZCG(accel_directives).max_accelerated_files);
+ add_assoc_double(&directives, "opcache.max_wasted_percentage", ZCG(accel_directives).max_wasted_percentage);
+ add_assoc_long(&directives, "opcache.consistency_checks", ZCG(accel_directives).consistency_checks);
+ add_assoc_long(&directives, "opcache.force_restart_timeout", ZCG(accel_directives).force_restart_timeout);
+ add_assoc_long(&directives, "opcache.revalidate_freq", ZCG(accel_directives).revalidate_freq);
+ add_assoc_string(&directives, "opcache.preferred_memory_model", STRING_NOT_NULL(ZCG(accel_directives).memory_model));
+ add_assoc_string(&directives, "opcache.blacklist_filename", STRING_NOT_NULL(ZCG(accel_directives).user_blacklist_filename));
+ add_assoc_long(&directives, "opcache.max_file_size", ZCG(accel_directives).max_file_size);
+ add_assoc_string(&directives, "opcache.error_log", STRING_NOT_NULL(ZCG(accel_directives).error_log));
+
+ add_assoc_bool(&directives, "opcache.protect_memory", ZCG(accel_directives).protect_memory);
+ add_assoc_bool(&directives, "opcache.save_comments", ZCG(accel_directives).save_comments);
+ add_assoc_bool(&directives, "opcache.load_comments", ZCG(accel_directives).load_comments);
+ add_assoc_bool(&directives, "opcache.fast_shutdown", ZCG(accel_directives).fast_shutdown);
+ add_assoc_bool(&directives, "opcache.enable_file_override", ZCG(accel_directives).file_override_enabled);
+ add_assoc_long(&directives, "opcache.optimization_level", ZCG(accel_directives).optimization_level);
+
+ add_assoc_zval(return_value, "directives", &directives);
/*version */
- MAKE_STD_ZVAL(version);
- array_init(version);
- add_assoc_string(version, "version", ACCELERATOR_VERSION, 1);
- add_assoc_string(version, "opcache_product_name", ACCELERATOR_PRODUCT_NAME, 1);
- add_assoc_zval(return_value, "version", version);
+ array_init(&version);
+ add_assoc_string(&version, "version", ACCELERATOR_VERSION);
+ add_assoc_string(&version, "opcache_product_name", ACCELERATOR_PRODUCT_NAME);
+ add_assoc_zval(return_value, "version", &version);
/* blacklist */
- MAKE_STD_ZVAL(blacklist);
- array_init(blacklist);
- zend_accel_blacklist_apply(&accel_blacklist, (apply_func_arg_t) add_blacklist_path, blacklist TSRMLS_CC);
- add_assoc_zval(return_value, "blacklist", blacklist);
+ array_init(&blacklist);
+ zend_accel_blacklist_apply(&accel_blacklist, add_blacklist_path, &blacklist);
+ add_assoc_zval(return_value, "blacklist", &blacklist);
}
/* {{{ proto void accelerator_reset()
Request that the contents of the opcode cache to be reset */
static ZEND_FUNCTION(opcache_reset)
{
- /* keep the compiler happy */
- (void)ht; (void)return_value_ptr; (void)this_ptr; (void)return_value_used;
-
-#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
if (zend_parse_parameters_none() == FAILURE) {
RETURN_FALSE;
}
-#endif
- if (!validate_api_restriction(TSRMLS_C)) {
+ if (!validate_api_restriction()) {
RETURN_FALSE;
}
@@ -724,7 +662,7 @@ static ZEND_FUNCTION(opcache_reset)
RETURN_FALSE;
}
- zend_accel_schedule_restart(ACCEL_RESTART_USER TSRMLS_CC);
+ zend_accel_schedule_restart(ACCEL_RESTART_USER);
RETURN_TRUE;
}
@@ -733,18 +671,18 @@ static ZEND_FUNCTION(opcache_reset)
static ZEND_FUNCTION(opcache_invalidate)
{
char *script_name;
- int script_name_len;
+ size_t script_name_len;
zend_bool force = 0;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &script_name, &script_name_len, &force) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|b", &script_name, &script_name_len, &force) == FAILURE) {
return;
}
- if (!validate_api_restriction(TSRMLS_C)) {
+ if (!validate_api_restriction()) {
RETURN_FALSE;
}
- if (zend_accel_invalidate(script_name, script_name_len, force TSRMLS_CC) == SUCCESS) {
+ if (zend_accel_invalidate(script_name, script_name_len, force) == SUCCESS) {
RETURN_TRUE;
} else {
RETURN_FALSE;
@@ -754,12 +692,12 @@ static ZEND_FUNCTION(opcache_invalidate)
static ZEND_FUNCTION(opcache_compile_file)
{
char *script_name;
- int script_name_len;
+ size_t script_name_len;
zend_file_handle handle;
zend_op_array *op_array = NULL;
zend_execute_data *orig_execute_data = NULL;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &script_name, &script_name_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &script_name, &script_name_len) == FAILURE) {
return;
}
@@ -776,20 +714,20 @@ static ZEND_FUNCTION(opcache_compile_file)
orig_execute_data = EG(current_execute_data);
zend_try {
- op_array = persistent_compile_file(&handle, ZEND_INCLUDE TSRMLS_CC);
+ op_array = persistent_compile_file(&handle, ZEND_INCLUDE);
} zend_catch {
EG(current_execute_data) = orig_execute_data;
zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME " could not compile file %s", handle.filename);
} zend_end_try();
if(op_array != NULL) {
- destroy_op_array(op_array TSRMLS_CC);
+ destroy_op_array(op_array);
efree(op_array);
RETVAL_TRUE;
} else {
RETVAL_FALSE;
}
- zend_destroy_file_handle(&handle TSRMLS_CC);
+ zend_destroy_file_handle(&handle);
}
/* {{{ proto bool opcache_is_script_cached(string $script)
@@ -797,9 +735,9 @@ static ZEND_FUNCTION(opcache_compile_file)
static ZEND_FUNCTION(opcache_is_script_cached)
{
char *script_name;
- int script_name_len;
+ size_t script_name_len;
- if (!validate_api_restriction(TSRMLS_C)) {
+ if (!validate_api_restriction()) {
RETURN_FALSE;
}
@@ -807,9 +745,9 @@ static ZEND_FUNCTION(opcache_is_script_cached)
RETURN_FALSE;
}
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &script_name, &script_name_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &script_name, &script_name_len) == FAILURE) {
return;
}
- RETURN_BOOL(filename_is_in_cache(script_name, script_name_len TSRMLS_CC));
+ RETURN_BOOL(filename_is_in_cache(script_name, script_name_len));
}
diff --git a/ext/opcache/zend_accelerator_module.h b/ext/opcache/zend_accelerator_module.h
index 9c1a6b925a..65b984a036 100644
--- a/ext/opcache/zend_accelerator_module.h
+++ b/ext/opcache/zend_accelerator_module.h
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| Zend OPcache |
+----------------------------------------------------------------------+
- | Copyright (c) 1998-2015 The PHP Group |
+ | Copyright (c) 1998-2014 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -23,6 +23,7 @@
#define ZEND_ACCELERATOR_MODULE_H
int start_accel_module(void);
-void zend_accel_override_file_functions(TSRMLS_D);
+
+void zend_accel_override_file_functions(void);
#endif /* _ZEND_ACCELERATOR_MODULE_H */
diff --git a/ext/opcache/zend_accelerator_util_funcs.c b/ext/opcache/zend_accelerator_util_funcs.c
index 87a06ef7d6..34950b88bd 100644
--- a/ext/opcache/zend_accelerator_util_funcs.c
+++ b/ext/opcache/zend_accelerator_util_funcs.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| Zend OPcache |
+----------------------------------------------------------------------+
- | Copyright (c) 1998-2015 The PHP Group |
+ | Copyright (c) 1998-2014 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -27,48 +27,48 @@
#define ZEND_PROTECTED_REFCOUNT (1<<30)
-static zend_uint zend_accel_refcount = ZEND_PROTECTED_REFCOUNT;
+static uint32_t zend_accel_refcount = ZEND_PROTECTED_REFCOUNT;
-#if SIZEOF_SIZE_T <= SIZEOF_LONG
+#if SIZEOF_SIZE_T <= SIZEOF_ZEND_LONG
/* If sizeof(void*) == sizeof(ulong) we can use zend_hash index functions */
-# define accel_xlat_set(old, new) zend_hash_index_update(&ZCG(bind_hash), (ulong)(zend_uintptr_t)(old), &(new), sizeof(void*), NULL)
-# define accel_xlat_get(old, new) zend_hash_index_find(&ZCG(bind_hash), (ulong)(zend_uintptr_t)(old), (void**)&(new))
+# define accel_xlat_set(old, new) zend_hash_index_update_ptr(&ZCG(bind_hash), (zend_ulong)(zend_uintptr_t)(old), (new))
+# define accel_xlat_get(old) zend_hash_index_find_ptr(&ZCG(bind_hash), (zend_ulong)(zend_uintptr_t)(old))
#else
-# define accel_xlat_set(old, new) zend_hash_quick_add(&ZCG(bind_hash), (char*)&(old), sizeof(void*), (ulong)(zend_uintptr_t)(old), (void**)&(new), sizeof(void*), NULL)
-# define accel_xlat_get(old, new) zend_hash_quick_find(&ZCG(bind_hash), (char*)&(old), sizeof(void*), (ulong)(zend_uintptr_t)(old), (void**)&(new))
+# define accel_xlat_set(old, new) (zend_hash_str_add_ptr(&ZCG(bind_hash), (char*)&(old), sizeof(void*), (zend_ulong)(zend_uintptr_t)(old), (void**)&(new))
+# define accel_xlat_get(old, new) ((new) = zend_hash_str_find_ptr(&ZCG(bind_hash), (char*)&(old), sizeof(void*), (zend_ulong)(zend_uintptr_t)(old), (void**)&(new)))
#endif
+#define ARENA_REALLOC(ptr) \
+ (void*)(((char*)(ptr)) + ((char*)ZCG(arena_mem) - (char*)ZCG(current_persistent_script)->arena_mem))
+
typedef int (*id_function_t)(void *, void *);
typedef void (*unique_copy_ctor_func_t)(void *pElement);
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
-static const Bucket *uninitialized_bucket = NULL;
-#endif
+static const uint32_t uninitialized_bucket = {INVALID_IDX};
-static int zend_prepare_function_for_execution(zend_op_array *op_array);
static void zend_hash_clone_zval(HashTable *ht, HashTable *source, int bind);
+static zend_ast *zend_ast_clone(zend_ast *ast);
-static void zend_accel_destroy_zend_function(zend_function *function)
+static void zend_accel_destroy_zend_function(zval *zv)
{
- TSRMLS_FETCH();
+ zend_function *function = Z_PTR_P(zv);
if (function->type == ZEND_USER_FUNCTION) {
if (function->op_array.static_variables) {
- efree(function->op_array.static_variables);
+ FREE_HASHTABLE(function->op_array.static_variables);
function->op_array.static_variables = NULL;
}
}
- destroy_zend_function(function TSRMLS_CC);
+ destroy_zend_function(function);
}
-static void zend_accel_destroy_zend_class(zend_class_entry **pce)
+static void zend_accel_destroy_zend_class(zval *zv)
{
- zend_class_entry *ce = *pce;
-
- ce->function_table.pDestructor = (dtor_func_t) zend_accel_destroy_zend_function;
- destroy_zend_class(pce);
+ zend_class_entry *ce = Z_PTR_P(zv);
+ ce->function_table.pDestructor = zend_accel_destroy_zend_function;
+ destroy_zend_class(zv);
}
zend_persistent_script* create_persistent_script(void)
@@ -76,68 +76,21 @@ zend_persistent_script* create_persistent_script(void)
zend_persistent_script *persistent_script = (zend_persistent_script *) emalloc(sizeof(zend_persistent_script));
memset(persistent_script, 0, sizeof(zend_persistent_script));
- zend_hash_init(&persistent_script->function_table, 100, NULL, (dtor_func_t) zend_accel_destroy_zend_function, 0);
+ zend_hash_init(&persistent_script->function_table, 128, NULL, ZEND_FUNCTION_DTOR, 0);
/* class_table is usually destroyed by free_persistent_script() that
* overrides destructor. ZEND_CLASS_DTOR may be used by standard
* PHP compiler
*/
- zend_hash_init(&persistent_script->class_table, 10, NULL, ZEND_CLASS_DTOR, 0);
+ zend_hash_init(&persistent_script->class_table, 16, NULL, ZEND_CLASS_DTOR, 0);
return persistent_script;
}
-static int compact_hash_table(HashTable *ht)
-{
- uint i = 3;
- uint nSize;
- Bucket **t;
-
- if (!ht->nNumOfElements) {
- /* Empty tables don't allocate space for Buckets */
- return 1;
- }
-
- if (ht->nNumOfElements >= 0x80000000) {
- /* prevent overflow */
- nSize = 0x80000000;
- } else {
- while ((1U << i) < ht->nNumOfElements) {
- i++;
- }
- nSize = 1 << i;
- }
-
- if (nSize >= ht->nTableSize) {
- /* Keep the size */
- return 1;
- }
-
- t = (Bucket **)pemalloc(nSize * sizeof(Bucket *), ht->persistent);
- if (!t) {
- return 0;
- }
-
- pefree(ht->arBuckets, ht->persistent);
-
- ht->arBuckets = t;
- ht->nTableSize = nSize;
- ht->nTableMask = ht->nTableSize - 1;
- zend_hash_rehash(ht);
-
- return 1;
-}
-
-int compact_persistent_script(zend_persistent_script *persistent_script)
-{
- return compact_hash_table(&persistent_script->function_table) &&
- compact_hash_table(&persistent_script->class_table);
-}
-
void free_persistent_script(zend_persistent_script *persistent_script, int destroy_elements)
{
if (destroy_elements) {
- persistent_script->function_table.pDestructor = (dtor_func_t)zend_accel_destroy_zend_function;
- persistent_script->class_table.pDestructor = (dtor_func_t)zend_accel_destroy_zend_class;
+ persistent_script->function_table.pDestructor = zend_accel_destroy_zend_function;
+ persistent_script->class_table.pDestructor = zend_accel_destroy_zend_class;
} else {
persistent_script->function_table.pDestructor = NULL;
persistent_script->class_table.pDestructor = NULL;
@@ -153,383 +106,334 @@ void free_persistent_script(zend_persistent_script *persistent_script, int destr
efree(persistent_script);
}
-static int is_not_internal_function(zend_function *function)
+static int is_not_internal_function(zval *zv)
{
+ zend_function *function = Z_PTR_P(zv);
return(function->type != ZEND_INTERNAL_FUNCTION);
}
-void zend_accel_free_user_functions(HashTable *ht TSRMLS_DC)
+void zend_accel_free_user_functions(HashTable *ht)
{
dtor_func_t orig_dtor = ht->pDestructor;
ht->pDestructor = NULL;
- zend_hash_apply(ht, (apply_func_t) is_not_internal_function TSRMLS_CC);
+ zend_hash_apply(ht, (apply_func_t) is_not_internal_function);
ht->pDestructor = orig_dtor;
}
-static int move_user_function(zend_function *function
-#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
- TSRMLS_DC
-#endif
- , int num_args, va_list args, zend_hash_key *hash_key)
+static int move_user_function(zval *zv, int num_args, va_list args, zend_hash_key *hash_key)
{
+ zend_function *function = Z_PTR_P(zv);
HashTable *function_table = va_arg(args, HashTable *);
(void)num_args; /* keep the compiler happy */
-#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
- TSRMLS_FETCH();
-#endif
if (function->type == ZEND_USER_FUNCTION) {
- zend_hash_quick_update(function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, function, sizeof(zend_function), NULL);
+ zend_hash_update_ptr(function_table, hash_key->key, function);
return 1;
} else {
return 0;
}
}
-void zend_accel_move_user_functions(HashTable *src, HashTable *dst TSRMLS_DC)
+void zend_accel_move_user_functions(HashTable *src, HashTable *dst)
{
dtor_func_t orig_dtor = src->pDestructor;
src->pDestructor = NULL;
-#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
zend_hash_apply_with_arguments(src, (apply_func_args_t)move_user_function, 1, dst);
-#else
- zend_hash_apply_with_arguments(src TSRMLS_CC, (apply_func_args_t)move_user_function, 1, dst);
-#endif
src->pDestructor = orig_dtor;
}
-static int copy_internal_function(zend_function *function, HashTable *function_table TSRMLS_DC)
+static int copy_internal_function(zval *zv, HashTable *function_table)
{
+ zend_internal_function *function = Z_PTR_P(zv);
if (function->type == ZEND_INTERNAL_FUNCTION) {
- zend_hash_update(function_table, function->common.function_name, strlen(function->common.function_name) + 1, function, sizeof(zend_function), NULL);
+ zend_hash_update_mem(function_table, function->function_name, function, sizeof(zend_internal_function));
}
return 0;
}
-void zend_accel_copy_internal_functions(TSRMLS_D)
+void zend_accel_copy_internal_functions(void)
{
- zend_hash_apply_with_argument(CG(function_table), (apply_func_arg_t)copy_internal_function, &ZCG(function_table) TSRMLS_CC);
+ zend_hash_apply_with_argument(CG(function_table), (apply_func_arg_t)copy_internal_function, &ZCG(function_table));
ZCG(internal_functions_count) = zend_hash_num_elements(&ZCG(function_table));
}
-static void zend_destroy_property_info(zend_property_info *property_info)
+static void zend_destroy_property_info(zval *zv)
{
- interned_efree((char*)property_info->name);
+ zend_property_info *property_info = Z_PTR_P(zv);
+
+ zend_string_release(property_info->name);
if (property_info->doc_comment) {
- efree((char*)property_info->doc_comment);
+ zend_string_release(property_info->doc_comment);
}
}
-#if ZEND_EXTENSION_API_NO > PHP_5_5_X_API_NO
-static zend_ast *zend_ast_clone(zend_ast *ast TSRMLS_DC)
+static zend_always_inline zend_string *zend_clone_str(zend_string *str)
{
- int i;
- zend_ast *node;
-
- if (ast->kind == ZEND_CONST) {
- node = emalloc(sizeof(zend_ast) + sizeof(zval));
- node->kind = ZEND_CONST;
- node->children = 0;
- node->u.val = (zval*)(node + 1);
- *node->u.val = *ast->u.val;
- if ((Z_TYPE_P(ast->u.val) & IS_CONSTANT_TYPE_MASK) >= IS_ARRAY) {
- switch ((Z_TYPE_P(ast->u.val) & IS_CONSTANT_TYPE_MASK)) {
- case IS_STRING:
- case IS_CONSTANT:
- Z_STRVAL_P(node->u.val) = (char *) interned_estrndup(Z_STRVAL_P(ast->u.val), Z_STRLEN_P(ast->u.val));
- break;
- case IS_ARRAY:
-#if ZEND_EXTENSION_API_NO <= PHP_5_5_API_NO
- case IS_CONSTANT_ARRAY:
-#endif
- if (ast->u.val->value.ht && ast->u.val->value.ht != &EG(symbol_table)) {
- ALLOC_HASHTABLE(node->u.val->value.ht);
- zend_hash_clone_zval(node->u.val->value.ht, ast->u.val->value.ht, 0);
- }
- break;
- case IS_CONSTANT_AST:
- Z_AST_P(node->u.val) = zend_ast_clone(Z_AST_P(ast->u.val) TSRMLS_CC);
- break;
- }
+ zend_string *ret;
+
+ if (EXPECTED(IS_INTERNED(str))) {
+ ret = str;
+ } else if (GC_REFCOUNT(str) <= 1 || (ret = accel_xlat_get(str)) == NULL) {
+ ret = zend_string_dup(str, 0);
+ GC_FLAGS(ret) = GC_FLAGS(str);
+ if (GC_REFCOUNT(str) > 1) {
+ accel_xlat_set(str, ret);
}
} else {
- node = emalloc(sizeof(zend_ast) + sizeof(zend_ast*) * (ast->children - 1));
- node->kind = ast->kind;
- node->children = ast->children;
- for (i = 0; i < ast->children; i++) {
- if ((&ast->u.child)[i]) {
- (&node->u.child)[i] = zend_ast_clone((&ast->u.child)[i] TSRMLS_CC);
- } else {
- (&node->u.child)[i] = NULL;
- }
- }
+ GC_REFCOUNT(ret)++;
}
- return node;
+ return ret;
}
-#endif
-static inline zval* zend_clone_zval(zval *src, int bind TSRMLS_DC)
+static inline void zend_clone_zval(zval *src, int bind)
{
- zval *ret, **ret_ptr = NULL;
-
- if (!bind) {
- ALLOC_ZVAL(ret);
- *ret = *src;
- INIT_PZVAL(ret);
- } else if (Z_REFCOUNT_P(src) == 1) {
- ALLOC_ZVAL(ret);
- *ret = *src;
- } else if (accel_xlat_get(src, ret_ptr) != SUCCESS) {
- ALLOC_ZVAL(ret);
- *ret = *src;
- accel_xlat_set(src, ret);
- } else {
- return *ret_ptr;
+ void *ptr;
+
+ if (Z_IMMUTABLE_P(src)) {
+ return;
}
-#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
- if ((Z_TYPE_P(ret) & IS_CONSTANT_TYPE_MASK) >= IS_ARRAY) {
- switch ((Z_TYPE_P(ret) & IS_CONSTANT_TYPE_MASK)) {
-#else
- if ((Z_TYPE_P(ret) & ~IS_CONSTANT_INDEX) >= IS_ARRAY) {
- switch ((Z_TYPE_P(ret) & ~IS_CONSTANT_INDEX)) {
-#endif
- case IS_STRING:
- case IS_CONSTANT:
- Z_STRVAL_P(ret) = (char *) interned_estrndup(Z_STRVAL_P(ret), Z_STRLEN_P(ret));
- break;
- case IS_ARRAY:
-#if ZEND_EXTENSION_API_NO <= PHP_5_5_API_NO
- case IS_CONSTANT_ARRAY:
-#endif
- if (ret->value.ht && ret->value.ht != &EG(symbol_table)) {
- ALLOC_HASHTABLE(ret->value.ht);
- zend_hash_clone_zval(ret->value.ht, src->value.ht, 0);
+ switch (Z_TYPE_P(src)) {
+ case IS_STRING:
+ case IS_CONSTANT:
+ Z_STR_P(src) = zend_clone_str(Z_STR_P(src));
+ break;
+ case IS_ARRAY:
+ if (Z_ARR_P(src) != &EG(symbol_table)) {
+ if (bind && Z_REFCOUNT_P(src) > 1 && (ptr = accel_xlat_get(Z_ARR_P(src))) != NULL) {
+ Z_ARR_P(src) = ptr;
+ } else {
+ zend_array *old = Z_ARR_P(src);
+
+ Z_ARR_P(src) = emalloc(sizeof(zend_array));
+ Z_ARR_P(src)->gc = old->gc;
+ if (bind && Z_REFCOUNT_P(src) > 1) {
+ accel_xlat_set(old, Z_ARR_P(src));
+ }
+ zend_hash_clone_zval(Z_ARRVAL_P(src), &old->ht, 0);
}
- break;
-#if ZEND_EXTENSION_API_NO > PHP_5_5_X_API_NO
- case IS_CONSTANT_AST:
- Z_AST_P(ret) = zend_ast_clone(Z_AST_P(ret) TSRMLS_CC);
- break;
-#endif
+ }
+ break;
+ case IS_REFERENCE:
+ if (bind && Z_REFCOUNT_P(src) > 1 && (ptr = accel_xlat_get(Z_REF_P(src))) != NULL) {
+ Z_REF_P(src) = ptr;
+ } else {
+ zend_reference *old = Z_REF_P(src);
+ ZVAL_NEW_REF(src, &old->val);
+ Z_REF_P(src)->gc = old->gc;
+ if (bind && Z_REFCOUNT_P(src) > 1) {
+ accel_xlat_set(old, Z_REF_P(src));
+ }
+ zend_clone_zval(Z_REFVAL_P(src), bind);
+ }
+ break;
+ case IS_CONSTANT_AST:
+ if (bind && Z_REFCOUNT_P(src) > 1 && (ptr = accel_xlat_get(Z_AST_P(src))) != NULL) {
+ Z_AST_P(src) = ptr;
+ } else {
+ zend_ast_ref *old = Z_AST_P(src);
+
+ ZVAL_NEW_AST(src, old->ast);
+ Z_AST_P(src)->gc = old->gc;
+ if (bind && Z_REFCOUNT_P(src) > 1) {
+ accel_xlat_set(old, Z_AST_P(src));
+ }
+ Z_ASTVAL_P(src) = zend_ast_clone(Z_ASTVAL_P(src));
+ }
+ break;
+ }
+}
+
+static zend_ast *zend_ast_clone(zend_ast *ast)
+{
+ uint32_t i;
+
+ if (ast->kind == ZEND_AST_ZVAL) {
+ zend_ast_zval *copy = emalloc(sizeof(zend_ast_zval));
+ copy->kind = ZEND_AST_ZVAL;
+ copy->attr = ast->attr;
+ ZVAL_COPY_VALUE(&copy->val, zend_ast_get_zval(ast));
+ zend_clone_zval(&copy->val, 0);
+ return (zend_ast *) copy;
+ } else if (zend_ast_is_list(ast)) {
+ zend_ast_list *list = zend_ast_get_list(ast);
+ zend_ast_list *copy = emalloc(
+ sizeof(zend_ast_list) - sizeof(zend_ast *) + sizeof(zend_ast *) * list->children);
+ copy->kind = list->kind;
+ copy->attr = list->attr;
+ copy->children = list->children;
+ for (i = 0; i < list->children; i++) {
+ if (list->child[i]) {
+ copy->child[i] = zend_ast_clone(list->child[i]);
+ } else {
+ copy->child[i] = NULL;
+ }
}
+ return (zend_ast *) copy;
+ } else {
+ uint32_t children = zend_ast_get_num_children(ast);
+ zend_ast *copy = emalloc(sizeof(zend_ast) - sizeof(zend_ast *) + sizeof(zend_ast *) * children);
+ copy->kind = ast->kind;
+ copy->attr = ast->attr;
+ for (i = 0; i < children; i++) {
+ if (ast->child[i]) {
+ copy->child[i] = zend_ast_clone(ast->child[i]);
+ } else {
+ copy->child[i] = NULL;
+ }
+ }
+ return copy;
}
- return ret;
}
static void zend_hash_clone_zval(HashTable *ht, HashTable *source, int bind)
{
- Bucket *p, *q, **prev;
- ulong nIndex;
- zval *ppz;
- TSRMLS_FETCH();
+ uint idx;
+ Bucket *p, *q, *r;
+ zend_ulong nIndex;
ht->nTableSize = source->nTableSize;
ht->nTableMask = source->nTableMask;
+ ht->nNumUsed = 0;
ht->nNumOfElements = source->nNumOfElements;
ht->nNextFreeElement = source->nNextFreeElement;
ht->pDestructor = ZVAL_PTR_DTOR;
-#if ZEND_DEBUG
- ht->inconsistent = 0;
-#endif
- ht->persistent = 0;
- ht->arBuckets = NULL;
- ht->pListHead = NULL;
- ht->pListTail = NULL;
- ht->pInternalPointer = NULL;
- ht->nApplyCount = 0;
- ht->bApplyProtection = 1;
-
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
- if (!ht->nTableMask) {
- ht->arBuckets = (Bucket**)&uninitialized_bucket;
+ ht->u.flags = (source->u.flags & HASH_FLAG_INITIALIZED) | HASH_FLAG_APPLY_PROTECTION;
+ ht->arData = NULL;
+ ht->arHash = NULL;
+ ht->nInternalPointer = source->nNumOfElements ? 0 : INVALID_IDX;
+
+ if (!(ht->u.flags & HASH_FLAG_INITIALIZED)) {
+ ht->arHash = (uint32_t*)&uninitialized_bucket;
return;
}
-#endif
- ht->arBuckets = (Bucket **) ecalloc(ht->nTableSize, sizeof(Bucket *));
+ if (source->u.flags & HASH_FLAG_PACKED) {
+ ht->u.flags |= HASH_FLAG_PACKED;
+ ht->arData = (Bucket *) emalloc(ht->nTableSize * sizeof(Bucket));
+ ht->arHash = (uint32_t*)&uninitialized_bucket;
- prev = &ht->pListHead;
- p = source->pListHead;
- while (p) {
- nIndex = p->h & ht->nTableMask;
+ for (idx = 0; idx < source->nNumUsed; idx++) {
+ p = source->arData + idx;
+ if (Z_TYPE(p->val) == IS_UNDEF) continue;
+ nIndex = p->h & ht->nTableMask;
- /* Create bucket and initialize key */
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
- if (!p->nKeyLength) {
- q = (Bucket *) emalloc(sizeof(Bucket));
- q->arKey = NULL;
- } else if (IS_INTERNED(p->arKey)) {
- q = (Bucket *) emalloc(sizeof(Bucket));
- q->arKey = p->arKey;
- } else {
- q = (Bucket *) emalloc(sizeof(Bucket) + p->nKeyLength);
- q->arKey = ((char*)q) + sizeof(Bucket);
- memcpy((char*)q->arKey, p->arKey, p->nKeyLength);
- }
-#else
- q = (Bucket *) emalloc(sizeof(Bucket) - 1 + p->nKeyLength);
- if (p->nKeyLength) {
- memcpy(q->arKey, p->arKey, p->nKeyLength);
- }
-#endif
- q->h = p->h;
- q->nKeyLength = p->nKeyLength;
-
- /* Insert into hash collision list */
- q->pNext = ht->arBuckets[nIndex];
- q->pLast = NULL;
- if (q->pNext) {
- q->pNext->pLast = q;
- }
- ht->arBuckets[nIndex] = q;
+ r = ht->arData + ht->nNumUsed;
+ q = ht->arData + p->h;
+ while (r != q) {
+ ZVAL_UNDEF(&r->val);
+ r++;
+ }
+ ht->nNumUsed = p->h + 1;
- /* Insert into global list */
- q->pListLast = ht->pListTail;
- ht->pListTail = q;
- q->pListNext = NULL;
- *prev = q;
- prev = &q->pListNext;
+ /* Initialize key */
+ q->h = p->h;
+ q->key = NULL;
- /* Copy data */
- q->pData = &q->pDataPtr;
- if (!bind) {
- ALLOC_ZVAL(ppz);
- *ppz = *((zval*)p->pDataPtr);
- INIT_PZVAL(ppz);
- } else if (Z_REFCOUNT_P((zval*)p->pDataPtr) == 1) {
- ALLOC_ZVAL(ppz);
- *ppz = *((zval*)p->pDataPtr);
- } else if (accel_xlat_get(p->pDataPtr, ppz) != SUCCESS) {
- ALLOC_ZVAL(ppz);
- *ppz = *((zval*)p->pDataPtr);
- accel_xlat_set(p->pDataPtr, ppz);
- } else {
- q->pDataPtr = *(void**)ppz;
- p = p->pListNext;
- continue;
+ /* Copy data */
+ ZVAL_COPY_VALUE(&q->val, &p->val);
+ zend_clone_zval(&q->val, bind);
}
- q->pDataPtr = (void*)ppz;
-
-#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
- if ((Z_TYPE_P((zval*)p->pDataPtr) & IS_CONSTANT_TYPE_MASK) >= IS_ARRAY) {
- switch ((Z_TYPE_P((zval*)p->pDataPtr) & IS_CONSTANT_TYPE_MASK)) {
-#else
- if ((Z_TYPE_P((zval*)p->pDataPtr) & ~IS_CONSTANT_INDEX) >= IS_ARRAY) {
- switch ((Z_TYPE_P((zval*)p->pDataPtr) & ~IS_CONSTANT_INDEX)) {
-#endif
- case IS_STRING:
- case IS_CONSTANT:
- Z_STRVAL_P(ppz) = (char *) interned_estrndup(Z_STRVAL_P((zval*)p->pDataPtr), Z_STRLEN_P((zval*)p->pDataPtr));
- break;
- case IS_ARRAY:
-#if ZEND_EXTENSION_API_NO <= PHP_5_5_API_NO
- case IS_CONSTANT_ARRAY:
-#endif
- if (((zval*)p->pDataPtr)->value.ht && ((zval*)p->pDataPtr)->value.ht != &EG(symbol_table)) {
- ALLOC_HASHTABLE(ppz->value.ht);
- zend_hash_clone_zval(ppz->value.ht, ((zval*)p->pDataPtr)->value.ht, 0);
- }
- break;
-#if ZEND_EXTENSION_API_NO > PHP_5_5_X_API_NO
- case IS_CONSTANT_AST:
- Z_AST_P(ppz) = zend_ast_clone(Z_AST_P(ppz) TSRMLS_CC);
- break;
-#endif
+ } else {
+ ht->arData = (Bucket *) emalloc(ht->nTableSize * (sizeof(Bucket) + sizeof(uint32_t)));
+ ht->arHash = (uint32_t*)(ht->arData + ht->nTableSize);
+ memset(ht->arHash, INVALID_IDX, sizeof(uint32_t) * ht->nTableSize);
+
+ for (idx = 0; idx < source->nNumUsed; idx++) {
+ p = source->arData + idx;
+ if (Z_TYPE(p->val) == IS_UNDEF) continue;
+ nIndex = p->h & ht->nTableMask;
+
+ /* Insert into hash collision list */
+ q = ht->arData + ht->nNumUsed;
+ Z_NEXT(q->val) = ht->arHash[nIndex];
+ ht->arHash[nIndex] = ht->nNumUsed++;
+
+ /* Initialize key */
+ q->h = p->h;
+ if (!p->key) {
+ q->key = NULL;
+ } else {
+ q->key = zend_clone_str(p->key);
}
+
+ /* Copy data */
+ ZVAL_COPY_VALUE(&q->val, &p->val);
+ zend_clone_zval(&q->val, bind);
}
+ }
+}
+
+/* protects reference count, creates copy of statics */
+static zend_always_inline void zend_prepare_function_for_execution(zend_op_array *op_array)
+{
+ /* protect reference count */
+ op_array->refcount = &zend_accel_refcount;
+ (*op_array->refcount) = ZEND_PROTECTED_REFCOUNT;
- p = p->pListNext;
+ /* copy statics */
+ if (UNEXPECTED(op_array->static_variables)) {
+ HashTable *shared_statics = op_array->static_variables;
+
+ ALLOC_HASHTABLE(op_array->static_variables);
+ zend_hash_clone_zval(op_array->static_variables, shared_statics, 0);
}
- ht->pInternalPointer = ht->pListHead;
}
-static void zend_hash_clone_methods(HashTable *ht, HashTable *source, zend_class_entry *old_ce, zend_class_entry *ce TSRMLS_DC)
+static void zend_hash_clone_methods(HashTable *ht, HashTable *source, zend_class_entry *old_ce, zend_class_entry *ce)
{
- Bucket *p, *q, **prev;
- ulong nIndex;
- zend_class_entry **new_ce;
- zend_function** new_prototype;
+ uint idx;
+ Bucket *p, *q;
+ zend_ulong nIndex;
+ zend_class_entry *new_ce;
+ zend_function *new_prototype;
zend_op_array *new_entry;
ht->nTableSize = source->nTableSize;
ht->nTableMask = source->nTableMask;
+ ht->nNumUsed = 0;
ht->nNumOfElements = source->nNumOfElements;
ht->nNextFreeElement = source->nNextFreeElement;
ht->pDestructor = ZEND_FUNCTION_DTOR;
-#if ZEND_DEBUG
- ht->inconsistent = 0;
-#endif
- ht->persistent = 0;
- ht->pListHead = NULL;
- ht->pListTail = NULL;
- ht->pInternalPointer = NULL;
- ht->nApplyCount = 0;
- ht->bApplyProtection = 1;
-
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
- if (!ht->nTableMask) {
- ht->arBuckets = (Bucket**)&uninitialized_bucket;
+ ht->u.flags = (source->u.flags & HASH_FLAG_INITIALIZED);
+ ht->nInternalPointer = source->nNumOfElements ? 0 : INVALID_IDX;
+
+ if (!(ht->u.flags & HASH_FLAG_INITIALIZED)) {
+ ht->arHash = (uint32_t*)&uninitialized_bucket;
return;
}
-#endif
- ht->arBuckets = (Bucket **) ecalloc(ht->nTableSize, sizeof(Bucket *));
+ ZEND_ASSERT(!(source->u.flags & HASH_FLAG_PACKED));
+ ht->arData = (Bucket *) emalloc(ht->nTableSize * (sizeof(Bucket) + sizeof(uint32_t)));
+ ht->arHash = (uint32_t *)(ht->arData + ht->nTableSize);
+ memset(ht->arHash, INVALID_IDX, sizeof(uint32_t) * ht->nTableSize);
- prev = &ht->pListHead;
- p = source->pListHead;
- while (p) {
- nIndex = p->h & ht->nTableMask;
+ for (idx = 0; idx < source->nNumUsed; idx++) {
+ p = source->arData + idx;
+ if (Z_TYPE(p->val) == IS_UNDEF) continue;
- /* Create bucket and initialize key */
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
- if (!p->nKeyLength) {
- q = (Bucket *) emalloc(sizeof(Bucket));
- q->arKey = NULL;
- } else if (IS_INTERNED(p->arKey)) {
- q = (Bucket *) emalloc(sizeof(Bucket));
- q->arKey = p->arKey;
- } else {
- q = (Bucket *) emalloc(sizeof(Bucket) + p->nKeyLength);
- q->arKey = ((char*)q) + sizeof(Bucket);
- memcpy((char*)q->arKey, p->arKey, p->nKeyLength);
- }
-#else
- q = (Bucket *) emalloc(sizeof(Bucket) - 1 + p->nKeyLength);
- if (p->nKeyLength) {
- memcpy(q->arKey, p->arKey, p->nKeyLength);
- }
-#endif
- q->h = p->h;
- q->nKeyLength = p->nKeyLength;
+ nIndex = p->h & ht->nTableMask;
/* Insert into hash collision list */
- q->pNext = ht->arBuckets[nIndex];
- q->pLast = NULL;
- if (q->pNext) {
- q->pNext->pLast = q;
- }
- ht->arBuckets[nIndex] = q;
+ q = ht->arData + ht->nNumUsed;
+ Z_NEXT(q->val) = ht->arHash[nIndex];
+ ht->arHash[nIndex] = ht->nNumUsed++;
- /* Insert into global list */
- q->pListLast = ht->pListTail;
- ht->pListTail = q;
- q->pListNext = NULL;
- *prev = q;
- prev = &q->pListNext;
+ /* Initialize key */
+ q->h = p->h;
+ ZEND_ASSERT(p->key != NULL);
+ q->key = zend_clone_str(p->key);
/* Copy data */
- q->pData = (void *) emalloc(sizeof(zend_function));
- new_entry = (zend_op_array*)q->pData;
- *new_entry = *(zend_op_array*)p->pData;
- q->pDataPtr = NULL;
+ ZVAL_PTR(&q->val, ARENA_REALLOC(Z_PTR(p->val)));
+ new_entry = (zend_op_array*)Z_PTR(q->val);
/* Copy constructor */
/* we use refcount to show that op_array is referenced from several places */
if (new_entry->refcount != NULL) {
- accel_xlat_set(p->pData, new_entry);
+ accel_xlat_set(Z_PTR(p->val), new_entry);
}
zend_prepare_function_for_execution(new_entry);
@@ -537,153 +441,97 @@ static void zend_hash_clone_methods(HashTable *ht, HashTable *source, zend_class
if (old_ce == new_entry->scope) {
new_entry->scope = ce;
} else {
- if (accel_xlat_get(new_entry->scope, new_ce) == SUCCESS) {
- new_entry->scope = *new_ce;
+ if ((new_ce = accel_xlat_get(new_entry->scope)) != NULL) {
+ new_entry->scope = new_ce;
} else {
- zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME " class loading error, class %s, function %s", ce->name, new_entry->function_name);
+ zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME " class loading error, class %s, function %s", ce->name->val, new_entry->function_name->val);
}
}
/* update prototype */
if (new_entry->prototype) {
- if (accel_xlat_get(new_entry->prototype, new_prototype) == SUCCESS) {
- new_entry->prototype = *new_prototype;
+ if ((new_prototype = accel_xlat_get(new_entry->prototype)) != NULL) {
+ new_entry->prototype = new_prototype;
} else {
- zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME " class loading error, class %s, function %s", ce->name, new_entry->function_name);
+ zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME " class loading error, class %s, function %s", ce->name->val, new_entry->function_name->val);
}
}
-
- p = p->pListNext;
}
- ht->pInternalPointer = ht->pListHead;
}
-static void zend_hash_clone_prop_info(HashTable *ht, HashTable *source, zend_class_entry *old_ce, zend_class_entry *ce TSRMLS_DC)
+static void zend_hash_clone_prop_info(HashTable *ht, HashTable *source, zend_class_entry *old_ce, zend_class_entry *ce)
{
- Bucket *p, *q, **prev;
- ulong nIndex;
- zend_class_entry **new_ce;
+ uint idx;
+ Bucket *p, *q;
+ zend_ulong nIndex;
+ zend_class_entry *new_ce;
zend_property_info *prop_info;
ht->nTableSize = source->nTableSize;
ht->nTableMask = source->nTableMask;
+ ht->nNumUsed = 0;
ht->nNumOfElements = source->nNumOfElements;
ht->nNextFreeElement = source->nNextFreeElement;
- ht->pDestructor = (dtor_func_t) zend_destroy_property_info;
-#if ZEND_DEBUG
- ht->inconsistent = 0;
-#endif
- ht->persistent = 0;
- ht->pListHead = NULL;
- ht->pListTail = NULL;
- ht->pInternalPointer = NULL;
- ht->nApplyCount = 0;
- ht->bApplyProtection = 1;
-
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
- if (!ht->nTableMask) {
- ht->arBuckets = (Bucket**)&uninitialized_bucket;
+ ht->pDestructor = zend_destroy_property_info;
+ ht->u.flags = (source->u.flags & HASH_FLAG_INITIALIZED);
+ ht->nInternalPointer = source->nNumOfElements ? 0 : INVALID_IDX;
+
+ if (!(ht->u.flags & HASH_FLAG_INITIALIZED)) {
+ ht->arHash = (uint32_t*)&uninitialized_bucket;
return;
}
-#endif
- ht->arBuckets = (Bucket **) ecalloc(ht->nTableSize, sizeof(Bucket *));
+ ZEND_ASSERT(!(source->u.flags & HASH_FLAG_PACKED));
+ ht->arData = (Bucket *) emalloc(ht->nTableSize * (sizeof(Bucket) + sizeof(uint32_t)));
+ ht->arHash = (uint32_t*)(ht->arData + ht->nTableSize);
+ memset(ht->arHash, INVALID_IDX, sizeof(uint32_t) * ht->nTableSize);
- prev = &ht->pListHead;
- p = source->pListHead;
- while (p) {
- nIndex = p->h & ht->nTableMask;
+ for (idx = 0; idx < source->nNumUsed; idx++) {
+ p = source->arData + idx;
+ if (Z_TYPE(p->val) == IS_UNDEF) continue;
- /* Create bucket and initialize key */
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
- if (!p->nKeyLength) {
- q = (Bucket *) emalloc(sizeof(Bucket));
- q->arKey = NULL;
- } else if (IS_INTERNED(p->arKey)) {
- q = (Bucket *) emalloc(sizeof(Bucket));
- q->arKey = p->arKey;
- } else {
- q = (Bucket *) emalloc(sizeof(Bucket) + p->nKeyLength);
- q->arKey = ((char*)q) + sizeof(Bucket);
- memcpy((char*)q->arKey, p->arKey, p->nKeyLength);
- }
-#else
- q = (Bucket *) emalloc(sizeof(Bucket) - 1 + p->nKeyLength);
- if (p->nKeyLength) {
- memcpy(q->arKey, p->arKey, p->nKeyLength);
- }
-#endif
- q->h = p->h;
- q->nKeyLength = p->nKeyLength;
+ nIndex = p->h & ht->nTableMask;
/* Insert into hash collision list */
- q->pNext = ht->arBuckets[nIndex];
- q->pLast = NULL;
- if (q->pNext) {
- q->pNext->pLast = q;
- }
- ht->arBuckets[nIndex] = q;
+ q = ht->arData + ht->nNumUsed;
+ Z_NEXT(q->val) = ht->arHash[nIndex];
+ ht->arHash[nIndex] = ht->nNumUsed++;
- /* Insert into global list */
- q->pListLast = ht->pListTail;
- ht->pListTail = q;
- q->pListNext = NULL;
- *prev = q;
- prev = &q->pListNext;
+ /* Initialize key */
+ q->h = p->h;
+ ZEND_ASSERT(p->key != NULL);
+ q->key = zend_clone_str(p->key);
/* Copy data */
- q->pData = (void *) emalloc(sizeof(zend_property_info));
- prop_info = q->pData;
- *prop_info = *(zend_property_info*)p->pData;
- q->pDataPtr = NULL;
+ ZVAL_PTR(&q->val, ARENA_REALLOC(Z_PTR(p->val)));
+ prop_info = Z_PTR(q->val);
/* Copy constructor */
- prop_info->name = interned_estrndup(prop_info->name, prop_info->name_length);
+ prop_info->name = zend_clone_str(prop_info->name);
if (prop_info->doc_comment) {
if (ZCG(accel_directives).load_comments) {
- prop_info->doc_comment = estrndup(prop_info->doc_comment, prop_info->doc_comment_len);
+ prop_info->doc_comment = zend_string_dup(prop_info->doc_comment, 0);
} else {
prop_info->doc_comment = NULL;
}
}
if (prop_info->ce == old_ce) {
prop_info->ce = ce;
- } else if (accel_xlat_get(prop_info->ce, new_ce) == SUCCESS) {
- prop_info->ce = *new_ce;
+ } else if ((new_ce = accel_xlat_get(prop_info->ce)) != NULL) {
+ prop_info->ce = new_ce;
} else {
- zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME" class loading error, class %s, property %s", ce->name, prop_info->name);
+ zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME" class loading error, class %s, property %s", ce->name->val, prop_info->name->val);
}
-
- p = p->pListNext;
- }
- ht->pInternalPointer = ht->pListHead;
-}
-
-/* protects reference count, creates copy of statics */
-static int zend_prepare_function_for_execution(zend_op_array *op_array)
-{
- HashTable *shared_statics = op_array->static_variables;
-
- /* protect reference count */
- op_array->refcount = &zend_accel_refcount;
- (*op_array->refcount) = ZEND_PROTECTED_REFCOUNT;
-
- /* copy statics */
- if (shared_statics) {
- ALLOC_HASHTABLE(op_array->static_variables);
- zend_hash_clone_zval(op_array->static_variables, shared_statics, 0);
}
-
- return 0;
}
#define zend_update_inherited_handler(handler) \
{ \
if (ce->handler != NULL) { \
- if (accel_xlat_get(ce->handler, new_func) == SUCCESS) { \
- ce->handler = *new_func; \
+ if ((new_func = accel_xlat_get(ce->handler)) != NULL) { \
+ ce->handler = new_func; \
} else { \
- zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME " class loading error, class %s", ce->name); \
+ zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME " class loading error, class %s", ce->name->val); \
} \
} \
}
@@ -693,12 +541,10 @@ static void zend_class_copy_ctor(zend_class_entry **pce)
{
zend_class_entry *ce = *pce;
zend_class_entry *old_ce = ce;
- zend_class_entry **new_ce;
- zend_function **new_func;
- TSRMLS_FETCH();
+ zend_class_entry *new_ce;
+ zend_function *new_func;
- *pce = ce = emalloc(sizeof(zend_class_entry));
- *ce = *old_ce;
+ *pce = ce = ARENA_REALLOC(old_ce);
ce->refcount = 1;
if (old_ce->refcount != 1) {
@@ -706,52 +552,38 @@ static void zend_class_copy_ctor(zend_class_entry **pce)
accel_xlat_set(old_ce, ce);
}
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
if (old_ce->default_properties_table) {
int i;
- ce->default_properties_table = emalloc(sizeof(zval*) * old_ce->default_properties_count);
+ ce->default_properties_table = emalloc(sizeof(zval) * old_ce->default_properties_count);
for (i = 0; i < old_ce->default_properties_count; i++) {
- if (old_ce->default_properties_table[i]) {
- ce->default_properties_table[i] = zend_clone_zval(old_ce->default_properties_table[i], 0 TSRMLS_CC);
- } else {
- ce->default_properties_table[i] = NULL;
- }
+ ZVAL_COPY_VALUE(&ce->default_properties_table[i], &old_ce->default_properties_table[i]);
+ zend_clone_zval(&ce->default_properties_table[i], 1);
}
}
-#else
- zend_hash_clone_zval(&ce->default_properties, &old_ce->default_properties, 0);
-#endif
- zend_hash_clone_methods(&ce->function_table, &old_ce->function_table, old_ce, ce TSRMLS_CC);
+ zend_hash_clone_methods(&ce->function_table, &old_ce->function_table, old_ce, ce);
/* static members */
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
if (old_ce->default_static_members_table) {
int i;
- ce->default_static_members_table = emalloc(sizeof(zval*) * old_ce->default_static_members_count);
+ ce->default_static_members_table = emalloc(sizeof(zval) * old_ce->default_static_members_count);
for (i = 0; i < old_ce->default_static_members_count; i++) {
- if (old_ce->default_static_members_table[i]) {
- ce->default_static_members_table[i] = zend_clone_zval(old_ce->default_static_members_table[i], 1 TSRMLS_CC);
- } else {
- ce->default_static_members_table[i] = NULL;
- }
+ ZVAL_COPY_VALUE(&ce->default_static_members_table[i], &old_ce->default_static_members_table[i]);
+ zend_clone_zval(&ce->default_static_members_table[i], 1);
}
}
ce->static_members_table = ce->default_static_members_table;
-#else
- zend_hash_clone_zval(&ce->default_static_members, &old_ce->default_static_members, 1);
- ce->static_members = &ce->default_static_members;
-#endif
/* properties_info */
- zend_hash_clone_prop_info(&ce->properties_info, &old_ce->properties_info, old_ce, ce TSRMLS_CC);
+ zend_hash_clone_prop_info(&ce->properties_info, &old_ce->properties_info, old_ce, ce);
/* constants table */
- zend_hash_clone_zval(&ce->constants_table, &old_ce->constants_table, 0);
+ zend_hash_clone_zval(&ce->constants_table, &old_ce->constants_table, 1);
+ ce->constants_table.u.flags &= ~HASH_FLAG_APPLY_PROTECTION;
- ce->name = interned_estrndup(ce->name, ce->name_length);
+ ce->name = zend_clone_str(ce->name);
/* interfaces aren't really implemented, so we create a new table */
if (ce->num_interfaces) {
@@ -762,17 +594,17 @@ static void zend_class_copy_ctor(zend_class_entry **pce)
}
if (ZEND_CE_DOC_COMMENT(ce)) {
if (ZCG(accel_directives).load_comments) {
- ZEND_CE_DOC_COMMENT(ce) = estrndup(ZEND_CE_DOC_COMMENT(ce), ZEND_CE_DOC_COMMENT_LEN(ce));
+ ZEND_CE_DOC_COMMENT(ce) = zend_string_dup(ZEND_CE_DOC_COMMENT(ce), 0);
} else {
ZEND_CE_DOC_COMMENT(ce) = NULL;
}
}
if (ce->parent) {
- if (accel_xlat_get(ce->parent, new_ce) == SUCCESS) {
- ce->parent = *new_ce;
+ if ((new_ce = accel_xlat_get(ce->parent)) != NULL) {
+ ce->parent = new_ce;
} else {
- zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME" class loading error, class %s", ce->name);
+ zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME" class loading error, class %s", ce->name->val);
}
}
@@ -790,17 +622,10 @@ static void zend_class_copy_ctor(zend_class_entry **pce)
/* 5.2 stuff */
zend_update_inherited_handler(__tostring);
-#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
/* 5.3 stuff */
zend_update_inherited_handler(__callstatic);
-#endif
-
-#if ZEND_EXTENSION_API_NO >= PHP_5_6_X_API_NO
-/* 5.6 stuff */
zend_update_inherited_handler(__debugInfo);
-#endif
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
/* 5.4 traits */
if (ce->trait_aliases) {
zend_trait_alias **trait_aliases;
@@ -819,20 +644,17 @@ static void zend_class_copy_ctor(zend_class_entry **pce)
if (trait_aliases[i]->trait_method) {
if (trait_aliases[i]->trait_method->method_name) {
trait_aliases[i]->trait_method->method_name =
- estrndup(trait_aliases[i]->trait_method->method_name,
- trait_aliases[i]->trait_method->mname_len);
+ zend_clone_str(trait_aliases[i]->trait_method->method_name);
}
if (trait_aliases[i]->trait_method->class_name) {
trait_aliases[i]->trait_method->class_name =
- estrndup(trait_aliases[i]->trait_method->class_name,
- trait_aliases[i]->trait_method->cname_len);
+ zend_clone_str(trait_aliases[i]->trait_method->class_name);
}
}
if (trait_aliases[i]->alias) {
trait_aliases[i]->alias =
- estrndup(trait_aliases[i]->alias,
- trait_aliases[i]->alias_len);
+ zend_clone_str(trait_aliases[i]->alias);
}
i++;
}
@@ -856,163 +678,204 @@ static void zend_class_copy_ctor(zend_class_entry **pce)
memcpy(trait_precedences[i]->trait_method, ce->trait_precedences[i]->trait_method, sizeof(zend_trait_method_reference));
trait_precedences[i]->trait_method->method_name =
- estrndup(trait_precedences[i]->trait_method->method_name,
- trait_precedences[i]->trait_method->mname_len);
+ zend_clone_str(trait_precedences[i]->trait_method->method_name);
trait_precedences[i]->trait_method->class_name =
- estrndup(trait_precedences[i]->trait_method->class_name,
- trait_precedences[i]->trait_method->cname_len);
+ zend_clone_str(trait_precedences[i]->trait_method->class_name);
if (trait_precedences[i]->exclude_from_classes) {
- zend_class_entry **exclude_from_classes;
+ zend_string **exclude_from_classes;
int j = 0;
- while (trait_precedences[i]->exclude_from_classes[j]) {
+ while (trait_precedences[i]->exclude_from_classes[j].class_name) {
j++;
}
- exclude_from_classes = emalloc(sizeof(zend_class_entry*) * (j + 1));
+ exclude_from_classes = emalloc(sizeof(zend_string*) * (j + 1));
j = 0;
- while (trait_precedences[i]->exclude_from_classes[j]) {
- exclude_from_classes[j] = (zend_class_entry*)estrndup(
- (char*)trait_precedences[i]->exclude_from_classes[j],
- strlen((char*)trait_precedences[i]->exclude_from_classes[j]));
+ while (trait_precedences[i]->exclude_from_classes[j].class_name) {
+ exclude_from_classes[j] =
+ zend_clone_str(trait_precedences[i]->exclude_from_classes[j].class_name);
j++;
}
exclude_from_classes[j] = NULL;
- trait_precedences[i]->exclude_from_classes = exclude_from_classes;
+ trait_precedences[i]->exclude_from_classes = (void*)exclude_from_classes;
}
i++;
}
trait_precedences[i] = NULL;
ce->trait_precedences = trait_precedences;
}
-#endif
}
-static int zend_hash_unique_copy(HashTable *target, HashTable *source, unique_copy_ctor_func_t pCopyConstructor, uint size, int ignore_dups, void **fail_data, void **conflict_data)
+static void zend_accel_function_hash_copy(HashTable *target, HashTable *source)
{
+ zend_function *function1, *function2;
+ uint idx;
Bucket *p;
- void *t;
-
- p = source->pListHead;
- while (p) {
- if (p->nKeyLength > 0) {
- if (zend_hash_quick_add(target, p->arKey, p->nKeyLength, p->h, p->pData, size, &t) == SUCCESS) {
- if (pCopyConstructor) {
- pCopyConstructor(t);
- }
- } else {
- if (p->nKeyLength > 0 && p->arKey[0] == 0) {
+ zval *t;
+
+ for (idx = 0; idx < source->nNumUsed; idx++) {
+ p = source->arData + idx;
+ if (Z_TYPE(p->val) == IS_UNDEF) continue;
+ if (p->key) {
+ t = zend_hash_add(target, p->key, &p->val);
+ if (UNEXPECTED(t == NULL)) {
+ if (p->key->len > 0 && p->key->val[0] == 0) {
/* Mangled key */
-#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
- if (zend_hash_quick_update(target, p->arKey, p->nKeyLength, p->h, p->pData, size, &t) == SUCCESS) {
- if (pCopyConstructor) {
- pCopyConstructor(t);
- }
- }
-#endif
- } else if (!ignore_dups && zend_hash_quick_find(target, p->arKey, p->nKeyLength, p->h, &t) == SUCCESS) {
- *fail_data = p->pData;
- *conflict_data = t;
- return FAILURE;
+ t = zend_hash_update(target, p->key, &p->val);
+ } else {
+ t = zend_hash_find(target, p->key);
+ goto failure;
}
}
} else {
- if (!zend_hash_index_exists(target, p->h) && zend_hash_index_update(target, p->h, p->pData, size, &t) == SUCCESS) {
- if (pCopyConstructor) {
- pCopyConstructor(t);
- }
- } else if (!ignore_dups && zend_hash_index_find(target,p->h, &t) == SUCCESS) {
- *fail_data = p->pData;
- *conflict_data = t;
- return FAILURE;
+ t = zend_hash_index_add(target, p->h, &p->val);
+ if (UNEXPECTED(t == NULL)) {
+ t = zend_hash_index_find(target, p->h);
+ goto failure;
}
}
- p = p->pListNext;
}
- target->pInternalPointer = target->pListHead;
-
- return SUCCESS;
+ target->nInternalPointer = target->nNumOfElements ? 0 : INVALID_IDX;
+ return;
+
+failure:
+ function1 = Z_PTR(p->val);
+ function2 = Z_PTR_P(t);
+ CG(in_compilation) = 1;
+ zend_set_compiled_filename(function1->op_array.filename);
+ CG(zend_lineno) = function1->op_array.opcodes[0].lineno;
+ if (function2->type == ZEND_USER_FUNCTION
+ && function2->op_array.last > 0) {
+ zend_error(E_ERROR, "Cannot redeclare %s() (previously declared in %s:%d)",
+ function1->common.function_name->val,
+ function2->op_array.filename->val,
+ (int)function2->op_array.opcodes[0].lineno);
+ } else {
+ zend_error(E_ERROR, "Cannot redeclare %s()", function1->common.function_name->val);
+ }
}
-static void zend_accel_function_hash_copy(HashTable *target, HashTable *source, unique_copy_ctor_func_t pCopyConstructor)
+static void zend_accel_function_hash_copy_from_shm(HashTable *target, HashTable *source)
{
zend_function *function1, *function2;
- TSRMLS_FETCH();
-
- if (zend_hash_unique_copy(target, source, pCopyConstructor, sizeof(zend_function), 0, (void**)&function1, (void**)&function2) != SUCCESS) {
- CG(in_compilation) = 1;
- zend_set_compiled_filename(function1->op_array.filename TSRMLS_CC);
- CG(zend_lineno) = function1->op_array.opcodes[0].lineno;
- if (function2->type == ZEND_USER_FUNCTION
- && function2->op_array.last > 0) {
- zend_error(E_ERROR, "Cannot redeclare %s() (previously declared in %s:%d)",
- function1->common.function_name,
- function2->op_array.filename,
- (int)function2->op_array.opcodes[0].lineno);
+ uint idx;
+ Bucket *p;
+ zval *t;
+
+ for (idx = 0; idx < source->nNumUsed; idx++) {
+ p = source->arData + idx;
+ if (Z_TYPE(p->val) == IS_UNDEF) continue;
+ if (p->key) {
+ t = zend_hash_add(target, p->key, &p->val);
+ if (UNEXPECTED(t == NULL)) {
+ if (p->key->len > 0 && p->key->val[0] == 0) {
+ /* Mangled key */
+ t = zend_hash_update(target, p->key, &p->val);
+ } else {
+ t = zend_hash_find(target, p->key);
+ goto failure;
+ }
+ }
} else {
- zend_error(E_ERROR, "Cannot redeclare %s()", function1->common.function_name);
+ t = zend_hash_index_add(target, p->h, &p->val);
+ if (UNEXPECTED(t == NULL)) {
+ t = zend_hash_index_find(target, p->h);
+ goto failure;
+ }
}
+ Z_PTR_P(t) = ARENA_REALLOC(Z_PTR(p->val));
+ zend_prepare_function_for_execution((zend_op_array*)Z_PTR_P(t));
+ }
+ target->nInternalPointer = target->nNumOfElements ? 0 : INVALID_IDX;
+ return;
+
+failure:
+ function1 = Z_PTR(p->val);
+ function2 = Z_PTR_P(t);
+ CG(in_compilation) = 1;
+ zend_set_compiled_filename(function1->op_array.filename);
+ CG(zend_lineno) = function1->op_array.opcodes[0].lineno;
+ if (function2->type == ZEND_USER_FUNCTION
+ && function2->op_array.last > 0) {
+ zend_error(E_ERROR, "Cannot redeclare %s() (previously declared in %s:%d)",
+ function1->common.function_name->val,
+ function2->op_array.filename->val,
+ (int)function2->op_array.opcodes[0].lineno);
+ } else {
+ zend_error(E_ERROR, "Cannot redeclare %s()", function1->common.function_name->val);
}
}
-static void zend_accel_class_hash_copy(HashTable *target, HashTable *source, unique_copy_ctor_func_t pCopyConstructor TSRMLS_DC)
-{
- zend_class_entry **pce1, **pce2;
-
- if (zend_hash_unique_copy(target, source, pCopyConstructor, sizeof(zend_class_entry*), ZCG(accel_directives).ignore_dups, (void**)&pce1, (void**)&pce2) != SUCCESS) {
- CG(in_compilation) = 1;
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
- zend_set_compiled_filename((*pce1)->info.user.filename TSRMLS_CC);
- CG(zend_lineno) = (*pce1)->info.user.line_start;
-#else
- zend_set_compiled_filename((*pce1)->filename TSRMLS_CC);
- CG(zend_lineno) = (*pce1)->line_start;
-#endif
- zend_error(E_ERROR, "Cannot redeclare class %s", (*pce1)->name);
- }
-}
-
-#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
-static void zend_do_delayed_early_binding(zend_op_array *op_array, zend_uint early_binding TSRMLS_DC)
+static void zend_accel_class_hash_copy(HashTable *target, HashTable *source, unique_copy_ctor_func_t pCopyConstructor)
{
- zend_uint opline_num = early_binding;
-
- if ((int)opline_num != -1) {
- zend_bool orig_in_compilation = CG(in_compilation);
- char *orig_compiled_filename = zend_set_compiled_filename(op_array->filename TSRMLS_CC);
- zend_class_entry **pce;
-
- CG(in_compilation) = 1;
- while ((int)opline_num != -1) {
- if (zend_lookup_class(Z_STRVAL(op_array->opcodes[opline_num - 1].op2.u.constant), Z_STRLEN(op_array->opcodes[opline_num - 1].op2.u.constant), &pce TSRMLS_CC) == SUCCESS) {
- do_bind_inherited_class(&op_array->opcodes[opline_num], EG(class_table), *pce, 1 TSRMLS_CC);
+ zend_class_entry *ce1;
+ uint idx;
+ Bucket *p;
+ zval *t;
+
+ for (idx = 0; idx < source->nNumUsed; idx++) {
+ p = source->arData + idx;
+ if (Z_TYPE(p->val) == IS_UNDEF) continue;
+ if (p->key) {
+ t = zend_hash_add(target, p->key, &p->val);
+ if (UNEXPECTED(t == NULL)) {
+ if (p->key->len > 0 && p->key->val[0] == 0) {
+ /* Mangled key - ignore and wait for runtime */
+ continue;
+ } else if (!ZCG(accel_directives).ignore_dups) {
+ t = zend_hash_find(target, p->key);
+ goto failure;
+ }
+ }
+ } else {
+ t = zend_hash_index_add(target, p->h, &p->val);
+ if (UNEXPECTED(t == NULL)) {
+ if (!ZCG(accel_directives).ignore_dups) {
+ t = zend_hash_index_find(target,p->h);
+ goto failure;
+ }
}
- opline_num = op_array->opcodes[opline_num].result.u.opline_num;
}
- zend_restore_compiled_filename(orig_compiled_filename TSRMLS_CC);
- CG(in_compilation) = orig_in_compilation;
+ if (pCopyConstructor) {
+ pCopyConstructor(&Z_PTR_P(t));
+ }
}
+ target->nInternalPointer = target->nNumOfElements ? 0 : INVALID_IDX;
+ return;
+
+failure:
+ ce1 = Z_PTR(p->val);
+ CG(in_compilation) = 1;
+ zend_set_compiled_filename(ce1->info.user.filename);
+ CG(zend_lineno) = ce1->info.user.line_start;
+ zend_error(E_ERROR, "Cannot redeclare class %s", ce1->name->val);
}
-#endif
-zend_op_array* zend_accel_load_script(zend_persistent_script *persistent_script, int from_shared_memory TSRMLS_DC)
+zend_op_array* zend_accel_load_script(zend_persistent_script *persistent_script, int from_shared_memory)
{
zend_op_array *op_array;
op_array = (zend_op_array *) emalloc(sizeof(zend_op_array));
*op_array = persistent_script->main_op_array;
- if (from_shared_memory) {
+ if (EXPECTED(from_shared_memory)) {
+ zend_hash_init(&ZCG(bind_hash), 10, NULL, NULL, 0);
+
+ ZCG(current_persistent_script) = persistent_script;
+ ZCG(arena_mem) = NULL;
+ if (EXPECTED(persistent_script->arena_size)) {
+ ZCG(arena_mem) = zend_arena_alloc(&CG(arena), persistent_script->arena_size);
+ memcpy(ZCG(arena_mem), persistent_script->arena_mem, persistent_script->arena_size);
+ }
+
/* Copy all the necessary stuff from shared memory to regular memory, and protect the shared script */
if (zend_hash_num_elements(&persistent_script->class_table) > 0) {
- zend_hash_init(&ZCG(bind_hash), 10, NULL, NULL, 0);
- zend_accel_class_hash_copy(CG(class_table), &persistent_script->class_table, (unique_copy_ctor_func_t) zend_class_copy_ctor TSRMLS_CC);
- zend_hash_destroy(&ZCG(bind_hash));
+ zend_accel_class_hash_copy(CG(class_table), &persistent_script->class_table, (unique_copy_ctor_func_t) zend_class_copy_ctor);
}
/* we must first to copy all classes and then prepare functions, since functions may try to bind
classes - which depend on pre-bind class entries existent in the class table */
if (zend_hash_num_elements(&persistent_script->function_table) > 0) {
- zend_accel_function_hash_copy(CG(function_table), &persistent_script->function_table, (unique_copy_ctor_func_t)zend_prepare_function_for_execution);
+ zend_accel_function_hash_copy_from_shm(CG(function_table), &persistent_script->function_table);
}
zend_prepare_function_for_execution(op_array);
@@ -1020,44 +883,35 @@ zend_op_array* zend_accel_load_script(zend_persistent_script *persistent_script,
/* Register __COMPILER_HALT_OFFSET__ constant */
if (persistent_script->compiler_halt_offset != 0 &&
persistent_script->full_path) {
- char *name, *cfilename;
+ zend_string *name;
char haltoff[] = "__COMPILER_HALT_OFFSET__";
- int len, clen;
- cfilename = persistent_script->full_path;
- clen = strlen(cfilename);
- zend_mangle_property_name(&name, &len, haltoff, sizeof(haltoff) - 1, cfilename, clen, 0);
- if (!zend_hash_exists(EG(zend_constants), name, len + 1)) {
- zend_register_long_constant(name, len + 1, persistent_script->compiler_halt_offset, CONST_CS, 0 TSRMLS_CC);
+ name = zend_mangle_property_name(haltoff, sizeof(haltoff) - 1, persistent_script->full_path->val, persistent_script->full_path->len, 0);
+ if (!zend_hash_exists(EG(zend_constants), name)) {
+ zend_register_long_constant(name->val, name->len, persistent_script->compiler_halt_offset, CONST_CS, 0);
}
- efree(name);
- }
-
-#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
- if ((int)persistent_script->early_binding != -1) {
- zend_do_delayed_early_binding(op_array, persistent_script->early_binding TSRMLS_CC);
+ zend_string_release(name);
}
-#endif
+ zend_hash_destroy(&ZCG(bind_hash));
+ ZCG(current_persistent_script) = NULL;
} else /* if (!from_shared_memory) */ {
if (zend_hash_num_elements(&persistent_script->function_table) > 0) {
- zend_accel_function_hash_copy(CG(function_table), &persistent_script->function_table, NULL);
+ zend_accel_function_hash_copy(CG(function_table), &persistent_script->function_table);
}
if (zend_hash_num_elements(&persistent_script->class_table) > 0) {
- zend_accel_class_hash_copy(CG(class_table), &persistent_script->class_table, NULL TSRMLS_CC);
+ zend_accel_class_hash_copy(CG(class_table), &persistent_script->class_table, NULL);
}
}
-#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
- if (op_array->early_binding != (zend_uint)-1) {
- char *orig_compiled_filename = CG(compiled_filename);
+ if (op_array->early_binding != (uint32_t)-1) {
+ zend_string *orig_compiled_filename = CG(compiled_filename);
CG(compiled_filename) = persistent_script->full_path;
- zend_do_delayed_early_binding(op_array TSRMLS_CC);
+ zend_do_delayed_early_binding(op_array);
CG(compiled_filename) = orig_compiled_filename;
}
-#endif
- if (!from_shared_memory) {
+ if (UNEXPECTED(!from_shared_memory)) {
free_persistent_script(persistent_script, 0); /* free only hashes */
}
diff --git a/ext/opcache/zend_accelerator_util_funcs.h b/ext/opcache/zend_accelerator_util_funcs.h
index 802e7f496b..7b3f099e65 100644
--- a/ext/opcache/zend_accelerator_util_funcs.h
+++ b/ext/opcache/zend_accelerator_util_funcs.h
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| Zend OPcache |
+----------------------------------------------------------------------+
- | Copyright (c) 1998-2015 The PHP Group |
+ | Copyright (c) 1998-2014 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -25,16 +25,15 @@
#include "zend.h"
#include "ZendAccelerator.h"
-void zend_accel_copy_internal_functions(TSRMLS_D);
+void zend_accel_copy_internal_functions(void);
zend_persistent_script* create_persistent_script(void);
-int compact_persistent_script(zend_persistent_script *script);
void free_persistent_script(zend_persistent_script *persistent_script, int destroy_elements);
-void zend_accel_free_user_functions(HashTable *ht TSRMLS_DC);
-void zend_accel_move_user_functions(HashTable *str, HashTable *dst TSRMLS_DC);
+void zend_accel_free_user_functions(HashTable *ht);
+void zend_accel_move_user_functions(HashTable *str, HashTable *dst);
-zend_op_array* zend_accel_load_script(zend_persistent_script *persistent_script, int from_shared_memory TSRMLS_DC);
+zend_op_array* zend_accel_load_script(zend_persistent_script *persistent_script, int from_shared_memory);
#define ADLER32_INIT 1 /* initial Adler-32 value */
diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c
index c0120f58cf..da3ceae357 100644
--- a/ext/opcache/zend_persist.c
+++ b/ext/opcache/zend_persist.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| Zend OPcache |
+----------------------------------------------------------------------+
- | Copyright (c) 1998-2015 The PHP Group |
+ | Copyright (c) 1998-2014 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -29,380 +29,409 @@
#include "zend_operators.h"
#define zend_accel_store(p, size) \
- (p = _zend_shared_memdup((void*)p, size, 1 TSRMLS_CC))
+ (p = _zend_shared_memdup((void*)p, size, 1))
#define zend_accel_memdup(p, size) \
- _zend_shared_memdup((void*)p, size, 0 TSRMLS_CC)
-
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
-# define zend_accel_memdup_interned_string(str, len) \
- IS_INTERNED(str) ? str : zend_accel_memdup(str, len)
-
-# define zend_accel_store_interned_string(str, len) do { \
- if (!IS_INTERNED(str)) { zend_accel_store(str, len); } \
+ _zend_shared_memdup((void*)p, size, 0)
+
+#define zend_accel_store_string(str) do { \
+ zend_string *new_str = zend_shared_alloc_get_xlat_entry(str); \
+ if (new_str) { \
+ zend_string_release(str); \
+ str = new_str; \
+ } else { \
+ new_str = zend_accel_memdup((void*)str, _STR_HEADER_SIZE + (str)->len + 1); \
+ zend_string_release(str); \
+ str = new_str; \
+ zend_string_hash_val(str); \
+ GC_FLAGS(str) = IS_STR_INTERNED | IS_STR_PERMANENT; \
+ } \
+ } while (0)
+#define zend_accel_memdup_string(str) do { \
+ str = zend_accel_memdup(str, _STR_HEADER_SIZE + (str)->len + 1); \
+ zend_string_hash_val(str); \
+ GC_FLAGS(str) = IS_STR_INTERNED | IS_STR_PERMANENT; \
+ } while (0)
+#define zend_accel_store_interned_string(str) do { \
+ if (!IS_ACCEL_INTERNED(str)) { \
+ zend_accel_store_string(str); \
+ } \
+ } while (0)
+#define zend_accel_memdup_interned_string(str) do { \
+ if (!IS_ACCEL_INTERNED(str)) { \
+ zend_accel_memdup_string(str); \
+ } \
} while (0)
-#else
-# define zend_accel_memdup_interned_string(str, len) \
- zend_accel_memdup(str, len)
-
-# define zend_accel_store_interned_string(str, len) \
- zend_accel_store(str, len)
-#endif
-typedef void (*zend_persist_func_t)(void * TSRMLS_DC);
+typedef void (*zend_persist_func_t)(zval*);
-static void zend_persist_zval_ptr(zval **zp TSRMLS_DC);
-static void zend_persist_zval(zval *z TSRMLS_DC);
+static void zend_persist_zval(zval *z);
+static void zend_persist_zval_const(zval *z);
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
-static const Bucket *uninitialized_bucket = NULL;
-#endif
+static const uint32_t uninitialized_bucket = {INVALID_IDX};
-static void zend_hash_persist(HashTable *ht, void (*pPersistElement)(void *pElement TSRMLS_DC), size_t el_size TSRMLS_DC)
+static void zend_hash_persist(HashTable *ht, zend_persist_func_t pPersistElement)
{
- Bucket *p = ht->pListHead;
- uint i;
+ uint idx;
+ Bucket *p;
- while (p) {
- Bucket *q = p;
+ if (!(ht->u.flags & HASH_FLAG_INITIALIZED)) {
+ ht->arHash = (uint32_t*)&uninitialized_bucket;
+ return;
+ }
+ if (ht->u.flags & HASH_FLAG_PACKED) {
+ zend_accel_store(ht->arData, sizeof(Bucket) * ht->nNumUsed);
+ ht->arHash = (uint32_t*)&uninitialized_bucket;
+ } else {
+ Bucket *d = (Bucket*)ZCG(mem);
+ uint32_t *h = (uint32_t*)(d + ht->nNumUsed);
- /* persist bucket and key */
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
- p = zend_accel_memdup(p, sizeof(Bucket));
- if (p->nKeyLength) {
- p->arKey = zend_accel_memdup_interned_string(p->arKey, p->nKeyLength);
- }
-#else
- p = zend_accel_memdup(p, sizeof(Bucket) - 1 + p->nKeyLength);
-#endif
+ ZCG(mem) = (void*)(h + ht->nTableSize);
+ memcpy(d, ht->arData, sizeof(Bucket) * ht->nNumUsed);
+ memcpy(h, ht->arHash, sizeof(uint32_t) * ht->nTableSize);
+ efree(ht->arData);
+ ht->arData = d;
+ ht->arHash = h;
+ }
+ for (idx = 0; idx < ht->nNumUsed; idx++) {
+ p = ht->arData + idx;
+ if (Z_TYPE(p->val) == IS_UNDEF) continue;
- /* persist data pointer in bucket */
- if (!p->pDataPtr) {
- zend_accel_store(p->pData, el_size);
- } else {
- /* Update p->pData to point to the new p->pDataPtr address, after the bucket relocation */
- p->pData = &p->pDataPtr;
+ /* persist bucket and key */
+ if (p->key) {
+ zend_accel_store_interned_string(p->key);
}
/* persist the data itself */
- if (pPersistElement) {
- pPersistElement(p->pData TSRMLS_CC);
- }
-
- /* update linked lists */
- if (p->pLast) {
- p->pLast->pNext = p;
- }
- if (p->pNext) {
- p->pNext->pLast = p;
- }
- if (p->pListLast) {
- p->pListLast->pListNext = p;
- }
- if (p->pListNext) {
- p->pListNext->pListLast = p;
- }
+ pPersistElement(&p->val);
+ }
+}
- p = p->pListNext;
+static void zend_hash_persist_immutable(HashTable *ht)
+{
+ uint idx;
+ Bucket *p;
- /* delete the old non-persistent bucket */
- efree(q);
+ if (!(ht->u.flags & HASH_FLAG_INITIALIZED)) {
+ ht->arHash = (uint32_t*)&uninitialized_bucket;
+ return;
}
+ if (ht->u.flags & HASH_FLAG_PACKED) {
+ ht->arData = zend_accel_memdup(ht->arData, sizeof(Bucket) * ht->nNumUsed);
+ ht->arHash = (uint32_t*)&uninitialized_bucket;
+ } else {
+ Bucket *d = (Bucket*)ZCG(mem);
+ uint32_t *h = (uint32_t*)(d + ht->nNumUsed);
- /* update linked lists */
- if (ht->pListHead) {
- ht->pListHead = zend_shared_alloc_get_xlat_entry(ht->pListHead);
- }
- if (ht->pListTail) {
- ht->pListTail = zend_shared_alloc_get_xlat_entry(ht->pListTail);
- }
- if (ht->pInternalPointer) {
- ht->pInternalPointer = zend_shared_alloc_get_xlat_entry(ht->pInternalPointer);
+ ZCG(mem) = (void*)(h + ht->nTableSize);
+ memcpy(d, ht->arData, sizeof(Bucket) * ht->nNumUsed);
+ memcpy(h, ht->arHash, sizeof(uint32_t) * ht->nTableSize);
+ ht->arData = d;
+ ht->arHash = h;
}
+ for (idx = 0; idx < ht->nNumUsed; idx++) {
+ p = ht->arData + idx;
+ if (Z_TYPE(p->val) == IS_UNDEF) continue;
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
- /* Check if HastTable is initialized */
- if (ht->nTableMask) {
-#endif
- if (ht->nNumOfElements) {
- /* update hash table */
- for (i = 0; i < ht->nTableSize; i++) {
- if (ht->arBuckets[i]) {
- ht->arBuckets[i] = zend_shared_alloc_get_xlat_entry(ht->arBuckets[i]);
- }
- }
+ /* persist bucket and key */
+ if (p->key) {
+ zend_accel_memdup_interned_string(p->key);
}
- zend_accel_store(ht->arBuckets, sizeof(Bucket*) * ht->nTableSize);
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
- } else {
- ht->arBuckets = (Bucket**)&uninitialized_bucket;
+
+ /* persist the data itself */
+ zend_persist_zval_const(&p->val);
}
-#endif
}
-#if ZEND_EXTENSION_API_NO > PHP_5_5_X_API_NO
-static zend_ast *zend_persist_ast(zend_ast *ast TSRMLS_DC)
+static zend_ast *zend_persist_ast(zend_ast *ast)
{
- int i;
+ uint32_t i;
zend_ast *node;
- if (ast->kind == ZEND_CONST) {
- node = zend_accel_memdup(ast, sizeof(zend_ast) + sizeof(zval));
- node->u.val = (zval*)(node + 1);
- zend_persist_zval(node->u.val TSRMLS_CC);
+ if (ast->kind == ZEND_AST_ZVAL) {
+ zend_ast_zval *copy = zend_accel_memdup(ast, sizeof(zend_ast_zval));
+ zend_persist_zval(&copy->val);
+ node = (zend_ast *) copy;
+ } else if (zend_ast_is_list(ast)) {
+ zend_ast_list *list = zend_ast_get_list(ast);
+ zend_ast_list *copy = zend_accel_memdup(ast,
+ sizeof(zend_ast_list) - sizeof(zend_ast *) + sizeof(zend_ast *) * list->children);
+ for (i = 0; i < list->children; i++) {
+ if (copy->child[i]) {
+ copy->child[i] = zend_persist_ast(copy->child[i]);
+ }
+ }
+ node = (zend_ast *) copy;
} else {
- node = zend_accel_memdup(ast, sizeof(zend_ast) + sizeof(zend_ast*) * (ast->children - 1));
- for (i = 0; i < ast->children; i++) {
- if ((&node->u.child)[i]) {
- (&node->u.child)[i] = zend_persist_ast((&node->u.child)[i] TSRMLS_CC);
+ uint32_t children = zend_ast_get_num_children(ast);
+ node = zend_accel_memdup(ast, sizeof(zend_ast) - sizeof(zend_ast *) + sizeof(zend_ast *) * children);
+ for (i = 0; i < children; i++) {
+ if (node->child[i]) {
+ node->child[i] = zend_persist_ast(node->child[i]);
}
}
}
+
efree(ast);
return node;
}
-#endif
-static void zend_persist_zval(zval *z TSRMLS_DC)
+static void zend_persist_zval(zval *z)
{
-#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
- switch (z->type & IS_CONSTANT_TYPE_MASK) {
-#else
- switch (z->type & ~IS_CONSTANT_INDEX) {
-#endif
+ zend_uchar flags;
+ void *new_ptr;
+
+ switch (Z_TYPE_P(z)) {
case IS_STRING:
case IS_CONSTANT:
- zend_accel_store_interned_string(z->value.str.val, z->value.str.len + 1);
+ flags = Z_GC_FLAGS_P(z) & ~ (IS_STR_PERSISTENT | IS_STR_INTERNED | IS_STR_PERMANENT);
+ zend_accel_store_interned_string(Z_STR_P(z));
+ Z_GC_FLAGS_P(z) |= flags;
+ Z_TYPE_FLAGS_P(z) &= ~(IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE);
break;
case IS_ARRAY:
-#if ZEND_EXTENSION_API_NO <= PHP_5_5_API_NO
- case IS_CONSTANT_ARRAY:
-#endif
- zend_accel_store(z->value.ht, sizeof(HashTable));
- zend_hash_persist(z->value.ht, (zend_persist_func_t) zend_persist_zval_ptr, sizeof(zval**) TSRMLS_CC);
+ new_ptr = zend_shared_alloc_get_xlat_entry(Z_ARR_P(z));
+ if (new_ptr) {
+ Z_ARR_P(z) = new_ptr;
+ Z_TYPE_FLAGS_P(z) = IS_TYPE_IMMUTABLE;
+ } else {
+ if (Z_IMMUTABLE_P(z)) {
+ Z_ARR_P(z) = zend_accel_memdup(Z_ARR_P(z), sizeof(zend_array));
+ zend_hash_persist_immutable(Z_ARRVAL_P(z));
+ } else {
+ GC_REMOVE_FROM_BUFFER(Z_ARR_P(z));
+ zend_accel_store(Z_ARR_P(z), sizeof(zend_array));
+ zend_hash_persist(Z_ARRVAL_P(z), zend_persist_zval);
+ /* make immutable array */
+ Z_TYPE_FLAGS_P(z) = IS_TYPE_IMMUTABLE;
+ GC_REFCOUNT(Z_COUNTED_P(z)) = 2;
+ Z_ARRVAL_P(z)->u.flags &= ~HASH_FLAG_APPLY_PROTECTION;
+ }
+ }
+ break;
+ case IS_REFERENCE:
+ new_ptr = zend_shared_alloc_get_xlat_entry(Z_REF_P(z));
+ if (new_ptr) {
+ Z_REF_P(z) = new_ptr;
+ } else {
+ zend_accel_store(Z_REF_P(z), sizeof(zend_reference));
+ zend_persist_zval(Z_REFVAL_P(z));
+ }
break;
-#if ZEND_EXTENSION_API_NO > PHP_5_5_X_API_NO
case IS_CONSTANT_AST:
- Z_AST_P(z) = zend_persist_ast(Z_AST_P(z) TSRMLS_CC);
+ new_ptr = zend_shared_alloc_get_xlat_entry(Z_AST_P(z));
+ if (new_ptr) {
+ Z_AST_P(z) = new_ptr;
+ } else {
+ zend_accel_store(Z_AST_P(z), sizeof(zend_ast_ref));
+ Z_ASTVAL_P(z) = zend_persist_ast(Z_ASTVAL_P(z));
+ }
break;
-#endif
}
}
-static void zend_persist_zval_ptr(zval **zp TSRMLS_DC)
+static void zend_persist_zval_const(zval *z)
{
- zval *new_ptr = zend_shared_alloc_get_xlat_entry(*zp);
+ zend_uchar flags;
+ void *new_ptr;
- if (new_ptr) {
- *zp = new_ptr;
- } else {
- /* Attempt to store only if we didn't store this zval_ptr yet */
- zend_accel_store(*zp, sizeof(zval));
- zend_persist_zval(*zp TSRMLS_CC);
+ switch (Z_TYPE_P(z)) {
+ case IS_STRING:
+ case IS_CONSTANT:
+ flags = Z_GC_FLAGS_P(z) & ~ (IS_STR_PERSISTENT | IS_STR_INTERNED | IS_STR_PERMANENT);
+ zend_accel_memdup_interned_string(Z_STR_P(z));
+ Z_GC_FLAGS_P(z) |= flags;
+ Z_TYPE_FLAGS_P(z) &= ~(IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE);
+ break;
+ case IS_ARRAY:
+ new_ptr = zend_shared_alloc_get_xlat_entry(Z_ARR_P(z));
+ if (new_ptr) {
+ Z_ARR_P(z) = new_ptr;
+ Z_TYPE_FLAGS_P(z) = IS_TYPE_IMMUTABLE;
+ } else {
+ if (Z_IMMUTABLE_P(z)) {
+ Z_ARR_P(z) = zend_accel_memdup(Z_ARR_P(z), sizeof(zend_array));
+ zend_hash_persist_immutable(Z_ARRVAL_P(z));
+ } else {
+ GC_REMOVE_FROM_BUFFER(Z_ARR_P(z));
+ zend_accel_store(Z_ARR_P(z), sizeof(zend_array));
+ zend_hash_persist(Z_ARRVAL_P(z), zend_persist_zval);
+ /* make immutable array */
+ Z_TYPE_FLAGS_P(z) = IS_TYPE_IMMUTABLE;
+ GC_REFCOUNT(Z_COUNTED_P(z)) = 2;
+ Z_ARRVAL_P(z)->u.flags &= ~HASH_FLAG_APPLY_PROTECTION;
+ }
+ }
+ break;
+ case IS_REFERENCE:
+ new_ptr = zend_shared_alloc_get_xlat_entry(Z_REF_P(z));
+ if (new_ptr) {
+ Z_REF_P(z) = new_ptr;
+ } else {
+ zend_accel_store(Z_REF_P(z), sizeof(zend_reference));
+ zend_persist_zval(Z_REFVAL_P(z));
+ }
+ break;
+ case IS_CONSTANT_AST:
+ new_ptr = zend_shared_alloc_get_xlat_entry(Z_AST_P(z));
+ if (new_ptr) {
+ Z_AST_P(z) = new_ptr;
+ } else {
+ zend_accel_store(Z_AST_P(z), sizeof(zend_ast_ref));
+ Z_ASTVAL_P(z) = zend_persist_ast(Z_ASTVAL_P(z));
+ }
+ break;
}
}
-static void zend_protect_zval(zval *z TSRMLS_DC)
-{
- PZ_SET_ISREF_P(z);
- PZ_SET_REFCOUNT_P(z, 2);
-}
-
-static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_script* main_persistent_script TSRMLS_DC)
+static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_script* main_persistent_script)
{
+ int already_stored = 0;
zend_op *persist_ptr;
-#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
- int has_jmp = 0;
-#endif
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
- zend_literal *orig_literals = NULL;
-#endif
+ zval *orig_literals = NULL;
if (op_array->type != ZEND_USER_FUNCTION) {
return;
}
-#if ZEND_EXTENSION_API_NO <= PHP_5_3_X_API_NO
- op_array->size = op_array->last;
-#endif
-
if (--(*op_array->refcount) == 0) {
efree(op_array->refcount);
}
op_array->refcount = NULL;
- if (op_array->filename) {
- /* do not free! PHP has centralized filename storage, compiler will free it */
- op_array->filename = zend_accel_memdup(op_array->filename, strlen(op_array->filename) + 1);
+ if (main_persistent_script) {
+ zend_execute_data *orig_execute_data = EG(current_execute_data);
+ zend_execute_data fake_execute_data;
+ zval *offset;
+
+ memset(&fake_execute_data, 0, sizeof(fake_execute_data));
+ fake_execute_data.func = (zend_function*)op_array;
+ EG(current_execute_data) = &fake_execute_data;
+ if ((offset = zend_get_constant_str("__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1)) != NULL) {
+ main_persistent_script->compiler_halt_offset = Z_LVAL_P(offset);
+ }
+ EG(current_execute_data) = orig_execute_data;
}
- if (main_persistent_script) {
- zend_bool orig_in_execution = EG(in_execution);
- zend_op_array *orig_op_array = EG(active_op_array);
- zval offset;
+ if (op_array->static_variables) {
+ zend_hash_persist(op_array->static_variables, zend_persist_zval);
+ zend_accel_store(op_array->static_variables, sizeof(HashTable));
+ }
-#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
- main_persistent_script->early_binding = -1;
-#endif
- EG(in_execution) = 1;
- EG(active_op_array) = op_array;
- if (zend_get_constant("__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1, &offset TSRMLS_CC)) {
- main_persistent_script->compiler_halt_offset = Z_LVAL(offset);
- }
- EG(active_op_array) = orig_op_array;
- EG(in_execution) = orig_in_execution;
+ if (zend_shared_alloc_get_xlat_entry(op_array->opcodes)) {
+ already_stored = 1;
}
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
if (op_array->literals) {
- orig_literals = zend_shared_alloc_get_xlat_entry(op_array->literals);
- if (orig_literals) {
+ if (already_stored) {
+ orig_literals = zend_shared_alloc_get_xlat_entry(op_array->literals);
+ ZEND_ASSERT(orig_literals != NULL);
op_array->literals = orig_literals;
} else {
- zend_literal *p = zend_accel_memdup(op_array->literals, sizeof(zend_literal) * op_array->last_literal);
- zend_literal *end = p + op_array->last_literal;
+ zval *p = zend_accel_memdup(op_array->literals, sizeof(zval) * op_array->last_literal);
+ zval *end = p + op_array->last_literal;
orig_literals = op_array->literals;
op_array->literals = p;
while (p < end) {
- zend_persist_zval(&p->constant TSRMLS_CC);
- zend_protect_zval(&p->constant TSRMLS_CC);
+ zend_persist_zval(p);
p++;
}
efree(orig_literals);
}
}
-#endif
- if ((persist_ptr = zend_shared_alloc_get_xlat_entry(op_array->opcodes))) {
+ if (already_stored) {
+ persist_ptr = zend_shared_alloc_get_xlat_entry(op_array->opcodes);
+ ZEND_ASSERT(persist_ptr != NULL);
op_array->opcodes = persist_ptr;
} else {
zend_op *new_opcodes = zend_accel_memdup(op_array->opcodes, sizeof(zend_op) * op_array->last);
+#if ZEND_USE_ABS_CONST_ADDR || ZEND_USE_ABS_JMP_ADDR
zend_op *opline = new_opcodes;
zend_op *end = new_opcodes + op_array->last;
int offset = 0;
for (; opline < end ; opline++, offset++) {
+# if ZEND_USE_ABS_CONST_ADDR
if (ZEND_OP1_TYPE(opline) == IS_CONST) {
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
opline->op1.zv = (zval*)((char*)opline->op1.zv + ((char*)op_array->literals - (char*)orig_literals));
-#else
- zend_persist_zval(&opline->op1.u.constant TSRMLS_CC);
- zend_protect_zval(&opline->op1.u.constant TSRMLS_CC);
-#endif
}
if (ZEND_OP2_TYPE(opline) == IS_CONST) {
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
opline->op2.zv = (zval*)((char*)opline->op2.zv + ((char*)op_array->literals - (char*)orig_literals));
-#else
- zend_persist_zval(&opline->op2.u.constant TSRMLS_CC);
- zend_protect_zval(&opline->op2.u.constant TSRMLS_CC);
-#endif
- }
-
-#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
- switch (opline->opcode) {
- case ZEND_JMP:
- has_jmp = 1;
- if (ZEND_DONE_PASS_TWO(op_array)) {
- ZEND_OP1(opline).jmp_addr = &new_opcodes[ZEND_OP1(opline).jmp_addr - op_array->opcodes];
- }
- break;
- case ZEND_JMPZ:
- case ZEND_JMPNZ:
- case ZEND_JMPZ_EX:
- case ZEND_JMPNZ_EX:
- has_jmp = 1;
- if (ZEND_DONE_PASS_TWO(op_array)) {
- ZEND_OP2(opline).jmp_addr = &new_opcodes[ZEND_OP2(opline).jmp_addr - op_array->opcodes];
- }
- break;
- case ZEND_JMPZNZ:
- case ZEND_BRK:
- case ZEND_CONT:
- has_jmp = 1;
- break;
- case ZEND_DECLARE_INHERITED_CLASS:
- if (main_persistent_script && ZCG(accel_directives).inherited_hack) {
- if (!has_jmp &&
- ((opline + 2) >= end ||
- (opline + 1)->opcode != ZEND_FETCH_CLASS ||
- (opline + 2)->opcode != ZEND_ADD_INTERFACE)) {
-
- zend_uint *opline_num = &main_persistent_script->early_binding;
-
- while ((int)*opline_num != -1) {
- opline_num = &new_opcodes[*opline_num].result.u.opline_num;
- }
- *opline_num = opline - new_opcodes;
- opline->result.op_type = IS_UNUSED;
- opline->result.u.opline_num = -1;
- opline->opcode = ZEND_DECLARE_INHERITED_CLASS_DELAYED;
- ZEND_VM_SET_OPCODE_HANDLER(opline);
- }
- break;
- }
}
-
-#else /* if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO */
-
+# endif
+# if ZEND_USE_ABS_JMP_ADDR
if (ZEND_DONE_PASS_TWO(op_array)) {
/* fix jumps to point to new array */
switch (opline->opcode) {
case ZEND_JMP:
case ZEND_GOTO:
-#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
case ZEND_FAST_CALL:
-#endif
ZEND_OP1(opline).jmp_addr = &new_opcodes[ZEND_OP1(opline).jmp_addr - op_array->opcodes];
break;
+ case ZEND_JMPZNZ:
+ /* relative extended_value don't have to be changed */
+ /* break omitted intentionally */
case ZEND_JMPZ:
case ZEND_JMPNZ:
case ZEND_JMPZ_EX:
case ZEND_JMPNZ_EX:
case ZEND_JMP_SET:
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
- case ZEND_JMP_SET_VAR:
-#endif
+ case ZEND_COALESCE:
+ case ZEND_NEW:
+ case ZEND_FE_RESET:
+ case ZEND_FE_FETCH:
ZEND_OP2(opline).jmp_addr = &new_opcodes[ZEND_OP2(opline).jmp_addr - op_array->opcodes];
break;
}
}
-#endif /* if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO */
+# endif
}
+#endif
efree(op_array->opcodes);
op_array->opcodes = new_opcodes;
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
if (op_array->run_time_cache) {
efree(op_array->run_time_cache);
op_array->run_time_cache = NULL;
}
-#endif
}
- if (op_array->function_name) {
- char *new_name;
- if ((new_name = zend_shared_alloc_get_xlat_entry(op_array->function_name))) {
+ if (op_array->function_name && !IS_ACCEL_INTERNED(op_array->function_name)) {
+ zend_string *new_name;
+ if (already_stored) {
+ new_name = zend_shared_alloc_get_xlat_entry(op_array->function_name);
+ ZEND_ASSERT(new_name != NULL);
op_array->function_name = new_name;
} else {
- zend_accel_store(op_array->function_name, strlen(op_array->function_name) + 1);
+ zend_accel_store_string(op_array->function_name);
}
}
+ if (op_array->filename) {
+ /* do not free! PHP has centralized filename storage, compiler will free it */
+ zend_accel_memdup_string(op_array->filename);
+ }
+
if (op_array->arg_info) {
- zend_arg_info *new_ptr;
- if ((new_ptr = zend_shared_alloc_get_xlat_entry(op_array->arg_info))) {
+ if (already_stored) {
+ zend_arg_info *new_ptr = zend_shared_alloc_get_xlat_entry(op_array->arg_info);
+ ZEND_ASSERT(new_ptr != NULL);
op_array->arg_info = new_ptr;
} else {
- zend_uint i;
+ uint32_t i, num_args;
- zend_accel_store(op_array->arg_info, sizeof(zend_arg_info) * op_array->num_args);
- for (i = 0; i < op_array->num_args; i++) {
+ num_args = op_array->num_args;
+ if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
+ num_args++;
+ }
+ zend_accel_store(op_array->arg_info, sizeof(zend_arg_info) * num_args);
+ for (i = 0; i < num_args; i++) {
if (op_array->arg_info[i].name) {
- zend_accel_store_interned_string(op_array->arg_info[i].name, op_array->arg_info[i].name_len + 1);
+ zend_accel_store_interned_string(op_array->arg_info[i].name);
}
if (op_array->arg_info[i].class_name) {
- zend_accel_store_interned_string(op_array->arg_info[i].class_name, op_array->arg_info[i].class_name_len + 1);
+ zend_accel_store_interned_string(op_array->arg_info[i].class_name);
}
}
}
@@ -412,25 +441,23 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc
zend_accel_store(op_array->brk_cont_array, sizeof(zend_brk_cont_element) * op_array->last_brk_cont);
}
- if (op_array->static_variables) {
- zend_hash_persist(op_array->static_variables, (zend_persist_func_t) zend_persist_zval_ptr, sizeof(zval**) TSRMLS_CC);
- zend_accel_store(op_array->static_variables, sizeof(HashTable));
- }
-
if (op_array->scope) {
op_array->scope = zend_shared_alloc_get_xlat_entry(op_array->scope);
}
if (op_array->doc_comment) {
if (ZCG(accel_directives).save_comments) {
- zend_accel_store(op_array->doc_comment, op_array->doc_comment_len + 1);
+ if (already_stored) {
+ op_array->doc_comment = zend_shared_alloc_get_xlat_entry(op_array->doc_comment);
+ ZEND_ASSERT(op_array->doc_comment != NULL);
+ } else {
+ zend_accel_store_string(op_array->doc_comment);
+ }
} else {
- if (!zend_shared_alloc_get_xlat_entry(op_array->doc_comment)) {
- zend_shared_alloc_register_xlat_entry(op_array->doc_comment, op_array->doc_comment);
- efree((char*)op_array->doc_comment);
+ if (!already_stored) {
+ zend_string_release(op_array->doc_comment);
}
op_array->doc_comment = NULL;
- op_array->doc_comment_len = 0;
}
}
@@ -439,13 +466,15 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc
}
if (op_array->vars) {
- if ((persist_ptr = zend_shared_alloc_get_xlat_entry(op_array->vars))) {
- op_array->vars = (zend_compiled_variable*)persist_ptr;
+ if (already_stored) {
+ persist_ptr = zend_shared_alloc_get_xlat_entry(op_array->vars);
+ ZEND_ASSERT(persist_ptr != NULL);
+ op_array->vars = (zend_string**)persist_ptr;
} else {
int i;
- zend_accel_store(op_array->vars, sizeof(zend_compiled_variable) * op_array->last_var);
+ zend_accel_store(op_array->vars, sizeof(zend_string*) * op_array->last_var);
for (i = 0; i < op_array->last_var; i++) {
- zend_accel_store_interned_string(op_array->vars[i].name, op_array->vars[i].name_len + 1);
+ zend_accel_store_interned_string(op_array->vars[i]);
}
}
}
@@ -462,88 +491,89 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc
}
}
-static void zend_persist_op_array(zend_op_array *op_array TSRMLS_DC)
+static void zend_persist_op_array(zval *zv)
{
- zend_persist_op_array_ex(op_array, NULL TSRMLS_CC);
+ memcpy(ZCG(arena_mem), Z_PTR_P(zv), sizeof(zend_op_array));
+ zend_shared_alloc_register_xlat_entry(Z_PTR_P(zv), ZCG(arena_mem));
+ Z_PTR_P(zv) = ZCG(arena_mem);
+ ZCG(arena_mem) = (void*)((char*)ZCG(arena_mem) + ZEND_ALIGNED_SIZE(sizeof(zend_op_array)));
+ zend_persist_op_array_ex(Z_PTR_P(zv), NULL);
}
-static void zend_persist_property_info(zend_property_info *prop TSRMLS_DC)
+static void zend_persist_property_info(zval *zv)
{
- zend_accel_store_interned_string(prop->name, prop->name_length + 1);
+ zend_property_info *prop;
+
+ memcpy(ZCG(arena_mem), Z_PTR_P(zv), sizeof(zend_property_info));
+ zend_shared_alloc_register_xlat_entry(Z_PTR_P(zv), ZCG(arena_mem));
+ prop = Z_PTR_P(zv) = ZCG(arena_mem);
+ ZCG(arena_mem) = (void*)((char*)ZCG(arena_mem) + ZEND_ALIGNED_SIZE(sizeof(zend_property_info)));
+ zend_accel_store_interned_string(prop->name);
if (prop->doc_comment) {
if (ZCG(accel_directives).save_comments) {
- zend_accel_store(prop->doc_comment, prop->doc_comment_len + 1);
+ zend_accel_store_string(prop->doc_comment);
} else {
if (!zend_shared_alloc_get_xlat_entry(prop->doc_comment)) {
zend_shared_alloc_register_xlat_entry(prop->doc_comment, prop->doc_comment);
- efree((char*)prop->doc_comment);
}
+ zend_string_release(prop->doc_comment);
prop->doc_comment = NULL;
- prop->doc_comment_len = 0;
}
}
}
-static void zend_persist_class_entry(zend_class_entry **pce TSRMLS_DC)
+static void zend_persist_class_entry(zval *zv)
{
- zend_class_entry *ce = *pce;
+ zend_class_entry *ce = Z_PTR_P(zv);
if (ce->type == ZEND_USER_CLASS) {
- *pce = zend_accel_store(ce, sizeof(zend_class_entry));
- zend_accel_store_interned_string(ce->name, ce->name_length + 1);
- zend_hash_persist(&ce->function_table, (zend_persist_func_t) zend_persist_op_array, sizeof(zend_op_array) TSRMLS_CC);
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
+ memcpy(ZCG(arena_mem), Z_PTR_P(zv), sizeof(zend_class_entry));
+ zend_shared_alloc_register_xlat_entry(Z_PTR_P(zv), ZCG(arena_mem));
+ ce = Z_PTR_P(zv) = ZCG(arena_mem);
+ ZCG(arena_mem) = (void*)((char*)ZCG(arena_mem) + ZEND_ALIGNED_SIZE(sizeof(zend_class_entry)));
+ zend_accel_store_interned_string(ce->name);
+ zend_hash_persist(&ce->function_table, zend_persist_op_array);
if (ce->default_properties_table) {
int i;
- zend_accel_store(ce->default_properties_table, sizeof(zval*) * ce->default_properties_count);
+ zend_accel_store(ce->default_properties_table, sizeof(zval) * ce->default_properties_count);
for (i = 0; i < ce->default_properties_count; i++) {
- if (ce->default_properties_table[i]) {
- zend_persist_zval_ptr(&ce->default_properties_table[i] TSRMLS_CC);
- }
+ zend_persist_zval(&ce->default_properties_table[i]);
}
}
if (ce->default_static_members_table) {
int i;
- zend_accel_store(ce->default_static_members_table, sizeof(zval*) * ce->default_static_members_count);
+ zend_accel_store(ce->default_static_members_table, sizeof(zval) * ce->default_static_members_count);
for (i = 0; i < ce->default_static_members_count; i++) {
- if (ce->default_static_members_table[i]) {
- zend_persist_zval_ptr(&ce->default_static_members_table[i] TSRMLS_CC);
- }
+ zend_persist_zval(&ce->default_static_members_table[i]);
}
}
ce->static_members_table = NULL;
-#else
- zend_hash_persist(&ce->default_properties, (zend_persist_func_t) zend_persist_zval_ptr, sizeof(zval**) TSRMLS_CC);
- zend_hash_persist(&ce->default_static_members, (zend_persist_func_t) zend_persist_zval_ptr, sizeof(zval**) TSRMLS_CC);
- ce->static_members = NULL;
-#endif
- zend_hash_persist(&ce->constants_table, (zend_persist_func_t) zend_persist_zval_ptr, sizeof(zval**) TSRMLS_CC);
+
+ zend_hash_persist(&ce->constants_table, zend_persist_zval);
if (ZEND_CE_FILENAME(ce)) {
/* do not free! PHP has centralized filename storage, compiler will free it */
- ZEND_CE_FILENAME(ce) = zend_accel_memdup(ZEND_CE_FILENAME(ce), strlen(ZEND_CE_FILENAME(ce)) + 1);
+ zend_accel_memdup_string(ZEND_CE_FILENAME(ce));
}
if (ZEND_CE_DOC_COMMENT(ce)) {
if (ZCG(accel_directives).save_comments) {
- zend_accel_store(ZEND_CE_DOC_COMMENT(ce), ZEND_CE_DOC_COMMENT_LEN(ce) + 1);
+ zend_accel_store_string(ZEND_CE_DOC_COMMENT(ce));
} else {
if (!zend_shared_alloc_get_xlat_entry(ZEND_CE_DOC_COMMENT(ce))) {
zend_shared_alloc_register_xlat_entry(ZEND_CE_DOC_COMMENT(ce), ZEND_CE_DOC_COMMENT(ce));
- efree((char*)ZEND_CE_DOC_COMMENT(ce));
+ zend_string_release(ZEND_CE_DOC_COMMENT(ce));
}
ZEND_CE_DOC_COMMENT(ce) = NULL;
- ZEND_CE_DOC_COMMENT_LEN(ce) = 0;
}
}
- zend_hash_persist(&ce->properties_info, (zend_persist_func_t) zend_persist_property_info, sizeof(zend_property_info) TSRMLS_CC);
+ zend_hash_persist(&ce->properties_info, zend_persist_property_info);
if (ce->num_interfaces && ce->interfaces) {
efree(ce->interfaces);
}
ce->interfaces = NULL; /* will be filled in on fetch */
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
if (ce->num_traits && ce->traits) {
efree(ce->traits);
}
@@ -554,12 +584,10 @@ static void zend_persist_class_entry(zend_class_entry **pce TSRMLS_DC)
while (ce->trait_aliases[i]) {
if (ce->trait_aliases[i]->trait_method) {
if (ce->trait_aliases[i]->trait_method->method_name) {
- zend_accel_store(ce->trait_aliases[i]->trait_method->method_name,
- ce->trait_aliases[i]->trait_method->mname_len + 1);
+ zend_accel_store_interned_string(ce->trait_aliases[i]->trait_method->method_name);
}
if (ce->trait_aliases[i]->trait_method->class_name) {
- zend_accel_store(ce->trait_aliases[i]->trait_method->class_name,
- ce->trait_aliases[i]->trait_method->cname_len + 1);
+ zend_accel_store_interned_string(ce->trait_aliases[i]->trait_method->class_name);
}
ce->trait_aliases[i]->trait_method->ce = NULL;
zend_accel_store(ce->trait_aliases[i]->trait_method,
@@ -567,13 +595,9 @@ static void zend_persist_class_entry(zend_class_entry **pce TSRMLS_DC)
}
if (ce->trait_aliases[i]->alias) {
- zend_accel_store(ce->trait_aliases[i]->alias,
- ce->trait_aliases[i]->alias_len + 1);
+ zend_accel_store_interned_string(ce->trait_aliases[i]->alias);
}
-#if ZEND_EXTENSION_API_NO <= PHP_5_4_X_API_NO
- ce->trait_aliases[i]->function = NULL;
-#endif
zend_accel_store(ce->trait_aliases[i], sizeof(zend_trait_alias));
i++;
}
@@ -585,10 +609,8 @@ static void zend_persist_class_entry(zend_class_entry **pce TSRMLS_DC)
int i = 0;
while (ce->trait_precedences[i]) {
- zend_accel_store(ce->trait_precedences[i]->trait_method->method_name,
- ce->trait_precedences[i]->trait_method->mname_len + 1);
- zend_accel_store(ce->trait_precedences[i]->trait_method->class_name,
- ce->trait_precedences[i]->trait_method->cname_len + 1);
+ zend_accel_store_interned_string(ce->trait_precedences[i]->trait_method->method_name);
+ zend_accel_store_interned_string(ce->trait_precedences[i]->trait_method->class_name);
ce->trait_precedences[i]->trait_method->ce = NULL;
zend_accel_store(ce->trait_precedences[i]->trait_method,
sizeof(zend_trait_method_reference));
@@ -596,37 +618,34 @@ static void zend_persist_class_entry(zend_class_entry **pce TSRMLS_DC)
if (ce->trait_precedences[i]->exclude_from_classes) {
int j = 0;
- while (ce->trait_precedences[i]->exclude_from_classes[j]) {
- zend_accel_store(ce->trait_precedences[i]->exclude_from_classes[j],
- strlen((char*)ce->trait_precedences[i]->exclude_from_classes[j]) + 1);
+ while (ce->trait_precedences[i]->exclude_from_classes[j].class_name) {
+ zend_accel_store_interned_string(ce->trait_precedences[i]->exclude_from_classes[j].class_name);
j++;
}
zend_accel_store(ce->trait_precedences[i]->exclude_from_classes,
sizeof(zend_class_entry*) * (j + 1));
}
-#if ZEND_EXTENSION_API_NO <= PHP_5_4_X_API_NO
- ce->trait_precedences[i]->function = NULL;
-#endif
zend_accel_store(ce->trait_precedences[i], sizeof(zend_trait_precedence));
i++;
}
zend_accel_store(
ce->trait_precedences, sizeof(zend_trait_precedence*) * (i + 1));
}
-#endif
}
}
-static int zend_update_property_info_ce(zend_property_info *prop TSRMLS_DC)
+static int zend_update_property_info_ce(zval *zv)
{
+ zend_property_info *prop = Z_PTR_P(zv);
+
prop->ce = zend_shared_alloc_get_xlat_entry(prop->ce);
return 0;
}
-static int zend_update_parent_ce(zend_class_entry **pce TSRMLS_DC)
+static int zend_update_parent_ce(zval *zv)
{
- zend_class_entry *ce = *pce;
+ zend_class_entry *ce = Z_PTR_P(zv);
if (ce->parent) {
ce->parent = zend_shared_alloc_get_xlat_entry(ce->parent);
@@ -680,37 +699,40 @@ static int zend_update_parent_ce(zend_class_entry **pce TSRMLS_DC)
ce->__tostring = zend_shared_alloc_get_xlat_entry(ce->__tostring);
ce->__tostring->op_array.refcount++;
}
-#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
if (ce->__callstatic) {
ce->__callstatic = zend_shared_alloc_get_xlat_entry(ce->__callstatic);
ce->__callstatic->op_array.refcount++;
}
-#endif
-#if ZEND_EXTENSION_API_NO >= PHP_5_6_X_API_NO
if (ce->__debugInfo) {
ce->__debugInfo = zend_shared_alloc_get_xlat_entry(ce->__debugInfo);
ce->__debugInfo->op_array.refcount++;
}
-#endif
- zend_hash_apply(&ce->properties_info, (apply_func_t) zend_update_property_info_ce TSRMLS_CC);
+ zend_hash_apply(&ce->properties_info, (apply_func_t) zend_update_property_info_ce);
return 0;
}
-static void zend_accel_persist_class_table(HashTable *class_table TSRMLS_DC)
+static void zend_accel_persist_class_table(HashTable *class_table)
{
- zend_hash_persist(class_table, (zend_persist_func_t) zend_persist_class_entry, sizeof(zend_class_entry*) TSRMLS_CC);
- zend_hash_apply(class_table, (apply_func_t) zend_update_parent_ce TSRMLS_CC);
+ zend_hash_persist(class_table, zend_persist_class_entry);
+ zend_hash_apply(class_table, (apply_func_t) zend_update_parent_ce);
}
-zend_persistent_script *zend_accel_script_persist(zend_persistent_script *script, char **key, unsigned int key_length TSRMLS_DC)
+zend_persistent_script *zend_accel_script_persist(zend_persistent_script *script, char **key, unsigned int key_length)
{
+ script->mem = ZCG(mem);
+
zend_shared_alloc_clear_xlat_table();
- zend_hash_persist(&script->function_table, (zend_persist_func_t) zend_persist_op_array, sizeof(zend_op_array) TSRMLS_CC);
- zend_accel_persist_class_table(&script->class_table TSRMLS_CC);
- zend_persist_op_array_ex(&script->main_op_array, script TSRMLS_CC);
- *key = zend_accel_memdup(*key, key_length + 1);
- zend_accel_store(script->full_path, script->full_path_len + 1);
+
zend_accel_store(script, sizeof(zend_persistent_script));
+ *key = zend_accel_memdup(*key, key_length + 1);
+ zend_accel_store_string(script->full_path);
+
+ script->arena_mem = ZCG(arena_mem) = ZCG(mem);
+ ZCG(mem) = (void*)((char*)ZCG(mem) + script->arena_size);
+
+ zend_accel_persist_class_table(&script->class_table);
+ zend_hash_persist(&script->function_table, zend_persist_op_array);
+ zend_persist_op_array_ex(&script->main_op_array, script);
return script;
}
diff --git a/ext/opcache/zend_persist.h b/ext/opcache/zend_persist.h
index 027f87a04a..1ae7fabf4e 100644
--- a/ext/opcache/zend_persist.h
+++ b/ext/opcache/zend_persist.h
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| Zend OPcache |
+----------------------------------------------------------------------+
- | Copyright (c) 1998-2015 The PHP Group |
+ | Copyright (c) 1998-2014 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -23,7 +23,7 @@
#define ZEND_PERSIST_H
int zend_accel_script_persistable(zend_persistent_script *script);
-uint zend_accel_script_persist_calc(zend_persistent_script *script, char *key, unsigned int key_length TSRMLS_DC);
-zend_persistent_script *zend_accel_script_persist(zend_persistent_script *script, char **key, unsigned int key_length TSRMLS_DC);
+uint zend_accel_script_persist_calc(zend_persistent_script *script, char *key, unsigned int key_length);
+zend_persistent_script *zend_accel_script_persist(zend_persistent_script *script, char **key, unsigned int key_length);
#endif /* ZEND_PERSIST_H */
diff --git a/ext/opcache/zend_persist_calc.c b/ext/opcache/zend_persist_calc.c
index 9b57e1bcb9..f06a871d08 100644
--- a/ext/opcache/zend_persist_calc.c
+++ b/ext/opcache/zend_persist_calc.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| Zend OPcache |
+----------------------------------------------------------------------+
- | Copyright (c) 1998-2015 The PHP Group |
+ | Copyright (c) 1998-2014 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -26,195 +26,187 @@
#include "zend_shared_alloc.h"
#include "zend_operators.h"
-#define START_SIZE() uint memory_used = 0
-#define ADD_DUP_SIZE(m,s) memory_used += zend_shared_memdup_size((void*)m, s)
-#define ADD_SIZE(m) memory_used += ZEND_ALIGNED_SIZE(m)
-#define RETURN_SIZE() return memory_used
+#define ADD_DUP_SIZE(m,s) ZCG(current_persistent_script)->size += zend_shared_memdup_size((void*)m, s)
+#define ADD_SIZE(m) ZCG(current_persistent_script)->size += ZEND_ALIGNED_SIZE(m)
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
-# define ADD_INTERNED_STRING(str, len) do { \
- if (!IS_INTERNED(str)) { \
- const char *tmp = accel_new_interned_string((str), (len), 1 TSRMLS_CC); \
+#define ADD_ARENA_SIZE(m) ZCG(current_persistent_script)->arena_size += ZEND_ALIGNED_SIZE(m)
+
+# define ADD_STRING(str) \
+ ADD_DUP_SIZE((str), _STR_HEADER_SIZE + (str)->len + 1)
+# define ADD_INTERNED_STRING(str, do_free) do { \
+ if (!IS_ACCEL_INTERNED(str)) { \
+ zend_string *tmp = accel_new_interned_string(str); \
if (tmp != (str)) { \
- (str) = (char*)tmp; \
+ if (do_free) { \
+ /*zend_string_release(str);*/ \
+ } \
+ (str) = tmp; \
} else { \
- ADD_DUP_SIZE((str), (len)); \
+ ADD_STRING(str); \
} \
} \
} while (0)
-#else
-# define ADD_INTERNED_STRING(str, len) ADD_DUP_SIZE((str), (len))
-#endif
-static uint zend_persist_zval_ptr_calc(zval **zp TSRMLS_DC);
-static uint zend_persist_zval_calc(zval *z TSRMLS_DC);
+static void zend_persist_zval_calc(zval *z);
-static uint zend_hash_persist_calc(HashTable *ht, int (*pPersistElement)(void *pElement TSRMLS_DC), size_t el_size TSRMLS_DC)
+static void zend_hash_persist_calc(HashTable *ht, void (*pPersistElement)(zval *pElement))
{
- Bucket *p = ht->pListHead;
- START_SIZE();
+ uint idx;
+ Bucket *p;
- while (p) {
- /* persist bucket and key */
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
- ADD_DUP_SIZE(p, sizeof(Bucket));
- if (p->nKeyLength) {
- const char *tmp = accel_new_interned_string(p->arKey, p->nKeyLength, 0 TSRMLS_CC);
- if (tmp != p->arKey) {
- p->arKey = tmp;
- } else {
- ADD_DUP_SIZE(p->arKey, p->nKeyLength);
- }
- }
-#else
- ADD_DUP_SIZE(p, sizeof(Bucket) - 1 + p->nKeyLength);
-#endif
+ if (!(ht->u.flags & HASH_FLAG_INITIALIZED)) {
+ return;
+ }
+ if (ht->u.flags & HASH_FLAG_PACKED) {
+ ADD_SIZE(sizeof(Bucket) * ht->nNumUsed);
+ } else {
+ ADD_SIZE(sizeof(Bucket) * ht->nNumUsed + sizeof(uint32_t) * ht->nTableSize);
+ }
- /* persist data pointer in bucket */
- if (!p->pDataPtr) {
- ADD_DUP_SIZE(p->pData, el_size);
- }
+ for (idx = 0; idx < ht->nNumUsed; idx++) {
+ p = ht->arData + idx;
+ if (Z_TYPE(p->val) == IS_UNDEF) continue;
- /* persist the data itself */
- if (pPersistElement) {
- ADD_SIZE(pPersistElement(p->pData TSRMLS_CC));
+ /* persist bucket and key */
+ if (p->key) {
+ zend_uchar flags = GC_FLAGS(p->key) & ~ (IS_STR_PERSISTENT | IS_STR_INTERNED | IS_STR_PERMANENT);
+ ADD_INTERNED_STRING(p->key, 1);
+ GC_FLAGS(p->key) |= flags;
}
- p = p->pListNext;
- }
-
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
- if (ht->nTableMask) {
- ADD_DUP_SIZE(ht->arBuckets, sizeof(Bucket*) * ht->nTableSize);
+ pPersistElement(&p->val);
}
-#else
- ADD_DUP_SIZE(ht->arBuckets, sizeof(Bucket*) * ht->nTableSize);
-#endif
-
- RETURN_SIZE();
}
-#if ZEND_EXTENSION_API_NO > PHP_5_5_X_API_NO
-static uint zend_persist_ast_calc(zend_ast *ast TSRMLS_DC)
+static void zend_persist_ast_calc(zend_ast *ast)
{
- int i;
- START_SIZE();
-
- if (ast->kind == ZEND_CONST) {
- ADD_SIZE(sizeof(zend_ast) + sizeof(zval));
- ADD_SIZE(zend_persist_zval_calc(ast->u.val TSRMLS_CC));
+ uint32_t i;
+
+ if (ast->kind == ZEND_AST_ZVAL) {
+ ADD_SIZE(sizeof(zend_ast_zval));
+ zend_persist_zval_calc(zend_ast_get_zval(ast));
+ } else if (zend_ast_is_list(ast)) {
+ zend_ast_list *list = zend_ast_get_list(ast);
+ ADD_SIZE(sizeof(zend_ast_list) - sizeof(zend_ast *) + sizeof(zend_ast *) * list->children);
+ for (i = 0; i < list->children; i++) {
+ if (list->child[i]) {
+ zend_persist_ast_calc(list->child[i]);
+ }
+ }
} else {
- ADD_SIZE(sizeof(zend_ast) + sizeof(zend_ast*) * (ast->children - 1));
- for (i = 0; i < ast->children; i++) {
- if ((&ast->u.child)[i]) {
- ADD_SIZE(zend_persist_ast_calc((&ast->u.child)[i] TSRMLS_CC));
+ uint32_t children = zend_ast_get_num_children(ast);
+ ADD_SIZE(sizeof(zend_ast) - sizeof(zend_ast *) + sizeof(zend_ast *) * children);
+ for (i = 0; i < children; i++) {
+ if (ast->child[i]) {
+ zend_persist_ast_calc(ast->child[i]);
}
}
}
- RETURN_SIZE();
}
-#endif
-static uint zend_persist_zval_calc(zval *z TSRMLS_DC)
+static void zend_persist_zval_calc(zval *z)
{
- START_SIZE();
+ zend_uchar flags;
+ uint size;
-#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
- switch (z->type & IS_CONSTANT_TYPE_MASK) {
-#else
- switch (z->type & ~IS_CONSTANT_INDEX) {
-#endif
+ switch (Z_TYPE_P(z)) {
case IS_STRING:
case IS_CONSTANT:
- ADD_INTERNED_STRING(Z_STRVAL_P(z), Z_STRLEN_P(z) + 1);
+ flags = Z_GC_FLAGS_P(z) & ~ (IS_STR_PERSISTENT | IS_STR_INTERNED | IS_STR_PERMANENT);
+ ADD_INTERNED_STRING(Z_STR_P(z), 0);
+ if (!Z_REFCOUNTED_P(z)) {
+ Z_TYPE_FLAGS_P(z) &= ~ (IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE);
+ }
+ Z_GC_FLAGS_P(z) |= flags;
break;
case IS_ARRAY:
-#if ZEND_EXTENSION_API_NO <= PHP_5_5_API_NO
- case IS_CONSTANT_ARRAY:
-#endif
- ADD_DUP_SIZE(z->value.ht, sizeof(HashTable));
- ADD_SIZE(zend_hash_persist_calc(z->value.ht, (int (*)(void* TSRMLS_DC)) zend_persist_zval_ptr_calc, sizeof(zval**) TSRMLS_CC));
+ size = zend_shared_memdup_size(Z_ARR_P(z), sizeof(zend_array));
+ if (size) {
+ ADD_SIZE(size);
+ zend_hash_persist_calc(Z_ARRVAL_P(z), zend_persist_zval_calc);
+ }
+ break;
+ case IS_REFERENCE:
+ size = zend_shared_memdup_size(Z_REF_P(z), sizeof(zend_reference));
+ if (size) {
+ ADD_SIZE(size);
+ zend_persist_zval_calc(Z_REFVAL_P(z));
+ }
break;
-#if ZEND_EXTENSION_API_NO > PHP_5_5_X_API_NO
case IS_CONSTANT_AST:
- ADD_SIZE(zend_persist_ast_calc(Z_AST_P(z) TSRMLS_CC));
+ size = zend_shared_memdup_size(Z_AST_P(z), sizeof(zend_ast_ref));
+ if (size) {
+ ADD_SIZE(size);
+ zend_persist_ast_calc(Z_ASTVAL_P(z));
+ }
break;
-#endif
}
- RETURN_SIZE();
}
-static uint zend_persist_zval_ptr_calc(zval **zp TSRMLS_DC)
+static void zend_persist_op_array_calc_ex(zend_op_array *op_array)
{
- START_SIZE();
- zval *new_ptr = zend_shared_alloc_get_xlat_entry(*zp);
-
- if (!new_ptr) {
- ADD_DUP_SIZE(*zp, sizeof(zval));
- ADD_SIZE(zend_persist_zval_calc(*zp TSRMLS_CC));
+ if (op_array->type != ZEND_USER_FUNCTION) {
+ return;
}
- RETURN_SIZE();
-}
-
-static uint zend_persist_op_array_calc(zend_op_array *op_array TSRMLS_DC)
-{
- START_SIZE();
- if (op_array->type != ZEND_USER_FUNCTION) {
- return 0;
+ if (op_array->static_variables) {
+ ADD_DUP_SIZE(op_array->static_variables, sizeof(HashTable));
+ zend_hash_persist_calc(op_array->static_variables, zend_persist_zval_calc);
}
- if (op_array->filename) {
- ADD_DUP_SIZE(op_array->filename, strlen(op_array->filename) + 1);
+ if (zend_shared_alloc_get_xlat_entry(op_array->opcodes)) {
+ /* already stored */
+ if (op_array->function_name) {
+ zend_string *new_name = zend_shared_alloc_get_xlat_entry(op_array->function_name);
+ if (IS_ACCEL_INTERNED(new_name)) {
+ op_array->function_name = new_name;
+ }
+ }
+ return;
}
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
- if (op_array->literals && !zend_shared_alloc_get_xlat_entry(op_array->literals)) {
- zend_literal *p = op_array->literals;
- zend_literal *end = p + op_array->last_literal;
- ADD_DUP_SIZE(op_array->literals, sizeof(zend_literal) * op_array->last_literal);
+ if (op_array->literals) {
+ zval *p = op_array->literals;
+ zval *end = p + op_array->last_literal;
+ ADD_DUP_SIZE(op_array->literals, sizeof(zval) * op_array->last_literal);
while (p < end) {
- ADD_SIZE(zend_persist_zval_calc(&p->constant TSRMLS_CC));
+ zend_persist_zval_calc(p);
p++;
}
}
-#endif
-
- if (!zend_shared_alloc_get_xlat_entry(op_array->opcodes)) {
-#if ZEND_EXTENSION_API_NO <= PHP_5_3_X_API_NO
- zend_op *opline = op_array->opcodes;
- zend_op *end = op_array->opcodes + op_array->last;
- ADD_DUP_SIZE(op_array->opcodes, sizeof(zend_op) * op_array->last);
- while (opline<end) {
- if (opline->op1.op_type == IS_CONST) {
- ADD_SIZE(zend_persist_zval_calc(&opline->op1.u.constant TSRMLS_CC));
- }
- if (opline->op2.op_type == IS_CONST) {
- ADD_SIZE(zend_persist_zval_calc(&opline->op2.u.constant TSRMLS_CC));
- }
- opline++;
- }
-#else
- ADD_DUP_SIZE(op_array->opcodes, sizeof(zend_op) * op_array->last);
-#endif
- }
+ ADD_DUP_SIZE(op_array->opcodes, sizeof(zend_op) * op_array->last);
if (op_array->function_name) {
- ADD_DUP_SIZE(op_array->function_name, strlen(op_array->function_name) + 1);
+ zend_string *old_name = op_array->function_name;
+ zend_string *new_name = zend_shared_alloc_get_xlat_entry(old_name);
+
+ if (new_name) {
+ op_array->function_name = new_name;
+ } else {
+ ADD_INTERNED_STRING(op_array->function_name, 0);
+ zend_shared_alloc_register_xlat_entry(old_name, op_array->function_name);
+ }
}
- if (op_array->arg_info &&
- !zend_shared_alloc_get_xlat_entry(op_array->arg_info)) {
- zend_uint i;
+ if (op_array->filename) {
+ ADD_STRING(op_array->filename);
+ }
- ADD_DUP_SIZE(op_array->arg_info, sizeof(zend_arg_info) * op_array->num_args);
- for (i = 0; i < op_array->num_args; i++) {
+ if (op_array->arg_info) {
+ uint32_t i, num_args;
+
+ num_args = op_array->num_args;
+ if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
+ num_args++;
+ }
+ ADD_DUP_SIZE(op_array->arg_info, sizeof(zend_arg_info) * num_args);
+ for (i = 0; i < num_args; i++) {
if (op_array->arg_info[i].name) {
- ADD_INTERNED_STRING(op_array->arg_info[i].name, op_array->arg_info[i].name_len + 1);
+ ADD_INTERNED_STRING(op_array->arg_info[i].name, 1);
}
if (op_array->arg_info[i].class_name) {
- ADD_INTERNED_STRING(op_array->arg_info[i].class_name, op_array->arg_info[i].class_name_len + 1);
+ ADD_INTERNED_STRING(op_array->arg_info[i].class_name, 1);
}
}
@@ -224,102 +216,91 @@ static uint zend_persist_op_array_calc(zend_op_array *op_array TSRMLS_DC)
ADD_DUP_SIZE(op_array->brk_cont_array, sizeof(zend_brk_cont_element) * op_array->last_brk_cont);
}
- if (op_array->static_variables) {
- ADD_DUP_SIZE(op_array->static_variables, sizeof(HashTable));
- ADD_SIZE(zend_hash_persist_calc(op_array->static_variables, (int (*)(void* TSRMLS_DC)) zend_persist_zval_ptr_calc, sizeof(zval**) TSRMLS_CC));
- }
-
if (ZCG(accel_directives).save_comments && op_array->doc_comment) {
- ADD_DUP_SIZE(op_array->doc_comment, op_array->doc_comment_len + 1);
+ ADD_STRING(op_array->doc_comment);
}
if (op_array->try_catch_array) {
ADD_DUP_SIZE(op_array->try_catch_array, sizeof(zend_try_catch_element) * op_array->last_try_catch);
}
- if (op_array->vars && !zend_shared_alloc_get_xlat_entry(op_array->vars)) {
+ if (op_array->vars) {
int i;
- ADD_DUP_SIZE(op_array->vars, sizeof(zend_compiled_variable) * op_array->last_var);
+ ADD_DUP_SIZE(op_array->vars, sizeof(zend_string*) * op_array->last_var);
for (i = 0; i < op_array->last_var; i++) {
- ADD_INTERNED_STRING(op_array->vars[i].name, op_array->vars[i].name_len + 1);
+ ADD_INTERNED_STRING(op_array->vars[i], 0);
}
}
+}
- RETURN_SIZE();
+static void zend_persist_op_array_calc(zval *zv)
+{
+ ADD_ARENA_SIZE(sizeof(zend_op_array));
+ zend_persist_op_array_calc_ex(Z_PTR_P(zv));
}
-static uint zend_persist_property_info_calc(zend_property_info *prop TSRMLS_DC)
+static void zend_persist_property_info_calc(zval *zv)
{
- START_SIZE();
- ADD_INTERNED_STRING(prop->name, prop->name_length + 1);
+ zend_property_info *prop = Z_PTR_P(zv);
+
+ ADD_ARENA_SIZE(sizeof(zend_property_info));
+ ADD_INTERNED_STRING(prop->name, 0);
if (ZCG(accel_directives).save_comments && prop->doc_comment) {
- ADD_DUP_SIZE(prop->doc_comment, prop->doc_comment_len + 1);
+ ADD_STRING(prop->doc_comment);
}
- RETURN_SIZE();
}
-static uint zend_persist_class_entry_calc(zend_class_entry **pce TSRMLS_DC)
+static void zend_persist_class_entry_calc(zval *zv)
{
- zend_class_entry *ce = *pce;
- START_SIZE();
+ zend_class_entry *ce = Z_PTR_P(zv);
if (ce->type == ZEND_USER_CLASS) {
- ADD_DUP_SIZE(ce, sizeof(zend_class_entry));
- ADD_INTERNED_STRING(ce->name, ce->name_length + 1);
- ADD_SIZE(zend_hash_persist_calc(&ce->function_table, (int (*)(void* TSRMLS_DC)) zend_persist_op_array_calc, sizeof(zend_op_array) TSRMLS_CC));
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
+ ADD_ARENA_SIZE(sizeof(zend_class_entry));
+ ADD_INTERNED_STRING(ce->name, 0);
+ zend_hash_persist_calc(&ce->function_table, zend_persist_op_array_calc);
if (ce->default_properties_table) {
int i;
- ADD_SIZE(sizeof(zval*) * ce->default_properties_count);
+ ADD_SIZE(sizeof(zval) * ce->default_properties_count);
for (i = 0; i < ce->default_properties_count; i++) {
- if (ce->default_properties_table[i]) {
- ADD_SIZE(zend_persist_zval_ptr_calc(&ce->default_properties_table[i] TSRMLS_CC));
- }
+ zend_persist_zval_calc(&ce->default_properties_table[i]);
}
}
if (ce->default_static_members_table) {
int i;
- ADD_SIZE(sizeof(zval*) * ce->default_static_members_count);
+ ADD_SIZE(sizeof(zval) * ce->default_static_members_count);
for (i = 0; i < ce->default_static_members_count; i++) {
- if (ce->default_static_members_table[i]) {
- ADD_SIZE(zend_persist_zval_ptr_calc(&ce->default_static_members_table[i] TSRMLS_CC));
- }
+ zend_persist_zval_calc(&ce->default_static_members_table[i]);
}
}
-#else
- ADD_SIZE(zend_hash_persist_calc(&ce->default_properties, (int (*)(void* TSRMLS_DC)) zend_persist_zval_ptr_calc, sizeof(zval**) TSRMLS_CC));
- ADD_SIZE(zend_hash_persist_calc(&ce->default_static_members, (int (*)(void* TSRMLS_DC)) zend_persist_zval_ptr_calc, sizeof(zval**) TSRMLS_CC));
-#endif
- ADD_SIZE(zend_hash_persist_calc(&ce->constants_table, (int (*)(void* TSRMLS_DC)) zend_persist_zval_ptr_calc, sizeof(zval**) TSRMLS_CC));
+ zend_hash_persist_calc(&ce->constants_table, zend_persist_zval_calc);
if (ZEND_CE_FILENAME(ce)) {
- ADD_DUP_SIZE(ZEND_CE_FILENAME(ce), strlen(ZEND_CE_FILENAME(ce)) + 1);
+ ADD_STRING(ZEND_CE_FILENAME(ce));
}
if (ZCG(accel_directives).save_comments && ZEND_CE_DOC_COMMENT(ce)) {
- ADD_DUP_SIZE(ZEND_CE_DOC_COMMENT(ce), ZEND_CE_DOC_COMMENT_LEN(ce) + 1);
+ ADD_STRING(ZEND_CE_DOC_COMMENT(ce));
}
- ADD_SIZE(zend_hash_persist_calc(&ce->properties_info, (int (*)(void* TSRMLS_DC)) zend_persist_property_info_calc, sizeof(zend_property_info) TSRMLS_CC));
+ zend_hash_persist_calc(&ce->properties_info, zend_persist_property_info_calc);
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
if (ce->trait_aliases) {
int i = 0;
while (ce->trait_aliases[i]) {
if (ce->trait_aliases[i]->trait_method) {
if (ce->trait_aliases[i]->trait_method->method_name) {
- ADD_SIZE(ce->trait_aliases[i]->trait_method->mname_len + 1);
+ ADD_INTERNED_STRING(ce->trait_aliases[i]->trait_method->method_name, 0);
}
if (ce->trait_aliases[i]->trait_method->class_name) {
- ADD_SIZE(ce->trait_aliases[i]->trait_method->cname_len + 1);
+ ADD_INTERNED_STRING(ce->trait_aliases[i]->trait_method->class_name, 0);
}
ADD_SIZE(sizeof(zend_trait_method_reference));
}
if (ce->trait_aliases[i]->alias) {
- ADD_SIZE(ce->trait_aliases[i]->alias_len + 1);
+ ADD_INTERNED_STRING(ce->trait_aliases[i]->alias, 0);
}
ADD_SIZE(sizeof(zend_trait_alias));
i++;
@@ -331,15 +312,15 @@ static uint zend_persist_class_entry_calc(zend_class_entry **pce TSRMLS_DC)
int i = 0;
while (ce->trait_precedences[i]) {
- ADD_SIZE(ce->trait_precedences[i]->trait_method->mname_len + 1);
- ADD_SIZE(ce->trait_precedences[i]->trait_method->cname_len + 1);
+ ADD_INTERNED_STRING(ce->trait_precedences[i]->trait_method->method_name, 0);
+ ADD_INTERNED_STRING(ce->trait_precedences[i]->trait_method->class_name, 0);
ADD_SIZE(sizeof(zend_trait_method_reference));
if (ce->trait_precedences[i]->exclude_from_classes) {
int j = 0;
- while (ce->trait_precedences[i]->exclude_from_classes[j]) {
- ADD_SIZE(strlen((char*)ce->trait_precedences[i]->exclude_from_classes[j]) + 1);
+ while (ce->trait_precedences[i]->exclude_from_classes[j].class_name) {
+ ADD_INTERNED_STRING(ce->trait_precedences[i]->exclude_from_classes[j].class_name, 0);
j++;
}
ADD_SIZE(sizeof(zend_class_entry*) * (j + 1));
@@ -349,26 +330,33 @@ static uint zend_persist_class_entry_calc(zend_class_entry **pce TSRMLS_DC)
}
ADD_SIZE(sizeof(zend_trait_precedence*) * (i + 1));
}
-#endif
}
- RETURN_SIZE();
}
-static uint zend_accel_persist_class_table_calc(HashTable *class_table TSRMLS_DC)
+static void zend_accel_persist_class_table_calc(HashTable *class_table)
{
- return zend_hash_persist_calc(class_table, (int (*)(void* TSRMLS_DC)) zend_persist_class_entry_calc, sizeof(zend_class_entry*) TSRMLS_CC);
+ zend_hash_persist_calc(class_table, zend_persist_class_entry_calc);
}
-uint zend_accel_script_persist_calc(zend_persistent_script *new_persistent_script, char *key, unsigned int key_length TSRMLS_DC)
+uint zend_accel_script_persist_calc(zend_persistent_script *new_persistent_script, char *key, unsigned int key_length)
{
- START_SIZE();
+ new_persistent_script->mem = NULL;
+ new_persistent_script->size = 0;
+ new_persistent_script->arena_mem = NULL;
+ new_persistent_script->arena_size = 0;
+ ZCG(current_persistent_script) = new_persistent_script;
- ADD_SIZE(zend_hash_persist_calc(&new_persistent_script->function_table, (int (*)(void* TSRMLS_DC)) zend_persist_op_array_calc, sizeof(zend_op_array) TSRMLS_CC));
- ADD_SIZE(zend_accel_persist_class_table_calc(&new_persistent_script->class_table TSRMLS_CC));
- ADD_SIZE(zend_persist_op_array_calc(&new_persistent_script->main_op_array TSRMLS_CC));
- ADD_DUP_SIZE(key, key_length + 1);
- ADD_DUP_SIZE(new_persistent_script->full_path, new_persistent_script->full_path_len + 1);
ADD_DUP_SIZE(new_persistent_script, sizeof(zend_persistent_script));
+ ADD_DUP_SIZE(key, key_length + 1);
+ ADD_STRING(new_persistent_script->full_path);
+
+ zend_accel_persist_class_table_calc(&new_persistent_script->class_table);
+ zend_hash_persist_calc(&new_persistent_script->function_table, zend_persist_op_array_calc);
+ zend_persist_op_array_calc_ex(&new_persistent_script->main_op_array);
+
+ new_persistent_script->size += new_persistent_script->arena_size;
+
+ ZCG(current_persistent_script) = NULL;
- RETURN_SIZE();
+ return new_persistent_script->size;
}
diff --git a/ext/opcache/zend_shared_alloc.c b/ext/opcache/zend_shared_alloc.c
index bbe26e8172..48c16abb9c 100644
--- a/ext/opcache/zend_shared_alloc.c
+++ b/ext/opcache/zend_shared_alloc.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| Zend OPcache |
+----------------------------------------------------------------------+
- | Copyright (c) 1998-2015 The PHP Group |
+ | Copyright (c) 1998-2014 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -157,7 +157,6 @@ int zend_shared_alloc_startup(size_t requested_size)
const zend_shared_memory_handler_entry *he;
int res = ALLOC_FAILURE;
- TSRMLS_FETCH();
/* shared_free must be valid before we call zend_shared_alloc()
* - make it temporarily point to a local variable
@@ -288,7 +287,7 @@ static size_t zend_shared_alloc_get_largest_free_block(void)
#define MIN_FREE_MEMORY 64*1024
#define SHARED_ALLOC_FAILED() do { \
- zend_accel_error(ACCEL_LOG_WARNING, "Not enough free shared space to allocate %ld bytes (%ld bytes free)", (long)size, (long)ZSMMG(shared_free)); \
+ zend_accel_error(ACCEL_LOG_WARNING, "Not enough free shared space to allocate %pd bytes (%pd bytes free)", (zend_long)size, (zend_long)ZSMMG(shared_free)); \
if (zend_shared_alloc_get_largest_free_block() < MIN_FREE_MEMORY) { \
ZSMMG(memory_exhausted) = 1; \
} \
@@ -298,7 +297,6 @@ void *zend_shared_alloc(size_t size)
{
int i;
unsigned int block_size = ZEND_ALIGNED_SIZE(size);
- TSRMLS_FETCH();
#if 1
if (!ZCG(locked)) {
@@ -325,9 +323,9 @@ void *zend_shared_alloc(size_t size)
int zend_shared_memdup_size(void *source, size_t size)
{
- void **old_p;
+ void *old_p;
- if (zend_hash_index_find(&xlat_table, (ulong)source, (void **)&old_p) == SUCCESS) {
+ if ((old_p = zend_hash_index_find_ptr(&xlat_table, (zend_ulong)source)) != NULL) {
/* we already duplicated this pointer */
return 0;
}
@@ -335,28 +333,28 @@ int zend_shared_memdup_size(void *source, size_t size)
return ZEND_ALIGNED_SIZE(size);
}
-void *_zend_shared_memdup(void *source, size_t size, zend_bool free_source TSRMLS_DC)
+void *_zend_shared_memdup(void *source, size_t size, zend_bool free_source)
{
- void **old_p, *retval;
+ void *old_p, *retval;
- if (zend_hash_index_find(&xlat_table, (ulong)source, (void **)&old_p) == SUCCESS) {
+ if ((old_p = zend_hash_index_find_ptr(&xlat_table, (zend_ulong)source)) != NULL) {
/* we already duplicated this pointer */
- return *old_p;
+ return old_p;
}
- retval = ZCG(mem);;
+ retval = ZCG(mem);
ZCG(mem) = (void*)(((char*)ZCG(mem)) + ZEND_ALIGNED_SIZE(size));
memcpy(retval, source, size);
+ zend_shared_alloc_register_xlat_entry(source, retval);
if (free_source) {
- interned_efree((char*)source);
+ efree(source);
}
- zend_shared_alloc_register_xlat_entry(source, retval);
return retval;
}
-void zend_shared_alloc_safe_unlock(TSRMLS_D)
+void zend_shared_alloc_safe_unlock(void)
{
if (ZCG(locked)) {
- zend_shared_alloc_unlock(TSRMLS_C);
+ zend_shared_alloc_unlock();
}
}
@@ -366,7 +364,7 @@ static FLOCK_STRUCTURE(mem_write_lock, F_WRLCK, SEEK_SET, 0, 1);
static FLOCK_STRUCTURE(mem_write_unlock, F_UNLCK, SEEK_SET, 0, 1);
#endif
-void zend_shared_alloc_lock(TSRMLS_D)
+void zend_shared_alloc_lock(void)
{
#ifndef ZEND_WIN32
@@ -402,10 +400,10 @@ void zend_shared_alloc_lock(TSRMLS_D)
* won't be taken from space which is freed by efree in memdup.
* Otherwise it leads to false matches in memdup check.
*/
- zend_hash_init(&xlat_table, 100, NULL, NULL, 1);
+ zend_hash_init(&xlat_table, 128, NULL, NULL, 1);
}
-void zend_shared_alloc_unlock(TSRMLS_D)
+void zend_shared_alloc_unlock(void)
{
/* Destroy translation table */
zend_hash_destroy(&xlat_table);
@@ -431,17 +429,17 @@ void zend_shared_alloc_clear_xlat_table(void)
void zend_shared_alloc_register_xlat_entry(const void *old, const void *new)
{
- zend_hash_index_update(&xlat_table, (ulong)old, (void*)&new, sizeof(void *), NULL);
+ zend_hash_index_update_ptr(&xlat_table, (zend_ulong)old, (void*)new);
}
void *zend_shared_alloc_get_xlat_entry(const void *old)
{
- void **retval;
+ void *retval;
- if (zend_hash_index_find(&xlat_table, (ulong)old, (void **)&retval) == FAILURE) {
+ if ((retval = zend_hash_index_find_ptr(&xlat_table, (zend_ulong)old)) == NULL) {
return NULL;
}
- return *retval;
+ return retval;
}
size_t zend_shared_alloc_get_free_memory(void)
@@ -476,7 +474,7 @@ const char *zend_accel_get_shared_model(void)
return g_shared_model;
}
-void zend_accel_shared_protect(int mode TSRMLS_DC)
+void zend_accel_shared_protect(int mode)
{
#ifdef HAVE_MPROTECT
int i;
diff --git a/ext/opcache/zend_shared_alloc.h b/ext/opcache/zend_shared_alloc.h
index 2ca15db86b..1476073f71 100644
--- a/ext/opcache/zend_shared_alloc.h
+++ b/ext/opcache/zend_shared_alloc.h
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| Zend OPcache |
+----------------------------------------------------------------------+
- | Copyright (c) 1998-2015 The PHP Group |
+ | Copyright (c) 1998-2014 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -124,13 +124,13 @@ void zend_shared_alloc_shutdown(void);
void *zend_shared_alloc(size_t size);
/* copy into shared memory */
-void *_zend_shared_memdup(void *p, size_t size, zend_bool free_source TSRMLS_DC);
+void *_zend_shared_memdup(void *p, size_t size, zend_bool free_source);
int zend_shared_memdup_size(void *p, size_t size);
typedef union _align_test {
void *ptr;
double dbl;
- long lng;
+ zend_long lng;
} align_test;
#if ZEND_GCC_VERSION >= 2000
@@ -143,9 +143,9 @@ typedef union _align_test {
((size + PLATFORM_ALIGNMENT - 1) & ~(PLATFORM_ALIGNMENT - 1))
/* exclusive locking */
-void zend_shared_alloc_lock(TSRMLS_D);
-void zend_shared_alloc_unlock(TSRMLS_D); /* returns the allocated size during lock..unlock */
-void zend_shared_alloc_safe_unlock(TSRMLS_D);
+void zend_shared_alloc_lock(void);
+void zend_shared_alloc_unlock(void); /* returns the allocated size during lock..unlock */
+void zend_shared_alloc_safe_unlock(void);
/* old/new mapping functions */
void zend_shared_alloc_clear_xlat_table(void);
@@ -158,7 +158,7 @@ void zend_shared_alloc_restore_state(void);
const char *zend_accel_get_shared_model(void);
/* memory write protection */
-void zend_accel_shared_protect(int mode TSRMLS_DC);
+void zend_accel_shared_protect(int mode);
#ifdef USE_MMAP
extern zend_shared_memory_handlers zend_alloc_mmap_handlers;