summaryrefslogtreecommitdiff
path: root/Zend/zend_compile.h
diff options
context:
space:
mode:
Diffstat (limited to 'Zend/zend_compile.h')
-rw-r--r--Zend/zend_compile.h164
1 files changed, 160 insertions, 4 deletions
diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h
index 63d67660c6..c44b37b995 100644
--- a/Zend/zend_compile.h
+++ b/Zend/zend_compile.h
@@ -56,13 +56,34 @@ typedef struct _zend_compiler_context {
HashTable *labels;
} zend_compiler_context;
+/* On 64-bi systems less optimal, but more compact VM code leads to better
+ * performance. So on 32-bit systems we use absolute addresses for jump
+ * targets and constants, but on 64-bit systems realtive 32-bit offsets */
+#if SIZEOF_SIZE_T == 4
+# define ZEND_USE_ABS_JMP_ADDR 1
+# define ZEND_USE_ABS_CONST_ADDR 1
+# define ZEND_EX_USE_LITERALS 0
+# define ZEND_EX_USE_RUN_TIME_CACHE 1
+#else
+# define ZEND_USE_ABS_JMP_ADDR 0
+# define ZEND_USE_ABS_CONST_ADDR 0
+# define ZEND_EX_USE_LITERALS 1
+# define ZEND_EX_USE_RUN_TIME_CACHE 1
+#endif
+
typedef union _znode_op {
uint32_t constant;
uint32_t var;
uint32_t num;
uint32_t opline_num; /* Needs to be signed */
+#if ZEND_USE_ABS_JMP_ADDR
zend_op *jmp_addr;
+#else
+ uint32_t jmp_offset;
+#endif
+#if ZEND_USE_ABS_CONST_ADDR
zval *zv;
+#endif
} znode_op;
typedef struct _znode { /* used only during compilation */
@@ -112,8 +133,8 @@ struct _zend_op {
znode_op op1;
znode_op op2;
znode_op result;
- zend_ulong extended_value;
- uint lineno;
+ uint32_t extended_value;
+ uint32_t lineno;
zend_uchar opcode;
zend_uchar op1_type;
zend_uchar op2_type;
@@ -374,12 +395,17 @@ typedef enum _zend_call_kind {
struct _zend_execute_data {
const zend_op *opline; /* executed opline */
zend_execute_data *call; /* current call */
- void **run_time_cache;
+ zval *return_value;
zend_function *func; /* executed op_array */
zval This;
+#if ZEND_EX_USE_RUN_TIME_CACHE
+ void **run_time_cache;
+#endif
+#if ZEND_EX_USE_LITERALS
+ zval *literals;
+#endif
zend_class_entry *called_scope;
zend_execute_data *prev_execute_data;
- zval *return_value;
zend_array *symbol_table;
};
@@ -430,6 +456,136 @@ struct _zend_execute_data {
#define EX_VAR_TO_NUM(n) (ZEND_CALL_VAR(NULL, n) - ZEND_CALL_VAR_NUM(NULL, 0))
+#define ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, opline_num) \
+ ((char*)&(op_array)->opcodes[opline_num] - (char*)(opline))
+
+#define ZEND_OFFSET_TO_OPLINE(base, offset) \
+ ((zend_op*)(((char*)(base)) + (int)offset))
+
+#define ZEND_OFFSET_TO_OPLINE_NUM(op_array, base, offset) \
+ (ZEND_OFFSET_TO_OPLINE(base, offset) - op_array->opcodes)
+
+#if ZEND_USE_ABS_JMP_ADDR
+
+/* run-time jump target */
+# define OP_JMP_ADDR(opline, node) \
+ (node).jmp_addr
+
+/* convert jump target from compile-time to run-time */
+# define ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, node) do { \
+ (node).jmp_addr = (op_array)->opcodes + (node).opline_num; \
+ } while (0)
+
+/* convert jump target back from run-time to compile-time */
+# define ZEND_PASS_TWO_UNDO_JMP_TARGET(op_array, opline, node) do { \
+ (node).opline_num = (node).jmp_addr - (op_array)->opcodes; \
+ } while (0)
+
+#else
+
+/* run-time jump target */
+# define OP_JMP_ADDR(opline, node) \
+ ZEND_OFFSET_TO_OPLINE(opline, (node).jmp_offset)
+
+/* convert jump target from compile-time to run-time */
+# define ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, node) do { \
+ (node).jmp_offset = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, (node).opline_num); \
+ } while (0)
+
+/* convert jump target back from run-time to compile-time */
+# define ZEND_PASS_TWO_UNDO_JMP_TARGET(op_array, opline, node) do { \
+ (node).opline_num = ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, (node).jmp_offset); \
+ } while (0)
+
+#endif
+
+/* constant-time constant */
+# define CT_CONSTANT_EX(op_array, num) \
+ ((op_array)->literals + (num))
+
+# define CT_CONSTANT(node) \
+ CT_CONSTANT_EX(CG(active_op_array), (node).constant)
+
+#if ZEND_USE_ABS_CONST_ADDR
+
+/* run-time constant */
+# define RT_CONSTANT_EX(base, node) \
+ (node).zv
+
+/* convert constant from compile-time to run-time */
+# define ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, node) do { \
+ (node).zv = CT_CONSTANT_EX(op_array, (node).constant); \
+ } while (0)
+
+/* convert constant back from run-time to compile-time */
+# define ZEND_PASS_TWO_UNDO_CONSTANT(op_array, node) do { \
+ (node).constant = (node).zv - (op_array)->literals; \
+ } while (0)
+
+#else
+
+/* run-time constant */
+# define RT_CONSTANT_EX(base, node) \
+ ((zval*)(((char*)(base)) + (node).constant))
+
+/* convert constant from compile-time to run-time */
+# define ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, node) do { \
+ (node).constant *= sizeof(zval); \
+ } while (0)
+
+/* convert constant back from run-time to compile-time (do nothing) */
+# define ZEND_PASS_TWO_UNDO_CONSTANT(op_array, node) do { \
+ (node).constant /= sizeof(zval); \
+ } while (0)
+
+#endif
+
+#if ZEND_EX_USE_LITERALS
+
+# define EX_LITERALS() \
+ EX(literals)
+
+# define EX_LOAD_LITERALS(op_array) do { \
+ EX(literals) = (op_array)->literals; \
+ } while (0)
+
+#else
+
+# define EX_LITERALS() \
+ EX(func)->op_array.literals
+
+# define EX_LOAD_LITERALS(op_array) do { \
+ } while (0)
+
+#endif
+
+/* run-time constant */
+#define RT_CONSTANT(op_array, node) \
+ RT_CONSTANT_EX((op_array)->literals, node)
+
+/* constant in currently executed function */
+#define EX_CONSTANT(node) \
+ RT_CONSTANT_EX(EX_LITERALS(), node)
+
+#if ZEND_EX_USE_RUN_TIME_CACHE
+
+# define EX_RUN_TIME_CACHE() \
+ EX(run_time_cache)
+
+# define EX_LOAD_RUN_TIME_CACHE(op_array) do { \
+ EX(run_time_cache) = (op_array)->run_time_cache; \
+ } while (0)
+
+#else
+
+# define EX_RUN_TIME_CACHE() \
+ EX(func)->op_array.run_time_cache
+
+# define EX_LOAD_RUN_TIME_CACHE(op_array) do { \
+ } while (0)
+
+#endif
+
#define IS_CONST (1<<0)
#define IS_TMP_VAR (1<<1)
#define IS_VAR (1<<2)