#define DECODE_CTOR(ce) \
((zend_class_entry*)(((zend_uintptr_t)(ce)) & ~(CTOR_CALL_BIT|CTOR_USED_BIT)))
+#define ZEND_VM_STACK_PAGE_SLOTS (16 * 1024) /* should be a power of 2 */
+
+#define ZEND_VM_STACK_PAGE_SIZE (ZEND_VM_STACK_PAGE_SLOTS * sizeof(zval))
+
+#define ZEND_VM_STACK_FREE_PAGE_SIZE \
+ ((ZEND_VM_STACK_PAGE_SLOTS - ZEND_VM_STACK_HEADER_SLOTS) * sizeof(zval))
+
+#define ZEND_VM_STACK_PAGE_ALIGNED_SIZE(size) \
+ (((size) + (ZEND_VM_STACK_FREE_PAGE_SIZE - 1)) & ~ZEND_VM_STACK_PAGE_SIZE)
+
+static zend_always_inline zend_vm_stack zend_vm_stack_new_page(size_t size, zend_vm_stack prev) {
+ zend_vm_stack page = (zend_vm_stack)emalloc(size);
+
+ page->top = ZEND_VM_STACK_ELEMETS(page);
+ page->end = (zval*)((char*)page + size);
+ page->prev = prev;
+ return page;
+}
+
+ZEND_API void zend_vm_stack_init(TSRMLS_D)
+{
+ EG(vm_stack) = zend_vm_stack_new_page(ZEND_VM_STACK_PAGE_SIZE, NULL);
+ EG(vm_stack)->top++;
+ EG(vm_stack_top) = EG(vm_stack)->top;
+ EG(vm_stack_end) = EG(vm_stack)->end;
+}
+
+ZEND_API void zend_vm_stack_destroy(TSRMLS_D)
+{
+ zend_vm_stack stack = EG(vm_stack);
+
+ while (stack != NULL) {
+ zend_vm_stack p = stack->prev;
+ efree(stack);
+ stack = p;
+ }
+}
+
+ZEND_API void* zend_vm_stack_extend(size_t size TSRMLS_DC)
+{
+ zend_vm_stack stack;
+ void *ptr;
+
+ stack = EG(vm_stack);
+ stack->top = EG(vm_stack_top);
+ EG(vm_stack) = stack = zend_vm_stack_new_page(
+ EXPECTED(size < ZEND_VM_STACK_FREE_PAGE_SIZE) ?
+ ZEND_VM_STACK_PAGE_SIZE : ZEND_VM_STACK_PAGE_ALIGNED_SIZE(size),
+ stack);
+ ptr = stack->top;
+ EG(vm_stack_top) = (void*)(((char*)ptr) + size);
+ EG(vm_stack_end) = stack->end;
+ return ptr;
+}
+
ZEND_API zval* zend_get_compiled_variable_value(const zend_execute_data *execute_data, uint32_t var)
{
return EX_VAR(var);
uint32_t num_args = call->num_args;
size_t stack_size = (ZEND_CALL_FRAME_SLOT + MAX(op_array->last_var + op_array->T, num_args)) * sizeof(zval);
- EG(argument_stack) = zend_vm_stack_new_page(
+ EG(vm_stack) = zend_vm_stack_new_page(
EXPECTED(stack_size < ZEND_VM_STACK_FREE_PAGE_SIZE) ?
ZEND_VM_STACK_PAGE_SIZE :
ZEND_VM_STACK_PAGE_ALIGNED_SIZE(stack_size),
NULL);
+ EG(vm_stack_top) = EG(vm_stack)->top;
+ EG(vm_stack_end) = EG(vm_stack)->end;
execute_data = zend_vm_stack_push_call_frame(
VM_FRAME_TOP_FUNCTION,
static zend_execute_data *zend_vm_stack_copy_call_frame(zend_execute_data *call, uint32_t passed_args, uint32_t additional_args TSRMLS_DC) /* {{{ */
{
zend_execute_data *new_call;
- int used_stack = (EG(argument_stack)->top - (zval*)call) + additional_args;
+ int used_stack = (EG(vm_stack_top) - (zval*)call) + additional_args;
/* copy call frame into new stack segment */
- zend_vm_stack_extend(used_stack * sizeof(zval) TSRMLS_CC);
- new_call = (zend_execute_data*)EG(argument_stack)->top;
- EG(argument_stack)->top += used_stack;
+ new_call = zend_vm_stack_extend(used_stack * sizeof(zval) TSRMLS_CC);
*new_call = *call;
if (passed_args) {
zval *src = ZEND_CALL_ARG(call, 1);
}
/* delete old call_frame from previous stack segment */
- EG(argument_stack)->prev->top = (zval*)call;
+ EG(vm_stack)->prev->top = (zval*)call;
/* delete previous stack segment if it becames empty */
- if (UNEXPECTED(EG(argument_stack)->prev->top == ZEND_VM_STACK_ELEMETS(EG(argument_stack)->prev))) {
- zend_vm_stack r = EG(argument_stack)->prev;
+ if (UNEXPECTED(EG(vm_stack)->prev->top == ZEND_VM_STACK_ELEMETS(EG(vm_stack)->prev))) {
+ zend_vm_stack r = EG(vm_stack)->prev;
- EG(argument_stack)->prev = r->prev;
+ EG(vm_stack)->prev = r->prev;
efree(r);
}
static zend_always_inline void zend_vm_stack_extend_call_frame(zend_execute_data **call, uint32_t passed_args, uint32_t additional_args TSRMLS_DC) /* {{{ */
{
- if (EXPECTED(EG(argument_stack)->end - EG(argument_stack)->top > additional_args)) {
- EG(argument_stack)->top += additional_args;
+ if (EXPECTED(EG(vm_stack_end) - EG(vm_stack_top) > additional_args)) {
+ EG(vm_stack_top) += additional_args;
} else {
*call = zend_vm_stack_copy_call_frame(*call, passed_args, additional_args TSRMLS_CC);
}
ZEND_API int zval_update_constant_ex(zval *pp, zend_bool inline_change, zend_class_entry *scope TSRMLS_DC);
/* dedicated Zend executor functions - do not use! */
-#define ZEND_VM_STACK_PAGE_SLOTS (16 * 1024) /* should be a power of 2 */
-
-#define ZEND_VM_STACK_PAGE_SIZE (ZEND_VM_STACK_PAGE_SLOTS * sizeof(zval))
-
struct _zend_vm_stack {
zval *top;
zval *end;
#define ZEND_VM_STACK_HEADER_SLOTS \
((ZEND_MM_ALIGNED_SIZE(sizeof(struct _zend_vm_stack)) + ZEND_MM_ALIGNED_SIZE(sizeof(zval)) - 1) / ZEND_MM_ALIGNED_SIZE(sizeof(zval)))
-#define ZEND_VM_STACK_FREE_PAGE_SIZE \
- ((ZEND_VM_STACK_PAGE_SLOTS - ZEND_VM_STACK_HEADER_SLOTS) * sizeof(zval))
-
-#define ZEND_VM_STACK_PAGE_ALIGNED_SIZE(size) \
- (((size) + (ZEND_VM_STACK_FREE_PAGE_SIZE - 1)) & ~ZEND_VM_STACK_PAGE_SIZE)
-
#define ZEND_VM_STACK_ELEMETS(stack) \
(((zval*)(stack)) + ZEND_VM_STACK_HEADER_SLOTS)
-static zend_always_inline zend_vm_stack zend_vm_stack_new_page(size_t size, zend_vm_stack prev) {
- zend_vm_stack page = (zend_vm_stack)emalloc(size);
-
- page->top = ZEND_VM_STACK_ELEMETS(page);
- page->end = (zval*)((char*)page + size);
- page->prev = prev;
- return page;
-}
-
-static zend_always_inline void zend_vm_stack_init(TSRMLS_D)
-{
- EG(argument_stack) = zend_vm_stack_new_page(ZEND_VM_STACK_PAGE_SIZE, NULL);
- EG(argument_stack)->top++;
-}
-
-static zend_always_inline void zend_vm_stack_destroy(TSRMLS_D)
-{
- zend_vm_stack stack = EG(argument_stack);
-
- while (stack != NULL) {
- zend_vm_stack p = stack->prev;
- efree(stack);
- stack = p;
- }
-}
-
-static zend_always_inline void zend_vm_stack_extend(size_t size TSRMLS_DC)
-{
- EG(argument_stack) = zend_vm_stack_new_page(
- EXPECTED(size < ZEND_VM_STACK_FREE_PAGE_SIZE) ?
- ZEND_VM_STACK_PAGE_SIZE : ZEND_VM_STACK_PAGE_ALIGNED_SIZE(size),
- EG(argument_stack));
-}
+ZEND_API void zend_vm_stack_init(TSRMLS_D);
+ZEND_API void zend_vm_stack_destroy(TSRMLS_D);
+ZEND_API void* zend_vm_stack_extend(size_t size TSRMLS_DC);
static zend_always_inline zval* zend_vm_stack_alloc(size_t size TSRMLS_DC)
{
- char *top = (char*)EG(argument_stack)->top;
+ char *top = (char*)EG(vm_stack_top);
- if (UNEXPECTED(size > (size_t)(((char*)EG(argument_stack)->end) - top))) {
- zend_vm_stack_extend(size TSRMLS_CC);
- top = (char*)EG(argument_stack)->top;
+ if (UNEXPECTED(size > (size_t)(((char*)EG(vm_stack_end)) - top))) {
+ return (zval*)zend_vm_stack_extend(size TSRMLS_CC);
}
- EG(argument_stack)->top = (zval*)(top + size);
+ EG(vm_stack_top) = (zval*)(top + size);
return (zval*)top;
}
static zend_always_inline void zend_vm_stack_free_call_frame(zend_execute_data *call TSRMLS_DC)
{
- zend_vm_stack p = EG(argument_stack);
+ zend_vm_stack p = EG(vm_stack);
if (UNEXPECTED(ZEND_VM_STACK_ELEMETS(p) == (zval*)call)) {
- EG(argument_stack) = p->prev;
+ zend_vm_stack prev = p->prev;
+
+ EG(vm_stack_top) = prev->top;
+ EG(vm_stack_end) = prev->end;
+ EG(vm_stack) = prev;
efree(p);
} else {
- p->top = (zval*)call;
+ EG(vm_stack_top) = (zval*)call;
}
}
zend_generator *generator;
zend_execute_data *current_execute_data;
zend_execute_data *execute_data;
- zend_vm_stack current_stack = EG(argument_stack);
+ zend_vm_stack current_stack = EG(vm_stack);
+ current_stack->top = EG(vm_stack_top);
/* Create a clone of closure, because it may be destroyed */
if (op_array->fn_flags & ZEND_ACC_CLOSURE) {
zend_op_array *op_array_copy = (zend_op_array*)emalloc(sizeof(zend_op_array));
generator = (zend_generator *) Z_OBJ_P(return_value);
execute_data->prev_execute_data = NULL;
generator->execute_data = execute_data;
- generator->stack = EG(argument_stack);
- EG(argument_stack) = current_stack;
+ generator->stack = EG(vm_stack);
+ generator->stack->top = EG(vm_stack_top);
+ EG(vm_stack_top) = current_stack->top;
+ EG(vm_stack_end) = current_stack->end;
+ EG(vm_stack) = current_stack;
/* EX(return_value) keeps pointer to zend_object (not a real zval) */
execute_data->return_value = (zval*)generator;
/* Backup executor globals */
zend_execute_data *original_execute_data = EG(current_execute_data);
zend_class_entry *original_scope = EG(scope);
- zend_vm_stack original_stack = EG(argument_stack);
+ zend_vm_stack original_stack = EG(vm_stack);
+ original_stack->top = EG(vm_stack_top);
/* Set executor globals */
EG(current_execute_data) = generator->execute_data;
EG(scope) = generator->execute_data->scope;
- EG(argument_stack) = generator->stack;
+ EG(vm_stack_top) = generator->stack->top;
+ EG(vm_stack_end) = generator->stack->end;
+ EG(vm_stack) = generator->stack;
/* We want the backtrace to look as if the generator function was
* called from whatever method we are current running (e.g. next()).
/* Restore executor globals */
EG(current_execute_data) = original_execute_data;
EG(scope) = original_scope;
- EG(argument_stack) = original_stack;
+ EG(vm_stack_top) = original_stack->top;
+ EG(vm_stack_end) = original_stack->end;
+ EG(vm_stack) = original_stack;
/* If an exception was thrown in the generator we have to internally
* rethrow it in the parent scope. */
HashTable *class_table; /* class table */
HashTable *zend_constants; /* constants table */
+ zval *vm_stack_top;
+ zval *vm_stack_end;
+ zend_vm_stack vm_stack;
+
+ struct _zend_execute_data *current_execute_data;
zend_class_entry *scope;
zend_long precision;
HashTable regular_list;
HashTable persistent_list;
- zend_vm_stack argument_stack;
-
int user_error_handler_error_reporting;
zval user_error_handler;
zval user_exception_handler;
const zend_op *opline_before_exception;
zend_op exception_op[3];
- struct _zend_execute_data *current_execute_data;
-
struct _zend_module_entry *current_module;
zend_property_info std_property_info;
int _old_soap_version = SOAP_GLOBAL(soap_version);\
zend_bool _old_in_compilation = CG(in_compilation); \
zend_execute_data *_old_current_execute_data = EG(current_execute_data); \
- zval *_old_stack_top = EG(argument_stack)->top; \
+ zval *_old_stack_top = EG(vm_stack_top); \
int _bailout = 0;\
SOAP_GLOBAL(use_soap_error_handler) = 1;\
SOAP_GLOBAL(error_code) = "Client";\
!instanceof_function(EG(exception)->ce, soap_fault_class_entry TSRMLS_CC)) {\
_bailout = 1;\
}\
- if (_old_stack_top != EG(argument_stack)->top) { \
- while (EG(argument_stack)->prev != NULL && \
- ((char*)_old_stack_top < (char*)EG(argument_stack) || \
- (char*) _old_stack_top > (char*)EG(argument_stack)->end)) { \
- zend_vm_stack tmp = EG(argument_stack)->prev; \
- efree(EG(argument_stack)); \
- EG(argument_stack) = tmp; \
+ if (_old_stack_top != EG(vm_stack_top)) { \
+ while (EG(vm_stack)->prev != NULL && \
+ ((char*)_old_stack_top < (char*)EG(vm_stack) || \
+ (char*) _old_stack_top > (char*)EG(vm_stack)->end)) { \
+ zend_vm_stack tmp = EG(vm_stack)->prev; \
+ efree(EG(vm_stack)); \
+ EG(vm_stack) = tmp; \
+ EG(vm_stack_end) = tmp->end; \
} \
- EG(argument_stack)->top = _old_stack_top; \
+ EG(vm_stack)->top = _old_stack_top; \
} \
} zend_end_try();\
SOAP_GLOBAL(use_soap_error_handler) = _old_handler;\