Hi,
Here's the last attempt at streams support in include_path.
After siccing callgrind on the patch, I'm confident it meets performance
requirements. Even in the worst case, it is significantly faster than
PHP 5.2, and insignificantly slower (1%) than the current CVS.
This patch is optimized so that it is:
1% faster than the current implementation for include/require
1% slower than current include_once/require_once implementation
It also fixes a compile warning caused by missing cast from const char *
to char *
Greg
Index: Zend/zend_vm_def.h
===================================================================
RCS file: /repository/ZendEngine2/zend_vm_def.h,v
retrieving revision 1.59.2.29.2.48.2.41
diff -u -r1.59.2.29.2.48.2.41 zend_vm_def.h
--- Zend/zend_vm_def.h 5 Mar 2008 13:34:12 -0000 1.59.2.29.2.48.2.41
+++ Zend/zend_vm_def.h 8 Mar 2008 18:35:06 -0000
@@ -3091,8 +3091,19 @@
}
break;
case ZEND_INCLUDE:
- case ZEND_REQUIRE:
- new_op_array =
compile_filename(Z_LVAL(opline->op2.u.constant), inc_filename TSRMLS_CC);
+ case ZEND_REQUIRE: {
+ char *resolved_path;
+
+ resolved_path =
zend_resolve_path(Z_STRVAL_P(inc_filename), Z_STRLEN_P(inc_filename) TSRMLS_CC);
+ if (resolved_path) {
+ zval rz;
+ ZVAL_STRINGL(&rz, resolved_path,
strlen(resolved_path), 0);
+ new_op_array =
compile_filename(Z_LVAL(opline->op2.u.constant), &rz TSRMLS_CC);
+ efree(resolved_path);
+ } else {
+ new_op_array =
compile_filename(Z_LVAL(opline->op2.u.constant), inc_filename TSRMLS_CC);
+ }
+ }
break;
case ZEND_EVAL: {
char *eval_desc =
zend_make_compiled_string_description("eval()'d code" TSRMLS_CC);
Index: Zend/zend_vm_execute.h
===================================================================
RCS file: /repository/ZendEngine2/zend_vm_execute.h,v
retrieving revision 1.62.2.30.2.49.2.40
diff -u -r1.62.2.30.2.49.2.40 zend_vm_execute.h
--- Zend/zend_vm_execute.h 5 Mar 2008 13:34:12 -0000
1.62.2.30.2.49.2.40
+++ Zend/zend_vm_execute.h 8 Mar 2008 18:35:22 -0000
@@ -1700,8 +1700,19 @@
}
break;
case ZEND_INCLUDE:
- case ZEND_REQUIRE:
- new_op_array =
compile_filename(Z_LVAL(opline->op2.u.constant), inc_filename TSRMLS_CC);
+ case ZEND_REQUIRE: {
+ char *resolved_path;
+
+ resolved_path =
zend_resolve_path(Z_STRVAL_P(inc_filename), Z_STRLEN_P(inc_filename) TSRMLS_CC);
+ if (resolved_path) {
+ zval rz;
+ ZVAL_STRINGL(&rz, resolved_path,
strlen(resolved_path), 0);
+ new_op_array =
compile_filename(Z_LVAL(opline->op2.u.constant), &rz TSRMLS_CC);
+ efree(resolved_path);
+ } else {
+ new_op_array =
compile_filename(Z_LVAL(opline->op2.u.constant), inc_filename TSRMLS_CC);
+ }
+ }
break;
case ZEND_EVAL: {
char *eval_desc =
zend_make_compiled_string_description("eval()'d code" TSRMLS_CC);
@@ -4885,8 +4896,19 @@
}
break;
case ZEND_INCLUDE:
- case ZEND_REQUIRE:
- new_op_array =
compile_filename(Z_LVAL(opline->op2.u.constant), inc_filename TSRMLS_CC);
+ case ZEND_REQUIRE: {
+ char *resolved_path;
+
+ resolved_path =
zend_resolve_path(Z_STRVAL_P(inc_filename), Z_STRLEN_P(inc_filename) TSRMLS_CC);
+ if (resolved_path) {
+ zval rz;
+ ZVAL_STRINGL(&rz, resolved_path,
strlen(resolved_path), 0);
+ new_op_array =
compile_filename(Z_LVAL(opline->op2.u.constant), &rz TSRMLS_CC);
+ efree(resolved_path);
+ } else {
+ new_op_array =
compile_filename(Z_LVAL(opline->op2.u.constant), inc_filename TSRMLS_CC);
+ }
+ }
break;
case ZEND_EVAL: {
char *eval_desc =
zend_make_compiled_string_description("eval()'d code" TSRMLS_CC);
@@ -8101,8 +8123,19 @@
}
break;
case ZEND_INCLUDE:
- case ZEND_REQUIRE:
- new_op_array =
compile_filename(Z_LVAL(opline->op2.u.constant), inc_filename TSRMLS_CC);
+ case ZEND_REQUIRE: {
+ char *resolved_path;
+
+ resolved_path =
zend_resolve_path(Z_STRVAL_P(inc_filename), Z_STRLEN_P(inc_filename) TSRMLS_CC);
+ if (resolved_path) {
+ zval rz;
+ ZVAL_STRINGL(&rz, resolved_path,
strlen(resolved_path), 0);
+ new_op_array =
compile_filename(Z_LVAL(opline->op2.u.constant), &rz TSRMLS_CC);
+ efree(resolved_path);
+ } else {
+ new_op_array =
compile_filename(Z_LVAL(opline->op2.u.constant), inc_filename TSRMLS_CC);
+ }
+ }
break;
case ZEND_EVAL: {
char *eval_desc =
zend_make_compiled_string_description("eval()'d code" TSRMLS_CC);
@@ -21781,8 +21814,19 @@
}
break;
case ZEND_INCLUDE:
- case ZEND_REQUIRE:
- new_op_array =
compile_filename(Z_LVAL(opline->op2.u.constant), inc_filename TSRMLS_CC);
+ case ZEND_REQUIRE: {
+ char *resolved_path;
+
+ resolved_path =
zend_resolve_path(Z_STRVAL_P(inc_filename), Z_STRLEN_P(inc_filename) TSRMLS_CC);
+ if (resolved_path) {
+ zval rz;
+ ZVAL_STRINGL(&rz, resolved_path,
strlen(resolved_path), 0);
+ new_op_array =
compile_filename(Z_LVAL(opline->op2.u.constant), &rz TSRMLS_CC);
+ efree(resolved_path);
+ } else {
+ new_op_array =
compile_filename(Z_LVAL(opline->op2.u.constant), inc_filename TSRMLS_CC);
+ }
+ }
break;
case ZEND_EVAL: {
char *eval_desc =
zend_make_compiled_string_description("eval()'d code" TSRMLS_CC);
Index: main/fopen_wrappers.c
===================================================================
RCS file: /repository/php-src/main/fopen_wrappers.c,v
retrieving revision 1.175.2.3.2.13.2.7
diff -u -r1.175.2.3.2.13.2.7 fopen_wrappers.c
--- main/fopen_wrappers.c 5 Mar 2008 13:34:12 -0000
1.175.2.3.2.13.2.7
+++ main/fopen_wrappers.c 8 Mar 2008 18:35:36 -0000
@@ -447,6 +447,9 @@
char resolved_path[MAXPATHLEN];
char trypath[MAXPATHLEN];
char *ptr, *end;
+ php_stream_wrapper *wrapper;
+ const char *p;
+ int n = 0;
if (!filename) {
return NULL;
@@ -462,21 +465,52 @@
return NULL;
}
}
+ /* test for stream wrappers and return */
+ for (p = filename; p - filename < filename_length && (isalnum((int)*p)
|| *p == '+' || *p == '-' || *p == '.'); p++) {
+ n++;
+ }
+
+ if (n < filename_length - 3 && (*p == ':') && (!strncmp("//", p+1, 2)
|| ( filename_length > 4 && !memcmp("data", filename, 4)))) {
+ /* found stream wrapper, this is an absolute path until stream
wrappers implement realpath */
+ return estrndup(filename, filename_length);
+ }
- ptr = path;
+ ptr = (char *) path;
while (ptr && *ptr) {
+ int len, is_stream_wrapper = 0, maybe_stream = 1;
+
end = strchr(ptr, DEFAULT_DIR_SEPARATOR);
+#ifndef PHP_WIN32
+ /* search for stream wrapper */
+ if (end - ptr <= 1) {
+ maybe_stream = 0;
+ goto not_stream;
+ }
+ for (p = ptr, n = 0; p < end && (isalnum((int)*p) || *p == '+'
|| *p == '-' || *p == '.'); p++) {
+ n++;
+ }
+
+ if (n == end - ptr && *p && !strncmp("//", p+1, 2)) {
+ is_stream_wrapper = 1;
+ /* seek to real end of include_path portion */
+ end = strchr(end + 1, DEFAULT_DIR_SEPARATOR);
+ } else {
+ maybe_stream = 0;
+ }
+not_stream:
+#endif
if (end) {
if ((end-ptr) + 1 + filename_length + 1 >= MAXPATHLEN) {
ptr = end + 1;
continue;
}
memcpy(trypath, ptr, end-ptr);
+ len = end-ptr;
trypath[end-ptr] = '/';
memcpy(trypath+(end-ptr)+1, filename,
filename_length+1);
ptr = end+1;
} else {
- int len = strlen(ptr);
+ len = strlen(ptr);
if (len + 1 + filename_length + 1 >= MAXPATHLEN) {
break;
@@ -486,6 +520,35 @@
memcpy(trypath+len+1, filename, filename_length+1);
ptr = NULL;
}
+
+ if (!is_stream_wrapper && maybe_stream) {
+ /* search for stream wrapper */
+ for (p = trypath, n = 0; isalnum((int)*p) || *p == '+'
|| *p == '-' || *p == '.'; p++) {
+ n++;
+ }
+ }
+
+ if (is_stream_wrapper || (n < len - 3 && (*p == ':') && (n > 1)
&& (!strncmp("//", p+1, 2) || !memcmp("data", trypath, 4)))) {
+ char *actual;
+
+ wrapper = php_stream_locate_url_wrapper(trypath,
&actual, STREAM_OPEN_FOR_INCLUDE TSRMLS_CC);
+ if (wrapper == &php_plain_files_wrapper) {
+ strncpy(trypath, actual, MAXPATHLEN);
+ } else if (!wrapper) {
+ /* if wrapper is NULL, there was a mal-formed
include_path stream wrapper, so skip this ptr */
+ continue;
+ } else {
+ if (wrapper->wops->url_stat) {
+ php_stream_statbuf ssb;
+
+ if (SUCCESS ==
wrapper->wops->url_stat(wrapper, trypath, 0, &ssb, NULL TSRMLS_CC)) {
+ return estrdup(trypath);
+ }
+ }
+ continue;
+ }
+ }
+
if (tsrm_realpath(trypath, resolved_path TSRMLS_CC)) {
return estrdup(resolved_path);
}
@@ -496,6 +559,8 @@
if (zend_is_executing(TSRMLS_C)) {
char *exec_fname = zend_get_executed_filename(TSRMLS_C);
int exec_fname_length = strlen(exec_fname);
+ const char *p;
+ int n = 0;
while ((--exec_fname_length >= 0) &&
!IS_SLASH(exec_fname[exec_fname_length]));
if (exec_fname && exec_fname[0] != '[' &&
@@ -503,6 +568,26 @@
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);
+
+ /* search for stream wrapper */
+ for (p = trypath; isalnum((int)*p) || *p == '+' || *p
== '-' || *p == '.'; p++) {
+ n++;
+ }
+ if (n < exec_fname_length - 3 && (*p == ':') && (n > 1)
&& (!strncmp("//", p+1, 2) || !memcmp("data", trypath, 4))) {
+ char *actual;
+
+ wrapper =
php_stream_locate_url_wrapper(trypath, &actual, STREAM_OPEN_FOR_INCLUDE
TSRMLS_CC);
+ if (wrapper == &php_plain_files_wrapper) {
+ /* this should never technically
happen, but we'll leave it here for completeness */
+ strncpy(trypath, actual, MAXPATHLEN);
+ } else if (!wrapper) {
+ /* if wrapper is NULL, there was a
mal-formed include_path stream wrapper
+ this also should be impossible */
+ return NULL;
+ } else {
+ return estrdup(trypath);
+ }
+ }
if (tsrm_realpath(trypath, resolved_path TSRMLS_CC)) {
return estrdup(resolved_path);
}
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php