Skip to content

Commit

Permalink
The patch we promised - redesigned the compilation/execution API:
Browse files Browse the repository at this point in the history
Advantages:
- Smaller memory footprint for the op arrays
- Slightly faster compilation times (due to saved erealloc() calls and faster zend_op
  initialization)
- include_once() & require_once() share the same file list
- Consistency between include() and require() - this mostly means that return()
  works inside require()'d files just as it does in include() files (it used to
  be meaningless in require()'d files, most of the time (see below))
- Made require() consistent with itself.  Before, if the argument was not a constant
  string, require() took the include() behavior (with return()).
- Removed lots of duplicate code.
Bottom line - require() and include() are very similar now;  require() is simply an include()
which isn't allowed to fail.  Due to the erealloc() calls for large op arrays, require()
didn't end up being any faster than include() in the Zend engine.
  • Loading branch information
zsuraski committed Aug 9, 2000
1 parent 609577d commit c06692e
Show file tree
Hide file tree
Showing 10 changed files with 93 additions and 236 deletions.
10 changes: 4 additions & 6 deletions Zend/zend-parser.y
Expand Up @@ -47,7 +47,7 @@
%pure_parser
%expect 4

%left T_INCLUDE T_INCLUDE_ONCE T_EVAL
%left T_INCLUDE T_INCLUDE_ONCE T_EVAL T_REQUIRE T_REQUIRE_ONCE
%left ','
%left T_LOGICAL_OR
%left T_LOGICAL_XOR
Expand Down Expand Up @@ -105,8 +105,6 @@
%token T_FUNCTION
%token T_CONST
%token T_RETURN
%token T_REQUIRE
%token T_REQUIRE_ONCE
%token T_USE
%token T_GLOBAL
%token T_STATIC
Expand Down Expand Up @@ -197,9 +195,7 @@ unticked_statement:
| T_ECHO echo_expr_list ';'
| T_INLINE_HTML { do_echo(&$1 CLS_CC); }
| expr ';' { do_free(&$1 CLS_CC); }
| T_REQUIRE expr ';' { do_require(&$2, 0 CLS_CC); }
| T_REQUIRE_ONCE use_filename ';' { do_require(&$2, 1 CLS_CC); }
| T_USE use_filename ';' { use_filename($2.u.constant.value.str.val, $2.u.constant.value.str.len CLS_CC); zval_dtor(&$2.u.constant); }
| T_USE use_filename ';' { zend_error(E_COMPILE_ERROR,"use: Not yet supported. Please use include_once() or require_once()"); zval_dtor(&$2.u.constant); }
| T_UNSET '(' unset_variables ')' ';'
| T_FOREACH '(' expr T_AS { do_foreach_begin(&$1, &$3, &$2, &$4 CLS_CC); } w_cvar foreach_optional_arg ')' { do_foreach_cont(&$6, &$7, &$4 CLS_CC); } foreach_statement { do_foreach_end(&$1, &$2 CLS_CC); }
| T_DECLARE { do_declare_begin(CLS_C); } '(' declare_list ')' declare_statement { do_declare_end(CLS_C); }
Expand Down Expand Up @@ -720,6 +716,8 @@ internal_functions_in_yacc:
| T_INCLUDE expr { do_include_or_eval(ZEND_INCLUDE, &$$, &$2 CLS_CC); }
| T_INCLUDE_ONCE expr { do_include_or_eval(ZEND_INCLUDE_ONCE, &$$, &$2 CLS_CC); }
| T_EVAL '(' expr ')' { do_include_or_eval(ZEND_EVAL, &$$, &$3 CLS_CC); }
| T_REQUIRE expr { do_include_or_eval(ZEND_REQUIRE, &$$, &$2 CLS_CC); }
| T_REQUIRE_ONCE use_filename { do_include_or_eval(ZEND_REQUIRE_ONCE, &$$, &$2 CLS_CC); }
;


Expand Down
161 changes: 23 additions & 138 deletions Zend/zend-scanner.l
Expand Up @@ -243,7 +243,7 @@ ZEND_API void zend_close_file_handle(zend_file_handle *file_handle CLS_DC)

ZEND_API int open_file_for_scanning(zend_file_handle *file_handle CLS_DC)
{
char *file_path;
char *file_path=NULL;

#ifndef ZTS
switch (file_handle->type) {
Expand Down Expand Up @@ -324,87 +324,55 @@ ZEND_API int open_file_for_scanning(zend_file_handle *file_handle CLS_DC)
END_EXTERN_C()


ZEND_API zend_op_array *zend_compile_files(int type CLS_DC, int file_count, ...)
{
va_list files;
zend_op_array *op_array;

va_start(files, file_count);
op_array = zend_v_compile_files(type CLS_CC, file_count, files);
va_end(files);
return op_array;
}


ZEND_API zend_op_array *v_compile_files(int type CLS_DC, int file_count, va_list files)
ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle CLS_DC)
{
zend_lex_state original_lex_state;
zend_op_array *op_array = (zend_op_array *) emalloc(sizeof(zend_op_array));
zend_op_array *original_active_op_array = CG(active_op_array);
zend_op_array *retval=NULL;
int i;
int compiler_result;
int compiled_files=0;
int last_file=0;
zend_bool compilation_successful=0;
znode retval_znode;
zend_bool original_in_compilation = CG(in_compilation);
zend_file_handle **file_handles = (zend_file_handle **) do_alloca(file_count * sizeof(zend_file_handle *));

retval_znode.op_type = IS_CONST;
retval_znode.u.constant.type = IS_LONG;
retval_znode.u.constant.value.lval = 1;
retval_znode.u.constant.is_ref = 0;
retval_znode.u.constant.refcount = 1;

init_op_array(op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE);
save_lexical_state(&original_lex_state CLS_CC);

retval = op_array; /* success oriented */

for (i=0; i<file_count; i++) {
file_handles[i] = va_arg(files, zend_file_handle *);
if (file_handles[i]) {
last_file = i;
}
}

for (i=0; i<file_count; i++) {
if (!file_handles[i]) {
continue;
}
if (open_file_for_scanning(file_handles[i] CLS_CC)==FAILURE) {
zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handles[i]->filename);
} else {
CG(in_compilation) = 1;
CG(active_op_array) = op_array;
compiler_result = zendparse(CLS_C);
zend_close_file_handle(file_handles[i] CLS_CC);
if (i == last_file) {
do_return(&retval_znode, 0 CLS_CC);
}
restore_lexical_state(&original_lex_state CLS_CC);
CG(in_compilation) = original_in_compilation;
if (compiler_result==1) { /* parser error */
CG(unclean_shutdown) = 1;
retval = NULL;
break;
}
compiled_files++;
if (open_file_for_scanning(file_handle CLS_CC)==FAILURE) {
zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle->filename);
compilation_successful=0;
} else {
init_op_array(op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE CLS_CC);
CG(in_compilation) = 1;
CG(active_op_array) = op_array;
compiler_result = zendparse(CLS_C);
zend_close_file_handle(file_handle CLS_CC);
do_return(&retval_znode, 0 CLS_CC);
restore_lexical_state(&original_lex_state CLS_CC);
CG(in_compilation) = original_in_compilation;
if (compiler_result==1) { /* parser error */
CG(unclean_shutdown) = 1;
retval = NULL;
}
compilation_successful=1;
}

if (retval) {
if (compiled_files>0) {
CG(active_op_array) = original_active_op_array;
CG(active_op_array) = original_active_op_array;
if (compilation_successful) {
pass_two(op_array);
} else {
CG(active_op_array) = original_active_op_array;
destroy_op_array(op_array);
efree(op_array);
retval = NULL;
}
}
free_alloca(file_handles);
return retval;
}

Expand Down Expand Up @@ -435,7 +403,7 @@ zend_op_array *compile_filename(int type, zval *filename CLS_DC ELS_DC)
error_reporting = EG(error_reporting);
EG(error_reporting) = 0;
}
retval = zend_compile_files(type CLS_CC, 1, &file_handle);
retval = zend_compile_file(&file_handle CLS_CC);

if (type==ZEND_REQUIRE) {
EG(error_reporting) = error_reporting;
Expand Down Expand Up @@ -496,13 +464,12 @@ zend_op_array *compile_string(zval *source_string CLS_DC)
convert_to_string(&tmp);
source_string = &tmp;

init_op_array(op_array, ZEND_EVAL_CODE, INITIAL_OP_ARRAY_SIZE);
save_lexical_state(&original_lex_state CLS_CC);
if (prepare_string_for_scanning(source_string CLS_CC)==FAILURE) {
destroy_op_array(op_array);
efree(op_array);
retval = NULL;
} else {
init_op_array(op_array, ZEND_EVAL_CODE, INITIAL_OP_ARRAY_SIZE CLS_CC);
CG(active_op_array) = op_array;
#ifndef ZTS
BEGIN(ST_IN_SCRIPTING);
Expand All @@ -520,7 +487,6 @@ zend_op_array *compile_string(zval *source_string CLS_DC)
do_return(NULL, 0 CLS_CC);
CG(active_op_array) = original_active_op_array;
pass_two(op_array);
pass_include_eval(op_array);
retval = op_array;
}
}
Expand All @@ -531,87 +497,6 @@ zend_op_array *compile_string(zval *source_string CLS_DC)


BEGIN_EXTERN_C()
int require_filename(char *filename, zend_bool unique CLS_DC)
{
zend_file_handle file_handle;

file_handle.type = ZEND_HANDLE_FILENAME;
file_handle.filename = filename;
file_handle.free_filename = 0;
if (require_file(&file_handle, unique CLS_CC)==FAILURE) {
zend_bailout();
return FAILURE; /* will never get here */
}
return SUCCESS;
}


int use_filename(char *filename, uint filename_length CLS_DC)
{
zend_error(E_COMPILE_ERROR,"use: Not yet supported. Please use include_once() or require_once()");
return FAILURE;

#if 0
zend_file_handle file_handle;

file_handle.filename = (char *) emalloc(filename_length + zend_uv.import_use_extension_length);
memcpy(file_handle.filename, filename, filename_length);
memcpy(file_handle.filename+filename_length, zend_uv.import_use_extension, zend_uv.import_use_extension_length);
file_handle.filename[filename_length+zend_uv.import_use_extension_length] = 0;
file_handle.free_filename = 1;

file_handle.type = ZEND_HANDLE_FILENAME;
if (require_file(&file_handle, 1 CLS_CC)==FAILURE) {
efree(file_handle.filename);
zend_bailout();
return FAILURE; /* will never get here */
}
return SUCCESS;
#endif
}


int require_file(zend_file_handle *file_handle, zend_bool unique CLS_DC)
{
zend_lex_state original_lex_state;
int compiler_result;

save_lexical_state(&original_lex_state CLS_CC);
if (open_file_for_scanning(file_handle CLS_CC)==FAILURE) {
zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename);
return FAILURE;
}
if (file_handle->opened_path) {
if (unique) {
zend_file_handle *pfh;

if (zend_hash_add(&CG(used_files), file_handle->opened_path, strlen(file_handle->opened_path)+1, file_handle, sizeof(zend_file_handle), (void **) &pfh)==FAILURE) {
zend_close_file_handle(file_handle CLS_CC);
restore_lexical_state(&original_lex_state CLS_CC);
return SUCCESS;
} else {
/* pfh is a copy we only save for get_used_files() */
pfh->type = ZEND_HANDLE_FILENAME;
if (pfh->filename) {
pfh->filename = estrdup(pfh->filename);
pfh->free_filename = 1;
}
if (pfh->opened_path) {
pfh->opened_path = strdup(pfh->opened_path);
}
}
}
}
compiler_result = zendparse(CLS_C);
zend_close_file_handle(file_handle CLS_CC);
restore_lexical_state(&original_lex_state CLS_CC);
if (compiler_result==1) {
zend_bailout();
}
return SUCCESS;
}


int highlight_file(char *filename, zend_syntax_highlighter_ini *syntax_highlighter_ini)
{
zend_lex_state original_lex_state;
Expand Down
34 changes: 33 additions & 1 deletion Zend/zend.c
Expand Up @@ -357,7 +357,7 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions, i
zend_get_ini_entry_p = utility_functions->get_ini_entry;
zend_ticks_function = utility_functions->ticks_function;

zend_v_compile_files = v_compile_files;
zend_compile_file = compile_file;
zend_execute = execute;

zend_startup_extensions();
Expand Down Expand Up @@ -692,3 +692,35 @@ ZEND_API void zend_output_debug_string(zend_bool trigger_break, char *format, ..
va_end(args);
#endif
}


ZEND_API int zend_execute_scripts(int type CLS_DC ELS_DC, int file_count, ...)
{
va_list files;
int i;
zend_file_handle *file_handle;

va_start(files, file_count);
for (i=0; i<file_count; i++) {
file_handle = va_arg(files, zend_file_handle *);
if (!file_handle) {
continue;
}
EG(active_op_array) = zend_compile_file(file_handle CLS_CC);
if (EG(active_op_array)) {
zend_execute(EG(active_op_array) ELS_CC);
zval_ptr_dtor(EG(return_value_ptr_ptr));
EG(return_value_ptr_ptr) = &EG(global_return_value_ptr);
EG(global_return_value_ptr) = NULL;
destroy_op_array(EG(active_op_array));
efree(EG(active_op_array));
} else if (type==ZEND_REQUIRE) {
va_end(files);
return FAILURE;
}
}
va_end(files);

return SUCCESS;
}

19 changes: 1 addition & 18 deletions Zend/zend_builtin_functions.c
Expand Up @@ -47,7 +47,6 @@ static ZEND_FUNCTION(leak);
#ifdef ZEND_TEST_EXCEPTIONS
static ZEND_FUNCTION(crash);
#endif
static ZEND_FUNCTION(get_required_files);
static ZEND_FUNCTION(get_included_files);
static ZEND_FUNCTION(is_subclass_of);
static ZEND_FUNCTION(get_class_vars);
Expand Down Expand Up @@ -91,8 +90,8 @@ static zend_function_entry builtin_functions[] = {
#ifdef ZEND_TEST_EXCEPTIONS
ZEND_FE(crash, NULL)
#endif
ZEND_FE(get_required_files, NULL)
ZEND_FE(get_included_files, NULL)
ZEND_FALIAS(get_required_files, get_included_files, NULL)
ZEND_FE(is_subclass_of, NULL)
ZEND_FE(get_class_vars, NULL)
ZEND_FE(get_object_vars, NULL)
Expand Down Expand Up @@ -713,22 +712,6 @@ static int copy_import_use_file(zend_file_handle *fh, zval *array)
}


/* {{{ proto array get_required_files(void)
Returns an array with the file names that were require_once()'d */
ZEND_FUNCTION(get_required_files)
{
CLS_FETCH();

if (ZEND_NUM_ARGS() != 0) {
ZEND_WRONG_PARAM_COUNT();
}

array_init(return_value);
zend_hash_apply_with_argument(&CG(used_files), (apply_func_arg_t) copy_import_use_file, return_value);
}
/* }}} */


/* {{{ proto array get_included_files(void)
Returns an array with the file names that were include_once()'d */
ZEND_FUNCTION(get_included_files)
Expand Down

0 comments on commit c06692e

Please sign in to comment.