xcache-3.1.0/0000755000175000010010000000000012225461700011145 5ustar mOoNonexcache-3.1.0/AUTHORS0000644000175000010010000000003212157744743012227 0ustar mOoNonemOo xcache-3.1.0/bin/0000755000175000010010000000000012206607316011721 5ustar mOoNonexcache-3.1.0/bin/phpdc.phpr0000755000175000010010000000132712167422211013713 0ustar mOoNone#! /usr/bin/php -dopen_basedir= decompileDasm(' . file_get_contents($argv[2]) . ');'); } else if (isset($argv[1])) { if ($dc->decompileFile($argv[1]) === false) { exit(2); } } else { $phpcode = ''; if (!defined('stdin')) { define('stdin', fopen('php://stdin', 'rb')); } while (!feof(stdin)) { $phpcode .= fgets(stdin); } if ($dc->decompileString($phpcode) === false) { exit(2); } } $dc->output(); xcache-3.1.0/bin/phpdop.phpr0000755000175000010010000000572112206607316014116 0ustar mOoNone#! /usr/bin/php 5, 'op1' => 20, 'op2' => 20); $opcodes = &$op_array['opcodes']; $decompiler->fixOpcode($opcodes); $decompiler->buildJmpInfo($op_array); foreach ($opcodes as $line => $op) { echo $indent; echo sprintf("%3d ", $op['lineno']); echo sprintf("%3d ", $line); $name = xcache_get_opcode($op['opcode']); if (substr($name, 0, 5) == 'ZEND_') { $name = substr($name, 5); } echo str_pad($name, 25); foreach ($types as $t => $len) { echo str_pad(isset($op[$t]) ? get_op($op[$t]) : "", $len); } printf("%5s", isset($op['extended_value']) ? $op['extended_value'] : ""); if (isset($op['jmpouts']) || isset($op['jmpins'])) { printf("%10s %10s" , (isset($op['jmpouts']) ? '>' . implode(',', $op['jmpouts']) : '') , (isset($op['jmpins']) ? '<' . implode(',', $op['jmpins']) : '') ); } if (isset($op['isCatchBegin'])) { echo 'CB'; } echo "\n"; } } function dump_function($name, $func, $indent = '') { if (isset($func['op_array'])) { $op_array = $func['op_array']; unset($func['op_array']); } else { $op_array = null; } var_dump($func); echo $indent, 'function ', $name, "\n"; if (isset($op_array)) { dump_opcodes($op_array, " " . $indent); } } function dump_class($name, $class, $indent = '') { if (isset($class['function_table'])) { $funcs = $class['function_table']; unset($class['function_table']); } else { $funcs = null; } echo $indent, 'class ', $name, "\n"; if (isset($funcs)) { foreach ($funcs as $name => $func) { dump_function($name, $func, " " . $indent); } } } if (!isset($argv[1])) { die("Usage: $argv[0] \n"); } $decompiler = new Decompiler(); if (isset($argv[2])) { eval('$pk = ' . file_get_contents($argv[2]) . ';'); } else { $pk = xcache_dasm_file($argv[1]); } $op_array = $funcs = $classes = null; if (isset($pk['op_array'])) { $op_array = $pk['op_array']; unset($pk['op_array']); } if (isset($pk['function_table'])) { $funcs = $pk['function_table']; unset($pk['function_table']); } if (isset($pk['class_table'])) { $classes = $pk['class_table']; unset($pk['class_table']); } var_dump($pk); if (isset($classes)) { foreach ($classes as $name => $class) { dump_class($name, $class); } } if (isset($funcs)) { foreach ($funcs as $name => $func) { dump_function($name, $func); } } if (isset($op_array)) { dump_opcodes($op_array); } xcache-3.1.0/ChangeLog0000644000175000010010000002672412225456054012740 0ustar mOoNone3.1.0 2013-10-10 ChangeLog ======== * added support for PHP_5_5 (cacher, optimizer, disassembler) * cacher: * closed #228: allow using var caching for cli to share data between child processes * compatible with pcntl_fork() * fixed support for __FILE__ __DIR__ to correctly handle files that got moved/hardlinked (this fix is now move out of xcache.experimental) * disassembler: * fixed crash with nested sandbox * improved support for PHP_4 ~ PHP_5_4, also added support for PHP_5_5 * admin * make mkpassword.php easier for noob * optimizer * rewrite try/catch handling to fix nested try/catch 3.0.4 2013-10-10 ChangeLog ======== * cacher * fixed #324: xcache.readonly_protection = Off cause SEGV under mass concurrent * fixed #323: refix locking impl for threaded env * build * win32: fix build with no indent.exe nor cat.exe 3.0.3 2013-06-18 ChangeLog ======== * clean files in release (fix htdocs config) 3.0.2 2013-06-10 ChangeLog ======== * cacher: * fixed #296: (PHP5.4+ only bug), racecondition Multiple instances of the same software causes PHP "cannot redeclare class" errors when readonly_protection is not in use * fixed #301: refix locking impl * fixed #307: compatible with Zend Debugger which requires to be installed after Zend Extension Manager * admin * fixed #303: tablesort.js not found in Diagnosis and Coverager * misc * fixed #297: segv on startup under sparc, ini setting overflow 3.0.1 2013-01-11 ChangeLog ======== * cacher: * fixed crash when cache is too small on start up * fixed #295: crash using traits with PHP 5.4.8+ * fix random crash when cache is reinitialized yet failed (Thanks to Brad Baker for generating crash dump) * fix locking impl: improve stability on threaded env (Thanks to Mircea Nicolae for reproducing the bug) * optimizer: * (PHP_5_4) fix ZEND_JMP_SET_VAR * (PHP_5_4) fix for goto * diagnosis: * undefined variable when ini is not found * misc: * fixed #290: workaround phpize vs fbsd make bug again * improve compatibility with "the ionCube PHP Loader", Zend Optimizer 3.0.0 2012-10-29 API Changes ======== * chg: proto array xcache_clear_cache(int type, [ int id = -1 ]). -1 means all cache splits * new: proto array xcache_enable_cache(int type, [ int id = -1, [ bool enable = true ] ]) * new: proto array xcache_admin_namespace() * new: proto array xcache_set_namespace(string namespace) Ini Settings Changes ======== * new: xcache.disable_on_crash = Off * new: xcache.coverager_autostart = On * new: xcache.allocator = bestfit (no other option value yet) * new: xcache.var_allocator = bestfit (no other option value yet) * new: xcache.var_namespace_mode = 0 * new: xcache.var_namespace = "" ChangeLog ======== * cacher: * closed #2 (auto disable caching on crash) * closed #174 (updated api to support "clear all cache") * closed #198 (support for caching protocol url) * closed #287 (namespace support) * cache can be enabled/disabled manually * coverager: * fixed #39 (ini_set never work for xcache.coverager setting. use API instead) * code refactor * use extension= to load XCache. loading via zend_extension= is unsupported * split XCache features into multiple sub modules * admin: * updated XCache admin page * adds an diagnosis module to give professional advise, accessable via htdocs pages * misc: * (>=PHP_5_3) closed #73 (warn for improper PHP_FCGI_CHILDREN setting fcgi mode) 2.0.1 2012-07-14 ChangeLog ======== * fixed #279: segv when cache is full (since 2.0) * fixed #281: subsequenc request segv when timeout happens during compiling * admin/ config changed. please update accordingly * WIN32: kill invalidate CRT parameters on shutdown * fixed: <=PHP_5_2 duplicate error message failed to include file * fixed #283: XCache admin APIs (admin page) cause SEGV if XCache failed to initize * fixed possible re-include a file by mixing include/include_once * fixed #264, #284: __FILE__ __DIR__ handling for moved/hardlinked files (set "xcache.experimental = on" to eanble this fix) 2.0.0 2012-04-20 Ini Settings Changes ======== * new: xcache.experimental = Off ChangeLog ======== * support for PHP_5_4 * reduce memory usage by caching 1 for multiple same content files * correct __FILE__ __DIR__ supported for hardlinked files * fixed #275: one line struct definition was confusing struct parser * fixed #102: segv when var cacher is too small * fixed #55: segv php tokenizer on certain special situation * fixed #278: admin page: wrong layout in opera * compiler errors: all compiler warning (E_STRICT only currently) is now cached and is supported for user handler * tests/bug52160.phpt: report multiple error correctly 1.3.2 2011-06-04 ======== * avoid possible filename injection in admin page * adds 30 seconds timeout to "compiling" flag * decompiler: improved decompiling * disassembler: improper handling of null field * disassembler: DECLARE_INHERITED_CLASS/DELAYED class not found * disassembler: don't dump builtin functions * fix win32 build against win32 native gnu tools * compatibility fix: fix segv on shutdown when ionCube Loader is loaded * fixed undefined index for xcache.count=1 and xcache.var_size>1 * fixed #258: builtin constant memory leak on compile 1.3.1 2010-11-27 ======== * 2G/4G limitation on 64bit arch * xcache_unset matching e.g. prefixed_ values 1.3.0 2009-08-04 == ChangeLog == * PHP 5.3 support * fixed #138: no segv if cache is not initialized correctly * default to 64M for xcache.size in xcache.ini * could not show module info in admin page when XCache is the last module * wrong http auth realm * coverager: font-size and newline fix for firefox * admin page is now magic quote gpc aware 1.2.2 2007-12-29 == ChangeLog == * added module dependency * live with wrong system time: allow caching files with mtime in further * bug fix for compatibility with Zend Optimizer and other non-cachable * #59: Maximum execution time of 60 seconds exceeded * #102: segv when var cacher is too small * #55: segv php tokenizer on certain special situation 1.2.1 2007-07-01 == Ini Settings Changes == * new: xcache.admin.enable_auth = On == ChangeLog == * #86: remove/edit variable in admin page * fixed #109: fast inc/dec was trying to break ro protection * fixed #101, #105: Fixed compatibility issue for apache 1.x * fixed #94: Garbage collector disabled when xcache.cacher set to off * fixed #92: Zend Optimizer compatibility issue * fixed #77: hits/misses was not updated * fixed #59: pass by reference for internal function was broken * fixed #56: xcache_set segfaults when xcache.var_size=0 ======== 1.2.0 2006-12-10 Ini Settings Changes ======== * new: xcache.stat = On * new: xcache.coverager = Off * chg: xcache.coveragedump_directory default to "" * del: xcache.coveragedumper = Off New APIs ======== * array xcache_coverager_decode(string data) * void xcache_coverager_start([bool clean = true]) * void xcache_coverager_stop([bool clean = false]) * array xcache_coverager_get([bool clean = false]) ChangeLog ======== * [290] [291] [292] build with the m4 on solaris * [283] removed zend_append_version_info. not needed after [282] * [282] fix possible alloca() scope problem in lock * [281] keep config.nice on make xcachesvnclean * [279] fixed #48, was leaking info when cacher is not enabled by size * [280] [278] trunk: fix coredump on shutdown when loaded as "extension" and after "suhosin" or "zend optimizer". thanks to Alex, Cristian and Esser * [271] fix auto detection of php-cli/php-cgi for test * [270] make [269] pass test cases * [269] do not destruct shallow copied tmp_auto_globals. also improve copying of other hash tables * [268] full compatible with auto_globals_jit, no need to disable it in ini from now on * [250] fixed css class on switcher * [231] fix zval reference handling * [230] update dprint support, added configure option: --enable-xcache-dprint * [228] more robust coverager * [227] cacher: remove redundant open_basedir check which broke php-src/ext/standard/tests/file/bug24313.phpt * [221] cacher: fix eleak in op_array non-shadow-copy (readonly_protection=on) * [220] fixed #36, Bug in inherited static class variables * [219] fix prototype for readonly_protection=off, fix testcase Zend/tests/bug37632.phpt * [217] kill leak warning on debug build * [216] avoid crash on php compiler error * [215] add `make xcachetest` to run xcache enabled test * [214] [212] fixed #41, early class binding * [272] [267] [263] [200] fixes for php6 * [224] [193] kill 64bit warning when self test is enabled * [190] trick to load and work with zend optimizer * [189] call op_array_ctor handler on restore to be more compatible with other zend_extension * [257] [183] xcache module is not required by coverage viewer any more * [165] xcache.stat support to allow tuning off stat (new ini) * [164] better way to handle system level ini settings so it can be display in phpinfo standardly 1.1.0 2006-11-11 * merged [254] fix xcache.var_ttl displaying in info, fix xcache_get for ttl-unlimited * merged [250] admin: fix switcher class on active * merged [249] return 0 s instead of empty for deltatime * merged [201] coverager: avoid crash when upstream failed to compile file * merged from trunk: 159,161-162,167-180,182,184,186-187,194 * [194] PHP_5_2: new element in zend_brk_cont_element * [186] [187] fix build on some rare arch * [184] fix tplcov * [178] fix type processor_t conflict with Mac OS X * remove redundant open_basedir check, it's done before compiling * trick in_compilation state, don't trigger __autoload at compile time * FIX conflict between sandbox and user error handler * [154] fix segv on MSHUTDOWN * [153] win32/vc build fix * [150] avoid crash when OOM on mem_realloc * [148] reconstruct shm/allocator * [147] show module info in statistics page * [146] avoid reading of uninitialized data. thanks to valgrind * [144] compat size displaying in admin page func * [143] fixed string parameter parsing arg type for disassembler functions. thanks to check_paramaters.php * [141] fix cache clear corruption bug * [140] fix refcount on cache #1 #2 … * [133] admin-page: be more friendly if XCache isn't loaded * [132] fix zts on calling destroy_op_array * [131] move open_files out of sandbox, it's not needed * [130] improve locking for compile * [137] [138] changed the coding way of unlinking list. fixed ttl expires dead loop * [114] gc expired items, new ini: xcache.ttl xcache.gc_interval xcache.var_ttl … * [126] fix xcache_isset reported by http://forum.lighttpd.net/topic/1397 * [119] fix leak in xcache.test=1; XCACHE_VERSION/XCACHE_MODULES length off-by-one * [118] show gc countdown in admin page * [113] zts build fix * [112] avoid crash when OOM on mem_(calloc|realloc|strndup) * [108] update percent bar to vertical/avail * [107] show XCache version in admin page * [105] trigger jit on $_SERVER when needed * [101] note: xcache.mmap_path is a file * [100] FIX: alloc'ed wrong size for string on restore * [99] sohosin compatible & TSRM fix. * [96] remove tailing \0 in filename of administration html output. reported by … * [94] PHP_5_2: __tostring cache was MFH by php * [93] try to show both count/size assert before abort * [92] PHP_5_2: auto module_global is maintained by php engine * [90] [91] kill compiler warnings * [87] XCACHE_INDENT fallback * [84] handle without inodes * [79] fix messy XCACHE_MAP_FAILED checking * [78] catch up with PHP_5_2, zend_property_info.ce * [77] leakcheck (not all changesets is list here) xcache-3.1.0/config.m40000644000175000010010000001114012225452353012655 0ustar mOoNonednl vim:ts=2:sw=2:expandtab AC_DEFUN([XCACHE_MODULE], [ PHP_ARG_ENABLE(xcache-$1, for XCache $1, [ --enable-xcache-$2 XCache: $4], no, no) if test "$PHP_$3" != "no"; then xcache_sources="$xcache_sources mod_$1/xc_$1.c" XCACHE_MODULES="$XCACHE_MODULES $1" HAVE_$3=1 AC_DEFINE([HAVE_$3], 1, [Define for XCache: $4]) else HAVE_$3= fi ])dnl PHP_ARG_ENABLE(xcache, for XCache support, [ --enable-xcache XCache Extension.]) if test "$PHP_XCACHE" != "no"; then PHP_ARG_ENABLE(xcache-constant, for XCache handle of compile time constant, [ --enable-xcache-constant XCache: Handle new constants made by php compiler (e.g.: for __halt_compiler)], yes, no) if test "$PHP_XCACHE_CONSTANT" != "no"; then AC_DEFINE([HAVE_XCACHE_CONSTANT], 1, [Define to enable XCache handling of compile time constants]) fi xcache_sources="xcache.c" for i in \ xc_stack.c \ xc_trace.c \ ; do xcache_sources="$xcache_sources util/$i" done for i in \ xc_allocator.c \ xc_allocator_bestfit.c \ xc_compatibility.c \ xc_const_string.c \ xc_extension.c \ xc_ini.c \ xc_mutex.c \ xc_opcode_spec.c \ xc_processor.c \ xc_sandbox.c \ xc_shm.c \ xc_shm_mmap.c \ xc_utils.c \ ; do xcache_sources="$xcache_sources xcache/$i" done for i in \ xc_cacher.c \ ; do xcache_sources="$xcache_sources mod_cacher/$i" done XCACHE_MODULES="cacher" AC_DEFINE([HAVE_XCACHE_CACHER], 1, [Define to enable XCache cacher]) XCACHE_MODULE([optimizer], [optimizer ], [XCACHE_OPTIMIZER], [(N/A)]) XCACHE_MODULE([coverager], [coverager ], [XCACHE_COVERAGER], [Enable code coverage dumper, useful for testing php scripts]) XCACHE_MODULE([assembler], [assembler ], [XCACHE_ASSEMBLER], [(N/A)]) XCACHE_MODULE([disassembler], [disassembler], [XCACHE_DISASSEMBLER], [Enable opcode to php variable dumper, not for server usage]) XCACHE_MODULE([encoder], [encoder ], [XCACHE_ENCODER], [(N/A)]) XCACHE_MODULE([decoder], [decoder ], [XCACHE_DECODER], [(N/A)]) AC_DEFINE_UNQUOTED([XCACHE_MODULES], "$XCACHE_MODULES", [Define what modules is built with XCache]) PHP_ARG_ENABLE(xcache-test, for XCache self test, [ --enable-xcache-test XCache: Enable self test - FOR DEVELOPERS ONLY!!], no, no) if test "$PHP_XCACHE_TEST" != "no"; then XCACHE_ENABLE_TEST=-DXCACHE_ENABLE_TEST xcache_sources="$xcache_sources xcache/xc_malloc.c" AC_DEFINE([HAVE_XCACHE_TEST], 1, [Define to enable XCache self test]) else XCACHE_ENABLE_TEST= fi PHP_SUBST([XCACHE_ENABLE_TEST]) PHP_ARG_ENABLE(xcache-dprint, for XCache self test, [ --enable-xcache-dprint XCache: Enable debug print functions - FOR DEVELOPERS ONLY!!], no, no) if test "$PHP_XCACHE_DPRINT" != "no"; then AC_DEFINE([HAVE_XCACHE_DPRINT], 1, [Define to enable XCache debug print functions]) fi PHP_NEW_EXTENSION(xcache, $xcache_sources, $ext_shared) for module in $XCACHE_MODULES; do PHP_ADD_BUILD_DIR($ext_builddir/mod_$module) done PHP_ADD_BUILD_DIR($ext_builddir/util) PHP_ADD_BUILD_DIR($ext_builddir/xcache) PHP_ADD_MAKEFILE_FRAGMENT() PHP_ADD_MAKEFILE_FRAGMENT($ext_srcdir/Makefile.frag.deps) AC_PATH_PROGS([XCACHE_AWK], [gawk awk]) dnl clean locale for gawk 3.1.5 assertion bug if echo | LANG=C "$XCACHE_AWK" -- '' > /dev/null 2>&1 ; then XCACHE_AWK="LANG=C $XCACHE_AWK" else if echo | /usr/bin/env - "$XCACHE_AWK" -- '' > /dev/null 2>&1 ; then XCACHE_AWK="/usr/bin/env - $XCACHE_AWK" fi fi PHP_SUBST([XCACHE_AWK]) AC_PATH_PROGS([M4], [m4]) if test "$PHP_XCACHE_TEST" != "no"; then if echo | "$M4" -E > /dev/null 2>&1 ; then M4="$M4 -E" fi fi dnl fix for solaris m4: size of the push-back and argument if echo | "$M4" -B 102400 > /dev/null 2>&1 ; then M4="$M4 -B 102400" fi PHP_SUBST([M4]) XCACHE_BACKTICK="'"'`'"'" PHP_SUBST([XCACHE_BACKTICK]) AC_PATH_PROGS([GREP], [grep]) PHP_SUBST([GREP]) AC_PATH_PROGS([SED], [sed]) PHP_SUBST([SED]) AC_PATH_PROGS([INDENT], [indent cat]) XCACHE_INDENT=cat case $INDENT in */indent[)] XCACHE_INDENT="$INDENT" opts="-kr --use-tabs --tab-size 4" if echo | $INDENT $opts > /dev/null 2>&1 ; then XCACHE_INDENT="$XCACHE_INDENT $opts" fi opts="-sob -nce" if echo | $INDENT $opts > /dev/null 2>&1 ; then XCACHE_INDENT="$XCACHE_INDENT $opts" fi opts="-l 160" if echo | $INDENT $opts > /dev/null 2>&1 ; then XCACHE_INDENT="$XCACHE_INDENT $opts" fi ;; esac PHP_SUBST([XCACHE_INDENT]) dnl $ac_srcdir etc require PHP_NEW_EXTENSION XCACHE_PROC_SOURCES=`ls $ac_srcdir/processor/*.m4` PHP_SUBST([XCACHE_PROC_SOURCES]) fi xcache-3.1.0/config.w320000644000175000010010000001166412225454046012764 0ustar mOoNone// vim:ft=javascript ARG_ENABLE("xcache", "XCache Extension", "no"); if (PHP_XCACHE != "no") { EXTENSION("xcache", "xcache.c", null, "/I " + configure_module_dirname); // {{{ check for xcache-constant ARG_ENABLE("xcache-constant", "XCache: Handle new constants made by php compiler (e.g.: for __halt_compiler)", "yes"); if (PHP_XCACHE_CONSTANT != "no") { AC_DEFINE("HAVE_XCACHE_CONSTANT", 1, "Define to enable XCache handling of compile time constants"); } // }}} ADD_SOURCES(configure_module_dirname + "/util", " \ xc_stack.c \ xc_trace.c \ ", "xcache"); ADD_SOURCES(configure_module_dirname + "/xcache", " \ xc_allocator.c \ xc_allocator_bestfit.c \ xc_compatibility.c \ xc_const_string.c \ xc_extension.c \ xc_ini.c \ xc_mutex.c \ xc_opcode_spec.c \ xc_processor.c \ xc_sandbox.c \ xc_shm.c \ xc_shm_mmap.c \ xc_utils.c \ ", "xcache"); ADD_SOURCES(configure_module_dirname + "/mod_cacher", " \ xc_cacher.c \ ", "xcache"); // {{{ add sources on enabled ARG_ENABLE("xcache-optimizer", "(N/A)", "no"); ARG_ENABLE("xcache-coverager", "Code coverage dumper, useful for testing php scripts", "no"); ARG_ENABLE("xcache-assembler", "(N/A)", "no"); ARG_ENABLE("xcache-disassembler", "Opcode to php variable dumper, not for server usage", "no"); ARG_ENABLE("xcache-encoder", "(N/A)", "no"); ARG_ENABLE("xcache-decoder", "(N/A)", "no"); var XCACHE_MODULES = "cacher"; AC_DEFINE("HAVE_XCACHE_CACHER", 1, "Define for XCache: cacher") var options = ["optimizer", "coverager", "assembler", "disassembler", "encoder", "decoder"]; for (var i in options) { var name = options[i]; var uname = name.toUpperCase(); var withval = eval("PHP_XCACHE_" + uname); if (withval != "no") { ADD_SOURCES(configure_module_dirname + "/mod_" + name, "xc_" + name + ".c", "xcache"); XCACHE_MODULES += " " + name; STDOUT.WriteLine("Enabling XCache Module: " + name); AC_DEFINE("HAVE_XCACHE_" + uname, 1, "Define for XCache: " + name) } } AC_DEFINE("XCACHE_MODULES", XCACHE_MODULES); // }}} // {{{ check for programs needed var apps = ["m4", "grep", "sed"]; for (var i in apps) { if (!PATH_PROG(apps[i])) { ERROR(apps[i] + " is currently required to build XCache"); } } DEFINE("XCACHE_BACKTICK", "`") PATH_PROG("gawk", null, "XCACHE_AWK") || PATH_PROG("awk", null, "XCACHE_AWK"); // the cygwin indent is known broken on our output var indent = false; // PATH_PROG("indent"); if (indent) { indent += " -kr --use-tabs --tab-size 4 -sob -nce"; } else { indent = PATH_PROG("cat"); if (!indent) { indent = ''; } } DEFINE("XCACHE_INDENT", indent); // }}} // {{{ check for xcache-test ARG_ENABLE("xcache-test", "XCache: Self test - FOR DEVELOPERS ONLY!!", "no"); if (PHP_XCACHE_TEST != "no") { ADD_FLAG("XCACHE_ENABLE_TEST", "-DXCACHE_ENABLE_TEST"); ADD_SOURCES(configure_module_dirname + "/xcache", "xc_malloc.c", "xcache"); AC_DEFINE("HAVE_XCACHE_TEST", 1, "Define to enable XCache self test"); } else { ADD_FLAG("XCACHE_ENABLE_TEST", ""); } // }}} // {{{ check for xcache-test ARG_ENABLE("xcache-dprint", "XCache: Debug print functions - FOR DEVELOPERS ONLY!!", "no"); if (PHP_XCACHE_DPRINT != "no") { AC_DEFINE("HAVE_XCACHE_DPRINT", 1, "Define to enable XCache debug print functions"); } // }}} // {{{ get ccrule var srcdir = configure_module_dirname; // it's a bit harder to get builddir var mfofile = "Makefile.objects"; MFO.Close(); var mfo = file_get_contents(mfofile); mfo.match(/(.*)\\xcache.obj:/); var builddir = RegExp.$1; mfo.match(/(.*\$\(CC\).* )\/c.*\\xcache.c.*/i); var ccrule = RegExp.$1; MFO = FSO.OpenTextFile(mfofile, 8); mfo = null; // }}} // {{{ add make fragments var makefileFrag = srcdir + "\\Makefile.frag"; var makefileFragDeps = srcdir + "\\Makefile.frag.deps"; STDOUT.WriteLine("Adding Makefile.frag: " + makefileFrag); STDOUT.WriteLine("Adding Makefile.frag.deps: " + makefileFragDeps); var frag = file_get_contents(makefileFrag) + "\r\n" + file_get_contents(makefileFragDeps); frag = frag.replace(/\$\(srcdir\)\//g, srcdir + '\\'); frag = frag.replace(/\$\(srcdir\)/g, srcdir); frag = frag.replace(/\$\(builddir\)\//g, builddir + '\\'); frag = frag.replace(/\$\(builddir\)/g, builddir); frag = frag.replace(/processor\//g, "processor\\"); frag = frag.replace(/\.lo:/g, ".obj:"); frag = frag.replace(/.*\$\(CC\).* -E (.*) -o (.*)/g, ccrule + " /E $1 > $2"); frag = frag.replace(/ -o /g, " /Fo"); frag = frag.replace(/cp /g, "copy "); frag = frag.replace(/mv /g, "move "); frag = frag.replace(/ \|\| /g, "\r\n\tif errorlevel 1 "); frag = frag.replace(/ && /g, "\r\n\tif not errorlevel 1 "); if (indent == '') { frag = frag.replace(/\| *\$\(XCACHE_INDENT\)/g, ''); frag = frag.replace(/\$\(XCACHE_INDENT\) *< */g, 'type '); } MFO.WriteLine(frag); ADD_FLAG("CFLAGS_XCACHE", "/I " + builddir); /// }}} XCACHE_PROC_SOURCES=glob(srcdir + "\\processor\\*.m4").join(' '); ADD_FLAG("XCACHE_PROC_SOURCES", XCACHE_PROC_SOURCES); } xcache-3.1.0/COPYING0000644000175000010010000000274612157744740012225 0ustar mOoNone Copyright (c) 2005-2013, mOo, phpxcache@gmail.com, XCache All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the 'XCache' nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. xcache-3.1.0/devel/0000755000175000010010000000000012225452352012247 5ustar mOoNonexcache-3.1.0/devel/gen_const_string_opcodes.awk0000755000175000010010000000253712157744737020065 0ustar mOoNone#! /usr/bin/awk -f # vim:ts=4:sw=4 # process zend_vm_def.h or zend_compile.h BEGIN { FS=" " max = 0; } /^ZEND_VM_HANDLER\(/ { # regex from php5.1+/Zend/zend_vm_gen.php gsub(/ +/, ""); if (!match($0, /^ZEND_VM_HANDLER\(([0-9]+),([A-Z_]+),([A-Z|]+),([A-Z|]+)\)/)) { print "error unmatch $0"; exit; } # life is hard without 3rd argument of match() sub(/^ZEND_VM_HANDLER\(/, ""); id = $0; sub(/,.*/, "", id); # chop id = 0 + id; sub(/^([0-9]+),/, ""); sub(/,.*/, ""); # chop name = $0; if (max < id) { max = id; } opcodes[id] = name; next; } /^#define +ZEND_[A-Z_]+[\t ]+[[:digit:]]+$/ { id = 0 + $3; name = $2; if (max < id) { max = id; } opcodes[id] = name; next; } /end of block/ { exit; } END { mymax = 112; if (max < mymax) { for (i = max + 1; i <= mymax; i ++) { opcodes[i] = "UNDEF"; } max = mymax; opcodes[110] = "ZEND_DO_FCALL_BY_FUNC"; opcodes[111] = "ZEND_INIT_FCALL_BY_FUNC"; opcodes[112] = "UNDEF"; } printf "/* size = %d */\n", max + 1; print "static const char *const xc_opcode_names[] = {"; for (i = 0; i <= max; i ++) { if (i != 0) { print ","; } printf "/* %d */\t", i if (i in opcodes) { name = opcodes[i]; sub(/^ZEND_/, "", name); printf "\"%s\"", name; } else if (i == 137) { printf "\"%s\"", "OP_DATA"; } else { printf "\"UNDEF\""; } } print ""; print "};"; } xcache-3.1.0/devel/gen_xc_opcode_spec.awk0000755000175000010010000000135112157744737016603 0ustar mOoNone#! /usr/bin/awk -f # vim:ts=4:sw=4 # process eaccelerator/opcodes.c BEGIN { FS=" " max = 0; started = 0 } /OPDEF/ { if (started) { name = ""; if (match($0, /"([^"]+)"/, m)) { name = m[1]; } sub(/"[^"]*"/, ""); if (!match($0, /EXT_([^ |]+).*OP[1S]_([^ |]+).*OP2_([^ |]+).*RES_([^ |)]+).*/, array)) { print "error" $0 exit } id = ""; if (match($0, /\/\* *([0-9]+) *\*\//, comments)) { id = comments[1]; } printf "\tOPSPEC(%10s, %10s, %10s, %10s) /* %s %-30s */\n", array[1], array[2], array[3], array[4], id, name; next } } /^}/ { print $0 exit; } /^[ ]*,[ ]*$/ { next } { if (started) { print $0 next } } /^static/ { started = 1; print "static const xc_opcode_spec_t xc_opcode_spec[] = {" } xcache-3.1.0/devel/graph/0000755000175000010010000000000012157744737013367 5ustar mOoNonexcache-3.1.0/devel/graph/cached_compile.dot0000644000175000010010000000131612157744737017017 0ustar mOoNonedigraph tree { subgraph cluster_compiling { label="compiling"; php_compile; php_store; entry_store; } error [color=red]; origin_compile [color=red] begin -> origin_compile [label="compiling", color=red]; begin -> entry_init_key -> entry_lookup; edge [label=hit, color=blue] entry_lookup -> restore; php_lookup -> entry_store; edge [label=miss, color=green] entry_lookup -> md5_init; md5_init -> php_lookup; php_lookup -> php_compile; edge [label="", color=""] php_lookup -> origin_compile [label="miss but compiling", color=red]; php_compile -> php_store -> entry_store -> restore; edge [color=red]; md5_init -> error; php_compile -> error; php_store -> error; entry_store -> error; } xcache-3.1.0/devel/lsnewini0000755000175000010010000000036412157744737014047 0ustar mOoNone#!/bin/sh tmp1=`mktemp` tmp2=`mktemp` grep -F '=' xcache.ini |grep -v '^;' | sed -r -e 's# *=.*##' | sort > $tmp2 grep 'PHP_INI.*("' *.c | sed -r -e 's#^[^"]*"([^"]*)".*#\1#' | sort > $tmp1 diff -iu $tmp2 $tmp1 |grep '^[-+]' rm -f $tmp1 $tmp2 xcache-3.1.0/devel/make0000755000175000010010000000004112157744737013124 0ustar mOoNone#!/bin/bash exec ./run make "$@" xcache-3.1.0/devel/po2php.awk0000755000175000010010000000157712157744737014217 0ustar mOoNone#!/usr/bin/awk -f BEGIN { print " \""msgstr"\","; } } else { print "unexpected section " section; exit 1; } section = null; } } /^msgid ".*"$/ { $0 = gensub(/^msgid "(.*)"$/, "\\1", $0); section = "msgid"; msgid = $0; next; } /^msgstr ".*"$/ { $0 = gensub(/^msgstr "(.*)"$/, "\\1", $0); section = "msgstr"; msgstr = $0; next; } /^".*"$/ { $0 = gensub(/^"(.*)"$/, "\\1", $0); if (section == "msgid") { msgid = msgid $0; } else { msgstr = msgstr $0; } next; } /^$/ { flushOut(); next; } /^#/ { next; } /./ { print "error", $0; exit 1; } END { flushOut(); print "\t\t);"; print ""; } xcache-3.1.0/devel/prepare.cfg.example0000644000175000010010000000030012206607316016012 0ustar mOoNone# copy this file as prepare.cfg before modifying PHP4_x_DIR= PHP5_0_DIR= PHP5_1_DIR= PHP5_3_DIR= PHP5_4_DIR= PHP5_5_DIR= PHP6_x_DIR= PHP_DEVEL_DIR= # path to eaccelerator source dir EA_DIR= xcache-3.1.0/devel/prepare.mak0000644000175000010010000001071512206607316014404 0ustar mOoNoneCTAGS=$(shell which ctags 2>/dev/null || which exuberant-ctags 2>/dev/null) AWK=$(shell which gawk 2>/dev/null || which awk 2>/dev/null) include devel/prepare.cfg .PHONY: dummy .PHONY: all all: xcache/xc_opcode_spec_def.h xc_const_string tags po .PHONY: clean clean: clean_xc_const_string clean_po rm -f tags xcache/xc_opcode_spec_def.h .PHONY: clean_xc_const_string clean_xc_const_string: rm -f xcache/xc_const_string_opcodes_php*.h .PHONY: xc_const_string xc_const_string: \ xcache/xc_const_string_opcodes_php4.x.h \ xcache/xc_const_string_opcodes_php5.0.h \ xcache/xc_const_string_opcodes_php5.1.h \ xcache/xc_const_string_opcodes_php5.2.h \ xcache/xc_const_string_opcodes_php5.3.h \ xcache/xc_const_string_opcodes_php5.4.h \ xcache/xc_const_string_opcodes_php5.5.h \ xcache/xc_const_string_opcodes_php6.x.h ifeq (${EA_DIR},) xcache/xc_opcode_spec_def.h: dummy @echo "Skipped $@: EA_DIR not set" else xcache/xc_opcode_spec_def.h: ${EA_DIR}/opcodes.c $(AWK) -f ./devel/gen_xc_opcode_spec.awk < "$<" > "$@".tmp mv "$@".tmp "$@" endif ifeq (${PHP4_x_DIR},) xcache/xc_const_string_opcodes_php4.x.h: dummy @echo "Skipped $@: PHP_4_x_DIR not set" else xcache/xc_const_string_opcodes_php4.x.h: ${PHP4_x_DIR}/Zend/zend_compile.h $(AWK) -f ./devel/gen_const_string_opcodes.awk < "$<" > "$@.tmp" mv "$@.tmp" "$@" endif ifeq (${PHP5_0_DIR},) xcache/xc_const_string_opcodes_php5.0.h: dummy @echo "Skipped $@: PHP_5_0_DIR not set" else xcache/xc_const_string_opcodes_php5.0.h: ${PHP5_0_DIR}/Zend/zend_compile.h $(AWK) -f ./devel/gen_const_string_opcodes.awk < "$<" > "$@.tmp" mv "$@.tmp" "$@" endif ifeq (${PHP5_1_DIR},) xcache/xc_const_string_opcodes_php5.1.h: dummy @echo "Skipped $@: PHP_5_1_DIR not set" else xcache/xc_const_string_opcodes_php5.1.h: ${PHP5_1_DIR}/Zend/zend_vm_def.h $(AWK) -f ./devel/gen_const_string_opcodes.awk < "$<" > "$@.tmp" mv "$@.tmp" "$@" endif ifeq (${PHP5_2_DIR},) xcache/xc_const_string_opcodes_php5.2.h: dummy @echo "Skipped $@: PHP_5_2_DIR not set" else xcache/xc_const_string_opcodes_php5.2.h: ${PHP5_2_DIR}/Zend/zend_vm_def.h $(AWK) -f ./devel/gen_const_string_opcodes.awk < "$<" > "$@.tmp" mv "$@.tmp" "$@" endif ifeq (${PHP5_3_DIR},) xcache/xc_const_string_opcodes_php5.3.h: dummy @echo "Skipped $@: PHP_5_3_DIR not set" else xcache/xc_const_string_opcodes_php5.3.h: ${PHP5_3_DIR}/Zend/zend_vm_def.h $(AWK) -f ./devel/gen_const_string_opcodes.awk < "$<" > "$@.tmp" mv "$@.tmp" "$@" endif ifeq (${PHP5_4_DIR},) xcache/xc_const_string_opcodes_php5.4.h: dummy @echo "Skipped $@: PHP_5_4_DIR not set" else xcache/xc_const_string_opcodes_php5.4.h: ${PHP5_4_DIR}/Zend/zend_vm_def.h $(AWK) -f ./devel/gen_const_string_opcodes.awk < "$<" > "$@.tmp" mv "$@.tmp" "$@" endif ifeq (${PHP5_5_DIR},) xcache/xc_const_string_opcodes_php5.5.h: dummy @echo "Skipped $@: PHP_5_5_DIR not set" else xcache/xc_const_string_opcodes_php5.5.h: ${PHP5_5_DIR}/Zend/zend_vm_def.h $(AWK) -f ./devel/gen_const_string_opcodes.awk < "$<" > "$@.tmp" mv "$@.tmp" "$@" endif ifeq (${PHP6_x_DIR},) xcache/xc_const_string_opcodes_php6.x.h: dummy @echo "Skipped $@: PHP_6_x_DIR not set" else xcache/xc_const_string_opcodes_php6.x.h: ${PHP6_x_DIR}/Zend/zend_vm_def.h $(AWK) -f ./devel/gen_const_string_opcodes.awk < "$<" > "$@.tmp" mv "$@.tmp" "$@" endif ifeq (${PHP_DEVEL_DIR},) tags: @echo "* Making tags without php source files" "$(CTAGS)" -R . else tags: @echo "* Making tags with ${PHP_DEVEL_DIR}" "$(CTAGS)" -R . "${PHP_DEVEL_DIR}/main" "${PHP_DEVEL_DIR}/Zend" "${PHP_DEVEL_DIR}/TSRM" "${PHP_DEVEL_DIR}/ext/standard" endif .PHONY: po define htdocspo po: \ htdocs/$(1)/lang/en.po \ htdocs/$(1)/lang/en.po-merged \ htdocs/$(1)/lang/zh-simplified.po-merged \ htdocs/$(1)/lang/zh-simplified.po \ htdocs/$(1)/lang/zh-traditional.po \ htdocs/$(1)/lang/zh-traditional.po-merged htdocs/$(1)/lang/%.po-merged: htdocs/$(1)/lang/%.po htdocs/$(1)/lang/$(1).pot msgmerge -o "$$@".tmp $$^ mv "$$@".tmp "$$@" htdocs/$(1)/lang/%.po: touch "$$@" htdocs/$(1)/lang/$(1).pot: xgettext --keyword=_T --keyword=N_ --from-code=UTF-8 -F -D htdocs/$(1)/ $$(subst htdocs/$(1)/,,$$^) -o "$$@".tmp mv "$$@".tmp "$$@" htdocs/$(1)/lang/$(1).pot: $(shell find htdocs/$(1) -type f | grep php | grep -v lang | grep -v config | grep -vF .swp) endef $(eval $(call htdocspo,cacher)) $(eval $(call htdocspo,common)) $(eval $(call htdocspo,coverager)) $(eval $(call htdocspo,diagnosis)) .PHONY: clean_po clean_po: clean_pot rm -f htdocs/*/lang/*.po-merged .PHONY: clean_pot clean_pot: rm -f htdocs/*/lang/*.pot xcache-3.1.0/devel/run0000755000175000010010000001766112225452352013014 0ustar mOoNone#!/bin/bash # this script is for developers only set -e MAKE=/usr/bin/make true() { # {{{1 return 0 } hi() { # {{{1 colors=(4 2 3 5 6 7 8 9) re=() i=0 for r in "$@"; do ((color=$i % ${#colors[@]})) || true color=${colors[$color]} r="${r/\#/\\#}" r="s#$r#[4${color}m\0#g" re[$i]="-e$r" ((i=i+1)) done sed -ur "${re[@]}" } hiecho() { # {{{1 echo """$@""" } # }}} stopfpm() { # {{{1 if [[ -f $1 ]]; then local pid=`cat $1 2>/dev/null || true` if [[ $pid -gt 0 ]]; then hiecho Stopping fpm $pid @ $1 kill $pid || true fi fi } xtest() { # {{{1 $MAKE ${MAKEOPTS} -f devel/test.mak } prep() { # {{{1 $MAKE ${MAKEOPTS} -f devel/prepare.mak "$@" } mergepo() { # {{{1 prep local i find htdocs -iname '*.po' | while read -r i; do if [[ -f $i-merged ]]; then mv $i-merged $i fi done } po2php() { # {{{1 mergepo local phpfile find htdocs -iname '*.po' | while read -r i; do phpfile=${i/.po/.php} devel/po2php.awk < $i > $phpfile.tmp mv $phpfile.tmp $phpfile done } updatedeps() { # {{{1 pwd=$(readlink -f "$(pwd)") builddir=$(readlink -f ../trunk-php5-debug-zts) if [[ -z $builddir ]]; then hiecho required ../trunk-php5-debug-zts not found return 1 fi find . -iname \*.c | LANG=C sort | while read -r sourceFile; do sourceFile=${sourceFile#./} { case "$sourceFile" in includes.c) echo '$(XCACHE_INCLUDES_I)' ;; esac echo ${sourceFile%.c}.lo '$(builddir)/'${sourceFile%.c}.lo: hiecho "Checking $sourceFile ..." >&2 for dependency in $(gcc -DHAVE_XCACHE_TEST -DHAVE_XCACHE_DPRINT -DXCACHE_DEBUG -MM $sourceFile -I$PHPSDIR/$phpbasename/include/php/{,main,Zend,TSRM} -I. -I${builddir} -MG | sed 's#.*:##g' | sed 's#\\##g'); do dependency=$(readlink -f "$dependency") case "$dependency" in $pwd/*) dependency=${dependency#$pwd/} ;; $builddir/*) dependency="\$(builddir)/"${dependency#$builddir/} ;; esac case "$dependency" in *xc_const_string_opcodes_php*) for dependency in xcache/xc_const_string_*.h; do echo '$(srcdir)/'$dependency done ;; /*) ;; $sourceFile) ;; xc_processor.h|\$\(builddir\)/xc_processor.h) echo '$(XCACHE_PROC_H)' ;; xc_processor.c.h|\$\(builddir\)/xc_processor.c.h) echo '$(XCACHE_PROC_C)' ;; *) if [[ -r $dependency ]]; then echo '$(srcdir)/'$dependency else hiecho "$dependency not found" >&2 fi esac done | LANG=C sort | uniq } | xargs done > Makefile.frag.deps } # }}}1 hiecho "Loading config devel/run.cfg" . devel/run.cfg PHPSDIR=${PHPSDIR:-$HOME/test} if [[ $# -eq 0 ]]; then set -- $action "${args[@]}" fi basename=$(basename $(pwd)) case "$basename" in *-*) # in build dir, starts from src dir dirs="${basename#*-}" xcachesrcdir=../${basename%%-*} cd $xcachesrcdir ;; *) # in src dir dirs=${dirs:-php5-debug-zts} xcachesrcdir=../$basename ;; esac touch devel.pid svn propget svn:ignore . > .svnignore # ========================== do_phpize() { # {{{1 if [[ ! -x $PHPSDIR/$phpbasename/bin/phpize ]]; then hiecho $PHPSDIR/$phpbasename/bin/phpize not found exit fi export PATH=$PHPSDIR/$phpbasename/bin:$PATH local pedantic= case $phpbasename in php5|php5.4) pedantic=-pedantic-errors;; *) pedantic=-pedantic;; esac phpize --clean \ && phpize \ && CFLAGS="$CFLAGS -g -O0 $pedantic -Wno-variadic-macros -Wno-long-long -Wall -Wno-unused-parameter -Wno-unused-function -W -Wshadow -Werror=implicit-function-declaration -std=c89 -D_GNU_SOURCE -D_POSIX_SOURCE -Dinline=" ./configure \ --enable-xcache-cacher \ --enable-xcache-optimizer \ --enable-xcache-encoder \ --enable-xcache-decoder \ --enable-xcache-disassembler \ --enable-xcache-assembler \ --enable-xcache-coverager \ --enable-xcache-test \ --enable-xcache-dprint \ --enable-xcache-constant } do_make() { # {{{1 if [[ ! -f Makefile ]]; then do_phpize fi LANG=C $MAKE $MAKEOPTS "$@" 2>&1 \ | sed -ur \ -e 's#Werror=implicit-function-declaration#We/rror=i/mplicit-function-declaration#' \ -e 's#-pedantic-errors#-pedantic-e/rrors#' \ -e 's#\./xc_processor\.h#'$PWD'/xc_processor.h#' \ -e 's#\./xc_processor\.c\.h#'$PWD'/xc_processor.c.h#' \ | hi error implicit warn FAIL ret=${PIPESTATUS[0]} if [[ $ret -ne 0 ]]; then exit $ret fi } cleanfpm() { # {{{1 echo stopfpm $pidfile } # }}} run() { pidfile=$xcachesrcdir/devel.pid # prepare {{{1 case "$1" in phpize) if [[ -r Makefile ]]; then $MAKE $MAKEOPTS xcachesvnclean || true fi ;; esac rm -f php-src find -L . -type d -print0 | xargs -0 rmdir -p 2>/dev/null || true find -L . -type l -print0 | xargs -0 rm -fv lndir "$xcachesrcdir" >/dev/null || true find . -iname .\*.swp -print0 | xargs -0 rm -f ln -snf ~/src/php/${phpbasename%%-*} php-src for i in ~/src/php/$phpbasename/sapi/cgi/php{,-cgi}; do if [[ -r $i ]]; then ln -snf "$i" php-cgi fi done ln -snf ~/src/php/$phpbasename/sapi/cli/php php-cli f=~/src/php/$phpbasename/sapi/cli/php; [ -f "$f" ] && ln -snf "$f" php-cli f=~/src/php/$phpbasename/sapi/fpm/php-fpm; [ -f "$f" ] && ln -snf "$f" php-fpm case "$1" in phpize) do_phpize; return $?;; make) shift; do_make "$@"; return $?;; *) do_make;; esac # }}}1 if [[ -z $1 ]]; then set -- devel.php fi cmd=() tracer=() # run utils {{{1 case "$1" in dc) shift case "$1" in *.cpp.php) < "$1" \ sed -r -e 's#__#____#g' \ | cpp -C -P -traditional-cpp -DPHP_VERSION=$phpVersion \ | sed -r -e 's#^ +##g' -e 's#\t +#\t#g' -e 's#____#__#g' > sample.php || exit $? shift ./php-cli -c devel.ini ./bin/phpdc.phpr sample.php "$@" | tee decompiled.php ;; *) ./php-cli -c devel.ini ./bin/phpdc.phpr "$@" | tee decompiled.php ;; esac return ;; retest) shift lastResult=$(ls php_test_results_*.txt | LANG=C sort | tail -n1) $MAKE $MAKEOPTS xcachetest "$@" TESTS="$(grep '^/.*\.phpt$' $lastResult | uniq | xargs)" return ;; test) shift case "$1" in *.phpt) $MAKE $MAKEOPTS xcachetest TEST_ARGS=-v TESTS="$*" return ;; */) $MAKE $MAKEOPTS xcachetest TESTS="$*" return ;; *) $MAKE $MAKEOPTS xcachetest return ;; esac ;; esac # }}} # pick tracer {{{1 case "$1" in ltr*) shift export USE_ZEND_ALLOC=0 tracer=(ltrace -s1024 -e malloc,realloc,free,write) ;; str*) shift tracer=(strace -s1024 -T) ;; gdb) shift #USE_ZEND_ALLOC=0 tracer=(gdb --args) ;; val*) shift export USE_ZEND_ALLOC=0 export ZEND_DONT_UNLOAD_MODULES=1 tracer=(valgrind -v --gen-suppressions=all) ;; esac # pick sapi {{{1 case "$phpbasename" in *-apache1*) cmd=($HOME/apache1/bin/httpd -X) ;; *-apache*) echo "Don't know how to run apache" exit 1 ;; *) case "$1" in dop) shift cmd=(./php-cli -c devel.ini) set -- ./bin/phpdop.phpr "$@" ;; fcgi) shift cmd=(./php-cgi -q -c devel.ini) set -- -b 1026 ;; fpm) shift cmd=(./php-fpm -c devel.ini -y devel.fpm -g $(readlink -f $pidfile)) set -- ;; *) cmd=(./php-cgi -q -c devel.ini) ;; esac "${cmd[@]}" -v || true esac # run {{{1 commandLine=("${tracer[@]}" "${cmd[@]}" "$@") case "${cmd[0]}" in *php-fpm*) stopfpm hiecho Starting fpm "${commandLine[@]}" ... "${commandLine[@]}" echo -n "Ctrl-C to stop" trap cleanfpm SIGINT SIGTERM exit cat > /dev/null || true stopfpm ;; *) hiecho "${commandLine[@]}" "${commandLine[@]}" ;; esac # }}} } for phpbasename in "${dirs[@]}"; do phpVersion=${phpbasename%%-*} phpVersion=${phpVersion##php} phpVersion=${phpVersion/./} case "$phpVersion" in ??) phpVersion="${phpVersion}0";; ?) phpVersion="${phpVersion}00";; esac # devel actions case "$1" in prep*) shift; prep "$@"; exit;; tags) shift; rm -f tags; prep tags "$@"; exit;; po2php) po2php; exit;; mergepo) mergepo; exit;; dep*) updatedeps; exit;; xtest) xtest; exit;; stopfpm) stopfpm devel.pid; exit;; esac mkdir -p ${xcachesrcdir}-${phpbasename} cd ${xcachesrcdir}-${phpbasename} || exit lndir ${xcachesrcdir} >/dev/null || true pwd run "$@" done xcache-3.1.0/devel/test.mak0000755000175000010010000000076012157744740013737 0ustar mOoNone#! /usr/bin/make -f EXES=allocator_test OBJS=allocator.o CC=gcc CFLAGS=-g -O0 -I. -D TEST -D HAVE_XCACHE_TEST -Wall TEST=valgrind all: allocator allocator_test: xcache/xc_allocator.h xcache/xc_allocator.c xcache/xc_malloc.c xcache/xc_allocator_bestfit.c util/xc_trace.c util/xc_trace.h $(CC) $(CFLAGS) -o allocator_test xcache/xc_allocator.c xcache/xc_malloc.c xcache/xc_allocator_bestfit.c util/xc_trace.c allocator: allocator_test $(TEST) ./allocator_test clean: rm -f $(OBJS) $(EXES) xcache-3.1.0/gen_structinfo.awk0000755000175000010010000000741612157744740014731 0ustar mOoNone#! /usr/bin/awk -f # vim:ts=4:sw=4 BEGIN { brace = 0; incomment = 0; buffer_len = 0; } function printstruct(structname) { printf "define(`ELEMENTSOF_%s', `%s')\n", structname, ELEMENTSOF[structname]; printf "define(`COUNTOF_%s', `%s')\n", structname, COUNTOF[structname]; printf "define(`SIZEOF_%s', `( %s )')\n", structname, SIZEOF[structname]; } function countBrace(text, len, i, char, braceCount) { len = length(text); braceCount = 0; for (i = 1; i <= len; ++i) { char = substr(text, i, 1); if (char == "{") { braceCount = braceCount + 1; } else if (char == "}") { braceCount = braceCount - 1; } } return braceCount; } # multiline comment handling { # removes one line comment gsub(/\/\*(.+?)\*\//, " "); } /\*\// { if (incomment) { sub(/.*\*\//, ""); incomment = 0; } } incomment { next; } /\/\*/ { sub(/\/\*.*/, ""); incomment = 1; # fall through } # skip file/line mark here to be faster /^#/ { next; } /^}.*;/ { if (instruct) { sub(";", ""); structname = instruct; if (structname == 1 && $2) { structname = $2; } if (structname in typedefs) { structname = typedefs[structname]; } sizeinfo = ""; elms = ""; for (i = 0; i in buffer; i ++) { if (i) { sizeinfo = sizeinfo " + "; } sizeinfo = sizeinfo "sizeof(((" structname "*)NULL)->" buffer[i] ")"; if (i == 0) { elms = "\"" buffer[i] "\""; } else { elms = elms "," "\"" buffer[i] "\""; } } ELEMENTSOF[structname] = elms; COUNTOF[structname] = i; SIZEOF[structname] = sizeinfo; printstruct(structname); print "\n"; for (i in buffer) { delete buffer[i]; } buffer_len = 0; instruct = 0; } next; } /.[{}]/ { brace += countBrace($0); } { if (brace == 1 && instruct) { gsub(/(^[\t ]+|[\t ]+$)/, ""); # trim whitespaces sub(/.*[{}]/, ""); gsub(/\[[^\]]+\]/, ""); # ignore [...] gsub(/:[0-9]+/, ""); # ignore struct bit if (match($0, /^[^(]*\([ ]*\*([^)]+)\)/)) { sub(/ +/, "") sub(/^[^(]*\(\*/, ""); sub(/\).*/, ""); # function pointer buffer[buffer_len] = $0; buffer_len ++; } else { # process normal variables # ignore any ()s while (gsub(/(\([^)]*\))/, "")) { } if (match($0, /[()]/)) { next; } # unsigned int *a, b; int c; gsub(/[*]/, " "); # unsigned int a, b; int c; gsub(/ +/, " "); # unsigned int a, b; int c; gsub(/ *[,;]/, ";"); # unsigned int a; b; int c; if (!match($0, /;/)) { next; } # print "=DEBUG=" $0 "=="; split($0, chunks, ";"); # [unsigned int a, b, c] for (i = 1; i in chunks; i ++) { if (chunks[i] == "") { delete chunks[i]; continue; } split(chunks[i], pieces, " "); # [unsigned, int, a] # [b] # [c] last_piece = ""; for (j = 1; j in pieces; j ++) { last_piece = pieces[j]; delete pieces[j]; } if (last_piece == "") { # print "=ERROR=" chunks[i] "=="; delete chunks[i]; continue; } # a # b # c buffer[buffer_len] = last_piece; buffer_len ++; delete chunks[i] } last_piece = ""; } next; } } /^typedef struct [^{]*;/ { sub(";", ""); typename=$3; newtypename=$4; typedefs[typename] = newtypename; if (ELEMENTSOF[typename]) { ELEMENTSOF[newtypename] = ELEMENTSOF[typename]; COUNTOF[newtypename] = COUNTOF[typename]; sub(/.*/, SIZEOF[typename]); gsub(typename, newtypename); SIZEOF[newtypename] = $0; printstruct(newtypename); } next; } /^typedef struct .*\{[^}]*$/ { brace = countBrace($0); if (brace > 0) { instruct = 1; } else { brace = 0; instruct = 0; } for (i in buffer) { delete buffer[i]; } next; } /^struct .*\{.*/ { brace = countBrace($0); if (brace > 0) { instruct = $2; } else { brace = 0; instruct = 0; } for (i in buffer) { delete buffer[i]; } next; } xcache-3.1.0/htdocs/0000755000175000010010000000000012157744742012447 5ustar mOoNonexcache-3.1.0/htdocs/cacher/0000755000175000010010000000000012220455230013652 5ustar mOoNonexcache-3.1.0/htdocs/cacher/cacher.css0000644000175000010010000000226512157744742015640 0ustar mOoNonetd, th { white-space: pre; } .percent { height: 3px; margin-bottom: 1px; border: 1px solid gray; } .percent div { float: left; height: 100%; } .pvalue { background: limegreen; } .blocksgraph { height: 13px; } .blocksgraph div { float: left; height: 3px; width: 4px; border: 0 solid gray; border-width: 0 0 1px 0; } .blocksgraph { border: 1px solid gray; border-bottom: 0; } .percent *, .blocksgraph *, .hitsgraph * { font-size: 1px; line-height: 1px; } .hitsgraph { margin: auto; } .hitsgraph a { display: block; float: left; border: 0 solid gray; } .hitsgraph a { width: 2px; height: 20px; border-top-width: 1px; border-bottom-width: 1px; } /* update this along with index.php */ .hitsgraph a * { display: block; } .hitsgraph a.active { border-top-color: yellow; } .hitsgraph a:hover { background: gray; } dl { overflow: hidden; } dt { font-weight: bold; clear: both; float: left; width: 100px; text-align: right; margin: 0; } dd { margin: 0; } .blockarea { overflow: hidden; width: 400px; } .legends { padding-bottom: 8px; } div.legend { float: left; border: 1px solid gray; font: 12px/12px monospace; } div.legendtitle { float: left; padding: 2px; padding-right: 10px; font: 12px/12px monospace; } xcache-3.1.0/htdocs/cacher/common.php0000644000175000010010000000014712157744742015677 0ustar mOoNone xcache-3.1.0/htdocs/cacher/edit.tpl.php0000644000175000010010000000127212157744742016132 0ustar mOoNone

>
xcache-3.1.0/htdocs/cacher/index.php0000644000175000010010000001634312157744742015523 0ustar mOoNone $v) { if ($config['percent_graph_type'] != 'free') { $v = 1 - $v; } $v = (int) ($v * $c); $r = $g = $c - $v; $b = $c; $html[] = '
'; } return implode('', $html); } // }}} function calc_total(&$total, $data) // {{{ { foreach ($data as $k => $v) { switch ($k) { case 'type': case 'cache_name': case 'cacheid': case 'free_blocks': continue 2; } if (!isset($total[$k])) { $total[$k] = $v; } else { switch ($k) { case 'hits_by_hour': case 'hits_by_second': foreach ($data[$k] as $kk => $vv) { $total[$k][$kk] += $vv; } break; default: $total[$k] += $v; } } } } // }}} function array_avg($a) // {{{ { if (count($a) == 0) { return ''; } return array_sum($a) / count($a); } // }}} function bar_hits_percent($v, $percent, $active) // {{{ { $r = 220 + (int) ($percent * 25); $g = $b = 220 - (int) ($percent * 220); $percent = (int) ($percent * 100); $a = $active ? ' class="active"' : ''; $height = 20 - 1 * 2; $valueHeight = ceil($height * $percent / 100); $paddingHeight = $height - $valueHeight; $valueHeight = $valueHeight ? $valueHeight . "px" : 0; $paddingHeight = $paddingHeight ? $paddingHeight . "px" : 0; return '' . ($paddingHeight ? '' : '') . ($valueHeight ? '' : '') . ''; } // }}} function get_cache_hits_graph($ci, $key) // {{{ { global $maxHitsByHour; if ($ci['cacheid'] == -1) { $max = max($ci[$key]); } else { $max = $maxHitsByHour[$ci['type']]; } if (!$max) { $max = 1; } $t = (time() / (60 * 60)) % 24; $html = array(); $width = count($ci[$key]) * 2; $html[] = '
'; foreach ($ci[$key] as $i => $v) { $html[] = bar_hits_percent($v, $v / $max, $i == $t); } $html[] = "
"; return implode('', $html); } // }}} function getModuleInfo() // {{{ { ob_start(); phpinfo(INFO_MODULES); $moduleInfo = ob_get_clean(); if (!preg_match_all('!(XCache[^<>]*)(.*?)

!is', $moduleInfo, $m)) { return; } $moduleInfo = array(); foreach ($m[1] as $i => $dummy) { $caption = trim($m[1][$i]); $info = str_replace('
', '', trim($m[2][$i])); $regex = '!]*>!'; if (preg_match($regex, $info)) { $moduleInfo[] = preg_replace($regex, "\\0$caption", $info, 1); } else { $moduleInfo[] = "

$caption

"; $moduleInfo[] = $info; } } $moduleInfo = implode('', $moduleInfo); if (ini_get("xcache.test")) { ob_start(); include "./sub/testcoredump.tpl.php"; $test_coredump = trim(ob_get_clean()); $moduleInfo = str_replace('xcache.coredump_directory', 'xcache.coredump_directory' . $test_coredump, $moduleInfo); } return $moduleInfo; } // }}} function getCacheInfos() // {{{ { static $cacheInfos; if (isset($cacheInfos)) { return $cacheInfos; } $phpCacheCount = xcache_count(XC_TYPE_PHP); $varCacheCount = xcache_count(XC_TYPE_VAR); $cacheInfos = array(); $total = array(); global $maxHitsByHour; $maxHitsByHour = array(0, 0); for ($i = 0; $i < $phpCacheCount; $i ++) { $data = xcache_info(XC_TYPE_PHP, $i); if ($_GET['do'] === 'listphp') { $data += xcache_list(XC_TYPE_PHP, $i); } $data['type'] = XC_TYPE_PHP; $data['cache_name'] = "php#$i"; $data['cacheid'] = $i; $cacheInfos[] = $data; $maxHitsByHour[XC_TYPE_PHP] = max($maxHitsByHour[XC_TYPE_PHP], max($data['hits_by_hour'])); if ($phpCacheCount >= 2) { calc_total($total, $data); } } if ($phpCacheCount >= 2) { $total['type'] = XC_TYPE_PHP; $total['cache_name'] = _T('Total'); $total['cacheid'] = -1; $total['gc'] = null; $total['istotal'] = true; unset($total['compiling']); $cacheInfos[] = $total; } $total = array(); for ($i = 0; $i < $varCacheCount; $i ++) { $data = xcache_info(XC_TYPE_VAR, $i); if ($_GET['do'] === 'listvar') { $data += xcache_list(XC_TYPE_VAR, $i); } $data['type'] = XC_TYPE_VAR; $data['cache_name'] = "var#$i"; $data['cacheid'] = $i; $cacheInfos[] = $data; $maxHitsByHour[XC_TYPE_VAR] = max($maxHitsByHour[XC_TYPE_VAR], max($data['hits_by_hour'])); if ($varCacheCount >= 2) { calc_total($total, $data); } } if ($varCacheCount >= 2) { $total['type'] = XC_TYPE_VAR; $total['cache_name'] = _T('Total'); $total['cacheid'] = -1; $total['gc'] = null; $total['istotal'] = true; $cacheInfos[] = $total; } return $cacheInfos; } // }}} function getEntryList() // {{{ { static $entryList; if (isset($entryList)) { return $entryList; } $entryList = array('cache_list' => array(), 'deleted_list' => array()); if ($_GET['do'] == 'listphp') { $entryList['type'] = XC_TYPE_PHP; } else { $entryList['type'] = XC_TYPE_VAR; } foreach (getCacheInfos() as $i => $c) { if (!empty($c['istotal'])) { continue; } if ($c['type'] == $entryList['type'] && isset($c['cache_list'])) { foreach ($c['cache_list'] as $e) { $e['cache_name'] = $c['cache_name']; $entryList['cache_list'][] = $e; } foreach ($c['deleted_list'] as $e) { $e['cache_name'] = $c['cache_name']; $entryList['deleted_list'][] = $e; } } } return $entryList; } // }}} if (!extension_loaded('XCache')) { header("Location: ../diagnosis"); exit; } xcache_count(XC_TYPE_PHP); // trigger auth xcache_admin_namespace(); $doTypes = array( '' => _T('Summary'), 'listphp' => _T('List PHP'), 'listvar' => _T('List Var Data'), ); function processPOST() // {{{ { if (isset($_POST['remove']) && is_array($_POST['remove'])) { foreach ($_POST['remove'] as $name) { if (is_string($name)) { xcache_unset($name); } } } $type = isset($_POST['type']) ? $_POST['type'] : null; if ($type != XC_TYPE_PHP && $type != XC_TYPE_VAR) { $type = null; } if (isset($type)) { $cacheid = (int) (isset($_POST['cacheid']) ? $_POST['cacheid'] : 0); if (isset($_POST['clearcache'])) { xcache_clear_cache($type, $cacheid); } if (isset($_POST['enable'])) { xcache_enable_cache($type, $cacheid); } if (isset($_POST['disable'])) { xcache_enable_cache($type, $cacheid, false); } } if (isset($_POST['coredump'])) { xcache_coredump(); } } // }}} processPOST(); if (!isset($_GET['do'])) { $_GET['do'] = ''; } switch ($_GET['do']) { case 'listphp': case 'listvar': include "./listentries.tpl.php"; break; default: include "./summary.tpl.php"; break; } ?> xcache-3.1.0/htdocs/cacher/lang/0000755000175000010010000000000012206607315014602 5ustar mOoNonexcache-3.1.0/htdocs/cacher/lang/en.php0000644000175000010010000000624212157744742015734 0ustar mOoNone "PHP Cached", "var Cached" => "Variable Cached", "php Deleted" => "PHP Deleted", "var Deleted" => "Variable Deleted", "entry.id" => "Id|", "entry.remove" => "Remove|", "entry.name" => "Entry name|The entry name or filename", "entry.hits" => "Hits|Hit times of this entry (loaded from this cache)", "entry.size" => "Size|Size in bytes of this entry in the cache", "entry.refcount" => "Refs|Reference count of this entry is holded by a php request", "entry.phprefcount" => "Shares|Count of entry sharing this php data", "entry.class_cnt" => "Cls.|Count of classes", "entry.function_cnt" => "Funcs|Count of functions", "entry.file_size" => "Src Size|Size of the source file", "entry.file_mtime" => "Modified|Last modified time of the source file", "entry.file_device" => "dev|device number of the source file", "entry.file_inode" => "ino|inode number of the source file", "entry.hash" => "Hash|Hash value of this entry", "entry.atime" => "Access|Last time when this entry is accessed", "entry.ctime" => "Create|The time when this entry is stored", "entry.delete" => "Delete|The time when this entry is deleted", "Caches" => "Caches", "cache.cache" => "Cache|", "cache.slots" => "Slots|Number of hash slots. the setting from your php.ini", "cache.size" => "Size|Cache Size, Size of the cache (or cache chunk), in bytes", "cache.avail" => "Avail|Available Memory, free memory in bytes of this cache", "cache.blocksgraph" => "Percent Graph|Shows how much memory available in percent, and memory blocks status in graph", "cache.operations" => "Operations|Press the clear button to clean this cache", "cache.status" => "Status|Compiling flag, \"Compiling\" if the cache is busy compiling php script. \"Disabled\" if cache is disabled", "cache.hits" => "Hits|Cache Hits, hit=a var/php is loaded from this cache", "cache.hits_graph" => "Hits*24H|Hits graph of last 24 hours", "cache.hits_avg_h" => "Hits/H|Average Hits per Hour. Only last 24 hours is logged", "cache.hits_avg_s" => "Hits/S|Average Hits per Second. Only last 5 seconds is logged", "cache.updates" => "Updates|Cache Updates", "cache.skips" => "Skips|Skips. Skip=updates are needed but skipped for some reason. e.g.: other process/thread is busy compiling on this cache", "cache.ooms" => "OOMs|Out Of Memory, how many times a new item should be stored but there isn't enough memory in the cache, think of increasing the xcache.size or xcache.var_size", "cache.errors" => "Errs|Compiler errors, how many times your script(s) failed to be compiled by PHP. You should really check what is happening if you see this value increase. (See Help for more information)", "cache.readonly_protected" => "Protected|Whether readonly_protection is available and enable on this cache (See help for more information)", "cache.cached" => "Cached|Number of entries stored in this cache", "cache.deleted" => "Deleted|Number of entries is pending in delete list (expired but referenced)", "cache.gc_timer" => "GC|Seconds count down of Garbage Collection", ); xcache-3.1.0/htdocs/cacher/lang/en.po0000644000175000010010000001350512206607315015550 0ustar mOoNonemsgid "" msgstr "" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-07-08 14:41+0800\n" "Language: en\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: edit.tpl.php:8 #, php-format msgid "Editing Variable %s" msgstr "" #: edit.tpl.php:13 #, php-format msgid "Set %s in config to enable" msgstr "" #: index.php:187 index.php:213 msgid "Total" msgstr "" #: index.php:263 msgid "Summary" msgstr "" #: index.php:264 msgid "List PHP" msgstr "" #: index.php:265 msgid "List Var Data" msgstr "" #: listentries.tpl.php:11 msgid "php Cached" msgstr "PHP Cached" #: listentries.tpl.php:11 msgid "var Cached" msgstr "Variable Cached" #: listentries.tpl.php:15 msgid "php Deleted" msgstr "PHP Deleted" #: listentries.tpl.php:15 msgid "var Deleted" msgstr "Variable Deleted" #: sub/entrylist.tpl.php:14 msgid "entry.id" msgstr "Id|" #: sub/entrylist.tpl.php:19 msgid "entry.remove" msgstr "Remove|" #: sub/entrylist.tpl.php:24 msgid "entry.name" msgstr "Entry name|The entry name or filename" #: sub/entrylist.tpl.php:25 msgid "entry.hits" msgstr "Hits|Hit times of this entry (loaded from this cache)" #: sub/entrylist.tpl.php:26 msgid "entry.size" msgstr "Size|Size in bytes of this entry in the cache" #: sub/entrylist.tpl.php:31 msgid "entry.refcount" msgstr "Refs|Reference count of this entry is holded by a php request" #: sub/entrylist.tpl.php:32 msgid "entry.phprefcount" msgstr "Shares|Count of entry sharing this php data" #: sub/entrylist.tpl.php:33 msgid "entry.class_cnt" msgstr "Cls.|Count of classes" #: sub/entrylist.tpl.php:34 msgid "entry.function_cnt" msgstr "Funcs|Count of functions" #: sub/entrylist.tpl.php:35 msgid "entry.file_size" msgstr "Src Size|Size of the source file" #: sub/entrylist.tpl.php:36 msgid "entry.file_mtime" msgstr "Modified|Last modified time of the source file" #: sub/entrylist.tpl.php:39 msgid "entry.file_device" msgstr "dev|device number of the source file" #: sub/entrylist.tpl.php:40 msgid "entry.file_inode" msgstr "ino|inode number of the source file" #: sub/entrylist.tpl.php:44 msgid "entry.hash" msgstr "Hash|Hash value of this entry" #: sub/entrylist.tpl.php:45 msgid "entry.atime" msgstr "Access|Last time when this entry is accessed" #: sub/entrylist.tpl.php:46 msgid "entry.ctime" msgstr "Create|The time when this entry is stored" #: sub/entrylist.tpl.php:51 msgid "entry.delete" msgstr "Delete|The time when this entry is deleted" #: sub/entrylist.tpl.php:149 msgid "Remove Selected" msgstr "" #: sub/moduleinfo.tpl.php:1 msgid "Module Info" msgstr "" #: sub/summary.tpl.php:3 msgid "Caches" msgstr "Caches" #: sub/summary.tpl.php:6 msgid "cache.cache" msgstr "Cache|" #: sub/summary.tpl.php:7 msgid "cache.slots" msgstr "Slots|Number of hash slots. the setting from your php.ini" #: sub/summary.tpl.php:8 msgid "cache.size" msgstr "Size|Cache Size, Size of the cache (or cache chunk), in bytes" #: sub/summary.tpl.php:9 msgid "cache.avail" msgstr "Avail|Available Memory, free memory in bytes of this cache" #: sub/summary.tpl.php:10 msgid "cache.blocksgraph" msgstr "" "Percent Graph|Shows how much memory available in percent, and memory blocks " "status in graph" #: sub/summary.tpl.php:11 msgid "cache.operations" msgstr "Operations|Press the clear button to clean this cache" #: sub/summary.tpl.php:12 msgid "cache.status" msgstr "" "Status|Compiling flag, \"Compiling\" if the cache is busy compiling php " "script. \"Disabled\" if cache is disabled" #: sub/summary.tpl.php:13 msgid "cache.hits" msgstr "Hits|Cache Hits, hit=a var/php is loaded from this cache" #: sub/summary.tpl.php:14 msgid "cache.hits_graph" msgstr "Hits*24H|Hits graph of last 24 hours" #: sub/summary.tpl.php:15 msgid "cache.hits_avg_h" msgstr "Hits/H|Average Hits per Hour. Only last 24 hours is logged" #: sub/summary.tpl.php:16 msgid "cache.hits_avg_s" msgstr "Hits/S|Average Hits per Second. Only last 5 seconds is logged" #: sub/summary.tpl.php:17 msgid "cache.updates" msgstr "Updates|Cache Updates" #: sub/summary.tpl.php:18 msgid "cache.skips" msgstr "" "Skips|Skips. Skip=updates are needed but skipped for some reason. e.g.: " "other process/thread is busy compiling on this cache" #: sub/summary.tpl.php:19 msgid "cache.ooms" msgstr "" "OOMs|Out Of Memory, how many times a new item should be stored but there " "isn't enough memory in the cache, think of increasing the xcache.size or " "xcache.var_size" #: sub/summary.tpl.php:20 msgid "cache.errors" msgstr "" "Errs|Compiler errors, how many times your script(s) failed to be compiled by " "PHP. You should really check what is happening if you see this value " "increase. (See Help for more information)" #: sub/summary.tpl.php:21 msgid "cache.readonly_protected" msgstr "" "Protected|Whether readonly_protection is available and enable on this cache " "(See help for more information)" #: sub/summary.tpl.php:22 msgid "cache.cached" msgstr "Cached|Number of entries stored in this cache" #: sub/summary.tpl.php:23 msgid "cache.deleted" msgstr "" "Deleted|Number of entries is pending in delete list (expired but referenced)" #: sub/summary.tpl.php:24 msgid "cache.gc_timer" msgstr "GC|Seconds count down of Garbage Collection" #: sub/summary.tpl.php:30 msgid "Clear" msgstr "" #: sub/summary.tpl.php:31 msgid "Disabled" msgstr "" #: sub/summary.tpl.php:32 msgid "Disable" msgstr "" #: sub/summary.tpl.php:33 msgid "Enable" msgstr "" #: sub/summary.tpl.php:34 msgid "Compiling" msgstr "" #: sub/summary.tpl.php:35 msgid "Normal" msgstr "" #: sub/summary.tpl.php:36 sub/testcoredump.tpl.php:3 msgid "Sure?" msgstr "" #: sub/summary.tpl.php:132 msgid "Legends:" msgstr "" #: sub/summary.tpl.php:134 msgid "% Free" msgstr "" #: sub/summary.tpl.php:134 msgid "% Used" msgstr "" #: sub/summary.tpl.php:136 msgid "Free Blocks" msgstr "" #: sub/summary.tpl.php:136 msgid "Used Blocks" msgstr "" #: sub/summary.tpl.php:138 msgid "Hits" msgstr "" xcache-3.1.0/htdocs/cacher/lang/zh-simplified.php0000644000175000010010000000760312157744742020100 0ustar mOoNone "正在编辑变量 %s", "Set %s in config to enable" => "请在配置文件中设置 %s 启用本功能", "Total" => "总共", "Summary" => "摘要信息", "List PHP" => "列出PHP", "List Var Data" => "列变量数据", "php Cached" => "缓存的 PHP 脚本", "var Cached" => "缓存的变量", "php Deleted" => "待删 PHP 脚本缓存", "var Deleted" => "待删变量缓存", "entry.id" => "Id|", "entry.remove" => "删除|", "entry.name" => "项目名/文件名|项目名或者文件名", "entry.hits" => "命中|该项目被命中的次数 (从缓存区载入)", "entry.size" => "大小|项目在缓存里占用字节数", "entry.refcount" => "引用数|项目依然被其他进程占据的引用次数", "entry.phprefcount" => "共享数|与本项目相同 PHP 代码的个数", "entry.class_cnt" => "类|类个数", "entry.function_cnt" => "函数|函数个数", "entry.file_size" => "源大小|源文件大小", "entry.file_mtime" => "修改|源文件最后修改时间", "entry.file_device" => "dev|源文件所在设备ID", "entry.file_inode" => "ino|源文件的 inode", "entry.hash" => "哈希|该项目的哈希值", "entry.atime" => "访问|最后访问该项目的时间", "entry.ctime" => "创建|该项目被创建于缓存区内的时间", "entry.delete" => "删除|该项目被决定删除的时间", "Remove Selected" => "删除所选", "Module Info" => "模块信息", "Caches" => "缓存区", "cache.cache" => "缓存|", "cache.slots" => "槽|Hash 槽个数, 对应 php.ini 里的设置", "cache.size" => "大小|共享内存区大小, 单位: 字节", "cache.avail" => "剩余|可用内存, 对应缓存区的剩余内存字节数", "cache.blocksgraph" => "百分比图|条状显示可用内存的比例, 以及显示分配块状态", "cache.operations" => "操作|点击按钮清除对应缓存区的数据", "cache.status" => "状态|状态标记. 当缓存区正在编译 PHP 脚本时标记为 \"编译中\". 当缓存区暂停使用时标记为 \"禁用\"", "cache.hits" => "命中|缓存命中次数, 命中=从该缓存载入 PHP 或者变量", "cache.hits_graph" => "24H 分布|24 小时命中分布图. 图表现是最后 24 小时的命中次数", "cache.hits_avg_h" => "命中/H|每小时命中次数. 只统计最后 24 小时", "cache.hits_avg_s" => "命中/S|每秒命中次数. 只统计最后 5 秒", "cache.updates" => "更新|缓存更新次数", "cache.skips" => "跳过|跳过更新次数, 跳过=XCache 自动判断阻塞的缓存区自动跳过阻塞等待, 直接使用编译不缓存方式继续处理请求", "cache.ooms" => "内存不足|内存不足次数, 显示需要存储新数据但是缓存区内存不足的次数. 如果出现太频繁请考虑加大配置中的 xcache.size 或者 xcache.var_size", "cache.errors" => "错误|编译错误, 显示您的脚本被编译时出错的次数. 如果您发现这个数字不断增长, 您应该检查什么脚本产生错误. 参考 帮助 获取更多信息", "cache.readonly_protected" => "保护|显示该 Cache 是否支持并启用 readonly_protection. 参考 帮助 获取更多信息", "cache.cached" => "缓存|缓存于该缓存区的项目条数", "cache.deleted" => "待删|缓存区内将要删除的项目 (已经删除但是还被某些进程占用)", "cache.gc_timer" => "GC|垃圾回收的倒计时", "Clear" => "清除", "Disabled" => "禁用", "Disable" => "禁用", "Enable" => "启用", "Compiling" => "编译中", "Normal" => "正常", "Sure?" => "确认?", "Legends:" => "图例:", "% Free" => "% 剩余", "% Used" => "% 已用", "Free Blocks" => "未用块", "Used Blocks" => "已用块", "Hits" => "命中", ); xcache-3.1.0/htdocs/cacher/lang/zh-simplified.po0000644000175000010010000001405212206607315017710 0ustar mOoNonemsgid "" msgstr "" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-07-08 14:41+0800\n" "Language: zh\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: edit.tpl.php:8 #, php-format msgid "Editing Variable %s" msgstr "正在编辑变量 %s" #: edit.tpl.php:13 #, php-format msgid "Set %s in config to enable" msgstr "请在配置文件中设置 %s 启用本功能" #: index.php:187 index.php:213 msgid "Total" msgstr "总共" #: index.php:263 msgid "Summary" msgstr "摘要信息" #: index.php:264 msgid "List PHP" msgstr "列出PHP" #: index.php:265 msgid "List Var Data" msgstr "列变量数据" #: listentries.tpl.php:11 msgid "php Cached" msgstr "缓存的 PHP 脚本" #: listentries.tpl.php:11 msgid "var Cached" msgstr "缓存的变量" #: listentries.tpl.php:15 msgid "php Deleted" msgstr "待删 PHP 脚本缓存" #: listentries.tpl.php:15 msgid "var Deleted" msgstr "待删变量缓存" #: sub/entrylist.tpl.php:14 msgid "entry.id" msgstr "Id|" #: sub/entrylist.tpl.php:19 msgid "entry.remove" msgstr "删除|" #: sub/entrylist.tpl.php:24 msgid "entry.name" msgstr "项目名/文件名|项目名或者文件名" #: sub/entrylist.tpl.php:25 msgid "entry.hits" msgstr "命中|该项目被命中的次数 (从缓存区载入)" #: sub/entrylist.tpl.php:26 msgid "entry.size" msgstr "大小|项目在缓存里占用字节数" #: sub/entrylist.tpl.php:31 msgid "entry.refcount" msgstr "引用数|项目依然被其他进程占据的引用次数" #: sub/entrylist.tpl.php:32 msgid "entry.phprefcount" msgstr "共享数|与本项目相同 PHP 代码的个数" #: sub/entrylist.tpl.php:33 msgid "entry.class_cnt" msgstr "类|类个数" #: sub/entrylist.tpl.php:34 msgid "entry.function_cnt" msgstr "函数|函数个数" #: sub/entrylist.tpl.php:35 msgid "entry.file_size" msgstr "源大小|源文件大小" #: sub/entrylist.tpl.php:36 msgid "entry.file_mtime" msgstr "修改|源文件最后修改时间" #: sub/entrylist.tpl.php:39 msgid "entry.file_device" msgstr "dev|源文件所在设备ID" #: sub/entrylist.tpl.php:40 msgid "entry.file_inode" msgstr "ino|源文件的 inode" #: sub/entrylist.tpl.php:44 msgid "entry.hash" msgstr "哈希|该项目的哈希值" #: sub/entrylist.tpl.php:45 msgid "entry.atime" msgstr "访问|最后访问该项目的时间" #: sub/entrylist.tpl.php:46 msgid "entry.ctime" msgstr "创建|该项目被创建于缓存区内的时间" #: sub/entrylist.tpl.php:51 msgid "entry.delete" msgstr "删除|该项目被决定删除的时间" #: sub/entrylist.tpl.php:149 msgid "Remove Selected" msgstr "删除所选" #: sub/moduleinfo.tpl.php:1 msgid "Module Info" msgstr "模块信息" #: sub/summary.tpl.php:3 msgid "Caches" msgstr "缓存区" #: sub/summary.tpl.php:6 msgid "cache.cache" msgstr "缓存|" #: sub/summary.tpl.php:7 msgid "cache.slots" msgstr "槽|Hash 槽个数, 对应 php.ini 里的设置" #: sub/summary.tpl.php:8 msgid "cache.size" msgstr "大小|共享内存区大小, 单位: 字节" #: sub/summary.tpl.php:9 msgid "cache.avail" msgstr "剩余|可用内存, 对应缓存区的剩余内存字节数" #: sub/summary.tpl.php:10 msgid "cache.blocksgraph" msgstr "百分比图|条状显示可用内存的比例, 以及显示分配块状态" #: sub/summary.tpl.php:11 msgid "cache.operations" msgstr "操作|点击按钮清除对应缓存区的数据" #: sub/summary.tpl.php:12 msgid "cache.status" msgstr "" "状态|状态标记. 当缓存区正在编译 PHP 脚本时标记为 \"编译中\". 当缓存区暂停使用" "时标记为 \"禁用\"" #: sub/summary.tpl.php:13 msgid "cache.hits" msgstr "命中|缓存命中次数, 命中=从该缓存载入 PHP 或者变量" #: sub/summary.tpl.php:14 msgid "cache.hits_graph" msgstr "24H 分布|24 小时命中分布图. 图表现是最后 24 小时的命中次数" #: sub/summary.tpl.php:15 msgid "cache.hits_avg_h" msgstr "命中/H|每小时命中次数. 只统计最后 24 小时" #: sub/summary.tpl.php:16 msgid "cache.hits_avg_s" msgstr "命中/S|每秒命中次数. 只统计最后 5 秒" #: sub/summary.tpl.php:17 msgid "cache.updates" msgstr "更新|缓存更新次数" #: sub/summary.tpl.php:18 msgid "cache.skips" msgstr "" "跳过|跳过更新次数, 跳过=XCache 自动判断阻塞的缓存区自动跳过阻塞等待, 直接使用" "编译不缓存方式继续处理请求" #: sub/summary.tpl.php:19 msgid "cache.ooms" msgstr "" "内存不足|内存不足次数, 显示需要存储新数据但是缓存区内存不足的次数. 如果出现太" "频繁请考虑加大配置中的 xcache.size 或者 xcache.var_size" #: sub/summary.tpl.php:20 msgid "cache.errors" msgstr "" "错误|编译错误, 显示您的脚本被编译时出错的次数. 如果您发现这个数字不断增长, 您" "应该检查什么脚本产生错误. 参考 帮助 获取更多信息" #: sub/summary.tpl.php:21 msgid "cache.readonly_protected" msgstr "" "保护|显示该 Cache 是否支持并启用 readonly_protection. 参考 帮助 获取更多信息" #: sub/summary.tpl.php:22 msgid "cache.cached" msgstr "缓存|缓存于该缓存区的项目条数" #: sub/summary.tpl.php:23 msgid "cache.deleted" msgstr "待删|缓存区内将要删除的项目 (已经删除但是还被某些进程占用)" #: sub/summary.tpl.php:24 msgid "cache.gc_timer" msgstr "GC|垃圾回收的倒计时" #: sub/summary.tpl.php:30 msgid "Clear" msgstr "清除" #: sub/summary.tpl.php:31 msgid "Disabled" msgstr "禁用" #: sub/summary.tpl.php:32 msgid "Disable" msgstr "禁用" #: sub/summary.tpl.php:33 msgid "Enable" msgstr "启用" #: sub/summary.tpl.php:34 msgid "Compiling" msgstr "编译中" #: sub/summary.tpl.php:35 msgid "Normal" msgstr "正常" #: sub/summary.tpl.php:36 sub/testcoredump.tpl.php:3 msgid "Sure?" msgstr "确认?" #: sub/summary.tpl.php:132 msgid "Legends:" msgstr "图例:" #: sub/summary.tpl.php:134 msgid "% Free" msgstr "% 剩余" #: sub/summary.tpl.php:134 msgid "% Used" msgstr "% 已用" #: sub/summary.tpl.php:136 msgid "Free Blocks" msgstr "未用块" #: sub/summary.tpl.php:136 msgid "Used Blocks" msgstr "已用块" #: sub/summary.tpl.php:138 msgid "Hits" msgstr "命中" xcache-3.1.0/htdocs/cacher/lang/zh-traditional.php0000644000175000010010000000775412157744742020274 0ustar mOoNone "正在编辑变量 %s", "Set %s in config to enable" => "請在配置文件中設置 %s 啟用本功能", "Total" => "总共", "Summary" => "簡要訊息", "List PHP" => "列出PHP", "List Var Data" => "列變數資料", "php Cached" => "快取的 PHP 指令", "var Cached" => "快取的變數", "php Deleted" => "待刪 PHP 指令快取", "var Deleted" => "待刪變數快取", "entry.id" => "Id|", "entry.remove" => "移除|", "entry.name" => "項目名稱/檔案名稱|項目名稱或者檔案名稱", "entry.hits" => "命中|該項目被命中的次數 (從共享記憶體區載入)", "entry.size" => "大小|項目在共享記憶體裡佔用位元數", "entry.refcount" => "引用數|項目依然被其他程序佔用的引用次數", "entry.phprefcount" => "共享|與本項目相同 PHP 內容的个數", "entry.class_cnt" => "类|类个数", "entry.function_cnt" => "函数|函数个数", "entry.file_size" => "源大小|原始檔案大小", "entry.file_mtime" => "修改|原始檔案最後修改時間", "entry.file_device" => "dev|原始檔案所在設備ID", "entry.file_inode" => "ino|原始檔案的inode", "entry.hash" => "Hash|Hash", "entry.atime" => "存取|最後存取該項目的時間", "entry.ctime" => "建立|該項目被建立於共享內的時間", "entry.delete" => "移除|該項目被移除於共享內的時間", "Remove Selected" => "移除所选", "Module Info" => "組元訊息", "Caches" => "快取", "cache.cache" => "快取|", "cache.slots" => "槽|Hash 槽個數,對應 php.ini 裡的設置", "cache.size" => "大小|共享記憶體區大小,單位:位元", "cache.avail" => "剩餘|可用記憶體,對應共享記憶體區的剩餘記憶體位元數", "cache.blocksgraph" => "百分比图|條狀顯示可用記憶體的比例", "cache.operations" => "操作|點擊按鈕清除對應共享記憶體區的資料", "cache.status" => "狀態|狀態標記. 當共享內存區正在編譯 PHP 腳本時標記為 \"編譯中\". 當共享內存區暫停使用時標記為 \"禁用\"", "cache.hits" => "命中|共享記憶體命中次數,命中=從該共享記憶體載入 PHP 或者變數", "cache.hits_graph" => "24H 分布|24 小时命中分布图. 图表现是最后 24 小时的命中次数", "cache.hits_avg_h" => "命中/H|每小时命中次数. 只统计最后 24 小时", "cache.hits_avg_s" => "命中/S|每秒命中次数. 只统计最后 5 秒", "cache.updates" => "更新|共享記憶更新過次數", "cache.skips" => "跳過|跳過更新次數,跳過=XCache 自動判斷阻塞的共享記憶體區自動跳過阻塞等待,直接使用编译不存储方式繼續處理請求", "cache.ooms" => "記憶體不足|記憶體不足次數,顯示需要儲存新資料但是共享記憶體區記憶體不足的次數. 如果出現太頻繁請考慮加大配置中的 xcache.size 或者 xcache.var_size", "cache.errors" => "错误|编译错误, 显示您的脚本被编译时出错的次数. 如果您发现这个数字不断增长, 您应该检查什么脚本产生错误. 参考 說明 获取更多信息", "cache.readonly_protected" => "保护|顯示該 Cache 是否支援並啟用 readonly_protection. 参考 說明", "cache.cached" => "快取|共享記憶體於該共享記憶體區的項目個數", "cache.deleted" => "待刪|共享記憶體區內將要刪除的項目 (已經刪除但是還被某些程序佔用)", "cache.gc_timer" => "GC|垃圾回收的倒數計時", "Clear" => "清除", "Disabled" => "禁用", "Disable" => "禁用", "Enable" => "啟用", "Compiling" => "編譯中", "Normal" => "正常", "Sure?" => "確認?", "Legends:" => "图例:", "% Free" => "% 剩余", "% Used" => "% 已用", "Free Blocks" => "未用块", "Used Blocks" => "已用块", "Hits" => "命中", ); xcache-3.1.0/htdocs/cacher/lang/zh-traditional.po0000644000175000010010000001422312206607315020075 0ustar mOoNonemsgid "" msgstr "" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-07-08 14:41+0800\n" "Language: zh_TW\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: edit.tpl.php:8 #, php-format msgid "Editing Variable %s" msgstr "正在编辑变量 %s" #: edit.tpl.php:13 #, php-format msgid "Set %s in config to enable" msgstr "請在配置文件中設置 %s 啟用本功能" #: index.php:187 index.php:213 msgid "Total" msgstr "总共" #: index.php:263 msgid "Summary" msgstr "簡要訊息" #: index.php:264 msgid "List PHP" msgstr "列出PHP" #: index.php:265 msgid "List Var Data" msgstr "列變數資料" #: listentries.tpl.php:11 msgid "php Cached" msgstr "快取的 PHP 指令" #: listentries.tpl.php:11 msgid "var Cached" msgstr "快取的變數" #: listentries.tpl.php:15 msgid "php Deleted" msgstr "待刪 PHP 指令快取" #: listentries.tpl.php:15 msgid "var Deleted" msgstr "待刪變數快取" #: sub/entrylist.tpl.php:14 msgid "entry.id" msgstr "Id|" #: sub/entrylist.tpl.php:19 msgid "entry.remove" msgstr "移除|" #: sub/entrylist.tpl.php:24 msgid "entry.name" msgstr "項目名稱/檔案名稱|項目名稱或者檔案名稱" #: sub/entrylist.tpl.php:25 msgid "entry.hits" msgstr "命中|該項目被命中的次數 (從共享記憶體區載入)" #: sub/entrylist.tpl.php:26 msgid "entry.size" msgstr "大小|項目在共享記憶體裡佔用位元數" #: sub/entrylist.tpl.php:31 msgid "entry.refcount" msgstr "引用數|項目依然被其他程序佔用的引用次數" #: sub/entrylist.tpl.php:32 msgid "entry.phprefcount" msgstr "共享|與本項目相同 PHP 內容的个數" #: sub/entrylist.tpl.php:33 msgid "entry.class_cnt" msgstr "类|类个数" #: sub/entrylist.tpl.php:34 msgid "entry.function_cnt" msgstr "函数|函数个数" #: sub/entrylist.tpl.php:35 msgid "entry.file_size" msgstr "源大小|原始檔案大小" #: sub/entrylist.tpl.php:36 msgid "entry.file_mtime" msgstr "修改|原始檔案最後修改時間" #: sub/entrylist.tpl.php:39 msgid "entry.file_device" msgstr "dev|原始檔案所在設備ID" #: sub/entrylist.tpl.php:40 msgid "entry.file_inode" msgstr "ino|原始檔案的inode" #: sub/entrylist.tpl.php:44 msgid "entry.hash" msgstr "Hash|Hash" #: sub/entrylist.tpl.php:45 msgid "entry.atime" msgstr "存取|最後存取該項目的時間" #: sub/entrylist.tpl.php:46 msgid "entry.ctime" msgstr "建立|該項目被建立於共享內的時間" #: sub/entrylist.tpl.php:51 msgid "entry.delete" msgstr "移除|該項目被移除於共享內的時間" #: sub/entrylist.tpl.php:149 msgid "Remove Selected" msgstr "移除所选" #: sub/moduleinfo.tpl.php:1 msgid "Module Info" msgstr "組元訊息" #: sub/summary.tpl.php:3 msgid "Caches" msgstr "快取" #: sub/summary.tpl.php:6 msgid "cache.cache" msgstr "快取|" #: sub/summary.tpl.php:7 msgid "cache.slots" msgstr "槽|Hash 槽個數,對應 php.ini 裡的設置" #: sub/summary.tpl.php:8 msgid "cache.size" msgstr "大小|共享記憶體區大小,單位:位元" #: sub/summary.tpl.php:9 msgid "cache.avail" msgstr "剩餘|可用記憶體,對應共享記憶體區的剩餘記憶體位元數" #: sub/summary.tpl.php:10 msgid "cache.blocksgraph" msgstr "百分比图|條狀顯示可用記憶體的比例" #: sub/summary.tpl.php:11 msgid "cache.operations" msgstr "操作|點擊按鈕清除對應共享記憶體區的資料" #: sub/summary.tpl.php:12 msgid "cache.status" msgstr "" "狀態|狀態標記. 當共享內存區正在編譯 PHP 腳本時標記為 \"編譯中\". 當共享內存區" "暫停使用時標記為 \"禁用\"" #: sub/summary.tpl.php:13 msgid "cache.hits" msgstr "命中|共享記憶體命中次數,命中=從該共享記憶體載入 PHP 或者變數" #: sub/summary.tpl.php:14 msgid "cache.hits_graph" msgstr "24H 分布|24 小时命中分布图. 图表现是最后 24 小时的命中次数" #: sub/summary.tpl.php:15 msgid "cache.hits_avg_h" msgstr "命中/H|每小时命中次数. 只统计最后 24 小时" #: sub/summary.tpl.php:16 msgid "cache.hits_avg_s" msgstr "命中/S|每秒命中次数. 只统计最后 5 秒" #: sub/summary.tpl.php:17 msgid "cache.updates" msgstr "更新|共享記憶更新過次數" #: sub/summary.tpl.php:18 msgid "cache.skips" msgstr "" "跳過|跳過更新次數,跳過=XCache 自動判斷阻塞的共享記憶體區自動跳過阻塞等待,直" "接使用编译不存储方式繼續處理請求" #: sub/summary.tpl.php:19 msgid "cache.ooms" msgstr "" "記憶體不足|記憶體不足次數,顯示需要儲存新資料但是共享記憶體區記憶體不足的次" "數. 如果出現太頻繁請考慮加大配置中的 xcache.size 或者 xcache.var_size" #: sub/summary.tpl.php:20 msgid "cache.errors" msgstr "" "错误|编译错误, 显示您的脚本被编译时出错的次数. 如果您发现这个数字不断增长, 您" "应该检查什么脚本产生错误. 参考 說明 获取更多信息" #: sub/summary.tpl.php:21 msgid "cache.readonly_protected" msgstr "保护|顯示該 Cache 是否支援並啟用 readonly_protection. 参考 說明" #: sub/summary.tpl.php:22 msgid "cache.cached" msgstr "快取|共享記憶體於該共享記憶體區的項目個數" #: sub/summary.tpl.php:23 msgid "cache.deleted" msgstr "待刪|共享記憶體區內將要刪除的項目 (已經刪除但是還被某些程序佔用)" #: sub/summary.tpl.php:24 msgid "cache.gc_timer" msgstr "GC|垃圾回收的倒數計時" #: sub/summary.tpl.php:30 msgid "Clear" msgstr "清除" #: sub/summary.tpl.php:31 msgid "Disabled" msgstr "禁用" #: sub/summary.tpl.php:32 msgid "Disable" msgstr "禁用" #: sub/summary.tpl.php:33 msgid "Enable" msgstr "啟用" #: sub/summary.tpl.php:34 msgid "Compiling" msgstr "編譯中" #: sub/summary.tpl.php:35 msgid "Normal" msgstr "正常" #: sub/summary.tpl.php:36 sub/testcoredump.tpl.php:3 msgid "Sure?" msgstr "確認?" #: sub/summary.tpl.php:132 msgid "Legends:" msgstr "图例:" #: sub/summary.tpl.php:134 msgid "% Free" msgstr "% 剩余" #: sub/summary.tpl.php:134 msgid "% Used" msgstr "% 已用" #: sub/summary.tpl.php:136 msgid "Free Blocks" msgstr "未用块" #: sub/summary.tpl.php:136 msgid "Used Blocks" msgstr "已用块" #: sub/summary.tpl.php:138 msgid "Hits" msgstr "命中" xcache-3.1.0/htdocs/cacher/listentries.tpl.php0000644000175000010010000000122012157744742017543 0ustar mOoNone
xcache-3.1.0/htdocs/cacher/mkpassword.php0000644000175000010010000000203312220455230016553 0ustar mOoNone Simple MD5 password generator

Simple MD5 password generator

Name:

Password:


The INI settings you need is:
$md5_1$md5_2\"\n";
				}
				?>
xcache-3.1.0/htdocs/cacher/sub/0000755000175000010010000000000012157744743014466 5ustar mOoNonexcache-3.1.0/htdocs/cacher/sub/entrylist.tpl.php0000644000175000010010000000660412157744742020037 0ustar mOoNone
TR; if ($isphp) { echo th(N_("entry.id")) ; } else { echo th(N_("entry.remove")) ; } echo th(N_("entry.name")) , th(N_("entry.hits")) , th(N_("entry.size")) ; if ($isphp) { echo th(N_("entry.refcount")) , th(N_("entry.phprefcount")) , th(N_("entry.class_cnt")) , th(N_("entry.function_cnt")) , th(N_("entry.file_size")) , th(N_("entry.file_mtime")) ; echo th(N_("entry.file_device")) , th(N_("entry.file_inode")) ; } echo th(N_("entry.hash")) , th(N_("entry.atime")) , th(N_("entry.ctime")) ; if ($listName == 'Deleted') { echo th(N_("entry.delete")) ; } ?> $entry) { $class = $cycleClass->next(); echo << TR; $hits = number_format($entry['hits']); $size = size($entry['size']); if ($isphp) { $class_cnt = number_format($entry['class_cnt']); $function_cnt = number_format($entry['function_cnt']); $phprefcount = number_format($entry['phprefcount']); $file_size = size($entry['file_size']); } if ($isphp) { $file_mtime = age($entry['file_mtime']); } $ctime = age($entry['ctime']); $atime = age($entry['atime']); if ($listName == 'Deleted') { $dtime = age($entry['dtime']); } if ($isphp) { $hname = htmlspecialchars($entry['name']); $namelink = $hname; echo <<{$entry['cache_name']} {$i} ENTRY; } else { $name = $entry['name']; if (!empty($config['enable_eval'])) { $name = var_export($name, true); } $uname = urlencode($name); $hname = htmlspecialchars(str_replace("\0", "\\0", $entry['name'])); echo << ENTRY; $namelink = "$hname"; } echo <<{$namelink} ENTRY; if ($isphp) { $refcount = number_format($entry['refcount']); echo <<{$entry['refcount']} ENTRY; if (isset($entry['file_inode'])) { echo <<{$entry['file_device']} ENTRY; } } echo <<{$entry['hvalue']} ENTRY; if ($listName == 'Deleted') { echo <<{$dtime} ENTRY; } echo << TR; } ?>
{$entry['hits']} {$size}{$phprefcount} {$class_cnt} {$function_cnt} {$file_size} {$file_mtime}{$entry['file_inode']}{$atime} {$ctime}
">
xcache-3.1.0/htdocs/cacher/sub/moduleinfo.tpl.php0000644000175000010010000000014412157744743020135 0ustar mOoNone

xcache-3.1.0/htdocs/cacher/sub/summary.tpl.php0000644000175000010010000001076212157744742017477 0ustar mOoNone $ci) { $class = $cycleClass->next(); echo << TR; $pvalue = (int) ($ci['avail'] / $ci['size'] * 100); $pempty = 100 - $pvalue; if ($config['percent_graph_type'] == 'used') { // swap $tmp = $pvalue; $pvalue = $pempty; $pempty = $tmp; } $w = $config['percent_graph_width'] + 2; if (empty($ci['istotal'])) { $graph = freeblock_to_graph($ci['free_blocks'], $ci['size']); $blocksgraph = "
{$graph}
"; } else { $blocksgraph = ''; } $ci_slots = size($ci['slots']); $ci_size = size($ci['size']); $ci_avail = size($ci['avail']); $ci = number_formats($ci, $numkeys); $hits_avg_h = number_format(array_avg($ci['hits_by_hour']), 2); $hits_avg_s = number_format(array_avg($ci['hits_by_second']), 2); $hits_graph_h = get_cache_hits_graph($ci, 'hits_by_hour'); if (!empty($ci['istotal'])) { $ci['status'] = '-'; $ci['can_readonly'] = '-'; } else { if ($ci['disabled']) { $ci['status'] = $l_disabled . sprintf("(%s)", age($ci['disabled'])); } else if ($ci['type'] == XC_TYPE_PHP) { $ci['status'] = $ci['compiling'] ? $l_compiling . sprintf("(%s)", age($ci['compiling'])) : $l_normal; } else { $ci['status'] = '-'; } $ci['can_readonly'] = $ci['can_readonly'] ? 'yes' : 'no'; } $enabledisable = $ci['disabled'] ? 'enable' : 'disable'; $l_enabledisable = $ci['disabled'] ? $l_enable : $l_disable; echo <<{$ci['cache_name']} EOS; ?>
{$ci_slots} {$ci_size} {$ci_avail}
{$blocksgraph}
{$ci['status']} {$ci['hits']} {$hits_graph_h} {$hits_avg_h} {$hits_avg_s} {$ci['updates']} {$ci['skips']} {$ci['ooms']} {$ci['errors']} {$ci['can_readonly']} {$ci['cached']} {$ci['deleted']} {$ci['gc']}
  
  
  
xcache-3.1.0/htdocs/cacher/sub/testcoredump.tpl.php0000644000175000010010000000027412157744742020515 0ustar mOoNone
xcache-3.1.0/htdocs/cacher/summary.tpl.php0000644000175000010010000000036512157744742016704 0ustar mOoNone
xcache-3.1.0/htdocs/common/0000755000175000010010000000000012157744742013737 5ustar mOoNonexcache-3.1.0/htdocs/common/common.css0000644000175000010010000001011612157744741015737 0ustar mOoNone* { box-sizing: border-box; -moz-box-sizing: border-box; } body { background: white; color: black; margin: 0; padding: 0; font-family: arial; font-size: 12pt; } form { margin: 0; padding: 0; } a:link , a:visited { color: #0066CC; } a:link:hover , a:visited:hover { color: #BB0000; } a:link:active , a:visited:active { color: red; } #header { background: #5084D5; position: relative; height: 51px; color: #d0d0d0; } h1, h2, h3, h4, h5, h6 { margin-bottom: 2px; } #header #banner { font: 32px/51px "arial", serif; color: white; } #header #banner a { color: white; } #header #banner #logo { border: 0; display: block; float: left; margin-right: 5px; background: white; } #header #mainnav { top: 3px; right: 5px; font-size: 16px; line-height: 16px; position: absolute; } #header #mainnav a { font-size: 14px; } #header #subnav { bottom: 0; right: 5px; position: absolute; font-size: 28px; line-height: 28px; } #header #subnav a { font-size: 24px; } #header #nav { font-family: "arial", serif; } #header #mainnav a:link, #header #mainnav a:visited { color: black; } #header #mainnav a:active, #header #mainnav a:hover { color: red; } #header #mainnav a { padding: 0 8px 0 8px; } #headerbase { background: #1163BC; border: 1px solid #334C66; border-width: 1px 0 1px 0; margin-bottom: 10px; font: 12px/12px serif; } #main table { font-size: 12px; border: 1px solid #334C66; border-top-width: 0; } #main table caption { background: #1163BC; color: white; line-height: 20px; border: 1px solid #334C66; border-bottom-width: 0; padding: 0; } #main table tfoot { background: #1163BC; } #main table th { background: #E7E7FF; color: black; } #main table td { vertical-align: top; } #main { margin: 20px; } #note { font-size: 11.9px; } #footer { bottom: 0px; background: #E7E7FF; border-top: 1px solid gray; } #poweredBy { overflow: hidden; } #footer { clear: both; height: 40px; position: relative; } #footer img { margin-top: 2px; margin-left: 2px; border: 0; } #poweredBy h3 { float: right; margin-right: 20px; margin-top: 20px; } #poweredBy h3 { margin: 0; font-size: 12px; position: absolute; bottom: 8px; right: 8px; } .phpinfo table { border: 1px solid #334C66; margin-bottom: 1px; } .phpinfo table th, .phpinfo table td { border: 1px solid #334C66; } .phpinfo table th { font-weight: bold; } .phpinfo .e {background: #81BBF2; font-weight: bold; color: #000000;} #main .phpinfo .h th {background: #5084D5; font-weight: bold; color: #000000;} .phpinfo .v {color: #000000;} .button { } span.sortarrow { color: white; text-decoration: none; } table.cycles { border: 1px solid #334C66; margin-bottom: 5px; } table.cycles .col1 { background: #f5f5f5; } table.cycles .col2 { background: #e0e0e0; } table.cycles th, table.cycles td { border: 1px solid #334C66; font-family: monospace; } #main table.cycles caption { color: white; font-weight: bold; height: 24px; line-height: 24px; font-family: serif; } #main table.cycles th { background: #81BBF2; color: #334C66; font-weight: bold; height: 20px; line-height: 20px; font-family: serif; } #main table.cycles th.h { background: #5084D5; } th.h a:visited , th.h a:link { color: black; } th.h a:hover { color: #BB0000; } th.h a:active { color: red; } th a { font-weight: bold; display: block; width: 100%; height: 100%; } th { font-size: 12px; } input, table { font-family: sans-serif; } input { font-size: 12px; } table { border-collapse: collapse; font-size: 11px; margin: 0; } table caption { font-size: 14px; font-weight: bold; } a { text-decoration: none; } #main table td { vertical-align: middle; } .switcher a { color: black; padding: 1px 8px 1px 8px; border: 1px solid white; } .switcher a { border-color: white; border-bottom-color: #334C66; } #nav .switcher a { border-color: #5084D5; border-bottom-color: #334C66; } #nav .switcher a.active, .switcher a.active { color: white; background: #1163BC; border-color: #334C66; border-bottom-color: #1163BC; } #nav .switcher a:hover.active, .switcher a:hover.active { background: #81BBF2; } .switcher a:hover { background: #81BBF2; } #nav .switcher a:active, .switcher a:active { background: #81BBF2; } xcache-3.1.0/htdocs/common/common.php0000644000175000010010000001432512157744741015744 0ustar mOoNonevalues = func_get_args(); $this->i = -1; $this->count = count($this->values); } function next() { $this->i = ($this->i + 1) % $this->count; return $this->values[$this->i]; } function cur() { return $this->values[$this->i]; } function reset() { $this->i = -1; } } function switcher($name, $options) { $n = isset($_GET[$name]) ? $_GET[$name] : null; $html = array(); foreach ($options as $k => $v) { $html[] = sprintf('%s', $name, $k, $k == $n ? ' class="active"' : '', $v); } return implode('', $html); } function mainnav() { foreach (array( "http://xcache.lighttpd.net/" => "XCache", "http://xcache.lighttpd.net/wiki/DocTOC" => _T("Document"), "http://xcache.lighttpd.net/wiki/PhpIni" => _T("INI Reference"), "http://xcache.lighttpd.net/wiki/GetSupport" => _T("Get Support"), "https://groups.google.com/group/xcache/" => _T("Discusson"), "http://www.php.net/" => "PHP", "http://www.lighttpd.net/" => "Lighttpd", ) as $url => $title) { $html[] = sprintf('%s', $url, $title); } return implode('|', $html); } function subnav() { global $module, $modules; $html = array(); foreach ($modules as $k => $v) { $html[] = sprintf('%s', $k, $k == $module ? ' class="active"' : '', $v); } return implode('', $html); } function th($name, $attrs = null) { $translated = __($name); if ($translated == $name) { $translated = "$name|$name"; } list($text, $title) = explode('|', $translated, 2); return sprintf('%s%s%s' , "\t" , $attrs ? " $attrs" : "" , $name, htmlspecialchars(trim($title)), trim($text) , "\n"); } function xcache_validateFileName($name) { return preg_match('!^[a-zA-Z0-9._-]+$!', $name); } function get_language_file_ex($dir, $lang) { static $langMap = array( 'zh' => 'zh-simplified', 'zh-hk' => 'zh-traditional', 'zh-tw' => 'zh-traditional', ); if (isset($langMap[$lang])) { $lang = $langMap[$lang]; } else if (!xcache_validateFileName($lang)) { return null; } $file = "$dir/$lang.php"; if (file_exists($file)) { return $file; } return null; } function get_language_file($dir) { global $config; if (!empty($config['lang'])) { $lang = strtolower($config['lang']); $file = get_language_file_ex($dir, $lang); if (!isset($file)) { $lang = strtok($lang, ':-'); $file = get_language_file_ex($dir, $lang); } } else { $config['lang'] = 'en'; if (!empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { foreach (explode(',', str_replace(' ', '', $_SERVER['HTTP_ACCEPT_LANGUAGE'])) as $lang) { $lang = strtok($lang, ':;'); $file = get_language_file_ex($dir, $lang); if (isset($file)) { $config['lang'] = $lang; break; } if (strpos($lang, '-') !== false) { $file = get_language_file_ex($dir, strtok($lang, ':-')); if (isset($file)) { $config['lang'] = $lang; break; } } } } } return isset($file) ? $file : "$dir/en.php"; } function _T($str) { if (isset($GLOBALS['strings'][$str])) { return $GLOBALS['strings'][$str]; } if (!empty($GLOBALS['config']['show_todo_strings'])) { return '' . $str . '|'; } return $str; } function __($str) { return _T($str); } function N_($str) { return $str; } function number_formats($a, $keys) { foreach ($keys as $k) { $a[$k] = number_format($a[$k]); } return $a; } function size($size) { $size = (int) $size; if ($size < 1024) return number_format($size, 2) . ' b'; if ($size < 1048576) return number_format($size / 1024, 2) . ' K'; return number_format($size / 1048576, 2) . ' M'; } function age($time) { if (!$time) return ''; $delta = REQUEST_TIME - $time; if ($delta < 0) { $delta = -$delta; } static $seconds = array(1, 60, 3600, 86400, 604800, 2678400, 31536000); static $name = array('s', 'm', 'h', 'd', 'w', 'M', 'Y'); for ($i = 6; $i >= 0; $i --) { if ($delta >= $seconds[$i]) { $ret = (int) ($delta / $seconds[$i]); return $ret . $name[$i]; } } return '0s'; } function stripaddslashes_array($value, $mqs = false) { if (is_array($value)) { foreach($value as $k => $v) { $value[$k] = stripaddslashes_array($v, $mqs); } } else if(is_string($value)) { $value = $mqs ? str_replace('\'\'', '\'', $value) : stripslashes($value); } return $value; } function ob_filter_path_nicer_default($list_html) { $sep = DIRECTORY_SEPARATOR; $docRoot = $_SERVER['DOCUMENT_ROOT']; if ($sep != '/') { $docRoot = str_replace('/', $sep, $docRoot); } $list_html = str_replace(">$docRoot", ">{DOCROOT}" . (substr($docRoot, -1) == $sep ? $sep : ""), $list_html); $xcachedir = realpath(dirname(__FILE__) . "$sep..$sep"); $list_html = str_replace(">$xcachedir$sep", ">{XCache}$sep", $list_html); if ($sep == '/') { $list_html = str_replace(">/home/", ">{H}/", $list_html); } return $list_html; } error_reporting(E_ALL); ini_set('display_errors', 'On'); define('REQUEST_TIME', time()); if (function_exists('get_magic_quotes_gpc') && @get_magic_quotes_gpc()) { $mqs = (bool) ini_get('magic_quotes_sybase'); $_GET = stripaddslashes_array($_GET, $mqs); $_POST = stripaddslashes_array($_POST, $mqs); $_REQUEST = stripaddslashes_array($_REQUEST, $mqs); unset($mqs); } ini_set('magic_quotes_runtime', '0'); $config = array(); if (file_exists("./config.default.php")) { include "./config.default.php"; } include "../config.default.php"; if (file_exists("../config.php")) { include "../config.php"; } if (file_exists("./config.php")) { include "./config.php"; } $strings = array(); include get_language_file("../common/lang"); $modules = array(); if (file_exists("../cacher/index.php")) { $modules["cacher"] = _T("Cacher"); } if (file_exists("../coverager/index.php")) { $modules["coverager"] = _T("Coverager"); } if (file_exists("../diagnosis/index.php")) { $modules["diagnosis"] = _T("Diagnosis"); } header("Cache-Control: no-cache, must-revalidate"); header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); header("Content-Type: text/html; " . $GLOBALS['config']['charset']); header("Content-Language: " . $GLOBALS['config']['lang']); ?> xcache-3.1.0/htdocs/common/footer.tpl.php0000644000175000010010000000117112157744742016544 0ustar mOoNone xcache-3.1.0/htdocs/common/header.tpl.php0000644000175000010010000000235512157744742016503 0ustar mOoNone <?php echo sprintf("XCache %s", $xcache_version = defined('XCACHE_VERSION') ? XCACHE_VERSION : ''); ?> - <?php echo ucfirst($GLOBALS['module']); ?>
 
xcache-3.1.0/htdocs/common/lang/0000755000175000010010000000000012206607315014645 5ustar mOoNonexcache-3.1.0/htdocs/common/lang/en.php0000644000175000010010000000010012157744741015761 0ustar mOoNone "帮助文档", "INI Reference" => "INI 参考", "Get Support" => "获取支持", "Discusson" => "讨论", "Cacher" => "缓存器", "Coverager" => "代码覆盖查看器", "Diagnosis" => "诊断", ); xcache-3.1.0/htdocs/common/lang/zh-simplified.po0000644000175000010010000000114512206607315017752 0ustar mOoNonemsgid "" msgstr "" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-07-08 14:41+0800\n" "Language: zh\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: common.php:47 msgid "Document" msgstr "帮助文档" #: common.php:48 msgid "INI Reference" msgstr "INI 参考" #: common.php:49 msgid "Get Support" msgstr "获取支持" #: common.php:50 msgid "Discusson" msgstr "讨论" #: common.php:267 msgid "Cacher" msgstr "缓存器" #: common.php:270 msgid "Coverager" msgstr "代码覆盖查看器" #: common.php:273 msgid "Diagnosis" msgstr "诊断" xcache-3.1.0/htdocs/common/lang/zh-traditional.php0000644000175000010010000000045712157744741020327 0ustar mOoNone "幫助文檔", "INI Reference" => "INI 參考", "Get Support" => "獲取支持", "Discusson" => "討論", "Cacher" => "快取器", "Coverager" => "代码覆盖查看器", "Diagnosis" => "診斷", ); xcache-3.1.0/htdocs/common/lang/zh-traditional.po0000644000175000010010000000115012206607315020133 0ustar mOoNonemsgid "" msgstr "" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-07-08 14:41+0800\n" "Language: zh_TW\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: common.php:47 msgid "Document" msgstr "幫助文檔" #: common.php:48 msgid "INI Reference" msgstr "INI 參考" #: common.php:49 msgid "Get Support" msgstr "獲取支持" #: common.php:50 msgid "Discusson" msgstr "討論" #: common.php:267 msgid "Cacher" msgstr "快取器" #: common.php:270 msgid "Coverager" msgstr "代码覆盖查看器" #: common.php:273 msgid "Diagnosis" msgstr "診斷" xcache-3.1.0/htdocs/common/tablesort.js0000644000175000010010000000301212157744742016270 0ustar mOoNonevar sort_column; var prev_span = null; function get_inner_text(el) { if((typeof el == 'string')||(typeof el == 'undefined')) return el; if(el.innerText) return el.innerText; else { var str = ""; var cs = el.childNodes; var l = cs.length; for (var i=0;iM3.╗qޏmk+ݱoZ)xHٽ\@{Pm=whMk?Rw̢lR;Y%,%X]jK5@Zur9D g N-s {OZ霴LT9dA dFuNQԓ<ҌiOH_mM'{Y$Щ$sLc|?_Y`ѻXz3^-oٷPR-klA pHYs+DIDATx^] xU~6Inh XRMvPĂ13zeq;0:x FD@DևUYeP(Z(Жii2w`ٓ.9] \r$#2\n0~"ª<5͡&kw{|탦Z{; ZYḛe&kBAJ\/3vg"|9׺Ԗ#W e PVV@.h܈Ԁ~qxj@[\' ."Xz:5[׶|u3Vh%&BWs"o`@d'͸QfA!y=.oK{Z%eN#.C#OpBO!?/l0jJBh|'ɜfpjKαF[B&}t;wIM1"e)ʸIt!ȝj5^(WNrR4)tׯ"=| `ONKjwn76bݮk]!-;ouQaJm1Pd0\VdyN $ʃ8edaIjf1w}!QN!"X;{ ڲH^Hveq]-ýb~2._~v FWu:uCH "MZI.W )a42ڐ,,<CJR9 }O#0鎍$=/*bƨ?! ͈o RN h TķDG8ك@sq.^*r ֩,:FzVJVy!ett2rK}KA<&\UHWe=Cd] cOZÂѭsnͷ|s( vha+mY&yop؄lud5/! +فfܳvi}{ \nཱུ? "Da?GZGJa74t1ȇC\\e]J^EN ]%R3eo įuTpzu Q,qy~.rܟe7g-'KFܦh0h<E)BCǐ}%rHXC6zҲn;tFrD5口n›Faj #TēѨA0)ȩGv^.]# i6V FBӆAz~n $52u_ێ qgZ.d;%P)m#wFkL,P;te\'ڤgJ%j*!a3.Sydc*ۘaDlﯫcI9^9)p;7|2 @^o._tb6QGIKeDxbmDۡ#iƊ[ӳ)VU|@_?[6;Q~6T+h8J:HU{?>0f h c!1diWoar̉41 )m W'0 gzz:Y ™%4 !Ct}{ZJnOkY~1$9vmn$2ќhq+">ĺM$庶nY 筥[E1v5o*ӈ,, vgkg~ }`^?7ygm)U0:GW-}*903חo%ppl e9u_baiv8"󦱅|zIx )5yKUY$ԯgx4 6A-|qO13E!$xũ 6aٽ8:X.mBddU!-<($BZ܂b!7ѐbfIcFkǫ~IBo.ZRL`l/uo wI9OO7$ N(Pρk筼JHS`hp9g˄;67'X_t >L7} VN`WG{a 6c>;S I6f,^k7.WUJ2aьhKWzt6:.om0vci6 6[c茩Ui?+P&%>#IJ^,hk0yҳ>./oioES\{ÿsGmpvaoe' wM&yXүR&9Di,o)7dcYDVWWlde.2,XrfQ=?aS7IJ]ZC%IBmfCqVEPW2]YA+O8$xn iL`3coX!?XXP̫N|hdv8'sPX& Ro| Aki򡯣-WpyܸvѫCKܚubehm,XVXto0qh/ Z!e,m#9'R@rH[f`/8\:*}r?1w_zvh%rN 4K`βaZ{,jRYB-*yt=.Y'~mcd s3e7V۬S0r;VcEO⳹=1 7)T>L}J %;ҝ %#ŗ[ֆ7,Y!>RM ĺ=p"-zQXaqBZ̾U E@\$2Y2iuZtiӌZVySJĦ'Jٚ !{1_\Oڜf2$V/9 x Z-qLTmtfWm($۠).KjYxKtVsܳ#IGN.~r.ϦK8p* 3ۜX3 ^PY^J zoj\0eԃؽ=a};cBrO?7G ?\qlfTNJq0,p$n75XZZ>4<oP }Յ=gቡkx?&E.ö/V ;+ֳ. I{ȸ V\MM6RΕ ׷h39t;7/dx1<9LGS"t$4'gS@6f1 _ydf1U}Vm)$1ck]~wn^馵';頑 sߦkCB*kH?2$Ǣ7y=f8C}Y󡲗%!Uh$ȡYŖ-D\) w 4{Rs^~wvZ;ao7Q/R\dطanBFR'R2/OӅBHg)zH J}[o5 s[R-!5τ /Ob3h DctA!M33RN ^z/{w2.x.ΔNۙFNz6~[D=!GE᝔Ȓ-p+ޝM/ ?khQDߝKSP6YPJȕ8s mZP/ $.KWn/8w^8ׯ9Ǎ'1iG&'?$3P{zwMģ˿h׃ GY$V?x9oYaoܴ!WH+P:u/yj9EIENDB`xcache-3.1.0/htdocs/config.default.php0000644000175000010010000000065112157744742016052 0ustar mOoNone
{$percent}
EOS; } function dir_head() { global $cycle; $cycle = new Cycle('class="col1"', 'class="col2"'); $l_dir = _T("Directory"); $l_per = _T("Percent"); $l_hit = _T("Hits"); $l_lns = _T("Lines"); $l_tds = _T("TODO"); return << {$l_dir}{$l_per}{$l_hit}{$l_lns}{$l_tds} EOS; } function dir_row($info, $srcdir) { global $cycle; if ($info['files'] || $info['todos']) { $srcdir .= DIRECTORY_SEPARATOR; $c = $cycle->next(); $srcdir_html = htmlspecialchars($srcdir); $todos = number_format($info['todos']); if ($info['total']) { $srcdir_url = urlencode($srcdir); $hits = number_format($info['hits']); $total = number_format($info['total']); calc_percent($info, $percent, $class); $bar = bar($percent, $class); return << {$srcdir_html} $bar {$hits} {$total} {$todos} EOS; } else { return << {$srcdir_html} {$todos} EOS; } } } function dir_foot() { return << EOS; } function file_head() { global $cycle; $cycle = new Cycle('class="col1"', 'class="col2"'); $l_fil = _T("File"); $l_per = _T("Percent"); $l_hit = _T("Hits"); $l_lns = _T("Lines"); return << {$l_fil}{$l_per}{$l_hit}{$l_lns} EOS; } function file_row($info, $srcfile) { global $cycle; $c = $cycle->next(); $srcfile_html = htmlspecialchars($srcfile); $total = number_format($info['total']); if ($info['total']) { $hits = number_format($info['hits']); $srcfile_url = urlencode($srcfile); calc_percent($info, $percent, $class); $bar = bar($percent, $class); return << {$srcfile_html} $bar {$hits} {$total} EOS; } else { return << {$srcfile_html} {$total} EOS; } } function file_foot() { return << EOS; } $l_root = _T("root"); if ($action == 'dir') { if (function_exists('ob_filter_path_nicer')) { ob_start('ob_filter_path_nicer'); } $path_html = htmlspecialchars($path); echo << $l_root $path
EOS; echo dir_head($dirinfo); echo dir_row($dirinfo, $path); echo dir_foot($dirinfo); if ($dirinfo['subdirs']) { echo dir_head(); foreach ($dirinfo['subdirs'] as $srcdir => $info) { echo dir_row($info, $srcdir); } echo dir_foot(); } if ($dirinfo['files']) { echo file_head(); foreach ($dirinfo['files'] as $srcfile => $info) { echo file_row($info, $srcfile); } echo file_foot(); } } else if ($action == 'file') { if (function_exists('ob_filter_path_nicer')) { ob_start('ob_filter_path_nicer'); } $dir_url = urlencode($dir); $dir_html = htmlspecialchars($dir); echo << $l_root {$dir_html}/{$filename}
EOS; echo file_head(); echo file_row($fileinfo, $path); echo file_foot(); if ($tplfile) { $tplfile_html = htmlspecialchars($tplfile); echo << {$tplfile_html}
EOS; } if (function_exists('ob_filter_path_nicer')) { ob_end_flush(); } echo <<
    {$filecov}
EOS; if ($tplfile) { echo <<{$tplfile}
    {$tplcov}
EOS; } } else { $error_html = htmlspecialchars($error); echo <<{$error_html} EOS; } ?> xcache-3.1.0/htdocs/coverager/index.php0000644000175000010010000001741712157744742016256 0ustar mOoNonedatadir = ini_get('xcache.coveragedump_directory'); global $config; foreach (array('charset', 'include_paths', 'exclude_paths', 'syntax_higlight', 'use_cache', 'datadir', 'lang') as $k) { if (isset($config[$k])) { $this->{$k} = $config[$k]; } } $this->datadir = preg_replace('!/$!', '', $this->datadir); $this->datadir_len = strlen($this->datadir); $this->path = isset($_GET['path']) ? $_GET['path'] : ''; $this->path = preg_replace('!\.{2,}!', '.', $this->path); $qsep = preg_quote(DIRECTORY_SEPARATOR, '!'); $this->path = preg_replace("![\\\\$qsep]{2,}!", DIRECTORY_SEPARATOR, $this->path); $this->path = preg_replace("!$qsep$!", '', $this->path); if ($this->path == '/') { $this->path = ''; } $this->outpath = $this->datadir . $this->path; } function main() { $path = $this->path; if (is_dir($this->outpath)) { $action = 'dir'; $prefix_len = strlen($path) + 1; $dirinfo = $this->loadDir($this->outpath); if (!$this->use_cache) { ksort($dirinfo['subdirs']); ksort($dirinfo['files']); } } else if (is_file($this->outpath . ".pcov")) { $action = 'file'; $dir = dirname($path); $filename = basename($path); $fileinfo = $this->loadCov($this->outpath . ".pcov"); $lines = file($path); // fix the tabs not in the middle foreach ($lines as $l => $line) { if (preg_match('!^(\\t*)([^\\t]+\\t.*)$!s', $line, $m)) { $lines[$l] = $m[1]; $chunks = explode("\t", $m[2]); for ($i = 0, $c = count($chunks) - 1; $i < $c; $i ++) { $lines[$l] .= $chunks[$i] . str_repeat(" ", 4 - (strlen($chunks[$i]) % 4)); } $lines[$l] .= $chunks[$c]; } } if ($this->syntax_higlight) { $source = implode('', $lines); ob_start(); highlight_string($source); $lines = str_replace("\n", "", ob_get_clean()); $lines = str_replace('', '', $lines); $lines = str_replace('', '', $lines); $lines = preg_replace('(^]*>|$)', '', $lines); $lines = explode('
', $lines); $last = array_pop($lines); $lines[count($lines) - 1] .= $last; $filecov = sprint_cov($fileinfo['cov'], $lines, false); unset($source); } else { $filecov = sprint_cov($fileinfo['cov'], $lines); } list($tplfile, $tpllines, $tplcov) = $this->loadTplCov($fileinfo['cov'], substr($this->outpath, $this->datadir_len)); if ($tplfile) { $tplcov = sprint_cov($tplcov, $tpllines); unset($tpllines); } } else if (!$this->datadir) { $action = 'error'; $error = 'require `xcache.coveragedump_directory` in ini or `$datadir` in config to be set'; } else { $action = 'error'; $error = "no data"; } global $config; include "coverager.tpl.php"; } function loadDir($outdir, $addtodo = null) { if ($this->use_cache) { $cachefile = $outdir . "/.pcovcache"; if (file_exists($cachefile)) { return unserialize(file_get_contents($cachefile)); } } $srcdir = substr($outdir, $this->datadir_len); $total = $hits = $todos = 0; $files = array(); $subdirs = array(); if (!isset($addtodo)) { if ($this->include_paths) { foreach ($this->include_paths as $p) { if (strncmp($p, $srcdir, strlen($p)) == 0) { $addtodo = true; break; } } } } if ($addtodo) { if ($this->exclude_paths) { foreach ($this->exclude_paths as $p) { if (strncmp($p, $srcdir, strlen($p)) == 0) { $addtodo = false; break; } } } } foreach (glob($outdir . "/*") as $outfile) { if (is_dir($outfile)) { $info = $this->loadDir($outfile, $addtodo); $srcfile = substr($outfile, $this->datadir_len); $subdirs += $info['subdirs']; $total += $info['total']; $hits += $info['hits']; if ($addtodo === true) { $todos += $info['todos']; } unset($info['subdirs']); $subdirs[$srcfile] = $info; } else if (substr($outfile, -5) == ".pcov") { // pass $info = $this->loadFile($outfile); $total += $info['total']; $hits += $info['hits']; $srcfile = substr($outfile, $this->datadir_len, -5); $files[$srcfile] = $info; } else { continue; } } if ($addtodo === true) { foreach (glob($srcdir . "/*") as $srcfile) { if (!isset($files[$srcfile]) && is_file($srcfile)) { $files[$srcfile] = array('total' => 0, 'hits' => 0); $todos ++; } else if (!isset($subdirs[$srcfile]) && is_dir($srcfile)) { $subdirs[$srcfile] = array('total' => 0, 'hits' => 0, 'todos' => 1, 'files' => 0, 'subdirs' => array()); $todos ++; } } } if ($this->use_cache) { ksort($subdirs); ksort($files); } $info = array( 'total' => $total, 'hits' => $hits, 'todos' => $todos, 'files' => $files, 'subdirs' => $subdirs, ); if ($this->use_cache) { $fp = fopen($cachefile, "wb"); fwrite($fp, serialize($info)); fclose($fp); } return $info; } function loadFile($file) { if ($this->use_cache) { $cachefile = $file . "cache"; if (file_exists($cachefile)) { return unserialize(file_get_contents($cachefile)); } } $info = $this->loadCov($file); //, $lines); unset($info['cov']); if ($this->use_cache) { $fp = fopen($cachefile, "wb"); fwrite($fp, serialize($info)); fclose($fp); } return $info; } function loadCov($file)//, $lines) { $total = $hits = 0; $cov = xcache_coverager_decode(file_get_contents($file)); return array('total' => count($cov) - 1, 'hits' => $cov[0], 'cov' => $cov); } function loadTplCov($cov, $ctpl) { $tplinfofile = $ctpl . '.phpinfo'; if (!file_exists($tplinfofile)) { return; } $tplinfo = unserialize(file_get_contents($tplinfofile)); if (!isset($tplinfo['sourceFile'])) { return; } $tplfile = $tplinfo['sourceFile']; if (!isset($tplinfo['lineMap']) || !count($tplinfo['lineMap'])) { return; } $tpllines = file($tplfile); $dline = 0; $sline = 0; $tplcov = array(); foreach ($cov as $line => $times) { // find nearest line while ($dline < $line) { if ((list($dline, $sline) = each($tplinfo['lineMap'])) === false) { break 2; } } $tplcov[$sline] = $times; } return array($tplfile, $tpllines, $tplcov); } } function sprint_cov($cov, $lines, $encode = true) { $lastattr = null; foreach ($lines as $l => $line) { $offs = $l + 1; if ($encode) { $line = str_replace("\n", "", htmlspecialchars($line)); } else if ($line !== "") { if (substr($line, 0, 7) == '') { $lastattr = null; $line = substr($line, 7); } else if (isset($lastattr)) { $line = $lastattr . $line; } if (preg_match('!(]+>|)[^<>]*$!', $line, $m)) { if ($m[1] == '') { $lastattr = null; } else { $line .= ''; $lastattr = $m[1]; } } } if (isset($cov[$offs])) { $lines[$l] = sprintf("
  •  %s\t%s\n
  • " , $cov[$offs] ? '' : 'No' , $cov[$offs] , $line); } else { $lines[$l] = "
  • \t$line\n
  • "; } } return implode('', $lines); } if (!function_exists('xcache_coverager_decode')) { function xcache_coverager_decode($bytes) { $bytes = unpack('l*', $bytes); $i = 1; if ($bytes[$i ++] != 0x564f4350) { return null; } $end = count($bytes); $cov = array(); for (/* empty*/; $i <= $end; $i += 2) { $hits = $bytes[$i + 1]; $cov[$bytes[$i]] = $hits <= 0 ? 0 : $hits; } return $cov; } } $app = new XcacheCoverageViewer(); $app->main(); ?> xcache-3.1.0/htdocs/coverager/lang/0000755000175000010010000000000012206607315015332 5ustar mOoNonexcache-3.1.0/htdocs/coverager/lang/en.php0000644000175000010010000000010012157744742016447 0ustar mOoNone "目录", "Percent" => "覆盖率", "Hits" => "命中", "Lines" => "行数", "TODO" => "闲置文件", "File" => "文件", "root" => "开始", ); xcache-3.1.0/htdocs/coverager/lang/zh-simplified.po0000644000175000010010000000124112206607315020434 0ustar mOoNonemsgid "" msgstr "" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-07-08 14:41+0800\n" "Language: zh\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: coverager.tpl.php:37 msgid "Directory" msgstr "目录" #: coverager.tpl.php:38 coverager.tpl.php:100 msgid "Percent" msgstr "覆盖率" #: coverager.tpl.php:39 coverager.tpl.php:101 msgid "Hits" msgstr "命中" #: coverager.tpl.php:40 coverager.tpl.php:102 msgid "Lines" msgstr "行数" #: coverager.tpl.php:41 msgid "TODO" msgstr "闲置文件" #: coverager.tpl.php:99 msgid "File" msgstr "文件" #: coverager.tpl.php:151 msgid "root" msgstr "开始" xcache-3.1.0/htdocs/coverager/lang/zh-traditional.php0000644000175000010010000000010012157744742020776 0ustar mOoNone
    xcache-3.1.0/htdocs/diagnosis/index.php0000644000175000010010000003023512157744742016252 0ustar mOoNone $item); } // }}} function result($type, $result, $suggestion = "") // {{{ { global $notes, $activeNote; $notes[] = array( 'type' => $type , 'result' => ($type != 'skipped' && !$suggestion ? "OK. " : "") . $result , 'suggestion' => $suggestion ) + $activeNote; } // }}} function getCacheInfos() // {{{ { $phpCacheCount = xcache_count(XC_TYPE_PHP); $varCacheCount = xcache_count(XC_TYPE_VAR); $cacheInfos = array(); for ($i = 0; $i < $phpCacheCount; $i ++) { $cacheInfo = xcache_info(XC_TYPE_PHP, $i); $cacheInfo['type'] = XC_TYPE_PHP; $cacheInfos[] = $cacheInfo; } for ($i = 0; $i < $varCacheCount; $i ++) { $cacheInfo = xcache_info(XC_TYPE_VAR, $i); $cacheInfo['type'] = XC_TYPE_VAR; $cacheInfos[] = $cacheInfo; } return $cacheInfos; } // }}} function getIniFileInfo() // {{{ { ob_start(); phpinfo(INFO_GENERAL); $info = ob_get_clean(); ob_start(); if (preg_match_all("![^<]*]*>[^<]*(?:Configuration|ini|Server API)[^<]*[^<]*]*>[^<]*[^<]*!s", $info, $m)) { $iniInfo = '' . implode('', $m[0]) . '
    '; } else { $iniInfo = ''; } $loadedIni = ''; $iniDirectory = ''; if (preg_match('!(.*?\\.ini)!', $info, $m)) { $loadedIni = trim($m[1]); } else if (preg_match('!Configuration File \\(php.ini\\) Path *([^<]+)!', $info, $m)) { $iniDirectory = trim($m[1]); } return array($loadedIni, $iniDirectory, $iniInfo); } // }}} $xcacheLoaded = extension_loaded('XCache'); checking(_T("XCache extension")); // {{{ if (!$xcacheLoaded) { list($loadedIni, $iniDirectory, $iniInfo) = getIniFileInfo(); if ($loadedIni) { echo sprintf(_T("Add extension=xcache.so (or xcache.dll) in %s"), $loadedIni); } else if ($iniDirectory) { echo sprintf(_T("Please put a php.ini in %s and add extension=xcache.so (or xcache.dll) in it"), $iniDirectory); } else { echo _T("Cannot detect php.ini location"); } echo " ", _T("(See above)"); result(N_("error"), _T('Not loaded'), ob_get_clean()); } else { result(N_("info"), _T('Loaded')); } // }}} if ($xcacheLoaded) { // {{{ load XCache summary $cacheInfos = getCacheInfos(); $ooms = 0; $errors = 0; $disabled = 0; $compiling = 0; $readonlyProtection = false; $phpCacheCount = xcache_count(XC_TYPE_PHP); $phpCached = 0; $varCached = 0; foreach ($cacheInfos as $cacheInfo) { $ooms += $cacheInfo['ooms']; $errors += $cacheInfo['errors']; $disabled += $cacheInfo['disabled'] ? 1 : 0; if ($cacheInfo['type'] == XC_TYPE_PHP) { $compiling += $cacheInfo['compiling'] ? 1 : 0; $phpCached += $cacheInfo['cached']; } if ($cacheInfo['type'] == XC_TYPE_VAR && $cacheInfo['cached']) { $varCached += $cacheInfo['cached']; } if ($cacheInfo['can_readonly']) { $readonlyProtection = true; } } } // }}} checking(_T("Enabling PHP Cacher")); // {{{ if (!$xcacheLoaded) { result(N_("skipped"), "XCache not loaded"); } else if (!ini_get("xcache.size")) { result(N_("error") , _T("Not enabled") , _T("Your PHP pages is not accelerated by XCache. Set xcache.size to non-zero, set xcache.cacher = On") ); } else if (!$phpCached) { result(N_("error") , _T("No php script cached") , _T("Your PHP pages is not accelerated by XCache. Set xcache.cacher = On") ); } else { result(N_("info"), _T('Enabled')); } // }}} checking(_T("PHP Compile Time Error")); // {{{ if (!$xcacheLoaded) { result(N_("skipped"), "XCache not loaded"); } else if (!$phpCacheCount) { result(N_("skipped"), "XCache PHP cacher not enabled"); } else if ($errors) { result(N_("warning") , _T("Error happened when compiling one or some of your PHP code") , _T("PHP code failed to be compiled cannot be cached. This usually means there was syntax error in your PHP code. Enable PHP error_log to see what parser error is it, fix your code. This warning won't go away until PHP is restarted") ); } else { result(N_("info"), _T('No error happened')); } // }}} checking(_T("Busy Compiling")); // {{{ if (!$xcacheLoaded) { result(N_("skipped"), "XCache not loaded"); } else if (!$phpCacheCount) { result(N_("skipped"), "XCache PHP cacher not enabled"); } else if ($compiling) { result(N_("warning") , _T("Cache marked as busy for compiling") , _T("It's ok if this status don't stay for long. Otherwise, it could be a sign of PHP crash/coredump, report to XCache devs") ); } else { result(N_("info"), _T('Idle')); } // }}} checking(_T("Enabling VAR Cacher")); // {{{ if (!$xcacheLoaded) { result(N_("skipped"), "XCache not loaded"); } else if (!ini_get("xcache.var_size")) { result(N_("warning") , _T("Not enabled") , _T("PHP code that use XCache caching backend have to use other caching backend instead. Set xcache.var_size to non-zero if you have any PHP code that can use XCache Data Caching API") ); } else { result(N_("info"), _T('Enabled')); checking(_T("Using VAR Cacher")); // {{{ if (!$varCached) { result(N_("warning") , _T("No variable data cached") , _T("Var Cacher won't work simply by enabling it." . " PHP code must call XCache APIs like xcache_set() to use it as cache backend. 3rd party web apps may come with XCache support, config it to use XCache as caching backend") ); } else { result(N_("info"), _T('Cache in use')); } // }}} } // }}} checking(_T("Cache Size")); // {{{ if (!$xcacheLoaded) { result(N_("skipped"), "XCache not loaded"); } else if ($ooms) { result(N_("warning") , _T("Out of memory happened when trying to write to cache") , _T("Increase xcache.size and/or xcache.var_size") ); } else { result(N_("info"), _T('Enough')); } // }}} checking(_T("Hash Slots")); // {{{ if (!$xcacheLoaded) { result(N_("skipped"), "XCache not loaded"); } else { $slotsTooBig = null; $slotsTooSmall = null; foreach ($cacheInfos as $cacheInfo) { if ($cacheInfo['size'] < '1024000' && $cacheInfo['slots'] >= '8192') { $slotsTooBig = $cacheInfo['type']; break; } if ($cacheInfo['slots'] < $cacheInfo['cached'] / 2) { $slotsTooSmall = $cacheInfo['type']; break; } } if (isset($slotsTooBig)) { $prefix = $slotsTooBig == XC_TYPE_PHP ? '' : 'var_'; result(N_("warning") , _T("Slots value too big") , sprintf(_T("A very small value is set to %s value and leave %s value is too big.\n" . "Decrease %s if small cache is really what you want"), "xcache.{$prefix}size", "xcache.{$prefix}slots", "xcache.{$prefix}slots") ); } else if (isset($slotsTooSmall)) { $prefix = $slotsTooSmall == XC_TYPE_PHP ? '' : 'var_'; result(N_("warning") , _T("Slots value too small") , sprintf(_T("So many item are cached. Increase %s to a more proper value"), "xcache.{$prefix}slots") ); } else { result(N_("info"), _T('Looks good')); } } // }}} checking(_T("Cache Status")); // {{{ if (!$xcacheLoaded) { result(N_("skipped"), "XCache not loaded"); } else if ($disabled) { result(N_("warning") , _T("At least one of the caches is disabled. ") , _T("Enable the cache.") . (ini_get("xcache.crash_on_coredump") ? " " . _T("It was disabled by PHP crash/coredump handler or you disabled it manually.") : _T('You disabled it manually.')) . (ini_get("xcache.crash_on_coredump") ? " " . _T("If it was caused by PHP crash/coredump, report to XCache devs") : "") ); } else { result(N_("info"), _T('Idle')); } // }}} checking(_T("Coredump Directory")); // {{{ if (!$xcacheLoaded) { result(N_("skipped"), "XCache not loaded"); } else if (!ini_get("xcache.coredump_directory")) { result(N_("info") , _T("Not enabled") , _T("Enable coredump to save debugging information in case when PHP crash. It can also be enabled in other module like php-fpm beside XCache") ); } else if (ini_get("xcache.coredump_directory")) { $coreDir = ini_get("xcache.coredump_directory"); if (substr($coreDir, -1) != DIRECTORY_SEPARATOR) { $coreDir .= DIRECTORY_SEPARATOR; } $coreFiles = glob($coreDir . "core*"); if ($coreFiles) { result(N_("error") , _T("Core files found:\n") . implode("\n", $coreFiles) , _T("Disable XCache PHP Cacher (set xcache.size=0), remove the core file(s), then restart PHP. If core file appears again, report call stack backtrace in the core to XCache devs") ); } else { result(N_("info") , _T("Enabled") , sprintf(_T("You can see core files if PHP crash in %s if PHP crash"), ini_get("xcache.coredump_directory")) ); } } // }}} checking(_T("Readonly Protection")); // {{{ if (!$xcacheLoaded) { result(N_("skipped"), "XCache not loaded"); } else if (ini_get("xcache.readonly_protection") && !$readonlyProtection) { result(N_("error") , _T("Set to enabled but not available") , _T("Use xcache.mmap_path other than /dev/zero") ); } else { result(N_("info") , $readonlyProtection ? _T("Enabled") : _T("Disabled") , _T("Enable readonly_protection == --performance & ++stability. " . "Disable readonly_protection == ++performance & --stability") ); } // }}} checking(_T("XCache modules")); // {{{ if (!$xcacheLoaded) { result(N_("skipped"), "XCache not loaded"); } else { $xcacheModules = explode(" ", XCACHE_MODULES); $unexpectedModules = array_intersect($xcacheModules, array("coverager", "disassembler")); if ($unexpectedModules) { result(N_("warning") , implode("\n", $unexpectedModules) , _T("Acceptable. Module(s) listed are built into XCache but not for production server.\n" . "Leave it as is if you're feeling good.\n" . "Re-configure XCache with the module(s) disabled if you're strict with server security.") ); } else { result(N_("info"), _T('Idle')); } } // }}} checking(_T("XCache test setting")); // {{{ if (!$xcacheLoaded) { result(N_("skipped"), "XCache not loaded"); } else if ((int) ini_get('xcache.test') == 1) { result(N_("warning") , _T("Enabled") , _T("xcache.test is for testing only, not for server. set it to off") ); } else { result(N_("info"), _T('Disabled')); } // }}} checking(_T("PHP Version")); // {{{ $phpVersion = phpversion(); $unstablePhpVersionReason = null; foreach ($knownUnstablePhpVersions as $knownUnstablePhpVersion) { list($compareOp, $unstablePhpVersion, $reason) = $knownUnstablePhpVersion; if ($compareOp) { $isUnstable = version_compare($phpVersion, $unstablePhpVersion, $compareOp); } else { $isUnstable = substr($phpVersion, 0, strlen($unstablePhpVersion)) == $unstablePhpVersion; } if ($isUnstable) { $unstablePhpVersionReason = $reason; break; } } if ($unstablePhpVersionReason) { result(N_("error") , _T("The version of PHP you're using is known to be unstable: ") . $unstablePhpVersionReason , _T("Upgrade to new version of PHP")); } else { result(N_("info"), _T("Looks good")); } // }}} checking(_T("Extension Compatibility")); // {{{ $loadedZendExtensions = get_loaded_extensions(true); $extensionGood = true; if (array_search("Zend Optimizer", $loadedZendExtensions) !== false) { result(N_("info") , _T("Zend Optimizer loaded") , _T("Optimizer feature of 'Zend Optimizer' is disabled by XCache due to compatibility reason; the Loader of it is still available, encoded files are still supported") ); $extensionGood = false; } if (array_search("the ionCube PHP Loader", $loadedZendExtensions) !== false) { result(N_("info") , _T("the ionCube PHP Loader loaded") , _T("Compatibility with this the ionCube PHp Loader' is taken care of; But in case if there's any problem, report to ionCube team and/or XCache devs") ); $extensionGood = false; } if (!$extensionGood) { result(N_("info"), _T("Looks good")); } // }}} checking(_T("SAPI Compatibility")); // {{{ if (php_sapi_name() == "cgi" || php_sapi_name() == "cgi-fcgi" && !isset($_SERVER["FCGI_ROLE"])) { result(N_("error"), _T("CGI is not supported"), _T("Use FastCGI or FPM instead")); } else if (php_sapi_name() == "cgi-fcgi" && isset($_SERVER["FCGI_ROLE"]) && (int) getenv("PHP_FCGI_CHILDREN") < 1) { result(N_("error") , "PHP_FCGI_CHILDREN<1" , _T("PHP_FCGI_CHILDREN should be >= 1 and use 1 group of parent/childs model. See http://xcache.lighttpd.net/wiki/Faq")); } else { result(N_("info"), _T("Looks good")); } // }}} include "./diagnosis.tpl.php"; xcache-3.1.0/htdocs/diagnosis/lang/0000755000175000010010000000000012206607316015336 5ustar mOoNonexcache-3.1.0/htdocs/diagnosis/lang/en.php0000644000175000010010000000010012157744742016452 0ustar mOoNone= 1 and use 1 group of parent/childs model. See " "http://xcache.lighttpd.net/wiki/Faq" msgstr "" xcache-3.1.0/htdocs/diagnosis/lang/zh-simplified.php0000644000175000010010000001770612157744742020640 0ustar mOoNone "诊断结果", "Item" => "项目", "Level" => "级别", "Result" => "结果", "Explanation/Suggestion" => "解释/建议", "XCache extension" => "XCache extension", "Add extension=xcache.so (or xcache.dll) in %s" => "在 %s 增加 extension=xcache.so (或 xcache.dll)", "Please put a php.ini in %s and add extension=xcache.so (or xcache.dll) in it" => "请在 %s 里放个 php.ini 并且在文件内写入 extension=xcache.so (或 xcache.dll)", "Cannot detect php.ini location" => "无法检测 php.ini 位置", "(See above)" => "(参见上面)", "Not loaded" => "未载入", "error" => "错误", "Loaded" => "已载入", "info" => "信息", "Enabling PHP Cacher" => "启用 PHP 缓存器", "skipped" => "跳过", "Not enabled" => "尚未启用", "Your PHP pages is not accelerated by XCache. Set xcache.size to non-zero, set xcache.cacher = On" => "XCache 并未对您的 PHP 网页起到加速作用. 设置 xcache.size 为非 0, 设置 xcache.cacher = On", "No php script cached" => "未缓存任何 PHP 脚本", "Your PHP pages is not accelerated by XCache. Set xcache.cacher = On" => "XCache 并未对您的 PHP 网页起到加速作用. 设置 xcache.cacher = On", "Enabled" => "已启用", "PHP Compile Time Error" => "PHP 编译时错误", "warning" => "警告", "Error happened when compiling one or some of your PHP code" => "至少在编译一个或多个您的 PHP 代码时发生编译错误", "PHP code failed to be compiled cannot be cached. This usually means there was syntax error in your PHP code. Enable PHP error_log to see what parser error is it, fix your code. This warning won't go away until PHP is restarted" => "编译失败的 PHP 代码是无法缓存的. 这通常意味着您的 PHP 代码有语法错误. 请启用 error_log 调查具体错误原因并修复您的代码. 重启 PHP 前这个警告不会消失", "No error happened" => "未发生过错误", "Busy Compiling" => "忙着编译", "Cache marked as busy for compiling" => "编译中, 缓存标记为忙", "It's ok if this status don't stay for long. Otherwise, it could be a sign of PHP crash/coredump, report to XCache devs" => "这个状态如果持续不就则无影响. 否则可能标志着 PHP 曾经发生异常退出, 如果是的话请报告给 XCache 开发组", "Idle" => "空闲", "Enabling VAR Cacher" => "启用 VAR 缓存器", "PHP code that use XCache caching backend have to use other caching backend instead. Set xcache.var_size to non-zero if you have any PHP code that can use XCache Data Caching API" => "支持使用 XCache 作为数据缓存器的 PHP 代码将不得不采用其他缓存器代替. 如果您有代码支持 XCache 缓存 API 的话, 您可以设置 xcache.var_size 为非 0", "Using VAR Cacher" => "使用 VAR 缓存器", "No variable data cached" => "未缓存任何变量数据", "Var Cacher won't work simply by enabling it. PHP code must call XCache APIs like xcache_set() to use it as cache backend. 3rd party web apps may come with XCache support, config it to use XCache as caching backend" => "只启用变量数据缓存器并无法将其利用起来. 必须通过 PHP 代码去调用 XCache API 接口(如 xcache_set() 函数) 将 XCache 作为缓存器. 第三方网页软件可能带有 XCache 支持, 留意其中的设置启用 XCache 作为缓存器", "Cache in use" => "缓存使用中", "Cache Size" => "缓存大小", "Out of memory happened when trying to write to cache" => "存入缓存时发生内存不足", "Increase xcache.size and/or xcache.var_size" => "加大 xcache.size 或 xcache.var_size", "Enough" => "充足", "Hash Slots" => "哈希槽", "Slots value too big" => "哈希槽设定太大", "A very small value is set to %s value and leave %s value is too big.\nDecrease %s if small cache is really what you want" => "设置给 %s 的值很小, 却采用过大的 %s. 如果您的确想要配置占用很少内存的缓存器, 可减少 %s", "Slots value too small" => "哈希槽设定太小", "So many item are cached. Increase %s to a more proper value" => "相当多的项目缓存了. 请适量加大 %s", "Looks good" => "看起来还行", "Cache Status" => "缓存状态", "At least one of the caches is disabled. " => "至少一个缓存器是禁止状态", "Enable the cache." => "启用已禁止的缓存器.", "It was disabled by PHP crash/coredump handler or you disabled it manually." => "可能是在 PHP 异常退出时自动标记为禁止了, 或者您手工禁止了", "You disabled it manually." => "您手工禁止了", "If it was caused by PHP crash/coredump, report to XCache devs" => "如果是由于 PHP 异常退出造成, 请报告给 XCache 开发组", "Coredump Directory" => "Coredump 目录", "Enable coredump to save debugging information in case when PHP crash. It can also be enabled in other module like php-fpm beside XCache" => "启用 coredump 设置. 这样万一发生 PHP 异常退出时可保存调试信息. 这个功能也可以在其他地方启用, 如 php-fpm", "Core files found:\n" => "发现 core 文件:\n", "Disable XCache PHP Cacher (set xcache.size=0), remove the core file(s), then restart PHP. If core file appears again, report call stack backtrace in the core to XCache devs" => "禁止 XCache 缓存器 (设置 xcache.size=0), 删除 Core 文件, 再重启 PHP. 如果不用 XCache 时不出现 Core, 请从 Core 中取得 call stack back trace 信息报告回 XCache 开发组", "You can see core files if PHP crash in %s if PHP crash" => "如果 PHP 异常退出, 您可以在 %s 目录看到 Core 文件", "Readonly Protection" => "只读保护", "Set to enabled but not available" => "设置为启用, 但目前不可用", "Use xcache.mmap_path other than /dev/zero" => "设置 xcache.mmap_path 使用 /dev/zero 以外的值", "Disabled" => "已禁止", "Enable readonly_protection == --performance & ++stability. Disable readonly_protection == ++performance & --stability" => "启用 readonly_protection == --性能 & ++稳定性. 禁用 readonly_protection == ++性能 & --稳定性", "XCache modules" => "XCache 模块", "Acceptable. Module(s) listed are built into XCache but not for production server.\nLeave it as is if you're feeling good.\nRe-configure XCache with the module(s) disabled if you're strict with server security." => "可接受. 以上列出的模块已编译入 XCache, 但这些模块并非用于产业服务器.\n如果您觉得没大碍, 就保持现状.\n如果您对稳定性/安全性要求极其严格, 建议重新编译 XCache 不启用这些模块\n", "XCache test setting" => "XCache 测试设置", "xcache.test is for testing only, not for server. set it to off" => "xcache.test 仅用于开发测试用, 不用于服务器. 将它设置为 off", "PHP Version" => "PHP 版本", "The version of PHP you're using is known to be unstable: " => "您所使用的 PHP 版本, 是众所周知的不稳定版本: ", "Upgrade to new version of PHP" => "升级到更新的 PHP 版本", "Extension Compatibility" => "Extension 兼容性", "Zend Optimizer loaded" => "Zend Optimizer 载入了", "Optimizer feature of 'Zend Optimizer' is disabled by XCache due to compatibility reason; the Loader of it is still available, encoded files are still supported" => "由于兼容性问题, 'Zend Optimizer' 的优化器已被 XCache 禁止; 其加载器依然可用, 可继续使用 Zend 加密的文件", "SAPI Compatibility" => "Extension 兼容性", "CGI is not supported" => "不支持 CGI", "Use FastCGI or FPM instead" => "请改用 FastCGI 或者 FPM", "PHP_FCGI_CHILDREN should be >= 1 and use 1 group of parent/childs model. See http://xcache.lighttpd.net/wiki/Faq" => "PHP_FCGI_CHILDREN 应该设为 >= 1 并且使用 1 组单父多子模型. 参见 http://xcache.lighttpd.net/wiki/Faq", ); xcache-3.1.0/htdocs/diagnosis/lang/zh-simplified.po0000644000175000010010000002621212206607316020445 0ustar mOoNonemsgid "" msgstr "" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-07-08 14:41+0800\n" "Language: zh\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: diagnosis.tpl.php:4 msgid "Diagnosis Result" msgstr "诊断结果" #: diagnosis.tpl.php:8 msgid "Item" msgstr "项目" #: diagnosis.tpl.php:11 msgid "Level" msgstr "级别" #: diagnosis.tpl.php:14 msgid "Result" msgstr "结果" #: diagnosis.tpl.php:17 msgid "Explanation/Suggestion" msgstr "解释/建议" #: index.php:77 msgid "XCache extension" msgstr "XCache extension" #: index.php:81 #, php-format msgid "Add extension=xcache.so (or xcache.dll) in %s" msgstr "在 %s 增加 extension=xcache.so (或 xcache.dll)" #: index.php:84 #, php-format msgid "" "Please put a php.ini in %s and add extension=xcache.so (or xcache.dll) in it" msgstr "" "请在 %s 里放个 php.ini 并且在文件内写入 extension=xcache.so (或 xcache.dll)" #: index.php:87 msgid "Cannot detect php.ini location" msgstr "无法检测 php.ini 位置" #: index.php:89 msgid "(See above)" msgstr "(参见上面)" #: index.php:90 msgid "Not loaded" msgstr "未载入" #: index.php:90 index.php:129 index.php:135 index.php:290 index.php:308 #: index.php:373 index.php:405 index.php:408 msgid "error" msgstr "错误" #: index.php:93 msgid "Loaded" msgstr "已载入" #: index.php:93 index.php:141 index.php:158 index.php:175 index.php:189 #: index.php:200 index.php:216 index.php:252 index.php:269 index.php:278 #: index.php:296 index.php:314 index.php:337 index.php:352 index.php:378 #: index.php:385 index.php:392 index.php:399 index.php:413 msgid "info" msgstr "信息" #: index.php:124 msgid "Enabling PHP Cacher" msgstr "启用 PHP 缓存器" #: index.php:126 index.php:146 index.php:149 index.php:163 index.php:166 #: index.php:180 index.php:207 index.php:221 index.php:258 index.php:275 #: index.php:305 index.php:323 index.php:343 msgid "skipped" msgstr "跳过" #: index.php:130 index.php:184 index.php:279 msgid "Not enabled" msgstr "尚未启用" #: index.php:131 msgid "" "Your PHP pages is not accelerated by XCache. Set xcache.size to non-zero, " "set xcache.cacher = On" msgstr "" "XCache 并未对您的 PHP 网页起到加速作用. 设置 xcache.size 为非 0, 设置 xcache." "cacher = On" #: index.php:136 msgid "No php script cached" msgstr "未缓存任何 PHP 脚本" #: index.php:137 msgid "Your PHP pages is not accelerated by XCache. Set xcache.cacher = On" msgstr "XCache 并未对您的 PHP 网页起到加速作用. 设置 xcache.cacher = On" #: index.php:141 index.php:189 index.php:297 index.php:315 index.php:347 msgid "Enabled" msgstr "已启用" #: index.php:144 msgid "PHP Compile Time Error" msgstr "PHP 编译时错误" #: index.php:152 index.php:169 index.php:183 index.php:193 index.php:210 #: index.php:238 index.php:246 index.php:261 index.php:329 index.php:346 msgid "warning" msgstr "警告" #: index.php:153 msgid "Error happened when compiling one or some of your PHP code" msgstr "至少在编译一个或多个您的 PHP 代码时发生编译错误" #: index.php:154 msgid "" "PHP code failed to be compiled cannot be cached. This usually means there " "was syntax error in your PHP code. Enable PHP error_log to see what parser " "error is it, fix your code. This warning won't go away until PHP is restarted" msgstr "" "编译失败的 PHP 代码是无法缓存的. 这通常意味着您的 PHP 代码有语法错误. 请启用 " "error_log 调查具体错误原因并修复您的代码. 重启 PHP 前这个警告不会消失" #: index.php:158 msgid "No error happened" msgstr "未发生过错误" #: index.php:161 msgid "Busy Compiling" msgstr "忙着编译" #: index.php:170 msgid "Cache marked as busy for compiling" msgstr "编译中, 缓存标记为忙" #: index.php:171 msgid "" "It's ok if this status don't stay for long. Otherwise, it could be a sign of " "PHP crash/coredump, report to XCache devs" msgstr "" "这个状态如果持续不就则无影响. 否则可能标志着 PHP 曾经发生异常退出, 如果是的话" "请报告给 XCache 开发组" #: index.php:175 index.php:269 index.php:337 msgid "Idle" msgstr "空闲" #: index.php:178 msgid "Enabling VAR Cacher" msgstr "启用 VAR 缓存器" #: index.php:185 #, fuzzy msgid "" "PHP code that use XCache caching backend have to use other caching backend " "instead. Set xcache.var_size to non-zero if you have any PHP code that can " "use XCache Data Caching API" msgstr "" "支持使用 XCache 作为数据缓存器的 PHP 代码将不得不采用其他缓存器代替. 如果您有" "代码支持 XCache 缓存 API 的话, 您可以设置 xcache.var_size 为非 0" #: index.php:191 msgid "Using VAR Cacher" msgstr "使用 VAR 缓存器" #: index.php:194 msgid "No variable data cached" msgstr "未缓存任何变量数据" #: index.php:195 msgid "" "Var Cacher won't work simply by enabling it. PHP code must call XCache APIs " "like xcache_set() to use it as cache backend. 3rd party web apps may come " "with XCache support, config it to use XCache as caching backend" msgstr "" "只启用变量数据缓存器并无法将其利用起来. 必须通过 PHP 代码去调用 XCache API 接" "口(如 xcache_set() 函数) 将 XCache 作为缓存器. 第三方网页软件可能带有 XCache " "支持, 留意其中的设置启用 XCache 作为缓存器" #: index.php:200 msgid "Cache in use" msgstr "缓存使用中" #: index.php:205 msgid "Cache Size" msgstr "缓存大小" #: index.php:211 msgid "Out of memory happened when trying to write to cache" msgstr "存入缓存时发生内存不足" #: index.php:212 msgid "Increase xcache.size and/or xcache.var_size" msgstr "加大 xcache.size 或 xcache.var_size" #: index.php:216 msgid "Enough" msgstr "充足" #: index.php:219 msgid "Hash Slots" msgstr "哈希槽" #: index.php:239 msgid "Slots value too big" msgstr "哈希槽设定太大" #: index.php:240 #, php-format msgid "" "A very small value is set to %s value and leave %s value is too big.\n" "Decrease %s if small cache is really what you want" msgstr "" "设置给 %s 的值很小, 却采用过大的 %s. 如果您的确想要配置占用很少内存的缓存器, " "可减少 %s" #: index.php:247 msgid "Slots value too small" msgstr "哈希槽设定太小" #: index.php:248 #, php-format msgid "So many item are cached. Increase %s to a more proper value" msgstr "相当多的项目缓存了. 请适量加大 %s" #: index.php:252 index.php:378 index.php:399 index.php:413 msgid "Looks good" msgstr "看起来还行" #: index.php:256 msgid "Cache Status" msgstr "缓存状态" #: index.php:262 msgid "At least one of the caches is disabled. " msgstr "至少一个缓存器是禁止状态" #: index.php:263 msgid "Enable the cache." msgstr "启用已禁止的缓存器." #: index.php:264 msgid "" "It was disabled by PHP crash/coredump handler or you disabled it manually." msgstr "可能是在 PHP 异常退出时自动标记为禁止了, 或者您手工禁止了" #: index.php:264 msgid "You disabled it manually." msgstr "您手工禁止了" #: index.php:265 msgid "If it was caused by PHP crash/coredump, report to XCache devs" msgstr "如果是由于 PHP 异常退出造成, 请报告给 XCache 开发组" #: index.php:273 msgid "Coredump Directory" msgstr "Coredump 目录" #: index.php:280 msgid "" "Enable coredump to save debugging information in case when PHP crash. It can " "also be enabled in other module like php-fpm beside XCache" msgstr "" "启用 coredump 设置. 这样万一发生 PHP 异常退出时可保存调试信息. 这个功能也可以" "在其他地方启用, 如 php-fpm" #: index.php:291 msgid "Core files found:\n" msgstr "发现 core 文件:\n" #: index.php:292 msgid "" "Disable XCache PHP Cacher (set xcache.size=0), remove the core file(s), then " "restart PHP. If core file appears again, report call stack backtrace in the " "core to XCache devs" msgstr "" "禁止 XCache 缓存器 (设置 xcache.size=0), 删除 Core 文件, 再重启 PHP. 如果不" "用 XCache 时不出现 Core, 请从 Core 中取得 call stack back trace 信息报告回 " "XCache 开发组" #: index.php:298 #, php-format msgid "You can see core files if PHP crash in %s if PHP crash" msgstr "如果 PHP 异常退出, 您可以在 %s 目录看到 Core 文件" #: index.php:303 msgid "Readonly Protection" msgstr "只读保护" #: index.php:309 msgid "Set to enabled but not available" msgstr "设置为启用, 但目前不可用" #: index.php:310 msgid "Use xcache.mmap_path other than /dev/zero" msgstr "设置 xcache.mmap_path 使用 /dev/zero 以外的值" #: index.php:315 index.php:352 msgid "Disabled" msgstr "已禁止" #: index.php:316 msgid "" "Enable readonly_protection == --performance & ++stability. Disable " "readonly_protection == ++performance & --stability" msgstr "" "启用 readonly_protection == --性能 & ++稳定性. 禁用 readonly_protection == +" "+性能 & --稳定性" #: index.php:321 msgid "XCache modules" msgstr "XCache 模块" #: index.php:331 msgid "" "Acceptable. Module(s) listed are built into XCache but not for production " "server.\n" "Leave it as is if you're feeling good.\n" "Re-configure XCache with the module(s) disabled if you're strict with server " "security." msgstr "" "可接受. 以上列出的模块已编译入 XCache, 但这些模块并非用于产业服务器.\n" "如果您觉得没大碍, 就保持现状.\n" "如果您对稳定性/安全性要求极其严格, 建议重新编译 XCache 不启用这些模块\n" #: index.php:341 msgid "XCache test setting" msgstr "XCache 测试设置" #: index.php:348 msgid "xcache.test is for testing only, not for server. set it to off" msgstr "xcache.test 仅用于开发测试用, 不用于服务器. 将它设置为 off" #: index.php:355 msgid "PHP Version" msgstr "PHP 版本" #: index.php:374 msgid "The version of PHP you're using is known to be unstable: " msgstr "您所使用的 PHP 版本, 是众所周知的不稳定版本: " #: index.php:375 msgid "Upgrade to new version of PHP" msgstr "升级到更新的 PHP 版本" #: index.php:381 msgid "Extension Compatibility" msgstr "Extension 兼容性" #: index.php:386 msgid "Zend Optimizer loaded" msgstr "Zend Optimizer 载入了" #: index.php:387 msgid "" "Optimizer feature of 'Zend Optimizer' is disabled by XCache due to " "compatibility reason; the Loader of it is still available, encoded files are " "still supported" msgstr "" "由于兼容性问题, 'Zend Optimizer' 的优化器已被 XCache 禁止; 其加载器依然可用, " "可继续使用 Zend 加密的文件" #: index.php:393 msgid "the ionCube PHP Loader loaded" msgstr "" #: index.php:394 msgid "" "Compatibility with this the ionCube PHp Loader' is taken care of; But in " "case if there's any problem, report to ionCube team and/or XCache devs" msgstr "" #: index.php:402 msgid "SAPI Compatibility" msgstr "Extension 兼容性" #: index.php:405 msgid "CGI is not supported" msgstr "不支持 CGI" #: index.php:405 msgid "Use FastCGI or FPM instead" msgstr "请改用 FastCGI 或者 FPM" #: index.php:410 msgid "" "PHP_FCGI_CHILDREN should be >= 1 and use 1 group of parent/childs model. See " "http://xcache.lighttpd.net/wiki/Faq" msgstr "" "PHP_FCGI_CHILDREN 应该设为 >= 1 并且使用 1 组单父多子模型. 参见 http://" "xcache.lighttpd.net/wiki/Faq" xcache-3.1.0/htdocs/diagnosis/lang/zh-traditional.php0000644000175000010010000000010012157744742021001 0ustar mOoNone= 1 and use 1 group of parent/childs model. See " "http://xcache.lighttpd.net/wiki/Faq" msgstr "" xcache-3.1.0/htdocs/diagnosis/lang/zh-tranditional.php0000644000175000010010000000000012157744742021156 0ustar mOoNonexcache-3.1.0/htdocs/index.php0000644000175000010010000000027112157744742014267 0ustar mOoNone $v) { header("Location: $k/"); break; } xcache-3.1.0/includes.c0000644000175000010010000000015412157744737013141 0ustar mOoNone#include "xcache.h" #include "mod_cacher/xc_cache.h" #include "xcache/xc_utils.h" #include "zend_compile.h" xcache-3.1.0/INSTALL0000644000175000010010000000074712157744740012222 0ustar mOoNone# vim:ts=4:sw=4 Installtion: $ phpize --clean && phpize $ ./configure --help $ CFLAGS='your cflags' ./configure --enable-xcache --enable... $ make $ su # make install (update php.ini, restart php) Reinstall: $ mv config.nice conf $ make distclean && phpize --clean && phpize $ mv conf config.nice $ ./config.nice $ make $ su # make install (update php.ini, restart php) Update php.ini: $ su # cat xcache.ini >> /etc/php.ini # $EDITOR /etc/php.ini xcache-3.1.0/lib/0000755000175000010010000000000012220455231011710 5ustar mOoNonexcache-3.1.0/lib/Decompiler.class.php0000644000175000010010000023244712220455231015624 0ustar mOoNone $value) { $array[] = var_export($key, true) . " => " . (is_scalar($value) ? var_export($value, true) : gettype($value)); if (count($array) >= 5) { $array[] = '...'; break; } } $args[] = 'array(' . implode(', ', $array) . ')'; } else { $args[] = gettype($arg); } } printf("%d: %s::%s(%s)" . PHP_EOL , $stack['line'] , isset($stack['class']) ? $stack['class'] : '' , $stack['function'] , implode(', ', $args) ); } } // }}} function str($code, $indent = '') // {{{ { if (is_array($code)) { $array = array(); foreach ($code as $key => $value) { $array[$key] = str($value, $indent); } return $array; } if (is_object($code)) { $code = foldToCode($code, $indent); return $code->toCode($indent); } return (string) $code; } // }}} function unsetArray(&$array, $name) // {{{ { unset($array[$name]); } // }}} function foldToCode($src, $indent = '') // {{{ wrap or rewrap anything to Decompiler_Code { if (is_array($indent)) { $indent = $indent['indent']; } if (!is_object($src)) { return new Decompiler_Code($src); } if (!method_exists($src, 'toCode')) { var_dump($src); exit('no toCode'); } if (get_class($src) != 'Decompiler_Code') { // rewrap it $src = new Decompiler_Code($src->toCode($indent)); } return $src; } // }}} function value($value, &$EX) // {{{ { $originalValue = xcache_get_special_value($value); if (isset($originalValue)) { if ((xcache_get_type($value) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) { // constant return $GLOBALS['__xcache_decompiler']->stripNamespace($originalValue); } $value = $originalValue; } if (is_a($value, 'Decompiler_Object')) { // use as is } else if (is_array($value)) { $value = new Decompiler_ConstArray($value, $EX); } else { if (isset($EX['value2constant'][$value])) { $value = new Decompiler_Code($EX['value2constant'][$value]); } else { $value = new Decompiler_Value($value); } } return $value; } // }}} function unquoteName_($str, $asVariableName, $indent = '') // {{{ { $str = str($str, $indent); if (preg_match("!^'[\\w_][\\w\\d_\\\\]*'\$!", $str)) { return str_replace('\\\\', '\\', substr($str, 1, -1)); } else if ($asVariableName) { return "{" . $str . "}"; } else { return $str; } } // }}} function unquoteVariableName($str, $indent = '') // {{{ { return unquoteName_($str, true, $indent); } // }}} function unquoteName($str, $indent = '') // {{{ { return unquoteName_($str, false, $indent); } // }}} class Decompiler_Object // {{{ { } // }}} class Decompiler_Value extends Decompiler_Object // {{{ { var $value; function Decompiler_Value($value = null) { $this->value = $value; } function toCode($indent) { $code = var_export($this->value, true); if (gettype($this->value) == 'string') { switch ($this->value) { case "\r": return '"\\r"'; case "\n": return '"\\n"'; case "\r\n": return '"\\r\\n"'; } $code = str_replace("\r\n", '\' . "\\r\\n" . \'', $code); $code = str_replace("\r", '\' . "\\r" . \'', $code); $code = str_replace("\n", '\' . "\\n" . \'', $code); } return $code; } } // }}} class Decompiler_Code extends Decompiler_Object // {{{ { var $src; function Decompiler_Code($src) { if (!assert('isset($src)')) { printBacktrace(); } $this->src = $src; } function toCode($indent) { return $this->src; } } // }}} class Decompiler_Binop extends Decompiler_Code // {{{ { var $opc; var $op1; var $op2; var $parent; function Decompiler_Binop($parent, $op1, $opc, $op2) { $this->parent = &$parent; $this->opc = $opc; $this->op1 = $op1; $this->op2 = $op2; } function toCode($indent) { $opstr = $this->parent->binops[$this->opc]; if (is_a($this->op1, 'Decompiler_TriOp') || is_a($this->op1, 'Decompiler_Binop') && $this->op1->opc != $this->opc) { $op1 = "(" . str($this->op1, $indent) . ")"; } else { $op1 = $this->op1; } if (is_a($this->op2, 'Decompiler_TriOp') || is_a($this->op2, 'Decompiler_Binop') && $this->op2->opc != $this->opc && substr($opstr, -1) != '=') { $op2 = "(" . str($this->op2, $indent) . ")"; } else { $op2 = $this->op2; } if (str($op1) == '0' && ($this->opc == XC_ADD || $this->opc == XC_SUB)) { return $opstr . str($op2, $indent); } return str($op1, $indent) . ' ' . $opstr . ($this->opc == XC_ASSIGN_REF ? '' : ' ') . str($op2, $indent); } } // }}} class Decompiler_TriOp extends Decompiler_Code // {{{ { var $condition; var $trueValue; var $falseValue; function Decompiler_TriOp($condition, $trueValue, $falseValue) { $this->condition = $condition; $this->trueValue = $trueValue; $this->falseValue = $falseValue; } function toCode($indent) { $trueValue = $this->trueValue; if (is_a($this->trueValue, 'Decompiler_TriOp')) { $trueValue = "(" . str($trueValue, $indent) . ")"; } $falseValue = $this->falseValue; if (is_a($this->falseValue, 'Decompiler_TriOp')) { $falseValue = "(" . str($falseValue, $indent) . ")"; } return str($this->condition) . ' ? ' . str($trueValue) . ' : ' . str($falseValue); } } // }}} class Decompiler_Fetch extends Decompiler_Code // {{{ { var $src; var $fetchType; function Decompiler_Fetch($src, $type, $globalSrc) { $this->src = $src; $this->fetchType = $type; $this->globalSrc = $globalSrc; } function toCode($indent) { switch ($this->fetchType) { case ZEND_FETCH_LOCAL: return '$' . $this->src; case ZEND_FETCH_STATIC: if (ZEND_ENGINE_2_3) { // closure local variable? return 'STR' . str($this->src); } else { $EX = array(); return str(value($this->src, $EX)); } die('static fetch cant to string'); case ZEND_FETCH_GLOBAL: case ZEND_FETCH_GLOBAL_LOCK: return $this->globalSrc; default: var_dump($this->fetchType); assert(0); } } } // }}} class Decompiler_Box // {{{ { var $obj; function Decompiler_Box(&$obj) { $this->obj = &$obj; } function toCode($indent) { return $this->obj->toCode($indent); } } // }}} class Decompiler_Dim extends Decompiler_Value // {{{ { var $offsets = array(); var $isLast = false; var $isObject = false; var $assign = null; function toCode($indent) { if (is_a($this->value, 'Decompiler_ListBox')) { $exp = str($this->value->obj->src, $indent); } else { $exp = str($this->value, $indent); } $last = count($this->offsets) - 1; foreach ($this->offsets as $i => $dim) { if ($this->isObject && $i == $last) { $exp .= '->' . unquoteVariableName($dim, $indent); } else { $exp .= '[' . str($dim, $indent) . ']'; } } return $exp; } } // }}} class Decompiler_DimBox extends Decompiler_Box // {{{ { } // }}} class Decompiler_List extends Decompiler_Code // {{{ { var $src; var $dims = array(); var $everLocked = false; function toCode($indent) { if (count($this->dims) == 1 && !$this->everLocked) { $dim = $this->dims[0]; unset($dim->value); $dim->value = $this->src; if (!isset($dim->assign)) { return str($dim, $indent); } return str($this->dims[0]->assign, $indent) . ' = ' . str($dim, $indent); } /* flatten dims */ $assigns = array(); foreach ($this->dims as $dim) { $assign = &$assigns; foreach ($dim->offsets as $offset) { $assign = &$assign[$offset]; } $assign = foldToCode($dim->assign, $indent); } return str($this->toList($assigns)) . ' = ' . str($this->src, $indent); } function toList($assigns) { $keys = array_keys($assigns); if (count($keys) < 2) { $keys[] = 0; } $max = call_user_func_array('max', $keys); $list = 'list('; for ($i = 0; $i <= $max; $i ++) { if ($i) { $list .= ', '; } if (!isset($assigns[$i])) { continue; } if (is_array($assigns[$i])) { $list .= $this->toList($assigns[$i]); } else { $list .= $assigns[$i]; } } return $list . ')'; } } // }}} class Decompiler_ListBox extends Decompiler_Box // {{{ { } // }}} class Decompiler_Array extends Decompiler_Value // {{{ { // emenets function Decompiler_Array() { $this->value = array(); } function toCode($indent) { $subindent = $indent . INDENT; $elementsCode = array(); $index = 0; foreach ($this->value as $element) { list($key, $value) = $element; if (!isset($key)) { $key = $index++; } $elementsCode[] = array(str($key, $subindent), str($value, $subindent), $key, $value); } $exp = "array("; $indent = $indent . INDENT; $assocWidth = 0; $multiline = 0; $i = 0; foreach ($elementsCode as $element) { list($keyCode, $valueCode) = $element; if ((string) $i !== $keyCode) { $assocWidth = 1; break; } ++$i; } foreach ($elementsCode as $element) { list($keyCode, $valueCode, $key, $value) = $element; if ($assocWidth) { $len = strlen($keyCode); if ($assocWidth < $len) { $assocWidth = $len; } } if (is_array($value) || is_a($value, 'Decompiler_Array')) { $multiline ++; } } $i = 0; foreach ($elementsCode as $element) { list($keyCode, $value) = $element; if ($multiline) { if ($i) { $exp .= ","; } $exp .= "\n"; $exp .= $indent; } else { if ($i) { $exp .= ", "; } } if ($assocWidth) { if ($multiline) { $exp .= sprintf("%-{$assocWidth}s => ", $keyCode); } else { $exp .= $keyCode . ' => '; } } $exp .= $value; $i ++; } if ($multiline) { $exp .= "\n$indent)"; } else { $exp .= ")"; } return $exp; } } // }}} class Decompiler_ConstArray extends Decompiler_Array // {{{ { function Decompiler_ConstArray($array, &$EX) { $elements = array(); foreach ($array as $key => $value) { if ((xcache_get_type($value) & IS_CONSTANT_INDEX)) { $keyCode = $GLOBALS['__xcache_decompiler']->stripNamespace( ZEND_ENGINE_2_3 ? substr($key, 0, -2) : $key ); } else { $keyCode = value($key, $EX); } $elements[] = array($keyCode, value($value, $EX)); } $this->value = $elements; } } // }}} class Decompiler_ForeachBox extends Decompiler_Box // {{{ { var $iskey; function toCode($indent) { return '#foreachBox#'; } } // }}} class Decompiler { var $namespace; var $namespaceDecided; var $activeFile; var $activeClass; var $activeMethod; var $activeFunction; function Decompiler() { $GLOBALS['__xcache_decompiler'] = $this; // {{{ testing // XC_UNDEF XC_OP_DATA $this->test = !empty($_ENV['XCACHE_DECOMPILER_TEST']); $this->usedOps = array(); if ($this->test) { $content = file_get_contents(__FILE__); for ($i = 0; $opname = xcache_get_opcode($i); $i ++) { if (!preg_match("/\\bXC_" . $opname . "\\b(?!')/", $content)) { echo "not recognized opcode ", $opname, "\n"; } } } // }}} // {{{ opinfo $this->unaryops = array( XC_BW_NOT => '~', XC_BOOL_NOT => '!', ); $this->binops = array( XC_ADD => "+", XC_ASSIGN_ADD => "+=", XC_SUB => "-", XC_ASSIGN_SUB => "-=", XC_MUL => "*", XC_ASSIGN_MUL => "*=", XC_DIV => "/", XC_ASSIGN_DIV => "/=", XC_MOD => "%", XC_ASSIGN_MOD => "%=", XC_SL => "<<", XC_ASSIGN_SL => "<<=", XC_SR => ">>", XC_ASSIGN_SR => ">>=", XC_CONCAT => ".", XC_ASSIGN_CONCAT => ".=", XC_IS_IDENTICAL => "===", XC_IS_NOT_IDENTICAL => "!==", XC_IS_EQUAL => "==", XC_IS_NOT_EQUAL => "!=", XC_IS_SMALLER => "<", XC_IS_SMALLER_OR_EQUAL => "<=", XC_BW_OR => "|", XC_ASSIGN_BW_OR => "|=", XC_BW_AND => "&", XC_ASSIGN_BW_AND => "&=", XC_BW_XOR => "^", XC_ASSIGN_BW_XOR => "^=", XC_BOOL_XOR => "xor", XC_ASSIGN => "=", XC_ASSIGN_REF => "= &", XC_JMP_SET => "?:", XC_JMP_SET_VAR => "?:", XC_JMPZ_EX => "&&", XC_JMPNZ_EX => "||", ); // }}} $this->includeTypes = array( // {{{ ZEND_EVAL => 'eval', ZEND_INCLUDE => 'include', ZEND_INCLUDE_ONCE => 'include_once', ZEND_REQUIRE => 'require', ZEND_REQUIRE_ONCE => 'require_once', ); // }}} } function detectNamespace($name) // {{{ { if ($this->namespaceDecided) { return; } if (strpos($name, '\\') !== false) { $this->namespace = strtok($name, '\\'); echo 'namespace ', $this->namespace, ";\n\n"; } $this->namespaceDecided = true; } // }}} function stripNamespace($name) // {{{ { if (!isset($name)) { return $name; } $name = str($name); $len = strlen($this->namespace) + 1; if (substr($name, 0, $len) == $this->namespace . '\\') { return substr($name, $len); } else { return $name; } } // }}} function outputPhp(&$EX, $range) // {{{ { $needBlankline = isset($EX['lastBlock']); $indent = $EX['indent']; $curticks = 0; for ($i = $range[0]; $i <= $range[1]; $i ++) { $op = $EX['opcodes'][$i]; if (isset($op['gofrom'])) { if ($needBlankline) { $needBlankline = false; echo PHP_EOL; } echo 'label' . $i, ":\n"; } if (isset($op['php'])) { $toticks = isset($op['ticks']) ? (int) str($op['ticks']) : 0; if ($curticks != $toticks) { $oldticks = $curticks; $curticks = $toticks; if (!$curticks) { echo $EX['indent'], "}\n\n"; $indent = $EX['indent']; } else { if ($oldticks) { echo $EX['indent'], "}\n\n"; } else if (!$oldticks) { $indent .= INDENT; } if ($needBlankline) { $needBlankline = false; echo PHP_EOL; } echo $EX['indent'], "declare (ticks=$curticks) {\n"; } } if ($needBlankline) { $needBlankline = false; echo PHP_EOL; } echo $indent, str($op['php'], $indent), ";\n"; $EX['lastBlock'] = 'basic'; } } if ($curticks) { echo $EX['indent'], "}\n"; } } // }}} function getOpVal($op, &$EX, $free = false) // {{{ { switch ($op['op_type']) { case XC_IS_CONST: return value($op['constant'], $EX); case XC_IS_VAR: case XC_IS_TMP_VAR: $T = &$EX['Ts']; if (!isset($T[$op['var']])) { printBacktrace(); } $ret = $T[$op['var']]; if ($free && empty($this->keepTs)) { unset($T[$op['var']]); } return $ret; case XC_IS_CV: $var = $op['var']; $var = $EX['op_array']['vars'][$var]; return '$' . $var['name']; case XC_IS_UNUSED: return null; } } // }}} function removeKeyPrefix($array, $prefix) // {{{ { $prefixLen = strlen($prefix); $ret = array(); foreach ($array as $key => $value) { if (substr($key, 0, $prefixLen) == $prefix) { $key = substr($key, $prefixLen); } $ret[$key] = $value; } return $ret; } // }}} function fixOpCode(&$opcodes, $removeTailing = false, $defaultReturnValue = null) // {{{ { $last = count($opcodes) - 1; for ($i = 0; $i <= $last; $i ++) { if (function_exists('xcache_get_fixed_opcode')) { $opcodes[$i]['opcode'] = xcache_get_fixed_opcode($opcodes[$i]['opcode'], $i); } if (isset($opcodes[$i]['op1'])) { $opcodes[$i]['op1'] = $this->removeKeyPrefix($opcodes[$i]['op1'], 'u.'); $opcodes[$i]['op2'] = $this->removeKeyPrefix($opcodes[$i]['op2'], 'u.'); $opcodes[$i]['result'] = $this->removeKeyPrefix($opcodes[$i]['result'], 'u.'); } else { $op = array( 'op1' => array(), 'op2' => array(), 'result' => array(), ); foreach ($opcodes[$i] as $name => $value) { if (preg_match('!^(op1|op2|result)\\.(.*)!', $name, $m)) { list(, $which, $field) = $m; $op[$which][$field] = $value; } else if (preg_match('!^(op1|op2|result)_type$!', $name, $m)) { list(, $which) = $m; $op[$which]['op_type'] = $value; } else { $op[$name] = $value; } } $opcodes[$i] = $op; } } if ($removeTailing) { $last = count($opcodes) - 1; if ($opcodes[$last]['opcode'] == XC_HANDLE_EXCEPTION) { $this->usedOps[XC_HANDLE_EXCEPTION] = true; $opcodes[$last]['opcode'] = XC_NOP; --$last; } if ($opcodes[$last]['opcode'] == XC_RETURN || $opcodes[$last]['opcode'] == XC_GENERATOR_RETURN) { $op1 = $opcodes[$last]['op1']; if ($op1['op_type'] == XC_IS_CONST && array_key_exists('constant', $op1) && $op1['constant'] === $defaultReturnValue) { $opcodes[$last]['opcode'] = XC_NOP; --$last; } } } } // }}} function decompileBasicBlock(&$EX, $range, $unhandled = false) // {{{ { $this->dasmBasicBlock($EX, $range); if ($unhandled) { $this->dumpRange($EX, $range); } $this->outputPhp($EX, $range); } // }}} function isIfCondition(&$EX, $range) // {{{ { $opcodes = &$EX['opcodes']; $firstOp = &$opcodes[$range[0]]; return $firstOp['opcode'] == XC_JMPZ && !empty($firstOp['jmpouts']) && $opcodes[$firstOp['jmpouts'][0] - 1]['opcode'] == XC_JMP && !empty($opcodes[$firstOp['jmpouts'][0] - 1]['jmpouts']) && $opcodes[$firstOp['jmpouts'][0] - 1]['jmpouts'][0] == $range[1] + 1; } // }}} function removeJmpInfo(&$EX, $line) // {{{ { $opcodes = &$EX['opcodes']; if (!isset($opcodes[$line]['jmpouts'])) { printBacktrace(); } foreach ($opcodes[$line]['jmpouts'] as $jmpTo) { $jmpins = &$opcodes[$jmpTo]['jmpins']; $jmpins = array_flip($jmpins); unset($jmpins[$line]); $jmpins = array_keys($jmpins); } // $opcodes[$line]['opcode'] = XC_NOP; unset($opcodes[$line]['jmpouts']); } // }}} function beginScope(&$EX, $doIndent = true) // {{{ { array_push($EX['scopeStack'], array($EX['lastBlock'], $EX['indent'])); if ($doIndent) { $EX['indent'] .= INDENT; } $EX['lastBlock'] = null; } // }}} function endScope(&$EX) // {{{ { list($EX['lastBlock'], $EX['indent']) = array_pop($EX['scopeStack']); } // }}} function beginComplexBlock(&$EX) // {{{ { if (isset($EX['lastBlock'])) { echo PHP_EOL; $EX['lastBlock'] = null; } } // }}} function endComplexBlock(&$EX) // {{{ { $EX['lastBlock'] = 'complex'; } // }}} function decompileComplexBlock(&$EX, $range) // {{{ { $T = &$EX['Ts']; $opcodes = &$EX['opcodes']; $indent = $EX['indent']; $firstOp = &$opcodes[$range[0]]; $lastOp = &$opcodes[$range[1]]; // {{{ && || and or if (($firstOp['opcode'] == XC_JMPZ_EX || $firstOp['opcode'] == XC_JMPNZ_EX) && !empty($firstOp['jmpouts']) && $firstOp['jmpouts'][0] == $range[1] + 1 && $lastOp['opcode'] == XC_BOOL && $firstOp['opcode']['result']['var'] == $lastOp['opcode']['result']['var'] ) { $this->removeJmpInfo($EX, $range[0]); $this->recognizeAndDecompileClosedBlocks($EX, array($range[0], $range[0])); $op1 = $this->getOpVal($firstOp['result'], $EX, true); $this->recognizeAndDecompileClosedBlocks($EX, array($range[0] + 1, $range[1])); $op2 = $this->getOpVal($lastOp['result'], $EX, true); $T[$firstOp['result']['var']] = new Decompiler_Binop($this, $op1, $firstOp['opcode'], $op2); return false; } // }}} // {{{ ?: excluding JMP_SET/JMP_SET_VAR if ($firstOp['opcode'] == XC_JMPZ && !empty($firstOp['jmpouts']) && $range[1] >= $range[0] + 3 && ($opcodes[$firstOp['jmpouts'][0] - 2]['opcode'] == XC_QM_ASSIGN || $opcodes[$firstOp['jmpouts'][0] - 2]['opcode'] == XC_QM_ASSIGN_VAR) && $opcodes[$firstOp['jmpouts'][0] - 1]['opcode'] == XC_JMP && $opcodes[$firstOp['jmpouts'][0] - 1]['jmpouts'][0] == $range[1] + 1 && ($lastOp['opcode'] == XC_QM_ASSIGN || $lastOp['opcode'] == XC_QM_ASSIGN_VAR) ) { $trueRange = array($range[0] + 1, $firstOp['jmpouts'][0] - 2); $falseRange = array($firstOp['jmpouts'][0], $range[1]); $this->removeJmpInfo($EX, $range[0]); $condition = $this->getOpVal($firstOp['op1'], $EX); $this->recognizeAndDecompileClosedBlocks($EX, $trueRange); $trueValue = $this->getOpVal($opcodes[$trueRange[1]]['result'], $EX, true); $this->recognizeAndDecompileClosedBlocks($EX, $falseRange); $falseValue = $this->getOpVal($opcodes[$falseRange[1]]['result'], $EX, true); $T[$opcodes[$trueRange[1]]['result']['var']] = new Decompiler_TriOp($condition, $trueValue, $falseValue); return false; } // }}} // {{{ goto (TODO: recognize BRK which is translated to JMP by optimizer) if ($firstOp['opcode'] == XC_JMP && !empty($firstOp['jmpouts']) && $firstOp['jmpouts'][0] == $range[1] + 1) { $this->removeJmpInfo($EX, $range[0]); assert(XC_GOTO != -1); $firstOp['opcode'] = XC_GOTO; $target = $firstOp['op1']['var']; $firstOp['goto'] = $target; $opcodes[$target]['gofrom'][] = $range[0]; $this->recognizeAndDecompileClosedBlocks($EX, $range); return false; } // }}} // {{{ for if (!empty($firstOp['jmpins']) && $opcodes[$firstOp['jmpins'][0]]['opcode'] == XC_JMP && $lastOp['opcode'] == XC_JMP && !empty($lastOp['jmpouts']) && $lastOp['jmpouts'][0] <= $firstOp['jmpins'][0] && !empty($opcodes[$range[1] + 1]['jmpins']) && $opcodes[$opcodes[$range[1] + 1]['jmpins'][0]]['opcode'] == XC_JMPZNZ ) { $nextRange = array($lastOp['jmpouts'][0], $firstOp['jmpins'][0]); $conditionRange = array($range[0], $nextRange[0] - 1); $this->removeJmpInfo($EX, $conditionRange[1]); $bodyRange = array($nextRange[1], $range[1]); $this->removeJmpInfo($EX, $bodyRange[1]); $initial = ''; $this->beginScope($EX); $this->dasmBasicBlock($EX, $conditionRange); $conditionCodes = array(); for ($i = $conditionRange[0]; $i <= $conditionRange[1]; ++$i) { if (isset($opcodes[$i]['php'])) { $conditionCodes[] = str($opcodes[$i]['php'], $EX); } } $conditionCodes[] = str($this->getOpVal($opcodes[$conditionRange[1]]['op1'], $EX), $EX); if (implode(',', $conditionCodes) == 'true') { $conditionCodes = array(); } $this->endScope($EX); $this->beginScope($EX); $this->dasmBasicBlock($EX, $nextRange); $nextCodes = array(); for ($i = $nextRange[0]; $i <= $nextRange[1]; ++$i) { if (isset($opcodes[$i]['php'])) { $nextCodes[] = str($opcodes[$i]['php'], $EX); } } $this->endScope($EX); $this->beginComplexBlock($EX); echo $indent, 'for (', str($initial, $EX), '; ', implode(', ', $conditionCodes), '; ', implode(', ', $nextCodes), ') ', '{', PHP_EOL; $this->beginScope($EX); $this->recognizeAndDecompileClosedBlocks($EX, $bodyRange); $this->endScope($EX); echo $indent, '}', PHP_EOL; $this->endComplexBlock($EX); return; } // }}} // {{{ if/elseif/else if ($this->isIfCondition($EX, $range)) { $this->beginComplexBlock($EX); $isElseIf = false; do { $ifRange = array($range[0], $opcodes[$range[0]]['jmpouts'][0] - 1); $this->removeJmpInfo($EX, $ifRange[0]); $this->removeJmpInfo($EX, $ifRange[1]); $condition = $this->getOpVal($opcodes[$ifRange[0]]['op1'], $EX); echo $indent, $isElseIf ? 'else if' : 'if', ' (', str($condition, $EX), ') ', '{', PHP_EOL; $this->beginScope($EX); $this->recognizeAndDecompileClosedBlocks($EX, $ifRange); $this->endScope($EX); $EX['lastBlock'] = null; echo $indent, '}', PHP_EOL; $isElseIf = true; // search for else if $range[0] = $ifRange[1] + 1; for ($i = $ifRange[1] + 1; $i <= $range[1]; ++$i) { // find first jmpout if (!empty($opcodes[$i]['jmpouts'])) { if ($this->isIfCondition($EX, array($i, $range[1]))) { $this->dasmBasicBlock($EX, array($range[0], $i)); $range[0] = $i; } break; } } } while ($this->isIfCondition($EX, $range)); if ($ifRange[1] < $range[1]) { $elseRange = array($ifRange[1], $range[1]); echo $indent, 'else ', '{', PHP_EOL; $this->beginScope($EX); $this->recognizeAndDecompileClosedBlocks($EX, $elseRange); $this->endScope($EX); $EX['lastBlock'] = null; echo $indent, '}', PHP_EOL; } $this->endComplexBlock($EX); return; } if ($firstOp['opcode'] == XC_JMPZ && !empty($firstOp['jmpouts']) && $firstOp['jmpouts'][0] - 1 == $range[1] && ($opcodes[$firstOp['jmpouts'][0] - 1]['opcode'] == XC_RETURN || $opcodes[$firstOp['jmpouts'][0] - 1]['opcode'] == XC_GENERATOR_RETURN)) { $this->beginComplexBlock($EX); $this->removeJmpInfo($EX, $range[0]); $condition = $this->getOpVal($opcodes[$range[0]]['op1'], $EX); echo $indent, 'if (', str($condition, $EX), ') ', '{', PHP_EOL; $this->beginScope($EX); $this->recognizeAndDecompileClosedBlocks($EX, $range); $this->endScope($EX); echo $indent, '}', PHP_EOL; $this->endComplexBlock($EX); return; } // }}} // {{{ try/catch if (!empty($firstOp['jmpins']) && !empty($opcodes[$firstOp['jmpins'][0]]['isCatchBegin'])) { $catchBlocks = array(); $catchFirst = $firstOp['jmpins'][0]; $tryRange = array($range[0], $catchFirst - 1); // search for XC_CATCH for ($i = $catchFirst; $i <= $range[1]; ) { if ($opcodes[$i]['opcode'] == XC_CATCH) { $catchOpLine = $i; $this->removeJmpInfo($EX, $catchFirst); $catchNext = $opcodes[$catchOpLine]['extended_value']; $catchBodyLast = $catchNext - 1; if ($opcodes[$catchBodyLast]['opcode'] == XC_JMP) { --$catchBodyLast; } $catchBlocks[$catchFirst] = array($catchOpLine, $catchBodyLast); $i = $catchFirst = $catchNext; } else { ++$i; } } if ($opcodes[$tryRange[1]]['opcode'] == XC_JMP) { --$tryRange[1]; } $this->beginComplexBlock($EX); echo $indent, "try {", PHP_EOL; $this->beginScope($EX); $this->recognizeAndDecompileClosedBlocks($EX, $tryRange); $this->endScope($EX); echo $indent, '}', PHP_EOL; if (!$catchBlocks) { printBacktrace(); assert($catchBlocks); } foreach ($catchBlocks as $catchFirst => $catchInfo) { list($catchOpLine, $catchBodyLast) = $catchInfo; $catchBodyFirst = $catchOpLine + 1; $this->dasmBasicBlock($EX, array($catchFirst, $catchOpLine)); $catchOp = &$opcodes[$catchOpLine]; echo $indent, 'catch (' , $this->stripNamespace(isset($catchOp['op1']['constant']) ? $catchOp['op1']['constant'] : str($this->getOpVal($catchOp['op1'], $EX))) , ' ' , isset($catchOp['op2']['constant']) ? '$' . $catchOp['op2']['constant'] : str($this->getOpVal($catchOp['op2'], $EX)) , ") {", PHP_EOL; unset($catchOp); $EX['lastBlock'] = null; $this->beginScope($EX); $this->recognizeAndDecompileClosedBlocks($EX, array($catchBodyFirst, $catchBodyLast)); $this->endScope($EX); echo $indent, '}', PHP_EOL; } $this->endComplexBlock($EX); return; } // }}} // {{{ switch/case if ( ($firstOp['opcode'] == XC_CASE || $firstOp['opcode'] == XC_JMP && !empty($firstOp['jmpouts']) && $opcodes[$firstOp['jmpouts'][0]]['opcode'] == XC_CASE ) && !empty($lastOp['jmpouts']) ) { $cases = array(); $caseDefault = null; $caseOp = null; for ($i = $range[0]; $i <= $range[1]; ) { $op = $opcodes[$i]; if ($op['opcode'] == XC_CASE) { if (!isset($caseOp)) { $caseOp = $op; } $jmpz = $opcodes[$i + 1]; assert('$jmpz["opcode"] == XC_JMPZ'); $caseNext = $jmpz['jmpouts'][0]; $cases[$i] = $caseNext - 1; $i = $caseNext; } else if ($op['opcode'] == XC_JMP && $op['jmpouts'][0] >= $i) { // default $caseNext = $op['jmpouts'][0]; $caseDefault = $i; $cases[$i] = $caseNext - 1; $i = $caseNext; } else { ++$i; } } $this->beginComplexBlock($EX); echo $indent, 'switch (', str($this->getOpVal($caseOp['op1'], $EX, true), $EX), ") {", PHP_EOL; $caseIsOut = false; foreach ($cases as $caseFirst => $caseLast) { if ($caseIsOut && empty($lastCaseFall)) { echo PHP_EOL; } $caseOp = $opcodes[$caseFirst]; echo $indent; if ($caseOp['opcode'] == XC_CASE) { echo 'case '; echo str($this->getOpVal($caseOp['op2'], $EX), $EX); echo ':', PHP_EOL; $this->removeJmpInfo($EX, $caseFirst); ++$caseFirst; assert('$opcodes[$caseFirst]["opcode"] == XC_JMPZ'); $this->removeJmpInfo($EX, $caseFirst); ++$caseFirst; } else { echo 'default'; echo ':', PHP_EOL; assert('$opcodes[$caseFirst]["opcode"] == XC_JMP'); $this->removeJmpInfo($EX, $caseFirst); ++$caseFirst; } assert('$opcodes[$caseLast]["opcode"] == XC_JMP'); $this->removeJmpInfo($EX, $caseLast); --$caseLast; switch ($opcodes[$caseLast]['opcode']) { case XC_BRK: case XC_CONT: case XC_GOTO: $lastCaseFall = false; break; default: $lastCaseFall = true; } $this->beginScope($EX); $this->recognizeAndDecompileClosedBlocks($EX, array($caseFirst, $caseLast)); $this->endScope($EX); $caseIsOut = true; } echo $indent, '}', PHP_EOL; $this->endComplexBlock($EX); return; } // }}} // {{{ do/while if ($lastOp['opcode'] == XC_JMPNZ && !empty($lastOp['jmpouts']) && $lastOp['jmpouts'][0] == $range[0]) { $this->removeJmpInfo($EX, $range[1]); $this->beginComplexBlock($EX); echo $indent, "do {", PHP_EOL; $this->beginScope($EX); $this->recognizeAndDecompileClosedBlocks($EX, $range); $this->endScope($EX); echo $indent, "} while (", str($this->getOpVal($lastOp['op1'], $EX)), ');', PHP_EOL; $this->endComplexBlock($EX); return; } // }}} // {{{ search firstJmpOp $firstJmp = -1; $firstJmpOp = null; for ($i = $range[0]; $i <= $range[1]; ++$i) { if (!empty($opcodes[$i]['jmpouts'])) { $firstJmp = $i; $firstJmpOp = &$opcodes[$firstJmp]; break; } } // }}} // {{{ search lastJmpOp $lastJmp = -1; $lastJmpOp = null; for ($i = $range[1]; $i > $firstJmp; --$i) { if (!empty($opcodes[$i]['jmpouts'])) { $lastJmp = $i; $lastJmpOp = &$opcodes[$lastJmp]; break; } } // }}} // {{{ while if (isset($firstJmpOp) && $firstJmpOp['opcode'] == XC_JMPZ && $firstJmpOp['jmpouts'][0] > $range[1] && $lastOp['opcode'] == XC_JMP && !empty($lastOp['jmpouts']) && $lastOp['jmpouts'][0] == $range[0]) { $this->removeJmpInfo($EX, $firstJmp); $this->removeJmpInfo($EX, $range[1]); $this->beginComplexBlock($EX); ob_start(); $this->beginScope($EX); $this->recognizeAndDecompileClosedBlocks($EX, $range); $this->endScope($EX); $body = ob_get_clean(); echo $indent, 'while (', str($this->getOpVal($firstJmpOp['op1'], $EX)), ") {", PHP_EOL; echo $body; echo $indent, '}', PHP_EOL; $this->endComplexBlock($EX); return; } // }}} // {{{ foreach if (isset($firstJmpOp) && $firstJmpOp['opcode'] == XC_FE_FETCH && !empty($firstJmpOp['jmpouts']) && $firstJmpOp['jmpouts'][0] > $lastJmp && isset($lastJmpOp) && $lastJmpOp['opcode'] == XC_JMP && !empty($lastJmpOp['jmpouts']) && $lastJmpOp['jmpouts'][0] == $firstJmp) { $this->removeJmpInfo($EX, $firstJmp); $this->removeJmpInfo($EX, $lastJmp); $this->beginComplexBlock($EX); ob_start(); $this->beginScope($EX); $this->recognizeAndDecompileClosedBlocks($EX, $range); $this->endScope($EX); $body = ob_get_clean(); $as = str(foldToCode($firstJmpOp['fe_as'], $EX), $EX); if (isset($firstJmpOp['fe_key'])) { $as = str($firstJmpOp['fe_key'], $EX) . ' => ' . $as; } echo $indent, 'foreach (', str($firstJmpOp['fe_src'], $EX), " as $as) {", PHP_EOL; echo $body; echo $indent, '}', PHP_EOL; $this->endComplexBlock($EX); return; } // }}} $this->decompileBasicBlock($EX, $range, true); } // }}} function recognizeAndDecompileClosedBlocks(&$EX, $range) // {{{ decompile in a tree way { $opcodes = &$EX['opcodes']; $starti = $range[0]; for ($i = $starti; $i <= $range[1]; ) { if (!empty($opcodes[$i]['jmpins']) || !empty($opcodes[$i]['jmpouts'])) { $blockFirst = $i; $blockLast = -1; $j = $blockFirst; do { $op = $opcodes[$j]; if (!empty($op['jmpins'])) { // care about jumping from blocks behind, not before foreach ($op['jmpins'] as $oplineNumber) { if ($oplineNumber <= $range[1] && $blockLast < $oplineNumber) { $blockLast = $oplineNumber; } } } if (!empty($op['jmpouts'])) { $blockLast = max($blockLast, max($op['jmpouts']) - 1); } ++$j; } while ($j <= $blockLast); if (!assert('$blockLast <= $range[1]')) { var_dump($blockLast, $range[1]); printBacktrace(); } if ($blockLast >= $blockFirst) { if ($blockFirst > $starti) { $this->decompileBasicBlock($EX, array($starti, $blockFirst - 1)); } if ($this->decompileComplexBlock($EX, array($blockFirst, $blockLast)) === false) { if ($EX['lastBlock'] == 'complex') { echo PHP_EOL; } $EX['lastBlock'] = null; } $starti = $blockLast + 1; $i = $starti; } else { ++$i; } } else { ++$i; } } if ($starti <= $range[1]) { $this->decompileBasicBlock($EX, array($starti, $range[1])); } } // }}} function buildJmpInfo(&$op_array) // {{{ build jmpins/jmpouts to op_array { $opcodes = &$op_array['opcodes']; $last = count($opcodes) - 1; for ($i = 0; $i <= $last; $i ++) { $op = &$opcodes[$i]; $op['line'] = $i; switch ($op['opcode']) { case XC_CONT: case XC_BRK: $op['jmpouts'] = array(); break; case XC_GOTO: $target = $op['op1']['var']; $op['goto'] = $target; $opcodes[$target]['gofrom'][] = $i; break; case XC_JMP: $target = $op['op1']['var']; $op['jmpouts'] = array($target); $opcodes[$target]['jmpins'][] = $i; break; case XC_JMPZNZ: $jmpz = $op['op2']['opline_num']; $jmpnz = $op['extended_value']; $op['jmpouts'] = array($jmpz, $jmpnz); $opcodes[$jmpz]['jmpins'][] = $i; $opcodes[$jmpnz]['jmpins'][] = $i; break; case XC_JMPZ: case XC_JMPNZ: case XC_JMPZ_EX: case XC_JMPNZ_EX: // case XC_JMP_SET: // case XC_JMP_SET_VAR: // case XC_FE_RESET: case XC_FE_FETCH: // case XC_JMP_NO_CTOR: $target = $op['op2']['opline_num']; //if (!isset($target)) { // $this->dumpop($op, $EX); // var_dump($op); exit; //} $op['jmpouts'] = array($target); $opcodes[$target]['jmpins'][] = $i; break; /* case XC_RETURN: $op['jmpouts'] = array(); break; */ case XC_CASE: // just to link together $op['jmpouts'] = array($i + 2); $opcodes[$i + 2]['jmpins'][] = $i; break; case XC_CATCH: $catchNext = $op['extended_value']; $catchBegin = $opcodes[$i - 1]['opcode'] == XC_FETCH_CLASS ? $i - 1 : $i; $opcodes[$catchBegin]['jmpouts'] = array($catchNext); $opcodes[$catchNext]['jmpins'][] = $catchBegin; break; } /* if (!empty($op['jmpouts']) || !empty($op['jmpins'])) { echo $i, "\t", xcache_get_opcode($op['opcode']), PHP_EOL; } // */ } unset($op); if (isset($op_array['try_catch_array'])) { foreach ($op_array['try_catch_array'] as $try_catch_element) { $catch_op = $try_catch_element['catch_op']; $opcodes[$catch_op]['isCatchBegin'] = true; } foreach ($op_array['try_catch_array'] as $try_catch_element) { $catch_op = $try_catch_element['catch_op']; $try_op = $try_catch_element['try_op']; do { $opcodes[$try_op]['jmpins'][] = $catch_op; $opcodes[$catch_op]['jmpouts'][] = $try_op; if ($opcodes[$catch_op]['opcode'] == XC_CATCH) { $catch_op = $opcodes[$catch_op]['extended_value']; } else if ($opcodes[$catch_op + 1]['opcode'] == XC_CATCH) { $catch_op = $opcodes[$catch_op + 1]['extended_value']; } else { break; } } while ($catch_op <= $last && empty($opcodes[$catch_op]['isCatchBegin'])); } } } // }}} function &dop_array($op_array, $indent = '') // {{{ { $this->fixOpCode($op_array['opcodes'], true, $indent == '' ? 1 : null); $this->buildJmpInfo($op_array); $opcodes = &$op_array['opcodes']; $last = count($opcodes) - 1; // build semi-basic blocks $nextbbs = array(); $starti = 0; for ($i = 1; $i <= $last; $i ++) { if (isset($opcodes[$i]['jmpins']) || isset($opcodes[$i - 1]['jmpouts'])) { $nextbbs[$starti] = $i; $starti = $i; } } $nextbbs[$starti] = $last + 1; $EX = array(); $EX['Ts'] = array(); $EX['indent'] = $indent; $EX['nextbbs'] = $nextbbs; $EX['op_array'] = &$op_array; $EX['opcodes'] = &$opcodes; $EX['range'] = array(0, count($opcodes) - 1); // func call $EX['object'] = null; $EX['called_scope'] = null; $EX['fbc'] = null; $EX['argstack'] = array(); $EX['arg_types_stack'] = array(); $EX['scopeStack'] = array(); $EX['silence'] = 0; $EX['recvs'] = array(); $EX['uses'] = array(); $EX['lastBlock'] = null; $EX['value2constant'] = array(); if (isset($this->activeFile)) { $EX['value2constant'][$this->activeFile] = '__FILE__'; } if (isset($this->activeClass)) { $EX['value2constant'][$this->activeClass] = '__CLASS__'; } if (isset($this->activeMethod)) { $EX['value2constant'][$this->activeMethod] = '__METHOD__'; } if (isset($this->activeFunction)) { $EX['value2constant'][$this->activeFunction] = '__FUNCTION__'; } /* dump whole array $this->keepTs = true; $this->dasmBasicBlock($EX, $range); for ($i = $range[0]; $i <= $range[1]; ++$i) { echo $i, "\t", $this->dumpop($opcodes[$i], $EX); } // */ // decompile in a tree way $this->recognizeAndDecompileClosedBlocks($EX, $EX['range'], $EX['indent']); return $EX; } // }}} function dasmBasicBlock(&$EX, $range) // {{{ { $T = &$EX['Ts']; $opcodes = &$EX['opcodes']; $lastphpop = null; $currentSourceLine = null; for ($i = $range[0]; $i <= $range[1]; $i ++, unsetArray($EX['value2constant'], $currentSourceLine)) { // {{{ prepair $op = &$opcodes[$i]; $opc = $op['opcode']; if ($opc == XC_NOP) { $this->usedOps[$opc] = true; continue; } $op1 = $op['op1']; $op2 = $op['op2']; $res = $op['result']; $ext = $op['extended_value']; $currentSourceLine = $op['lineno']; $EX['value2constant'][$currentSourceLine] = '__LINE__'; $opname = xcache_get_opcode($opc); if ($opname == 'UNDEF' || !isset($opname)) { echo 'UNDEF OP:'; $this->dumpop($op, $EX); continue; } // echo $i, ' '; $this->dumpop($op, $EX); //var_dump($op); $resvar = null; unset($curResVar); if (array_key_exists($res['var'], $T)) { $curResVar = &$T[$res['var']]; } if ((ZEND_ENGINE_2_4 ? ($res['op_type'] & EXT_TYPE_UNUSED) : ($res['EA.type'] & EXT_TYPE_UNUSED)) || $res['op_type'] == XC_IS_UNUSED) { $istmpres = false; } else { $istmpres = true; } // }}} // echo $opname, "\n"; $notHandled = false; switch ($opc) { case XC_NEW: // {{{ array_push($EX['arg_types_stack'], array($EX['fbc'], $EX['object'], $EX['called_scope'])); $EX['object'] = $istmpres ? (int) $res['var'] : null; $EX['called_scope'] = null; $EX['fbc'] = 'new ' . $this->stripNamespace(isset($op1['constant']) ? $op1['constant'] : $this->getOpVal($op1, $EX)); break; // }}} case XC_THROW: // {{{ $resvar = 'throw ' . str($this->getOpVal($op1, $EX)); break; // }}} case XC_CLONE: // {{{ $resvar = 'clone ' . str($this->getOpVal($op1, $EX)); break; // }}} case XC_CATCH: // {{{ break; // }}} case XC_INSTANCEOF: // {{{ $resvar = str($this->getOpVal($op1, $EX)) . ' instanceof ' . $this->stripNamespace($this->getOpVal($op2, $EX)); break; // }}} case XC_FETCH_CLASS: // {{{ if ($op2['op_type'] == XC_IS_UNUSED) { switch (($ext & (defined('ZEND_FETCH_CLASS_MASK') ? ZEND_FETCH_CLASS_MASK : 0xFF))) { case ZEND_FETCH_CLASS_SELF: $class = 'self'; break; case ZEND_FETCH_CLASS_PARENT: $class = 'parent'; break; case ZEND_FETCH_CLASS_STATIC: $class = 'static'; break; } $istmpres = true; } else { $class = isset($op2['constant']) ? $op2['constant'] : $this->getOpVal($op2, $EX); } $resvar = $class; break; // }}} case XC_FETCH_CONSTANT: // {{{ if ($op1['op_type'] == XC_IS_UNUSED) { $resvar = $this->stripNamespace($op2['constant']); break; } if ($op1['op_type'] == XC_IS_CONST) { if (!ZEND_ENGINE_2) { $resvar = $op1['constant']; break; } $resvar = $this->stripNamespace($op1['constant']); } else { $resvar = $this->getOpVal($op1, $EX); } $resvar = str($resvar) . '::' . unquoteName($this->getOpVal($op2, $EX)); break; // }}} // {{{ case FETCH_* case XC_FETCH_R: case XC_FETCH_W: case XC_FETCH_RW: case XC_FETCH_FUNC_ARG: case XC_FETCH_UNSET: case XC_FETCH_IS: $fetchType = defined('ZEND_FETCH_TYPE_MASK') ? ($ext & ZEND_FETCH_TYPE_MASK) : $op2[!ZEND_ENGINE_2 ? 'fetch_type' : 'EA.type']; $name = isset($op1['constant']) ? $op1['constant'] : unquoteName($this->getOpVal($op1, $EX), $EX); if ($fetchType == ZEND_FETCH_STATIC_MEMBER) { $class = isset($op2['constant']) ? $op2['constant'] : $this->getOpVal($op2, $EX); $rvalue = $this->stripNamespace($class) . '::$' . $name; } else { $rvalue = isset($op1['constant']) ? $op1['constant'] : $this->getOpVal($op1, $EX); $globalName = xcache_is_autoglobal($name) ? "\$$name" : "\$GLOBALS[" . str($this->getOpVal($op1, $EX), $EX) . "]"; $rvalue = new Decompiler_Fetch($rvalue, $fetchType, $globalName); } if ($res['op_type'] != XC_IS_UNUSED) { $resvar = $rvalue; } break; // }}} case XC_UNSET_VAR: // {{{ $fetchType = defined('ZEND_FETCH_TYPE_MASK') ? ($ext & ZEND_FETCH_TYPE_MASK) : $op2['EA.type']; if ($fetchType == ZEND_FETCH_STATIC_MEMBER) { $class = isset($op2['constant']) ? $op2['constant'] /* PHP5.3- */ : $this->getOpVal($op2, $EX); $rvalue = $this->stripNamespace($class) . '::$' . $op1['constant']; } else { $rvalue = isset($op1['constant']) ? '$' . $op1['constant'] /* PHP5.1- */ : $this->getOpVal($op1, $EX); } $op['php'] = "unset(" . str($rvalue, $EX) . ")"; $lastphpop = &$op; break; // }}} // {{{ case FETCH_DIM_* case XC_FETCH_DIM_TMP_VAR: case XC_FETCH_DIM_R: case XC_FETCH_DIM_W: case XC_FETCH_DIM_RW: case XC_FETCH_DIM_FUNC_ARG: case XC_FETCH_DIM_UNSET: case XC_FETCH_DIM_IS: case XC_ASSIGN_DIM: case XC_UNSET_DIM: case XC_UNSET_DIM_OBJ: case XC_UNSET_OBJ: $src = $this->getOpVal($op1, $EX); if (is_a($src, "Decompiler_ForeachBox")) { assert($opc == XC_FETCH_DIM_TMP_VAR); if (ZEND_ENGINE_2) { $src = clone($src); } else { $src = new Decompiler_ForeachBox($src->obj); } $src->iskey = $op2['constant']; $resvar = $src; break; } if (is_a($src, "Decompiler_DimBox")) { $dimbox = $src; } else { if (!is_a($src, "Decompiler_ListBox")) { $op1val = $this->getOpVal($op1, $EX); $list = new Decompiler_List(isset($op1val) ? $op1val : '$this'); $src = new Decompiler_ListBox($list); if (!isset($op1['var'])) { $this->dumpop($op, $EX); var_dump($op); die('missing var'); } $T[$op1['var']] = $src; unset($list); } $dim = new Decompiler_Dim($src); $src->obj->dims[] = &$dim; $dimbox = new Decompiler_DimBox($dim); } $dim = &$dimbox->obj; $dim->offsets[] = $this->getOpVal($op2, $EX); /* TODO: use type mask */ if ($ext == ZEND_FETCH_ADD_LOCK) { $src->obj->everLocked = true; } else if ($ext == ZEND_FETCH_STANDARD) { $dim->isLast = true; } if ($opc == XC_UNSET_OBJ) { $dim->isObject = true; } else if ($opc == XC_UNSET_DIM_OBJ) { $dim->isObject = ZEND_ENGINE_2 ? $ext == ZEND_UNSET_OBJ : false /* cannot distingue */; } unset($dim); $rvalue = $dimbox; unset($dimbox); if ($opc == XC_ASSIGN_DIM) { $lvalue = $rvalue; ++ $i; $rvalue = $this->getOpVal($opcodes[$i]['op1'], $EX); $resvar = str($lvalue, $EX) . ' = ' . str($rvalue); } else if ($opc == XC_UNSET_DIM || $opc == XC_UNSET_OBJ || $opc == XC_UNSET_DIM_OBJ) { $op['php'] = "unset(" . str($rvalue, $EX) . ")"; $lastphpop = &$op; } else if ($res['op_type'] != XC_IS_UNUSED) { $resvar = $rvalue; } break; // }}} case XC_ASSIGN: // {{{ $lvalue = $this->getOpVal($op1, $EX); $rvalue = $this->getOpVal($op2, $EX); if (is_a($rvalue, 'Decompiler_ForeachBox')) { $type = $rvalue->iskey ? 'fe_key' : 'fe_as'; $rvalue->obj[$type] = $lvalue; unset($T[$op2['var']]); break; } if (is_a($rvalue, "Decompiler_DimBox")) { $dim = &$rvalue->obj; $dim->assign = $lvalue; if ($dim->isLast) { $resvar = foldToCode($dim->value, $EX); } unset($dim); break; } if (is_a($rvalue, 'Decompiler_Fetch')) { $src = str($rvalue->src, $EX); if ('$' . unquoteName($src) == $lvalue) { switch ($rvalue->fetchType) { case ZEND_FETCH_STATIC: $statics = &$EX['op_array']['static_variables']; if ((xcache_get_type($statics[$name]) & IS_LEXICAL_VAR)) { $EX['uses'][] = str($lvalue); unset($statics); break 2; } unset($statics); } } } $resvar = new Decompiler_Binop($this, $lvalue, XC_ASSIGN, $rvalue); break; // }}} case XC_ASSIGN_REF: // {{{ $lvalue = $this->getOpVal($op1, $EX); $rvalue = $this->getOpVal($op2, $EX); if (is_a($rvalue, 'Decompiler_Fetch')) { $src = str($rvalue->src, $EX); if ('$' . unquoteName($src) == $lvalue) { switch ($rvalue->fetchType) { case ZEND_FETCH_GLOBAL: case ZEND_FETCH_GLOBAL_LOCK: $resvar = 'global ' . $lvalue; break 2; case ZEND_FETCH_STATIC: $statics = &$EX['op_array']['static_variables']; if ((xcache_get_type($statics[$name]) & IS_LEXICAL_REF)) { $EX['uses'][] = '&' . str($lvalue); unset($statics); break 2; } $resvar = 'static ' . $lvalue; $name = unquoteName($src); if (isset($statics[$name])) { $var = $statics[$name]; $resvar .= ' = '; $resvar .= str(value($var, $EX), $EX); } unset($statics); break 2; default: } } } // TODO: PHP_6 global $resvar = new Decompiler_Binop($this, $lvalue, XC_ASSIGN_REF, $rvalue); break; // }}} // {{{ case FETCH_OBJ_* case XC_FETCH_OBJ_R: case XC_FETCH_OBJ_W: case XC_FETCH_OBJ_RW: case XC_FETCH_OBJ_FUNC_ARG: case XC_FETCH_OBJ_UNSET: case XC_FETCH_OBJ_IS: case XC_ASSIGN_OBJ: $obj = $this->getOpVal($op1, $EX); if (!isset($obj)) { $obj = '$this'; } $rvalue = str($obj) . "->" . unquoteVariableName($this->getOpVal($op2, $EX), $EX); if ($res['op_type'] != XC_IS_UNUSED) { $resvar = $rvalue; } if ($opc == XC_ASSIGN_OBJ) { ++ $i; $lvalue = $rvalue; $rvalue = $this->getOpVal($opcodes[$i]['op1'], $EX); $resvar = "$lvalue = " . str($rvalue); } break; // }}} case XC_ISSET_ISEMPTY_DIM_OBJ: case XC_ISSET_ISEMPTY_PROP_OBJ: case XC_ISSET_ISEMPTY: case XC_ISSET_ISEMPTY_VAR: // {{{ if ($opc == XC_ISSET_ISEMPTY_VAR) { $rvalue = $this->getOpVal($op1, $EX); // for < PHP_5_3 if ($op1['op_type'] == XC_IS_CONST) { $rvalue = '$' . unquoteVariableName($this->getOpVal($op1, $EX)); } $fetchtype = defined('ZEND_FETCH_TYPE_MASK') ? ($ext & ZEND_FETCH_TYPE_MASK) : $op2['EA.type']; if ($fetchtype == ZEND_FETCH_STATIC_MEMBER) { $class = isset($op2['constant']) ? $op2['constant'] : $this->getOpVal($op2, $EX); $rvalue = $this->stripNamespace($class) . '::' . unquoteName($rvalue, $EX); } } else if ($opc == XC_ISSET_ISEMPTY) { $rvalue = $this->getOpVal($op1, $EX); } else { $container = $this->getOpVal($op1, $EX); $dim = $this->getOpVal($op2, $EX); if ($opc == XC_ISSET_ISEMPTY_PROP_OBJ) { if (!isset($container)) { $container = '$this'; } $rvalue = str($container, $EX) . "->" . unquoteVariableName($dim); } else { $rvalue = str($container, $EX) . '[' . str($dim) .']'; } } switch (((!ZEND_ENGINE_2 ? $op['op2']['var'] /* constant */ : $ext) & ZEND_ISSET_ISEMPTY_MASK)) { case ZEND_ISSET: $rvalue = "isset(" . str($rvalue) . ")"; break; case ZEND_ISEMPTY: $rvalue = "empty(" . str($rvalue) . ")"; break; } $resvar = $rvalue; break; // }}} case XC_SEND_VAR_NO_REF: case XC_SEND_VAL: case XC_SEND_REF: case XC_SEND_VAR: // {{{ $ref = ($opc == XC_SEND_REF ? '&' : ''); $EX['argstack'][] = $ref . str($this->getOpVal($op1, $EX)); break; // }}} case XC_INIT_STATIC_METHOD_CALL: case XC_INIT_METHOD_CALL: // {{{ array_push($EX['arg_types_stack'], array($EX['fbc'], $EX['object'], $EX['called_scope'])); if ($opc == XC_INIT_STATIC_METHOD_CALL) { $EX['object'] = null; $EX['called_scope'] = $this->stripNamespace(isset($op1['constant']) ? $op1['constant'] : $this->getOpVal($op1, $EX)); } else { $obj = $this->getOpVal($op1, $EX); if (!isset($obj)) { $obj = '$this'; } $EX['object'] = $obj; $EX['called_scope'] = null; } if ($res['op_type'] != XC_IS_UNUSED) { $resvar = '$obj call$'; } $EX['fbc'] = isset($op2['constant']) ? $op2['constant'] : $this->getOpVal($op2, $EX); if (!isset($EX['fbc'])) { $EX['fbc'] = '__construct'; } break; // }}} case XC_INIT_NS_FCALL_BY_NAME: case XC_INIT_FCALL_BY_NAME: // {{{ if (!ZEND_ENGINE_2 && ($ext & ZEND_CTOR_CALL)) { break; } array_push($EX['arg_types_stack'], array($EX['fbc'], $EX['object'], $EX['called_scope'])); if (!ZEND_ENGINE_2 && ($ext & ZEND_MEMBER_FUNC_CALL)) { if (isset($op1['constant'])) { $EX['object'] = null; $EX['called_scope'] = $this->stripNamespace($op1['constant']); } else { $EX['object'] = $this->getOpVal($op1, $EX); $EX['called_scope'] = null; } } else { $EX['object'] = null; $EX['called_scope'] = null; } $EX['fbc'] = isset($op2['constant']) ? $op2['constant'] : $this->getOpVal($op2, $EX); break; // }}} case XC_INIT_FCALL_BY_FUNC: // {{{ deprecated even in PHP 4? $EX['object'] = null; $EX['called_scope'] = null; $which = $op1['var']; $EX['fbc'] = $EX['op_array']['funcs'][$which]['name']; break; // }}} case XC_DO_FCALL_BY_FUNC: $which = $op1['var']; $fname = $EX['op_array']['funcs'][$which]['name']; $args = $this->popargs($EX, $ext); $resvar = $fname . "($args)"; break; case XC_DO_FCALL: $fname = unquoteName($this->getOpVal($op1, $EX), $EX); $args = $this->popargs($EX, $ext); $resvar = $fname . "($args)"; break; case XC_DO_FCALL_BY_NAME: // {{{ $object = null; if (!is_int($EX['object'])) { $object = $EX['object']; } $args = $this->popargs($EX, $ext); $prefix = (isset($object) ? str($object) . '->' : '' ) . (isset($EX['called_scope']) ? str($EX['called_scope']) . '::' : '' ); $resvar = $prefix . (!$prefix ? $this->stripNamespace($EX['fbc']) : str($EX['fbc'])) . "($args)"; unset($args); if (is_int($EX['object'])) { $T[$EX['object']] = $resvar; $resvar = null; } list($EX['fbc'], $EX['object'], $EX['called_scope']) = array_pop($EX['arg_types_stack']); break; // }}} case XC_VERIFY_ABSTRACT_CLASS: // {{{ //unset($T[$op1['var']]); break; // }}} case XC_DECLARE_CLASS: case XC_DECLARE_INHERITED_CLASS: case XC_DECLARE_INHERITED_CLASS_DELAYED: // {{{ $key = $op1['constant']; if (!isset($this->dc['class_table'][$key])) { echo 'class not found: ', $key, 'existing classes are:', "\n"; var_dump(array_keys($this->dc['class_table'])); exit; } $class = &$this->dc['class_table'][$key]; if (!isset($class['name'])) { $class['name'] = unquoteName($this->getOpVal($op2, $EX), $EX); } if ($opc == XC_DECLARE_INHERITED_CLASS || $opc == XC_DECLARE_INHERITED_CLASS_DELAYED) { $ext /= XC_SIZEOF_TEMP_VARIABLE; $class['parent'] = $T[$ext]; unset($T[$ext]); } else { $class['parent'] = null; } for (;;) { if ($i + 1 <= $range[1] && $opcodes[$i + 1]['opcode'] == XC_ADD_INTERFACE && $opcodes[$i + 1]['op1']['var'] == $res['var']) { // continue } else if ($i + 2 <= $range[1] && $opcodes[$i + 2]['opcode'] == XC_ADD_INTERFACE && $opcodes[$i + 2]['op1']['var'] == $res['var'] && $opcodes[$i + 1]['opcode'] == XC_FETCH_CLASS) { // continue } else { break; } $this->usedOps[XC_ADD_INTERFACE] = true; $fetchop = &$opcodes[$i + 1]; $interface = $this->stripNamespace(unquoteName($this->getOpVal($fetchop['op2'], $EX), $EX)); $addop = &$opcodes[$i + 2]; $class['interfaces'][$addop['extended_value']] = $interface; unset($fetchop, $addop); $i += 2; } $this->activeClass = $class['name']; $this->dclass($class, $EX['indent']); $this->activeClass = null; echo "\n"; unset($class); break; // }}} case XC_INIT_STRING: // {{{ $resvar = "''"; break; // }}} case XC_ADD_CHAR: case XC_ADD_STRING: case XC_ADD_VAR: // {{{ $op1val = $this->getOpVal($op1, $EX); $op2val = $this->getOpVal($op2, $EX); switch ($opc) { case XC_ADD_CHAR: $op2val = value(chr(str($op2val)), $EX); break; case XC_ADD_STRING: break; case XC_ADD_VAR: break; } if (str($op1val) == "''") { $rvalue = $op2val; } else if (str($op2val) == "''") { $rvalue = $op1val; } else { $rvalue = str($op1val) . ' . ' . str($op2val); } $resvar = $rvalue; // }}} break; case XC_PRINT: // {{{ $op1val = $this->getOpVal($op1, $EX); $resvar = "print(" . str($op1val) . ")"; break; // }}} case XC_ECHO: // {{{ $op1val = $this->getOpVal($op1, $EX); $resvar = "echo " . str($op1val); break; // }}} case XC_EXIT: // {{{ $op1val = $this->getOpVal($op1, $EX); $resvar = "exit($op1val)"; break; // }}} case XC_INIT_ARRAY: case XC_ADD_ARRAY_ELEMENT: // {{{ $rvalue = $this->getOpVal($op1, $EX, true); if ($opc == XC_ADD_ARRAY_ELEMENT) { $assoc = $this->getOpVal($op2, $EX); if (isset($assoc)) { $curResVar->value[] = array($assoc, $rvalue); } else { $curResVar->value[] = array(null, $rvalue); } } else { if ($opc == XC_INIT_ARRAY) { $resvar = new Decompiler_Array(); if (!isset($rvalue)) { continue; } } $assoc = $this->getOpVal($op2, $EX); if (isset($assoc)) { $resvar->value[] = array($assoc, $rvalue); } else { $resvar->value[] = array(null, $rvalue); } } break; // }}} case XC_QM_ASSIGN: case XC_QM_ASSIGN_VAR: // {{{ if (isset($curResVar) && is_a($curResVar, 'Decompiler_Binop')) { $curResVar->op2 = $this->getOpVal($op1, $EX); } else { $resvar = $this->getOpVal($op1, $EX); } break; // }}} case XC_BOOL: // {{{ $resvar = /*'(bool) ' .*/ $this->getOpVal($op1, $EX); break; // }}} case XC_GENERATOR_RETURN: case XC_RETURN: // {{{ $resvar = "return " . str($this->getOpVal($op1, $EX)); break; // }}} case XC_INCLUDE_OR_EVAL: // {{{ $type = ZEND_ENGINE_2_4 ? $ext : $op2['var']; // hack $keyword = $this->includeTypes[$type]; $resvar = "$keyword " . str($this->getOpVal($op1, $EX)); break; // }}} case XC_FE_RESET: // {{{ $resvar = $this->getOpVal($op1, $EX); break; // }}} case XC_FE_FETCH: // {{{ $op['fe_src'] = $this->getOpVal($op1, $EX, true); $fe = new Decompiler_ForeachBox($op); $fe->iskey = false; if (ZEND_ENGINE_2_1) { // save current first $T[$res['var']] = $fe; // move to next opcode ++ $i; assert($opcodes[$i]['opcode'] == XC_OP_DATA); $fe = new Decompiler_ForeachBox($op); $fe->iskey = true; $res = $opcodes[$i]['result']; } $resvar = $fe; break; // }}} case XC_YIELD: // {{{ $resvar = 'yield ' . str($this->getOpVal($op1, $EX)); break; // }}} case XC_SWITCH_FREE: // {{{ if (isset($T[$op1['var']])) { $this->beginComplexBlock($EX); echo $EX['indent'], 'switch (', str($this->getOpVal($op1, $EX)), ") {", PHP_EOL; echo $EX['indent'], '}', PHP_EOL; $this->endComplexBlock($EX); } break; // }}} case XC_FREE: // {{{ $free = $T[$op1['var']]; if (!is_a($free, 'Decompiler_Array') && !is_a($free, 'Decompiler_Box')) { $op['php'] = is_object($free) ? $free : $this->unquote($free, '(', ')'); $lastphpop = &$op; } unset($T[$op1['var']], $free); break; // }}} case XC_JMP_NO_CTOR: break; case XC_JMPZ_EX: // and case XC_JMPNZ_EX: // or $resvar = $this->getOpVal($op1, $EX); break; case XC_JMPNZ: // while case XC_JMPZNZ: // for case XC_JMPZ: // {{{ break; // }}} case XC_CONT: case XC_BRK: $resvar = $opc == XC_CONT ? 'continue' : 'break'; $count = str($this->getOpVal($op2, $EX)); if ($count != '1') { $resvar .= ' ' . $count; } break; case XC_GOTO: $resvar = 'goto label' . $op['op1']['var']; $istmpres = false; break; case XC_JMP: // {{{ break; // }}} case XC_CASE: // $switchValue = $this->getOpVal($op1, $EX); $caseValue = $this->getOpVal($op2, $EX); $resvar = $caseValue; break; case XC_RECV_INIT: case XC_RECV: $offset = isset($op1['var']) ? $op1['var'] : $op1['constant']; $lvalue = $this->getOpVal($op['result'], $EX); if ($opc == XC_RECV_INIT) { $default = value($op['op2']['constant'], $EX); } else { $default = null; } $EX['recvs'][$offset] = array($lvalue, $default); break; case XC_POST_DEC: case XC_POST_INC: case XC_POST_DEC_OBJ: case XC_POST_INC_OBJ: case XC_PRE_DEC: case XC_PRE_INC: case XC_PRE_DEC_OBJ: case XC_PRE_INC_OBJ: // {{{ $flags = array_flip(explode('_', $opname)); if (isset($flags['OBJ'])) { $resvar = str($this->getOpVal($op1, $EX)) . '->' . $op2['constant']; } else { $resvar = str($this->getOpVal($op1, $EX)); } $opstr = isset($flags['DEC']) ? '--' : '++'; if (isset($flags['POST'])) { $resvar .= $opstr; } else { $resvar = "$opstr$resvar"; } break; // }}} case XC_BEGIN_SILENCE: // {{{ $EX['silence'] ++; break; // }}} case XC_END_SILENCE: // {{{ $EX['silence'] --; $lastresvar = '@' . str($lastresvar, $EX); break; // }}} case XC_CAST: // {{{ $type = $ext; static $type2cast = array( IS_LONG => '(int)', IS_DOUBLE => '(double)', IS_STRING => '(string)', IS_ARRAY => '(array)', IS_OBJECT => '(object)', IS_BOOL => '(bool)', IS_NULL => '(unset)', ); assert(isset($type2cast[$type])); $cast = $type2cast[$type]; $resvar = $cast . ' ' . str($this->getOpVal($op1, $EX)); break; // }}} case XC_EXT_STMT: case XC_EXT_FCALL_BEGIN: case XC_EXT_FCALL_END: case XC_EXT_NOP: case XC_INIT_CTOR_CALL: break; case XC_DECLARE_FUNCTION: $this->dfunction($this->dc['function_table'][$op1['constant']], $EX['indent']); break; case XC_DECLARE_LAMBDA_FUNCTION: // {{{ ob_start(); $this->dfunction($this->dc['function_table'][$op1['constant']], $EX['indent']); $resvar = ob_get_clean(); $istmpres = true; break; // }}} case XC_DECLARE_CONST: $name = $this->stripNamespace(unquoteName($this->getOpVal($op1, $EX), $EX)); $value = str($this->getOpVal($op2, $EX)); $resvar = 'const ' . $name . ' = ' . $value; break; case XC_DECLARE_FUNCTION_OR_CLASS: /* always removed by compiler */ break; case XC_TICKS: $lastphpop['ticks'] = ZEND_ENGINE_2_4 ? $ext : $this->getOpVal($op1, $EX); // $EX['tickschanged'] = true; break; case XC_RAISE_ABSTRACT_ERROR: // abstract function body is empty, don't need this code break; case XC_USER_OPCODE: echo '// ZEND_USER_OPCODE, impossible to decompile'; break; case XC_OP_DATA: break; default: // {{{ $call = array(&$this, $opname); if (is_callable($call)) { $this->usedOps[$opc] = true; $this->{$opname}($op, $EX); } else if (isset($this->binops[$opc])) { // {{{ $this->usedOps[$opc] = true; $op1val = $this->getOpVal($op1, $EX); $op2val = $this->getOpVal($op2, $EX); $rvalue = new Decompiler_Binop($this, $op1val, $opc, $op2val); $resvar = $rvalue; // }}} } else if (isset($this->unaryops[$opc])) { // {{{ $this->usedOps[$opc] = true; $op1val = $this->getOpVal($op1, $EX); $myop = $this->unaryops[$opc]; $rvalue = $myop . str($op1val); $resvar = $rvalue; // }}} } else { $notHandled = true; } // }}} } if ($notHandled) { echo "\x1B[31m * TODO ", $opname, "\x1B[0m\n"; } else { $this->usedOps[$opc] = true; } if (isset($resvar)) { if ($istmpres) { $T[$res['var']] = $resvar; $lastresvar = &$T[$res['var']]; } else { $op['php'] = $resvar; $lastphpop = &$op; $lastresvar = &$op['php']; } } } return $T; } // }}} function unquote($str, $st, $ed) // {{{ { $l1 = strlen($st); $l2 = strlen($ed); if (substr($str, 0, $l1) === $st && substr($str, -$l2) === $ed) { $str = substr($str, $l1, -$l2); } return $str; } // }}} function popargs(&$EX, $n) // {{{ { $args = array(); for ($i = 0; $i < $n; $i ++) { $a = array_pop($EX['argstack']); if (is_array($a)) { array_unshift($args, foldToCode($a, $EX)); } else { array_unshift($args, $a); } } return implode(', ', $args); } // }}} function dumpop($op, &$EX) // {{{ { assert('isset($op)'); $op1 = $op['op1']; $op2 = $op['op2']; $d = array(xcache_get_opcode($op['opcode']), $op['opcode']); foreach (array('op1' => '1:', 'op2' => '2:', 'result' => '>') as $k => $kk) { switch ($op[$k]['op_type']) { case XC_IS_UNUSED: $d[$kk] = 'U:' . $op[$k]['opline_num']; break; case XC_IS_VAR: $d[$kk] = '$' . $op[$k]['var']; if ($k != 'result') { $d[$kk] .= ':' . str($this->getOpVal($op[$k], $EX)); } break; case XC_IS_TMP_VAR: $d[$kk] = '#' . $op[$k]['var']; if ($k != 'result') { $d[$kk] .= ':' . str($this->getOpVal($op[$k], $EX)); } break; case XC_IS_CV: $d[$kk] = $this->getOpVal($op[$k], $EX); break; default: $d[$kk] = $this->getOpVal($op[$k], $EX); } } $d[';'] = $op['extended_value']; if (!empty($op['jmpouts'])) { $d['>>'] = implode(',', $op['jmpouts']); } if (!empty($op['jmpins'])) { $d['<<'] = implode(',', $op['jmpins']); } foreach ($d as $k => $v) { echo is_int($k) ? '' : $k, str($v), "\t"; } echo PHP_EOL; } // }}} function dumpRange(&$EX, $range) // {{{ { for ($i = $range[0]; $i <= $range[1]; ++$i) { echo $EX['indent'], $i, "\t"; $this->dumpop($EX['opcodes'][$i], $EX); } echo $EX['indent'], "==", PHP_EOL; } // }}} function dargs(&$EX) // {{{ { $op_array = &$EX['op_array']; if (isset($op_array['num_args'])) { $c = $op_array['num_args']; } else if (!empty($op_array['arg_types'])) { $c = count($op_array['arg_types']); } else { // php4 $c = count($EX['recvs']); } $refrest = false; for ($i = 0; $i < $c; $i ++) { if ($i) { echo ', '; } $arg = $EX['recvs'][$i + 1]; if (isset($op_array['arg_info'])) { $ai = $op_array['arg_info'][$i]; if (isset($ai['type_hint']) ? ($ai['type_hint'] == IS_CALLABLE || $ai['type_hint'] == IS_OBJECT) : !empty($ai['class_name'])) { echo $this->stripNamespace($ai['class_name']), ' '; if (!ZEND_ENGINE_2_2 && $ai['allow_null']) { echo 'or NULL '; } } else if (isset($ai['type_hint']) ? $ai['type_hint'] == IS_ARRAY : !empty($ai['array_type_hint'])) { echo 'array '; if (!ZEND_ENGINE_2_2 && $ai['allow_null']) { echo 'or NULL '; } } if ($ai['pass_by_reference']) { echo '&'; } printf("\$%s", $ai['name']); } else { if ($refrest) { echo '&'; } else if (!empty($op_array['arg_types']) && isset($op_array['arg_types'][$i])) { switch ($op_array['arg_types'][$i]) { case BYREF_FORCE_REST: $refrest = true; /* fall */ case BYREF_FORCE: echo '&'; break; case BYREF_NONE: case BYREF_ALLOW: break; default: assert(0); } } echo str($arg[0], $EX); } if (isset($arg[1])) { echo ' = ', str($arg[1], $EX); } } } // }}} function duses(&$EX) // {{{ { if ($EX['uses']) { echo ' use(', implode(', ', $EX['uses']), ')'; } } // }}} function dfunction($func, $indent = '', $decorations = array(), $nobody = false) // {{{ { $this->detectNamespace($func['op_array']['function_name']); if ($nobody) { $EX = array(); $EX['op_array'] = &$func['op_array']; $EX['recvs'] = array(); $EX['uses'] = array(); } else { ob_start(); $EX = &$this->dop_array($func['op_array'], $indent . INDENT); $body = ob_get_clean(); } $functionName = $this->stripNamespace($func['op_array']['function_name']); $isExpression = false; if ($functionName == '{closure}') { $functionName = ''; $isExpression = true; } echo $isExpression ? '' : $indent; if ($decorations) { echo implode(' ', $decorations), ' '; } echo 'function', $functionName ? ' ' . $functionName : '', '('; $this->dargs($EX); echo ")"; $this->duses($EX); if ($nobody) { echo ";\n"; } else { if (!$isExpression) { echo "\n"; echo $indent, "{\n"; } else { echo " {\n"; } echo $body; echo "$indent}"; if (!$isExpression) { echo "\n"; } } } // }}} function dclass($class, $indent = '') // {{{ { $this->detectNamespace($class['name']); // {{{ class decl if (!empty($class['doc_comment'])) { echo $indent; echo $class['doc_comment']; echo "\n"; } $isInterface = false; $decorations = array(); if (!empty($class['ce_flags'])) { if ($class['ce_flags'] & ZEND_ACC_INTERFACE) { $isInterface = true; } else { if ($class['ce_flags'] & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS) { $decorations[] = "abstract"; } if ($class['ce_flags'] & ZEND_ACC_FINAL_CLASS) { $decorations[] = "final"; } } } echo $indent; if ($decorations) { echo implode(' ', $decorations), ' '; } echo $isInterface ? 'interface ' : 'class ', $this->stripNamespace($class['name']); if ($class['parent']) { echo ' extends ', $this->stripNamespace($class['parent']); } /* TODO */ if (!empty($class['interfaces'])) { echo ' implements '; echo implode(', ', $class['interfaces']); } echo "\n"; echo $indent, "{"; // }}} $newindent = INDENT . $indent; // {{{ const if (!empty($class['constants_table'])) { echo "\n"; foreach ($class['constants_table'] as $name => $v) { echo $newindent; echo 'const ', $name, ' = '; echo str(value($v, $EX), $newindent); echo ";\n"; } } // }}} // {{{ properties if (ZEND_ENGINE_2 && !ZEND_ENGINE_2_4) { $default_static_members = $class[ZEND_ENGINE_2_1 ? 'default_static_members' : 'static_members']; } $member_variables = $class[ZEND_ENGINE_2 ? 'properties_info' : 'default_properties']; if ($member_variables) { echo "\n"; foreach ($member_variables as $name => $dummy) { $info = isset($class['properties_info']) ? $class['properties_info'][$name] : null; if (isset($info) && !empty($info['doc_comment'])) { echo $newindent; echo $info['doc_comment']; echo "\n"; } echo $newindent; if (ZEND_ENGINE_2) { $static = ($info['flags'] & ZEND_ACC_STATIC); if ($static) { echo "static "; } } $mangleSuffix = ''; if (!ZEND_ENGINE_2) { echo 'var '; } else if (!isset($info)) { echo 'public '; } else { if ($info['flags'] & ZEND_ACC_SHADOW) { continue; } switch ($info['flags'] & ZEND_ACC_PPP_MASK) { case ZEND_ACC_PUBLIC: echo "public "; break; case ZEND_ACC_PRIVATE: echo "private "; $mangleSuffix = "\000"; break; case ZEND_ACC_PROTECTED: echo "protected "; $mangleSuffix = "\000"; break; } } echo '$', $name; if (ZEND_ENGINE_2_4) { $value = $class[$static ? 'default_static_members_table' : 'default_properties_table'][$info['offset']]; } else if (!ZEND_ENGINE_2) { $value = $class['default_properties'][$name]; } else { $key = $info['name'] . $mangleSuffix; if ($static) { $value = $default_static_members[$key]; } else { $value = $class['default_properties'][$key]; } } if (isset($value)) { echo ' = '; echo str(value($value, $EX), $newindent); } echo ";\n"; } } // }}} // {{{ function_table if (isset($class['function_table'])) { foreach ($class['function_table'] as $func) { if (!isset($func['scope']) || $func['scope'] == $class['name']) { // TODO: skip shadow here echo "\n"; $opa = $func['op_array']; if (!empty($opa['doc_comment'])) { echo $newindent; echo $opa['doc_comment']; echo "\n"; } $isAbstractMethod = false; $decorations = array(); if (isset($opa['fn_flags'])) { if (($opa['fn_flags'] & ZEND_ACC_ABSTRACT) && !$isInterface) { $decorations[] = "abstract"; $isAbstractMethod = true; } if ($opa['fn_flags'] & ZEND_ACC_FINAL) { $decorations[] = "final"; } if ($opa['fn_flags'] & ZEND_ACC_STATIC) { $decorations[] = "static"; } switch ($opa['fn_flags'] & ZEND_ACC_PPP_MASK) { case ZEND_ACC_PUBLIC: $decorations[] = "public"; break; case ZEND_ACC_PRIVATE: $decorations[] = "private"; break; case ZEND_ACC_PROTECTED: $decorations[] = "protected"; break; default: $decorations[] = ""; break; } } $this->activeMethod = $this->activeClass . '::' . $opa['function_name']; $this->activeFunction = $opa['function_name']; $this->dfunction($func, $newindent, $decorations, $isInterface || $isAbstractMethod); $this->activeFunction = null; $this->activeMethod = null; if ($opa['function_name'] == 'Decompiler') { //exit; } } } } // }}} echo $indent, "}\n"; } // }}} function decompileString($string) // {{{ { $this->dc = xcache_dasm_string($string); if ($this->dc === false) { echo "error compling string\n"; return false; } $this->activeFile = null; return true; } // }}} function decompileFile($file) // {{{ { $this->dc = xcache_dasm_file($file); if ($this->dc === false) { echo "error compling $file\n"; return false; } $this->activeFile = realpath($file); return true; } // }}} function decompileDasm($content) // {{{ { $this->dc = $content; $this->activeFile = null; return true; } // }}} function output() // {{{ { echo "dc['class_table'] as $key => $class) { if ($key{0} != "\0") { $this->activeClass = $class['name']; $this->dclass($class); $this->activeClass = null; echo "\n"; } } foreach ($this->dc['function_table'] as $key => $func) { if ($key{0} != "\0") { $this->activeFunction = $key; $this->dfunction($func); $this->activeFunction = null; echo "\n"; } } $this->dop_array($this->dc['op_array']); echo "\n?" . ">\n"; if (!empty($this->test)) { $this->outputUnusedOp(); } return true; } // }}} function outputUnusedOp() // {{{ { for ($i = 0; $opname = xcache_get_opcode($i); $i ++) { if ($opname == 'UNDEF') { continue; } if (!isset($this->usedOps[$i])) { echo "not covered opcode ", $opname, "\n"; } } } // }}} } // {{{ defines define('ZEND_ENGINE_2_4', PHP_VERSION >= "5.4"); define('ZEND_ENGINE_2_3', ZEND_ENGINE_2_4 || PHP_VERSION >= "5.3."); define('ZEND_ENGINE_2_2', ZEND_ENGINE_2_3 || PHP_VERSION >= "5.2."); define('ZEND_ENGINE_2_1', ZEND_ENGINE_2_2 || PHP_VERSION >= "5.1."); define('ZEND_ENGINE_2', ZEND_ENGINE_2_1 || PHP_VERSION >= "5.0."); define('ZEND_ACC_STATIC', 0x01); define('ZEND_ACC_ABSTRACT', 0x02); define('ZEND_ACC_FINAL', 0x04); define('ZEND_ACC_IMPLEMENTED_ABSTRACT', 0x08); define('ZEND_ACC_IMPLICIT_ABSTRACT_CLASS', 0x10); define('ZEND_ACC_EXPLICIT_ABSTRACT_CLASS', 0x20); define('ZEND_ACC_FINAL_CLASS', 0x40); define('ZEND_ACC_INTERFACE', 0x80); if (ZEND_ENGINE_2_4) { define('ZEND_ACC_TRAIT', 0x120); } define('ZEND_ACC_PUBLIC', 0x100); define('ZEND_ACC_PROTECTED', 0x200); define('ZEND_ACC_PRIVATE', 0x400); define('ZEND_ACC_PPP_MASK', (ZEND_ACC_PUBLIC | ZEND_ACC_PROTECTED | ZEND_ACC_PRIVATE)); define('ZEND_ACC_CHANGED', 0x800); define('ZEND_ACC_IMPLICIT_PUBLIC', 0x1000); define('ZEND_ACC_CTOR', 0x2000); define('ZEND_ACC_DTOR', 0x4000); define('ZEND_ACC_CLONE', 0x8000); define('ZEND_ACC_ALLOW_STATIC', 0x10000); define('ZEND_ACC_SHADOW', 0x2000); if (ZEND_ENGINE_2_4) { define('ZEND_FETCH_GLOBAL', 0x00000000); define('ZEND_FETCH_LOCAL', 0x10000000); define('ZEND_FETCH_STATIC', 0x20000000); define('ZEND_FETCH_STATIC_MEMBER', 0x30000000); define('ZEND_FETCH_GLOBAL_LOCK', 0x40000000); define('ZEND_FETCH_LEXICAL', 0x50000000); define('ZEND_FETCH_TYPE_MASK', 0x70000000); define('ZEND_FETCH_STANDARD', 0x00000000); define('ZEND_FETCH_ADD_LOCK', 0x08000000); define('ZEND_FETCH_MAKE_REF', 0x04000000); } else { define('ZEND_FETCH_GLOBAL', 0); define('ZEND_FETCH_LOCAL', 1); define('ZEND_FETCH_STATIC', 2); define('ZEND_FETCH_STATIC_MEMBER', 3); define('ZEND_FETCH_GLOBAL_LOCK', 4); define('ZEND_FETCH_STANDARD', 0); define('ZEND_FETCH_ADD_LOCK', 1); } if (ZEND_ENGINE_2_4) { define('ZEND_ISSET', 0x02000000); define('ZEND_ISEMPTY', 0x01000000); define('ZEND_ISSET_ISEMPTY_MASK', (ZEND_ISSET | ZEND_ISEMPTY)); define('ZEND_QUICK_SET', 0x00800000); } else { define('ZEND_ISSET', (1<<0)); define('ZEND_ISEMPTY', (1<<1)); define('ZEND_ISSET_ISEMPTY_MASK', (ZEND_ISSET | ZEND_ISEMPTY)); } define('ZEND_FETCH_CLASS_DEFAULT', 0); define('ZEND_FETCH_CLASS_SELF', 1); define('ZEND_FETCH_CLASS_PARENT', 2); define('ZEND_FETCH_CLASS_MAIN', 3); define('ZEND_FETCH_CLASS_GLOBAL', 4); define('ZEND_FETCH_CLASS_AUTO', 5); define('ZEND_FETCH_CLASS_INTERFACE', 6); define('ZEND_FETCH_CLASS_STATIC', 7); if (ZEND_ENGINE_2_4) { define('ZEND_FETCH_CLASS_TRAIT', 14); } if (ZEND_ENGINE_2_3) { define('ZEND_FETCH_CLASS_MASK', 0xF); } define('ZEND_EVAL', (1<<0)); define('ZEND_INCLUDE', (1<<1)); define('ZEND_INCLUDE_ONCE', (1<<2)); define('ZEND_REQUIRE', (1<<3)); define('ZEND_REQUIRE_ONCE', (1<<4)); if (ZEND_ENGINE_2_4) { define('EXT_TYPE_UNUSED', (1<<5)); } else { define('EXT_TYPE_UNUSED', (1<<0)); } if (ZEND_ENGINE_2_1) { define('ZEND_FE_FETCH_BYREF', 1); define('ZEND_FE_FETCH_WITH_KEY', 2); } else { define('ZEND_UNSET_DIM', 1); define('ZEND_UNSET_OBJ', 2); } define('ZEND_MEMBER_FUNC_CALL', 1<<0); define('ZEND_CTOR_CALL', 1<<1); define('ZEND_ARG_SEND_BY_REF', (1<<0)); define('ZEND_ARG_COMPILE_TIME_BOUND', (1<<1)); define('ZEND_ARG_SEND_FUNCTION', (1<<2)); define('BYREF_NONE', 0); define('BYREF_FORCE', 1); define('BYREF_ALLOW', 2); define('BYREF_FORCE_REST', 3); define('IS_NULL', 0); define('IS_LONG', 1); define('IS_DOUBLE', 2); define('IS_BOOL', ZEND_ENGINE_2_1 ? 3 : 6); define('IS_ARRAY', 4); define('IS_OBJECT', 5); define('IS_STRING', ZEND_ENGINE_2_1 ? 6 : 3); define('IS_RESOURCE', 7); define('IS_CONSTANT', 8); define('IS_CONSTANT_ARRAY', 9); if (ZEND_ENGINE_2_4) { define('IS_CALLABLE', 10); } /* Ugly hack to support constants as static array indices */ define('IS_CONSTANT_TYPE_MASK', 0x0f); define('IS_CONSTANT_UNQUALIFIED', 0x10); define('IS_CONSTANT_INDEX', 0x80); define('IS_LEXICAL_VAR', 0x20); define('IS_LEXICAL_REF', 0x40); @define('XC_IS_CV', 16); /* if (preg_match_all('!XC_[A-Z_]+!', file_get_contents(__FILE__), $ms)) { $verdiff = array(); foreach ($ms[0] as $k) { if (!defined($k)) { $verdiff[$k] = -1; define($k, -1); } } var_export($verdiff); exit; } //*/ foreach (array ( 'XC_ADD_INTERFACE' => -1, 'XC_ASSIGN_DIM' => -1, 'XC_ASSIGN_OBJ' => -1, 'XC_CATCH' => -1, 'XC_CLONE' => -1, 'XC_DECLARE_CLASS' => -1, 'XC_DECLARE_CONST' => -1, 'XC_DECLARE_FUNCTION' => -1, 'XC_DECLARE_FUNCTION_OR_CLASS' => -1, 'XC_DECLARE_INHERITED_CLASS' => -1, 'XC_DECLARE_INHERITED_CLASS_DELAYED' => -1, 'XC_DECLARE_LAMBDA_FUNCTION' => -1, 'XC_DO_FCALL_BY_FUNC' => -1, 'XC_FETCH_CLASS' => -1, 'XC_GENERATOR_RETURN' => -1, 'XC_GOTO' => -1, 'XC_HANDLE_EXCEPTION' => -1, 'XC_INIT_CTOR_CALL' => -1, 'XC_INIT_FCALL_BY_FUNC' => -1, 'XC_INIT_METHOD_CALL' => -1, 'XC_INIT_NS_FCALL_BY_NAME' => -1, 'XC_INIT_STATIC_METHOD_CALL' => -1, 'XC_INSTANCEOF' => -1, 'XC_ISSET_ISEMPTY' => -1, 'XC_ISSET_ISEMPTY_DIM_OBJ' => -1, 'XC_ISSET_ISEMPTY_PROP_OBJ' => -1, 'XC_ISSET_ISEMPTY_VAR' => -1, 'XC_JMP_NO_CTOR' => -1, 'XC_JMP_SET' => -1, 'XC_JMP_SET_VAR' => -1, 'XC_OP_DATA' => -1, 'XC_POST_DEC_OBJ' => -1, 'XC_POST_INC_OBJ' => -1, 'XC_PRE_DEC_OBJ' => -1, 'XC_PRE_INC_OBJ' => -1, 'XC_QM_ASSIGN_VAR' => -1, 'XC_RAISE_ABSTRACT_ERROR' => -1, 'XC_THROW' => -1, 'XC_UNSET_DIM' => -1, 'XC_UNSET_DIM_OBJ' => -1, 'XC_UNSET_OBJ' => -1, 'XC_USER_OPCODE' => -1, 'XC_VERIFY_ABSTRACT_CLASS' => -1, 'XC_YIELD' => -1, ) as $k => $v) { if (!defined($k)) { define($k, $v); } } // }}} xcache-3.1.0/Makefile.frag0000644000175000010010000000406512167422206013533 0ustar mOoNoneXCACHE_PROC_SRC=$(srcdir)/processor/main.m4 XCACHE_PROC_OUT=$(builddir)/processor.out.c XCACHE_PROC_C=$(builddir)/xc_processor.c.h XCACHE_PROC_H=$(builddir)/xc_processor.h XCACHE_INCLUDES_SRC=$(srcdir)/includes.c XCACHE_INCLUDES_I=$(builddir)/includes.i XCACHE_STRUCTINFO_OUT=$(builddir)/structinfo.m4 $(XCACHE_INCLUDES_I): $(CC) -I. -I$(srcdir) $(COMMON_FLAGS) $(CFLAGS_CLEAN) $(EXTRA_CFLAGS) -E $(XCACHE_INCLUDES_SRC) -o $(XCACHE_INCLUDES_I) $(XCACHE_STRUCTINFO_OUT): $(XCACHE_INCLUDES_I) $(srcdir)/gen_structinfo.awk @echo $(XCACHE_STRUCTINFO_OUT) is optional if XCache test is not enabled, feel free if it awk failed to produce it -$(XCACHE_AWK) -f $(srcdir)/gen_structinfo.awk < $(XCACHE_INCLUDES_I) > $(XCACHE_STRUCTINFO_OUT).tmp && mv $(XCACHE_STRUCTINFO_OUT).tmp $(XCACHE_STRUCTINFO_OUT) $(XCACHE_PROC_OUT): $(XCACHE_PROC_SRC) $(XCACHE_STRUCTINFO_OUT) $(XCACHE_PROC_SOURCES) $(M4) -D srcdir=$(XCACHE_BACKTICK)"$(srcdir)'" -D builddir=$(XCACHE_BACKTICK)"$(builddir)'" $(XCACHE_ENABLE_TEST) $(XCACHE_PROC_SRC) > $(XCACHE_PROC_OUT).tmp mv $(XCACHE_PROC_OUT).tmp $(XCACHE_PROC_OUT) $(XCACHE_PROC_H): $(XCACHE_PROC_OUT) $(GREP) "export: " $(XCACHE_PROC_OUT) | $(SED) "s/.*export:\(.*\):export.*/\1/g" > $(XCACHE_PROC_H) -$(XCACHE_INDENT) < $(XCACHE_PROC_H) > $(XCACHE_PROC_H).tmp && mv $(XCACHE_PROC_H).tmp $(XCACHE_PROC_H) $(XCACHE_PROC_C): $(XCACHE_PROC_OUT) $(XCACHE_PROC_H) cp $(XCACHE_PROC_OUT) $(XCACHE_PROC_C) -$(XCACHE_INDENT) < $(XCACHE_PROC_OUT) > $(XCACHE_PROC_C).tmp && mv $(XCACHE_PROC_C).tmp $(XCACHE_PROC_C) xcachesvnclean: clean -svn propget svn:ignore . > .svnignore.tmp 2>/dev/null && mv .svnignore.tmp .svnignore cat .svnignore | grep -v devel | grep -v svnignore | grep -v ^Makefile | grep -v ^config.nice | xargs rm -rf xcachetest: all $(SED) "s#\\./\\.libs/#$(top_builddir)/\\.libs/#" < $(srcdir)/xcache-test.ini > $(top_builddir)/tmp-php.ini if test -z "$(TESTS)"; then \ TEST_PHP_SRCDIR=$(srcdir) $(srcdir)/run-xcachetest $(TEST_ARGS) -c $(top_builddir)/tmp-php.ini; \ fi $(srcdir)/run-xcachetest $(TESTS) $(TEST_ARGS) -c $(top_builddir)/tmp-php.ini xcache-3.1.0/Makefile.frag.deps0000644000175000010010000001276312213477011014465 0ustar mOoNone$(XCACHE_INCLUDES_I) includes.lo $(builddir)/includes.lo: $(srcdir)/mod_cacher/xc_cache.h $(srcdir)/xcache.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_mutex.h $(srcdir)/xcache/xc_shm.h $(srcdir)/xcache/xc_utils.h mod_assembler/xc_assembler.lo $(builddir)/mod_assembler/xc_assembler.lo: mod_cacher/xc_cacher.lo $(builddir)/mod_cacher/xc_cacher.lo: $(srcdir)/mod_cacher/xc_cache.h $(srcdir)/mod_cacher/xc_cacher.h $(srcdir)/util/xc_align.h $(srcdir)/util/xc_stack.h $(srcdir)/util/xc_trace.h $(srcdir)/util/xc_vector.h $(srcdir)/xcache_globals.h $(srcdir)/xcache.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_extension.h $(srcdir)/xcache/xc_ini.h $(srcdir)/xcache/xc_mutex.h $(srcdir)/xcache/xc_sandbox.h $(srcdir)/xcache/xc_shm.h $(srcdir)/xcache/xc_utils.h $(XCACHE_PROC_H) mod_coverager/xc_coverager.lo $(builddir)/mod_coverager/xc_coverager.lo: $(srcdir)/mod_coverager/xc_coverager.h $(srcdir)/util/xc_stack.h $(srcdir)/util/xc_trace.h $(srcdir)/xcache_globals.h $(srcdir)/xcache.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_extension.h $(srcdir)/xcache/xc_ini.h $(srcdir)/xcache/xc_mutex.h $(srcdir)/xcache/xc_shm.h $(srcdir)/xcache/xc_utils.h mod_decoder/xc_decoder.lo $(builddir)/mod_decoder/xc_decoder.lo: mod_disassembler/xc_disassembler.lo $(builddir)/mod_disassembler/xc_disassembler.lo: $(srcdir)/mod_disassembler/xc_disassembler.h $(srcdir)/xcache.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_ini.h $(srcdir)/xcache/xc_mutex.h $(srcdir)/xcache/xc_sandbox.h $(srcdir)/xcache/xc_shm.h $(srcdir)/xcache/xc_utils.h $(XCACHE_PROC_H) mod_encoder/xc_encoder.lo $(builddir)/mod_encoder/xc_encoder.lo: mod_optimizer/xc_optimizer.lo $(builddir)/mod_optimizer/xc_optimizer.lo: $(srcdir)/mod_optimizer/xc_optimizer.h $(srcdir)/util/xc_stack.h $(srcdir)/util/xc_trace.h $(srcdir)/xcache_globals.h $(srcdir)/xcache.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_const_string.h $(srcdir)/xcache/xc_extension.h $(srcdir)/xcache/xc_ini.h $(srcdir)/xcache/xc_mutex.h $(srcdir)/xcache/xc_opcode_spec.h $(srcdir)/xcache/xc_shm.h $(srcdir)/xcache/xc_utils.h $(XCACHE_PROC_H) util/xc_stack.lo $(builddir)/util/xc_stack.lo: $(srcdir)/util/xc_stack.h $(srcdir)/util/xc_trace.h util/xc_trace.lo $(builddir)/util/xc_trace.lo: $(srcdir)/util/xc_trace.h xcache.lo $(builddir)/xcache.lo: $(srcdir)/util/xc_foreachcoresig.h $(srcdir)/util/xc_stack.h $(srcdir)/xcache_globals.h $(srcdir)/xcache.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_const_string.h $(srcdir)/xcache/xc_extension.h $(srcdir)/xcache/xc_ini.h $(srcdir)/xcache/xc_mutex.h $(srcdir)/xcache/xc_opcode_spec.h $(srcdir)/xcache/xc_shm.h $(srcdir)/xcache/xc_utils.h $(XCACHE_PROC_H) xcache/xc_allocator_bestfit.lo $(builddir)/xcache/xc_allocator_bestfit.lo: $(srcdir)/util/xc_align.h $(srcdir)/util/xc_trace.h $(srcdir)/xcache/xc_allocator.h $(srcdir)/xcache/xc_shm.h xcache/xc_allocator.lo $(builddir)/xcache/xc_allocator.lo: $(srcdir)/xcache/xc_allocator.h $(srcdir)/xcache/xc_shm.h xcache/xc_compatibility.lo $(builddir)/xcache/xc_compatibility.lo: $(srcdir)/xcache/xc_compatibility.h xcache/xc_const_string.lo $(builddir)/xcache/xc_const_string.lo: $(srcdir)/xcache.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_const_string.h $(srcdir)/xcache/xc_const_string_opcodes_php4.x.h $(srcdir)/xcache/xc_const_string_opcodes_php5.0.h $(srcdir)/xcache/xc_const_string_opcodes_php5.1.h $(srcdir)/xcache/xc_const_string_opcodes_php5.2.h $(srcdir)/xcache/xc_const_string_opcodes_php5.3.h $(srcdir)/xcache/xc_const_string_opcodes_php5.4.h $(srcdir)/xcache/xc_const_string_opcodes_php5.5.h $(srcdir)/xcache/xc_const_string_opcodes_php6.x.h $(srcdir)/xcache/xc_mutex.h $(srcdir)/xcache/xc_shm.h xcache/xc_extension.lo $(builddir)/xcache/xc_extension.lo: $(srcdir)/util/xc_stack.h $(srcdir)/util/xc_trace.h $(srcdir)/xcache.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_extension.h $(srcdir)/xcache/xc_mutex.h $(srcdir)/xcache/xc_shm.h xcache/xc_ini.lo $(builddir)/xcache/xc_ini.lo: $(srcdir)/xcache/xc_ini.h xcache/xc_malloc.lo $(builddir)/xcache/xc_malloc.lo: $(srcdir)/util/xc_align.h $(srcdir)/xcache.h $(srcdir)/xcache/xc_allocator.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_mutex.h $(srcdir)/xcache/xc_shm.h xcache/xc_mutex.lo $(builddir)/xcache/xc_mutex.lo: $(srcdir)/xcache.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_mutex.h $(srcdir)/xcache/xc_shm.h xcache/xc_opcode_spec.lo $(builddir)/xcache/xc_opcode_spec.lo: $(srcdir)/xcache.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_const_string.h $(srcdir)/xcache/xc_mutex.h $(srcdir)/xcache/xc_opcode_spec_def.h $(srcdir)/xcache/xc_opcode_spec.h $(srcdir)/xcache/xc_shm.h xcache/xc_processor.lo $(builddir)/xcache/xc_processor.lo: $(XCACHE_PROC_C) xcache/xc_sandbox.lo $(builddir)/xcache/xc_sandbox.lo: $(srcdir)/util/xc_stack.h $(srcdir)/xcache_globals.h $(srcdir)/xcache.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_mutex.h $(srcdir)/xcache/xc_sandbox.h $(srcdir)/xcache/xc_shm.h $(srcdir)/xcache/xc_utils.h xcache/xc_shm.lo $(builddir)/xcache/xc_shm.lo: $(srcdir)/xcache/xc_shm.h xcache/xc_shm_mmap.lo $(builddir)/xcache/xc_shm_mmap.lo: $(srcdir)/xcache.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_mutex.h $(srcdir)/xcache/xc_shm.h $(srcdir)/xcache/xc_utils.h xcache/xc_utils.lo $(builddir)/xcache/xc_utils.lo: $(srcdir)/util/xc_stack.h $(srcdir)/util/xc_trace.h $(srcdir)/xcache_globals.h $(srcdir)/xcache.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_mutex.h $(srcdir)/xcache/xc_opcode_spec.h $(srcdir)/xcache/xc_shm.h $(srcdir)/xcache/xc_utils.h xcache-3.1.0/mod_assembler/0000755000175000010010000000000012157744741013776 5ustar mOoNonexcache-3.1.0/mod_assembler/xc_assembler.c0000644000175000010010000000000012157744741016577 0ustar mOoNonexcache-3.1.0/mod_cacher/0000755000175000010010000000000012213477010013227 5ustar mOoNonexcache-3.1.0/mod_cacher/xc_cache.h0000644000175000010010000001101012206607317015135 0ustar mOoNone#ifndef XC_CACHE_H_684B099102B4651FB10058EF6F7E80CE #define XC_CACHE_H_684B099102B4651FB10058EF6F7E80CE #if _MSC_VER > 1000 #pragma once #endif /* _MSC_VER > 1000 */ #include "xcache.h" #include "xcache/xc_compatibility.h" typedef ulong xc_hash_value_t; typedef struct _xc_hash_t xc_hash_t; typedef struct _xc_cached_t xc_cached_t; typedef struct _xc_entry_t xc_entry_t; typedef struct _xc_entry_data_php_t xc_entry_data_php_t; struct _xc_lock_t; struct _xc_shm_t; /* {{{ xc_op_array_info_detail_t */ typedef struct { zend_uint index; zend_uint info; } xc_op_array_info_detail_t; /* }}} */ /* {{{ xc_op_array_info_t */ typedef struct { #ifdef ZEND_ENGINE_2_4 zend_uint literalinfo_cnt; xc_op_array_info_detail_t *literalinfos; #else zend_uint oplineinfo_cnt; xc_op_array_info_detail_t *oplineinfos; #endif } xc_op_array_info_t; /* }}} */ /* {{{ xc_classinfo_t */ typedef struct { #ifdef IS_UNICODE zend_uchar type; #endif const24_zstr key; zend_uint key_size; ulong h; zend_uint methodinfo_cnt; xc_op_array_info_t *methodinfos; xc_cest_t cest; #ifndef ZEND_COMPILE_DELAYED_BINDING int oplineno; #endif } xc_classinfo_t; /* }}} */ #ifdef HAVE_XCACHE_CONSTANT /* {{{ xc_constinfo_t */ typedef struct { #ifdef IS_UNICODE zend_uchar type; #endif const24_zstr key; zend_uint key_size; ulong h; zend_constant constant; } xc_constinfo_t; /* }}} */ #endif /* {{{ xc_funcinfo_t */ typedef struct { #ifdef IS_UNICODE zend_uchar type; #endif const24_zstr key; zend_uint key_size; ulong h; xc_op_array_info_t op_array_info; zend_function func; } xc_funcinfo_t; /* }}} */ #ifdef ZEND_ENGINE_2_1 /* {{{ xc_autoglobal_t */ typedef struct { #ifdef IS_UNICODE zend_uchar type; #endif const24_zstr key; zend_uint key_len; ulong h; } xc_autoglobal_t; /* }}} */ #endif typedef struct { char digest[16]; } xc_md5sum_t; struct _xc_compilererror_t; /* {{{ xc_entry_data_php_t */ struct _xc_entry_data_php_t { xc_entry_data_php_t *next; xc_hash_value_t hvalue; xc_md5sum_t md5; /* md5sum of the source */ zend_ulong refcount; /* count of entries referencing to this data */ zend_ulong hits; /* hits of this php */ size_t size; xc_op_array_info_t op_array_info; zend_op_array *op_array; #ifdef HAVE_XCACHE_CONSTANT zend_uint constinfo_cnt; xc_constinfo_t *constinfos; #endif zend_uint funcinfo_cnt; xc_funcinfo_t *funcinfos; zend_uint classinfo_cnt; xc_classinfo_t *classinfos; #ifndef ZEND_COMPILE_DELAYED_BINDING zend_bool have_early_binding; #endif #ifdef ZEND_ENGINE_2_1 zend_uint autoglobal_cnt; xc_autoglobal_t *autoglobals; #endif #ifdef XCACHE_ERROR_CACHING zend_uint compilererror_cnt; struct _xc_compilererror_t *compilererrors; #endif zend_bool have_references; }; /* }}} */ typedef zvalue_value xc_entry_name_t; /* {{{ xc_entry_t */ struct _xc_entry_t { xc_entry_t *next; size_t size; time_t ctime; /* creation ctime of this entry */ time_t atime; /* access atime of this entry */ time_t dtime; /* deletion time of this entry */ zend_ulong hits; zend_ulong ttl; xc_entry_name_t name; }; typedef struct { xc_entry_t entry; xc_entry_data_php_t *php; zend_ulong refcount; /* count of php instances holding this entry */ time_t file_mtime; size_t file_size; size_t file_device; size_t file_inode; size_t filepath_len; ZEND_24(NOTHING, const) char *filepath; size_t dirpath_len; char *dirpath; #ifdef IS_UNICODE int ufilepath_len; UChar *ufilepath; int udirpath_len; UChar *udirpath; #endif } xc_entry_php_t; typedef struct { xc_entry_t entry; #ifdef IS_UNICODE zend_uchar name_type; #endif zval *value; zend_bool have_references; } xc_entry_var_t; /* }}} */ typedef struct xc_entry_hash_t { /* {{{ */ xc_hash_value_t cacheid; xc_hash_value_t entryslotid; } xc_entry_hash_t; /* }}} */ zend_bool xc_is_rw(const void *p); zend_bool xc_is_ro(const void *p); zend_bool xc_is_shm(const void *p); /* {{{ xc_gc_op_array_t */ typedef struct { #ifdef ZEND_ENGINE_2 zend_uint num_args; zend_arg_info *arg_info; #endif #ifdef ZEND_ENGINE_2_4 zend_literal *literals; #endif zend_op *opcodes; } xc_gc_op_array_t; /* }}} */ void xc_gc_add_op_array(xc_gc_op_array_t *gc_op_array TSRMLS_DC); void xc_fix_op_array_info(const xc_entry_php_t *xce, const xc_entry_data_php_t *php, zend_op_array *op_array, int shallow_copy, const xc_op_array_info_t *op_array_info TSRMLS_DC); #endif /* XC_CACHE_H_684B099102B4651FB10058EF6F7E80CE */ xcache-3.1.0/mod_cacher/xc_cacher.c0000644000175000010010000034006112213477010015316 0ustar mOoNone#if 0 #define XCACHE_DEBUG #endif #if 0 #define SHOW_DPRINT #endif /* {{{ macros */ #include "xc_cacher.h" #include "xc_cache.h" #include "xcache.h" #include "xc_processor.h" #include "xcache_globals.h" #include "xcache/xc_extension.h" #include "xcache/xc_ini.h" #include "xcache/xc_utils.h" #include "xcache/xc_sandbox.h" #include "util/xc_trace.h" #include "util/xc_vector.h" #include "util/xc_align.h" #include "php.h" #include "ext/standard/info.h" #include "ext/standard/md5.h" #ifdef ZEND_ENGINE_2_1 # include "ext/date/php_date.h" #endif #ifdef ZEND_WIN32 # include #endif #include "ext/standard/php_math.h" #include "SAPI.h" #define ECALLOC_N(x, n) ((x) = ecalloc(n, sizeof((x)[0]))) #define ECALLOC_ONE(x) ECALLOC_N(x, 1) #define VAR_ENTRY_EXPIRED(pentry) ((pentry)->ttl && XG(request_time) > (pentry)->ctime + (time_t) (pentry)->ttl) #define CHECK(x, e) do { if ((x) == NULL) { zend_error(E_ERROR, "XCache: " e); goto err; } } while (0) #define LOCK(x) xc_mutex_lock((x)->mutex) #define UNLOCK(x) xc_mutex_unlock((x)->mutex) #define ENTER_LOCK_EX(x) \ LOCK((x)); \ zend_try { \ do #define LEAVE_LOCK_EX(x) \ while (0); \ } zend_catch { \ catched = 1; \ } zend_end_try(); \ UNLOCK((x)) #define ENTER_LOCK(x) do { \ int catched = 0; \ ENTER_LOCK_EX(x) #define LEAVE_LOCK(x) \ LEAVE_LOCK_EX(x); \ if (catched) { \ zend_bailout(); \ } \ } while(0) /* }}} */ struct _xc_hash_t { /* {{{ */ size_t bits; size_t size; xc_hash_value_t mask; }; /* }}} */ struct _xc_cached_t { /* {{{ stored in shm */ int cacheid; time_t compiling; time_t disabled; zend_ulong updates; zend_ulong hits; zend_ulong skips; zend_ulong ooms; zend_ulong errors; xc_entry_t **entries; int entries_count; xc_entry_data_php_t **phps; int phps_count; xc_entry_t *deletes; int deletes_count; time_t last_gc_deletes; time_t last_gc_expires; time_t hits_by_hour_cur_time; zend_uint hits_by_hour_cur_slot; zend_ulong hits_by_hour[24]; time_t hits_by_second_cur_time; zend_uint hits_by_second_cur_slot; zend_ulong hits_by_second[5]; }; /* }}} */ typedef struct { /* {{{ xc_cache_t: only cache info, not in shm */ int cacheid; xc_hash_t *hcache; /* hash to cacheid */ xc_mutex_t *mutex; xc_shm_t *shm; /* which shm contains us */ xc_allocator_t *allocator; xc_hash_t *hentry; /* hash settings to entry */ xc_hash_t *hphp; /* hash settings to php */ xc_cached_t *cached; } xc_cache_t; /* }}} */ /* {{{ globals */ static char *xc_shm_scheme = NULL; static char *xc_mmap_path = NULL; static zend_bool xc_admin_enable_auth = 1; static xc_hash_t xc_php_hcache = { 0, 0, 0 }; static xc_hash_t xc_php_hentry = { 0, 0, 0 }; static xc_hash_t xc_var_hcache = { 0, 0, 0 }; static xc_hash_t xc_var_hentry = { 0, 0, 0 }; static zend_ulong xc_php_ttl = 0; static zend_ulong xc_var_maxttl = 0; enum { xc_deletes_gc_interval = 120 }; static zend_ulong xc_php_gc_interval = 0; static zend_ulong xc_var_gc_interval = 0; static char *xc_php_allocator = NULL; static char *xc_var_allocator = NULL; /* total size */ static zend_ulong xc_php_size = 0; static zend_ulong xc_var_size = 0; static xc_cache_t *xc_php_caches = NULL; static xc_cache_t *xc_var_caches = NULL; static zend_bool xc_initized = 0; static time_t xc_init_time = 0; static long unsigned xc_init_instance_id = 0; #ifdef ZTS static long unsigned xc_init_instance_subid = 0; #endif static zend_compile_file_t *old_compile_file = NULL; static zend_bool xc_readonly_protection = 0; static zend_ulong xc_var_namespace_mode = 0; static char *xc_var_namespace = NULL; zend_bool xc_have_op_array_ctor = 0; /* }}} */ typedef enum { XC_TYPE_PHP, XC_TYPE_VAR } xc_entry_type_t; static void xc_holds_init(TSRMLS_D); static void xc_holds_destroy(TSRMLS_D); /* any function in *_unlocked is only safe be called within locked (single thread access) area */ static void xc_php_add_unlocked(xc_cached_t *cached, xc_entry_data_php_t *php) /* {{{ */ { xc_entry_data_php_t **head = &(cached->phps[php->hvalue]); php->next = *head; *head = php; cached->phps_count ++; } /* }}} */ static xc_entry_data_php_t *xc_php_store_unlocked(xc_cache_t *cache, xc_entry_data_php_t *php TSRMLS_DC) /* {{{ */ { xc_entry_data_php_t *stored_php; php->hits = 0; php->refcount = 0; stored_php = xc_processor_store_xc_entry_data_php_t(cache->shm, cache->allocator, php TSRMLS_CC); if (stored_php) { xc_php_add_unlocked(cache->cached, stored_php); return stored_php; } else { cache->cached->ooms ++; return NULL; } } /* }}} */ static xc_entry_data_php_t *xc_php_find_unlocked(xc_cached_t *cached, xc_entry_data_php_t *php TSRMLS_DC) /* {{{ */ { xc_entry_data_php_t *p; for (p = cached->phps[php->hvalue]; p; p = (xc_entry_data_php_t *) p->next) { if (memcmp(&php->md5.digest, &p->md5.digest, sizeof(php->md5.digest)) == 0) { p->hits ++; return p; } } return NULL; } /* }}} */ static void xc_php_free_unlocked(xc_cache_t *cache, xc_entry_data_php_t *php) /* {{{ */ { cache->allocator->vtable->free(cache->allocator, (xc_entry_data_php_t *)php); } /* }}} */ static void xc_php_addref_unlocked(xc_entry_data_php_t *php) /* {{{ */ { php->refcount ++; } /* }}} */ static void xc_php_release_unlocked(xc_cache_t *cache, xc_entry_data_php_t *php) /* {{{ */ { if (-- php->refcount == 0) { xc_entry_data_php_t **pp = &(cache->cached->phps[php->hvalue]); xc_entry_data_php_t *p; for (p = *pp; p; pp = &(p->next), p = p->next) { if (memcmp(&php->md5.digest, &p->md5.digest, sizeof(php->md5.digest)) == 0) { /* unlink */ *pp = p->next; xc_php_free_unlocked(cache, php); return; } } assert(0); } } /* }}} */ static inline zend_bool xc_entry_equal_unlocked(xc_entry_type_t type, const xc_entry_t *entry1, const xc_entry_t *entry2 TSRMLS_DC) /* {{{ */ { /* this function isn't required but can be in unlocked */ switch (type) { case XC_TYPE_PHP: { const xc_entry_php_t *php_entry1 = (const xc_entry_php_t *) entry1; const xc_entry_php_t *php_entry2 = (const xc_entry_php_t *) entry2; if (php_entry1->file_inode && php_entry2->file_inode) { zend_bool inodeIsSame = php_entry1->file_inode == php_entry2->file_inode && php_entry1->file_device == php_entry2->file_device; if (!inodeIsSame) { return 0; } } } assert(strstr(entry1->name.str.val, "://") != NULL || IS_ABSOLUTE_PATH(entry1->name.str.val, entry1->name.str.len)); assert(strstr(entry1->name.str.val, "://") != NULL || IS_ABSOLUTE_PATH(entry2->name.str.val, entry2->name.str.len)); return entry1->name.str.len == entry2->name.str.len && memcmp(entry1->name.str.val, entry2->name.str.val, entry1->name.str.len + 1) == 0; case XC_TYPE_VAR: #ifdef IS_UNICODE if (entry1->name_type != entry2->name_type) { return 0; } if (entry1->name_type == IS_UNICODE) { return entry1->name.ustr.len == entry2->name.ustr.len && memcmp(entry1->name.ustr.val, entry2->name.ustr.val, (entry1->name.ustr.len + 1) * sizeof(entry1->name.ustr.val[0])) == 0; } #endif return entry1->name.str.len == entry2->name.str.len && memcmp(entry1->name.str.val, entry2->name.str.val, entry1->name.str.len + 1) == 0; break; default: assert(0); } return 0; } /* }}} */ static void xc_entry_add_unlocked(xc_cached_t *cached, xc_hash_value_t entryslotid, xc_entry_t *entry) /* {{{ */ { xc_entry_t **head = &(cached->entries[entryslotid]); entry->next = *head; *head = entry; cached->entries_count ++; } /* }}} */ static xc_entry_t *xc_entry_store_unlocked(xc_entry_type_t type, xc_cache_t *cache, xc_hash_value_t entryslotid, xc_entry_t *entry TSRMLS_DC) /* {{{ */ { xc_entry_t *stored_entry; entry->hits = 0; entry->ctime = XG(request_time); entry->atime = XG(request_time); stored_entry = type == XC_TYPE_PHP ? (xc_entry_t *) xc_processor_store_xc_entry_php_t(cache->shm, cache->allocator, (xc_entry_php_t *) entry TSRMLS_CC) : (xc_entry_t *) xc_processor_store_xc_entry_var_t(cache->shm, cache->allocator, (xc_entry_var_t *) entry TSRMLS_CC); if (stored_entry) { xc_entry_add_unlocked(cache->cached, entryslotid, stored_entry); ++cache->cached->updates; return stored_entry; } else { cache->cached->ooms ++; return NULL; } } /* }}} */ static xc_entry_php_t *xc_entry_php_store_unlocked(xc_cache_t *cache, xc_hash_value_t entryslotid, xc_entry_php_t *entry_php TSRMLS_DC) /* {{{ */ { return (xc_entry_php_t *) xc_entry_store_unlocked(XC_TYPE_PHP, cache, entryslotid, (xc_entry_t *) entry_php TSRMLS_CC); } /* }}} */ static xc_entry_var_t *xc_entry_var_store_unlocked(xc_cache_t *cache, xc_hash_value_t entryslotid, xc_entry_var_t *entry_var TSRMLS_DC) /* {{{ */ { return (xc_entry_var_t *) xc_entry_store_unlocked(XC_TYPE_VAR, cache, entryslotid, (xc_entry_t *) entry_var TSRMLS_CC); } /* }}} */ static void xc_entry_free_real_unlocked(xc_entry_type_t type, xc_cache_t *cache, volatile xc_entry_t *entry) /* {{{ */ { if (type == XC_TYPE_PHP) { xc_php_release_unlocked(cache, ((xc_entry_php_t *) entry)->php); } cache->allocator->vtable->free(cache->allocator, (xc_entry_t *)entry); } /* }}} */ static void xc_entry_free_unlocked(xc_entry_type_t type, xc_cache_t *cache, xc_entry_t *entry TSRMLS_DC) /* {{{ */ { cache->cached->entries_count --; if ((type == XC_TYPE_PHP ? ((xc_entry_php_t *) entry)->refcount : 0) == 0) { xc_entry_free_real_unlocked(type, cache, entry); } else { entry->next = cache->cached->deletes; cache->cached->deletes = entry; entry->dtime = XG(request_time); cache->cached->deletes_count ++; } return; } /* }}} */ static void xc_entry_remove_unlocked(xc_entry_type_t type, xc_cache_t *cache, xc_hash_value_t entryslotid, xc_entry_t *entry TSRMLS_DC) /* {{{ */ { xc_entry_t **pp = &(cache->cached->entries[entryslotid]); xc_entry_t *p; for (p = *pp; p; pp = &(p->next), p = p->next) { if (xc_entry_equal_unlocked(type, entry, p TSRMLS_CC)) { /* unlink */ *pp = p->next; xc_entry_free_unlocked(type, cache, entry TSRMLS_CC); return; } } assert(0); } /* }}} */ static xc_entry_t *xc_entry_find_unlocked(xc_entry_type_t type, xc_cache_t *cache, xc_hash_value_t entryslotid, xc_entry_t *entry TSRMLS_DC) /* {{{ */ { xc_entry_t *p; for (p = cache->cached->entries[entryslotid]; p; p = p->next) { if (xc_entry_equal_unlocked(type, entry, p TSRMLS_CC)) { zend_bool fresh; switch (type) { case XC_TYPE_PHP: { xc_entry_php_t *p_php = (xc_entry_php_t *) p; xc_entry_php_t *entry_php = (xc_entry_php_t *) entry; fresh = p_php->file_mtime == entry_php->file_mtime && p_php->file_size == entry_php->file_size; } break; case XC_TYPE_VAR: { fresh = !VAR_ENTRY_EXPIRED(p); } break; default: assert(0); } if (fresh) { p->hits ++; p->atime = XG(request_time); return p; } xc_entry_remove_unlocked(type, cache, entryslotid, p TSRMLS_CC); return NULL; } } return NULL; } /* }}} */ static void xc_entry_hold_php_unlocked(xc_cache_t *cache, xc_entry_php_t *entry TSRMLS_DC) /* {{{ */ { TRACE("hold %d:%s", entry->file_inode, entry->entry.name.str.val); #ifndef ZEND_WIN32 if (XG(holds_pid) != getpid()) { xc_holds_destroy(TSRMLS_C); xc_holds_init(TSRMLS_C); } #endif entry->refcount ++; xc_stack_push(&XG(php_holds)[cache->cacheid], (void *)entry); } /* }}} */ static inline zend_uint advance_wrapped(zend_uint val, zend_uint count) /* {{{ */ { if (val + 1 >= count) { return 0; } return val + 1; } /* }}} */ static inline void xc_counters_inc(time_t *curtime, zend_uint *curslot, time_t interval, zend_ulong *counters, zend_uint count TSRMLS_DC) /* {{{ */ { time_t n = XG(request_time) / interval; if (*curtime != n) { zend_uint target_slot = ((zend_uint) n) % count; zend_uint slot; for (slot = advance_wrapped(*curslot, count); slot != target_slot; slot = advance_wrapped(slot, count)) { counters[slot] = 0; } counters[target_slot] = 0; *curtime = n; *curslot = target_slot; } counters[*curslot] ++; } /* }}} */ static inline void xc_cached_hit_unlocked(xc_cached_t *cached TSRMLS_DC) /* {{{ */ { cached->hits ++; xc_counters_inc(&cached->hits_by_hour_cur_time , &cached->hits_by_hour_cur_slot, 60 * 60 , cached->hits_by_hour , sizeof(cached->hits_by_hour) / sizeof(cached->hits_by_hour[0]) TSRMLS_CC); xc_counters_inc(&cached->hits_by_second_cur_time , &cached->hits_by_second_cur_slot, 1 , cached->hits_by_second , sizeof(cached->hits_by_second) / sizeof(cached->hits_by_second[0]) TSRMLS_CC); } /* }}} */ /* helper function that loop through each entry */ #define XC_ENTRY_APPLY_FUNC(name) zend_bool name(xc_entry_t *entry TSRMLS_DC) typedef XC_ENTRY_APPLY_FUNC((*cache_apply_unlocked_func_t)); static void xc_entry_apply_unlocked(xc_entry_type_t type, xc_cache_t *cache, cache_apply_unlocked_func_t apply_func TSRMLS_DC) /* {{{ */ { xc_entry_t *p, **pp; size_t i, c; for (i = 0, c = cache->hentry->size; i < c; i ++) { pp = &(cache->cached->entries[i]); for (p = *pp; p; p = *pp) { if (apply_func(p TSRMLS_CC)) { /* unlink */ *pp = p->next; xc_entry_free_unlocked(type, cache, p TSRMLS_CC); } else { pp = &(p->next); } } } } /* }}} */ #define XC_CACHE_APPLY_FUNC(name) void name(xc_cache_t *cache TSRMLS_DC) /* call graph: * xc_gc_expires_php -> xc_gc_expires_one -> xc_entry_apply_unlocked -> xc_gc_expires_php_entry_unlocked * xc_gc_expires_var -> xc_gc_expires_one -> xc_entry_apply_unlocked -> xc_gc_expires_var_entry_unlocked */ static XC_ENTRY_APPLY_FUNC(xc_gc_expires_php_entry_unlocked) /* {{{ */ { TRACE("ttl %lu, %lu %lu", (zend_ulong) XG(request_time), (zend_ulong) entry->atime, xc_php_ttl); if (XG(request_time) > entry->atime + (time_t) xc_php_ttl) { return 1; } return 0; } /* }}} */ static XC_ENTRY_APPLY_FUNC(xc_gc_expires_var_entry_unlocked) /* {{{ */ { if (VAR_ENTRY_EXPIRED(entry)) { return 1; } return 0; } /* }}} */ static void xc_gc_expires_one(xc_entry_type_t type, xc_cache_t *cache, zend_ulong gc_interval, cache_apply_unlocked_func_t apply_func TSRMLS_DC) /* {{{ */ { TRACE("interval %lu, %lu %lu", (zend_ulong) XG(request_time), (zend_ulong) cache->cached->last_gc_expires, gc_interval); if (!cache->cached->disabled && XG(request_time) >= cache->cached->last_gc_expires + (time_t) gc_interval) { ENTER_LOCK(cache) { if (XG(request_time) >= cache->cached->last_gc_expires + (time_t) gc_interval) { cache->cached->last_gc_expires = XG(request_time); xc_entry_apply_unlocked(type, cache, apply_func TSRMLS_CC); } } LEAVE_LOCK(cache); } } /* }}} */ static void xc_gc_expires_php(TSRMLS_D) /* {{{ */ { size_t i, c; if (!xc_php_ttl || !xc_php_gc_interval || !xc_php_caches) { return; } for (i = 0, c = xc_php_hcache.size; i < c; i ++) { xc_gc_expires_one(XC_TYPE_PHP, &xc_php_caches[i], xc_php_gc_interval, xc_gc_expires_php_entry_unlocked TSRMLS_CC); } } /* }}} */ static void xc_gc_expires_var(TSRMLS_D) /* {{{ */ { size_t i, c; if (!xc_var_gc_interval || !xc_var_caches) { return; } for (i = 0, c = xc_var_hcache.size; i < c; i ++) { xc_gc_expires_one(XC_TYPE_VAR, &xc_var_caches[i], xc_var_gc_interval, xc_gc_expires_var_entry_unlocked TSRMLS_CC); } } /* }}} */ static XC_CACHE_APPLY_FUNC(xc_gc_delete_unlocked) /* {{{ */ { xc_entry_t *p, **pp; pp = &cache->cached->deletes; for (p = *pp; p; p = *pp) { xc_entry_php_t *entry = (xc_entry_php_t *) p; if (XG(request_time) - p->dtime > 3600) { entry->refcount = 0; /* issue warning here */ } if (entry->refcount == 0) { /* unlink */ *pp = p->next; cache->cached->deletes_count --; xc_entry_free_real_unlocked(XC_TYPE_PHP, cache, p); } else { pp = &(p->next); } } } /* }}} */ static XC_CACHE_APPLY_FUNC(xc_gc_deletes_one) /* {{{ */ { if (!cache->cached->disabled && cache->cached->deletes && XG(request_time) - cache->cached->last_gc_deletes > xc_deletes_gc_interval) { ENTER_LOCK(cache) { if (cache->cached->deletes && XG(request_time) - cache->cached->last_gc_deletes > xc_deletes_gc_interval) { cache->cached->last_gc_deletes = XG(request_time); xc_gc_delete_unlocked(cache TSRMLS_CC); } } LEAVE_LOCK(cache); } } /* }}} */ static void xc_gc_deletes(TSRMLS_D) /* {{{ */ { size_t i, c; if (xc_php_caches) { for (i = 0, c = xc_php_hcache.size; i < c; i ++) { xc_gc_deletes_one(&xc_php_caches[i] TSRMLS_CC); } } if (xc_var_caches) { for (i = 0, c = xc_var_hcache.size; i < c; i ++) { xc_gc_deletes_one(&xc_var_caches[i] TSRMLS_CC); } } } /* }}} */ /* helper functions for user functions */ static void xc_fillinfo_unlocked(int cachetype, xc_cache_t *cache, zval *return_value TSRMLS_DC) /* {{{ */ { zval *blocks, *hits; size_t i; const xc_allocator_block_t *b; #ifndef NDEBUG xc_memsize_t avail = 0; #endif const xc_allocator_t *allocator = cache->allocator; const xc_allocator_vtable_t *vtable = allocator->vtable; zend_ulong interval; const xc_cached_t *cached = cache->cached; if (cachetype == XC_TYPE_PHP) { interval = xc_php_ttl ? xc_php_gc_interval : 0; } else { interval = xc_var_gc_interval; } add_assoc_long_ex(return_value, XCACHE_STRS("slots"), cache->hentry->size); add_assoc_long_ex(return_value, XCACHE_STRS("compiling"), cached->compiling); add_assoc_long_ex(return_value, XCACHE_STRS("disabled"), cached->disabled); add_assoc_long_ex(return_value, XCACHE_STRS("updates"), cached->updates); add_assoc_long_ex(return_value, XCACHE_STRS("misses"), cached->updates); /* deprecated */ add_assoc_long_ex(return_value, XCACHE_STRS("hits"), cached->hits); add_assoc_long_ex(return_value, XCACHE_STRS("skips"), cached->skips); add_assoc_long_ex(return_value, XCACHE_STRS("clogs"), cached->skips); /* deprecated */ add_assoc_long_ex(return_value, XCACHE_STRS("ooms"), cached->ooms); add_assoc_long_ex(return_value, XCACHE_STRS("errors"), cached->errors); add_assoc_long_ex(return_value, XCACHE_STRS("cached"), cached->entries_count); add_assoc_long_ex(return_value, XCACHE_STRS("deleted"), cached->deletes_count); if (interval) { time_t gc = (cached->last_gc_expires + interval) - XG(request_time); add_assoc_long_ex(return_value, XCACHE_STRS("gc"), gc > 0 ? gc : 0); } else { add_assoc_null_ex(return_value, XCACHE_STRS("gc")); } MAKE_STD_ZVAL(hits); array_init(hits); for (i = 0; i < sizeof(cached->hits_by_hour) / sizeof(cached->hits_by_hour[0]); i ++) { add_next_index_long(hits, (long) cached->hits_by_hour[i]); } add_assoc_zval_ex(return_value, XCACHE_STRS("hits_by_hour"), hits); MAKE_STD_ZVAL(hits); array_init(hits); for (i = 0; i < sizeof(cached->hits_by_second) / sizeof(cached->hits_by_second[0]); i ++) { add_next_index_long(hits, (long) cached->hits_by_second[i]); } add_assoc_zval_ex(return_value, XCACHE_STRS("hits_by_second"), hits); MAKE_STD_ZVAL(blocks); array_init(blocks); add_assoc_long_ex(return_value, XCACHE_STRS("size"), vtable->size(allocator)); add_assoc_long_ex(return_value, XCACHE_STRS("avail"), vtable->avail(allocator)); add_assoc_bool_ex(return_value, XCACHE_STRS("can_readonly"), xc_readonly_protection); for (b = vtable->freeblock_first(allocator); b; b = vtable->freeblock_next(b)) { zval *bi; MAKE_STD_ZVAL(bi); array_init(bi); add_assoc_long_ex(bi, XCACHE_STRS("size"), vtable->block_size(b)); add_assoc_long_ex(bi, XCACHE_STRS("offset"), vtable->block_offset(allocator, b)); add_next_index_zval(blocks, bi); #ifndef NDEBUG avail += vtable->block_size(b); #endif } add_assoc_zval_ex(return_value, XCACHE_STRS("free_blocks"), blocks); #ifndef NDEBUG assert(avail == vtable->avail(allocator)); #endif } /* }}} */ static void xc_fillentry_unlocked(xc_entry_type_t type, const xc_entry_t *entry, xc_hash_value_t entryslotid, int del, zval *list TSRMLS_DC) /* {{{ */ { zval* ei; const xc_entry_data_php_t *php; ALLOC_INIT_ZVAL(ei); array_init(ei); add_assoc_long_ex(ei, XCACHE_STRS("hits"), entry->hits); add_assoc_long_ex(ei, XCACHE_STRS("ctime"), entry->ctime); add_assoc_long_ex(ei, XCACHE_STRS("atime"), entry->atime); add_assoc_long_ex(ei, XCACHE_STRS("hvalue"), entryslotid); if (del) { add_assoc_long_ex(ei, XCACHE_STRS("dtime"), entry->dtime); } #ifdef IS_UNICODE do { zval *zv; ALLOC_INIT_ZVAL(zv); switch (entry->name_type) { case IS_UNICODE: ZVAL_UNICODEL(zv, entry->name.ustr.val, entry->name.ustr.len, 1); break; case IS_STRING: ZVAL_STRINGL(zv, entry->name.str.val, entry->name.str.len, 1); break; default: assert(0); } zv->type = entry->name_type; add_assoc_zval_ex(ei, XCACHE_STRS("name"), zv); } while (0); #else add_assoc_stringl_ex(ei, XCACHE_STRS("name"), entry->name.str.val, entry->name.str.len, 1); #endif switch (type) { case XC_TYPE_PHP: { xc_entry_php_t *entry_php = (xc_entry_php_t *) entry; php = entry_php->php; add_assoc_long_ex(ei, XCACHE_STRS("size"), entry->size + php->size); add_assoc_long_ex(ei, XCACHE_STRS("refcount"), entry_php->refcount); add_assoc_long_ex(ei, XCACHE_STRS("phprefcount"), php->refcount); add_assoc_long_ex(ei, XCACHE_STRS("file_mtime"), entry_php->file_mtime); add_assoc_long_ex(ei, XCACHE_STRS("file_size"), entry_php->file_size); add_assoc_long_ex(ei, XCACHE_STRS("file_device"), entry_php->file_device); add_assoc_long_ex(ei, XCACHE_STRS("file_inode"), entry_php->file_inode); #ifdef HAVE_XCACHE_CONSTANT add_assoc_long_ex(ei, XCACHE_STRS("constinfo_cnt"), php->constinfo_cnt); #endif add_assoc_long_ex(ei, XCACHE_STRS("function_cnt"), php->funcinfo_cnt); add_assoc_long_ex(ei, XCACHE_STRS("class_cnt"), php->classinfo_cnt); #ifdef ZEND_ENGINE_2_1 add_assoc_long_ex(ei, XCACHE_STRS("autoglobal_cnt"),php->autoglobal_cnt); #endif break; } case XC_TYPE_VAR: add_assoc_long_ex(ei, XCACHE_STRS("refcount"), 0); /* for BC only */ add_assoc_long_ex(ei, XCACHE_STRS("size"), entry->size); break; default: assert(0); } add_next_index_zval(list, ei); } /* }}} */ static void xc_filllist_unlocked(xc_entry_type_t type, xc_cache_t *cache, zval *return_value TSRMLS_DC) /* {{{ */ { zval* list; size_t i, c; xc_entry_t *e; ALLOC_INIT_ZVAL(list); array_init(list); for (i = 0, c = cache->hentry->size; i < c; i ++) { for (e = cache->cached->entries[i]; e; e = e->next) { xc_fillentry_unlocked(type, e, i, 0, list TSRMLS_CC); } } add_assoc_zval(return_value, "cache_list", list); ALLOC_INIT_ZVAL(list); array_init(list); for (e = cache->cached->deletes; e; e = e->next) { xc_fillentry_unlocked(XC_TYPE_PHP, e, 0, 1, list TSRMLS_CC); } add_assoc_zval(return_value, "deleted_list", list); } /* }}} */ static zend_op_array *xc_entry_install(xc_entry_php_t *entry_php TSRMLS_DC) /* {{{ */ { zend_uint i; xc_entry_data_php_t *p = entry_php->php; zend_op_array *old_active_op_array = CG(active_op_array); #ifndef ZEND_ENGINE_2 ALLOCA_FLAG(use_heap) /* new ptr which is stored inside CG(class_table) */ xc_cest_t **new_cest_ptrs = (xc_cest_t **)xc_do_alloca(sizeof(xc_cest_t*) * p->classinfo_cnt, use_heap); #endif CG(active_op_array) = p->op_array; #ifdef HAVE_XCACHE_CONSTANT /* install constant */ for (i = 0; i < p->constinfo_cnt; i ++) { xc_constinfo_t *ci = &p->constinfos[i]; xc_install_constant(entry_php->entry.name.str.val, &ci->constant, UNISW(0, ci->type), ci->key, ci->key_size, ci->h TSRMLS_CC); } #endif /* install function */ for (i = 0; i < p->funcinfo_cnt; i ++) { xc_funcinfo_t *fi = &p->funcinfos[i]; xc_install_function(entry_php->entry.name.str.val, &fi->func, UNISW(0, fi->type), fi->key, fi->key_size, fi->h TSRMLS_CC); } /* install class */ for (i = 0; i < p->classinfo_cnt; i ++) { xc_classinfo_t *ci = &p->classinfos[i]; #ifndef ZEND_ENGINE_2 zend_class_entry *ce = CestToCePtr(ci->cest); /* fix pointer to the be which inside class_table */ if (ce->parent) { zend_uint class_idx = (/* class_num */ (int) (long) ce->parent) - 1; assert(class_idx < i); ci->cest.parent = new_cest_ptrs[class_idx]; } new_cest_ptrs[i] = #endif #ifdef ZEND_COMPILE_DELAYED_BINDING xc_install_class(entry_php->entry.name.str.val, &ci->cest, -1, UNISW(0, ci->type), ci->key, ci->key_size, ci->h TSRMLS_CC); #else xc_install_class(entry_php->entry.name.str.val, &ci->cest, ci->oplineno, UNISW(0, ci->type), ci->key, ci->key_size, ci->h TSRMLS_CC); #endif } #ifdef ZEND_ENGINE_2_1 /* trigger auto_globals jit */ for (i = 0; i < p->autoglobal_cnt; i ++) { xc_autoglobal_t *aginfo = &p->autoglobals[i]; zend_u_is_auto_global(aginfo->type, aginfo->key, aginfo->key_len TSRMLS_CC); } #endif #ifdef XCACHE_ERROR_CACHING /* restore trigger errors */ for (i = 0; i < p->compilererror_cnt; i ++) { xc_compilererror_t *error = &p->compilererrors[i]; CG(zend_lineno) = error->lineno; zend_error(error->type, "%s", error->error); } CG(zend_lineno) = 0; #endif i = 1; #ifndef ZEND_ENGINE_2_2 zend_hash_add(&EG(included_files), entry_php->entry.name.str.val, entry_php->entry.name.str.len+1, (void *)&i, sizeof(int), NULL); #endif #ifndef ZEND_ENGINE_2 xc_free_alloca(new_cest_ptrs, use_heap); #endif CG(active_op_array) = old_active_op_array; return p->op_array; } /* }}} */ static inline void xc_entry_unholds_real(xc_stack_t *holds, xc_cache_t *caches, size_t cachecount TSRMLS_DC) /* {{{ */ { size_t i; xc_stack_t *s; xc_cache_t *cache; xc_entry_php_t *entry_php; for (i = 0; i < cachecount; i ++) { s = &holds[i]; TRACE("holded %d items", xc_stack_count(s)); if (xc_stack_count(s)) { cache = &caches[i]; ENTER_LOCK(cache) { while (xc_stack_count(s)) { entry_php = (xc_entry_php_t *) xc_stack_pop(s); TRACE("unhold %d:%s", entry_php->file_inode, entry_php->entry.name.str.val); assert(entry_php->refcount > 0); --entry_php->refcount; } } LEAVE_LOCK(cache); } } } /* }}} */ static void xc_entry_unholds(TSRMLS_D) /* {{{ */ { if (xc_php_caches) { xc_entry_unholds_real(XG(php_holds), xc_php_caches, xc_php_hcache.size TSRMLS_CC); } if (xc_var_caches) { xc_entry_unholds_real(XG(var_holds), xc_var_caches, xc_var_hcache.size TSRMLS_CC); } } /* }}} */ #define HASH(i) (i) #define HASH_ZSTR_L(t, s, l) HASH(zend_u_inline_hash_func((t), (s), ((l) + 1) * sizeof(UChar))) #define HASH_STR_S(s, l) HASH(zend_inline_hash_func((char *) (s), (l))) #define HASH_STR_L(s, l) HASH_STR_S((s), (l) + 1) #define HASH_STR(s) HASH_STR_L((s), strlen((s)) + 1) #define HASH_NUM(n) HASH(n) static inline xc_hash_value_t xc_hash_fold(xc_hash_value_t hvalue, const xc_hash_t *hasher) /* {{{ fold hash bits as needed */ { xc_hash_value_t folded = 0; while (hvalue) { folded ^= (hvalue & hasher->mask); hvalue >>= hasher->bits; } return folded; } /* }}} */ static inline xc_hash_value_t xc_entry_hash_name(xc_entry_t *entry TSRMLS_DC) /* {{{ */ { return UNISW(NOTHING, UG(unicode) ? HASH_ZSTR_L(entry->name_type, entry->name.uni.val, entry->name.uni.len) :) HASH_STR_L(entry->name.str.val, entry->name.str.len); } /* }}} */ #define xc_entry_hash_var xc_entry_hash_name static void xc_entry_free_key_php(xc_entry_php_t *entry_php TSRMLS_DC) /* {{{ */ { #define X_FREE(var) do {\ if (entry_php->var) { \ efree(entry_php->var); \ } \ } while (0) X_FREE(dirpath); #ifdef IS_UNICODE X_FREE(ufilepath); X_FREE(udirpath); #endif #undef X_FREE } /* }}} */ static char *xc_expand_url(const char *filepath, char *real_path TSRMLS_DC) /* {{{ */ { if (strstr(filepath, "://") != NULL) { size_t filepath_len = strlen(filepath); size_t copy_len = filepath_len > MAXPATHLEN - 1 ? MAXPATHLEN - 1 : filepath_len; memcpy(real_path, filepath, filepath_len); real_path[copy_len] = '\0'; return real_path; } return expand_filepath(filepath, real_path TSRMLS_CC); } /* }}} */ #define XC_RESOLVE_PATH_CHECKER(name) int name(const char *filepath, size_t filepath_len, void *data TSRMLS_DC) typedef XC_RESOLVE_PATH_CHECKER((*xc_resolve_path_checker_func_t)); static int xc_resolve_path(const char *filepath, char *path_buffer, xc_resolve_path_checker_func_t checker_func, void *data TSRMLS_DC) /* {{{ */ { char *paths, *path; char *tokbuf; size_t path_buffer_len; size_t size; char tokens[] = { DEFAULT_DIR_SEPARATOR, '\0' }; int ret; ALLOCA_FLAG(use_heap) #if 0 if ((*filepath == '.' && (IS_SLASH(filepath[1]) || ((filepath[1] == '.') && IS_SLASH(filepath[2])))) || IS_ABSOLUTE_PATH(filepath, strlen(filepath)) || !path || !*path) { ret = checker_func(path_buffer, path_buffer_len, data TSRMLS_CC); goto finish; } #endif size = strlen(PG(include_path)) + 1; paths = (char *)xc_do_alloca(size, use_heap); memcpy(paths, PG(include_path), size); for (path = php_strtok_r(paths, tokens, &tokbuf); path; path = php_strtok_r(NULL, tokens, &tokbuf)) { path_buffer_len = snprintf(path_buffer, MAXPATHLEN, "%s/%s", path, filepath); if (path_buffer_len < MAXPATHLEN - 1) { ret = checker_func(path_buffer, path_buffer_len, data TSRMLS_CC); if (ret == SUCCESS) { goto finish; } } } /* fall back to current directory */ if (zend_is_executing(TSRMLS_C)) { const char *executing_filename = zend_get_executed_filename(TSRMLS_C); int dirname_len = (int) strlen(executing_filename); size_t filename_len = strlen(filepath); while ((--dirname_len >= 0) && !IS_SLASH(executing_filename[dirname_len])); if (executing_filename && dirname_len > 0 && executing_filename[0] && executing_filename[0] != '[' && dirname_len + 1 + filename_len + 1 < MAXPATHLEN) { memcpy(path_buffer, executing_filename, dirname_len + 1); memcpy(path_buffer + dirname_len + 1, filepath, filename_len + 1); path_buffer_len = dirname_len + 1 + filename_len; ret = checker_func(path_buffer, path_buffer_len, data TSRMLS_CC); if (ret == SUCCESS) { goto finish; } } } ret = FAILURE; finish: xc_free_alloca(paths, use_heap); return ret; } /* }}} */ static zend_bool xc_is_absolute(const char *filepath, size_t filepath_len) /* {{{ */ { const char *p; if (IS_ABSOLUTE_PATH(filepath, filepath_len)) { return 1; } for (p = filepath; isalnum((int)*p) || *p == '+' || *p == '-' || *p == '.'; p++); if ((*p == ':') && (p - filepath > 1) && (p[1] == '/') && (p[2] == '/')) { return 1; } return 0; } /* }}} */ static int xc_stat(const char *filepath, struct stat *statbuf TSRMLS_DC) /* {{{ */ { if (strstr(filepath, "://") != NULL) { php_stream_statbuf ssb; php_stream_wrapper *wrapper = NULL; char *path_for_open = NULL; wrapper = php_stream_locate_url_wrapper(filepath, &path_for_open, 0 TSRMLS_CC); if (wrapper && wrapper->wops->url_stat #ifdef ZEND_ENGINE_2 && wrapper->wops->url_stat(wrapper, path_for_open, PHP_STREAM_URL_STAT_QUIET, &ssb, NULL TSRMLS_CC) == SUCCESS #else && wrapper->wops->url_stat(wrapper, path_for_open, &ssb TSRMLS_CC) == SUCCESS #endif ) { *statbuf = ssb.sb; return SUCCESS; } return FAILURE; } return VCWD_STAT(filepath, statbuf); } /* }}} */ static XC_RESOLVE_PATH_CHECKER(xc_resolve_path_stat_checker) /* {{{ */ { return xc_stat(filepath, (struct stat *) data TSRMLS_CC); } /* }}} */ #ifndef ZEND_ENGINE_2_3 static int xc_resolve_path_stat(const char *filepath, char *path_buffer, struct stat *pbuf TSRMLS_DC) /* {{{ */ { return xc_resolve_path(filepath, path_buffer, xc_resolve_path_stat_checker, (void *) pbuf TSRMLS_CC); } /* }}} */ #endif typedef struct xc_compiler_t { /* {{{ */ /* XCache cached compile state */ const char *filename; size_t filename_len; const char *opened_path; char opened_path_buffer[MAXPATHLEN]; xc_entry_hash_t entry_hash; xc_entry_php_t new_entry; xc_entry_data_php_t new_php; } xc_compiler_t; /* }}} */ typedef struct xc_resolve_path_entry_checker_t { /* {{{ */ xc_compiler_t *compiler; xc_entry_php_t **stored_entry; } xc_resolve_path_entry_checker_data_t; /* }}} */ static XC_RESOLVE_PATH_CHECKER(xc_resolve_path_entry_checker) /* {{{ */ { xc_resolve_path_entry_checker_data_t *entry_checker_data = (xc_resolve_path_entry_checker_data_t *) data; xc_compiler_t *compiler = entry_checker_data->compiler; compiler->new_entry.entry.name.str.val = xc_expand_url(filepath, compiler->opened_path_buffer TSRMLS_CC); compiler->new_entry.entry.name.str.len = (int) strlen(compiler->new_entry.entry.name.str.val); *entry_checker_data->stored_entry = (xc_entry_php_t *) xc_entry_find_unlocked( XC_TYPE_PHP , &xc_php_caches[compiler->entry_hash.cacheid] , compiler->entry_hash.entryslotid , (xc_entry_t *) &compiler->new_entry TSRMLS_CC); return *entry_checker_data->stored_entry ? SUCCESS : FAILURE; } /* }}} */ static int xc_resolve_path_check_entry_unlocked(xc_compiler_t *compiler, const char *filepath, xc_entry_php_t **stored_entry TSRMLS_DC) /* {{{ */ { char path_buffer[MAXPATHLEN]; xc_resolve_path_entry_checker_data_t entry_checker_data; entry_checker_data.compiler = compiler; entry_checker_data.stored_entry = stored_entry; return xc_resolve_path(filepath, path_buffer, xc_resolve_path_entry_checker, (void *) &entry_checker_data TSRMLS_CC); } /* }}} */ static int xc_entry_php_quick_resolve_opened_path(xc_compiler_t *compiler, struct stat *statbuf TSRMLS_DC) /* {{{ */ { if (strcmp(SG(request_info).path_translated, compiler->filename) == 0) { /* sapi has already done this stat() for us */ if (statbuf) { struct stat *sapi_stat = sapi_get_stat(TSRMLS_C); if (!sapi_stat) { goto giveupsapistat; } *statbuf = *sapi_stat; } compiler->opened_path = xc_expand_url(compiler->filename, compiler->opened_path_buffer TSRMLS_CC); return SUCCESS; } giveupsapistat: /* absolute path */ if (xc_is_absolute(compiler->filename, strlen(compiler->filename))) { if (statbuf && xc_stat(compiler->filename, statbuf TSRMLS_CC) != SUCCESS) { return FAILURE; } compiler->opened_path = xc_expand_url(compiler->filename, compiler->opened_path_buffer TSRMLS_CC); return SUCCESS; } /* relative path */ if (*compiler->filename == '.' && (IS_SLASH(compiler->filename[1]) || compiler->filename[1] == '.')) { const char *ptr = compiler->filename + 1; if (*ptr == '.') { while (*(++ptr) == '.'); if (!IS_SLASH(*ptr)) { return FAILURE; } } if (statbuf && VCWD_STAT(compiler->filename, statbuf) != 0) { return FAILURE; } compiler->opened_path = xc_expand_url(compiler->filename, compiler->opened_path_buffer TSRMLS_CC); return SUCCESS; } return FAILURE; } /* }}} */ static int xc_entry_php_resolve_opened_path(xc_compiler_t *compiler, struct stat *statbuf TSRMLS_DC) /* {{{ */ { if (xc_entry_php_quick_resolve_opened_path(compiler, statbuf TSRMLS_CC) == SUCCESS) { /* opened_path resolved */ return SUCCESS; } /* fall back to real stat call */ else { #ifdef ZEND_ENGINE_2_3 char *opened_path = php_resolve_path(compiler->filename, (int) compiler->filename_len, PG(include_path) TSRMLS_CC); if (opened_path) { strcpy(compiler->opened_path_buffer, opened_path); efree(opened_path); compiler->opened_path = compiler->opened_path_buffer; if (!statbuf || xc_stat(compiler->opened_path, statbuf TSRMLS_CC) == SUCCESS) { return SUCCESS; } } #else char path_buffer[MAXPATHLEN]; if (xc_resolve_path_stat(compiler->filename, path_buffer, statbuf TSRMLS_CC) == SUCCESS) { compiler->opened_path = xc_expand_url(path_buffer, compiler->opened_path_buffer TSRMLS_CC); return SUCCESS; } #endif } return FAILURE; } /* }}} */ static int xc_entry_php_init_key(xc_compiler_t *compiler TSRMLS_DC) /* {{{ */ { if (XG(stat)) { struct stat buf; time_t delta; if (compiler->opened_path) { if (xc_stat(compiler->opened_path, &buf TSRMLS_CC) != SUCCESS) { return FAILURE; } } else { if (xc_entry_php_resolve_opened_path(compiler, &buf TSRMLS_CC) != SUCCESS) { return FAILURE; } } delta = XG(request_time) - buf.st_mtime; if (abs((int) delta) < 2 && !xc_test) { return FAILURE; } compiler->new_entry.file_mtime = buf.st_mtime; compiler->new_entry.file_size = buf.st_size; compiler->new_entry.file_device = buf.st_dev; compiler->new_entry.file_inode = buf.st_ino; } else { xc_entry_php_quick_resolve_opened_path(compiler, NULL TSRMLS_CC); compiler->new_entry.file_mtime = 0; compiler->new_entry.file_size = 0; compiler->new_entry.file_device = 0; compiler->new_entry.file_inode = 0; } { xc_hash_value_t basename_hash_value; if (xc_php_hcache.size > 1 || !compiler->new_entry.file_inode) { const char *filename_end = compiler->filename + compiler->filename_len; const char *basename_begin = filename_end - 1; /* scan till out of basename part */ while (basename_begin >= compiler->filename && !IS_SLASH(*basename_begin)) { --basename_begin; } /* get back to basename_begin */ ++basename_begin; basename_hash_value = HASH_STR_L(basename_begin, (uint) (filename_end - basename_begin)); } compiler->entry_hash.cacheid = xc_php_hcache.size > 1 ? xc_hash_fold(basename_hash_value, &xc_php_hcache) : 0; compiler->entry_hash.entryslotid = xc_hash_fold( compiler->new_entry.file_inode ? (xc_hash_value_t) HASH(compiler->new_entry.file_device + compiler->new_entry.file_inode) : basename_hash_value , &xc_php_hentry); } compiler->new_entry.filepath = NULL; compiler->new_entry.dirpath = NULL; #ifdef IS_UNICODE compiler->new_entry.ufilepath = NULL; compiler->new_entry.udirpath = NULL; #endif return SUCCESS; } /* }}} */ static inline xc_hash_value_t xc_php_hash_md5(xc_entry_data_php_t *php TSRMLS_DC) /* {{{ */ { return HASH_STR_S(php->md5.digest, sizeof(php->md5.digest)); } /* }}} */ static int xc_entry_data_php_init_md5(xc_cache_t *cache, xc_compiler_t *compiler TSRMLS_DC) /* {{{ */ { unsigned char buf[1024]; PHP_MD5_CTX context; int n; php_stream *stream; ulong old_rsid = EG(regular_list).nNextFreeElement; stream = php_stream_open_wrapper((char *) compiler->filename, "rb", USE_PATH | REPORT_ERRORS | ENFORCE_SAFE_MODE | STREAM_DISABLE_OPEN_BASEDIR, NULL); if (!stream) { return FAILURE; } PHP_MD5Init(&context); while ((n = php_stream_read(stream, (char *) buf, (int) sizeof(buf))) > 0) { PHP_MD5Update(&context, buf, n); } PHP_MD5Final((unsigned char *) compiler->new_php.md5.digest, &context); php_stream_close(stream); if (EG(regular_list).nNextFreeElement == old_rsid + 1) { EG(regular_list).nNextFreeElement = old_rsid; } if (n < 0) { return FAILURE; } compiler->new_php.hvalue = (xc_php_hash_md5(&compiler->new_php TSRMLS_CC) & cache->hphp->mask); #ifdef XCACHE_DEBUG { char md5str[33]; make_digest(md5str, (unsigned char *) compiler->new_php.md5.digest); TRACE("md5 %s", md5str); } #endif return SUCCESS; } /* }}} */ static void xc_entry_php_init(xc_entry_php_t *entry_php, const char *filepath TSRMLS_DC) /* {{{*/ { entry_php->filepath = ZEND_24((char *), NOTHING) filepath; entry_php->filepath_len = strlen(entry_php->filepath); entry_php->dirpath = estrndup(entry_php->filepath, entry_php->filepath_len); entry_php->dirpath_len = zend_dirname(entry_php->dirpath, entry_php->filepath_len); #ifdef IS_UNICODE zend_string_to_unicode(ZEND_U_CONVERTER(UG(runtime_encoding_conv)), &entry_php->ufilepath, &entry_php->ufilepath_len, entry_php->filepath, entry_php->filepath_len TSRMLS_CC); zend_string_to_unicode(ZEND_U_CONVERTER(UG(runtime_encoding_conv)), &entry_php->udirpath, &entry_php->udirpath_len, entry_php->dirpath, entry_php->dirpath_len TSRMLS_CC); #endif } /* }}} */ #ifndef ZEND_COMPILE_DELAYED_BINDING static void xc_cache_early_binding_class_cb(zend_op *opline, int oplineno, void *data TSRMLS_DC) /* {{{ */ { char *class_name; zend_uint i; int class_len; xc_cest_t cest; xc_entry_data_php_t *php = (xc_entry_data_php_t *) data; class_name = Z_OP_CONSTANT(opline->op1).value.str.val; class_len = Z_OP_CONSTANT(opline->op1).value.str.len; if (zend_hash_find(CG(class_table), class_name, class_len, (void **) &cest) == FAILURE) { assert(0); } TRACE("got ZEND_DECLARE_INHERITED_CLASS: %s", class_name + 1); /* let's see which class */ for (i = 0; i < php->classinfo_cnt; i ++) { if (memcmp(ZSTR_S(php->classinfos[i].key), class_name, class_len) == 0) { php->classinfos[i].oplineno = oplineno; php->have_early_binding = 1; break; } } if (i == php->classinfo_cnt) { assert(0); } } /* }}} */ #endif /* {{{ Constant Usage */ #ifdef ZEND_ENGINE_2_4 # define xcache_literal_is_dir 1 # define xcache_literal_is_file 2 #else # define xcache_op1_is_file 1 # define xcache_op1_is_dir 2 # define xcache_op2_is_file 4 # define xcache_op2_is_dir 8 #endif typedef struct { zend_bool filepath_used; zend_bool dirpath_used; zend_bool ufilepath_used; zend_bool udirpath_used; } xc_const_usage_t; /* }}} */ static void xc_collect_op_array_info(xc_compiler_t *compiler, xc_const_usage_t *usage, xc_op_array_info_t *op_array_info, zend_op_array *op_array TSRMLS_DC) /* {{{ */ { #ifdef ZEND_ENGINE_2_4 int literalindex; #else zend_uint oplinenum; #endif xc_vector_t details; xc_vector_init(xc_op_array_info_detail_t, &details); #define XCACHE_ANALYZE_LITERAL(type) \ if (zend_binary_strcmp(Z_STRVAL(literal->constant), Z_STRLEN(literal->constant), compiler->new_entry.type##path, compiler->new_entry.type##path_len) == 0) { \ usage->type##path_used = 1; \ literalinfo |= xcache_##literal##_is_##type; \ } #define XCACHE_U_ANALYZE_LITERAL(type) \ if (zend_u_##binary_strcmp(Z_USTRVAL(literal->constant), Z_USTRLEN(literal->constant), compiler->new_entry.u##type##path, compiler->new_entry.u##type##path_len) == 0) { \ usage->u##type##path_used = 1; \ literalinfo |= xcache_##literal##_is_##type; \ } #define XCACHE_ANALYZE_OP(type, op) \ if (zend_binary_strcmp(Z_STRVAL(Z_OP_CONSTANT(opline->op)), Z_STRLEN(Z_OP_CONSTANT(opline->op)), compiler->new_entry.type##path, compiler->new_entry.type##path_len) == 0) { \ usage->type##path_used = 1; \ oplineinfo |= xcache_##op##_is_##type; \ } #define XCACHE_U_ANALYZE_OP(type, op) \ if (zend_u_##binary_strcmp(Z_USTRVAL(Z_OP_CONSTANT(opline->op)), Z_USTRLEN(Z_OP_CONSTANT(opline->op)), compiler->new_entry.u##type##path, compiler->new_entry.u##type##path_len) == 0) { \ usage->u##type##path_used = 1; \ oplineinfo |= xcache_##op##_is_##type; \ } #ifdef ZEND_ENGINE_2_4 for (literalindex = 0; literalindex < op_array->last_literal; literalindex++) { zend_literal *literal = &op_array->literals[literalindex]; zend_uint literalinfo = 0; if (Z_TYPE(literal->constant) == IS_STRING) { XCACHE_ANALYZE_LITERAL(file) else XCACHE_ANALYZE_LITERAL(dir) } #ifdef IS_UNICODE else if (Z_TYPE(literal->constant) == IS_UNICODE) { XCACHE_U_ANALYZE_LITERAL(file) else XCACHE_U_ANALYZE_LITERAL(dir) } #endif if (literalinfo) { xc_op_array_info_detail_t detail; detail.index = literalindex; detail.info = literalinfo; xc_vector_add(xc_op_array_info_detail_t, &details, detail); } } op_array_info->literalinfo_cnt = details.cnt; op_array_info->literalinfos = xc_vector_detach(xc_op_array_info_detail_t, &details); #else /* ZEND_ENGINE_2_4 */ for (oplinenum = 0; oplinenum < op_array->last; oplinenum++) { zend_op *opline = &op_array->opcodes[oplinenum]; zend_uint oplineinfo = 0; if (Z_OP_TYPE(opline->op1) == IS_CONST) { if (Z_TYPE(Z_OP_CONSTANT(opline->op1)) == IS_STRING) { XCACHE_ANALYZE_OP(file, op1) else XCACHE_ANALYZE_OP(dir, op1) } #ifdef IS_UNICODE else if (Z_TYPE(Z_OP_CONSTANT(opline->op1)) == IS_UNICODE) { XCACHE_U_ANALYZE_OP(file, op1) else XCACHE_U_ANALYZE_OP(dir, op1) } #endif } if (Z_OP_TYPE(opline->op2) == IS_CONST) { if (Z_TYPE(Z_OP_CONSTANT(opline->op2)) == IS_STRING) { XCACHE_ANALYZE_OP(file, op2) else XCACHE_ANALYZE_OP(dir, op2) } #ifdef IS_UNICODE else if (Z_TYPE(Z_OP_CONSTANT(opline->op2)) == IS_UNICODE) { XCACHE_U_ANALYZE_OP(file, op2) else XCACHE_U_ANALYZE_OP(dir, op2) } #endif } if (oplineinfo) { xc_op_array_info_detail_t detail; detail.index = oplinenum; detail.info = oplineinfo; xc_vector_add(xc_op_array_info_detail_t, &details, detail); } } op_array_info->oplineinfo_cnt = details.cnt; op_array_info->oplineinfos = xc_vector_detach(xc_op_array_info_detail_t, &details); #endif /* ZEND_ENGINE_2_4 */ xc_vector_free(xc_op_array_info_detail_t, &details); } /* }}} */ void xc_fix_op_array_info(const xc_entry_php_t *entry_php, const xc_entry_data_php_t *php, zend_op_array *op_array, int shallow_copy, const xc_op_array_info_t *op_array_info TSRMLS_DC) /* {{{ */ { #ifdef ZEND_ENGINE_2_4 zend_uint literalinfoindex; for (literalinfoindex = 0; literalinfoindex < op_array_info->literalinfo_cnt; ++literalinfoindex) { int literalindex = op_array_info->literalinfos[literalinfoindex].index; int literalinfo = op_array_info->literalinfos[literalinfoindex].info; zend_literal *literal = &op_array->literals[literalindex]; if ((literalinfo & xcache_literal_is_file)) { if (!shallow_copy) { efree(Z_STRVAL(literal->constant)); } if (Z_TYPE(literal->constant) == IS_STRING) { assert(entry_php->filepath); ZVAL_STRINGL(&literal->constant, entry_php->filepath, entry_php->filepath_len, !shallow_copy); TRACE("restored literal constant: %s", entry_php->filepath); } #ifdef IS_UNICODE else if (Z_TYPE(literal->constant) == IS_UNICODE) { assert(entry_php->ufilepath); ZVAL_UNICODEL(&literal->constant, entry_php->ufilepath, entry_php->ufilepath_len, !shallow_copy); } #endif else { assert(0); } } else if ((literalinfo & xcache_literal_is_dir)) { if (!shallow_copy) { efree(Z_STRVAL(literal->constant)); } if (Z_TYPE(literal->constant) == IS_STRING) { assert(entry_php->dirpath); TRACE("restored literal constant: %s", entry_php->dirpath); ZVAL_STRINGL(&literal->constant, entry_php->dirpath, entry_php->dirpath_len, !shallow_copy); } #ifdef IS_UNICODE else if (Z_TYPE(literal->constant) == IS_UNICODE) { assert(!entry_php->udirpath); ZVAL_UNICODEL(&literal->constant, entry_php->udirpath, entry_php->udirpath_len, !shallow_copy); } #endif else { assert(0); } } } #else /* ZEND_ENGINE_2_4 */ zend_uint oplinenum; for (oplinenum = 0; oplinenum < op_array_info->oplineinfo_cnt; ++oplinenum) { int oplineindex = op_array_info->oplineinfos[oplinenum].index; int oplineinfo = op_array_info->oplineinfos[oplinenum].info; zend_op *opline = &op_array->opcodes[oplineindex]; if ((oplineinfo & xcache_op1_is_file)) { assert(Z_OP_TYPE(opline->op1) == IS_CONST); if (!shallow_copy) { efree(Z_STRVAL(Z_OP_CONSTANT(opline->op1))); } if (Z_TYPE(Z_OP_CONSTANT(opline->op1)) == IS_STRING) { assert(entry_php->filepath); ZVAL_STRINGL(&Z_OP_CONSTANT(opline->op1), entry_php->filepath, entry_php->filepath_len, !shallow_copy); TRACE("restored op1 constant: %s", entry_php->filepath); } #ifdef IS_UNICODE else if (Z_TYPE(Z_OP_CONSTANT(opline->op1)) == IS_UNICODE) { assert(entry_php->ufilepath); ZVAL_UNICODEL(&Z_OP_CONSTANT(opline->op1), entry_php->ufilepath, entry_php->ufilepath_len, !shallow_copy); } #endif else { assert(0); } } else if ((oplineinfo & xcache_op1_is_dir)) { assert(Z_OP_TYPE(opline->op1) == IS_CONST); if (!shallow_copy) { efree(Z_STRVAL(Z_OP_CONSTANT(opline->op1))); } if (Z_TYPE(Z_OP_CONSTANT(opline->op1)) == IS_STRING) { assert(entry_php->dirpath); TRACE("restored op1 constant: %s", entry_php->dirpath); ZVAL_STRINGL(&Z_OP_CONSTANT(opline->op1), entry_php->dirpath, entry_php->dirpath_len, !shallow_copy); } #ifdef IS_UNICODE else if (Z_TYPE(Z_OP_CONSTANT(opline->op1)) == IS_UNICODE) { assert(!entry_php->udirpath); ZVAL_UNICODEL(&Z_OP_CONSTANT(opline->op1), entry_php->udirpath, entry_php->udirpath_len, !shallow_copy); } #endif else { assert(0); } } if ((oplineinfo & xcache_op2_is_file)) { assert(Z_OP_TYPE(opline->op2) == IS_CONST); if (!shallow_copy) { efree(Z_STRVAL(Z_OP_CONSTANT(opline->op2))); } if (Z_TYPE(Z_OP_CONSTANT(opline->op2)) == IS_STRING) { assert(entry_php->filepath); TRACE("restored op2 constant: %s", entry_php->filepath); ZVAL_STRINGL(&Z_OP_CONSTANT(opline->op2), entry_php->filepath, entry_php->filepath_len, !shallow_copy); } #ifdef IS_UNICODE else if (Z_TYPE(Z_OP_CONSTANT(opline->op2)) == IS_UNICODE) { assert(entry_php->ufilepath); ZVAL_UNICODEL(&Z_OP_CONSTANT(opline->op2), entry_php->ufilepath, entry_php->ufilepath_len, !shallow_copy); } #endif else { assert(0); } } else if ((oplineinfo & xcache_op2_is_dir)) { assert(Z_OP_TYPE(opline->op2) == IS_CONST); if (!shallow_copy) { efree(Z_STRVAL(Z_OP_CONSTANT(opline->op2))); } if (Z_TYPE(Z_OP_CONSTANT(opline->op2)) == IS_STRING) { assert(entry_php->dirpath); TRACE("restored op2 constant: %s", entry_php->dirpath); ZVAL_STRINGL(&Z_OP_CONSTANT(opline->op2), entry_php->dirpath, entry_php->dirpath_len, !shallow_copy); } #ifdef IS_UNICODE else if (Z_TYPE(Z_OP_CONSTANT(opline->op2)) == IS_UNICODE) { assert(entry_php->udirpath); ZVAL_UNICODEL(&Z_OP_CONSTANT(opline->op2), entry_php->udirpath, entry_php->udirpath_len, !shallow_copy); } #endif else { assert(0); } } } #endif /* ZEND_ENGINE_2_4 */ } /* }}} */ static void xc_free_op_array_info(xc_op_array_info_t *op_array_info TSRMLS_DC) /* {{{ */ { #ifdef ZEND_ENGINE_2_4 if (op_array_info->literalinfos) { efree(op_array_info->literalinfos); } #else if (op_array_info->oplineinfos) { efree(op_array_info->oplineinfos); } #endif } /* }}} */ static void xc_free_php(xc_entry_data_php_t *php TSRMLS_DC) /* {{{ */ { zend_uint i; if (php->classinfos) { for (i = 0; i < php->classinfo_cnt; i ++) { xc_classinfo_t *classinfo = &php->classinfos[i]; zend_uint j; for (j = 0; j < classinfo->methodinfo_cnt; j ++) { xc_free_op_array_info(&classinfo->methodinfos[j] TSRMLS_CC); } if (classinfo->methodinfos) { efree(classinfo->methodinfos); } } } if (php->funcinfos) { for (i = 0; i < php->funcinfo_cnt; i ++) { xc_free_op_array_info(&php->funcinfos[i].op_array_info TSRMLS_CC); } } xc_free_op_array_info(&php->op_array_info TSRMLS_CC); #define X_FREE(var) do {\ if (php->var) { \ efree(php->var); \ } \ } while (0) #ifdef ZEND_ENGINE_2_1 X_FREE(autoglobals); #endif X_FREE(classinfos); X_FREE(funcinfos); #ifdef HAVE_XCACHE_CONSTANT X_FREE(constinfos); #endif #undef X_FREE } /* }}} */ static void xc_compile_php(xc_compiler_t *compiler, zend_file_handle *h, int type TSRMLS_DC) /* {{{ */ { zend_uint old_constinfo_cnt, old_funcinfo_cnt, old_classinfo_cnt; zend_bool catched = 0; /* {{{ compile */ TRACE("compiling %s", h->opened_path ? h->opened_path : h->filename); old_classinfo_cnt = zend_hash_num_elements(CG(class_table)); old_funcinfo_cnt = zend_hash_num_elements(CG(function_table)); old_constinfo_cnt = zend_hash_num_elements(EG(zend_constants)); zend_try { compiler->new_php.op_array = old_compile_file(h, type TSRMLS_CC); } zend_catch { catched = 1; } zend_end_try(); if (catched) { goto err_bailout; } if (compiler->new_php.op_array == NULL) { goto err_op_array; } if (!XG(initial_compile_file_called)) { TRACE("%s", "!initial_compile_file_called, give up"); return; } /* }}} */ /* {{{ prepare */ zend_restore_compiled_filename(h->opened_path ? h->opened_path : (char *) h->filename TSRMLS_CC); #ifdef HAVE_XCACHE_CONSTANT compiler->new_php.constinfo_cnt = zend_hash_num_elements(EG(zend_constants)) - old_constinfo_cnt; #endif compiler->new_php.funcinfo_cnt = zend_hash_num_elements(CG(function_table)) - old_funcinfo_cnt; compiler->new_php.classinfo_cnt = zend_hash_num_elements(CG(class_table)) - old_classinfo_cnt; #ifdef ZEND_ENGINE_2_1 /* {{{ count new_php.autoglobal_cnt */ { Bucket *b; compiler->new_php.autoglobal_cnt = 0; for (b = CG(auto_globals)->pListHead; b != NULL; b = b->pListNext) { zend_auto_global *auto_global = (zend_auto_global *) b->pData; /* check if actived */ if (auto_global->auto_global_callback && !auto_global->armed) { compiler->new_php.autoglobal_cnt ++; } } } /* }}} */ #endif #define X_ALLOC_N(var, cnt) do { \ if (compiler->new_php.cnt) { \ ECALLOC_N(compiler->new_php.var, compiler->new_php.cnt); \ if (!compiler->new_php.var) { \ goto err_alloc; \ } \ } \ else { \ compiler->new_php.var = NULL; \ } \ } while (0) #ifdef HAVE_XCACHE_CONSTANT X_ALLOC_N(constinfos, constinfo_cnt); #endif X_ALLOC_N(funcinfos, funcinfo_cnt); X_ALLOC_N(classinfos, classinfo_cnt); #ifdef ZEND_ENGINE_2_1 X_ALLOC_N(autoglobals, autoglobal_cnt); #endif #undef X_ALLOC /* }}} */ /* {{{ shallow copy, pointers only */ { Bucket *b; zend_uint i; zend_uint j; #define COPY_H(vartype, var, cnt, name, datatype) do { \ for (i = 0, j = 0; b; i ++, b = b->pListNext) { \ vartype *data = &compiler->new_php.var[j]; \ \ if (i < old_##cnt) { \ continue; \ } \ j ++; \ \ assert(i < old_##cnt + compiler->new_php.cnt); \ assert(b->pData); \ memcpy(&data->name, b->pData, sizeof(datatype)); \ UNISW(NOTHING, data->type = b->key.type;) \ if (UNISW(1, b->key.type == IS_STRING)) { \ ZSTR_S(data->key) = BUCKET_KEY_S(b); \ } \ else { \ ZSTR_U(data->key) = BUCKET_KEY_U(b); \ } \ data->key_size = b->nKeyLength; \ data->h = b->h; \ } \ } while(0) #ifdef HAVE_XCACHE_CONSTANT b = EG(zend_constants)->pListHead; COPY_H(xc_constinfo_t, constinfos, constinfo_cnt, constant, zend_constant); #endif b = CG(function_table)->pListHead; COPY_H(xc_funcinfo_t, funcinfos, funcinfo_cnt, func, zend_function); b = CG(class_table)->pListHead; COPY_H(xc_classinfo_t, classinfos, classinfo_cnt, cest, xc_cest_t); #undef COPY_H /* for ZE1, cest need to be fixed inside store */ #ifdef ZEND_ENGINE_2_1 /* scan for acatived auto globals */ i = 0; for (b = CG(auto_globals)->pListHead; b != NULL; b = b->pListNext) { zend_auto_global *auto_global = (zend_auto_global *) b->pData; /* check if actived */ if (auto_global->auto_global_callback && !auto_global->armed) { xc_autoglobal_t *data = &compiler->new_php.autoglobals[i]; assert(i < compiler->new_php.autoglobal_cnt); i ++; UNISW(NOTHING, data->type = b->key.type;) if (UNISW(1, b->key.type == IS_STRING)) { ZSTR_S(data->key) = BUCKET_KEY_S(b); } else { ZSTR_U(data->key) = BUCKET_KEY_U(b); } data->key_len = b->nKeyLength - 1; data->h = b->h; } } #endif } /* }}} */ /* {{{ collect info for file/dir path */ { Bucket *b; xc_const_usage_t const_usage; unsigned int i; xc_entry_php_init(&compiler->new_entry, zend_get_compiled_filename(TSRMLS_C) TSRMLS_CC); memset(&const_usage, 0, sizeof(const_usage)); for (i = 0; i < compiler->new_php.classinfo_cnt; i ++) { xc_classinfo_t *classinfo = &compiler->new_php.classinfos[i]; zend_class_entry *ce = CestToCePtr(classinfo->cest); classinfo->methodinfo_cnt = ce->function_table.nTableSize; if (classinfo->methodinfo_cnt) { int j; ECALLOC_N(classinfo->methodinfos, classinfo->methodinfo_cnt); if (!classinfo->methodinfos) { goto err_alloc; } for (j = 0, b = ce->function_table.pListHead; b; j ++, b = b->pListNext) { xc_collect_op_array_info(compiler, &const_usage, &classinfo->methodinfos[j], (zend_op_array *) b->pData TSRMLS_CC); } } else { classinfo->methodinfos = NULL; } } for (i = 0; i < compiler->new_php.funcinfo_cnt; i ++) { xc_collect_op_array_info(compiler, &const_usage, &compiler->new_php.funcinfos[i].op_array_info, (zend_op_array *) &compiler->new_php.funcinfos[i].func TSRMLS_CC); } xc_collect_op_array_info(compiler, &const_usage, &compiler->new_php.op_array_info, compiler->new_php.op_array TSRMLS_CC); /* file/dir path free unused */ #define X_FREE_UNUSED(var) \ if (!const_usage.var##path_used) { \ efree(compiler->new_entry.var##path); \ compiler->new_entry.var##path = NULL; \ compiler->new_entry.var##path_len = 0; \ } /* filepath is required to restore op_array->filename, so no free filepath here */ X_FREE_UNUSED(dir) #ifdef IS_UNICODE X_FREE_UNUSED(ufile) X_FREE_UNUSED(udir) #endif #undef X_FREE_UNUSED } /* }}} */ #ifdef XCACHE_ERROR_CACHING compiler->new_php.compilererrors = xc_sandbox_compilererrors(TSRMLS_C); compiler->new_php.compilererror_cnt = xc_sandbox_compilererror_cnt(TSRMLS_C); #endif #ifndef ZEND_COMPILE_DELAYED_BINDING /* {{{ find inherited classes that should be early-binding */ compiler->new_php.have_early_binding = 0; { zend_uint i; for (i = 0; i < compiler->new_php.classinfo_cnt; i ++) { compiler->new_php.classinfos[i].oplineno = -1; } } xc_undo_pass_two(compiler->new_php.op_array TSRMLS_CC); xc_foreach_early_binding_class(compiler->new_php.op_array, xc_cache_early_binding_class_cb, (void *) &compiler->new_php TSRMLS_CC); xc_redo_pass_two(compiler->new_php.op_array TSRMLS_CC); /* }}} */ #endif return; err_alloc: xc_free_php(&compiler->new_php TSRMLS_CC); err_bailout: err_op_array: if (catched) { zend_bailout(); } } /* }}} */ static zend_op_array *xc_compile_restore(xc_entry_php_t *stored_entry, xc_entry_data_php_t *stored_php TSRMLS_DC) /* {{{ */ { zend_op_array *op_array; xc_entry_php_t restored_entry; xc_entry_data_php_t restored_php; zend_bool catched; zend_uint i; /* still needed because in zend_language_scanner.l, require()/include() check file_handle.handle.stream.handle */ i = 1; zend_hash_add(&EG(included_files), stored_entry->entry.name.str.val, stored_entry->entry.name.str.len + 1, (void *)&i, sizeof(int), NULL); CG(in_compilation) = 1; CG(compiled_filename) = stored_entry->entry.name.str.val; CG(zend_lineno) = 0; TRACE("restoring %d:%s", stored_entry->file_inode, stored_entry->entry.name.str.val); xc_processor_restore_xc_entry_php_t(&restored_entry, stored_entry TSRMLS_CC); xc_processor_restore_xc_entry_data_php_t(stored_entry, &restored_php, stored_php, xc_readonly_protection TSRMLS_CC); restored_entry.php = &restored_php; #ifdef SHOW_DPRINT xc_dprint(&restored_entry, 0 TSRMLS_CC); #endif catched = 0; zend_try { op_array = xc_entry_install(&restored_entry TSRMLS_CC); } zend_catch { catched = 1; } zend_end_try(); #ifdef HAVE_XCACHE_CONSTANT if (restored_php.constinfos) { efree(restored_php.constinfos); } #endif if (restored_php.funcinfos) { efree(restored_php.funcinfos); } if (restored_php.classinfos) { efree(restored_php.classinfos); } if (catched) { zend_bailout(); } CG(in_compilation) = 0; CG(compiled_filename) = NULL; TRACE("restored %d:%s", stored_entry->file_inode, stored_entry->entry.name.str.val); return op_array; } /* }}} */ typedef struct xc_sandboxed_compiler_t { /* {{{ */ xc_compiler_t *compiler; /* input */ zend_file_handle *h; int type; /* sandbox output */ xc_entry_php_t *stored_entry; xc_entry_data_php_t *stored_php; } xc_sandboxed_compiler_t; /* }}} */ static zend_op_array *xc_compile_file_sandboxed(void *data TSRMLS_DC) /* {{{ */ { xc_sandboxed_compiler_t *sandboxed_compiler = (xc_sandboxed_compiler_t *) data; xc_compiler_t *compiler = sandboxed_compiler->compiler; zend_bool catched = 0; xc_cache_t *cache = &xc_php_caches[compiler->entry_hash.cacheid]; xc_entry_php_t *stored_entry; xc_entry_data_php_t *stored_php; /* {{{ compile */ /* make compile inside sandbox */ #ifdef HAVE_XCACHE_CONSTANT compiler->new_php.constinfos = NULL; #endif compiler->new_php.funcinfos = NULL; compiler->new_php.classinfos = NULL; #ifdef ZEND_ENGINE_2_1 compiler->new_php.autoglobals = NULL; #endif memset(&compiler->new_php.op_array_info, 0, sizeof(compiler->new_php.op_array_info)); zend_try { compiler->new_php.op_array = NULL; xc_compile_php(compiler, sandboxed_compiler->h, sandboxed_compiler->type TSRMLS_CC); } zend_catch { catched = 1; } zend_end_try(); if (catched || !compiler->new_php.op_array /* possible ? */ || !XG(initial_compile_file_called)) { goto err_aftersandbox; } /* }}} */ #ifdef SHOW_DPRINT compiler->new_entry.php = &compiler->new_php; xc_dprint(&compiler->new_entry, 0 TSRMLS_CC); #endif stored_entry = NULL; stored_php = NULL; ENTER_LOCK_EX(cache) { /* {{{ php_store/entry_store */ /* php_store */ stored_php = xc_php_store_unlocked(cache, &compiler->new_php TSRMLS_CC); if (!stored_php) { /* error */ break; } /* entry_store */ compiler->new_entry.php = stored_php; stored_entry = xc_entry_php_store_unlocked(cache, compiler->entry_hash.entryslotid, &compiler->new_entry TSRMLS_CC); if (stored_entry) { xc_php_addref_unlocked(stored_php); TRACE(" cached %d:%s, holding", compiler->new_entry.file_inode, stored_entry->entry.name.str.val); xc_entry_hold_php_unlocked(cache, stored_entry TSRMLS_CC); } } LEAVE_LOCK_EX(cache); /* }}} */ TRACE("%s", stored_entry ? "stored" : "store failed"); if (catched || !stored_php) { goto err_aftersandbox; } cache->cached->compiling = 0; xc_free_php(&compiler->new_php TSRMLS_CC); if (stored_entry) { sandboxed_compiler->stored_entry = stored_entry; sandboxed_compiler->stored_php = stored_php; /* discard newly compiled result, restore from stored one */ if (compiler->new_php.op_array) { #ifdef ZEND_ENGINE_2 destroy_op_array(compiler->new_php.op_array TSRMLS_CC); #else destroy_op_array(compiler->new_php.op_array); #endif efree(compiler->new_php.op_array); compiler->new_php.op_array = NULL; } return NULL; } else { return compiler->new_php.op_array; } err_aftersandbox: xc_free_php(&compiler->new_php TSRMLS_CC); cache->cached->compiling = 0; if (catched) { cache->cached->errors ++; zend_bailout(); } return compiler->new_php.op_array; } /* }}} */ static zend_op_array *xc_compile_file_cached(xc_compiler_t *compiler, zend_file_handle *h, int type TSRMLS_DC) /* {{{ */ { /* if (clog) { return old; } if (cached_entry = getby entry_hash) { php = cached_entry.php; php = restore(php); return php; } else { if (!(php = getby md5)) { if (clog) { return old; } inside_sandbox { php = compile; entry = create entries[entry]; } } entry.php = php; return php; } */ xc_entry_php_t *stored_entry; xc_entry_data_php_t *stored_php; zend_bool gaveup = 0; zend_bool catched = 0; zend_op_array *op_array; xc_cache_t *cache = &xc_php_caches[compiler->entry_hash.cacheid]; xc_sandboxed_compiler_t sandboxed_compiler; if (cache->cached->disabled) { return old_compile_file(h, type TSRMLS_CC); } /* stale skips precheck */ if (cache->cached->disabled || XG(request_time) - cache->cached->compiling < 30) { cache->cached->skips ++; return old_compile_file(h, type TSRMLS_CC); } /* {{{ entry_lookup/hit/md5_init/php_lookup */ stored_entry = NULL; stored_php = NULL; ENTER_LOCK_EX(cache) { if (!compiler->opened_path && xc_resolve_path_check_entry_unlocked(compiler, compiler->filename, &stored_entry TSRMLS_CC) == SUCCESS) { compiler->opened_path = compiler->new_entry.entry.name.str.val; } else { if (!compiler->opened_path && xc_entry_php_resolve_opened_path(compiler, NULL TSRMLS_CC) != SUCCESS) { gaveup = 1; break; } /* finalize name */ compiler->new_entry.entry.name.str.val = (char *) compiler->opened_path; compiler->new_entry.entry.name.str.len = strlen(compiler->new_entry.entry.name.str.val); stored_entry = (xc_entry_php_t *) xc_entry_find_unlocked(XC_TYPE_PHP, cache, compiler->entry_hash.entryslotid, (xc_entry_t *) &compiler->new_entry TSRMLS_CC); } if (stored_entry) { xc_cached_hit_unlocked(cache->cached TSRMLS_CC); TRACE(" hit %d:%s, holding", compiler->new_entry.file_inode, stored_entry->entry.name.str.val); xc_entry_hold_php_unlocked(cache, stored_entry TSRMLS_CC); stored_php = stored_entry->php; break; } TRACE("miss entry %d:%s", compiler->new_entry.file_inode, compiler->new_entry.entry.name.str.val); if (xc_entry_data_php_init_md5(cache, compiler TSRMLS_CC) != SUCCESS) { gaveup = 1; break; } stored_php = xc_php_find_unlocked(cache->cached, &compiler->new_php TSRMLS_CC); if (stored_php) { compiler->new_entry.php = stored_php; xc_entry_php_init(&compiler->new_entry, compiler->opened_path TSRMLS_CC); stored_entry = xc_entry_php_store_unlocked(cache, compiler->entry_hash.entryslotid, &compiler->new_entry TSRMLS_CC); if (stored_entry) { xc_php_addref_unlocked(stored_php); TRACE(" cached %d:%s, holding", compiler->new_entry.file_inode, stored_entry->entry.name.str.val); xc_entry_hold_php_unlocked(cache, stored_entry TSRMLS_CC); } else { gaveup = 1; } break; } if (XG(request_time) - cache->cached->compiling < 30) { TRACE("%s", "miss php, but compiling"); cache->cached->skips ++; gaveup = 1; break; } TRACE("%s", "miss php, going to compile"); cache->cached->compiling = XG(request_time); } LEAVE_LOCK_EX(cache); if (catched) { cache->cached->compiling = 0; zend_bailout(); } /* found entry */ if (stored_entry && stored_php) { zend_llist_add_element(&CG(open_files), h); return xc_compile_restore(stored_entry, stored_php TSRMLS_CC); } /* gaveup */ if (gaveup) { return old_compile_file(h, type TSRMLS_CC); } /* }}} */ sandboxed_compiler.compiler = compiler; sandboxed_compiler.h = h; sandboxed_compiler.type = type; sandboxed_compiler.stored_php = NULL; sandboxed_compiler.stored_entry = NULL; op_array = xc_sandbox(xc_compile_file_sandboxed, (void *) &sandboxed_compiler, h->opened_path ? h->opened_path : h->filename TSRMLS_CC); if (sandboxed_compiler.stored_entry) { return xc_compile_restore(sandboxed_compiler.stored_entry, sandboxed_compiler.stored_php TSRMLS_CC); } else { return op_array; } } /* }}} */ static zend_op_array *xc_compile_file(zend_file_handle *h, int type TSRMLS_DC) /* {{{ */ { xc_compiler_t compiler; zend_op_array *op_array; assert(xc_initized); TRACE("xc_compile_file: type=%d name=%s", h->type, h->filename ? h->filename : "NULL"); if (!XG(cacher) || !h->filename || !SG(request_info).path_translated ) { TRACE("%s", "cacher not enabled"); return old_compile_file(h, type TSRMLS_CC); } /* {{{ entry_init_key */ compiler.opened_path = h->opened_path; compiler.filename = compiler.opened_path ? compiler.opened_path : h->filename; compiler.filename_len = strlen(compiler.filename); if (xc_entry_php_init_key(&compiler TSRMLS_CC) != SUCCESS) { TRACE("failed to init key for %s", compiler.filename); return old_compile_file(h, type TSRMLS_CC); } /* }}} */ op_array = xc_compile_file_cached(&compiler, h, type TSRMLS_CC); xc_entry_free_key_php(&compiler.new_entry TSRMLS_CC); return op_array; } /* }}} */ /* gdb helper functions, but N/A for coredump */ zend_bool xc_is_rw(const void *p) /* {{{ */ { xc_shm_t *shm; size_t i; if (xc_php_caches) { for (i = 0; i < xc_php_hcache.size; i ++) { shm = xc_php_caches[i].shm; if (shm->handlers->is_readwrite(shm, p)) { return 1; } } } if (xc_var_caches) { for (i = 0; i < xc_var_hcache.size; i ++) { shm = xc_var_caches[i].shm; if (shm->handlers->is_readwrite(shm, p)) { return 1; } } } return 0; } /* }}} */ zend_bool xc_is_ro(const void *p) /* {{{ */ { xc_shm_t *shm; size_t i; if (xc_php_caches) { for (i = 0; i < xc_php_hcache.size; i ++) { shm = xc_php_caches[i].shm; if (shm->handlers->is_readonly(shm, p)) { return 1; } } } if (xc_var_caches) { for (i = 0; i < xc_var_hcache.size; i ++) { shm = xc_var_caches[i].shm; if (shm->handlers->is_readonly(shm, p)) { return 1; } } } return 0; } /* }}} */ zend_bool xc_is_shm(const void *p) /* {{{ */ { return xc_is_ro(p) || xc_is_rw(p); } /* }}} */ void xc_gc_add_op_array(xc_gc_op_array_t *gc_op_array TSRMLS_DC) /* {{{ */ { zend_llist_add_element(&XG(gc_op_arrays), (void *) gc_op_array); } /* }}} */ static void xc_gc_op_array(void *pDest) /* {{{ */ { xc_gc_op_array_t *op_array = (xc_gc_op_array_t *) pDest; #ifdef ZEND_ENGINE_2 if (op_array->arg_info) { zend_uint i; for (i = 0; i < op_array->num_args; i++) { efree((char *) ZSTR_V(op_array->arg_info[i].name)); if (ZSTR_V(op_array->arg_info[i].class_name)) { efree((char *) ZSTR_V(op_array->arg_info[i].class_name)); } } efree(op_array->arg_info); } #endif if (op_array->opcodes) { efree(op_array->opcodes); } #ifdef ZEND_ENGINE_2_4 if (op_array->literals) { efree(op_array->literals); } #endif } /* }}} */ /* variable namespace */ #ifdef IS_UNICODE void xc_var_namespace_init_from_unicodel(const UChar *string, int len TSRMLS_DC) /* {{{ */ { if (!len) { #ifdef IS_UNICODE ZVAL_EMPTY_UNICODE(&XG(uvar_namespace_hard)); #endif ZVAL_EMPTY_STRING(&XG(var_namespace_hard)); } else { ZVAL_UNICODE_L(&XG(uvar_namespace_hard), string, len, 1); /* TODO: copy to var */ } } /* }}} */ #endif void xc_var_namespace_init_from_stringl(const char *string, int len TSRMLS_DC) /* {{{ */ { if (!len) { #ifdef IS_UNICODE ZVAL_EMPTY_UNICODE(&XG(uvar_namespace_hard)); #endif ZVAL_EMPTY_STRING(&XG(var_namespace_hard)); } else { ZVAL_STRINGL(&XG(var_namespace_hard), string, len, 1); #ifdef IS_UNICODE /* TODO: copy to uvar */ #endif } } /* }}} */ void xc_var_namespace_init_from_long(long value TSRMLS_DC) /* {{{ */ { ZVAL_LONG(&XG(var_namespace_hard), value); #ifdef IS_UNICODE /* TODO: copy to uvar_namespace */ #endif } /* }}} */ #ifdef IS_UNICODE void xc_var_namespace_set_unicodel(const UChar *unicode, int len TSRMLS_DC) /* {{{ */ { zval_dtor(&XG(uvar_namespace_soft)); zval_dtor(&XG(var_namespace_soft)); if (len) { if (!Z_USTRLEN_P(&XG(uvar_namespace_soft))) { ZVAL_UNICODEL(&XG(uvar_namespace_soft), unicode, len, 1); } else { int buffer_len = Z_USTRLEN_P(&XG(var_namespace_hard)) + 1 + len; char *buffer = emalloc((buffer_len + 1) * sizeof(unicode[0])); char *p = buffer; memcpy(p, Z_USTRVAL_P(&XG(var_namespace_hard)), (Z_USTRLEN_P(&XG(var_namespace_hard)) + 1)); p += (Z_USTRLEN_P(&XG(var_namespace_hard)) + 1) * sizeof(unicode[0]); memcpy(p, unicode, (len + 1) * sizeof(unicode[0])); ZVAL_UNICODEL(&XG(uvar_namespace_soft), buffer, buffer_len, 0); } /* TODO: copy to var */ } else { #ifdef IS_UNICODE XG(uvar_namespace_soft) = XG(uvar_namespace_hard); zval_copy_ctor(&XG(uvar_namespace_soft)); #endif XG(var_namespace_soft) = XG(var_namespace_hard); zval_copy_ctor(&XG(var_namespace_soft)); } } /* }}} */ #endif void xc_var_namespace_set_stringl(const char *string, int len TSRMLS_DC) /* {{{ */ { #ifdef IS_UNICODE zval_dtor(&XG(uvar_namespace_soft)); #endif zval_dtor(&XG(var_namespace_soft)); if (len) { if (!Z_STRLEN_P(&XG(var_namespace_soft))) { ZVAL_STRINGL(&XG(var_namespace_soft), string, len, 1); } else { int buffer_len = Z_STRLEN_P(&XG(var_namespace_hard)) + 1 + len; char *buffer = emalloc(buffer_len + 1); char *p = buffer; memcpy(p, Z_STRVAL_P(&XG(var_namespace_hard)), Z_STRLEN_P(&XG(var_namespace_hard)) + 1); p += Z_STRLEN_P(&XG(var_namespace_hard)) + 1; memcpy(p, string, len + 1); ZVAL_STRINGL(&XG(var_namespace_soft), buffer, buffer_len, 0); } #ifdef IS_UNICODE /* TODO: copy to uvar */ #endif } else { #ifdef IS_UNICODE XG(uvar_namespace_soft) = XG(uvar_namespace_hard); zval_copy_ctor(&XG(uvar_namespace_soft)); #endif XG(var_namespace_soft) = XG(var_namespace_hard); zval_copy_ctor(&XG(var_namespace_soft)); } } /* }}} */ static void xc_var_namespace_break(TSRMLS_D) /* {{{ */ { #ifdef IS_UNICODE zval_dtor(&XG(uvar_namespace_soft)); #endif zval_dtor(&XG(var_namespace_soft)); #ifdef IS_UNICODE ZVAL_EMPTY_UNICODE(&XG(uvar_namespace_soft)); #endif ZVAL_EMPTY_STRING(&XG(var_namespace_soft)); } /* }}} */ static void xc_var_namespace_init(TSRMLS_D) /* {{{ */ { uid_t id = (uid_t) -1; switch (xc_var_namespace_mode) { case 1: { zval **server; HashTable *ht; zval **val; #ifdef ZEND_ENGINE_2_1 zend_is_auto_global("_SERVER", sizeof("_SERVER") - 1 TSRMLS_CC); #endif if (zend_hash_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER"), (void**)&server) == FAILURE || Z_TYPE_PP(server) != IS_ARRAY || !(ht = Z_ARRVAL_P(*server)) || zend_hash_find(ht, xc_var_namespace, strlen(xc_var_namespace) + 1, (void**)&val) == FAILURE) { xc_var_namespace_init_from_stringl(NULL, 0 TSRMLS_CC); } else { #ifdef IS_UNICODE if (Z_TYPE_PP(val) == IS_UNICODE) { xc_var_namespace_init_from_unicodel(Z_USTRVAL_PP(val), Z_USTRLEN_PP(val) TSRMLS_CC); } else #endif { xc_var_namespace_init_from_stringl(Z_STRVAL_PP(val), Z_STRLEN_PP(val) TSRMLS_CC); } } } break; case 2: if (strncmp(xc_var_namespace, "uid", 3) == 0) { id = getuid(); } else if (strncmp(xc_var_namespace, "gid", 3) == 0) { id = getgid(); } if (id == (uid_t) -1){ xc_var_namespace_init_from_stringl(NULL, 0 TSRMLS_CC); } else { xc_var_namespace_init_from_long((long) id TSRMLS_CC); } break; case 0: default: xc_var_namespace_init_from_stringl(xc_var_namespace, strlen(xc_var_namespace) TSRMLS_CC); break; } #ifdef IS_UNICODE INIT_ZVAL(XG(uvar_namespace_soft)); #endif INIT_ZVAL(XG(var_namespace_soft)); xc_var_namespace_set_stringl("", 0 TSRMLS_CC); } /* }}} */ static void xc_var_namespace_destroy(TSRMLS_D) /* {{{ */ { #ifdef IS_UNICODE zval_dtor(&XG(uvar_namespace_hard)); zval_dtor(&XG(uvar_namespace_soft)); #endif zval_dtor(&XG(var_namespace_hard)); zval_dtor(&XG(var_namespace_soft)); } /* }}} */ static int xc_var_buffer_prepare(zval *name TSRMLS_DC) /* {{{ prepare name, calculate buffer size */ { int namespace_len; switch (name->type) { #ifdef IS_UNICODE case IS_UNICODE: do_unicode: namespace_len = Z_USTRLEN_P(&XG(uvar_namespace_soft)); return (namespace_len ? namespace_len + 1 : 0) + Z_USTRLEN_P(name); #endif case IS_STRING: do_string: namespace_len = Z_STRLEN_P(&XG(var_namespace_soft)); return (namespace_len ? namespace_len + 1 : 0) + Z_STRLEN_P(name); default: #ifdef IS_UNICODE convert_to_unicode(name); goto do_unicode; #else convert_to_string(name); goto do_string; #endif } } /* }}} */ static int xc_var_buffer_alloca_size(zval *name TSRMLS_DC) /* {{{ prepare name, calculate buffer size */ { int namespace_len; switch (name->type) { #ifdef IS_UNICODE case IS_UNICODE: namespace_len = Z_USTRLEN_P(&XG(uvar_namespace_soft)); return !namespace_len ? 0 : (namespace_len + 1 + Z_USTRLEN_P(name) + 1) * sizeof(Z_USTRVAL_P(&XG(uvar_namespace_soft))[0]); #endif case IS_STRING: namespace_len = Z_STRLEN_P(&XG(var_namespace_soft)); return !namespace_len ? 0 : (namespace_len + 1 + Z_STRLEN_P(name) + 1); } assert(0); return 0; } /* }}} */ static void xc_var_buffer_init(char *buffer, zval *name TSRMLS_DC) /* {{{ prepare name, calculate buffer size */ { #ifdef IS_UNICODE if (Z_TYPE(name) == IS_UNICODE) { memcpy(buffer, Z_USTRVAL_P(&XG(uvar_namespace_soft)), (Z_USTRLEN_P(&XG(uvar_namespace_soft)) + 1) * sizeof(Z_USTRVAL_P(name)[0])); buffer += (Z_USTRLEN_P(&XG(uvar_namespace_soft)) + 1) * sizeof(Z_USTRVAL_P(name)[0]); memcpy(buffer, Z_USTRVAL_P(name), (Z_USTRLEN_P(name) + 1) * sizeof(Z_USTRVAL_P(name)[0])); } #endif memcpy(buffer, Z_STRVAL_P(&XG(var_namespace_soft)), (Z_STRLEN_P(&XG(var_namespace_soft)) + 1)); buffer += (Z_STRLEN_P(&XG(var_namespace_soft)) + 1); memcpy(buffer, Z_STRVAL_P(name), (Z_STRLEN_P(name) + 1)); } /* }}} */ typedef struct xc_namebuffer_t_ { /* {{{ */ ALLOCA_FLAG(useheap) void *buffer; int alloca_size; int len; } xc_namebuffer_t; /* }}} */ #define VAR_BUFFER_FLAGS(name) \ xc_namebuffer_t name##_buffer; #define VAR_BUFFER_INIT(name) \ name##_buffer.len = xc_var_buffer_prepare(name TSRMLS_CC); \ name##_buffer.alloca_size = xc_var_buffer_alloca_size(name TSRMLS_CC); \ name##_buffer.buffer = name##_buffer.alloca_size \ ? xc_do_alloca(name##_buffer.alloca_size, name##_buffer.useheap) \ : UNISW(Z_STRVAL_P(name), Z_TYPE(name) == IS_UNICODE ? Z_USTRVAL_P(name) : Z_STRVAL_P(name)); \ if (name##_buffer.alloca_size) xc_var_buffer_init(name##_buffer.buffer, name TSRMLS_CC); #define VAR_BUFFER_FREE(name) \ if (name##_buffer.alloca_size) { \ xc_free_alloca(name##_buffer.buffer, name##_buffer.useheap); \ } static inline zend_bool xc_var_has_prefix(const xc_entry_t *entry, zval *prefix, const xc_namebuffer_t *prefix_buffer TSRMLS_DC) /* {{{ */ { zend_bool result = 0; if (UNISW(IS_STRING, entry->name_type) != prefix->type) { return 0; } #ifdef IS_UNICODE if (Z_TYPE(prefix) == IS_UNICODE) { return result = entry->name.ustr.len >= prefix_buffer->len && memcmp(entry->name.ustr.val, prefix_buffer->buffer, prefix_buffer->len * sizeof(Z_USTRVAL_P(prefix)[0])) == 0; } #endif return result = entry->name.str.len >= prefix_buffer->len && memcmp(entry->name.str.val, prefix_buffer->buffer, prefix_buffer->len) == 0; } /* }}} */ /* module helper function */ static int xc_init_constant(int module_number TSRMLS_DC) /* {{{ */ { zend_register_long_constant(XCACHE_STRS("XC_TYPE_PHP"), XC_TYPE_PHP, CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC); zend_register_long_constant(XCACHE_STRS("XC_TYPE_VAR"), XC_TYPE_VAR, CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC); return SUCCESS; } /* }}} */ static xc_shm_t *xc_cache_destroy(xc_cache_t *caches, xc_hash_t *hcache) /* {{{ */ { size_t i; xc_shm_t *shm = NULL; assert(caches); for (i = 0; i < hcache->size; i ++) { xc_cache_t *cache = &caches[i]; if (cache) { /* do NOT touch cached data, do not release mutex shared inside cache */ if (cache->mutex) { xc_mutex_destroy(cache->mutex); } shm = cache->shm; if (shm) { cache->shm->handlers->memdestroy(cache->allocator); } } } free(caches); return shm; } /* }}} */ static xc_cache_t *xc_cache_init(xc_shm_t *shm, const char *allocator_name, xc_hash_t *hcache, xc_hash_t *hentry, xc_hash_t *hphp, xc_shmsize_t shmsize) /* {{{ */ { xc_cache_t *caches = NULL; xc_allocator_t *allocator; time_t now = time(NULL); size_t i; xc_memsize_t memsize; memsize = shmsize / hcache->size; /* Don't let it break out of mem after ALIGNed * This is important for * Simply loop until it fit our need */ while (ALIGN(memsize) * hcache->size > shmsize && ALIGN(memsize) != memsize) { if (memsize < ALIGN(1)) { CHECK(NULL, "cache too small"); } memsize --; } CHECK(caches = calloc(hcache->size, sizeof(xc_cache_t)), "caches OOM"); for (i = 0; i < hcache->size; i ++) { xc_cache_t *cache = &caches[i]; CHECK(allocator = shm->handlers->meminit(shm, memsize), "Failed init shm"); if (!(allocator->vtable = xc_allocator_find(allocator_name))) { zend_error(E_ERROR, "Allocator %s not found", allocator_name); goto err; } CHECK(allocator->vtable->init(shm, allocator, memsize), "Failed init allocator"); CHECK(cache->cached = allocator->vtable->calloc(allocator, 1, sizeof(xc_cached_t)), "create cache OOM"); CHECK(cache->cached->entries = allocator->vtable->calloc(allocator, hentry->size, sizeof(xc_entry_t*)), "create entries OOM"); if (hphp) { CHECK(cache->cached->phps = allocator->vtable->calloc(allocator, hphp->size, sizeof(xc_entry_data_php_t*)), "create phps OOM"); } CHECK(cache->mutex = allocator->vtable->calloc(allocator, 1, xc_mutex_size()), "create lock OOM"); CHECK(cache->mutex = xc_mutex_init(cache->mutex, NULL, 1), "can't create mutex"); cache->hcache = hcache; cache->hentry = hentry; cache->hphp = hphp; cache->shm = shm; cache->allocator = allocator; cache->cacheid = i; cache->cached->last_gc_deletes = now; cache->cached->last_gc_expires = now; } return caches; err: if (caches) { xc_cache_destroy(caches, hcache); } return NULL; } /* }}} */ static void xc_destroy() /* {{{ */ { xc_shm_t *shm = NULL; TSRMLS_FETCH(); if (old_compile_file && zend_compile_file == xc_compile_file) { zend_compile_file = old_compile_file; old_compile_file = NULL; } if (xc_php_caches) { shm = xc_cache_destroy(xc_php_caches, &xc_php_hcache); xc_php_caches = NULL; } if (xc_var_caches) { shm = xc_cache_destroy(xc_var_caches, &xc_var_hcache); xc_var_caches = NULL; } if (shm) { xc_shm_destroy(shm); } xc_holds_destroy(TSRMLS_C); xc_initized = 0; } /* }}} */ static int xc_init() /* {{{ */ { xc_shm_t *shm = NULL; xc_shmsize_t shmsize = ALIGN(xc_php_size) + ALIGN(xc_var_size); xc_php_caches = xc_var_caches = NULL; if (shmsize < (size_t) xc_php_size || shmsize < (size_t) xc_var_size) { zend_error(E_ERROR, "XCache: neither xcache.size nor xcache.var_size can be negative"); goto err; } if (xc_php_size || xc_var_size) { CHECK(shm = xc_shm_init(xc_shm_scheme, shmsize, xc_readonly_protection, xc_mmap_path, NULL), "Cannot create shm"); if (!shm->handlers->can_readonly(shm)) { xc_readonly_protection = 0; } if (xc_php_size) { CHECK(xc_php_caches = xc_cache_init(shm, xc_php_allocator, &xc_php_hcache, &xc_php_hentry, &xc_php_hentry, xc_php_size), "failed init opcode cache"); } if (xc_var_size) { CHECK(xc_var_caches = xc_cache_init(shm, xc_var_allocator, &xc_var_hcache, &xc_var_hentry, NULL, xc_var_size), "failed init variable cache"); } } return SUCCESS; err: if (xc_php_caches || xc_var_caches) { xc_destroy(); /* shm destroied in xc_destroy() */ } else if (shm) { xc_destroy(); xc_shm_destroy(shm); shm = NULL; } return FAILURE; } /* }}} */ static void xc_holds_init(TSRMLS_D) /* {{{ */ { size_t i; #ifndef ZEND_WIN32 XG(holds_pid) = getpid(); #endif if (xc_php_caches && !XG(php_holds)) { XG(php_holds_size) = xc_php_hcache.size; XG(php_holds) = calloc(XG(php_holds_size), sizeof(xc_stack_t)); for (i = 0; i < xc_php_hcache.size; i ++) { xc_stack_init(&XG(php_holds[i])); } } if (xc_var_caches && !XG(var_holds)) { XG(var_holds_size) = xc_var_hcache.size; XG(var_holds) = calloc(XG(var_holds_size), sizeof(xc_stack_t)); for (i = 0; i < xc_var_hcache.size; i ++) { xc_stack_init(&XG(var_holds[i])); } } } /* }}} */ static void xc_holds_destroy(TSRMLS_D) /* {{{ */ { size_t i; if (xc_php_caches && XG(php_holds)) { for (i = 0; i < XG(php_holds_size); i ++) { xc_stack_destroy(&XG(php_holds[i])); } free(XG(php_holds)); XG(php_holds) = NULL; XG(php_holds_size) = 0; } if (xc_var_caches && XG(var_holds)) { for (i = 0; i < XG(var_holds_size); i ++) { xc_stack_destroy(&XG(var_holds[i])); } free(XG(var_holds)); XG(var_holds) = NULL; XG(var_holds_size) = 0; } } /* }}} */ static void xc_request_init(TSRMLS_D) /* {{{ */ { if (!XG(internal_table_copied)) { zend_function tmp_func; xc_cest_t tmp_cest; #ifdef HAVE_XCACHE_CONSTANT zend_hash_destroy(&XG(internal_constant_table)); #endif zend_hash_destroy(&XG(internal_function_table)); zend_hash_destroy(&XG(internal_class_table)); #ifdef HAVE_XCACHE_CONSTANT zend_hash_init_ex(&XG(internal_constant_table), 20, NULL, (dtor_func_t) xc_zend_constant_dtor, 1, 0); #endif zend_hash_init_ex(&XG(internal_function_table), 100, NULL, NULL, 1, 0); zend_hash_init_ex(&XG(internal_class_table), 10, NULL, NULL, 1, 0); #ifdef HAVE_XCACHE_CONSTANT xc_copy_internal_zend_constants(&XG(internal_constant_table), EG(zend_constants)); #endif zend_hash_copy(&XG(internal_function_table), CG(function_table), NULL, &tmp_func, sizeof(tmp_func)); zend_hash_copy(&XG(internal_class_table), CG(class_table), NULL, &tmp_cest, sizeof(tmp_cest)); XG(internal_table_copied) = 1; } xc_holds_init(TSRMLS_C); xc_var_namespace_init(TSRMLS_C); #ifdef ZEND_ENGINE_2 zend_llist_init(&XG(gc_op_arrays), sizeof(xc_gc_op_array_t), xc_gc_op_array, 0); #endif #if PHP_API_VERSION <= 20041225 XG(request_time) = time(NULL); #else XG(request_time) = sapi_get_request_time(TSRMLS_C); #endif } /* }}} */ static void xc_request_shutdown(TSRMLS_D) /* {{{ */ { #ifndef ZEND_WIN32 if (XG(holds_pid) == getpid()) #endif { xc_entry_unholds(TSRMLS_C); } xc_gc_expires_php(TSRMLS_C); xc_gc_expires_var(TSRMLS_C); xc_gc_deletes(TSRMLS_C); xc_var_namespace_destroy(TSRMLS_C); #ifdef ZEND_ENGINE_2 zend_llist_destroy(&XG(gc_op_arrays)); #endif } /* }}} */ /* user functions */ static zend_bool xcache_admin_auth_check(TSRMLS_D) /* {{{ */ { zval **server = NULL; zval **user = NULL; zval **pass = NULL; char *admin_user = NULL; char *admin_pass = NULL; HashTable *ht; /* auth disabled, nothing to do.. */ if (!xc_admin_enable_auth) { return 1; } if (cfg_get_string("xcache.admin.user", &admin_user) == FAILURE || !admin_user[0]) { admin_user = NULL; } if (cfg_get_string("xcache.admin.pass", &admin_pass) == FAILURE || !admin_pass[0]) { admin_pass = NULL; } if (admin_user == NULL || admin_pass == NULL) { php_error_docref(XCACHE_WIKI_URL "/InstallAdministration" TSRMLS_CC, E_ERROR, "xcache.admin.user and/or xcache.admin.pass settings is not configured." " Make sure you've modified the correct php ini file for your php used in webserver."); zend_bailout(); } if (strlen(admin_pass) != 32) { php_error_docref(NULL TSRMLS_CC, E_ERROR, "xcache.admin.pass is %lu chars unexpectedly, it is supposed to be the password after md5() which should be 32 chars", (unsigned long) strlen(admin_pass)); zend_bailout(); } #ifdef ZEND_ENGINE_2_1 zend_is_auto_global("_SERVER", sizeof("_SERVER") - 1 TSRMLS_CC); #endif if (zend_hash_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER"), (void **) &server) != SUCCESS || Z_TYPE_PP(server) != IS_ARRAY) { php_error_docref(NULL TSRMLS_CC, E_ERROR, "_SERVER is corrupted"); zend_bailout(); } ht = Z_ARRVAL_P((*server)); if (zend_hash_find(ht, "PHP_AUTH_USER", sizeof("PHP_AUTH_USER"), (void **) &user) == FAILURE) { user = NULL; } else if (Z_TYPE_PP(user) != IS_STRING) { user = NULL; } if (zend_hash_find(ht, "PHP_AUTH_PW", sizeof("PHP_AUTH_PW"), (void **) &pass) == FAILURE) { pass = NULL; } else if (Z_TYPE_PP(pass) != IS_STRING) { pass = NULL; } if (user != NULL && pass != NULL && strcmp(admin_user, Z_STRVAL_PP(user)) == 0) { PHP_MD5_CTX context; char md5str[33]; unsigned char digest[16]; PHP_MD5Init(&context); PHP_MD5Update(&context, (unsigned char *) Z_STRVAL_PP(pass), Z_STRLEN_PP(pass)); PHP_MD5Final(digest, &context); md5str[0] = '\0'; make_digest(md5str, digest); if (strcmp(admin_pass, md5str) == 0) { return 1; } } #define STR "HTTP/1.0 401 Unauthorized" sapi_add_header_ex(STR, sizeof(STR) - 1, 1, 1 TSRMLS_CC); #undef STR #define STR "WWW-authenticate: Basic Realm=\"XCache Administration\"" sapi_add_header_ex(STR, sizeof(STR) - 1, 1, 1 TSRMLS_CC); #undef STR #define STR "Content-type: text/html; charset=UTF-8" sapi_add_header_ex(STR, sizeof(STR) - 1, 1, 1 TSRMLS_CC); #undef STR ZEND_PUTS("\n"); ZEND_PUTS("XCache Authentication Failed\n"); ZEND_PUTS("\n"); ZEND_PUTS("

    XCache Authentication Failed

    \n"); ZEND_PUTS("

    You're not authorized to access this page due to wrong username and/or password you typed.
    The following check points is suggested:

    \n"); ZEND_PUTS("
      \n"); ZEND_PUTS("
    • Be aware that `Username' and `Password' is case sense. Check capslock status led on your keyboard, and punch left/right Shift keys once for each
    • \n"); ZEND_PUTS("
    • Make sure the md5 password is generated correctly. You may use mkpassword.php
    • \n"); ZEND_PUTS("
    • Reload browser cache by pressing F5 and/or Ctrl+F5, or simply clear browser cache after you've updated username/password in php ini.
    • \n"); ZEND_PUTS("
    \n"); ZEND_PUTS("Check XCache wiki page for more information.\n"); ZEND_PUTS("\n"); ZEND_PUTS("\n"); zend_bailout(); return 0; } /* }}} */ static void xc_clear(long type, xc_cache_t *cache TSRMLS_DC) /* {{{ */ { xc_entry_t *e, *next; int entryslotid, c; ENTER_LOCK(cache) { for (entryslotid = 0, c = cache->hentry->size; entryslotid < c; entryslotid ++) { for (e = cache->cached->entries[entryslotid]; e; e = next) { next = e->next; xc_entry_remove_unlocked(type, cache, entryslotid, e TSRMLS_CC); } cache->cached->entries[entryslotid] = NULL; } } LEAVE_LOCK(cache); } /* }}} */ /* {{{ xcache_admin_operate */ typedef enum { XC_OP_COUNT, XC_OP_INFO, XC_OP_LIST, XC_OP_CLEAR, XC_OP_ENABLE } xcache_op_type; static void xcache_admin_operate(xcache_op_type optype, INTERNAL_FUNCTION_PARAMETERS) { long type; long size; xc_cache_t *caches, *cache; long id = 0; zend_bool enable = 1; xcache_admin_auth_check(TSRMLS_C); if (!xc_initized) { RETURN_NULL(); } switch (optype) { case XC_OP_COUNT: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &type) == FAILURE) { return; } break; case XC_OP_CLEAR: id = -1; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l", &type, &id) == FAILURE) { return; } break; case XC_OP_ENABLE: id = -1; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|lb", &type, &id, &enable) == FAILURE) { return; } break; default: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &type, &id) == FAILURE) { return; } } switch (type) { case XC_TYPE_PHP: size = xc_php_hcache.size; caches = xc_php_caches; break; case XC_TYPE_VAR: size = xc_var_hcache.size; caches = xc_var_caches; break; default: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown type %ld", type); RETURN_FALSE; } switch (optype) { case XC_OP_COUNT: RETURN_LONG(caches ? size : 0) break; case XC_OP_INFO: case XC_OP_LIST: if (!caches || id < 0 || id >= size) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cache not exists"); RETURN_FALSE; } array_init(return_value); cache = &caches[id]; ENTER_LOCK(cache) { if (optype == XC_OP_INFO) { xc_fillinfo_unlocked(type, cache, return_value TSRMLS_CC); } else { xc_filllist_unlocked(type, cache, return_value TSRMLS_CC); } } LEAVE_LOCK(cache); break; case XC_OP_CLEAR: if (!caches || id < -1 || id >= size) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cache not exists"); RETURN_FALSE; } if (id == -1) { for (id = 0; id < size; ++id) { xc_clear(type, &caches[id] TSRMLS_CC); } } else { xc_clear(type, &caches[id] TSRMLS_CC); } xc_gc_deletes(TSRMLS_C); break; case XC_OP_ENABLE: if (!caches || id < -1 || id >= size) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cache not exists"); RETURN_FALSE; } if (id == -1) { for (id = 0; id < size; ++id) { caches[id].cached->disabled = !enable ? XG(request_time) : 0; } } else { caches[id].cached->disabled = !enable ? XG(request_time) : 0; } break; default: assert(0); } } /* }}} */ /* {{{ proto int xcache_count(int type) Return count of cache on specified cache type */ PHP_FUNCTION(xcache_count) { xcache_admin_operate(XC_OP_COUNT, INTERNAL_FUNCTION_PARAM_PASSTHRU); } /* }}} */ /* {{{ proto array xcache_info(int type, int id) Get cache info by id on specified cache type */ PHP_FUNCTION(xcache_info) { xcache_admin_operate(XC_OP_INFO, INTERNAL_FUNCTION_PARAM_PASSTHRU); } /* }}} */ /* {{{ proto array xcache_list(int type, int id) Get cache entries list by id on specified cache type */ PHP_FUNCTION(xcache_list) { xcache_admin_operate(XC_OP_LIST, INTERNAL_FUNCTION_PARAM_PASSTHRU); } /* }}} */ /* {{{ proto array xcache_clear_cache(int type, [ int id = -1 ]) Clear cache by id on specified cache type */ PHP_FUNCTION(xcache_clear_cache) { xcache_admin_operate(XC_OP_CLEAR, INTERNAL_FUNCTION_PARAM_PASSTHRU); } /* }}} */ /* {{{ proto array xcache_enable_cache(int type, [ int id = -1, [ bool enable = true ] ]) Enable or disable cache by id on specified cache type */ PHP_FUNCTION(xcache_enable_cache) { xcache_admin_operate(XC_OP_ENABLE, INTERNAL_FUNCTION_PARAM_PASSTHRU); } /* }}} */ /* {{{ proto mixed xcache_admin_namespace() Break out of namespace limitation */ PHP_FUNCTION(xcache_admin_namespace) { xcache_admin_auth_check(TSRMLS_C); xc_var_namespace_break(TSRMLS_C); } /* }}} */ #define VAR_CACHE_NOT_INITIALIZED() do { \ php_error_docref(NULL TSRMLS_CC, E_WARNING, "XCache var cache was not initialized properly. Check php log for actual reason"); \ } while (0) static int xc_entry_var_init_key(xc_entry_var_t *entry_var, xc_entry_hash_t *entry_hash, xc_namebuffer_t *name_buffer TSRMLS_DC) /* {{{ */ { xc_hash_value_t hv; #ifdef IS_UNICODE entry_var->name_type = name->type; #endif entry_var->entry.name.str.val = name_buffer->buffer; entry_var->entry.name.str.len = name_buffer->len; hv = xc_entry_hash_var((xc_entry_t *) entry_var TSRMLS_CC); entry_hash->cacheid = (hv & xc_var_hcache.mask); hv >>= xc_var_hcache.bits; entry_hash->entryslotid = (hv & xc_var_hentry.mask); return SUCCESS; } /* }}} */ /* {{{ proto mixed xcache_set_namespace(string namespace) Switch to user defined namespace */ PHP_FUNCTION(xcache_set_namespace) { zval *namespace; if (!xc_var_caches) { VAR_CACHE_NOT_INITIALIZED(); RETURN_NULL(); } if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &namespace) == FAILURE) { return; } if (Z_TYPE_P(namespace) == IS_STRING) { xc_var_namespace_set_stringl(Z_STRVAL_P(namespace), Z_STRLEN_P(namespace) TSRMLS_CC); } #ifdef IS_UNICODE else if (Z_TYPE_P(namespace) == IS_UNICODE) { xc_var_namespace_set_unicodel(Z_USTRVAL_P(namespace), Z_USTRLEN_P(namespace) TSRMLS_CC); } #endif } /* }}} */ /* {{{ proto mixed xcache_get(string name) Get cached data by specified name */ PHP_FUNCTION(xcache_get) { xc_entry_hash_t entry_hash; xc_cache_t *cache; xc_entry_var_t entry_var, *stored_entry_var; zval *name; VAR_BUFFER_FLAGS(name); if (!xc_var_caches) { VAR_CACHE_NOT_INITIALIZED(); RETURN_NULL(); } if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &name) == FAILURE) { return; } VAR_BUFFER_INIT(name); xc_entry_var_init_key(&entry_var, &entry_hash, &name_buffer TSRMLS_CC); cache = &xc_var_caches[entry_hash.cacheid]; if (cache->cached->disabled) { VAR_BUFFER_FREE(name); RETURN_NULL(); } ENTER_LOCK(cache) { stored_entry_var = (xc_entry_var_t *) xc_entry_find_unlocked(XC_TYPE_VAR, cache, entry_hash.entryslotid, (xc_entry_t *) &entry_var TSRMLS_CC); if (stored_entry_var) { /* return */ xc_processor_restore_zval(return_value, stored_entry_var->value, stored_entry_var->have_references TSRMLS_CC); xc_cached_hit_unlocked(cache->cached TSRMLS_CC); } else { RETVAL_NULL(); } } LEAVE_LOCK(cache); VAR_BUFFER_FREE(name); } /* }}} */ /* {{{ proto bool xcache_set(string name, mixed value [, int ttl]) Store data to cache by specified name */ PHP_FUNCTION(xcache_set) { xc_entry_hash_t entry_hash; xc_cache_t *cache; xc_entry_var_t entry_var, *stored_entry_var; zval *name; zval *value; VAR_BUFFER_FLAGS(name); if (!xc_var_caches) { VAR_CACHE_NOT_INITIALIZED(); RETURN_NULL(); } entry_var.entry.ttl = XG(var_ttl); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz|l", &name, &value, &entry_var.entry.ttl) == FAILURE) { return; } if (Z_TYPE_P(value) == IS_OBJECT) { php_error_docref(NULL TSRMLS_CC, E_ERROR, "Objects cannot be stored in the variable cache. Use serialize before xcache_set"); RETURN_NULL(); } /* max ttl */ if (xc_var_maxttl && (!entry_var.entry.ttl || entry_var.entry.ttl > xc_var_maxttl)) { entry_var.entry.ttl = xc_var_maxttl; } VAR_BUFFER_INIT(name); xc_entry_var_init_key(&entry_var, &entry_hash, &name_buffer TSRMLS_CC); cache = &xc_var_caches[entry_hash.cacheid]; if (cache->cached->disabled) { VAR_BUFFER_FREE(name); RETURN_NULL(); } ENTER_LOCK(cache) { stored_entry_var = (xc_entry_var_t *) xc_entry_find_unlocked(XC_TYPE_VAR, cache, entry_hash.entryslotid, (xc_entry_t *) &entry_var TSRMLS_CC); if (stored_entry_var) { xc_entry_remove_unlocked(XC_TYPE_VAR, cache, entry_hash.entryslotid, (xc_entry_t *) stored_entry_var TSRMLS_CC); } entry_var.value = value; RETVAL_BOOL(xc_entry_var_store_unlocked(cache, entry_hash.entryslotid, &entry_var TSRMLS_CC) != NULL ? 1 : 0); } LEAVE_LOCK(cache); VAR_BUFFER_FREE(name); } /* }}} */ /* {{{ proto bool xcache_isset(string name) Check if an entry exists in cache by specified name */ PHP_FUNCTION(xcache_isset) { xc_entry_hash_t entry_hash; xc_cache_t *cache; xc_entry_var_t entry_var, *stored_entry_var; zval *name; VAR_BUFFER_FLAGS(name); if (!xc_var_caches) { VAR_CACHE_NOT_INITIALIZED(); RETURN_FALSE; } if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &name) == FAILURE) { return; } VAR_BUFFER_INIT(name); xc_entry_var_init_key(&entry_var, &entry_hash, &name_buffer TSRMLS_CC); cache = &xc_var_caches[entry_hash.cacheid]; if (cache->cached->disabled) { VAR_BUFFER_FREE(name); RETURN_FALSE; } ENTER_LOCK(cache) { stored_entry_var = (xc_entry_var_t *) xc_entry_find_unlocked(XC_TYPE_VAR, cache, entry_hash.entryslotid, (xc_entry_t *) &entry_var TSRMLS_CC); if (stored_entry_var) { xc_cached_hit_unlocked(cache->cached TSRMLS_CC); RETVAL_TRUE; /* return */ } else { RETVAL_FALSE; } } LEAVE_LOCK(cache); VAR_BUFFER_FREE(name); } /* }}} */ /* {{{ proto bool xcache_unset(string name) Unset existing data in cache by specified name */ PHP_FUNCTION(xcache_unset) { xc_entry_hash_t entry_hash; xc_cache_t *cache; xc_entry_var_t entry_var, *stored_entry_var; zval *name; VAR_BUFFER_FLAGS(name); if (!xc_var_caches) { VAR_CACHE_NOT_INITIALIZED(); RETURN_FALSE; } if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &name) == FAILURE) { return; } VAR_BUFFER_INIT(name); xc_entry_var_init_key(&entry_var, &entry_hash, &name_buffer TSRMLS_CC); cache = &xc_var_caches[entry_hash.cacheid]; if (cache->cached->disabled) { VAR_BUFFER_FREE(name); RETURN_FALSE; } ENTER_LOCK(cache) { stored_entry_var = (xc_entry_var_t *) xc_entry_find_unlocked(XC_TYPE_VAR, cache, entry_hash.entryslotid, (xc_entry_t *) &entry_var TSRMLS_CC); if (stored_entry_var) { xc_entry_remove_unlocked(XC_TYPE_VAR, cache, entry_hash.entryslotid, (xc_entry_t *) stored_entry_var TSRMLS_CC); RETVAL_TRUE; } else { RETVAL_FALSE; } } LEAVE_LOCK(cache); VAR_BUFFER_FREE(name); } /* }}} */ /* {{{ proto bool xcache_unset_by_prefix(string prefix) Unset existing data in cache by specified prefix */ PHP_FUNCTION(xcache_unset_by_prefix) { zval *prefix; int i, iend; VAR_BUFFER_FLAGS(prefix); if (!xc_var_caches) { VAR_CACHE_NOT_INITIALIZED(); RETURN_FALSE; } if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &prefix) == FAILURE) { return; } VAR_BUFFER_INIT(prefix); for (i = 0, iend = xc_var_hcache.size; i < iend; i ++) { xc_cache_t *cache = &xc_var_caches[i]; if (cache->cached->disabled) { continue; } ENTER_LOCK(cache) { int entryslotid, jend; for (entryslotid = 0, jend = cache->hentry->size; entryslotid < jend; entryslotid ++) { xc_entry_t *entry, *next; for (entry = cache->cached->entries[entryslotid]; entry; entry = next) { next = entry->next; if (xc_var_has_prefix(entry, prefix, &prefix_buffer TSRMLS_CC)) { xc_entry_remove_unlocked(XC_TYPE_VAR, cache, entryslotid, entry TSRMLS_CC); } } } } LEAVE_LOCK(cache); } VAR_BUFFER_FREE(prefix); } /* }}} */ static inline void xc_var_inc_dec(int inc, INTERNAL_FUNCTION_PARAMETERS) /* {{{ */ { xc_entry_hash_t entry_hash; xc_cache_t *cache; xc_entry_var_t entry_var, *stored_entry_var; zval *name; long count = 1; long value = 0; zval oldzval; VAR_BUFFER_FLAGS(name); if (!xc_var_caches) { VAR_CACHE_NOT_INITIALIZED(); RETURN_NULL(); } entry_var.entry.ttl = XG(var_ttl); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|ll", &name, &count, &entry_var.entry.ttl) == FAILURE) { return; } /* max ttl */ if (xc_var_maxttl && (!entry_var.entry.ttl || entry_var.entry.ttl > xc_var_maxttl)) { entry_var.entry.ttl = xc_var_maxttl; } VAR_BUFFER_INIT(name); xc_entry_var_init_key(&entry_var, &entry_hash, &name_buffer TSRMLS_CC); cache = &xc_var_caches[entry_hash.cacheid]; if (cache->cached->disabled) { VAR_BUFFER_FREE(name); RETURN_NULL(); } ENTER_LOCK(cache) { stored_entry_var = (xc_entry_var_t *) xc_entry_find_unlocked(XC_TYPE_VAR, cache, entry_hash.entryslotid, (xc_entry_t *) &entry_var TSRMLS_CC); if (stored_entry_var) { TRACE("incdec: got entry_var %s", entry_var.entry.name.str.val); /* do it in place */ if (Z_TYPE_P(stored_entry_var->value) == IS_LONG) { zval *zv; stored_entry_var->entry.ctime = XG(request_time); stored_entry_var->entry.ttl = entry_var.entry.ttl; TRACE("%s", "incdec: islong"); value = Z_LVAL_P(stored_entry_var->value); value += (inc == 1 ? count : - count); RETVAL_LONG(value); zv = (zval *) cache->shm->handlers->to_readwrite(cache->shm, (char *) stored_entry_var->value); Z_LVAL_P(zv) = value; ++cache->cached->updates; break; /* leave lock */ } TRACE("%s", "incdec: notlong"); xc_processor_restore_zval(&oldzval, stored_entry_var->value, stored_entry_var->have_references TSRMLS_CC); convert_to_long(&oldzval); value = Z_LVAL(oldzval); zval_dtor(&oldzval); } else { TRACE("incdec: %s not found", entry_var.entry.name.str.val); } value += (inc == 1 ? count : - count); RETVAL_LONG(value); entry_var.value = return_value; if (stored_entry_var) { entry_var.entry.atime = stored_entry_var->entry.atime; entry_var.entry.ctime = stored_entry_var->entry.ctime; entry_var.entry.hits = stored_entry_var->entry.hits; xc_entry_remove_unlocked(XC_TYPE_VAR, cache, entry_hash.entryslotid, (xc_entry_t *) stored_entry_var TSRMLS_CC); } xc_entry_var_store_unlocked(cache, entry_hash.entryslotid, &entry_var TSRMLS_CC); } LEAVE_LOCK(cache); VAR_BUFFER_FREE(name); } /* }}} */ /* {{{ proto int xcache_inc(string name [, int value [, int ttl]]) Increase an int counter in cache by specified name, create it if not exists */ PHP_FUNCTION(xcache_inc) { xc_var_inc_dec(1, INTERNAL_FUNCTION_PARAM_PASSTHRU); } /* }}} */ /* {{{ proto int xcache_dec(string name [, int value [, int ttl]]) Decrease an int counter in cache by specified name, create it if not exists */ PHP_FUNCTION(xcache_dec) { xc_var_inc_dec(-1, INTERNAL_FUNCTION_PARAM_PASSTHRU); } /* }}} */ static zend_function_entry xcache_cacher_functions[] = /* {{{ */ { PHP_FE(xcache_count, NULL) PHP_FE(xcache_info, NULL) PHP_FE(xcache_list, NULL) PHP_FE(xcache_clear_cache, NULL) PHP_FE(xcache_enable_cache, NULL) PHP_FE(xcache_admin_namespace, NULL) PHP_FE(xcache_set_namespace, NULL) PHP_FE(xcache_get, NULL) PHP_FE(xcache_set, NULL) PHP_FE(xcache_isset, NULL) PHP_FE(xcache_unset, NULL) PHP_FE(xcache_unset_by_prefix, NULL) PHP_FE(xcache_inc, NULL) PHP_FE(xcache_dec, NULL) PHP_FE_END }; /* }}} */ static int xc_cacher_zend_startup(zend_extension *extension) /* {{{ */ { if ((xc_php_size || xc_var_size) && xc_mmap_path && xc_mmap_path[0]) { if (xc_init() != SUCCESS) { zend_error(E_ERROR, "XCache: Cannot init"); return FAILURE; } xc_initized = 1; xc_init_time = time(NULL); xc_init_instance_id = getpid(); #ifdef ZTS xc_init_instance_subid = tsrm_thread_id(); #endif } if (xc_php_size) { old_compile_file = zend_compile_file; zend_compile_file = xc_compile_file; } return SUCCESS; } /* }}} */ static void xc_cacher_zend_shutdown(zend_extension *extension) /* {{{ */ { if (xc_initized) { xc_destroy(); } } /* }}} */ /* {{{ zend extension definition structure */ static zend_extension xc_cacher_zend_extension_entry = { XCACHE_NAME " Cacher", XCACHE_VERSION, XCACHE_AUTHOR, XCACHE_URL, XCACHE_COPYRIGHT, xc_cacher_zend_startup, xc_cacher_zend_shutdown, NULL, /* activate_func_t */ NULL, /* deactivate_func_t */ NULL, /* message_handler_func_t */ NULL, /* op_array_handler_func_t */ NULL, /* statement_handler_func_t */ NULL, /* fcall_begin_handler_func_t */ NULL, /* fcall_end_handler_func_t */ NULL, /* op_array_ctor_func_t */ NULL, /* op_array_dtor_func_t */ STANDARD_ZEND_EXTENSION_PROPERTIES }; /* }}} */ /* {{{ ini */ #ifdef ZEND_WIN32 # define DEFAULT_PATH "xcache" #else # define DEFAULT_PATH "/dev/zero" #endif PHP_INI_BEGIN() PHP_INI_ENTRY1 ("xcache.shm_scheme", "mmap", PHP_INI_SYSTEM, xcache_OnUpdateString, &xc_shm_scheme) PHP_INI_ENTRY1 ("xcache.mmap_path", DEFAULT_PATH, PHP_INI_SYSTEM, xcache_OnUpdateString, &xc_mmap_path) PHP_INI_ENTRY1_EX ("xcache.readonly_protection", "0", PHP_INI_SYSTEM, xcache_OnUpdateBool, &xc_readonly_protection, zend_ini_boolean_displayer_cb) /* opcode cache */ PHP_INI_ENTRY1_EX ("xcache.admin.enable_auth", "1", PHP_INI_SYSTEM, xcache_OnUpdateBool, &xc_admin_enable_auth, zend_ini_boolean_displayer_cb) PHP_INI_ENTRY1 ("xcache.size", "0", PHP_INI_SYSTEM, xcache_OnUpdateDummy, NULL) PHP_INI_ENTRY1 ("xcache.count", "1", PHP_INI_SYSTEM, xcache_OnUpdateDummy, NULL) PHP_INI_ENTRY1 ("xcache.slots", "8K", PHP_INI_SYSTEM, xcache_OnUpdateDummy, NULL) PHP_INI_ENTRY1 ("xcache.allocator", "bestfit", PHP_INI_SYSTEM, xcache_OnUpdateString, &xc_php_allocator) PHP_INI_ENTRY1 ("xcache.ttl", "0", PHP_INI_SYSTEM, xcache_OnUpdateULong, &xc_php_ttl) PHP_INI_ENTRY1 ("xcache.gc_interval", "0", PHP_INI_SYSTEM, xcache_OnUpdateULong, &xc_php_gc_interval) STD_PHP_INI_BOOLEAN("xcache.cacher", "1", PHP_INI_ALL, OnUpdateBool, cacher, zend_xcache_globals, xcache_globals) STD_PHP_INI_BOOLEAN("xcache.stat", "1", PHP_INI_ALL, OnUpdateBool, stat, zend_xcache_globals, xcache_globals) /* var cache */ PHP_INI_ENTRY1 ("xcache.var_size", "0", PHP_INI_SYSTEM, xcache_OnUpdateDummy, NULL) PHP_INI_ENTRY1 ("xcache.var_count", "1", PHP_INI_SYSTEM, xcache_OnUpdateDummy, NULL) PHP_INI_ENTRY1 ("xcache.var_slots", "8K", PHP_INI_SYSTEM, xcache_OnUpdateDummy, NULL) PHP_INI_ENTRY1 ("xcache.var_maxttl", "0", PHP_INI_SYSTEM, xcache_OnUpdateULong, &xc_var_maxttl) PHP_INI_ENTRY1 ("xcache.var_gc_interval", "120", PHP_INI_SYSTEM, xcache_OnUpdateULong, &xc_var_gc_interval) PHP_INI_ENTRY1 ("xcache.var_allocator", "bestfit", PHP_INI_SYSTEM, xcache_OnUpdateString, &xc_var_allocator) STD_PHP_INI_ENTRY ("xcache.var_ttl", "0", PHP_INI_ALL, OnUpdateLong, var_ttl, zend_xcache_globals, xcache_globals) PHP_INI_ENTRY1 ("xcache.var_namespace_mode", "0", PHP_INI_SYSTEM, xcache_OnUpdateULong, &xc_var_namespace_mode) PHP_INI_ENTRY1 ("xcache.var_namespace", "", PHP_INI_SYSTEM, xcache_OnUpdateString, &xc_var_namespace) PHP_INI_END() /* }}} */ static PHP_MINFO_FUNCTION(xcache_cacher) /* {{{ */ { char buf[100]; char *ptr; int left, len; xc_shm_scheme_t *scheme; php_info_print_table_start(); php_info_print_table_row(2, "XCache Cacher Module", "enabled"); php_info_print_table_row(2, "Readonly Protection", xc_readonly_protection ? "enabled" : "disabled"); #ifdef ZEND_ENGINE_2_1 ptr = php_format_date("Y-m-d H:i:s", sizeof("Y-m-d H:i:s") - 1, XG(request_time), 1 TSRMLS_CC); php_info_print_table_row(2, "Page Request Time", ptr); efree(ptr); ptr = php_format_date("Y-m-d H:i:s", sizeof("Y-m-d H:i:s") - 1, xc_init_time, 1 TSRMLS_CC); php_info_print_table_row(2, "Cache Init Time", ptr); efree(ptr); #else snprintf(buf, sizeof(buf), "%lu", (long unsigned) XG(request_time)); php_info_print_table_row(2, "Page Request Time", buf); snprintf(buf, sizeof(buf), "%lu", (long unsigned) xc_init_time); php_info_print_table_row(2, "Cache Init Time", buf); #endif #ifdef ZTS snprintf(buf, sizeof(buf), "%lu.%lu", xc_init_instance_id, xc_init_instance_subid); #else snprintf(buf, sizeof(buf), "%lu", xc_init_instance_id); #endif php_info_print_table_row(2, "Cache Instance Id", buf); if (xc_php_size) { ptr = _php_math_number_format(xc_php_size, 0, '.', ','); snprintf(buf, sizeof(buf), "enabled, %s bytes, %lu split(s), with %lu slots each", ptr, (unsigned long) xc_php_hcache.size, xc_php_hentry.size); php_info_print_table_row(2, "Opcode Cache", buf); efree(ptr); } else { php_info_print_table_row(2, "Opcode Cache", "disabled"); } if (xc_var_size) { ptr = _php_math_number_format(xc_var_size, 0, '.', ','); snprintf(buf, sizeof(buf), "enabled, %s bytes, %lu split(s), with %lu slots each", ptr, (unsigned long) xc_var_hcache.size, xc_var_hentry.size); php_info_print_table_row(2, "Variable Cache", buf); efree(ptr); } else { php_info_print_table_row(2, "Variable Cache", "disabled"); } left = sizeof(buf); ptr = buf; buf[0] = '\0'; for (scheme = xc_shm_scheme_first(); scheme; scheme = xc_shm_scheme_next(scheme)) { len = snprintf(ptr, left, ptr == buf ? "%s" : ", %s", xc_shm_scheme_name(scheme)); left -= len; ptr += len; } php_info_print_table_row(2, "Shared Memory Schemes", buf); php_info_print_table_end(); DISPLAY_INI_ENTRIES(); } /* }}} */ static int xc_config_hash(xc_hash_t *p, char *name, char *default_value) /* {{{ */ { size_t bits, size; char *value; if (cfg_get_string(name, &value) != SUCCESS) { value = default_value; } p->size = zend_atoi(value, strlen(value)); for (size = 1, bits = 1; size < p->size; bits ++, size <<= 1) { /* empty body */ } p->size = size; p->bits = bits; p->mask = size - 1; return SUCCESS; } /* }}} */ static int xc_config_long(zend_ulong *p, char *name, char *default_value) /* {{{ */ { char *value; if (cfg_get_string(name, &value) != SUCCESS) { value = default_value; } *p = zend_atol(value, strlen(value)); return SUCCESS; } /* }}} */ static PHP_MINIT_FUNCTION(xcache_cacher) /* {{{ */ { zend_extension *ext; zend_llist_position lpos; ext = zend_get_extension("Zend Optimizer"); if (ext) { /* zend_optimizer.optimization_level>0 is not compatible with other cacher, disabling */ ext->op_array_handler = NULL; } /* cache if there's an op_array_ctor */ for (ext = zend_llist_get_first_ex(&zend_extensions, &lpos); ext; ext = zend_llist_get_next_ex(&zend_extensions, &lpos)) { if (ext->op_array_ctor) { xc_have_op_array_ctor = 1; break; } } xc_config_long(&xc_php_size, "xcache.size", "0"); xc_config_hash(&xc_php_hcache, "xcache.count", "1"); xc_config_hash(&xc_php_hentry, "xcache.slots", "8K"); xc_config_long(&xc_var_size, "xcache.var_size", "0"); xc_config_hash(&xc_var_hcache, "xcache.var_count", "1"); xc_config_hash(&xc_var_hentry, "xcache.var_slots", "8K"); if (strcmp(sapi_module.name, "cli") == 0) { if (!xc_test) { /* disable cache for cli except for testing */ xc_php_size = 0; } } if (xc_php_size <= 0) { xc_php_size = xc_php_hcache.size = 0; } if (xc_var_size <= 0) { xc_var_size = xc_var_hcache.size = 0; } xc_init_constant(module_number TSRMLS_CC); REGISTER_INI_ENTRIES(); xc_sandbox_module_init(module_number TSRMLS_CC); return xcache_zend_extension_add(&xc_cacher_zend_extension_entry, 0); } /* }}} */ static PHP_MSHUTDOWN_FUNCTION(xcache_cacher) /* {{{ */ { xc_sandbox_module_shutdown(); xcache_zend_extension_remove(&xc_cacher_zend_extension_entry); UNREGISTER_INI_ENTRIES(); if (xc_mmap_path) { pefree(xc_mmap_path, 1); xc_mmap_path = NULL; } if (xc_shm_scheme) { pefree(xc_shm_scheme, 1); xc_shm_scheme = NULL; } if (xc_php_allocator) { pefree(xc_php_allocator, 1); xc_php_allocator = NULL; } if (xc_var_allocator) { pefree(xc_var_allocator, 1); xc_var_allocator = NULL; } if (xc_var_namespace) { pefree(xc_var_namespace, 1); xc_var_namespace = NULL; } return SUCCESS; } /* }}} */ static PHP_RINIT_FUNCTION(xcache_cacher) /* {{{ */ { xc_request_init(TSRMLS_C); return SUCCESS; } /* }}} */ /* {{{ static PHP_RSHUTDOWN_FUNCTION(xcache_cacher) */ #ifndef ZEND_ENGINE_2 static PHP_RSHUTDOWN_FUNCTION(xcache_cacher) #else static ZEND_MODULE_POST_ZEND_DEACTIVATE_D(xcache_cacher) #endif { #ifdef ZEND_ENGINE_2 TSRMLS_FETCH(); #endif xc_request_shutdown(TSRMLS_C); return SUCCESS; } /* }}} */ static zend_module_entry xcache_cacher_module_entry = { /* {{{ */ STANDARD_MODULE_HEADER, XCACHE_NAME " Cacher", xcache_cacher_functions, PHP_MINIT(xcache_cacher), PHP_MSHUTDOWN(xcache_cacher), PHP_RINIT(xcache_cacher), #ifndef ZEND_ENGINE_2 PHP_RSHUTDOWN(xcache_cacher), #else NULL, #endif PHP_MINFO(xcache_cacher), XCACHE_VERSION, #ifdef PHP_GINIT NO_MODULE_GLOBALS, #endif #ifdef ZEND_ENGINE_2 ZEND_MODULE_POST_ZEND_DEACTIVATE_N(xcache_cacher), #else NULL, NULL, #endif STANDARD_MODULE_PROPERTIES_EX }; /* }}} */ int xc_cacher_startup_module() /* {{{ */ { return zend_startup_module(&xcache_cacher_module_entry); } /* }}} */ void xc_cacher_disable() /* {{{ */ { time_t now = time(NULL); size_t i; if (xc_php_caches) { for (i = 0; i < xc_php_hcache.size; i ++) { if (xc_php_caches[i].cached) { xc_php_caches[i].cached->disabled = now; } } } if (xc_var_caches) { for (i = 0; i < xc_var_hcache.size; i ++) { if (xc_var_caches[i].cached) { xc_var_caches[i].cached->disabled = now; } } } } /* }}} */ xcache-3.1.0/mod_cacher/xc_cacher.h0000644000175000010010000000043712157744740015341 0ustar mOoNone#ifndef XC_CACHER_H_1CADCD7E46ABC70014D0766CE97B9741 #define XC_CACHER_H_1CADCD7E46ABC70014D0766CE97B9741 #if _MSC_VER > 1000 #pragma once #endif /* _MSC_VER > 1000 */ int xc_cacher_startup_module(); void xc_cacher_disable(); #endif /* XC_CACHER_H_1CADCD7E46ABC70014D0766CE97B9741 */ xcache-3.1.0/mod_coverager/0000755000175000010010000000000012206607317013766 5ustar mOoNonexcache-3.1.0/mod_coverager/xc_coverager.c0000644000175000010010000004205112206607317016603 0ustar mOoNone#if 0 #define XCACHE_DEBUG #endif #include "xc_coverager.h" #include #include "xcache.h" #include "ext/standard/flock_compat.h" #ifdef HAVE_SYS_FILE_H # include #endif #include #include #include #include "xcache/xc_extension.h" #include "xcache/xc_ini.h" #include "xcache/xc_utils.h" #include "util/xc_stack.h" #include "util/xc_trace.h" #include "xcache_globals.h" #include "ext/standard/info.h" #include "zend_compile.h" typedef HashTable *coverager_t; #define PCOV_HEADER_MAGIC 0x564f4350 static char *xc_coveragedump_dir = NULL; static zend_compile_file_t *old_compile_file = NULL; /* dumper */ static void xc_destroy_coverage(void *pDest) /* {{{ */ { coverager_t cov = *(coverager_t*) pDest; TRACE("destroy %p", cov); zend_hash_destroy(cov); efree(cov); } /* }}} */ static void xcache_mkdirs_ex(char *root, long rootlen, char *path, long pathlen TSRMLS_DC) /* {{{ */ { char *fullpath; struct stat st; ALLOCA_FLAG(use_heap) TRACE("mkdirs %s %d %s %d", root, rootlen, path, pathlen); fullpath = xc_do_alloca(rootlen + pathlen + 1, use_heap); memcpy(fullpath, root, rootlen); memcpy(fullpath + rootlen, path, pathlen); fullpath[rootlen + pathlen] = '\0'; if (stat(fullpath, &st) != 0) { char *chr; chr = strrchr(path, PHP_DIR_SEPARATOR); if (chr && chr != path) { *chr = '\0'; xcache_mkdirs_ex(root, rootlen, path, chr - path TSRMLS_CC); *chr = PHP_DIR_SEPARATOR; } TRACE("mkdir %s", fullpath); #if PHP_MAJOR_VERSION > 5 php_stream_mkdir(fullpath, 0700, REPORT_ERRORS, NULL); #else mkdir(fullpath, 0700); #endif } xc_free_alloca(fullpath, use_heap); } /* }}} */ static void xc_coverager_save_cov(char *srcfile, char *outfilename, coverager_t cov TSRMLS_DC) /* {{{ */ { long *buf = NULL, *p; long covlines, *phits; int fd = -1; size_t size; int newfile; struct stat srcstat, outstat; HashPosition pos; char *contents = NULL; long len; if (stat(srcfile, &srcstat) != 0) { return; } newfile = 0; if (stat(outfilename, &outstat) != 0) { newfile = 1; } else { if (srcstat.st_mtime > outstat.st_mtime) { newfile = 1; } } fd = open(outfilename, O_RDWR | O_CREAT, 0600); if (fd < 0) { char *chr; chr = strrchr(srcfile, PHP_DIR_SEPARATOR); if (chr) { *chr = '\0'; xcache_mkdirs_ex(xc_coveragedump_dir, strlen(xc_coveragedump_dir), srcfile, chr - srcfile TSRMLS_CC); *chr = PHP_DIR_SEPARATOR; } fd = open(outfilename, O_RDWR | O_CREAT, 0600); if (fd < 0) { goto bailout; } } if (flock(fd, LOCK_EX) != SUCCESS) { goto bailout; } if (newfile) { TRACE("%s", "new file"); } else if (outstat.st_size) { len = outstat.st_size; contents = emalloc(len); if (read(fd, (void *) contents, len) != len) { goto bailout; } TRACE("oldsize %d", (int) len); do { p = (long *) contents; len -= sizeof(long); if (len < 0) { break; } if (*p++ != PCOV_HEADER_MAGIC) { TRACE("wrong magic in file %s", outfilename); break; } p += 2; /* skip covliens */ len -= sizeof(long) * 2; if (len < 0) { break; } for (; len >= (int) sizeof(long) * 2; len -= sizeof(long) * 2, p += 2) { if (zend_hash_index_find(cov, p[0], (void**)&phits) == SUCCESS) { if (p[1] == -1) { /* OPTIMIZE: already marked */ continue; } if (*phits != -1) { p[1] += *phits; } } zend_hash_index_update(cov, p[0], &p[1], sizeof(p[1]), NULL); } } while (0); efree(contents); contents = NULL; } /* serialize */ size = (zend_hash_num_elements(cov) + 1) * sizeof(long) * 2 + sizeof(long); p = buf = emalloc(size); *p++ = PCOV_HEADER_MAGIC; p += 2; /* for covlines */ covlines = 0; zend_hash_internal_pointer_reset_ex(cov, &pos); while (zend_hash_get_current_data_ex(cov, (void**)&phits, &pos) == SUCCESS) { *p++ = pos->h; *p++ = *phits; if (*phits > 0) { covlines ++; } zend_hash_move_forward_ex(cov, &pos); } p = buf + 1; p[0] = 0; p[1] = covlines; if (ftruncate(fd, 0) != 0) { goto bailout; } lseek(fd, 0, SEEK_SET); if (write(fd, (char *) buf, size) != (ssize_t) size) { goto bailout; } bailout: if (contents) efree(contents); if (fd >= 0) close(fd); if (buf) efree(buf); } /* }}} */ static void xc_coverager_initenv(TSRMLS_D) /* {{{ */ { if (!XG(coverages)) { XG(coverages) = emalloc(sizeof(HashTable)); zend_hash_init(XG(coverages), 0, NULL, xc_destroy_coverage, 0); } } /* }}} */ static void xc_coverager_clean(TSRMLS_D) /* {{{ */ { if (XG(coverages)) { HashPosition pos; coverager_t *pcov; zend_hash_internal_pointer_reset_ex(XG(coverages), &pos); while (zend_hash_get_current_data_ex(XG(coverages), (void **) &pcov, &pos) == SUCCESS) { long *phits; coverager_t cov; HashPosition pos2; cov = *pcov; zend_hash_internal_pointer_reset_ex(cov, &pos2); while (zend_hash_get_current_data_ex(cov, (void**)&phits, &pos2) == SUCCESS) { long hits = *phits; if (hits != -1) { hits = -1; zend_hash_index_update(cov, pos2->h, &hits, sizeof(hits), NULL); } zend_hash_move_forward_ex(cov, &pos2); } zend_hash_move_forward_ex(XG(coverages), &pos); } } } /* }}} */ static void xc_coverager_cleanup(TSRMLS_D) /* {{{ */ { if (XG(coverages)) { zend_hash_destroy(XG(coverages)); efree(XG(coverages)); XG(coverages) = NULL; } } /* }}} */ static void xc_coverager_start(TSRMLS_D) /* {{{ */ { XG(coverager_started) = 1; } /* }}} */ static void xc_coverager_stop(TSRMLS_D) /* {{{ */ { XG(coverager_started) = 0; } /* }}} */ static PHP_RINIT_FUNCTION(xcache_coverager) /* {{{ */ { if (XG(coverager)) { if (XG(coverager_autostart)) { xc_coverager_start(TSRMLS_C); } #ifdef ZEND_COMPILE_EXTENDED_INFO CG(compiler_options) |= ZEND_COMPILE_EXTENDED_INFO; #else CG(extended_info) = 1; #endif } else { XG(coverager_started) = 0; } return SUCCESS; } /* }}} */ static void xc_coverager_autodump(TSRMLS_D) /* {{{ */ { coverager_t *pcov; zstr s; char *outfilename; size_t dumpdir_len, outfilelen, alloc_len = 0; uint size; HashPosition pos; if (XG(coverages) && xc_coveragedump_dir) { dumpdir_len = strlen(xc_coveragedump_dir); alloc_len = dumpdir_len + 1 + 128; outfilename = emalloc(alloc_len); strcpy(outfilename, xc_coveragedump_dir); zend_hash_internal_pointer_reset_ex(XG(coverages), &pos); while (zend_hash_get_current_data_ex(XG(coverages), (void **) &pcov, &pos) == SUCCESS) { zend_hash_get_current_key_ex(XG(coverages), &s, &size, NULL, 0, &pos); outfilelen = dumpdir_len + size + 5; if (alloc_len < outfilelen) { alloc_len = outfilelen + 128; outfilename = erealloc(outfilename, alloc_len); } strcpy(outfilename + dumpdir_len, ZSTR_S(s)); strcpy(outfilename + dumpdir_len + size - 1, ".pcov"); TRACE("outfilename %s", outfilename); xc_coverager_save_cov(ZSTR_S(s), outfilename, *pcov TSRMLS_CC); zend_hash_move_forward_ex(XG(coverages), &pos); } efree(outfilename); } } /* }}} */ static void xc_coverager_dump(zval *return_value TSRMLS_DC) /* {{{ */ { coverager_t *pcov; HashPosition pos; if (XG(coverages)) { array_init(return_value); zend_hash_internal_pointer_reset_ex(XG(coverages), &pos); while (zend_hash_get_current_data_ex(XG(coverages), (void **) &pcov, &pos) == SUCCESS) { zval *lines; long *phits; coverager_t cov; HashPosition pos2; zstr filename; uint size; cov = *pcov; zend_hash_get_current_key_ex(XG(coverages), &filename, &size, NULL, 0, &pos); MAKE_STD_ZVAL(lines); array_init(lines); zend_hash_internal_pointer_reset_ex(cov, &pos2); while (zend_hash_get_current_data_ex(cov, (void**)&phits, &pos2) == SUCCESS) { long hits = *phits; add_index_long(lines, pos2->h, hits >= 0 ? hits : 0); zend_hash_move_forward_ex(cov, &pos2); } add_assoc_zval_ex(return_value, ZSTR_S(filename), (uint) strlen(ZSTR_S(filename)) + 1, lines); zend_hash_move_forward_ex(XG(coverages), &pos); } } else { RETVAL_NULL(); } } /* }}} */ static PHP_RSHUTDOWN_FUNCTION(xcache_coverager) /* {{{ */ { if (XG(coverager)) { xc_coverager_autodump(TSRMLS_C); xc_coverager_cleanup(TSRMLS_C); } return SUCCESS; } /* }}} */ /* helper func to store hits into coverages */ static coverager_t xc_coverager_get(const char *filename TSRMLS_DC) /* {{{ */ { uint len = (uint) strlen(filename) + 1; coverager_t cov, *pcov; if (zend_u_hash_find(XG(coverages), IS_STRING, filename, len, (void **) &pcov) == SUCCESS) { TRACE("got coverage %s %p", filename, *pcov); return *pcov; } else { cov = emalloc(sizeof(HashTable)); zend_hash_init(cov, 0, NULL, NULL, 0); zend_u_hash_add(XG(coverages), IS_STRING, filename, len, (void **) &cov, sizeof(cov), NULL); TRACE("new coverage %s %p", filename, cov); return cov; } } /* }}} */ static void xc_coverager_add_hits(HashTable *cov, long line, long hits TSRMLS_DC) /* {{{ */ { long *poldhits; if (line == 0) { return; } if (zend_hash_index_find(cov, line, (void**)&poldhits) == SUCCESS) { if (hits == -1) { /* OPTIMIZE: -1 == init-ing, but it's already initized */ return; } if (*poldhits != -1) { hits += *poldhits; } } zend_hash_index_update(cov, line, &hits, sizeof(hits), NULL); } /* }}} */ static int xc_coverager_get_op_array_size_no_tail(zend_op_array *op_array) /* {{{ */ { zend_uint last = op_array->last; do { next_op: if (last == 0) { break; } switch (op_array->opcodes[last - 1].opcode) { #ifdef ZEND_HANDLE_EXCEPTION case ZEND_HANDLE_EXCEPTION: #endif case ZEND_RETURN: case ZEND_EXT_STMT: --last; goto next_op; } } while (0); return last; } /* }}} */ /* prefill */ static int xc_coverager_init_op_array(zend_op_array *op_array TSRMLS_DC) /* {{{ */ { zend_uint size; coverager_t cov; zend_uint i; if (op_array->type != ZEND_USER_FUNCTION) { return 0; } size = xc_coverager_get_op_array_size_no_tail(op_array); cov = xc_coverager_get(op_array->filename TSRMLS_CC); for (i = 0; i < size; i ++) { switch (op_array->opcodes[i].opcode) { case ZEND_EXT_STMT: #if 0 case ZEND_EXT_FCALL_BEGIN: case ZEND_EXT_FCALL_END: #endif xc_coverager_add_hits(cov, op_array->opcodes[i].lineno, -1 TSRMLS_CC); break; } } return 0; } /* }}} */ static void xc_coverager_init_compile_result(zend_op_array *op_array TSRMLS_DC) /* {{{ */ { xc_compile_result_t cr; xc_compile_result_init_cur(&cr, op_array TSRMLS_CC); xc_apply_op_array(&cr, (apply_func_t) xc_coverager_init_op_array TSRMLS_CC); xc_compile_result_free(&cr); } /* }}} */ static zend_op_array *xc_compile_file_for_coverage(zend_file_handle *h, int type TSRMLS_DC) /* {{{ */ { zend_op_array *op_array; op_array = old_compile_file(h, type TSRMLS_CC); if (op_array) { if (XG(coverager)) { xc_coverager_initenv(TSRMLS_C); xc_coverager_init_compile_result(op_array TSRMLS_CC); } } return op_array; } /* }}} */ /* hits */ static void xc_coverager_handle_ext_stmt(zend_op_array *op_array, zend_uchar op) /* {{{ */ { TSRMLS_FETCH(); if (XG(coverages) && XG(coverager_started)) { int size = xc_coverager_get_op_array_size_no_tail(op_array); int oplineno = (int) ((*EG(opline_ptr)) - op_array->opcodes); if (oplineno < size) { xc_coverager_add_hits(xc_coverager_get(op_array->filename TSRMLS_CC), (*EG(opline_ptr))->lineno, 1 TSRMLS_CC); } } } /* }}} */ /* user api */ /* {{{ proto array xcache_coverager_decode(string data) * decode specified data which is saved by auto dumper to array */ PHP_FUNCTION(xcache_coverager_decode) { char *str; int len; long *p; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &len) == FAILURE) { return; } array_init(return_value); p = (long*) str; len -= (int) sizeof(long); if (len < 0) { return; } if (*p++ != PCOV_HEADER_MAGIC) { TRACE("%s", "wrong magic in xcache_coverager_decode"); return; } for (; len >= (int) sizeof(long) * 2; len -= (int) sizeof(long) * 2, p += 2) { add_index_long(return_value, p[0], p[1] < 0 ? 0 : p[1]); } } /* }}} */ /* {{{ proto void xcache_coverager_start([bool clean = true]) * starts coverager data collecting */ PHP_FUNCTION(xcache_coverager_start) { zend_bool clean = 1; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &clean) == FAILURE) { return; } if (clean) { xc_coverager_clean(TSRMLS_C); } if (XG(coverager)) { xc_coverager_start(TSRMLS_C); } else { php_error(E_WARNING, "You can only start coverager after you set 'xcache.coverager' to 'On' in ini"); } } /* }}} */ /* {{{ proto void xcache_coverager_stop([bool clean = false]) * stop coverager data collecting */ PHP_FUNCTION(xcache_coverager_stop) { zend_bool clean = 0; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &clean) == FAILURE) { return; } xc_coverager_stop(TSRMLS_C); if (clean) { xc_coverager_clean(TSRMLS_C); } } /* }}} */ /* {{{ proto array xcache_coverager_get([bool clean = false]) * get coverager data collected */ PHP_FUNCTION(xcache_coverager_get) { zend_bool clean = 0; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &clean) == FAILURE) { return; } xc_coverager_dump(return_value TSRMLS_CC); if (clean) { xc_coverager_clean(TSRMLS_C); } } /* }}} */ static zend_function_entry xcache_coverager_functions[] = /* {{{ */ { PHP_FE(xcache_coverager_decode, NULL) PHP_FE(xcache_coverager_start, NULL) PHP_FE(xcache_coverager_stop, NULL) PHP_FE(xcache_coverager_get, NULL) PHP_FE_END }; /* }}} */ static int xc_coverager_zend_startup(zend_extension *extension) /* {{{ */ { old_compile_file = zend_compile_file; zend_compile_file = xc_compile_file_for_coverage; return SUCCESS; } /* }}} */ static void xc_coverager_zend_shutdown(zend_extension *extension) /* {{{ */ { /* empty */ } /* }}} */ static void xc_statement_handler(zend_op_array *op_array) /* {{{ */ { xc_coverager_handle_ext_stmt(op_array, ZEND_EXT_STMT); } /* }}} */ static void xc_fcall_begin_handler(zend_op_array *op_array) /* {{{ */ { #if 0 xc_coverager_handle_ext_stmt(op_array, ZEND_EXT_FCALL_BEGIN); #endif } /* }}} */ static void xc_fcall_end_handler(zend_op_array *op_array) /* {{{ */ { #if 0 xc_coverager_handle_ext_stmt(op_array, ZEND_EXT_FCALL_END); #endif } /* }}} */ /* {{{ zend extension definition structure */ static zend_extension xc_coverager_zend_extension_entry = { XCACHE_NAME " Coverager", XCACHE_VERSION, XCACHE_AUTHOR, XCACHE_URL, XCACHE_COPYRIGHT, xc_coverager_zend_startup, xc_coverager_zend_shutdown, NULL, /* activate_func_t */ NULL, /* deactivate_func_t */ NULL, /* message_handler_func_t */ NULL, /* statement_handler_func_t */ xc_statement_handler, xc_fcall_begin_handler, xc_fcall_end_handler, NULL, /* op_array_ctor_func_t */ NULL, /* op_array_dtor_func_t */ STANDARD_ZEND_EXTENSION_PROPERTIES }; /* }}} */ /* {{{ PHP_INI */ PHP_INI_BEGIN() STD_PHP_INI_BOOLEAN("xcache.coverager", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateBool, coverager, zend_xcache_globals, xcache_globals) STD_PHP_INI_BOOLEAN("xcache.coverager_autostart", "1", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateBool, coverager_autostart, zend_xcache_globals, xcache_globals) PHP_INI_ENTRY1 ("xcache.coveragedump_directory", "", PHP_INI_SYSTEM, xcache_OnUpdateDummy, NULL) PHP_INI_END() /* }}} */ static PHP_MINFO_FUNCTION(xcache_coverager) /* {{{ */ { char *covdumpdir; php_info_print_table_start(); php_info_print_table_row(2, "XCache Coverager Module", "enabled"); if (cfg_get_string("xcache.coveragedump_directory", &covdumpdir) != SUCCESS || !covdumpdir[0]) { covdumpdir = NULL; } php_info_print_table_row(2, "Coverage Started", XG(coverager_started) && covdumpdir ? "On" : "Off"); php_info_print_table_end(); DISPLAY_INI_ENTRIES(); } /* }}} */ static PHP_MINIT_FUNCTION(xcache_coverager) /* {{{ */ { REGISTER_INI_ENTRIES(); if (cfg_get_string("xcache.coveragedump_directory", &xc_coveragedump_dir) == SUCCESS && xc_coveragedump_dir) { size_t len; xc_coveragedump_dir = pestrdup(xc_coveragedump_dir, 1); len = strlen(xc_coveragedump_dir); if (len) { if (xc_coveragedump_dir[len - 1] == '/') { xc_coveragedump_dir[len - 1] = '\0'; } } if (!strlen(xc_coveragedump_dir)) { pefree(xc_coveragedump_dir, 1); xc_coveragedump_dir = NULL; } } return xcache_zend_extension_add(&xc_coverager_zend_extension_entry, 0); } /* }}} */ static PHP_MSHUTDOWN_FUNCTION(xcache_coverager) /* {{{ */ { if (old_compile_file && zend_compile_file == xc_compile_file_for_coverage) { zend_compile_file = old_compile_file; old_compile_file = NULL; } if (xc_coveragedump_dir) { pefree(xc_coveragedump_dir, 1); xc_coveragedump_dir = NULL; } UNREGISTER_INI_ENTRIES(); return xcache_zend_extension_remove(&xc_coverager_zend_extension_entry); } /* }}} */ static zend_module_entry xcache_coverager_module_entry = { /* {{{ */ STANDARD_MODULE_HEADER, XCACHE_NAME " Coverager", xcache_coverager_functions, PHP_MINIT(xcache_coverager), PHP_MSHUTDOWN(xcache_coverager), PHP_RINIT(xcache_coverager), PHP_RSHUTDOWN(xcache_coverager), PHP_MINFO(xcache_coverager), XCACHE_VERSION, #ifdef PHP_GINIT NO_MODULE_GLOBALS, #endif #ifdef ZEND_ENGINE_2 NULL, #else NULL, NULL, #endif STANDARD_MODULE_PROPERTIES_EX }; /* }}} */ int xc_coverager_startup_module() /* {{{ */ { return zend_startup_module(&xcache_coverager_module_entry); } /* }}} */ xcache-3.1.0/mod_coverager/xc_coverager.h0000644000175000010010000000044312157744740016616 0ustar mOoNone#ifndef XC_COVERAGER_H_D5BB29AAB992B932E91C70A8C2F5D2B1 #define XC_COVERAGER_H_D5BB29AAB992B932E91C70A8C2F5D2B1 #if _MSC_VER > 1000 #pragma once #endif /* _MSC_VER > 1000 */ #include "php.h" int xc_coverager_startup_module(); #endif /* XC_COVERAGER_H_D5BB29AAB992B932E91C70A8C2F5D2B1 */ xcache-3.1.0/mod_decoder/0000755000175000010010000000000012157744740013425 5ustar mOoNonexcache-3.1.0/mod_decoder/xc_decoder.c0000644000175000010010000000003012157744740015661 0ustar mOoNonestatic void dummy() { } xcache-3.1.0/mod_disassembler/0000755000175000010010000000000012220455231014456 5ustar mOoNonexcache-3.1.0/mod_disassembler/sample.cpp.php0000644000175000010010000002420012220455231017227 0ustar mOoNone= 500 # define PublicMethod public #else # define ClassName classname # define PublicMethod # define abstract # define innerIf_ innerif_ # define emptySwitch emptyswitch # define defaultSwitch defaultswitch #endif #if PHP_VERSION >= 520 #else # define __callStatic __callstatic # define __toString __tostring #endif #if PHP_VERSION >= 530 namespace ns; #endif abstract class ClassName { #if PHP_VERSION >= 500 const CONST_VALUE = 'A constant value'; /** doc */ static public $static = array( 0 => array('array'), 1 => 'str', CONST_VALUE => CONST_VALUE ); static public $static_const1 = CONST_VALUE; static public $static_const2 = self::CONST_VALUE; static public $static_const3 = ClassName::CONST_VALUE; static public $static_const4 = array(CONST_VALUE => 'test'); static public $static_const5 = array(self::CONST_VALUE => 'test'); static public $static_const6 = array(ClassName::CONST_VALUE => 'test'); static public $static_const7 = array('test' => CONST_VALUE); static public $static_const8 = array('test' => self::CONST_VALUE); static public $static_const9 = array('test' => ClassName::CONST_VALUE); static public $static_const10 = array(CONST_VALUE => CONST_VALUE); static public $static_const11 = array(self::CONST_VALUE => self::CONST_VALUE); static public $static_const12 = array(ClassName::CONST_VALUE => ClassName::CONST_VALUE); /** doc */ static public $public_static = array(2, 'str'); /** doc */ static private $private_static = array(2, 'str'); static private $private_static2 = array(self::CONST_VALUE => self::CONST_VALUE); /** doc */ static protected $protected_static = array(2, 'str'); static protected $protected_static2 = array(self::CONST_VALUE => self::CONST_VALUE); /** doc */ public $property = array( array('array'), 'str' ); /** doc */ public $public_property = array(2, 'str'); /** doc */ private $private_property = array(2, 'str'); /** doc */ protected $protected_property = array(2, 'str'); #else var $property = array( array('array'), 'str' ); #endif #if PHP_VERSION >= 500 /** doc */ #endif PublicMethod function __construct($a, $b) { static $array = array( 0 => array('array'), 1 => 'str', CONST_VALUE => CONST_VALUE ); static $a = 1; static $str = 'string'; echo CONST_VALUE; #if PHP_VERSION >= 500 echo ClassName::CONST_VALUE; empty(ClassName::$classProp); isset(ClassName::$classProp); unset(ClassName::$classProp); ClassName::$classProp = 1; echo ClassName::$classProp; #endif empty($obj->objProp); isset($obj->objProp); #if PHP_VERSION >= 500 unset($obj->objProp); #endif $obj->objProp = 1; echo $obj->objProp; empty($this->thisProp); isset($this->thisProp); #if PHP_VERSION >= 500 unset($this->thisProp); #endif $this->thisProp = 1; echo $this->thisProp; #if PHP_VERSION >= 500 unset($array['index']->valueProp); #endif unset($obj->array['index']); unset($this->array['index']); empty($_GET['get']); isset($_GET['get']); unset($_GET['get']); $_GET['get'] = 1; echo $_GET['get']; isset($GLOBALS['global']); empty($GLOBALS['global']); unset($GLOBALS['global']); $GLOBALS['global'] = 1; echo $GLOBALS['global']; empty($array['index']); isset($array['index']); unset($array['index']); $array['index'] = 1; echo $array['index']; empty($array['index']->indexProp); isset($array['index']->indexProp); #if PHP_VERSION >= 500 unset($array['index']->indexProp); #endif $array['index']->indexProp = 1; echo $array['index']->indexProp; empty($GLOBALS['var']->indexProp); isset($GLOBALS['var']->indexProp); #if PHP_VERSION >= 500 unset($GLOBALS['var']->indexProp); #endif $GLOBALS['var']->indexProp = 1; echo $GLOBALS['var']->indexProp; ClassName::__construct(); ClassName::$func(); echo __CLASS__; echo __METHOD__; echo __FUNCTION__; $this->methodCall(); #if PHP_VERSION >= 500 throw new Exception(); new Exception(); #endif } #if PHP_VERSION >= 500 /** doc */ abstract public function abastractMethod(); #endif #if PHP_VERSION >= 500 /** doc */ #endif PublicMethod function method($a = NULL, $b = NULL) { } #if PHP_VERSION >= 500 /** doc */ protected function protectedMethod(ClassName $a, $b = array( array('array') )) { $runtimeArray = array('1'); $runtimeArray2 = array( '1', array() ); $runtimeArray3 = array( 'a' => '1', 2 => array() ); return 'protected'; } /** doc */ private function privateMethod(ClassName $a, $b = NULL) { return 'private'; } #endif } #if PHP_VERSION >= 500 interface IInterface { public function nothing(); } #endif function f1($f) { echo __FUNCTION__; echo $f; #if PHP_VERSION >= 550 foreach ($a as $b) { yield $b; } yield f1($b); #endif } #if PHP_VERSION >= 500 final class Child extends ClassName implements IInterface { public function __construct() { parent::__construct(); } public function __destruct() { parent::__destruct(); functionCall(); } static public function __callStatic($name, $args) { parent::__callStatic($name, $args); } public function __toString() { parent::__toString(); } public function __set($name, $value) { } public function __get($name) { } public function __isset($name) { } public function __unset($name) { } public function __sleep() { } public function __wakeup() { } public function __clone() { return array(); } } #endif if ($late) { class LateBindingClass { PublicMethod function __construct() { } } function lateBindingFunction($arg) { echo 'lateFunction'; return new lateBindingFunction(); } } echo "\r\n"; echo "\r"; echo "\n"; echo str_replace(array('a' => 'a', 'b' => 'c'), 'b'); $object = new ClassName(); $object = new $className(); #if PHP_VERSION >= 500 $result = $object instanceof ClassName; $cloned = clone $object; #endif $a = 1; $a = $b + $c; $a = $b + 1; $a = 1 + $b; $a = $b - $c; $a = $b * $c; $a = $b / $c; $a = $b % $c; $a = $b . $c; $a = $b = $c; $a = $b & $c; $a = $b | $c; $a = $b ^ $c; $a = ~$b; $a = -$b; $a = +$b; $a = $b >> $c; $a = $b >> $c; $a = $b == $c; $a = $b === $c; $a = $b != $c; $a = $b < $c; $a = $b <= $c; $a = $b <= $c; $a = $b++; $a = ++$b; $a = $obj->b++; $a = ++$obj->b; $a = $b--; $a = --$b; $a = $obj->b--; $a = --$obj->b; $a = !$b; $a = $b === $c; $a = $b !== $c; $a = $b << 2; $a = $b >> 3; $a += $b; $a -= $b; $a *= $b; $a /= $b; $a <<= $b; $a >>= $b; $a &= $b; $a |= $b; $a .= $b; $a %= $b; $a ^= $b; $a = 'a' . 'b'; $a = 'a' . 'abc'; @f1(); print('1'); $a = $array['index']; $a = $object->prop; $a = $this->prop; $array['index'] = 1; $object->prop = 1; $this->prop = 1; $a = isset($b); $a = empty($b); unset($b); $a = isset($array['index']); $a = empty($array['index']); unset($array['index']); $a = isset($object->prop); $a = empty($object->prop); #if PHP_VERSION >= 500 unset($object->prop); #endif $a = isset($this->prop); $a = empty($this->prop); #if PHP_VERSION >= 500 unset($this->prop); $a = isset(ClassName::$prop); $a = empty(ClassName::$prop); unset(ClassName::$prop); #endif $a = (int) $b; $a = (double) $b; $a = (string) $b; $a = (array) $b; $a = (object) $b; $a = (bool) $b; $a = (unset) $b; $a = (array) $b; $a = (object) $b; $a = ($b ? $c : $d); $a = (f1() ? f2() : f3()); ($a = $b) xor $c; ($a = $b) and $c; ($a = $b) or $c; $a = $b && $c; $a = $b || $c; #if PHP_VERSION >= 500 do { try { echo 'outer try 1'; try { echo 'inner try'; } catch (InnerException $e) { echo $e; } catch (InnerException2 $e2) { echo $e2; } #if PHP_VERSION >= 550 finally { echo 'inner finally'; } #endif echo 'outer try 2'; } catch (OuterException $e) { echo $e; } catch (OuterException2 $e2) { echo $e2; } #if PHP_VERSION >= 550 finally { echo 'outer finally'; } #endif } while (0); #endif if (if_()) { echo 'if'; if (innerIf_()) { echo 'if innerIf'; } } else if (elseif_()) { echo 'else if'; if (innerIf_()) { echo 'if innerIf'; } } else { if (innerIf_()) { echo 'if innerIf'; } echo 'else'; } while (false) { echo 'while'; } do { echo 'do/while'; } while (false); $i = 1; for (; $i < 10; ++$i) { echo $i; break; } foreach ($array as $value) { foreach ($value as $key => $value) { echo $key . ' = ' . $value . "\n"; break 2; continue; } } switch ($normalSwitch) { case 'case1': echo 'case1'; switch ($nestedSwitch) { case 1: } break; case 'case2': echo 'case2'; break; default: switch ($nestedSwitch) { case 1: } echo 'default'; break; } switch ($switchWithoutDefault) { case 'case1': echo 'case1'; break; case 'case2': echo 'case2'; break; } switch ($switchWithMiddleDefault) { case 'case1': echo 'case1'; break; default: echo 'default'; break; case 'case2': echo 'case2'; break; } switch ($switchWithInitialDefault) { default: echo 'default'; break; case 'case1': echo 'case1'; break; case 'case2': echo 'case2'; break; } switch (emptySwitch()) { } switch (defaultSwitch()) { default: } declare (ticks=1) { echo 1; } while (1) { declare (ticks=1) { echo 2; } } require 'require.php'; require_once 'require_once.php'; include 'include.php'; include_once 'include_once.php'; echo __FILE__; echo __LINE__; #if PHP_VERSION >= 530 echo 'PHP 5.3+ code testing'; const CONST_VALUE = 1; echo $this::CONST_VALUE; echo $a::CONST_VALUE; echo CONST_VALUE; $this::__construct(); $obj::__construct(); $a = $b ?: $d; $a = ($b ?: $d) + $c; $a = f1() ?: f2(); $a = C::f1() ?: C::f2(); $a = ($b ? $c : $d); $a = ($b ? $c : $d) + $c; $a = (f1() ? f3() : f2()); if ($b ?: $d) { echo 'if ($b ?: $d)'; } if (($b ?: $d) + $c) { echo 'if (($b ?: $d) + $c)'; } if (f1() ?: f2()) { echo 'if (f1() ?: f2())'; } echo 'goto a'; goto a; $i = 1; for (; $i <= 2; ++$i) { goto a; } a: echo 'label a'; echo preg_replace_callback('~-([a-z])~', function($match) { return strtoupper($match[1]); }, 'hello-world'); $greet = function($name) { printf('Hello %s' . "\r\n" . '', $name); }; $greet('World'); $greet('PHP'); $total = 0; $tax = 1; $callback = function($quantity, $product) use($tax, &$total) { $tax = 'tax'; static $static1 = array(1); static $static2; $tax = 'tax'; $tax = --$tax; $pricePerItem = constant('PRICE_' . strtoupper($product)); $total += $pricePerItem * $quantity * ($tax + 1); }; #endif exit(); ?> xcache-3.1.0/mod_disassembler/xc_disassembler.c0000644000175000010010000001461212206607316020004 0ustar mOoNone#include "xc_disassembler.h" #include "xcache.h" #include "xcache/xc_ini.h" #include "xcache/xc_utils.h" #include "xcache/xc_sandbox.h" #include "xcache/xc_compatibility.h" #include "xc_processor.h" #include "ext/standard/info.h" static void xc_dasm(zval *output, zend_op_array *op_array TSRMLS_DC) /* {{{ */ { const Bucket *b; zval *zv, *list; xc_compile_result_t cr; int bufsize = 2; char *buf; xc_dasm_t dasm; xc_compile_result_init_cur(&cr, op_array TSRMLS_CC); xc_apply_op_array(&cr, (apply_func_t) xc_undo_pass_two TSRMLS_CC); xc_apply_op_array(&cr, (apply_func_t) xc_fix_opcode TSRMLS_CC); /* go */ array_init(output); ALLOC_INIT_ZVAL(zv); array_init(zv); xc_dasm_zend_op_array(&dasm, zv, op_array TSRMLS_CC); add_assoc_zval_ex(output, XCACHE_STRS("op_array"), zv); buf = emalloc(bufsize); ALLOC_INIT_ZVAL(list); array_init(list); for (b = xc_sandbox_user_function_begin(TSRMLS_C); b; b = b->pListNext) { int keysize, keyLength; ALLOC_INIT_ZVAL(zv); array_init(zv); xc_dasm_zend_function(&dasm, zv, b->pData TSRMLS_CC); keysize = BUCKET_KEY_SIZE(b) + 2; if (keysize > bufsize) { do { bufsize *= 2; } while (keysize > bufsize); buf = erealloc(buf, bufsize); } memcpy(buf, BUCKET_KEY_S(b), keysize); buf[keysize - 2] = buf[keysize - 1] = ""[0]; keyLength = b->nKeyLength; #ifdef IS_UNICODE if (BUCKET_KEY_TYPE(b) == IS_UNICODE) { if (buf[0] == ""[0] && buf[1] == ""[0]) { keyLength ++; } } else #endif { if (buf[0] == ""[0]) { keyLength ++; } } add_u_assoc_zval_ex(list, BUCKET_KEY_TYPE(b), ZSTR(buf), keyLength, zv); } add_assoc_zval_ex(output, XCACHE_STRS("function_table"), list); ALLOC_INIT_ZVAL(list); array_init(list); for (b = xc_sandbox_user_class_begin(TSRMLS_C); b; b = b->pListNext) { int keysize, keyLength; ALLOC_INIT_ZVAL(zv); array_init(zv); xc_dasm_zend_class_entry(&dasm, zv, CestToCePtr(*(xc_cest_t *)b->pData) TSRMLS_CC); keysize = BUCKET_KEY_SIZE(b) + 2; if (keysize > bufsize) { do { bufsize *= 2; } while (keysize > bufsize); buf = erealloc(buf, bufsize); } memcpy(buf, BUCKET_KEY_S(b), keysize); buf[keysize - 2] = buf[keysize - 1] = ""[0]; keyLength = b->nKeyLength; #ifdef IS_UNICODE if (BUCKET_KEY_TYPE(b) == IS_UNICODE) { if (buf[0] == ""[0] && buf[1] == ""[0]) { keyLength ++; } } else #endif { if (buf[0] == ""[0]) { keyLength ++; } } add_u_assoc_zval_ex(list, BUCKET_KEY_TYPE(b), ZSTR(buf), keyLength, zv); } efree(buf); add_assoc_zval_ex(output, XCACHE_STRS("class_table"), list); /*xc_apply_op_array(&cr, (apply_func_t) xc_redo_pass_two TSRMLS_CC);*/ xc_compile_result_free(&cr); } /* }}} */ typedef struct xc_dasm_sandboxed_t { /* {{{ */ enum Type { xc_dasm_file_t , xc_dasm_string_t } type; union { zval *zfilename; struct { zval *source; char *eval_name; } compile_string; } input; zval *output; } xc_dasm_sandboxed_t; /* }}} */ zend_op_array *xc_dasm_sandboxed(void *data TSRMLS_DC) /* {{{ */ { zend_bool catched = 0; zend_op_array *op_array = NULL; xc_dasm_sandboxed_t *sandboxed_dasm = (xc_dasm_sandboxed_t *) data; zend_try { if (sandboxed_dasm->type == xc_dasm_file_t) { op_array = compile_filename(ZEND_REQUIRE, sandboxed_dasm->input.zfilename TSRMLS_CC); } else { op_array = compile_string(sandboxed_dasm->input.compile_string.source, sandboxed_dasm->input.compile_string.eval_name TSRMLS_CC); } } zend_catch { catched = 1; } zend_end_try(); if (catched || !op_array) { #define return_value sandboxed_dasm->output RETVAL_FALSE; #undef return_value return NULL; } xc_dasm(sandboxed_dasm->output, op_array TSRMLS_CC); /* free */ #ifdef ZEND_ENGINE_2 destroy_op_array(op_array TSRMLS_CC); #else destroy_op_array(op_array); #endif efree(op_array); return NULL; } /* }}} */ void xc_dasm_string(zval *output, zval *source TSRMLS_DC) /* {{{ */ { xc_dasm_sandboxed_t sandboxed_dasm; char *eval_name = zend_make_compiled_string_description("runtime-created function" TSRMLS_CC); sandboxed_dasm.output = output; sandboxed_dasm.type = xc_dasm_string_t; sandboxed_dasm.input.compile_string.source = source; sandboxed_dasm.input.compile_string.eval_name = eval_name; xc_sandbox(&xc_dasm_sandboxed, (void *) &sandboxed_dasm, eval_name TSRMLS_CC); efree(eval_name); } /* }}} */ void xc_dasm_file(zval *output, const char *filename TSRMLS_DC) /* {{{ */ { zval *zfilename; xc_dasm_sandboxed_t sandboxed_dasm; MAKE_STD_ZVAL(zfilename); zfilename->value.str.val = estrdup(filename); zfilename->value.str.len = strlen(filename); zfilename->type = IS_STRING; sandboxed_dasm.output = output; sandboxed_dasm.type = xc_dasm_file_t; sandboxed_dasm.input.zfilename = zfilename; xc_sandbox(&xc_dasm_sandboxed, (void *) &sandboxed_dasm, zfilename->value.str.val TSRMLS_CC); zval_dtor(zfilename); FREE_ZVAL(zfilename); } /* }}} */ /* {{{ proto array xcache_dasm_file(string filename) Disassemble file into opcode array by filename */ PHP_FUNCTION(xcache_dasm_file) { char *filename; int filename_len; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) { return; } if (!filename_len) RETURN_FALSE; xc_dasm_file(return_value, filename TSRMLS_CC); } /* }}} */ /* {{{ proto array xcache_dasm_string(string code) Disassemble php code into opcode array */ PHP_FUNCTION(xcache_dasm_string) { zval *code; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &code) == FAILURE) { return; } xc_dasm_string(return_value, code TSRMLS_CC); } /* }}} */ /* {{{ PHP_MINFO_FUNCTION(xcache_disassembler) */ static PHP_MINFO_FUNCTION(xcache_disassembler) { php_info_print_table_start(); php_info_print_table_row(2, "XCache Disassembler Module", "enabled"); php_info_print_table_end(); DISPLAY_INI_ENTRIES(); } /* }}} */ static zend_function_entry xcache_disassembler_functions[] = /* {{{ */ { PHP_FE(xcache_dasm_file, NULL) PHP_FE(xcache_dasm_string, NULL) PHP_FE_END }; /* }}} */ static zend_module_entry xcache_disassembler_module_entry = { /* {{{ */ STANDARD_MODULE_HEADER, XCACHE_NAME " Disassembler", xcache_disassembler_functions, NULL, NULL, NULL, NULL, PHP_MINFO(xcache_disassembler), XCACHE_VERSION, #ifdef PHP_GINIT NO_MODULE_GLOBALS, #endif #ifdef ZEND_ENGINE_2 NULL, #else NULL, NULL, #endif STANDARD_MODULE_PROPERTIES_EX }; /* }}} */ int xc_disassembler_startup_module() /* {{{ */ { return zend_startup_module(&xcache_disassembler_module_entry); } /* }}} */ xcache-3.1.0/mod_disassembler/xc_disassembler.h0000644000175000010010000000043512157744740020017 0ustar mOoNone#ifndef XC_DISASSEMBLER_H_1547840703D7ADD9C19041818BE9E3C7 #define XC_DISASSEMBLER_H_1547840703D7ADD9C19041818BE9E3C7 #if _MSC_VER > 1000 #pragma once #endif /* _MSC_VER > 1000 */ int xc_disassembler_startup_module(); #endif /* XC_DISASSEMBLER_H_1547840703D7ADD9C19041818BE9E3C7 */ xcache-3.1.0/mod_encoder/0000755000175000010010000000000012157744741013440 5ustar mOoNonexcache-3.1.0/mod_encoder/xc_encoder.c0000644000175000010010000000003012157744741015706 0ustar mOoNonestatic void dummy() { } xcache-3.1.0/mod_optimizer/0000755000175000010010000000000012225452352014031 5ustar mOoNonexcache-3.1.0/mod_optimizer/xc_optimizer.c0000644000175000010010000004067712225452352016727 0ustar mOoNone#if 0 # define XCACHE_DEBUG #endif #include "xc_optimizer.h" #include "xcache/xc_extension.h" #include "xcache/xc_ini.h" #include "xcache/xc_utils.h" #include "util/xc_stack.h" #include "util/xc_trace.h" #include "xcache_globals.h" #include "ext/standard/info.h" #ifdef XCACHE_DEBUG # include "xc_processor.h" # include "xcache/xc_const_string.h" # include "xcache/xc_opcode_spec.h" # include "ext/standard/php_var.h" #endif #ifdef IS_CV # define XCACHE_IS_CV IS_CV #else # define XCACHE_IS_CV 16 #endif #ifdef ZEND_ENGINE_2_4 # undef Z_OP_CONSTANT /* Z_OP_CONSTANT is used before pass_two is applied */ # define Z_OP_CONSTANT(op) op_array->literals[(op).constant].constant #endif typedef zend_uint bbid_t; #define BBID_INVALID ((bbid_t) -1) /* {{{ basic block */ typedef struct _bb_t { bbid_t id; zend_bool used; zend_bool alloc; zend_op *opcodes; int count; int size; bbid_t fall; zend_uint opnum; /* opnum after joining basic block */ } bb_t; /* }}} */ /* basic blocks */ typedef xc_stack_t bbs_t; /* op array helper functions */ static int op_array_convert_switch(zend_op_array *op_array) /* {{{ */ { zend_uint i; if (op_array->brk_cont_array == NULL) { return SUCCESS; } for (i = 0; i < op_array->last; i ++) { zend_op *opline = &op_array->opcodes[i]; zend_brk_cont_element *jmp_to; zend_bool can_convert = 1; int array_offset, nest_levels; switch (opline->opcode) { case ZEND_BRK: case ZEND_CONT: break; #ifdef ZEND_GOTO case ZEND_GOTO: #endif continue; default: continue; } if (Z_OP_TYPE(opline->op2) != IS_CONST || Z_OP_CONSTANT(opline->op2).type != IS_LONG) { return FAILURE; } nest_levels = Z_OP_CONSTANT(opline->op2).value.lval; array_offset = Z_OP(opline->op1).opline_num; do { if (array_offset == -1) { return FAILURE; } jmp_to = &op_array->brk_cont_array[array_offset]; if (nest_levels > 1) { zend_op *brk_opline = &op_array->opcodes[jmp_to->brk]; switch (brk_opline->opcode) { case ZEND_SWITCH_FREE: case ZEND_FREE: #ifdef EXT_TYPE_FREE_ON_RETURN if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) #endif { can_convert = 0; } break; } } array_offset = jmp_to->parent; } while (--nest_levels > 0); if (can_convert) { /* rewrite to jmp */ switch (opline->opcode) { case ZEND_BRK: Z_OP(opline->op1).opline_num = jmp_to->brk; break; case ZEND_CONT: Z_OP(opline->op1).opline_num = jmp_to->cont; break; } Z_OP_TYPE(opline->op2) = IS_UNUSED; opline->opcode = ZEND_JMP; } } return SUCCESS; } /* }}} */ /* {{{ op_flowinfo helper func */ enum { XC_OPNUM_INVALID = -1 }; typedef struct { int jmpout_op1; int jmpout_op2; int jmpout_ext; zend_bool fall; } op_flowinfo_t; static void op_flowinfo_init(op_flowinfo_t *fi) { fi->jmpout_op1 = fi->jmpout_op2 = fi->jmpout_ext = XC_OPNUM_INVALID; fi->fall = 0; } /* }}} */ static int op_get_flowinfo(op_flowinfo_t *fi, zend_op *opline) /* {{{ */ { op_flowinfo_init(fi); switch (opline->opcode) { #ifdef ZEND_HANDLE_EXCEPTION case ZEND_HANDLE_EXCEPTION: #endif case ZEND_RETURN: #ifdef ZEND_FAST_RET case ZEND_FAST_RET: #endif #ifdef ZEND_GENERATOR_RETURN case ZEND_GENERATOR_RETURN: #endif case ZEND_EXIT: return SUCCESS; /* no fall */ #ifdef ZEND_GOTO case ZEND_GOTO: #endif case ZEND_JMP: fi->jmpout_op1 = Z_OP(opline->op1).opline_num; return SUCCESS; /* no fall */ #ifdef ZEND_FAST_CALL case ZEND_FAST_CALL: fi->jmpout_op1 = Z_OP(opline->op1).opline_num; if (opline->extended_value) { fi->jmpout_op2 = Z_OP(opline->op2).opline_num; } return SUCCESS; /* no fall */ #endif case ZEND_JMPZNZ: fi->jmpout_op2 = Z_OP(opline->op2).opline_num; fi->jmpout_ext = (int) opline->extended_value; return SUCCESS; /* no fall */ case ZEND_JMPZ: case ZEND_JMPNZ: case ZEND_JMPZ_EX: case ZEND_JMPNZ_EX: #ifdef ZEND_JMP_SET case ZEND_JMP_SET: #endif #ifdef ZEND_JMP_SET_VAR case ZEND_JMP_SET_VAR: #endif #ifdef ZEND_JMP_NO_CTOR case ZEND_JMP_NO_CTOR: #endif #ifdef ZEND_NEW case ZEND_NEW: #endif #ifdef ZEND_FE_RESET case ZEND_FE_RESET: #endif case ZEND_FE_FETCH: fi->jmpout_op2 = Z_OP(opline->op2).opline_num; fi->fall = 1; return SUCCESS; #ifdef ZEND_CATCH case ZEND_CATCH: fi->jmpout_ext = (int) opline->extended_value; fi->fall = 1; return SUCCESS; #endif default: return FAILURE; } } /* }}} */ #ifdef XCACHE_DEBUG static void op_snprint(zend_op_array *op_array, char *buf, int size, zend_uchar op_type, znode_op *op, xc_op_spec_t op_spec) /* {{{ */ { switch ((op_spec & OPSPEC_UNUSED) ? IS_UNUSED : op_type) { case IS_CONST: { zval result; zval *zv = &Z_OP_CONSTANT(*op); TSRMLS_FETCH(); php_output_start_default(TSRMLS_C); php_var_export(&zv, 1 TSRMLS_CC); php_output_get_contents(&result TSRMLS_CC); php_output_discard(TSRMLS_C); snprintf(buf, size, Z_STRVAL(result)); zval_dtor(&result); } break; case IS_TMP_VAR: snprintf(buf, size, "t@%d", Z_OP(*op).var); break; case XCACHE_IS_CV: case IS_VAR: snprintf(buf, size, "v@%d", Z_OP(*op).var); break; case IS_UNUSED: if (Z_OP(*op).opline_num) { snprintf(buf, size, "u#%d", Z_OP(*op).opline_num); } else { snprintf(buf, size, "-"); } break; default: snprintf(buf, size, "%d %d", op_type, Z_OP(*op).var); } } /* }}} */ static void op_print(zend_op_array *op_array, int line, zend_op *first, zend_op *end) /* {{{ */ { zend_op *opline; for (opline = first; opline < end; opline ++) { char buf_r[20]; char buf_1[20]; char buf_2[20]; const xc_opcode_spec_t *opcode_spec = xc_get_opcode_spec(opline->opcode); op_snprint(op_array, buf_r, sizeof(buf_r), Z_OP_TYPE(opline->result), &opline->result, opcode_spec->res); op_snprint(op_array, buf_1, sizeof(buf_1), Z_OP_TYPE(opline->op1), &opline->op1, opcode_spec->op1); op_snprint(op_array, buf_2, sizeof(buf_2), Z_OP_TYPE(opline->op2), &opline->op2, opcode_spec->op2); fprintf(stderr, "%3d %3lu" " %-25s%-8s%-20s%-20s%5lu\n" , opline->lineno, (long) (opline - first + line) , xc_get_opcode(opline->opcode), buf_r, buf_1, buf_2, opline->extended_value); } } /* }}} */ static void op_array_print_try_catch(zend_op_array *op_array TSRMLS_DC) /* {{{ */ { int i; for (i = 0; i < op_array->last_try_catch; i ++) { zend_try_catch_element *element = &op_array->try_catch_array[i]; # ifdef ZEND_ENGINE_2_5 fprintf(stderr, "try_catch[%d] = %u, %u, %u, %u\n", i, element->try_op, element->catch_op, element->finally_op, element->finally_end); # else fprintf(stderr, "try_catch[%d] = %u, %u\n", i, element->try_op, element->catch_op); # endif } } /* }}} */ #endif /* * basic block functions */ static bb_t *bb_new_ex(zend_op *opcodes, int count) /* {{{ */ { bb_t *bb = (bb_t *) ecalloc(sizeof(bb_t), 1); bb->fall = BBID_INVALID; if (opcodes) { bb->alloc = 0; bb->size = bb->count = count; bb->opcodes = opcodes; } else { bb->alloc = 1; bb->size = bb->count = 8; bb->opcodes = ecalloc(sizeof(zend_op), bb->size); } return bb; } /* }}} */ #define bb_new() bb_new_ex(NULL, 0) static void bb_destroy(bb_t *bb) /* {{{ */ { if (bb->alloc) { efree(bb->opcodes); } efree(bb); } /* }}} */ #ifdef XCACHE_DEBUG static void bb_print(bb_t *bb, zend_op_array *op_array) /* {{{ */ { int line = bb->opcodes - op_array->opcodes; op_flowinfo_t fi; zend_op *last = bb->opcodes + bb->count - 1; op_get_flowinfo(&fi, last); fprintf(stderr, "\n==== #%-3d cnt:%-3d lno:%-3d" " %c%c" " op1:%-3d op2:%-3d ext:%-3d fal:%-3d %s ====\n" , bb->id, bb->count, bb->alloc ? -1 : line , bb->used ? 'U' : ' ', bb->alloc ? 'A' : ' ' , fi.jmpout_op1, fi.jmpout_op2, fi.jmpout_ext, bb->fall, xc_get_opcode(last->opcode) ); op_print(op_array, line, bb->opcodes, last + 1); } /* }}} */ #endif static bb_t *bbs_get(bbs_t *bbs, int n) /* {{{ */ { return (bb_t *) xc_stack_get(bbs, n); } /* }}} */ static int bbs_count(bbs_t *bbs) /* {{{ */ { return xc_stack_count(bbs); } /* }}} */ static void bbs_destroy(bbs_t *bbs) /* {{{ */ { bb_t *bb; while (bbs_count(bbs)) { bb = (bb_t *) xc_stack_pop(bbs); bb_destroy(bb); } xc_stack_destroy(bbs); } /* }}} */ #ifdef XCACHE_DEBUG static void bbs_print(bbs_t *bbs, zend_op_array *op_array) /* {{{ */ { int i; for (i = 0; i < xc_stack_count(bbs); i ++) { bb_print(bbs_get(bbs, i), op_array); } } /* }}} */ #endif #define bbs_init(bbs) xc_stack_init_ex(bbs, 16) static bb_t *bbs_add_bb(bbs_t *bbs, bb_t *bb) /* {{{ */ { bb->id = (bbid_t) xc_stack_count(bbs); xc_stack_push(bbs, (void *) bb); return bb; } /* }}} */ static bb_t *bbs_new_bb_ex(bbs_t *bbs, zend_op *opcodes, int count) /* {{{ */ { return bbs_add_bb(bbs, bb_new_ex(opcodes, count)); } /* }}} */ static int bbs_build_from(bbs_t *bbs, zend_op_array *op_array, int count) /* {{{ */ { int i, start; bb_t *bb; bbid_t id; op_flowinfo_t fi; zend_op *opline; ALLOCA_FLAG(opline_infos_use_heap) typedef struct { zend_bool isbbhead; bbid_t bbid; } oplineinfo_t; oplineinfo_t *oplineinfos = xc_do_alloca(count * sizeof(oplineinfo_t), opline_infos_use_heap); memset(oplineinfos, 0, count * sizeof(oplineinfo_t)); /* {{{ mark jmpin/jumpout */ oplineinfos[0].isbbhead = 1; for (i = 0; i < count; i ++) { if (op_get_flowinfo(&fi, &op_array->opcodes[i]) == SUCCESS) { if (fi.jmpout_op1 != XC_OPNUM_INVALID) { oplineinfos[fi.jmpout_op1].isbbhead = 1; } if (fi.jmpout_op2 != XC_OPNUM_INVALID) { oplineinfos[fi.jmpout_op2].isbbhead = 1; } if (fi.jmpout_ext != XC_OPNUM_INVALID) { oplineinfos[fi.jmpout_ext].isbbhead = 1; } if (i + 1 < count) { oplineinfos[i + 1].isbbhead = 1; } } } #ifdef ZEND_ENGINE_2 /* mark try start */ for (i = 0; i < op_array->last_try_catch; i ++) { # define MARK_OP_BB_HEAD(name) \ oplineinfos[op_array->try_catch_array[i].name].isbbhead = 1 MARK_OP_BB_HEAD(try_op); MARK_OP_BB_HEAD(catch_op); # ifdef ZEND_ENGINE_2_5 MARK_OP_BB_HEAD(finally_op); # endif # undef MARK_OP_BB_HEAD } #endif /* }}} */ /* {{{ fill op lines with newly allocated id */ for (i = 0; i < count; i ++) { oplineinfos[i].bbid = BBID_INVALID; } id = -1; for (i = 0; i < count; i ++) { if (oplineinfos[i].isbbhead) { id ++; } oplineinfos[i].bbid = id; TRACE("bbids[%d] = %d", i, id); } /* }}} */ #ifdef ZEND_ENGINE_2 /* {{{ convert try_catch_array.* from oplinenum to bbid */ for (i = 0; i < op_array->last_try_catch; i ++) { # define OPNUM_TO_BBID(name) \ op_array->try_catch_array[i].name = oplineinfos[op_array->try_catch_array[i].name].bbid; OPNUM_TO_BBID(try_op); OPNUM_TO_BBID(catch_op); # ifdef ZEND_ENGINE_2_5 OPNUM_TO_BBID(finally_op); # endif # undef OPNUM_TO_BBID } /* }}} */ #endif /* {{{ create basic blocks */ start = 0; id = 0; /* loop over to deal with the last block */ for (i = 1; i <= count; i ++) { if (i < count && id == oplineinfos[i].bbid) { continue; } opline = op_array->opcodes + start; bb = bbs_new_bb_ex(bbs, opline, i - start); /* last */ opline = bb->opcodes + bb->count - 1; if (op_get_flowinfo(&fi, opline) == SUCCESS) { if (fi.jmpout_op1 != XC_OPNUM_INVALID) { Z_OP(opline->op1).opline_num = oplineinfos[fi.jmpout_op1].bbid; assert(Z_OP(opline->op1).opline_num != BBID_INVALID); } if (fi.jmpout_op2 != XC_OPNUM_INVALID) { Z_OP(opline->op2).opline_num = oplineinfos[fi.jmpout_op2].bbid; assert(Z_OP(opline->op2).opline_num != BBID_INVALID); } if (fi.jmpout_ext != XC_OPNUM_INVALID) { opline->extended_value = oplineinfos[fi.jmpout_ext].bbid; assert(opline->extended_value != BBID_INVALID); } if (fi.fall && i + 1 < count) { bb->fall = oplineinfos[i + 1].bbid; TRACE("fall %d", bb->fall); assert(bb->fall != BBID_INVALID); } } if (i >= count) { break; } start = i; id = oplineinfos[i].bbid; } /* }}} */ xc_free_alloca(oplineinfos, opline_infos_use_heap); return SUCCESS; } /* }}} */ static void bbs_restore_opnum(bbs_t *bbs, zend_op_array *op_array) /* {{{ */ { int bbid; zend_uint i; for (bbid = 0; bbid < bbs_count(bbs); bbid ++) { op_flowinfo_t fi; bb_t *bb = bbs_get(bbs, bbid); zend_op *last = bb->opcodes + bb->count - 1; if (op_get_flowinfo(&fi, last) == SUCCESS) { if (fi.jmpout_op1 != XC_OPNUM_INVALID) { Z_OP(last->op1).opline_num = bbs_get(bbs, fi.jmpout_op1)->opnum; assert(Z_OP(last->op1).opline_num != BBID_INVALID); } if (fi.jmpout_op2 != XC_OPNUM_INVALID) { Z_OP(last->op2).opline_num = bbs_get(bbs, fi.jmpout_op2)->opnum; assert(Z_OP(last->op2).opline_num != BBID_INVALID); } if (fi.jmpout_ext != XC_OPNUM_INVALID) { last->extended_value = bbs_get(bbs, fi.jmpout_ext)->opnum; assert(last->extended_value != BBID_INVALID); } } } #ifdef ZEND_ENGINE_2 /* {{{ convert try_catch_array from bbid to oplinenum */ for (i = 0; i < op_array->last_try_catch; i ++) { # define BBID_TO_OPNUM(name) \ op_array->try_catch_array[i].name = bbs_get(bbs, op_array->try_catch_array[i].name)->opnum; BBID_TO_OPNUM(try_op); BBID_TO_OPNUM(catch_op); # ifdef ZEND_ENGINE_2_5 BBID_TO_OPNUM(finally_op); # endif # undef BBID_TO_OPNUM } /* }}} */ #endif /* ZEND_ENGINE_2 */ } /* }}} */ /* * optimize */ static int xc_optimize_op_array(zend_op_array *op_array TSRMLS_DC) /* {{{ */ { bbs_t bbs; if (op_array->type != ZEND_USER_FUNCTION) { return 0; } #ifdef XCACHE_DEBUG TRACE("optimize file: %s", op_array->filename); # if 0 && HAVE_XCACHE_DPRINT xc_dprint_zend_op_array(op_array, 0 TSRMLS_CC); # endif op_array_print_try_catch(op_array TSRMLS_CC); op_print(op_array, 0, op_array->opcodes, op_array->opcodes + op_array->last); #endif if (op_array_convert_switch(op_array) == SUCCESS) { bbs_init(&bbs); if (bbs_build_from(&bbs, op_array, op_array->last) == SUCCESS) { int i; #ifdef XCACHE_DEBUG bbs_print(&bbs, op_array); #endif /* TODO: calc opnum after basic block move */ for (i = 0; i < bbs_count(&bbs); i ++) { bb_t *bb = bbs_get(&bbs, i); bb->opnum = bb->opcodes - op_array->opcodes; } bbs_restore_opnum(&bbs, op_array); } bbs_destroy(&bbs); } #ifdef XCACHE_DEBUG TRACE("%s", "after compiles"); # if 0 xc_dprint_zend_op_array(op_array, 0 TSRMLS_CC); # endif op_array_print_try_catch(op_array TSRMLS_CC); op_print(op_array, 0, op_array->opcodes, op_array->opcodes + op_array->last); #endif return 0; } /* }}} */ static void xc_optimizer_op_array_handler(zend_op_array *op_array) /* {{{ */ { TSRMLS_FETCH(); if (XG(optimizer)) { xc_optimize_op_array(op_array TSRMLS_CC); } } /* }}} */ static int xc_coverager_zend_startup(zend_extension *extension) /* {{{ */ { return SUCCESS; } /* }}} */ static void xc_coverager_zend_shutdown(zend_extension *extension) /* {{{ */ { } /* }}} */ /* {{{ zend extension definition structure */ static zend_extension xc_optimizer_zend_extension_entry = { XCACHE_NAME " Optimizer", XCACHE_VERSION, XCACHE_AUTHOR, XCACHE_URL, XCACHE_COPYRIGHT, xc_coverager_zend_startup, xc_coverager_zend_shutdown, NULL, /* activate_func_t */ NULL, /* deactivate_func_t */ NULL, /* message_handler_func_t */ xc_optimizer_op_array_handler, NULL, /* statement_handler_func_t */ NULL, /* fcall_begin_handler_func_t */ NULL, /* fcall_end_handler_func_t */ NULL, /* op_array_ctor_func_t */ NULL, /* op_array_dtor_func_t */ STANDARD_ZEND_EXTENSION_PROPERTIES }; /* }}} */ /* {{{ ini */ PHP_INI_BEGIN() STD_PHP_INI_BOOLEAN("xcache.optimizer", "0", PHP_INI_ALL, OnUpdateBool, optimizer, zend_xcache_globals, xcache_globals) PHP_INI_END() /* }}} */ static PHP_MINFO_FUNCTION(xcache_optimizer) /* {{{ */ { php_info_print_table_start(); php_info_print_table_row(2, "XCache Optimizer Module", "enabled"); php_info_print_table_end(); DISPLAY_INI_ENTRIES(); } /* }}} */ static PHP_MINIT_FUNCTION(xcache_optimizer) /* {{{ */ { REGISTER_INI_ENTRIES(); return xcache_zend_extension_add(&xc_optimizer_zend_extension_entry, 0); } /* }}} */ static PHP_MSHUTDOWN_FUNCTION(xcache_optimizer) /* {{{ */ { UNREGISTER_INI_ENTRIES(); return xcache_zend_extension_remove(&xc_optimizer_zend_extension_entry); } /* }}} */ static zend_module_entry xcache_optimizer_module_entry = { /* {{{ */ STANDARD_MODULE_HEADER, XCACHE_NAME " Optimizer", NULL, PHP_MINIT(xcache_optimizer), PHP_MSHUTDOWN(xcache_optimizer), NULL, NULL, PHP_MINFO(xcache_optimizer), XCACHE_VERSION, #ifdef PHP_GINIT NO_MODULE_GLOBALS, #endif #ifdef ZEND_ENGINE_2 NULL, #else NULL, NULL, #endif STANDARD_MODULE_PROPERTIES_EX }; /* }}} */ int xc_optimizer_startup_module() /* {{{ */ { return zend_startup_module(&xcache_optimizer_module_entry); } /* }}} */ xcache-3.1.0/mod_optimizer/xc_optimizer.h0000644000175000010010000000044312157744740016730 0ustar mOoNone#ifndef XC_OPTIMIZER_H_6614228F428A266C39CDAC30269D9857 #define XC_OPTIMIZER_H_6614228F428A266C39CDAC30269D9857 #if _MSC_VER > 1000 #pragma once #endif /* _MSC_VER > 1000 */ #include "php.h" int xc_optimizer_startup_module(); #endif /* XC_OPTIMIZER_H_6614228F428A266C39CDAC30269D9857 */ xcache-3.1.0/NEWS0000644000175000010010000000633712225461700011655 0ustar mOoNone3.1.0 2013-10-10 ======== * adds support for PHP_5_5 * compatible with pcntl_fork() * fixes support for __FILE__ __DIR__ on moved/hardlinked files * disassembler now working again (fail since 3.0), supports PHP 4.x ~ PHP 5.5.x 3.0.4 2013-10-10 ======== * improve stability under massive concurrent * refix locking impl for threaded env * fix out of source building 3.0.3 2013-06-18 ======== * clean files in release (fix htdocs config) 3.0.2 2013-06-10 ======== * (PHP5.4+ only bug) random "cannot redeclare class" errors is now gone. Can also be avoid by using readonly_protection (unavailable with /dev/zero). * fixes SEGV with Zend Debugger * more bug fixes 3.0.1 2013-01-11 ======== * bug fixes * improve compatibility with "the ionCube PHP Loader", Zend Optimizer * improve stability * improve support for PHP_5_4 * improve stability on threaded env 3.0.0 2012-10-29 ======== * lots of improvements * bug fixes * updates api, adds a few ini * uses extension= to load XCache. loading via zend_extension= is unsupported * updates XCache admin page * namespace support * professional helpers * adds an diagnosis module to give advise @ htdocs * auto disable caching on crash @ runtime 2.0.1 2012-07-14 ======== * improve stability * admin/ config changed. please update accordingly * PHP 5.3.14 is unstable. Please upgrade to new version. You have been warned * fixed __FILE__ __DIR__ handling for moved/hardlinked files (set "xcache.experimental = on" to eanble this fix) 2.0.0 2012-04-20 ======== * support for PHP_5_4 * reduce memory usage by caching 1 for multiple same content files * correct __FILE__ __DIR__ supported for hardlinked files 1.3.2 2011-06-04 ======== * admin page security fix * adds 30 seconds timeout to "compiling" flag * improves decompiling * memory leak on recompile * disassembler fixes and updates for new PHP * win32 build fix * improve compatibility with ionCube Loader 1.3.1 2010-11-27 ======== * 2G/4G limitation on 64bit arch * xcache_unset matching e.g. prefixed_ values 1.3.0 2009-08-04 ======== * PHP 5.3 support * many cacher/coverager bug fixes * improved admin pages * admin page is now magic quote gpc aware 1.2.2 2007-12-29 ======== * live with wrong system time: allow caching files with mtime in further * bug fix for compatibility with Zend Optimizer and other non-cachable * a rare segv bug with token_get_all * minor bug fixes 1.2.1 2007-07-01 ======== * compatibility fix for apache 1.x, which init XCache module correctly * full Zend Optimizer compatibility * ini settings changed * other bug fixes 1.2.0 2006-12-10 ======== * full 5.2 support * minor admin/coverage-viewer page improves * compatible with suhosin/ZendOptimizer * xcache_get reference handling * new apis for coverager * some ini settings changed 1.1.0 2006-11-11 ======== * fix xcache_get issue on ttl 0 data * avoid crash when php failed to compile file when coverager enabled * gc expired items, new ini * Partial php 5.2 support * "Cannot redeclare ()" bug * bug fixes * Chinese Simplified/Traditional translations * admin page fixes and applied phpinfo style * coverage viewer page use phpinfo style * fix build on rare arch and Mac OS X * zts build * includes all fixes from <=1.0.2 xcache-3.1.0/processor/0000755000175000010010000000000012225452353013170 5ustar mOoNonexcache-3.1.0/processor/hashtable.m40000644000175000010010000001117512225452353015372 0ustar mOoNonednl DEF_HASH_TABLE_FUNC(1:name, 2:datatype [, 3:dataname] [, 4:check_function]) define(`DEF_HASH_TABLE_FUNC', ` DEF_STRUCT_P_FUNC(`HashTable', `$1', ` pushdefFUNC_NAME(`$2', `$3') dnl {{{ dasm IFDASM(` const Bucket *srcBucket; zval *zv; int bufsize = 2; char *buf = emalloc(bufsize); int keysize; #if defined(HARDENING_PATCH_HASH_PROTECT) && HARDENING_PATCH_HASH_PROTECT DONE(canary) #endif DONE(nTableSize) DONE(nTableMask) DONE(nNumOfElements) DONE(nNextFreeElement) DONE(pInternalPointer) DONE(pListHead) DONE(pListTail) DONE(arBuckets) DONE(pDestructor) DONE(persistent) DONE(nApplyCount) DONE(bApplyProtection) #if ZEND_DEBUG DONE(inconsistent) #endif #ifdef IS_UNICODE DONE(unicode) #endif DISABLECHECK(` for (srcBucket = SRC(`pListHead'); srcBucket != NULL; srcBucket = srcBucket->pListNext) { ALLOC_INIT_ZVAL(zv); array_init(zv); FUNC_NAME (dasm, zv, (($2*)srcBucket->pData) TSRMLS_CC); keysize = BUCKET_KEY_SIZE(srcBucket) + 2; if (keysize > bufsize) { do { bufsize *= 2; } while (keysize > bufsize); buf = erealloc(buf, bufsize); } memcpy(buf, BUCKET_KEY_S(srcBucket), keysize); buf[keysize - 2] = buf[keysize - 1] = ""[0]; keysize = srcBucket->nKeyLength; #ifdef IS_UNICODE if (BUCKET_KEY_TYPE(srcBucket) == IS_UNICODE) { if (buf[0] == ""[0] && buf[1] == ""[0]) { keysize ++; } } else #endif { if (buf[0] == ""[0]) { keysize ++; } } add_u_assoc_zval_ex(dst, BUCKET_KEY_TYPE(srcBucket), ZSTR(buf), keysize, zv); } ') efree(buf); ', ` dnl }}} Bucket *srcBucket; IFCOPY(`Bucket *pnew = NULL, *prev = NULL;') zend_bool first = 1; dnl only used for copy IFCOPY(`uint n;') IFCALCCOPY(`size_t bucketsize;') #if defined(HARDENING_PATCH_HASH_PROTECT) && HARDENING_PATCH_HASH_PROTECT IFRESTORE(`DST(`canary') = zend_hash_canary; DONE(canary)', ` dnl else PROCESS(unsigned int, canary) ') #endif PROCESS(uint, nTableSize) PROCESS(uint, nTableMask) PROCESS(uint, nNumOfElements) PROCESS(ulong, nNextFreeElement) IFCOPY(`DST(`pInternalPointer') = NULL; /* Used for element traversal */') DONE(pInternalPointer) IFCOPY(`DST(`pListHead') = NULL;') DONE(pListHead) #ifdef ZEND_ENGINE_2_4 if (SRC(`nTableMask')) { #endif CALLOC(`DST(`arBuckets')', Bucket*, SRC(`nTableSize')) DONE(arBuckets) DISABLECHECK(` for (srcBucket = SRC(`pListHead'); srcBucket != NULL; srcBucket = srcBucket->pListNext) { ifelse($4, `', `', ` pushdef(`BUCKET', `srcBucket') if ($4 == ZEND_HASH_APPLY_REMOVE) { IFCOPY(`DST(`nNumOfElements') --;') continue; } popdef(`BUCKET') ') IFCALCCOPY(`bucketsize = BUCKET_SIZE(srcBucket);') ALLOC(pnew, char, bucketsize, , Bucket) IFCOPY(` #ifdef ZEND_ENGINE_2_4 memcpy(pnew, srcBucket, BUCKET_HEAD_SIZE(Bucket)); if (BUCKET_KEY_SIZE(srcBucket)) { memcpy((char *) (pnew + 1), srcBucket->arKey, BUCKET_KEY_SIZE(srcBucket)); pnew->arKey = (const char *) (pnew + 1); } else { pnew->arKey = NULL; } #else memcpy(pnew, srcBucket, bucketsize); #endif n = srcBucket->h & SRC(`nTableMask'); /* pnew into hash node chain */ pnew->pLast = NULL; pnew->pNext = DST(`arBuckets[n]'); if (pnew->pNext) { pnew->pNext->pLast = pnew; } DST(`arBuckets[n]') = pnew; ') IFDPRINT(` INDENT() fprintf(stderr, "$2:\""); xc_dprint_str_len(BUCKET_KEY_S(srcBucket), BUCKET_KEY_SIZE(srcBucket)); fprintf(stderr, "\" %d:h=%lu ", BUCKET_KEY_SIZE(srcBucket), srcBucket->h); ') if (sizeof(void *) == sizeof($2)) { IFCOPY(`pnew->pData = &pnew->pDataPtr;') dnl no alloc STRUCT_P_EX(`$2', pnew->pData, (($2*)srcBucket->pData), `', `$3', ` ') } else { STRUCT_P_EX(`$2', pnew->pData, (($2*)srcBucket->pData), `', `$3') IFCOPY(`pnew->pDataPtr = NULL;') } if (first) { IFCOPY(`DST(`pListHead') = pnew;') first = 0; } IFCOPY(` /* flat link */ pnew->pListLast = prev; pnew->pListNext = NULL; if (prev) { prev->pListNext = pnew; } prev = pnew; ') } ') dnl TODO: fix pointer on arBuckets[n] FIXPOINTER(Bucket *, arBuckets) #ifdef ZEND_ENGINE_2_4 } else { /* if (SRC(`nTableMask')) */ DONE(arBuckets) } #endif IFCOPY(`DST(`pListTail') = pnew;') DONE(pListTail) IFCOPY(`DST(`pDestructor') = SRC(`pDestructor');') DONE(pDestructor) PROCESS(zend_bool, persistent) #ifdef IS_UNICODE PROCESS(zend_bool, unicode) #endif PROCESS(unsigned char, nApplyCount) PROCESS(zend_bool, bApplyProtection) #if ZEND_DEBUG PROCESS(int, inconsistent) #endif ')dnl IFDASM popdef(`FUNC_NAME') ') ') xcache-3.1.0/processor/head.m40000644000175000010010000003725512220455234014343 0ustar mOoNonednl {{{ === program start ======================================== divert(0) #include #include #include "php.h" #include "zend_extensions.h" #include "zend_compile.h" #include "zend_API.h" #include "zend_ini.h" /* export: #include "xcache.h" :export */ #include "xcache.h" /* export: #include "mod_cacher/xc_cache.h" :export */ #include "mod_cacher/xc_cache.h" /* export: #include "xcache/xc_shm.h" :export */ #include "xcache/xc_shm.h" /* export: #include "xcache/xc_allocator.h" :export */ #include "xcache/xc_allocator.h" #include "xcache/xc_const_string.h" #include "xcache/xc_utils.h" #include "util/xc_align.h" #include "xc_processor.h" #include "xcache_globals.h" #if defined(HARDENING_PATCH_HASH_PROTECT) && HARDENING_PATCH_HASH_PROTECT extern unsigned int zend_hash_canary; #endif define(`SIZEOF_zend_uint', `sizeof(zend_uint)') define(`COUNTOF_zend_uint', `1') define(`SIZEOF_int', `sizeof(int)') define(`COUNTOF_int', `1') define(`SIZEOF_zend_function', `sizeof(zend_function)') define(`COUNTOF_zend_function', `1') define(`SIZEOF_zval_ptr', `sizeof(zval_ptr)') define(`COUNTOF_zval_ptr', `1') define(`SIZEOF_zval_ptr_nullable', `sizeof(zval_ptr_nullable)') define(`COUNTOF_zval_ptr_nullable', `1') define(`SIZEOF_zend_trait_alias_ptr', `sizeof(zend_trait_alias)') define(`COUNTOF_zend_trait_alias_ptr', `1') define(`SIZEOF_zend_trait_precedence_ptr', `sizeof(zend_trait_precedence)') define(`COUNTOF_zend_trait_precedence_ptr', `1') define(`SIZEOF_xc_entry_name_t', `sizeof(xc_entry_name_t)') define(`COUNTOF_xc_entry_name_t', `1') define(`SIZEOF_xc_ztstring', `sizeof(xc_ztstring)') define(`COUNTOF_xc_ztstring', `1') ifdef(`XCACHE_ENABLE_TEST', ` #undef NDEBUG #include m4_errprint(`AUTOCHECK INFO: runtime autocheck Enabled (debug build)') ', ` m4_errprint(`AUTOCHECK INFO: runtime autocheck Disabled (optimized build)') ') ifdef(`DEBUG_SIZE', `static int xc_totalsize = 0;') sinclude(builddir`/structinfo.m4') #ifndef NDEBUG # undef inline #define inline #endif typedef zval *zval_ptr; typedef zval *zval_ptr_nullable; typedef char *xc_ztstring; #ifdef ZEND_ENGINE_2_4 typedef zend_trait_alias *zend_trait_alias_ptr; typedef zend_trait_precedence *zend_trait_precedence_ptr; #endif #ifdef ZEND_ENGINE_2_3 typedef int last_brk_cont_t; #else typedef zend_uint last_brk_cont_t; #endif typedef zend_uchar xc_zval_type_t; typedef int xc_op_type; typedef zend_uchar xc_opcode; #ifdef IS_UNICODE typedef UChar zstr_uchar; #endif typedef char zstr_char; #define MAX_DUP_STR_LEN 256 dnl }}} /* export: typedef struct _xc_processor_t xc_processor_t; :export {{{ */ struct _xc_processor_t { char *p; size_t size; HashTable strings; HashTable zvalptrs; zend_bool reference; /* enable if to deal with reference */ zend_bool have_references; const xc_entry_php_t *entry_php_src; const xc_entry_php_t *entry_php_dst; const xc_entry_data_php_t *php_src; const xc_entry_data_php_t *php_dst; xc_shm_t *shm; xc_allocator_t *allocator; const zend_class_entry *cache_ce; zend_ulong cache_class_index; const zend_op_array *active_op_array_src; zend_op_array *active_op_array_dst; const zend_class_entry *active_class_entry_src; zend_class_entry *active_class_entry_dst; zend_uint active_class_index; zend_uint active_op_array_index; const xc_op_array_info_t *active_op_array_infos_src; zend_bool readonly_protection; /* wheather it's present */ IFAUTOCHECK(xc_stack_t allocsizes;) }; /* }}} */ /* export: typedef struct _xc_dasm_t { const zend_op_array *active_op_array_src; } xc_dasm_t; :export {{{ */ /* }}} */ /* {{{ memsetptr */ IFAUTOCHECK(`dnl static void *memsetptr(void *mem, void *content, size_t n) { void **p = (void **) mem; void **end = (void **) ((char *) mem + n); while (p < end - sizeof(content)) { *p = content; p += sizeof(content); } if (p < end) { memset(p, -1, end - p); } return mem; } ') /* }}} */ #ifdef HAVE_XCACHE_DPRINT static void xc_dprint_indent(int indent) /* {{{ */ { int i; for (i = 0; i < indent; i ++) { fprintf(stderr, " "); } } /* }}} */ static void xc_dprint_str_len(const char *str, int len) /* {{{ */ { const unsigned char *p = (const unsigned char *) str; int i; for (i = 0; i < len; i ++) { if (p[i] < 32 || p[i] == 127) { fprintf(stderr, "\\%03o", (unsigned int) p[i]); } else { fputc(p[i], stderr); } } } /* }}} */ #endif /* {{{ xc_zstrlen_char */ static inline size_t xc_zstrlen_char(const_zstr s) { return strlen(ZSTR_S(s)); } /* }}} */ #ifdef IS_UNICODE /* {{{ xc_zstrlen_uchar */ static inline size_t xc_zstrlen_uchar(zstr s) { return u_strlen(ZSTR_U(s)); } /* }}} */ /* {{{ xc_zstrlen */ static inline size_t xc_zstrlen(int type, const_zstr s) { return type == IS_UNICODE ? xc_zstrlen_uchar(s) : xc_zstrlen_char(s); } /* }}} */ #else /* {{{ xc_zstrlen */ #define xc_zstrlen(dummy, s) xc_zstrlen_char(s) /* }}} */ #endif /* {{{ xc_calc_string_n */ REDEF(`PROCESSOR_TYPE', `calc') #undef C_RELAYLINE #define C_RELAYLINE IFAUTOCHECK(` #undef C_RELAYLINE #define C_RELAYLINE , __LINE__ ') static inline void xc_calc_string_n(xc_processor_t *processor, zend_uchar type, const_zstr str, long size IFAUTOCHECK(`, int relayline')) { pushdef(`__LINE__', `relayline') size_t realsize = UNISW(size, (type == IS_UNICODE) ? UBYTES(size) : size); long dummy = 1; if (realsize > MAX_DUP_STR_LEN) { ALLOC(, char, realsize) } else if (zend_u_hash_add(&processor->strings, type, str, (uint) size, (void *) &dummy, sizeof(dummy), NULL) == SUCCESS) { /* new string */ ALLOC(, char, realsize) } IFAUTOCHECK(` else { dnl fprintf(stderr, "dupstr %s\n", ZSTR_S(str)); } ') popdef(`__LINE__') } /* }}} */ /* {{{ xc_store_string_n */ REDEF(`PROCESSOR_TYPE', `store') static inline zstr xc_store_string_n(xc_processor_t *processor, zend_uchar type, const_zstr str, long size IFAUTOCHECK(`, int relayline')) { pushdef(`__LINE__', `relayline') size_t realsize = UNISW(size, (type == IS_UNICODE) ? UBYTES(size) : size); zstr ret, *pret; if (realsize > MAX_DUP_STR_LEN) { ALLOC(ZSTR_V(ret), char, realsize) memcpy(ZSTR_V(ret), ZSTR_V(str), realsize); return ret; } if (zend_u_hash_find(&processor->strings, type, str, (uint) size, (void **) &pret) == SUCCESS) { return *pret; } /* new string */ ALLOC(ZSTR_V(ret), char, realsize) memcpy(ZSTR_V(ret), ZSTR_V(str), realsize); zend_u_hash_add(&processor->strings, type, str, (uint) size, (void *) &ret, sizeof(zstr), NULL); return ret; popdef(`__LINE__') } /* }}} */ /* {{{ xc_get_class_num * return class_index + 1 */ static zend_ulong xc_get_class_num(xc_processor_t *processor, zend_class_entry *ce) { zend_uint i; const xc_entry_data_php_t *php = processor->php_src; zend_class_entry *ceptr; if (processor->cache_ce == ce) { return processor->cache_class_index + 1; } for (i = 0; i < php->classinfo_cnt; i ++) { ceptr = CestToCePtr(php->classinfos[i].cest); if (ZCEP_REFCOUNT_PTR(ceptr) == ZCEP_REFCOUNT_PTR(ce)) { processor->cache_ce = ceptr; processor->cache_class_index = i; return i + 1; } } assert(0); return (zend_ulong) -1; } define(`xc_get_class_num', `xc_get_class_numNOTDEFINED') /* }}} */ /* {{{ xc_get_class */ #ifdef ZEND_ENGINE_2 static zend_class_entry *xc_get_class(xc_processor_t *processor, zend_ulong class_num) { /* must be parent or currrent class */ assert(class_num <= processor->active_class_index + 1); return CestToCePtr(processor->php_dst->classinfos[class_num - 1].cest); } #endif define(`xc_get_class', `xc_get_classNOTDEFINED') /* }}} */ #ifdef ZEND_ENGINE_2 /* fix method on store */ static void xc_fix_method(xc_processor_t *processor, zend_op_array *dst TSRMLS_DC) /* {{{ */ { zend_function *zf = (zend_function *) dst; zend_class_entry *ce = processor->active_class_entry_dst; const zend_class_entry *srcce = processor->active_class_entry_src; /* Fixing up the default functions for objects here since * we need to compare with the newly allocated functions * * caveat: a sub-class method can have the same name as the * parent~s constructor and create problems. */ if (zf->common.fn_flags & ZEND_ACC_CTOR) { if (!ce->constructor) { ce->constructor = zf; } } else if (zf->common.fn_flags & ZEND_ACC_DTOR) { ce->destructor = zf; } else if (zf->common.fn_flags & ZEND_ACC_CLONE) { ce->clone = zf; } else { pushdef(`SET_IF_SAME_NAMEs', ` SET_IF_SAME_NAME(__get); SET_IF_SAME_NAME(__set); #ifdef ZEND_ENGINE_2_1 SET_IF_SAME_NAME(__unset); SET_IF_SAME_NAME(__isset); #endif SET_IF_SAME_NAME(__call); #ifdef ZEND_CALLSTATIC_FUNC_NAME SET_IF_SAME_NAME(__callstatic); #endif #if defined(ZEND_ENGINE_2_2) || PHP_MAJOR_VERSION >= 6 SET_IF_SAME_NAME(__tostring); #endif ') #ifdef IS_UNICODE if (UG(unicode)) { #define SET_IF_SAME_NAME(member) \ do { \ if (srcce->member && u_strcmp(ZSTR_U(zf->common.function_name), ZSTR_U(srcce->member->common.function_name)) == 0) { \ ce->member = zf; \ } \ } \ while(0) SET_IF_SAME_NAMEs() #undef SET_IF_SAME_NAME } else #endif do { #define SET_IF_SAME_NAME(member) \ do { \ if (srcce->member && strcmp(ZSTR_S(zf->common.function_name), ZSTR_S(srcce->member->common.function_name)) == 0) { \ ce->member = zf; \ } \ } \ while(0) SET_IF_SAME_NAMEs() #undef SET_IF_SAME_NAME } while (0); popdef(`SET_IF_SAME_NAMEs') } } /* }}} */ #endif /* {{{ call op_array ctor handler */ extern zend_bool xc_have_op_array_ctor; static void xc_zend_extension_op_array_ctor_handler(zend_extension *extension, zend_op_array *op_array TSRMLS_DC) { if (extension->op_array_ctor) { extension->op_array_ctor(op_array); } } /* }}} */ /* {{{ field name checker */ IFAUTOCHECK(`dnl static int xc_check_names(const char *file, int line, const char *functionName, const char **assert_names, size_t assert_names_count, HashTable *done_names) { int errors = 0; if (assert_names_count) { size_t i; Bucket *b; for (i = 0; i < assert_names_count; ++i) { if (!zend_u_hash_exists(done_names, IS_STRING, assert_names[i], (uint) strlen(assert_names[i]) + 1)) { fprintf(stderr , "Error: missing field at %s `#'%d %s`' : %s\n" , file, line, functionName , assert_names[i] ); ++errors; } } for (b = done_names->pListHead; b != NULL; b = b->pListNext) { int known = 0; for (i = 0; i < assert_names_count; ++i) { if (strcmp(assert_names[i], BUCKET_KEY_S(b)) == 0) { known = 1; break; } } if (!known) { fprintf(stderr , "Error: unknown field at %s `#'%d %s`' : %s\n" , file, line, functionName , BUCKET_KEY_S(b) ); ++errors; } } } return errors; } ') /* }}} */ dnl ================ export API define(`DEFINE_STORE_API', ` /* export: $1 *xc_processor_store_$1(xc_shm_t *shm, xc_allocator_t *allocator, $1 *src TSRMLS_DC); :export {{{ */ $1 *xc_processor_store_$1(xc_shm_t *shm, xc_allocator_t *allocator, $1 *src TSRMLS_DC) { $1 *dst; xc_processor_t processor; memset(&processor, 0, sizeof(processor)); processor.reference = 1; processor.shm = shm; processor.allocator = allocator; IFAUTOCHECK(`xc_stack_init(&processor.allocsizes);') /* calc size */ { zend_hash_init(&processor.strings, 0, NULL, NULL, 0); if (processor.reference) { zend_hash_init(&processor.zvalptrs, 0, NULL, NULL, 0); } processor.size = 0; /* allocate */ processor.size = ALIGN(processor.size + sizeof(src[0])); xc_calc_$1(&processor, src TSRMLS_CC); if (processor.reference) { zend_hash_destroy(&processor.zvalptrs); } zend_hash_destroy(&processor.strings); } ifelse( `$1', `xc_entry_data_php_t', `SRC(`size')', `', `', SRC(`entry.size')) = processor.size; ifelse( `$1', `xc_entry_var_t', `SRC(`have_references') = processor.have_references;', `$1', `xc_entry_data_php_t', `SRC(`have_references') = processor.have_references;' ) IFAUTOCHECK(`xc_stack_reverse(&processor.allocsizes);') /* store {{{ */ { IFAUTOCHECK(`char *oldp;') zend_hash_init(&processor.strings, 0, NULL, NULL, 0); if (processor.reference) { zend_hash_init(&processor.zvalptrs, 0, NULL, NULL, 0); } /* allocator :) */ processor.p = (char *) processor.allocator->vtable->malloc(processor.allocator, processor.size); if (processor.p == NULL) { dst = NULL; goto err_alloc; } IFAUTOCHECK(`oldp = processor.p;') assert(processor.p == (char *) ALIGN(processor.p)); /* allocate */ dst = ($1 *) processor.p; processor.p = (char *) ALIGN(processor.p + sizeof(dst[0])); xc_store_$1(&processor, dst, src TSRMLS_CC); IFAUTOCHECK(` { size_t unexpected = processor.p - oldp; size_t expected = processor.size; if (unexpected != processor.size) { fprintf(stderr, "unexpected:%lu - expected:%lu = %ld != 0\n", (unsigned long) unexpected, (unsigned long) expected, (long) unexpected - expected); abort(); } }') err_alloc: if (processor.reference) { zend_hash_destroy(&processor.zvalptrs); } zend_hash_destroy(&processor.strings); } /* }}} */ IFAUTOCHECK(`xc_stack_destroy(&processor.allocsizes);') return dst; } /* }}} */ ') DEFINE_STORE_API(`xc_entry_var_t') DEFINE_STORE_API(`xc_entry_php_t') DEFINE_STORE_API(`xc_entry_data_php_t') /* export: xc_entry_php_t *xc_processor_restore_xc_entry_php_t(xc_entry_php_t *dst, const xc_entry_php_t *src TSRMLS_DC); :export {{{ */ xc_entry_php_t *xc_processor_restore_xc_entry_php_t(xc_entry_php_t *dst, const xc_entry_php_t *src TSRMLS_DC) { xc_processor_t processor; memset(&processor, 0, sizeof(processor)); xc_restore_xc_entry_php_t(&processor, dst, src TSRMLS_CC); return dst; } /* }}} */ /* export: xc_entry_data_php_t *xc_processor_restore_xc_entry_data_php_t(const xc_entry_php_t *entry_php, xc_entry_data_php_t *dst, const xc_entry_data_php_t *src, zend_bool readonly_protection TSRMLS_DC); :export {{{ */ xc_entry_data_php_t *xc_processor_restore_xc_entry_data_php_t(const xc_entry_php_t *entry_php, xc_entry_data_php_t *dst, const xc_entry_data_php_t *src, zend_bool readonly_protection TSRMLS_DC) { xc_processor_t processor; memset(&processor, 0, sizeof(processor)); processor.readonly_protection = readonly_protection; /* this function is used for php data only */ if (SRC(`have_references')) { processor.reference = 1; } processor.entry_php_src = entry_php; if (processor.reference) { zend_hash_init(&processor.zvalptrs, 0, NULL, NULL, 0); } xc_restore_xc_entry_data_php_t(&processor, dst, src TSRMLS_CC); if (processor.reference) { zend_hash_destroy(&processor.zvalptrs); } return dst; } /* }}} */ /* export: xc_entry_var_t *xc_processor_restore_xc_entry_var_t(xc_entry_var_t *dst, const xc_entry_var_t *src TSRMLS_DC); :export {{{ */ xc_entry_var_t *xc_processor_restore_xc_entry_var_t(xc_entry_var_t *dst, const xc_entry_var_t *src TSRMLS_DC) { xc_processor_t processor; memset(&processor, 0, sizeof(processor)); xc_restore_xc_entry_var_t(&processor, dst, src TSRMLS_CC); return dst; } /* }}} */ /* export: zval *xc_processor_restore_zval(zval *dst, const zval *src, zend_bool have_references TSRMLS_DC); :export {{{ */ zval *xc_processor_restore_zval(zval *dst, const zval *src, zend_bool have_references TSRMLS_DC) { xc_processor_t processor; memset(&processor, 0, sizeof(processor)); processor.reference = have_references; if (processor.reference) { zend_hash_init(&processor.zvalptrs, 0, NULL, NULL, 0); dnl fprintf(stderr, "mark[%p] = %p\n", src, dst); zend_hash_add(&processor.zvalptrs, (char *)src, sizeof(src), (void*)&dst, sizeof(dst), NULL); } xc_restore_zval(&processor, dst, src TSRMLS_CC); if (processor.reference) { zend_hash_destroy(&processor.zvalptrs); } return dst; } /* }}} */ /* export: void xc_dprint(xc_entry_php_t *src, int indent TSRMLS_DC); :export {{{ */ #ifdef HAVE_XCACHE_DPRINT void xc_dprint(xc_entry_php_t *src, int indent TSRMLS_DC) { IFDPRINT(`INDENT()`'fprintf(stderr, "xc_entry_php_t:src");') xc_dprint_xc_entry_php_t(src, indent TSRMLS_CC); } #endif /* }}} */ xcache-3.1.0/processor/main.m40000644000175000010010000002137612225452353014367 0ustar mOoNonedivert(-1) dnl ================ start ====================== dnl define(`XCACHE_ENABLE_TEST') dnl define(`DEBUG_SIZE') define(`USEMEMCPY') dnl ================ main dnl {{{ basic define(`REDEF', `ifdef(`$1', `undefine(`$1')') define(`$1', `$2')') define(`MAKE_MACRONAME', `translit(`$1', ` (): ', `_____')') define(`ONCE', `ifdef(MAKE_MACRONAME(`ONCE $1'), `', `define(MAKE_MACRONAME(`ONCE $1'))$1')') define(`m4_errprint', `ONCE(`errprint(`$1 ')')') ifdef(`len', ` define(`m4_len', defn(`len')) undefine(`len') ') define(`XCACHE_STRS', `($1), (sizeof($1))') define(`XCACHE_STRL', `($1), (sizeof($1) - 1)') define(`DST', `dst->$1') define(`SRC', `src->$1') dnl ============ define(`INDENT', `xc_dprint_indent(indent);') dnl }}} dnl {{{ ALLOC(1:dst, 2:type, 3:count=1, 4:clean=false, 5:realtype=$2) define(`ALLOC', ` pushdef(`COUNT', `ifelse(`$3', `', `1', `$3')') pushdef(`SIZE', `sizeof($2)ifelse(`$3', `', `', ` * $3')') pushdef(`REALTYPE', `ifelse(`$5', , `$2', `$5')') /* allocate */ IFCALC(` IFAUTOCHECK(` xc_stack_push(&processor->allocsizes, (void *) (long) (SIZE)); xc_stack_push(&processor->allocsizes, (void *) (long) (__LINE__)); ') processor->size = (size_t) ALIGN(processor->size); processor->size += SIZE; ') IFSTORE(` IFAUTOCHECK(`{ if (!xc_stack_count(&processor->allocsizes)) { fprintf(stderr, "mismatch `$@' at line %d\n", __LINE__); } else { unsigned long expect = (unsigned long) xc_stack_pop(&processor->allocsizes); unsigned long atline = (unsigned long) xc_stack_pop(&processor->allocsizes); unsigned long real = SIZE; if (expect != real) { fprintf(stderr, "mismatch `$@' at line %d(was %lu): real %lu - expect %lu = %lu\n", __LINE__, atline, real, expect, real - expect); } } }') ifdef(`DEBUG_SIZE', ` { void *oldp = processor->p; ') $1 = (REALTYPE *) (processor->p = (char *) ALIGN(processor->p)); ifelse(`$4', `', ` IFAUTOCHECK(`memsetptr($1, (void *) (unsigned long) __LINE__, SIZE);') ', ` memset($1, 0, SIZE); ') processor->p += SIZE; ifdef(`DEBUG_SIZE', ` xc_totalsize += (char *) processor->p - (char *) oldp; fprintf(stderr, "%d\t%d\t`'SIZE()\n", (char *) processor->p - (char *) oldp, xc_totalsize); } ') ') IFRESTORE(`ifelse(`$4', `', ` ifelse( REALTYPE*COUNT, `zval*1', `ALLOC_ZVAL($1);', REALTYPE*COUNT, `HashTable*1', `ALLOC_HASHTABLE($1);', `', `', `$1 = (REALTYPE *) emalloc(SIZE);') IFAUTOCHECK(`memsetptr($1, (void *) __LINE__, SIZE);') ', ` $1 = (REALTYPE *) ecalloc(COUNT, sizeof($2)); ') ') popdef(`REALTYPE') popdef(`COUNT') popdef(`SIZE') ') dnl CALLOC(1:dst, 2:type [, 3:count=1, 4:realtype=$2 ]) define(`CALLOC', `ALLOC(`$1', `$2', `$3', `1', `$4')') dnl }}} dnl {{{ PROC_CLASS_ENTRY_P(1:elm) define(`PROC_CLASS_ENTRY_P', `PROC_CLASS_ENTRY_P_EX(`DST(`$1')', `SRC(`$1')', `$1')`'DONE(`$1')') dnl PROC_CLASS_ENTRY_P_EX(1:dst, 2:src, 3:elm-name) define(`PROC_CLASS_ENTRY_P_EX', ` if ($2) { IFSTORE(`$1 = (zend_class_entry *) xc_get_class_num(processor, $2);') IFRESTORE(`$1 = xc_get_class(processor, (zend_ulong) $2);') #ifdef IS_UNICODE IFDASM(`add_assoc_unicodel_ex(dst, XCACHE_STRS("$3"), ZSTR_U($2->name), $2->name_length, 1);') #else IFDASM(`add_assoc_stringl_ex(dst, XCACHE_STRS("$3"), (char *) $2->name, $2->name_length, 1);') #endif } else { COPYNULL_EX(`$1', `$3') } ') dnl }}} dnl {{{ IFAUTOCHECKEX define(`IFAUTOCHECKEX', `ifdef(`XCACHE_ENABLE_TEST', `$1', `$2')') dnl }}} dnl {{{ IFAUTOCHECK define(`IFAUTOCHECK', `IFAUTOCHECKEX(` #ifndef NDEBUG $1 #endif ')') dnl }}} dnl {{{ DBG define(`DBG', `ifdef(`XCACHE_ENABLE_TEST', ` /* `$1' */ ')') dnl }}} dnl {{{ EXPORT define(`EXPORT', `define(`EXPORT_$1')') dnl }}} dnl {{{ FIXPOINTER define(`FIXPOINTER', `FIXPOINTER_EX(`$1', `DST(`$2')')') define(`FIXPOINTER_EX', `IFSTORE(` $2 = ($1 *) processor->shm->handlers->to_readonly(processor->shm, (void *)$2); ')') define(`UNFIXPOINTER', `UNFIXPOINTER_EX(`$1', `DST(`$2')')') define(`UNFIXPOINTER_EX', `IFSTORE(` $2 = ($1 *) processor->shm->handlers->to_readwrite(processor->shm, (void *)$2); ')') dnl }}} dnl {{{ COPY define(`COPY', `IFNOTMEMCPY(`IFCOPY(`DST(`$1') = SRC(`$1');')')DONE(`$1')') dnl }}} dnl {{{ COPY_N_EX define(`COPY_N_EX', ` ALLOC(`DST(`$3')', `$2', `SRC(`$1')') IFCOPY(` memcpy(DST(`$3'), SRC(`$3'), sizeof(DST(`$3[0]')) * SRC(`$1')); ') ') dnl }}} dnl {{{ COPY_N define(`COPY_N', `COPY_N_EX(`$1',`$2')DONE(`$1')') dnl }}} dnl {{{ COPYPOINTER define(`COPYPOINTER', `COPY(`$1')') dnl }}} dnl {{{ COPYARRAY_EX define(`COPYARRAY_EX', `IFNOTMEMCPY(`IFCOPY(`memcpy(DST(`$1'), SRC(`$1'), sizeof(DST(`$1')));')')') dnl }}} dnl {{{ COPYARRAY define(`COPYARRAY', `COPYARRAY_EX(`$1',`$2')DONE(`$1')') dnl }}} dnl {{{ SETNULL_EX define(`SETNULL_EX', `IFCOPY(`$1 = NULL;')') define(`SETNULL', `SETNULL_EX(`DST(`$1')')DONE(`$1')') dnl }}} dnl {{{ SETZERO_EX define(`SETZERO_EX', `IFCOPY(`$1 = 0;')') define(`SETZERO', `SETZERO_EX(`DST(`$1')')DONE(`$1')') dnl }}} dnl {{{ COPYNULL_EX(1:dst, 2:elm-name) define(`COPYNULL_EX', ` IFDASM(`add_assoc_null_ex(dst, XCACHE_STRS("$2"));') IFNOTMEMCPY(`IFCOPY(`$1 = NULL;')') assert(patsubst($1, dst, src) == NULL); ') dnl }}} dnl {{{ COPYNULL(1:elm) define(`COPYNULL', ` COPYNULL_EX(`DST(`$1')', `$1')DONE(`$1') ') dnl }}} dnl {{{ COPYZERO_EX(1:dst, 2:elm-name) define(`COPYZERO_EX', ` IFDASM(`add_assoc_long_ex(dst, XCACHE_STRS("$2"), 0);') IFNOTMEMCPY(`IFCOPY(`$1 = 0;')') assert(patsubst($1, dst, src) == 0); ') dnl }}} dnl {{{ COPYZERO(1:elm) define(`COPYZERO', ` COPYZERO_EX(`DST(`$1')', `$1')DONE(`$1') ') dnl }}} dnl {{{ LIST_DIFF(1:left-list, 2:right-list) define(`foreach', `pushdef(`$1')_foreach(`$1', `$2', `$3')popdef(`$1')') define(`_arg1', `$1') define(`_foreach', `ifelse(`$2', `()', , `define(`$1', _arg1$2)$3`'_foreach(`$1', (shift$2), `$3')')') define(`LIST_DIFF', `dnl foreach(`i', `($1)', `pushdef(`item_'defn(`i'))')dnl allocate variable for items in $1 foreach(`i', `($2)', `pushdef(`item_'defn(`i'))undefine(`item_'defn(`i'))')dnl allocate variable for items in $2, and undefine it foreach(`i', `($1)', `ifdef(`item_'defn(`i'), `defn(`i') ')')dnl see what is still defined foreach(`i', `($2)', `define(`item_'defn(`i'))popdef(`item_'defn(`i'))')dnl foreach(`i', `($1)', `popdef(`item_'defn(`i'))')dnl ') dnl }}} dnl {{{ DONE_* define(`DONE_SIZE', `IFAUTOCHECK(`dnl xc_autocheck_done_size += (int) $1`'; xc_autocheck_done_count ++; ')') define(`DONE', ` define(`ELEMENTS_DONE', defn(`ELEMENTS_DONE')`,"$1"') IFAUTOCHECK(`dnl if (zend_u_hash_exists(&xc_autocheck_done_names, IS_STRING, "$1", sizeof("$1"))) { fprintf(stderr , "duplicate field at %s `#'%d FUNC_NAME`' : %s\n" , __FILE__, __LINE__ , "$1" ); } else { zend_uchar b = 1; zend_hash_add(&xc_autocheck_done_names, "$1", sizeof("$1"), (void*)&b, sizeof(b), NULL); } ') DONE_SIZE(`sizeof(SRC(`$1'))') ') define(`DISABLECHECK', ` pushdef(`DONE_SIZE') pushdef(`DONE') $1 popdef(`DONE_SIZE') popdef(`DONE') ') dnl }}} dnl {{{ IF** define(`IFCALC', `ifelse(PROCESSOR_TYPE, `calc', `$1', `$2')') define(`IFSTORE', `ifelse(PROCESSOR_TYPE, `store', `$1', `$2')') define(`IFCALCSTORE', `IFSTORE(`$1', `IFCALC(`$1', `$2')')') define(`IFRESTORE', `ifelse(PROCESSOR_TYPE, `restore', `$1', `$2')') define(`IFCOPY', `IFSTORE(`$1', `IFRESTORE(`$1', `$2')')') define(`IFCALCCOPY', `IFCALC(`$1', `IFCOPY(`$1', `$2')')') define(`IFDPRINT', `ifelse(PROCESSOR_TYPE, `dprint', `$1', `$2')') define(`IFDASM', `ifelse(PROCESSOR_TYPE, `dasm', `$1', `$2')') dnl }}} EXPORT(`zend_op') EXPORT(`zend_op_array') EXPORT(`zend_function') EXPORT(`HashTable_zend_function') EXPORT(`zend_class_entry') EXPORT(`xc_classinfo_t') EXPORT(`xc_funcinfo_t') EXPORT(`xc_entry_var_t') EXPORT(`xc_entry_php_t') EXPORT(`xc_entry_data_php_t') EXPORT(`zval') include(srcdir`/processor/hashtable.m4') include(srcdir`/processor/string.m4') include(srcdir`/processor/struct.m4') include(srcdir`/processor/process.m4') include(srcdir`/processor/head.m4') define(`IFNOTMEMCPY', `ifdef(`USEMEMCPY', `', `$1')') REDEF(`PROCESSOR_TYPE', `calc') include(srcdir`/processor/processor.m4') pushdef(`xc_get_class_num', ``xc_get_class_num'($@)') REDEF(`PROCESSOR_TYPE', `store') include(srcdir`/processor/processor.m4') popdef(`xc_get_class_num') pushdef(`xc_get_class', ``xc_get_class'($@)') REDEF(`PROCESSOR_TYPE', `restore') include(srcdir`/processor/processor.m4') popdef(`xc_get_class') REDEF(`IFNOTMEMCPY', `$1') #ifdef HAVE_XCACHE_DPRINT REDEF(`PROCESSOR_TYPE', `dprint') include(srcdir`/processor/processor.m4') #endif /* HAVE_XCACHE_DPRINT */ #ifdef HAVE_XCACHE_DISASSEMBLER REDEF(`PROCESSOR_TYPE', `dasm') include(srcdir`/processor/processor.m4') #endif /* HAVE_XCACHE_DISASSEMBLER */ ifdef(`EXIT_PENDING', `m4exit(EXIT_PENDING)') xcache-3.1.0/processor/process.m40000644000175000010010000001114412220455234015105 0ustar mOoNonedefine(`PROCESS_SCALAR', `dnl {{{ (1:elm, 2:format=%d, 3:type=) IFNOTMEMCPY(`IFCOPY(`DST(`$1') = SRC(`$1');')') IFDPRINT(` INDENT() fprintf(stderr, "$3:$1:\t%ifelse(`$2',`',`d',`$2')\n", SRC(`$1')); ') IFDASM(` ifelse( `$3', `zend_bool', `add_assoc_bool_ex(dst, XCACHE_STRS("$1"), SRC(`$1') ? 1 : 0);' , `', `', `add_assoc_long_ex(dst, XCACHE_STRS("$1"), SRC(`$1'));' ) ') DONE(`$1') ') dnl }}} define(`PROCESS_xc_ztstring', `dnl {{{ (1:elm) pushdef(`REALPTRTYPE', `zend_class_entry') PROC_STRING(`$1') popdef(`REALPTRTYPE') ') dnl }}} define(`PROCESS_xc_zval_type_t', `dnl {{{ (1:elm) IFDPRINT(` INDENT() fprintf(stderr, ":$1:\t%d %s\n", SRC(`$1'), xc_get_data_type(SRC(`$1'))); DONE(`$1') ', `PROCESS_SCALAR(`$1')') ') dnl }}} define(`PROCESS_xc_op_type', `dnl {{{ (1:elm) IFDPRINT(` INDENT() fprintf(stderr, ":$1:\t%d %s\n", SRC(`$1'), xc_get_op_type(SRC(`$1'))); DONE(`$1') ', `PROCESS_SCALAR(`$1')') ') dnl }}} define(`PROCESS_xc_opcode', `dnl {{{ (1:elm) IFDPRINT(` INDENT() fprintf(stderr, ":$1:\t%u %s\n", SRC(`$1'), xc_get_opcode(SRC(`$1'))); DONE(`$1') ', `PROCESS_SCALAR(`$1')') ') dnl }}} define(`PROCESS', `dnl PROCESS(1:type, 2:elm) DBG(`$0($*)') assert(sizeof($1) == sizeof(SRC(`$2'))); ifelse( `$1', `zend_bool', `PROCESS_SCALAR(`$2', `u', `$1')' , `$1', `zend_uchar', `PROCESS_SCALAR(`$2', `u', `$1')' , `$1', `char', `PROCESS_SCALAR(`$2', `d', `$1')' , `$1', `int32_t', `PROCESS_SCALAR(`$2', `d', `$1')' , `$1', `unsigned char', `PROCESS_SCALAR(`$2', `u', `$1')' , `$1', `zend_uint', `PROCESS_SCALAR(`$2', `u', `$1')' , `$1', `uint', `PROCESS_SCALAR(`$2', `u', `$1')' , `$1', `unsigned int', `PROCESS_SCALAR(`$2', `u', `$1')' , `$1', `zend_ulong', `PROCESS_SCALAR(`$2', `lu', `$1')' , `$1', `ulong', `PROCESS_SCALAR(`$2', `lu', `$1')' , `$1', `size_t', `PROCESS_SCALAR(`$2', `lu', `$1')' , `$1', `long', `PROCESS_SCALAR(`$2', `ld', `$1')' , `$1', `time_t', `PROCESS_SCALAR(`$2', `ld', `$1')' , `$1', `zend_ushort', `PROCESS_SCALAR(`$2', `hu', `$1')' , `$1', `int', `PROCESS_SCALAR(`$2', `d', `$1')' , `$1', `double', `PROCESS_SCALAR(`$2', `f', `$1')' , `$1', `xc_entry_type_t', `PROCESS_SCALAR(`$2', `d', `$1')' , `$1', `xc_hash_value_t', `PROCESS_SCALAR(`$2', `lu', `$1')' , `$1', `last_brk_cont_t', `PROCESS_SCALAR(`$2', `d', `$1')' , `$1', `xc_ztstring', `PROCESS_xc_ztstring(`$2')' , `$1', `xc_zval_type_t', `PROCESS_xc_zval_type_t(`$2')' , `$1', `xc_op_type', `PROCESS_xc_op_type(`$2')' , `$1', `xc_opcode', `PROCESS_xc_opcode(`$2')' , `$1', `opcode_handler_t', `/* is copying enough? */COPY(`$2')' , `$1', `xc_md5sum_t', `COPY(`$2')' , `', `', `m4_errprint(`AUTOCHECK ERROR: Unknown type "$1"')define(`EXIT_PENDING', 1)' ) ') define(`PROCESS_ARRAY', `dnl {{{ (1:count, 2:type, 3:elm, [4:real_type]) if (SRC(`$3')) { int LOOPCOUNTER; IFDASM(` zval *arr; ALLOC_INIT_ZVAL(arr); array_init(arr); for (LOOPCOUNTER = 0; ifelse(`$1', `', `SRC(`$3[LOOPCOUNTER]')', `', `', `LOOPCOUNTER < SRC(`$1')'); ++LOOPCOUNTER) { pushdef(`dst', `arr') pushdef(`SRC', `ifelse(`$4', `', `', `', `', `($2)')' defn(`SRC') `[LOOPCOUNTER]') popdef(`add_assoc_bool_ex', `add_next_index_bool($1, $3)') popdef(`add_assoc_string_ex', `add_next_index_string($1, $3)') popdef(`add_assoc_long_ex', `add_next_index_long($1, $3)') popdef(`add_assoc_zval_ex', `add_next_index_zval($1, $3)') DISABLECHECK(` PROCESS(`$2', `$3') ') popdef(`add_assoc_zval_ex') popdef(`add_assoc_long_ex') popdef(`add_assoc_string_ex') popdef(`add_assoc_bool_ex') popdef(`SRC') popdef(`dst') } add_assoc_zval_ex(dst, XCACHE_STRS("$3"), arr); ', ` dnl find count with NULL ifelse(`$1', `', ` size_t count = 0; while (SRC(`$3[count]')) { ++count; } ++count; pushdef(`STRUCT_COUNT', `count') ', `', `', `pushdef(`STRUCT_COUNT', `SRC(`$1')')') ALLOC(`DST(`$3')', `$2', `STRUCT_COUNT', , `$4') popdef(`STRUCT_COUNT') for (LOOPCOUNTER = 0; ifelse(`$1', `', `SRC(`$3[LOOPCOUNTER]')', `', `', `LOOPCOUNTER < SRC(`$1')'); ++LOOPCOUNTER) { DISABLECHECK(` pushdef(`DST', defn(`DST') `[LOOPCOUNTER]') pushdef(`SRC', `ifelse(`$4', `', `', `', `', `($2)')' defn(`SRC') `[LOOPCOUNTER]') PROCESS(`$2', `$3') popdef(`SRC') popdef(`DST') ') } dnl the end marker ifelse(`$1', `', `IFCOPY(`DST(`$3[LOOPCOUNTER]') = NULL;')') ')dnl IFDASM DONE(`$3') } else { COPYNULL(`$3') } ') dnl }}} xcache-3.1.0/processor/processor.m40000644000175000010010000007703312225452353015463 0ustar mOoNonednl ================ /* {{{ Pre-declare */ DECL_STRUCT_P_FUNC(`zval') DECL_STRUCT_P_FUNC(`zval_ptr') DECL_STRUCT_P_FUNC(`zval_ptr_nullable') DECL_STRUCT_P_FUNC(`zend_op_array') DECL_STRUCT_P_FUNC(`zend_class_entry') #ifdef HAVE_XCACHE_CONSTANT DECL_STRUCT_P_FUNC(`zend_constant') #endif DECL_STRUCT_P_FUNC(`zend_function') DECL_STRUCT_P_FUNC(`xc_entry_var_t') DECL_STRUCT_P_FUNC(`xc_entry_php_t') #ifdef ZEND_ENGINE_2 DECL_STRUCT_P_FUNC(`zend_property_info') #endif /* }}} */ dnl ==================================================== #ifdef IS_CV DEF_STRUCT_P_FUNC(`zend_compiled_variable', , `dnl {{{ PROCESS(int, name_len) PROC_ZSTRING_L(, name, name_len) PROCESS(ulong, hash_value) ') dnl }}} #endif DEF_STRUCT_P_FUNC(`zend_uint', , `dnl {{{ IFCOPY(`dst[0] = src[0];') IFDPRINT(` INDENT() fprintf(stderr, "%u\n", src[0]); ') DONE_SIZE(sizeof(src[0])) ') dnl }}} #ifndef ZEND_ENGINE_2 DEF_STRUCT_P_FUNC(`int', , `dnl {{{ IFCOPY(`*dst = *src;') IFDPRINT(` INDENT() fprintf(stderr, "%d\n", src[0]); ') DONE_SIZE(sizeof(src[0])) ') dnl }}} #endif #ifdef ZEND_ENGINE_2 DEF_STRUCT_P_FUNC(`zend_try_catch_element', , `dnl {{{ PROCESS(zend_uint, try_op) PROCESS(zend_uint, catch_op) #ifdef ZEND_ENGINE_2_5 PROCESS(zend_uint, finally_op) PROCESS(zend_uint, finally_end) #endif ') dnl }}} #endif DEF_STRUCT_P_FUNC(`zend_brk_cont_element', , `dnl {{{ #ifdef ZEND_ENGINE_2_2 PROCESS(int, start) #endif PROCESS(int, cont) PROCESS(int, brk) PROCESS(int, parent) ') dnl }}} DEF_HASH_TABLE_FUNC(`HashTable_zval_ptr', `zval_ptr') DEF_HASH_TABLE_FUNC(`HashTable_zend_function', `zend_function') #ifdef ZEND_ENGINE_2 DEF_HASH_TABLE_FUNC(`HashTable_zend_property_info', `zend_property_info') #endif DEF_STRUCT_P_FUNC(`zval', , `dnl {{{ IFDASM(`do { zval_dtor(dst); *dst = *src; zval_copy_ctor(dst); Z_SET_REFCOUNT(*dst, 1); DONE(value) DONE(type) #ifdef ZEND_ENGINE_2_3 DONE(is_ref__gc) DONE(refcount__gc) #else DONE(is_ref) DONE(refcount) #endif } while(0); ', ` dnl IFDASM else /* Variable information */ dnl {{{ zvalue_value DISABLECHECK(` switch ((Z_TYPE_P(src) & IS_CONSTANT_TYPE_MASK)) { case IS_LONG: case IS_RESOURCE: case IS_BOOL: PROCESS(long, value.lval) break; case IS_DOUBLE: PROCESS(double, value.dval) break; case IS_NULL: IFDPRINT(`INDENT()`'fprintf(stderr, "\tNULL\n");') break; case IS_CONSTANT: #ifdef IS_UNICODE if (UG(unicode)) { goto proc_unicode; } #endif case IS_STRING: #ifdef FLAG_IS_BC case FLAG_IS_BC: #endif PROCESS(int, value.str.len) PROC_STRING_L(value.str.val, value.str.len) break; #ifdef IS_UNICODE case IS_UNICODE: proc_unicode: PROCESS(int32_t, value.uni.len) PROC_ZSTRING_L(1, value.uni.val, value.uni.len) break; #endif case IS_ARRAY: case IS_CONSTANT_ARRAY: STRUCT_P(HashTable, value.ht, HashTable_zval_ptr) break; case IS_OBJECT: IFNOTMEMCPY(`IFCOPY(`memcpy(dst, src, sizeof(src[0]));')') dnl STRUCT(value.obj) #ifndef ZEND_ENGINE_2 STRUCT_P(zend_class_entry, value.obj.ce) STRUCT_P(HashTable, value.obj.properties, HashTable_zval_ptr) #endif break; default: assert(0); } ') dnl }}} DONE(value) PROCESS(xc_zval_type_t, type) #ifdef ZEND_ENGINE_2_3 PROCESS(zend_uchar, is_ref__gc) #else PROCESS(zend_uchar, is_ref) #endif #ifdef ZEND_ENGINE_2_3 PROCESS(zend_uint, refcount__gc) #elif defined(ZEND_ENGINE_2) PROCESS(zend_uint, refcount) #else PROCESS(zend_ushort, refcount) #endif ')dnl IFDASM ') dnl }}} DEF_STRUCT_P_FUNC(`zval_ptr', , `dnl {{{ IFDASM(` pushdefFUNC_NAME(`zval') FUNC_NAME (dasm, dst, src[0] TSRMLS_CC); popdef(`FUNC_NAME') ', ` do { IFCALCCOPY(` if (processor->reference) { zval_ptr *ppzv; if (zend_hash_find(&processor->zvalptrs, (char *) &src[0], sizeof(src[0]), (void **) &ppzv) == SUCCESS) { IFCOPY(` dst[0] = *ppzv; /* *dst is updated */ dnl fprintf(stderr, "*dst is set to %p, PROCESSOR_TYPE is_shm %d\n", dst[0], xc_is_shm(dst[0])); ') IFCALCSTORE(`processor->have_references = 1;') IFSTORE(`assert(xc_is_shm(dst[0]));') IFRESTORE(`assert(!xc_is_shm(dst[0]));') break; } } ') ALLOC(dst[0], zval) IFCALCCOPY(` if (processor->reference) { IFCALC(` /* make dummy */ zval_ptr pzv = (zval_ptr)-1; ', ` zval_ptr pzv = dst[0]; FIXPOINTER_EX(zval, pzv) ') if (zend_hash_add(&processor->zvalptrs, (char *) &src[0], sizeof(src[0]), (void *) &pzv, sizeof(pzv), NULL) == SUCCESS) { /* first add, go on */ dnl fprintf(stderr, "mark[%p] = %p\n", src[0], pzv); } else { assert(0); } } ') IFCOPY(` dnl fprintf(stderr, "copy from %p to %p\n", src[0], dst[0]); ') IFDPRINT(`INDENT()`'fprintf(stderr, "[%p] ", (void *) src[0]);') STRUCT_P_EX(zval, dst[0], src[0], `[0]', `', ` ') FIXPOINTER_EX(zval, dst[0]) } while (0); ') DONE_SIZE(sizeof(zval_ptr)) ') dnl }}} DEF_STRUCT_P_FUNC(`zval_ptr_nullable', , `dnl {{{ if (src[0]) { pushdef(`DASM_STRUCT_DIRECT') STRUCT_P_EX(zval_ptr, dst, src, `', `', ` ') popdef(`DASM_STRUCT_DIRECT') } else { IFCOPY(`COPYNULL_EX(src[0], src)') } DONE_SIZE(sizeof(zval_ptr_nullable)) ') dnl }}} #ifdef ZEND_ENGINE_2 DEF_STRUCT_P_FUNC(`zend_arg_info', , `dnl {{{ PROCESS(zend_uint, name_len) PROC_ZSTRING_L(, name, name_len) PROCESS(zend_uint, class_name_len) PROC_ZSTRING_L(, class_name, class_name_len) #ifdef ZEND_ENGINE_2_4 PROCESS(zend_uchar, type_hint) #elif defined(ZEND_ENGINE_2_1) PROCESS(zend_bool, array_type_hint) #endif PROCESS(zend_bool, allow_null) PROCESS(zend_bool, pass_by_reference) #ifndef ZEND_ENGINE_2_4 PROCESS(zend_bool, return_reference) PROCESS(int, required_num_args) #endif ') dnl }}} #endif #ifdef HAVE_XCACHE_CONSTANT DEF_STRUCT_P_FUNC(`zend_constant', , `dnl {{{ STRUCT(zval, value) PROCESS(int, flags) PROCESS(uint, name_len) pushdef(`estrndup', `zend_strndup') PROC_ZSTRING_N(, name, name_len) popdef(`estrndup') PROCESS(int, module_number) ') dnl }}} #endif DEF_STRUCT_P_FUNC(`zend_function', , `dnl {{{ DISABLECHECK(` switch (SRC(`type')) { case ZEND_INTERNAL_FUNCTION: case ZEND_OVERLOADED_FUNCTION: IFNOTMEMCPY(`IFCOPY(`memcpy(dst, src, sizeof(src[0]));')') break; case ZEND_USER_FUNCTION: case ZEND_EVAL_CODE: DONE(type) STRUCT(zend_op_array, op_array) break; default: assert(0); } ') DONE_SIZE(sizeof(src[0])) ') dnl }}} #ifdef ZEND_ENGINE_2 DEF_STRUCT_P_FUNC(`zend_property_info', , `dnl {{{ PROCESS(zend_uint, flags) PROCESS(int, name_length) PROC_ZSTRING_L(, name, name_length) PROCESS(ulong, h) #ifdef ZEND_ENGINE_2_4 PROCESS(int, offset) #endif #ifdef ZEND_ENGINE_2_1 PROCESS(int, doc_comment_len) PROC_ZSTRING_L(, doc_comment, doc_comment_len) #endif dnl isnt in php6 yet #if defined(ZEND_ENGINE_2_2) PROC_CLASS_ENTRY_P(ce) #endif ') dnl }}} #endif #ifdef ZEND_ENGINE_2_4 DEF_STRUCT_P_FUNC(`zend_trait_method_reference', , `dnl {{{ PROCESS(unsigned int, mname_len) PROC_STRING_L(method_name, mname_len) COPYNULL(ce) PROCESS(unsigned int, cname_len) PROC_STRING_L(class_name, cname_len) ') dnl }}} DEF_STRUCT_P_FUNC(`zend_trait_alias', , `dnl {{{ STRUCT_P(zend_trait_method_reference, trait_method) PROCESS(unsigned int, alias_len) PROC_STRING_L(alias, alias_len) PROCESS(zend_uint, modifiers) #ifndef ZEND_ENGINE_2_5 COPYNULL(function) #endif ') dnl }}} DEF_STRUCT_P_FUNC(`zend_trait_precedence', , `dnl {{{ STRUCT_P(zend_trait_method_reference, trait_method) PROCESS_ARRAY(, xc_ztstring, exclude_from_classes, zend_class_entry*) #ifndef ZEND_ENGINE_2_5 COPYNULL(function) #endif ') dnl }}} DEF_STRUCT_P_FUNC(`zend_trait_alias_ptr', , `dnl {{{ IFDASM(` pushdefFUNC_NAME(`zend_trait_alias') FUNC_NAME (dasm, dst, src[0] TSRMLS_CC); popdef(`FUNC_NAME') ', ` ALLOC(dst[0], zend_trait_alias) STRUCT_P_EX(zend_trait_alias, dst[0], src[0], `[0]', `', ` ') FIXPOINTER_EX(zend_trait_alias, dst[0]) ') DONE_SIZE(sizeof(zend_trait_alias)) ') dnl }}} DEF_STRUCT_P_FUNC(`zend_trait_precedence_ptr', , `dnl {{{ IFDASM(` pushdefFUNC_NAME(`zend_trait_precedence') FUNC_NAME (dasm, dst, src[0] TSRMLS_CC); popdef(`FUNC_NAME') ', ` ALLOC(dst[0], zend_trait_precedence) STRUCT_P_EX(zend_trait_precedence, dst[0], src[0], `[0]', `', ` ') FIXPOINTER_EX(zend_trait_precedence, dst[0]) ') DONE_SIZE(sizeof(zend_trait_precedence)) ') dnl }}} #endif DEF_STRUCT_P_FUNC(`zend_class_entry', , `dnl {{{ IFCALCCOPY(` processor->active_class_entry_src = src; IFCOPY(`processor->active_class_entry_dst = dst;') ') PROCESS(char, type) PROCESS(zend_uint, name_length) PROC_ZSTRING_L(, name, name_length) IFRESTORE(` #ifndef ZEND_ENGINE_2 /* just copy parent and resolve on install_class */ COPY(parent) #else PROC_CLASS_ENTRY_P(parent) #endif ', ` PROC_CLASS_ENTRY_P(parent) ') #ifdef ZEND_ENGINE_2 PROCESS(int, refcount) #else STRUCT_P(int, refcount) #endif #ifndef ZEND_ENGINE_2_4 PROCESS(zend_bool, constants_updated) #endif #ifdef ZEND_ENGINE_2 PROCESS(zend_uint, ce_flags) #endif #ifdef ZEND_ENGINE_2 STRUCT(HashTable, properties_info, HashTable_zend_property_info) #endif #ifdef ZEND_ENGINE_2_4 STRUCT_ARRAY(int, default_properties_count, zval_ptr_nullable, default_properties_table) PROCESS(int, default_properties_count) STRUCT_ARRAY(int, default_static_members_count, zval_ptr_nullable, default_static_members_table) PROCESS(int, default_static_members_count) IFCOPY(`DST(`static_members_table') = DST(`default_static_members_table');') DONE(static_members_table) #else IFCOPY(`DST(`builtin_functions') = SRC(`builtin_functions');') DONE(builtin_functions) STRUCT(HashTable, default_properties, HashTable_zval_ptr) # ifdef ZEND_ENGINE_2_1 STRUCT(HashTable, default_static_members, HashTable_zval_ptr) IFCOPY(`DST(`static_members') = &DST(`default_static_members');') DONE(static_members) # elif defined(ZEND_ENGINE_2) STRUCT_P(HashTable, static_members, HashTable_zval_ptr) # endif #endif /* ZEND_ENGINE_2_4 */ #ifdef ZEND_ENGINE_2 STRUCT(HashTable, constants_table, HashTable_zval_ptr) #ifdef ZEND_ENGINE_2_2 dnl runtime binding: ADD_INTERFACE will deal with it COPYNULL(`interfaces') COPYZERO(`num_interfaces') # ifdef ZEND_ENGINE_2_4 dnl runtime binding: ADD_TRAIT will deal with it COPYNULL(traits) COPYZERO(num_traits) STRUCT_ARRAY(, , zend_trait_alias_ptr, trait_aliases) STRUCT_ARRAY(, , zend_trait_precedence_ptr, trait_precedences) # endif #else IFRESTORE(` if (SRC(`num_interfaces')) { CALLOC(DST(`interfaces'), zend_class_entry*, SRC(`num_interfaces')) DONE(`interfaces') } else { COPYNULL(`interfaces') } ', ` DONE(`interfaces') ') PROCESS(zend_uint, num_interfaces) #endif # ifdef ZEND_ENGINE_2_4 DISABLECHECK(` IFRESTORE(`DST(`info.user.filename') = processor->entry_php_src->filepath;', `PROC_STRING(info.user.filename)') PROCESS(zend_uint, info.user.line_start) PROCESS(zend_uint, info.user.line_end) PROCESS(zend_uint, info.user.doc_comment_len) PROC_ZSTRING_L(, info.user.doc_comment, info.user.doc_comment_len) ') DONE(info) # else IFRESTORE(`DST(`filename') = processor->entry_php_src->filepath;DONE(filename)', `PROC_STRING(filename)') PROCESS(zend_uint, line_start) PROCESS(zend_uint, line_end) PROCESS(zend_uint, doc_comment_len) PROC_ZSTRING_L(, doc_comment, doc_comment_len) # endif /* # NOT DONE */ # ifdef ZEND_ENGINE_2_1 COPY(serialize_func) COPY(unserialize_func) # endif COPY(iterator_funcs) COPY(create_object) COPY(get_iterator) COPY(interface_gets_implemented) # ifdef ZEND_ENGINE_2_3 COPY(get_static_method) # endif # ifdef ZEND_ENGINE_2_1 COPY(serialize) COPY(unserialize) # endif /* deal with it inside xc_fix_method */ SETNULL(constructor) COPY(destructor) COPY(clone) COPY(__get) COPY(__set) /* should be >5.1 */ # ifdef ZEND_ENGINE_2_1 COPY(__unset) COPY(__isset) # if defined(ZEND_ENGINE_2_2) || PHP_MAJOR_VERSION >= 6 COPY(__tostring) # endif # endif COPY(__call) # ifdef ZEND_CALLSTATIC_FUNC_NAME COPY(__callstatic) # endif # ifndef ZEND_ENGINE_2_4 /* # NOT DONE */ COPY(module) # endif #else /* ZEND_ENGINE_2 */ COPY(handle_function_call) COPY(handle_property_get) COPY(handle_property_set) #endif dnl must do after SETNULL(constructor) and dst->parent STRUCT(HashTable, function_table, HashTable_zend_function) IFRESTORE(`DST(`function_table.pDestructor') = ZEND_FUNCTION_DTOR;') IFCALCCOPY(` processor->active_class_entry_src = NULL; IFCOPY(`processor->active_class_entry_dst = NULL;') ') ') dnl }}} #ifdef ZEND_ENGINE_2_4 undefine(`UNION_znode_op') define(`UNION_znode_op', `dnl {{{ #ifndef NDEBUG switch ((SRC(`$1_type') ifelse($1, `result', & ~EXT_TYPE_UNUSED))) { case IS_CONST: case IS_VAR: case IS_CV: case IS_TMP_VAR: case IS_UNUSED: break; default: assert(0); } #endif dnl dirty dispatch DISABLECHECK(` switch ((SRC(`$1_type') ifelse($1, `result', & ~EXT_TYPE_UNUSED))) { case IS_CONST: ifelse($1, `result', ` PROCESS(zend_uint, $1.constant) ', ` IFDASM(`{ zval *zv; ALLOC_INIT_ZVAL(zv); *zv = dasm->active_op_array_src->literals[SRC(`$1.constant')].constant; zval_copy_ctor(zv); add_assoc_zval_ex(dst, XCACHE_STRS("$1.constant"), zv); } ', ` IFCOPY(` DST(`$1') = SRC(`$1'); ', ` PROCESS(zend_uint, $1.constant) ') ') ') break; IFCOPY(` IFNOTMEMCPY(` default: $1 = $2; ') ', ` case IS_VAR: case IS_TMP_VAR: case IS_CV: PROCESS(zend_uint, $1.var) break; case IS_UNUSED: IFDASM(`PROCESS(zend_uint, $1.var)') PROCESS(zend_uint, $1.opline_num) break; ') } ') DONE($1) ') dnl }}} #else DEF_STRUCT_P_FUNC(`znode', , `dnl {{{ PROCESS(xc_op_type, op_type) #ifdef IS_CV # define XCACHE_IS_CV IS_CV #else /* compatible with zend optimizer */ # define XCACHE_IS_CV 16 #endif assert(SRC(`op_type') == IS_CONST || SRC(`op_type') == IS_VAR || SRC(`op_type') == XCACHE_IS_CV || SRC(`op_type') == IS_TMP_VAR || SRC(`op_type') == IS_UNUSED); dnl dirty dispatch DISABLECHECK(` switch (SRC(`op_type')) { case IS_CONST: STRUCT(zval, u.constant) break; IFCOPY(` IFNOTMEMCPY(` default: memcpy(&DST(`u'), &SRC(`u'), sizeof(SRC(`u'))); ') ', ` case IS_VAR: case IS_TMP_VAR: case XCACHE_IS_CV: PROCESS(zend_uint, u.var) PROCESS(zend_uint, u.EA.type) break; case IS_UNUSED: IFDASM(`PROCESS(zend_uint, u.var)') PROCESS(zend_uint, u.opline_num) #ifndef ZEND_ENGINE_2 PROCESS(zend_uint, u.fetch_type) #endif PROCESS(zend_uint, u.EA.type) break; ') } ') DONE(u) #if 0 DONE(EA) #endif #undef XCACHE_IS_CV ') dnl }}} #endif DEF_STRUCT_P_FUNC(`zend_op', , `dnl {{{ PROCESS(xc_opcode, opcode) #ifdef ZEND_ENGINE_2_4 IFRESTORE(`', ` switch (SRC(`opcode')) { case ZEND_BIND_TRAITS: ((zend_op *) src)->op2_type = IS_UNUSED; break; } ') UNION_znode_op(result) UNION_znode_op(op1) UNION_znode_op(op2) #else STRUCT(znode, result) STRUCT(znode, op1) STRUCT(znode, op2) #endif PROCESS(ulong, extended_value) PROCESS(uint, lineno) #ifdef ZEND_ENGINE_2_4 PROCESS(zend_uchar, op1_type) PROCESS(zend_uchar, op2_type) PROCESS(zend_uchar, result_type) #endif IFCOPY(` assert(processor->active_op_array_src); assert(processor->active_op_array_dst); #ifdef ZEND_ENGINE_2_4 pushdef(`UNION_znode_op_literal', ` if (SRC(`$1_type') == IS_CONST) { DST(`$1').constant = SRC(`$1.literal') - processor->active_op_array_src->literals; DST(`$1').literal = &processor->active_op_array_dst->literals[DST(`$1').constant]; } ') UNION_znode_op_literal(op1) UNION_znode_op_literal(op2) #endif popdef(`UNION_znode_op_literal') #ifdef ZEND_ENGINE_2 switch (SRC(`opcode')) { # ifdef ZEND_GOTO case ZEND_GOTO: # endif case ZEND_JMP: # ifdef ZEND_FAST_CALL case ZEND_FAST_CALL: # endif assert(Z_OP(SRC(`op1')).jmp_addr >= processor->active_op_array_src->opcodes); assert(Z_OP(SRC(`op1')).jmp_addr - processor->active_op_array_src->opcodes < processor->active_op_array_src->last); Z_OP(DST(`op1')).jmp_addr = processor->active_op_array_dst->opcodes + (Z_OP(SRC(`op1')).jmp_addr - processor->active_op_array_src->opcodes); assert(Z_OP(DST(`op1')).jmp_addr >= processor->active_op_array_dst->opcodes); assert(Z_OP(DST(`op1')).jmp_addr - processor->active_op_array_dst->opcodes < processor->active_op_array_dst->last); FIXPOINTER_EX(zend_op, `Z_OP(DST(`op1')).jmp_addr') break; case ZEND_JMPZ: case ZEND_JMPNZ: case ZEND_JMPZ_EX: case ZEND_JMPNZ_EX: # ifdef ZEND_JMP_SET case ZEND_JMP_SET: # endif # ifdef ZEND_JMP_SET_VAR case ZEND_JMP_SET_VAR: # endif assert(Z_OP(SRC(`op2')).jmp_addr >= processor->active_op_array_src->opcodes); assert(Z_OP(SRC(`op2')).jmp_addr - processor->active_op_array_src->opcodes < processor->active_op_array_src->last); Z_OP(DST(`op2')).jmp_addr = processor->active_op_array_dst->opcodes + (Z_OP(SRC(`op2')).jmp_addr - processor->active_op_array_src->opcodes); assert(Z_OP(DST(`op2')).jmp_addr >= processor->active_op_array_dst->opcodes); assert(Z_OP(DST(`op2')).jmp_addr - processor->active_op_array_dst->opcodes < processor->active_op_array_dst->last); FIXPOINTER_EX(zend_op, `Z_OP(DST(`op2')).jmp_addr') break; default: break; } # endif ') #ifdef ZEND_ENGINE_2 PROCESS(opcode_handler_t, handler) #endif ') dnl }}} #ifdef ZEND_ENGINE_2_4 DEF_STRUCT_P_FUNC(`zend_literal', , `dnl {{{ STRUCT(zval, constant) PROCESS(zend_ulong, hash_value) PROCESS(zend_uint, cache_slot) ') dnl }}} #endif DEF_STRUCT_P_FUNC(`zend_op_array', , `dnl {{{ IFCOPY(` processor->active_op_array_dst = dst; processor->active_op_array_src = src; ') IFDASM(` dasm->active_op_array_src = src; ') { IFRESTORE(` const xc_op_array_info_t *op_array_info = &processor->active_op_array_infos_src[processor->active_op_array_index++]; dnl shadow copy must NOT meet: dnl readonly_protection=on dnl main op_array && have early binding #ifdef ZEND_COMPILE_DELAYED_BINDING zend_bool need_early_binding = 0; #else zend_bool need_early_binding = processor->php_src->have_early_binding; #endif zend_bool shallow_copy = !processor->readonly_protection && !(src == processor->php_src->op_array && need_early_binding); if (shallow_copy) { zend_bool gc_arg_info = 0; zend_bool gc_opcodes = 0; #ifdef ZEND_ENGINE_2_4 zend_bool gc_literals = 0; #endif /* really fast shallow copy */ memcpy(dst, src, sizeof(src[0])); DST(`refcount') = &XG(op_array_dummy_refcount_holder); XG(op_array_dummy_refcount_holder) = ((zend_uint) -1) / 2; #ifdef ZEND_ACC_ALIAS if ((processor->active_class_entry_src && (processor->active_class_entry_src->ce_flags & ZEND_ACC_TRAIT))) { PROC_ZSTRING(, function_name) } #endif /* deep */ STRUCT_P(HashTable, static_variables, HashTable_zval_ptr) #ifdef ZEND_ENGINE_2 STRUCT_ARRAY(zend_uint, num_args, zend_arg_info, arg_info) gc_arg_info = 1; #endif DST(`filename') = processor->entry_php_src->filepath; #ifdef ZEND_ENGINE_2_4 if (SRC(`literals')) { gc_opcodes = 1; if (op_array_info->literalinfo_cnt) { gc_literals = 1; } } #else if (op_array_info->oplineinfo_cnt) { gc_opcodes = 1; } #endif #ifdef ZEND_ENGINE_2_4 if (gc_literals) { dnl used when copying opcodes COPY_N_EX(last_literal, zend_literal, literals) } #endif if (gc_opcodes) { zend_op *opline, *end; COPY_N_EX(last, zend_op, opcodes) for (opline = DST(`opcodes'), end = opline + SRC(`last'); opline < end; ++opline) { #ifdef ZEND_ENGINE_2_4 pushdef(`UNION_znode_op_literal', ` if (opline->$1_type == IS_CONST) { opline->$1.literal = &DST(`literals[opline->$1.literal - SRC(`literals')]'); } ') UNION_znode_op_literal(op1) UNION_znode_op_literal(op2) popdef(`UNION_znode_op_literal') #endif switch (opline->opcode) { #ifdef ZEND_GOTO case ZEND_GOTO: #endif case ZEND_JMP: #ifdef ZEND_FAST_CALL case ZEND_FAST_CALL: #endif #ifdef ZEND_ENGINE_2 Z_OP(opline->op1).jmp_addr = &DST(`opcodes[Z_OP(opline->op1).jmp_addr') - SRC(`opcodes')]; #endif break; case ZEND_JMPZ: case ZEND_JMPNZ: case ZEND_JMPZ_EX: case ZEND_JMPNZ_EX: #ifdef ZEND_JMP_SET case ZEND_JMP_SET: #endif #ifdef ZEND_JMP_SET_VAR case ZEND_JMP_SET_VAR: #endif #ifdef ZEND_ENGINE_2 Z_OP(opline->op2).jmp_addr = &DST(`opcodes[Z_OP(opline->op2).jmp_addr') - SRC(`opcodes')]; #endif break; default: break; } } } if (gc_arg_info || gc_opcodes #ifdef ZEND_ENGINE_2_4 || gc_literals #endif ) { xc_gc_op_array_t gc_op_array; #ifdef ZEND_ENGINE_2 gc_op_array.num_args = gc_arg_info ? DST(`num_args') : 0; gc_op_array.arg_info = gc_arg_info ? DST(`arg_info') : NULL; #endif gc_op_array.opcodes = gc_opcodes ? DST(`opcodes') : NULL; #ifdef ZEND_ENGINE_2_4 gc_op_array.literals = gc_literals ? DST(`literals') : NULL; #endif xc_gc_add_op_array(&gc_op_array TSRMLS_CC); } IFAUTOCHECK(`xc_autocheck_skip = 1;') } else ') do { dnl RESTORE is done above! /* Common elements */ PROCESS(zend_uchar, type) PROC_ZSTRING(, function_name) #ifdef ZEND_ENGINE_2 PROCESS(zend_uint, fn_flags) STRUCT_ARRAY(zend_uint, num_args, zend_arg_info, arg_info) PROCESS(zend_uint, num_args) PROCESS(zend_uint, required_num_args) # ifndef ZEND_ENGINE_2_4 PROCESS(zend_bool, pass_rest_by_reference) # endif #else if (SRC(`arg_types')) { ALLOC(`DST(`arg_types')', zend_uchar, SRC(`arg_types[0]') + 1) IFCOPY(`memcpy(DST(`arg_types'), SRC(`arg_types'), sizeof(SRC(`arg_types[0]')) * (SRC(`arg_types[0]')+1));') IFDASM(`do { int i; zval *zv; ALLOC_INIT_ZVAL(zv); array_init(zv); for (i = 0; i < SRC(`arg_types[0]'); i ++) { add_next_index_long(zv, SRC(`arg_types[i + 1]')); } add_assoc_zval_ex(dst, ZEND_STRS("arg_types"), zv); } while (0);') DONE(arg_types) } else { COPYNULL(arg_types) } #endif #ifndef ZEND_ENGINE_2_4 PROCESS(unsigned char, return_reference) #endif /* END of common elements */ #ifdef IS_UNICODE dnl SETNULL(u_twin) #endif STRUCT_P(zend_uint, refcount) IFSTORE(` UNFIXPOINTER(zend_uint, refcount) DST(`refcount[0]') = 1; FIXPOINTER(zend_uint, refcount) ') #ifdef ZEND_ENGINE_2_4 dnl used when copying opcodes STRUCT_ARRAY(int, last_literal, zend_literal, literals) PROCESS(int, last_literal) #endif dnl uses literals STRUCT_ARRAY(zend_uint, last, zend_op, opcodes) PROCESS(zend_uint, last) #ifndef ZEND_ENGINE_2_4 IFCOPY(`DST(`size') = SRC(`last');DONE(size)', `PROCESS(zend_uint, size)') #endif #ifdef IS_CV STRUCT_ARRAY(int, last_var, zend_compiled_variable, vars) PROCESS(int, last_var) # ifndef ZEND_ENGINE_2_4 IFCOPY(`DST(`size_var') = SRC(`last_var');DONE(size_var)', `PROCESS(zend_uint, size_var)') # endif #else dnl zend_cv.m4 is illegal to be made public, don not ask me for it IFDASM(` sinclude(srcdir`/processor/zend_cv.m4') ') #endif PROCESS(zend_uint, T) #ifdef ZEND_ENGINE_2_5 PROCESS(zend_uint, nested_calls) PROCESS(zend_uint, used_stack) #endif STRUCT_ARRAY(last_brk_cont_t, last_brk_cont, zend_brk_cont_element, brk_cont_array) PROCESS(last_brk_cont_t, last_brk_cont) #ifndef ZEND_ENGINE_2_4 PROCESS(zend_uint, current_brk_cont) #endif #ifndef ZEND_ENGINE_2 PROCESS(zend_bool, uses_globals) #endif #ifdef ZEND_ENGINE_2 STRUCT_ARRAY(int, last_try_catch, zend_try_catch_element, try_catch_array) PROCESS(int, last_try_catch) #endif #ifdef ZEND_ENGINE_2_5 PROCESS(zend_bool, has_finally_block) #endif STRUCT_P(HashTable, static_variables, HashTable_zval_ptr) #ifndef ZEND_ENGINE_2_4 COPY(start_op) PROCESS(int, backpatch_count) #endif #ifdef ZEND_ENGINE_2_3 PROCESS(zend_uint, this_var) #endif #ifndef ZEND_ENGINE_2_4 PROCESS(zend_bool, done_pass_two) #endif /* 5.0 <= ver < 5.3 */ #if defined(ZEND_ENGINE_2) && !defined(ZEND_ENGINE_2_3) PROCESS(zend_bool, uses_this) #endif IFRESTORE(`DST(`filename') = processor->entry_php_src->filepath;DONE(filename)', `PROC_STRING(filename)') #ifdef IS_UNICODE IFRESTORE(` COPY(script_encoding) ', ` PROC_STRING(script_encoding) ') #endif #ifdef ZEND_ENGINE_2 PROCESS(zend_uint, line_start) PROCESS(zend_uint, line_end) PROCESS(int, doc_comment_len) PROC_ZSTRING_L(, doc_comment, doc_comment_len) #endif #ifdef ZEND_COMPILE_DELAYED_BINDING PROCESS(zend_uint, early_binding); #endif /* reserved */ DONE(reserved) #if defined(HARDENING_PATCH) && HARDENING_PATCH PROCESS(zend_bool, created_by_eval) #endif #ifdef ZEND_ENGINE_2_4 SETNULL(run_time_cache) PROCESS(int, last_cache_slot) #endif } while (0); IFRESTORE(`xc_fix_op_array_info(processor->entry_php_src, processor->php_src, dst, shallow_copy, op_array_info TSRMLS_CC);') #ifdef ZEND_ENGINE_2 dnl mark it as -1 on store, and lookup parent on restore IFSTORE(`DST(`prototype') = (processor->active_class_entry_src && SRC(`prototype')) ? (zend_function *) -1 : NULL;', ` IFRESTORE(`do { zend_function *parent; if (SRC(`prototype') != NULL && zend_u_hash_find(&(processor->active_class_entry_dst->parent->function_table), UG(unicode) ? IS_UNICODE : IS_STRING, SRC(`function_name'), xc_zstrlen(UG(unicode) ? IS_UNICODE : IS_STRING, SRC(`function_name')) + 1, (void **) &parent) == SUCCESS) { /* see do_inherit_method_check() */ if ((parent->common.fn_flags & ZEND_ACC_ABSTRACT)) { DST(`prototype') = parent; } else if (!(parent->common.fn_flags & ZEND_ACC_CTOR) || (parent->common.prototype && (parent->common.prototype->common.scope->ce_flags & ZEND_ACC_INTERFACE))) { /* ctors only have a prototype if it comes from an interface */ DST(`prototype') = parent->common.prototype ? parent->common.prototype : parent; } else { DST(`prototype') = NULL; } } else { DST(`prototype') = NULL; } } while (0); ') ') DONE(prototype) #endif #ifdef ZEND_ENGINE_2 PROC_CLASS_ENTRY_P(scope) IFCOPY(` if (SRC(`scope')) { xc_fix_method(processor, dst TSRMLS_CC); } ') #endif IFRESTORE(` if (xc_have_op_array_ctor) { zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) xc_zend_extension_op_array_ctor_handler, dst TSRMLS_CC); } ') } IFCOPY(` processor->active_op_array_dst = NULL; processor->active_op_array_src = NULL; ') IFDASM(` dasm->active_op_array_src = NULL; ') ') dnl }}} #ifdef HAVE_XCACHE_CONSTANT DEF_STRUCT_P_FUNC(`xc_constinfo_t', , `dnl {{{ PROCESS(zend_uint, key_size) #ifdef IS_UNICODE PROCESS(zend_uchar, type) #endif IFRESTORE(`COPY(key)', ` PROC_ZSTRING_N(type, key, key_size) ') PROCESS(ulong, h) STRUCT(zend_constant, constant) ') dnl }}} #endif IFRESTORE(`', ` DEF_STRUCT_P_FUNC(`xc_op_array_info_detail_t', , `dnl {{{ PROCESS(zend_uint, index) PROCESS(zend_uint, info) ') dnl }}} DEF_STRUCT_P_FUNC(`xc_op_array_info_t', , `dnl {{{ #ifdef ZEND_ENGINE_2_4 PROCESS(zend_uint, literalinfo_cnt) STRUCT_ARRAY(zend_uint, literalinfo_cnt, xc_op_array_info_detail_t, literalinfos) #else PROCESS(zend_uint, oplineinfo_cnt) STRUCT_ARRAY(zend_uint, oplineinfo_cnt, xc_op_array_info_detail_t, oplineinfos) #endif ') dnl }}} ') DEF_STRUCT_P_FUNC(`xc_funcinfo_t', , `dnl {{{ PROCESS(zend_uint, key_size) #ifdef IS_UNICODE PROCESS(zend_uchar, type) #endif IFRESTORE(`COPY(key)', ` PROC_ZSTRING_N(type, key, key_size) ') PROCESS(ulong, h) IFRESTORE(`COPY(op_array_info)', ` STRUCT(xc_op_array_info_t, op_array_info) ') IFRESTORE(` processor->active_op_array_infos_src = &SRC(`op_array_info'); processor->active_op_array_index = 0; ') STRUCT(zend_function, func) ') dnl }}} DEF_STRUCT_P_FUNC(`xc_classinfo_t', , `dnl {{{ PROCESS(zend_uint, key_size) #ifdef IS_UNICODE PROCESS(zend_uchar, type) #endif IFRESTORE(`COPY(key)', ` PROC_ZSTRING_N(type, key, key_size) ') PROCESS(ulong, h) PROCESS(zend_uint, methodinfo_cnt) IFRESTORE(`COPY(methodinfos)', ` STRUCT_ARRAY(zend_uint, methodinfo_cnt, xc_op_array_info_t, methodinfos) ') IFRESTORE(` processor->active_op_array_infos_src = SRC(`methodinfos'); processor->active_op_array_index = 0; ') #ifdef ZEND_ENGINE_2 STRUCT_P(zend_class_entry, cest) #else STRUCT(zend_class_entry, cest) #endif #ifndef ZEND_COMPILE_DELAYED_BINDING PROCESS(int, oplineno) #endif ') dnl }}} IFRESTORE(`', ` #ifdef ZEND_ENGINE_2_1 DEF_STRUCT_P_FUNC(`xc_autoglobal_t', , `dnl {{{ PROCESS(zend_uint, key_len) #ifdef IS_UNICODE PROCESS(zend_uchar, type) #endif IFRESTORE(`COPY(key)', ` PROC_ZSTRING_L(type, key, key_len) ') PROCESS(ulong, h) ') dnl }}} #endif ') IFRESTORE(`', ` #ifdef XCACHE_ERROR_CACHING DEF_STRUCT_P_FUNC(`xc_compilererror_t', , `dnl {{{ PROCESS(int, type) PROCESS(uint, lineno) PROCESS(int, error_len) PROC_STRING_L(error, error_len) ') dnl }}} #endif ') DEF_STRUCT_P_FUNC(`xc_entry_data_php_t', , `dnl {{{ IFCOPY(` processor->php_dst = dst; processor->php_src = src; ') /* skip */ DONE(next) PROCESS(xc_hash_value_t, hvalue) PROCESS(xc_md5sum_t, md5) PROCESS(zend_ulong, refcount) PROCESS(zend_ulong, hits) PROCESS(size_t, size) IFRESTORE(`COPY(op_array_info)', ` STRUCT(xc_op_array_info_t, op_array_info) ') IFRESTORE(` processor->active_op_array_infos_src = &DST(`op_array_info'); processor->active_op_array_index = 0; ') STRUCT_P(zend_op_array, op_array) #ifdef HAVE_XCACHE_CONSTANT PROCESS(zend_uint, constinfo_cnt) STRUCT_ARRAY(zend_uint, constinfo_cnt, xc_constinfo_t, constinfos) #endif PROCESS(zend_uint, funcinfo_cnt) STRUCT_ARRAY(zend_uint, funcinfo_cnt, xc_funcinfo_t, funcinfos) PROCESS(zend_uint, classinfo_cnt) STRUCT_ARRAY(zend_uint, classinfo_cnt, xc_classinfo_t, classinfos, , IFRESTORE(`processor->active_class_index')) #ifdef ZEND_ENGINE_2_1 PROCESS(zend_uint, autoglobal_cnt) IFRESTORE(` COPY(autoglobals) ', ` STRUCT_ARRAY(zend_uint, autoglobal_cnt, xc_autoglobal_t, autoglobals) ') #endif #ifdef XCACHE_ERROR_CACHING PROCESS(zend_uint, compilererror_cnt) IFRESTORE(` COPY(compilererrors) ', ` STRUCT_ARRAY(zend_uint, compilererror_cnt, xc_compilererror_t, compilererrors) ') #endif #ifndef ZEND_COMPILE_DELAYED_BINDING PROCESS(zend_bool, have_early_binding) #endif PROCESS(zend_bool, have_references) ') dnl }}} DEF_STRUCT_P_FUNC(`xc_entry_t', , `dnl {{{ /* skip */ DONE(next) PROCESS(size_t, size) PROCESS(time_t, ctime) PROCESS(time_t, atime) PROCESS(time_t, dtime) PROCESS(long, ttl) PROCESS(zend_ulong, hits) DONE(name) dnl handle in xc_entry_php_t and xc_entry_var_t ') dnl }}} DEF_STRUCT_P_FUNC(`xc_entry_php_t', , `dnl {{{ STRUCT(xc_entry_t, entry) DISABLECHECK(` PROCESS(int, entry.name.str.len) IFRESTORE(`COPY(entry.name.str.val)', ` PROC_STRING_L(entry.name.str.val, entry.name.str.len) ') ') IFCALCCOPY(`COPY(php)', `STRUCT_P(xc_entry_data_php_t, php)') IFSTORE(`DST(`refcount') = 0; DONE(refcount)', `PROCESS(long, refcount)') PROCESS(time_t, file_mtime) PROCESS(size_t, file_size) PROCESS(size_t, file_device) PROCESS(size_t, file_inode) PROCESS(size_t, filepath_len) IFRESTORE(`COPY(filepath)', `PROC_STRING_L(filepath, filepath_len)') PROCESS(size_t, dirpath_len) IFRESTORE(`COPY(dirpath)', `PROC_STRING_L(dirpath, dirpath_len)') #ifdef IS_UNICODE PROCESS(int, ufilepath_len) IFRESTORE(`COPY(ufilepath)', `PROC_USTRING_L(ufilepath, ufilepath_len)') PROCESS(int, udirpath_len) IFRESTORE(`COPY(udirpath)', `PROC_USTRING_L(udirpath, udirpath_len)') #endif ') dnl }}} DEF_STRUCT_P_FUNC(`xc_entry_var_t', , `dnl {{{ STRUCT(xc_entry_t, entry) #ifdef IS_UNICODE PROCESS(zend_uchar, name_type) #endif dnl {{{ entry.name DISABLECHECK(` #ifdef IS_UNICODE if (SRC(`name_type') == IS_UNICODE) { PROCESS(int32_t, entry.name.ustr.len) } else { PROCESS(int, entry.name.str.len) } #else PROCESS(int, entry.name.str.len) #endif IFRESTORE(`COPY(entry.name.str.val)', ` #ifdef IS_UNICODE PROC_ZSTRING_L(name_type, entry.name.uni.val, entry.name.uni.len) #else PROC_STRING_L(entry.name.str.val, entry.name.str.len) #endif ') ') dnl }}} IFDPRINT(`INDENT()`'fprintf(stderr, "zval:value");') STRUCT_P_EX(zval_ptr, DST(`value'), SRC(`value'), `value', `', `&') PROCESS(zend_bool, have_references) DONE(value) ') dnl }}} dnl ==================================================== xcache-3.1.0/processor/string.m40000644000175000010010000001032112206607315014734 0ustar mOoNone dnl {{{ PROC_STRING_N_EX(1:dst, 2:src, 3:size, 4:name, 5:type=char) define(`PROC_STRING_N_EX', ` pushdef(`STRTYPE', `ifelse(`$5',,`char',`$5')') pushdef(`PTRTYPE', ifelse( STRTYPE, `char', `char', STRTYPE, `zstr_char', `char', `', `', `UChar')) pushdef(`ISTYPE', ifelse(PTRTYPE,`UChar',IS_UNICODE,IS_STRING)) pushdef(`UNI_STRLEN', ifelse( STRTYPE, `zstr_uchar', `xc_zstrlen_uchar', STRTYPE, `zstr_char', `xc_zstrlen_char', `', `', `strlen')) pushdef(`SRCSTR', ifelse(STRTYPE,`char',`ZSTR($2)',STRTYPE,`UChar',`ZSTR($2)',`$2')) pushdef(`SRCPTR', ifelse( STRTYPE, `zstr_uchar', `ZSTR_U($2)', STRTYPE, `zstr_char', `ZSTR_S($2)', `', `', `$2')) pushdef(`DSTPTR', ifelse( STRTYPE, `zstr_uchar', `ZSTR_U($1)', STRTYPE, `zstr_char', `ZSTR_S($1)', `', `', `$1')) pushdef(`STRDUP', ifelse( PTRTYPE, `char', `estrndup', PTRTYPE, `UChar', `eustrndup')) if (SRCPTR == NULL) { IFNOTMEMCPY(`IFCOPY(` DSTPTR = NULL; ')') IFDASM(` add_assoc_null_ex(dst, XCACHE_STRS("$4")); ') } else { IFDPRINT(`INDENT() ifelse(STRTYPE, `zstr_uchar', ` #ifdef IS_UNICODE do { zval zv; zval reszv; int usecopy; INIT_ZVAL(zv); ZVAL_UNICODEL(&zv, ZSTR_U($2), $3 - 1, 1); zend_make_printable_zval(&zv, &reszv, &usecopy); fprintf(stderr, "string:%s:\t\"", "$1"); xc_dprint_str_len(Z_STRVAL(reszv), Z_STRLEN(reszv)); fprintf(stderr, "\" len=%lu\n", (unsigned long) $3 - 1); if (usecopy) { zval_dtor(&reszv); } zval_dtor(&zv); } while (0); #endif ', ` fprintf(stderr, "string:%s:\t\"", "$1"); xc_dprint_str_len(SRCPTR, $3 - 1); fprintf(stderr, "\" len=%lu\n", (unsigned long) $3 - 1); ') ') IFCALC(`xc_calc_string_n(processor, ISTYPE, SRCSTR, $3 C_RELAYLINE);') IFSTORE(`DSTPTR = ifdef(`REALPTRTYPE', `(REALPTRTYPE() *)') ifelse(PTRTYPE,`char',`ZSTR_S',`ZSTR_U')(xc_store_string_n(processor, ISTYPE, SRCSTR, $3 C_RELAYLINE));') IFRESTORE(` DSTPTR = ifdef(`REALPTRTYPE', `(REALPTRTYPE() *)') STRDUP() (SRCPTR, ($3) - 1); ') FIXPOINTER_EX(ifdef(`REALPTRTYPE', `REALPTRTYPE()', `PTRTYPE'), DSTPTR) IFDASM(` ifelse(STRTYPE,zstr_uchar, ` add_assoc_unicodel_ex(dst, XCACHE_STRS("$4"), ZSTR_U($2), $3-1, 1); ', ` dnl else ifelse(STRTYPE,zstr_char, ` add_assoc_stringl_ex(dst, XCACHE_STRS("$4"), (char *) ZSTR_S($2), $3-1, 1); ', ` add_assoc_stringl_ex(dst, XCACHE_STRS("$4"), (char *) $2, $3-1, 1); ') ') ') } popdef(`STRDUP') popdef(`DSTPTR') popdef(`SRCPTR') popdef(`SRCSTR') popdef(`UNI_STRLEN') popdef(`STRTYPE') popdef(`ISTYPE') ') dnl }}} dnl PROC_STRING_N(1:name, 2:size, 3:type) define(`PROC_STRING_N', `DBG(`$0($*)') DONE(`$1')`'PROC_STRING_N_EX(`DST(`$1')', `SRC(`$1')', `SRC(`$2')', `$1', `char')') define(`PROC_USTRING_N', `DBG(`$0($*)') DONE(`$1')`'PROC_STRING_N_EX(`DST(`$1')', `SRC(`$1')', `SRC(`$2')', `$1', `UChar')') define(`PROC_STRING_L', `DBG(`$0($*)') PROC_STRING_N(`$1', `$2 + 1')') define(`PROC_USTRING_L', `DBG(`$0($*)') PROC_USTRING_N(`$1', `$2 + 1')') define(`PROC_STRING', `DBG(`$0($*)') DONE(`$1')`'PROC_STRING_N_EX(`DST(`$1')', `SRC(`$1')', `strlen(SRC(`$1')) + 1', `$1', `char')') define(`PROC_USTRING', `DBG(`$0($*)') DONE(`$1')`'PROC_STRING_N_EX(`DST(`$1')', `SRC(`$1')', `strlen(SRC(`$1')) + 1', `$1', `UChar')') dnl {{{ PROC_ZSTRING_N(1:type, 2:name, 3:size, 4:size_type) define(`PROC_ZSTRING_N', ` DBG(`$0($*)') #ifdef IS_UNICODE pushdef(`NSIZE', ifelse( `$4', `strlen', `UNI_STRLEN (SRC(`$2')) + 1', `$4', `len', `SRC(`$3') + 1', `', `', `SRC(`$3')', )) DONE(`$2') ifelse(`$1', `1', `PROC_STRING_N_EX(`DST(`$2')', `SRC(`$2')', defn(`NSIZE'), `$2', `zstr_uchar') ', ` if (ifelse(`$1', `', `UG(unicode)', `SRC(`$1') == IS_UNICODE')) { PROC_STRING_N_EX(`DST(`$2')', `SRC(`$2')', defn(`NSIZE'), `$2', `zstr_uchar') } else { PROC_STRING_N_EX(`DST(`$2')', `SRC(`$2')', defn(`NSIZE'), `$2', `zstr_char') } ') #else DONE(`$2') PROC_STRING_N_EX(`DST(`$2')', `SRC(`$2')', NSIZE, `$2', `zstr_char') #endif popdef(`NSIZE') ') dnl }}} define(`PROC_ZSTRING_L', `DBG(`$0($*)') PROC_ZSTRING_N(`$1', `$2', `$3', `len')') define(`PROC_ZSTRING', `DBG(`$0($*)') PROC_ZSTRING_N(`$1', `$2', , `strlen')') xcache-3.1.0/processor/struct.m40000644000175000010010000001632712225452353014767 0ustar mOoNonedefine(`pushdefFUNC_NAME', ` pushdef(`FUNC_NAME', `xc_`'PROCESSOR_TYPE`'_`'ifelse(`$2', `', `$1', `$2')') ') dnl {{{ DECL_STRUCT_P_FUNC(1:type, 2:name, 3:comma=;) define(`DECL_STRUCT_P_FUNC', `translit( pushdefFUNC_NAME(`$1', `$2') define(`DEFINED_'ifelse(`$2', `', `$1', `$2'), `') ifdef(`EXPORT_'ifelse(`$2', `', `$1', `$2'), `void', `static void inline') FUNC_NAME`'( IFDPRINT( `const $1 * const src, int indent') IFCALC( `xc_processor_t *processor, const $1 * const src') IFSTORE( `xc_processor_t *processor, $1 *dst, const $1 * const src') IFRESTORE(`xc_processor_t *processor, $1 *dst, const $1 * const src') IFDASM( `xc_dasm_t *dasm, zval *dst, const $1 * const src') TSRMLS_DC )ifelse(`$3', `', `;') popdef(`FUNC_NAME')dnl , ` ', ` ')') dnl }}} dnl {{{ DEF_STRUCT_P_FUNC(1:type, 2:name, 3:body) define(`DEF_STRUCT_P_FUNC', ` pushdefFUNC_NAME(`$1', `$2') /* {`{'{ FUNC_NAME */ ifdef(`EXPORT_'ifelse(`$2', `', `$1', `$2'), ` /* export: DECL_STRUCT_P_FUNC(`$1', `$2') :export */ ') DECL_STRUCT_P_FUNC(`$1', `$2', 1) { pushdef(`ELEMENTS_DONE') IFAUTOCHECK(` /* {{{ init assert */ ifdef(`SIZEOF_$1', , `m4_errprint(`Warning: missing SIZEOF_$1, safe to ignore')') ifdef(`COUNTOF_$1', , `m4_errprint(`Warning: missing COUNTOF_$1, safe to ignore')') dnl SIZEOF_x COUNTOF_x can be both defined or both not ifdef(`SIZEOF_$1', ` ifdef(`COUNTOF_$1', , `m4_errprint(`AUTOCHECK WARN: missing COUNTOF_$1')') ', ` define(`SIZEOF_$1', 0) ') ifdef(`COUNTOF_$1', ` ifdef(`SIZEOF_$1', , `m4_errprint(`AUTOCHECK WARN: missing SIZEOF_$1')') ', ` define(`COUNTOF_$1', 0) ') int xc_autocheck_assert_size = SIZEOF_$1, assert_count = COUNTOF_$1; int xc_autocheck_done_size = 0, xc_autocheck_done_count = 0; ifdef(`ELEMENTSOF_$1', ` const char *xc_autocheck_assert_names[] = { ELEMENTSOF_$1 }; size_t xc_autocheck_assert_names_count = sizeof(xc_autocheck_assert_names) / sizeof(xc_autocheck_assert_names[0]); ', ` const char **xc_autocheck_assert_names = NULL; size_t xc_autocheck_assert_names_count = 0; ') zend_bool xc_autocheck_skip = 0; HashTable xc_autocheck_done_names; zend_hash_init(&xc_autocheck_done_names, 0, NULL, NULL, 0); /* }}} */ IFRESTORE(`assert(xc_is_shm(src));') IFCALCSTORE(`assert(!xc_is_shm(src));') do { ') ifdef(`SIZEOF_$1', , `m4_errprint(`AUTOCHECK WARN: $1: missing structinfo, dont panic')') ifdef(`USEMEMCPY', `IFCOPY(` memcpy(dst, src, sizeof($1)); do { ')') IFDPRINT(` fprintf(stderr, "%s", "{\n"); indent ++; { ') $3`' IFDPRINT(` } indent --; INDENT()fprintf(stderr, "}\n"); ') IFAUTOCHECK(` /* {{{ autocheck */ if (!xc_autocheck_skip) { int name_check_errors = xc_check_names(__FILE__, __LINE__, "FUNC_NAME", xc_autocheck_assert_names, xc_autocheck_assert_names_count, &xc_autocheck_done_names); if (xc_autocheck_done_count != assert_count) { fprintf(stderr , "count assertion failed at %s `#'%d FUNC_NAME`' : unexpected:%d - expecting:%d = %d != 0\n" , __FILE__, __LINE__ , xc_autocheck_done_count, assert_count, xc_autocheck_done_count - assert_count ); } if (xc_autocheck_done_size != xc_autocheck_assert_size) { fprintf(stderr , "size assertion failed at %s `#'%d FUNC_NAME`' : unexpected:%d - expecting:%d = %d != 0\n" , __FILE__, __LINE__ , xc_autocheck_done_size, xc_autocheck_assert_size, xc_autocheck_done_size - xc_autocheck_assert_size ); } if (name_check_errors || xc_autocheck_done_count != assert_count || xc_autocheck_done_size != xc_autocheck_assert_size) { assert(0); } } zend_hash_destroy(&xc_autocheck_done_names); /* }}} */ ') ifdef(`ELEMENTSOF_$1', ` pushdef(`ELEMENTS_UNDONE', LIST_DIFF(defn(`ELEMENTSOF_$1'), defn(`ELEMENTS_DONE'))) ifelse(defn(`ELEMENTS_UNDONE'), , `m4_errprint(`AUTOCHECK INFO: $1: processor looks good')', ` m4_errprint(`AUTOCHECK ERROR: ====' PROCESSOR_TYPE `$1 =================') m4_errprint(`AUTOCHECK expected:' defn(`ELEMENTSOF_$1')) m4_errprint(`AUTOCHECK missing :' defn(`ELEMENTS_UNDONE')) define(`EXIT_PENDING', 1) ') popdef(`ELEMENTS_UNDONE') ') ifdef(`USEMEMCPY', `IFCOPY(` } while (0); ')') IFAUTOCHECK(` } while (0); ') popdef(`ELEMENTS_DONE') } /* }`}'} */ popdef(`FUNC_NAME') ') dnl }}} dnl {{{ STRUCT_P_EX(1:type, 2:dst, 3:src, 4:elm-name, 5:name=type, 6:&) define(`STRUCT_P_EX', ` DBG(`$0($*)') pushdefFUNC_NAME(`$1', `$5') ifdef(`DEFINED_'ifelse(`$5', `', `$1', `$5'), `', `m4_errprint(`AUTOCHECK ERROR: Unknown struct "'ifelse(`$5', `', `$1', `$5')`"')define(`EXIT_PENDING', 1)') assert(sizeof($1) == sizeof(($6 $3)[0])); ifelse(`$6', `', `ALLOC(`$2', `$1')') ifdef(`DASM_STRUCT_DIRECT', `', ` IFDASM(`do { zval *zv; ALLOC_INIT_ZVAL(zv); array_init(zv); ') ') FUNC_NAME`'( IFDPRINT( ` $6 $3, indent') IFCALC( `processor, $6 $3') IFSTORE( `processor, $6 $2, $6 $3') IFRESTORE(`processor, $6 $2, $6 $3') IFDASM( `dasm, ifdef(`DASM_STRUCT_DIRECT', `dst', `zv'), $6 $3') TSRMLS_CC ); ifdef(`DASM_STRUCT_DIRECT', `', ` IFDASM(` add_assoc_zval_ex(dst, XCACHE_STRS("$4"), zv); } while (0); ') ') popdef(`FUNC_NAME') ifelse(`$6', , `FIXPOINTER_EX(`$1', `$2')') ') dnl }}} dnl {{{ STRUCT_P(1:type, 2:elm, 3:name=type) define(`STRUCT_P', ` DBG(`$0($*)') if (SRC(`$2')) { IFDPRINT(`INDENT()`'fprintf(stderr, "$1:$2 ");') STRUCT_P_EX(`$1', `DST(`$2')', `SRC(`$2')', `$2', `$3') } else { IFDPRINT(`INDENT()`'fprintf(stderr, "$1:$2:\tNULL\n");') COPYNULL_EX(`DST(`$2')', `$2') } DONE(`$2') ') dnl }}} dnl {{{ STRUCT(1:type, 2:elm, 3:name=type) define(`STRUCT', ` DBG(`$0($*)') assert(sizeof($1) == sizeof(SRC(`$2'))); IFDPRINT(`INDENT()`'fprintf(stderr, "$1:$2 ");') STRUCT_P_EX(`$1', `DST(`$2')', `SRC(`$2')', `$2', `$3', `&') DONE(`$2') ') dnl }}} dnl {{{ STRUCT_ARRAY(1:count_type, 2:count, 3:type, 4:elm, 5:name=type, 6:loopcounter) define(`STRUCT_ARRAY', ` if (SRC(`$4')) { ifelse( `$6', `', `ifelse(`$1', `', `size_t', `$1') i; pushdef(`LOOPCOUNTER', `i')', `', `', `pushdef(`LOOPCOUNTER', `$6')') pushdefFUNC_NAME(`$3', `$5') IFDASM(` zval *arr; ALLOC_INIT_ZVAL(arr); array_init(arr); for (LOOPCOUNTER = 0; ifelse(`$2', `', `SRC(`$4[LOOPCOUNTER]')', `', `', `LOOPCOUNTER < SRC(`$2')'); ++LOOPCOUNTER) { zval *zv; ALLOC_INIT_ZVAL(zv); array_init(zv); FUNC_NAME (dasm, zv, &(SRC(`$4[LOOPCOUNTER]')) TSRMLS_CC); add_next_index_zval(arr, zv); } add_assoc_zval_ex(dst, XCACHE_STRS("$4"), arr); ', ` dnl find count with NULL ifelse(`$2', `', ` size_t count = 0; while (SRC(`$4[count]')) { ++count; } ++count; pushdef(`ARRAY_ELEMENT_COUNT', `count') ', `', `', `pushdef(`ARRAY_ELEMENT_COUNT', `SRC(`$2')')') ALLOC(`DST(`$4')', `$3', `ARRAY_ELEMENT_COUNT') popdef(`ARRAY_ELEMENT_COUNT') for (LOOPCOUNTER = 0; ifelse(`$2', `', `SRC(`$4[LOOPCOUNTER]')', `', `', `LOOPCOUNTER < SRC(`$2')'); ++LOOPCOUNTER) { DISABLECHECK(` STRUCT(`$3', `$4[LOOPCOUNTER]', `$5') ') } dnl the end marker ifelse(`$2', `', `IFCOPY(`DST(`$4[LOOPCOUNTER]') = NULL;')') ')dnl IFDASM FIXPOINTER(`$3', `$4') DONE(`$4') popdef(`FUNC_NAME') popdef(`LOOPCOUNTER') } else { COPYNULL(`$4') } ') dnl }}} xcache-3.1.0/README0000644000175000010010000000055412157744737012053 0ustar mOoNoneXCache is a fast, stable PHP opcode cacher that has been tested and is now running on production servers under high load. It is tested (on linux) and supported on all of the latest version of PHP popular release branches. ThreadSafe/Windows is also perfectly supported. Please check http://xcache.lighttpd.net/ and https://groups.google.com/group/xcache for help xcache-3.1.0/run-xcachetest0000755000175000010010000000254012225452352014034 0ustar mOoNone#!/bin/sh getAbsolutePath() { which readlink >/dev/null 2>&1 && readlink -f "$@" || echo "$@" } # use symlink first if test -x ./php-cli ; then php_cli=`getAbsolutePath ./php-cli` elif test ! -z "$TEST_PHP_EXECUTABLE" && test -x "$TEST_PHP_EXECUTABLE"; then php_cli="$TEST_PHP_EXECUTABLE" else php_cli="`which php`" fi if test -x ./php-cgi ; then php_cgi=`getAbsolutePath ./php-cgi` else php_cgi="`which php-cgi`" fi TEST_PHP_EXECUTABLE="$php_cli" TEST_PHP_CGI_EXECUTABLE="$php_cgi" real_php_src=`getAbsolutePath ./php-src`; test -z "$TEST_PHP_SRCDIR" && TEST_PHP_SRCDIR=$real_php_src export TEST_PHP_EXECUTABLE export TEST_PHP_CGI_EXECUTABLE export TEST_PHP_SRCDIR echo "XCache test running with:" echo "TEST_PHP_CGI_EXECUTABLE: $TEST_PHP_CGI_EXECUTABLE" echo "TEST_PHP_EXECUTABLE: $TEST_PHP_EXECUTABLE" echo "TEST_PHP_SRCDIR: $TEST_PHP_SRCDIR" patch_run_tests_ext() { if test -z "$TEST_EXT" ; then sed "s#'ext',##g" else cat fi } patch_run_tests_report_leaks() { if test -z "$TEST_REPORT_MEMLEAKS" ; then sed "s#'report_memleaks=1',#'report_memleaks=0',#g" else cat fi } run_tests_src=$real_php_src/run-tests.php patch_run_tests_ext < "$run_tests_src" | patch_run_tests_report_leaks > run-tests.php exec "$php_cli" -d "open_basedir=" -d "safe_mode=0" -d "output_buffering=0" -d "memory_limit=-1" `getAbsolutePath ./run-tests.php` "$@" xcache-3.1.0/tests/0000755000175000010010000000000012220455231012304 5ustar mOoNonexcache-3.1.0/tests/include-skipif.inc0000644000175000010010000000016512157744740015726 0ustar mOoNone xcache-3.1.0/tests/skipif.inc0000644000175000010010000000013012220455231014256 0ustar mOoNone xcache-3.1.0/tests/sub-a.inc0000644000175000010010000000006712157744740014030 0ustar mOoNone --EXPECT-- 12 xcache-3.1.0/tests/xcache_deep_copy_opcodes_for_const.phpt0000644000175000010010000000025412220455231022254 0ustar mOoNone--TEST-- xcache requires deep copying opcodes for __FILE__ and __DIR__ --INI-- --FILE-- --EXPECTF-- %sxcache_deep_copy_opcodes_for_const%s xcache-3.1.0/tests/xcache_deep_copy_static_variables.phpt0000644000175000010010000000027312220455231022064 0ustar mOoNone--TEST-- xcache requires deep copying static variables in shallow copy mode --INI-- xcache.readonly_protection=0 --FILE-- --EXPECT-- 1 xcache-3.1.0/tests/xcache_include_absolute.phpt0000644000175000010010000000034612157744740020057 0ustar mOoNone--TEST-- include absolute path --SKIPIF-- --FILE-- --EXPECTF-- %stests %stests%ssub-a.inc %stests %stests%ssub-b.inc xcache-3.1.0/tests/xcache_include_relative_cwd.phpt0000644000175000010010000000036612157744740020713 0ustar mOoNone--TEST-- include relative to current working dir --SKIPIF-- --FILE-- --EXPECTF-- %stests %stests%ssub-a.inc %stests %stests%ssub-b.inc xcache-3.1.0/tests/xcache_include_relative_file.phpt0000644000175000010010000000033312157744740021047 0ustar mOoNone--TEST-- include relative to current file --SKIPIF-- --FILE-- --EXPECTF-- %stests %stests%ssub-a.inc %stests %stests%ssub-b.inc xcache-3.1.0/tests/xcache_is_autoglobal.phpt0000644000175000010010000000023412220455231017337 0ustar mOoNone--TEST-- xcache_is_autoglobal --SKIPIF-- --FILE-- --EXPECT-- bool(true) xcache-3.1.0/tests/xcache_shallow_copy_check_early_binding.phpt0000644000175000010010000000042712220455231023245 0ustar mOoNone--TEST-- xcache shallow copying precondition: early binding changes constant inside opcode for PHP5.2- --SKIPIF-- =")) { die("skip only needed for PHP 5.2 or less"); } ?> --FILE-- --EXPECT-- xcache-3.1.0/tests/xcache_var.phpt0000644000175000010010000000071612220455231015310 0ustar mOoNone--TEST-- xcache_set/get test --SKIPIF-- --FILE-- --EXPECT-- bool(false) bool(true) int(1) bool(true) int(11) int(11) int(6) int(6) bool(false) xcache-3.1.0/THANKS0000644000175000010010000000060112157744740012071 0ustar mOoNone Jan , host XCache website Alex , redist to FreeBSD darix , redist to openSUSE judas_iscariote , redist/test with openSUSE Finjon Kiang , Chinese Traditional translation There is also many ppl on IRC or forum helped me a lot testing XCache. Without them, XCache may not even be released. xcache-3.1.0/util/0000755000175000010010000000000012220455232012120 5ustar mOoNonexcache-3.1.0/util/README0000644000175000010010000000006112157744740013013 0ustar mOoNonegeneric utility stuffs unrelatived to ZendEngine xcache-3.1.0/util/xc_align.h0000644000175000010010000000067512157744740014103 0ustar mOoNone#ifndef __ALIGN_H #define __ALIGN_H #ifndef ALIGN typedef union align_union { double d; void *v; int (*func)(int); long l; } align_union; #if (defined (__GNUC__) && __GNUC__ >= 2) #define XCACHE_PLATFORM_ALIGNMENT (__alignof__ (align_union)) #else #define XCACHE_PLATFORM_ALIGNMENT (sizeof(align_union)) #endif #define ALIGN(n) ((((size_t)(n)-1) & ~(XCACHE_PLATFORM_ALIGNMENT-1)) + XCACHE_PLATFORM_ALIGNMENT) #endif #endif /* __ALIGN_H */ xcache-3.1.0/util/xc_foreachcoresig.h0000644000175000010010000000111512157744740015762 0ustar mOoNone/* all signals generate coredump by default is list here */ #ifdef SIGABRT FOREACH_SIG(SIGABRT); #endif #ifdef SIGBUS FOREACH_SIG(SIGBUS); #endif #ifdef SIGEMT FOREACH_SIG(SIGEMT); #endif #ifdef SIGFPE FOREACH_SIG(SIGFPE); #endif #ifdef SIGILL FOREACH_SIG(SIGILL); #endif #ifdef SIGIOT FOREACH_SIG(SIGIOT); #endif #ifdef SIGQUIT FOREACH_SIG(SIGQUIT); #endif #ifdef SIGSEGV FOREACH_SIG(SIGSEGV); #endif #ifdef SIGSYS FOREACH_SIG(SIGSYS); #endif #ifdef SIGTRAP FOREACH_SIG(SIGTRAP); #endif #ifdef SIGXCPU FOREACH_SIG(SIGXCPU); #endif #ifdef SIGXFSZ FOREACH_SIG(SIGXFSZ); #endif xcache-3.1.0/util/xc_stack.c0000644000175000010010000000217012220455232014063 0ustar mOoNone#include #include "xc_trace.h" #include "xc_stack.h" typedef xc_stack_t* S; void xc_stack_init_ex(S stack, int initsize) { stack->cnt = 0; stack->size = initsize; stack->data = malloc(sizeof(void *) * stack->size); } void xc_stack_destroy(S stack) { free(stack->data); } void xc_stack_push(S stack, void *item) { if (stack->cnt == stack->size) { stack->size <<= 1; stack->data = realloc(stack->data, sizeof(void *) * stack->size); } stack->data[stack->cnt++] = item; } void* xc_stack_pop(S stack) { assert(stack != NULL); assert(stack->size > 0); return stack->data[--stack->cnt]; } void* xc_stack_top(S stack) { assert(stack != NULL); assert(stack->cnt > 0); return stack->data[stack->cnt-1]; } void* xc_stack_get(S stack, int n) { assert(stack != NULL); assert(stack->cnt > 0); return stack->data[n]; } int xc_stack_count(S stack) { assert(stack != NULL); return stack->cnt; } void xc_stack_reverse(S stack) { int i, j; void *tmp; assert(stack != NULL); for (i = 0, j = stack->cnt - 1; i < j; i ++, j --) { tmp = stack->data[i]; stack->data[i] = stack->data[j]; stack->data[j] = tmp; } } xcache-3.1.0/util/xc_stack.h0000644000175000010010000000077312157744740014115 0ustar mOoNone#ifndef __XC_UTIL_STACK #define __XC_UTIL_STACK typedef struct { void **data; int cnt; int size; } xc_stack_t; #define S xc_stack_t* void xc_stack_init_ex(S stack, int initsize); #define xc_stack_init(stack) xc_stack_init_ex(stack, 8) void xc_stack_destroy(S stack); void xc_stack_push(S stack, void *item); void *xc_stack_pop(S stack); void *xc_stack_top(S stack); void *xc_stack_get(S stack, int n); int xc_stack_count(S stack); void xc_stack_reverse(S stack); #undef S #endif /* __XC_UTIL_STACK */ xcache-3.1.0/util/xc_trace.c0000644000175000010010000000115312220455232014054 0ustar mOoNone#ifdef TEST # define PHP_DIR_SEPARATOR '/' #else # include "php.h" #endif #include "xc_trace.h" #include #include #include const char *xc_trace_get_basename(const char *path) /* {{{ */ { const char *last_separator = strrchr(path, PHP_DIR_SEPARATOR); return last_separator ? last_separator + 1 : path; } /* }}} */ int xc_vtrace(const char *fmt, va_list args) /* {{{ */ { return vfprintf(stderr, fmt, args); } /* }}} */ int xc_trace(const char *fmt, ...) /* {{{ */ { va_list args; int ret; va_start(args, fmt); ret = xc_vtrace(fmt, args); va_end(args); return ret; } /* }}} */ xcache-3.1.0/util/xc_trace.h0000644000175000010010000000240112157744740014074 0ustar mOoNone#ifndef XC_TRACE_H_709AE2523EDACB72B54D9CB42DDB0FEE #define XC_TRACE_H_709AE2523EDACB72B54D9CB42DDB0FEE #if _MSC_VER > 1000 #pragma once #endif /* _MSC_VER > 1000 */ #ifdef ZEND_WIN32 # ifndef inline # ifdef ZEND_WIN32_FORCE_INLINE # define inline __forceinline # else # define inline # endif # endif #endif #ifdef XCACHE_DEBUG # define IFDEBUG(x) (x) int xc_vtrace(const char *fmt, va_list args); int xc_trace(const char *fmt, ...) ZEND_ATTRIBUTE_PTR_FORMAT(printf, 1, 2); # ifdef ZEND_WIN32 static inline int TRACE(const char *fmt, ...) { va_list args; int ret; va_start(args, fmt); ret = xc_vtrace(fmt, args); va_end(args); return ret; } # else const char *xc_trace_get_basename(const char *path); # define TRACE(fmt, ...) \ xc_trace("%s:%04d: " fmt "\r\n", xc_trace_get_basename(__FILE__), __LINE__, __VA_ARGS__) # endif /* ZEND_WIN32 */ # undef NDEBUG # undef inline # define inline #else /* XCACHE_DEBUG */ # ifdef ZEND_WIN32 static inline int TRACE_DUMMY(const char *fmt, ...) { return 0; } # define TRACE 1 ? 0 : TRACE_DUMMY # else # define TRACE(fmt, ...) do { } while (0) # endif /* ZEND_WIN32 */ # define IFDEBUG(x) do { } while (0) #endif /* XCACHE_DEBUG */ #include #endif /* XC_TRACE_H_709AE2523EDACB72B54D9CB42DDB0FEE */ xcache-3.1.0/util/xc_vector.h0000644000175000010010000000246612157744740014313 0ustar mOoNone#ifndef XC_VECTOR_H_0957AC4E1A44E838C7B8DBECFF9C4B3B #define XC_VECTOR_H_0957AC4E1A44E838C7B8DBECFF9C4B3B #if _MSC_VER > 1000 #pragma once #endif /* _MSC_VER > 1000 */ typedef struct { zend_uint size; zend_uint cnt; void *data; } xc_vector_t; #define xc_vector_init(type, vector) do { \ (vector)->cnt = 0; \ (vector)->size = 0; \ (vector)->data = NULL; \ } while (0) #define xc_vector_add(type, vector, value) do { \ if ((vector)->cnt == (vector)->size) { \ if ((vector)->size) { \ (vector)->size <<= 1; \ (vector)->data = erealloc((vector)->data, sizeof(type) * (vector)->size); \ } \ else { \ (vector)->size = 8; \ (vector)->data = emalloc(sizeof(type) * (vector)->size); \ } \ } \ ((type *) (vector)->data)[(vector)->cnt++] = value; \ } while (0) static inline void *xc_vector_detach_impl(xc_vector_t *vector) { void *data = vector->data; vector->data = NULL; vector->size = 0; vector->cnt = 0; return data; } #define xc_vector_detach(type, vector) ((type *) xc_vector_detach_impl(vector)) static inline void xc_vector_free_impl(xc_vector_t *vector TSRMLS_DC) { if (vector->data) { efree(vector->data); } vector->size = 0; vector->cnt = 0; } #define xc_vector_free(type, vector) xc_vector_free_impl(vector TSRMLS_CC) #endif /* XC_VECTOR_H_0957AC4E1A44E838C7B8DBECFF9C4B3B */ xcache-3.1.0/xcache/0000755000175000010010000000000012220455233012377 5ustar mOoNonexcache-3.1.0/xcache/README0000644000175000010010000000001712157744741013273 0ustar mOoNoneunderstructure xcache-3.1.0/xcache/xc_allocator.c0000644000175000010010000000534412220455233015223 0ustar mOoNone#ifdef TEST # ifdef HAVE_CONFIG_H # include # endif #else # include "xcache.h" #endif #include "xc_allocator.h" #include #include typedef struct { const char *name; const xc_allocator_vtable_t *allocator_vtable; } xc_allocator_info_t; static xc_allocator_info_t xc_allocator_infos[10]; int xc_allocator_register(const char *name, const xc_allocator_vtable_t *allocator_vtable) /* {{{ */ { size_t i; for (i = 0; i < sizeof(xc_allocator_infos) / sizeof(xc_allocator_infos[0]); i ++) { if (!xc_allocator_infos[i].name) { xc_allocator_infos[i].name = name; xc_allocator_infos[i].allocator_vtable = allocator_vtable; return 1; } } return 0; } /* }}} */ const xc_allocator_vtable_t *xc_allocator_find(const char *name) /* {{{ */ { size_t i; for (i = 0; i < sizeof(xc_allocator_infos) / sizeof(xc_allocator_infos[0]) && xc_allocator_infos[i].name; i ++) { if (strcmp(xc_allocator_infos[i].name, name) == 0) { return xc_allocator_infos[i].allocator_vtable; } } return NULL; } /* }}} */ void xc_allocator_init() /* {{{ */ { extern void xc_allocator_bestfit_register(); #ifdef HAVE_XCACHE_TEST extern void xc_allocator_malloc_register(); #endif memset(xc_allocator_infos, 0, sizeof(xc_allocator_infos)); xc_allocator_bestfit_register(); #ifdef HAVE_XCACHE_TEST xc_allocator_malloc_register(); #endif } /* }}} */ #ifdef TEST /* {{{ testing */ #undef CHECK #define CHECK(a, msg) do { \ if (!(a)) { \ fprintf(stderr, "%s\n", msg); return -1; \ } \ } while (0) #include int testAllocator(const xc_allocator_vtable_t *allocator_vtable) { int count = 0; void *p; xc_allocator_t *allocator; void *memory; void **ptrs; int size, i; #if 0 fprintf(stderr, "%s", "Input test size: "); scanf("%d", &size); #else size = 1024; #endif CHECK(memory = malloc(size), "OOM"); CHECK(ptrs = malloc(size * sizeof(void *)), "OOM"); allocator = (xc_allocator_t *) memory; allocator->vtable = allocator_vtable; CHECK(allocator = allocator->vtable->init(NULL, allocator, size), "Failed init memory allocator"); while ((p = allocator->vtable->malloc(allocator, 1))) { ptrs[count ++] = p; } fprintf(stderr, "count=%d, random freeing\n", count); srandom(time(NULL)); while (count) { i = (random() % count); fprintf(stderr, "freeing %d: ", i); allocator->vtable->free(allocator, ptrs[i]); ptrs[i] = ptrs[count - 1]; count --; } free(ptrs); free(memory); return 0; } /* }}} */ int main() /* {{{ */ { int i; xc_allocator_init(); for (i = 0; i < sizeof(xc_allocator_infos) / sizeof(xc_allocator_infos[0]) && xc_allocator_infos[i].name; i ++) { fprintf(stderr, "testing %s...\n", xc_allocator_infos[i].name); testAllocator(xc_allocator_infos[i].allocator_vtable); } return 0; } /* }}} */ #endif xcache-3.1.0/xcache/xc_allocator.h0000644000175000010010000000564412157744741015251 0ustar mOoNone#ifndef XC_ALLOCATOR_H_155E773CA8AFC18F3CCCDCF0831EE41D #define XC_ALLOCATOR_H_155E773CA8AFC18F3CCCDCF0831EE41D #if _MSC_VER > 1000 #pragma once #endif /* _MSC_VER > 1000 */ #include "xc_shm.h" typedef struct _xc_allocator_vtable_t xc_allocator_vtable_t; #ifndef _xc_allocator_t struct _xc_allocator_t { const xc_allocator_vtable_t *vtable; xc_shm_t *shm; }; #endif typedef struct _xc_allocator_t xc_allocator_t; typedef struct _xc_allocator_block_t xc_allocator_block_t; typedef xc_shmsize_t xc_memsize_t; /* allocator */ #define XC_ALLOCATOR_MALLOC(func) void *func(xc_allocator_t *allocator, xc_memsize_t size) #define XC_ALLOCATOR_FREE(func) xc_memsize_t func(xc_allocator_t *allocator, const void *p) #define XC_ALLOCATOR_CALLOC(func) void *func(xc_allocator_t *allocator, xc_memsize_t memb, xc_memsize_t size) #define XC_ALLOCATOR_REALLOC(func) void *func(xc_allocator_t *allocator, const void *p, xc_memsize_t size) #define XC_ALLOCATOR_AVAIL(func) xc_memsize_t func(const xc_allocator_t *allocator) #define XC_ALLOCATOR_SIZE(func) xc_memsize_t func(const xc_allocator_t *allocator) #define XC_ALLOCATOR_FREEBLOCK_FIRST(func) const xc_allocator_block_t *func(const xc_allocator_t *allocator) #define XC_ALLOCATOR_FREEBLOCK_NEXT(func) const xc_allocator_block_t *func(const xc_allocator_block_t *block) #define XC_ALLOCATOR_BLOCK_SIZE(func) xc_memsize_t func(const xc_allocator_block_t *block) #define XC_ALLOCATOR_BLOCK_OFFSET(func) xc_memsize_t func(const xc_allocator_t *allocator, const xc_allocator_block_t *block) #define XC_ALLOCATOR_INIT(func) xc_allocator_t *func(xc_shm_t *shm, xc_allocator_t *allocator, xc_memsize_t size) #define XC_ALLOCATOR_DESTROY(func) void func(xc_allocator_t *allocator) #define XC_ALLOCATOR_VTABLE(name) { \ xc_##name##_malloc \ , xc_##name##_free \ , xc_##name##_calloc \ , xc_##name##_realloc \ , xc_##name##_avail \ , xc_##name##_size \ , xc_##name##_freeblock_first \ , xc_##name##_freeblock_next \ , xc_##name##_block_size \ , xc_##name##_block_offset \ \ , xc_##name##_init \ , xc_##name##_destroy \ } struct _xc_allocator_vtable_t { XC_ALLOCATOR_MALLOC((*malloc)); XC_ALLOCATOR_FREE((*free)); XC_ALLOCATOR_CALLOC((*calloc)); XC_ALLOCATOR_REALLOC((*realloc)); XC_ALLOCATOR_AVAIL((*avail)); XC_ALLOCATOR_SIZE((*size)); XC_ALLOCATOR_FREEBLOCK_FIRST((*freeblock_first)); XC_ALLOCATOR_FREEBLOCK_NEXT((*freeblock_next)); XC_ALLOCATOR_BLOCK_SIZE((*block_size)); XC_ALLOCATOR_BLOCK_OFFSET((*block_offset)); XC_ALLOCATOR_INIT((*init)); XC_ALLOCATOR_DESTROY((*destroy)); }; int xc_allocator_register(const char *name, const xc_allocator_vtable_t *allocator_vtable); const xc_allocator_vtable_t *xc_allocator_find(const char *name); #endif /* XC_ALLOCATOR_H_155E773CA8AFC18F3CCCDCF0831EE41D */ xcache-3.1.0/xcache/xc_allocator_bestfit.c0000644000175000010010000001731512220455233016744 0ustar mOoNone#define _xc_allocator_t _xc_allocator_bestfit_t #define _xc_allocator_block_t _xc_allocator_bestfit_block_t #include "xc_allocator.h" #undef _xc_allocator_t #undef _xc_allocator_block_t #ifdef TEST # include # include # define XCACHE_DEBUG typedef int zend_bool; # define ZEND_ATTRIBUTE_PTR_FORMAT(a, b, c) # define zend_error(type, error) fprintf(stderr, "%s", error) #else # include #endif #ifdef XCACHE_DEBUG # define ALLOC_DEBUG_BLOCK_CHECK #endif #include #include #include #include "xc_shm.h" #include "util/xc_align.h" #include "util/xc_trace.h" #if 0 #undef ALLOC_DEBUG_BLOCK_CHECK #endif #define CHAR_PTR(p) ((char *) (p)) #define PADD(p, a) (CHAR_PTR(p) + a) #define PSUB(p1, p2) (CHAR_PTR(p1) - CHAR_PTR(p2)) /* {{{ allocator */ typedef struct _xc_allocator_bestfit_block_t xc_allocator_bestfit_block_t; struct _xc_allocator_bestfit_block_t { #ifdef ALLOC_DEBUG_BLOCK_CHECK unsigned int magic; #endif xc_memsize_t size; /* reserved even after alloc */ xc_allocator_bestfit_block_t *next; /* not used after alloc */ }; typedef struct _xc_allocator_bestfit_t { const xc_allocator_vtable_t *vtable; xc_shm_t *shm; xc_memsize_t size; xc_memsize_t avail; /* total free */ xc_allocator_bestfit_block_t headblock[1]; /* just as a pointer to first block*/ } xc_allocator_bestfit_t; #include #define SizeOf(type, field) sizeof( ((type *) 0)->field ) #define BLOCK_HEADER_SIZE() (ALIGN( offsetof(xc_allocator_bestfit_block_t, size) + SizeOf(xc_allocator_bestfit_block_t, size) )) #define BLOCK_MAGIC ((unsigned int) 0x87655678) /* }}} */ static inline void xc_block_setup(xc_allocator_bestfit_block_t *b, xc_memsize_t size, xc_allocator_bestfit_block_t *next) /* {{{ */ { #ifdef ALLOC_DEBUG_BLOCK_CHECK b->magic = BLOCK_MAGIC; #endif b->size = size; b->next = next; } /* }}} */ #ifdef ALLOC_DEBUG_BLOCK_CHECK static void xc_block_check(xc_allocator_bestfit_block_t *b) /* {{{ */ { if (b->magic != BLOCK_MAGIC) { fprintf(stderr, "0x%X != 0x%X magic wrong \n", b->magic, BLOCK_MAGIC); } } /* }}} */ #else # define xc_block_check(b) do { } while(0) #endif static XC_ALLOCATOR_MALLOC(xc_allocator_bestfit_malloc) /* {{{ */ { xc_allocator_bestfit_block_t *prev, *cur; xc_allocator_bestfit_block_t *newb, *b; xc_memsize_t realsize; xc_memsize_t minsize; void *p; /* [xc_allocator_bestfit_block_t:size|size] */ realsize = BLOCK_HEADER_SIZE() + size; /* realsize is ALIGNed so next block start at ALIGNed address */ realsize = ALIGN(realsize); TRACE("avail: %lu (%luKB). Allocate size: %lu realsize: %lu (%luKB)" , allocator->avail, allocator->avail / 1024 , size , realsize, realsize / 1024 ); do { p = NULL; if (allocator->avail < realsize) { TRACE("%s", " oom"); break; } b = NULL; minsize = ULONG_MAX; /* prev|cur */ for (prev = allocator->headblock; prev->next; prev = cur) { /* while (prev->next != 0) { */ cur = prev->next; xc_block_check(cur); if (cur->size == realsize) { /* found a perfect fit, stop searching */ b = prev; break; } /* make sure we can split on the block */ else if (cur->size > (sizeof(xc_allocator_bestfit_block_t) + realsize) && cur->size < minsize) { /* cur is acceptable and memller */ b = prev; minsize = cur->size; } prev = cur; } if (b == NULL) { TRACE("%s", " no fit chunk"); break; } prev = b; cur = prev->next; p = PADD(cur, BLOCK_HEADER_SIZE()); /* update the block header */ allocator->avail -= realsize; /* perfect fit, just unlink */ if (cur->size == realsize) { prev->next = cur->next; TRACE(" perfect fit. Got: %p", p); break; } /* make new free block after alloced space */ /* save, as it might be overwrited by newb (cur->size is ok) */ b = cur->next; /* prev|cur |next=b */ newb = (xc_allocator_bestfit_block_t *)PADD(cur, realsize); xc_block_setup(newb, cur->size - realsize, b); cur->size = realsize; /* prev|cur|newb|next * `--^ */ TRACE(" -> avail: %lu (%luKB). new next: %p offset: %lu %luKB. Got: %p" , allocator->avail, allocator->avail / 1024 , newb , PSUB(newb, allocator), PSUB(newb, allocator) / 1024 , p ); prev->next = newb; /* prev|cur|newb|next * `-----^ */ } while (0); return p; } /* }}} */ static XC_ALLOCATOR_FREE(xc_allocator_bestfit_free) /* {{{ return block size freed */ { xc_allocator_bestfit_block_t *cur, *b; int size; cur = (xc_allocator_bestfit_block_t *) (CHAR_PTR(p) - BLOCK_HEADER_SIZE()); TRACE("freeing: %p, size=%lu", p, cur->size); xc_block_check(cur); assert((char*)allocator < (char*)cur); assert((char*)cur < (char*)allocator + allocator->size); /* find free block right before the p */ b = allocator->headblock; while (b->next != 0 && b->next < cur) { b = b->next; } /* restore block */ cur->next = b->next; b->next = cur; size = cur->size; TRACE(" avail %lu (%luKB)", allocator->avail, allocator->avail / 1024); allocator->avail += size; /* combine prev|cur */ if (PADD(b, b->size) == (char *)cur) { b->size += cur->size; b->next = cur->next; cur = b; TRACE("%s", " combine prev"); } /* combine cur|next */ b = cur->next; if (PADD(cur, cur->size) == (char *)b) { cur->size += b->size; cur->next = b->next; TRACE("%s", " combine next"); } TRACE(" -> avail %lu (%luKB)", allocator->avail, allocator->avail / 1024); return size; } /* }}} */ static XC_ALLOCATOR_CALLOC(xc_allocator_bestfit_calloc) /* {{{ */ { xc_memsize_t realsize = memb * size; void *p = xc_allocator_bestfit_malloc(allocator, realsize); if (p) { memset(p, 0, realsize); } return p; } /* }}} */ static XC_ALLOCATOR_REALLOC(xc_allocator_bestfit_realloc) /* {{{ */ { void *newp = xc_allocator_bestfit_malloc(allocator, size); if (p && newp) { memcpy(newp, p, size); xc_allocator_bestfit_free(allocator, p); } return newp; } /* }}} */ static XC_ALLOCATOR_AVAIL(xc_allocator_bestfit_avail) /* {{{ */ { return allocator->avail; } /* }}} */ static XC_ALLOCATOR_SIZE(xc_allocator_bestfit_size) /* {{{ */ { return allocator->size; } /* }}} */ static XC_ALLOCATOR_FREEBLOCK_FIRST(xc_allocator_bestfit_freeblock_first) /* {{{ */ { return allocator->headblock->next; } /* }}} */ static XC_ALLOCATOR_FREEBLOCK_NEXT(xc_allocator_bestfit_freeblock_next) /* {{{ */ { return block->next; } /* }}} */ static XC_ALLOCATOR_BLOCK_SIZE(xc_allocator_bestfit_block_size) /* {{{ */ { return block->size; } /* }}} */ static XC_ALLOCATOR_BLOCK_OFFSET(xc_allocator_bestfit_block_offset) /* {{{ */ { return ((char *) block) - ((char *) allocator); } /* }}} */ static XC_ALLOCATOR_INIT(xc_allocator_bestfit_init) /* {{{ */ { xc_allocator_bestfit_block_t *b; #define MINSIZE (ALIGN(sizeof(xc_allocator_bestfit_t)) + sizeof(xc_allocator_bestfit_block_t)) /* requires at least the header and 1 tail block */ if (size < MINSIZE) { fprintf(stderr, "xc_allocator_bestfit_init requires %lu bytes at least\n", (unsigned long) MINSIZE); return NULL; } TRACE("size=%lu", size); allocator->shm = shm; allocator->size = size; allocator->avail = size - MINSIZE; /* pointer to first block, right after ALIGNed header */ b = allocator->headblock; xc_block_setup(b, 0, (xc_allocator_bestfit_block_t *) PADD(allocator, ALIGN(sizeof(xc_allocator_bestfit_t)))); /* first block*/ b = b->next; xc_block_setup(b, allocator->avail, 0); #undef MINSIZE return allocator; } /* }}} */ static XC_ALLOCATOR_DESTROY(xc_allocator_bestfit_destroy) /* {{{ */ { } /* }}} */ static xc_allocator_vtable_t xc_allocator_bestfit = XC_ALLOCATOR_VTABLE(allocator_bestfit); void xc_allocator_bestfit_register() /* {{{ */ { if (xc_allocator_register("bestfit", &xc_allocator_bestfit) == 0) { zend_error(E_ERROR, "XCache: failed to register allocator 'bestfit'"); } } /* }}} */ xcache-3.1.0/xcache/xc_compatibility.c0000644000175000010010000000132612206607320016110 0ustar mOoNone#include "xc_compatibility.h" #ifndef ZEND_ENGINE_2_3 #include "ext/standard/php_string.h" size_t xc_dirname(char *path, size_t len) /* {{{ */ { #ifdef ZEND_ENGINE_2 return php_dirname(path, len); #else php_dirname(path, len); return strlen(path); #endif } /* }}} */ long xc_atol(const char *str, int str_len) /* {{{ */ { long retval; if (!str_len) { str_len = strlen(str); } retval = strtol(str, NULL, 0); if (str_len > 0) { switch (str[str_len - 1]) { case 'g': case 'G': retval *= 1024; /* break intentionally missing */ case 'm': case 'M': retval *= 1024; /* break intentionally missing */ case 'k': case 'K': retval *= 1024; break; } } return retval; } /* }}} */ #endif xcache-3.1.0/xcache/xc_compatibility.h0000644000175000010010000001654012206607320016121 0ustar mOoNone#ifndef XC_COMPATIBILITY_H_54F26ED90198353558718191D5EE244C #define XC_COMPATIBILITY_H_54F26ED90198353558718191D5EE244C #if _MSC_VER > 1000 #pragma once #endif /* _MSC_VER > 1000 */ #include "php.h" /* Purpose: Privode stuffs for compatibility with different PHP version */ #if !defined(ZEND_ENGINE_2_5) && (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 5 || PHP_MAJOR_VERSION > 6) # define ZEND_ENGINE_2_5 #endif #if !defined(ZEND_ENGINE_2_4) && (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 4 || defined(ZEND_ENGINE_2_5)) # define ZEND_ENGINE_2_4 #endif #if !defined(ZEND_ENGINE_2_3) && (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 3 || defined(ZEND_ENGINE_2_4)) # define ZEND_ENGINE_2_3 #endif #if !defined(ZEND_ENGINE_2_2) && (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 2 || defined(ZEND_ENGINE_2_3)) # define ZEND_ENGINE_2_2 #endif #if !defined(ZEND_ENGINE_2_1) && (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 1 || defined(ZEND_ENGINE_2_2)) # define ZEND_ENGINE_2_1 #endif #define NOTHING /* ZendEngine code Switcher */ #ifndef ZEND_ENGINE_2 # define ZESW(v1, v2) v1 #else # define ZESW(v1, v2) v2 #endif #ifdef ZEND_ENGINE_2_4 # define ZEND_24(pre24, v24) v24 #else # define ZEND_24(pre24, v24) pre24 #endif #ifdef do_alloca_with_limit # define xc_do_alloca(size, use_heap) do_alloca_with_limit(size, use_heap) # define xc_free_alloca(size, use_heap) free_alloca_with_limit(size, use_heap) #elif defined(ALLOCA_FLAG) # define xc_do_alloca(size, use_heap) do_alloca(size, use_heap) # define xc_free_alloca(size, use_heap) free_alloca(size, use_heap) #else # define xc_do_alloca(size, use_heap) do_alloca(size) # define xc_free_alloca(size, use_heap) free_alloca(size) # define ALLOCA_FLAG(x) #endif #ifndef Z_ISREF # define Z_ISREF(z) (z).is_ref #endif #ifndef Z_SET_ISREF # define Z_SET_ISREF(z) (z).is_ref = 1 #endif #ifndef Z_UNSET_ISREF # define Z_UNSET_ISREF(z) (z).is_ref = 0 #endif #ifndef Z_REFCOUNT # define Z_REFCOUNT(z) (z).refcount #endif #ifndef Z_SET_REFCOUNT # define Z_SET_REFCOUNT(z, rc) (z).refcount = rc #endif #ifndef IS_CONSTANT_TYPE_MASK # define IS_CONSTANT_TYPE_MASK (~IS_CONSTANT_INDEX) #endif /* {{{ dirty fix for PHP 6 */ #ifdef add_assoc_long_ex static inline void xc_add_assoc_long_ex(zval *arg, char *key, uint key_len, long value) { add_assoc_long_ex(arg, key, key_len, value); } # undef add_assoc_long_ex # define add_assoc_long_ex xc_add_assoc_long_ex #endif #ifdef add_assoc_bool_ex static inline void xc_add_assoc_bool_ex(zval *arg, char *key, uint key_len, zend_bool value) { add_assoc_bool_ex(arg, key, key_len, value); } # undef add_assoc_bool_ex # define add_assoc_bool_ex xc_add_assoc_bool_ex #endif #ifdef add_assoc_null_ex static inline void xc_add_assoc_null_ex(zval *arg, char *key, uint key_len) { add_assoc_null_ex(arg, key, key_len); } # undef add_assoc_null_ex # define add_assoc_null_ex xc_add_assoc_null_ex #endif /* }}} */ #ifdef ZEND_ENGINE_2_4 # define Z_OP(op) (op) # define Z_OP_CONSTANT(op) (op).literal->constant # define Z_OP_TYPE(op) op##_##type # define Z_OP_TYPEOF_TYPE zend_uchar # define Z_CLASS_INFO(className) (className).info.user #else # define Z_OP(op) (op).u # define Z_OP_CONSTANT(op) (op).u.constant # define Z_OP_TYPE(op) (op).op_type # define Z_OP_TYPEOF_TYPE int typedef znode znode_op; # define Z_CLASS_INFO(className) (className) static inline int php_output_start_default(TSRMLS_D) { return php_start_ob_buffer(NULL, 0, 1 TSRMLS_CC); } static inline int php_output_get_contents(zval *p TSRMLS_DC) { return php_ob_get_buffer(p TSRMLS_CC); } static inline int php_output_discard(TSRMLS_D) { php_end_ob_buffer(0, 0 TSRMLS_CC); return SUCCESS; } #endif /* unicode */ #ifdef IS_UNICODE # define UNISW(text, unicode) unicode #else # define UNISW(text, unicode) text #endif #define BUCKET_KEY_SIZE(b) \ (UNISW( \ (b)->nKeyLength, \ ((b)->key.type == IS_UNICODE) \ ? UBYTES(b->nKeyLength) \ : b->nKeyLength \ )) #define BUCKET_KEY(b) (UNISW((b)->arKey, (b)->key.arKey)) #define BUCKET_KEY_S(b) ZSTR_S(BUCKET_KEY(b)) #define BUCKET_KEY_U(b) ZSTR_U(BUCKET_KEY(b)) #define BUCKET_KEY_TYPE(b) (UNISW(IS_STRING, (b)->key.type)) #ifdef IS_UNICODE # define BUCKET_HEAD_SIZE(b) XtOffsetOf(Bucket, key.arKey) #else # define BUCKET_HEAD_SIZE(b) XtOffsetOf(Bucket, arKey) #endif #ifdef ZEND_ENGINE_2_4 # define BUCKET_SIZE(b) (sizeof(Bucket) + BUCKET_KEY_SIZE(b)) #else # define BUCKET_SIZE(b) (BUCKET_HEAD_SIZE(b) + BUCKET_KEY_SIZE(b)) #endif #ifndef IS_UNICODE typedef char *zstr; typedef const char *const_zstr; #ifdef ZEND_ENGINE_2_4 typedef const char *const24_zstr; typedef const char *const24_str; #else typedef char *const24_zstr; typedef char *const24_str; #endif # define ZSTR_S(s) (s) # define ZSTR_U(s) (s) # define ZSTR_V(s) (s) # define ZSTR_PS(s) (s) # define ZSTR_PU(s) (s) # define ZSTR_PV(s) (s) #else typedef const zstr const_zstr; # define ZSTR_S(zs) ((zs).s) # define ZSTR_U(zs) ((zs).u) # define ZSTR_V(zs) ((zs).v) # define ZSTR_PS(pzs) ((pzs)->s) # define ZSTR_PU(pzs) ((pzs)->u) # define ZSTR_PV(pzs) ((pzs)->v) #endif #ifndef ZSTR # define ZSTR(s) (s) #endif #ifndef Z_UNIVAL # define Z_UNIVAL(zval) (zval).value.str.val # define Z_UNILEN(zval) (zval).value.str.len #endif /* {{{ u hash wrapper */ #ifndef IS_UNICODE # define zend_u_hash_add(ht, type, arKey, nKeyLength, pData, nDataSize, pDest) \ zend_hash_add(ht, ZEND_24((char *), NOTHING) arKey, nKeyLength, pData, nDataSize, pDest) # define zend_u_hash_quick_add(ht, type, arKey, nKeyLength, h, pData, nDataSize, pDest) \ zend_hash_quick_add(ht, ZEND_24((char *), NOTHING) arKey, nKeyLength, h, pData, nDataSize, pDest) # define zend_u_hash_update(ht, type, arKey, nKeyLength, pData, nDataSize, pDest) \ zend_hash_update(ht, ZEND_24((char *), NOTHING) arKey, nKeyLength, pData, nDataSize, pDest) # define zend_u_hash_quick_update(ht, type, arKey, nKeyLength, h, pData, nDataSize, pDest) \ zend_hash_quick_update(ht, ZEND_24((char *), NOTHING) arKey, nKeyLength, h, pData, nDataSize, pDest) # define zend_u_hash_find(ht, type, arKey, nKeyLength, pData) \ zend_hash_find(ht, ZEND_24((char *), NOTHING) arKey, nKeyLength, pData) # define zend_u_hash_quick_find(ht, type, arKey, nKeyLength, h, pData) \ zend_hash_quick_find(ht, ZEND_24((char *), NOTHING) arKey, nKeyLength, h, pData) # define zend_u_hash_exists(ht, type, arKey, nKeyLength) \ zend_hash_exists(ht, ZEND_24((char *), NOTHING) arKey, nKeyLength) # define add_u_assoc_zval_ex(arg, type, key, key_len, value) \ add_assoc_zval_ex(arg, key, key_len, value) # define zend_u_is_auto_global(type, name, name_len) \ zend_is_auto_global(name, name_len) #endif /* }}} */ /* the class entry type to be stored in class_table */ typedef ZESW(zend_class_entry, zend_class_entry*) xc_cest_t; /* xc_cest_t to (zend_class_entry*) */ #define CestToCePtr(st) (ZESW(\ &(st), \ st \ ) ) /* ZCEP=zend class entry ptr */ #define ZCEP_REFCOUNT_PTR(pce) (ZESW( \ (pce)->refcount, \ &((pce)->refcount) \ )) #ifndef ZEND_ENGINE_2_3 size_t xc_dirname(char *path, size_t len); #define zend_dirname xc_dirname long xc_atol(const char *str, int len); #define zend_atol xc_atol #endif #ifndef ZEND_MOD_END # define ZEND_MOD_END {NULL, NULL, NULL, 0} #endif #ifndef PHP_FE_END # ifdef ZEND_ENGINE_2 # define PHP_FE_END {NULL, NULL, NULL, 0, 0} # else # define PHP_FE_END {NULL, NULL, NULL} # endif #endif #endif /* XC_COMPATIBILITY_H_54F26ED90198353558718191D5EE244C */ xcache-3.1.0/xcache/xc_const_string.c0000644000175000010010000000420612206607320015753 0ustar mOoNone#include "xcache.h" #include "xc_const_string.h" /* {{{ xc_get_op_type */ static const char *const op_type_names[] = { /* 0 */ "NULL?", /* 1 */ "IS_CONST", /* 2 */ "IS_TMP_VAR", /* 3 */ NULL, /* 4 */ "IS_VAR", /* 5 */ NULL, /* 6 */ NULL, /* 7 */ NULL, /* 8 */ "IS_UNUSED", #ifdef IS_CV /* 9 */ NULL, /* 10 */ NULL, /* 11 */ NULL, /* 12 */ NULL, /* 13 */ NULL, /* 14 */ NULL, /* 15 */ NULL, /* 16 */ "IS_CV" #endif }; zend_uchar xc_get_op_type_count() { return sizeof(op_type_names) / sizeof(op_type_names[0]); } const char *xc_get_op_type(zend_uchar op_type) { assert(op_type < xc_get_op_type_count()); return op_type_names[op_type]; } /* }}} */ /* {{{ xc_get_data_type */ static const char *const data_type_names[] = { /* 0 */ "IS_NULL", /* 1 */ "IS_LONG", /* 2 */ "IS_DOUBLE", #ifdef ZEND_ENGINE_2_1 /* 3 */ "IS_BOOL", #else /* 6 */ "IS_STRING", #endif /* 4 */ "IS_ARRAY", /* 5 */ "IS_OBJECT", #ifdef ZEND_ENGINE_2_1 /* 6 */ "IS_STRING", #else /* 3 */ "IS_BOOL", #endif /* 7 */ "IS_RESOURCE", /* 8 */ "IS_CONSTANT", /* 9 */ "IS_CONSTANT_ARRAY", /* 10 */ "IS_UNICODE" }; zend_uchar xc_get_data_type_count() { return sizeof(data_type_names) / sizeof(data_type_names[0]); } const char *xc_get_data_type(zend_uchar data_type) { return data_type_names[(data_type & IS_CONSTANT_TYPE_MASK)]; } /* }}} */ /* {{{ xc_get_opcode */ #if PHP_MAJOR_VERSION >= 6 # include "xc_const_string_opcodes_php6.x.h" #elif defined(ZEND_ENGINE_2_5) # include "xc_const_string_opcodes_php5.5.h" #elif defined(ZEND_ENGINE_2_4) # include "xc_const_string_opcodes_php5.4.h" #elif defined(ZEND_ENGINE_2_3) # include "xc_const_string_opcodes_php5.3.h" #elif defined(ZEND_ENGINE_2_2) # include "xc_const_string_opcodes_php5.2.h" #elif defined(ZEND_ENGINE_2_1) # include "xc_const_string_opcodes_php5.1.h" #elif defined(ZEND_ENGINE_2) # include "xc_const_string_opcodes_php5.0.h" #else # include "xc_const_string_opcodes_php4.x.h" #endif zend_uchar xc_get_opcode_count() { return sizeof(xc_opcode_names) / sizeof(xc_opcode_names[0]); } const char *xc_get_opcode(zend_uchar opcode) { assert(opcode < xc_get_opcode_count()); return xc_opcode_names[opcode]; } /* }}} */ xcache-3.1.0/xcache/xc_const_string.h0000644000175000010010000000041612157744741015775 0ustar mOoNone#include "php.h" zend_uchar xc_get_op_type_count(); const char *xc_get_op_type(zend_uchar op_type); zend_uchar xc_get_data_type_count(); const char *xc_get_data_type(zend_uchar data_type); zend_uchar xc_get_opcode_count(); const char *xc_get_opcode(zend_uchar opcode); xcache-3.1.0/xcache/xc_const_string_opcodes_php4.x.h0000644000175000010010000000501612206607320020675 0ustar mOoNone/* size = 113 */ static const char *const xc_opcode_names[] = { /* 0 */ "NOP", /* 1 */ "ADD", /* 2 */ "SUB", /* 3 */ "MUL", /* 4 */ "DIV", /* 5 */ "MOD", /* 6 */ "SL", /* 7 */ "SR", /* 8 */ "CONCAT", /* 9 */ "BW_OR", /* 10 */ "BW_AND", /* 11 */ "BW_XOR", /* 12 */ "BW_NOT", /* 13 */ "BOOL_NOT", /* 14 */ "BOOL_XOR", /* 15 */ "IS_IDENTICAL", /* 16 */ "IS_NOT_IDENTICAL", /* 17 */ "IS_EQUAL", /* 18 */ "IS_NOT_EQUAL", /* 19 */ "IS_SMALLER", /* 20 */ "IS_SMALLER_OR_EQUAL", /* 21 */ "CAST", /* 22 */ "QM_ASSIGN", /* 23 */ "ASSIGN_ADD", /* 24 */ "ASSIGN_SUB", /* 25 */ "ASSIGN_MUL", /* 26 */ "ASSIGN_DIV", /* 27 */ "ASSIGN_MOD", /* 28 */ "ASSIGN_SL", /* 29 */ "ASSIGN_SR", /* 30 */ "ASSIGN_CONCAT", /* 31 */ "ASSIGN_BW_OR", /* 32 */ "ASSIGN_BW_AND", /* 33 */ "ASSIGN_BW_XOR", /* 34 */ "PRE_INC", /* 35 */ "PRE_DEC", /* 36 */ "POST_INC", /* 37 */ "POST_DEC", /* 38 */ "ASSIGN", /* 39 */ "ASSIGN_REF", /* 40 */ "ECHO", /* 41 */ "PRINT", /* 42 */ "JMP", /* 43 */ "JMPZ", /* 44 */ "JMPNZ", /* 45 */ "JMPZNZ", /* 46 */ "JMPZ_EX", /* 47 */ "JMPNZ_EX", /* 48 */ "CASE", /* 49 */ "SWITCH_FREE", /* 50 */ "BRK", /* 51 */ "CONT", /* 52 */ "BOOL", /* 53 */ "INIT_STRING", /* 54 */ "ADD_CHAR", /* 55 */ "ADD_STRING", /* 56 */ "ADD_VAR", /* 57 */ "BEGIN_SILENCE", /* 58 */ "END_SILENCE", /* 59 */ "INIT_FCALL_BY_NAME", /* 60 */ "DO_FCALL", /* 61 */ "DO_FCALL_BY_NAME", /* 62 */ "RETURN", /* 63 */ "RECV", /* 64 */ "RECV_INIT", /* 65 */ "SEND_VAL", /* 66 */ "SEND_VAR", /* 67 */ "SEND_REF", /* 68 */ "NEW", /* 69 */ "JMP_NO_CTOR", /* 70 */ "FREE", /* 71 */ "INIT_ARRAY", /* 72 */ "ADD_ARRAY_ELEMENT", /* 73 */ "INCLUDE_OR_EVAL", /* 74 */ "UNSET_VAR", /* 75 */ "UNSET_DIM_OBJ", /* 76 */ "ISSET_ISEMPTY", /* 77 */ "FE_RESET", /* 78 */ "FE_FETCH", /* 79 */ "EXIT", /* 80 */ "FETCH_R", /* 81 */ "FETCH_DIM_R", /* 82 */ "FETCH_OBJ_R", /* 83 */ "FETCH_W", /* 84 */ "FETCH_DIM_W", /* 85 */ "FETCH_OBJ_W", /* 86 */ "FETCH_RW", /* 87 */ "FETCH_DIM_RW", /* 88 */ "FETCH_OBJ_RW", /* 89 */ "FETCH_IS", /* 90 */ "FETCH_DIM_IS", /* 91 */ "FETCH_OBJ_IS", /* 92 */ "FETCH_FUNC_ARG", /* 93 */ "FETCH_DIM_FUNC_ARG", /* 94 */ "FETCH_OBJ_FUNC_ARG", /* 95 */ "FETCH_UNSET", /* 96 */ "FETCH_DIM_UNSET", /* 97 */ "FETCH_OBJ_UNSET", /* 98 */ "FETCH_DIM_TMP_VAR", /* 99 */ "FETCH_CONSTANT", /* 100 */ "DECLARE_FUNCTION_OR_CLASS", /* 101 */ "EXT_STMT", /* 102 */ "EXT_FCALL_BEGIN", /* 103 */ "EXT_FCALL_END", /* 104 */ "EXT_NOP", /* 105 */ "TICKS", /* 106 */ "SEND_VAR_NO_REF", /* 107 */ "UNDEF", /* 108 */ "UNDEF", /* 109 */ "UNDEF", /* 110 */ "DO_FCALL_BY_FUNC", /* 111 */ "INIT_FCALL_BY_FUNC", /* 112 */ "UNDEF" }; xcache-3.1.0/xcache/xc_const_string_opcodes_php5.0.h0000644000175000010010000000656412157744741020615 0ustar mOoNone/* size = 150 */ static const char *const xc_opcode_names[] = { /* 0 */ "NOP", /* 1 */ "ADD", /* 2 */ "SUB", /* 3 */ "MUL", /* 4 */ "DIV", /* 5 */ "MOD", /* 6 */ "SL", /* 7 */ "SR", /* 8 */ "CONCAT", /* 9 */ "BW_OR", /* 10 */ "BW_AND", /* 11 */ "BW_XOR", /* 12 */ "BW_NOT", /* 13 */ "BOOL_NOT", /* 14 */ "BOOL_XOR", /* 15 */ "IS_IDENTICAL", /* 16 */ "IS_NOT_IDENTICAL", /* 17 */ "IS_EQUAL", /* 18 */ "IS_NOT_EQUAL", /* 19 */ "IS_SMALLER", /* 20 */ "IS_SMALLER_OR_EQUAL", /* 21 */ "CAST", /* 22 */ "QM_ASSIGN", /* 23 */ "ASSIGN_ADD", /* 24 */ "ASSIGN_SUB", /* 25 */ "ASSIGN_MUL", /* 26 */ "ASSIGN_DIV", /* 27 */ "ASSIGN_MOD", /* 28 */ "ASSIGN_SL", /* 29 */ "ASSIGN_SR", /* 30 */ "ASSIGN_CONCAT", /* 31 */ "ASSIGN_BW_OR", /* 32 */ "ASSIGN_BW_AND", /* 33 */ "ASSIGN_BW_XOR", /* 34 */ "PRE_INC", /* 35 */ "PRE_DEC", /* 36 */ "POST_INC", /* 37 */ "POST_DEC", /* 38 */ "ASSIGN", /* 39 */ "ASSIGN_REF", /* 40 */ "ECHO", /* 41 */ "PRINT", /* 42 */ "JMP", /* 43 */ "JMPZ", /* 44 */ "JMPNZ", /* 45 */ "JMPZNZ", /* 46 */ "JMPZ_EX", /* 47 */ "JMPNZ_EX", /* 48 */ "CASE", /* 49 */ "SWITCH_FREE", /* 50 */ "BRK", /* 51 */ "CONT", /* 52 */ "BOOL", /* 53 */ "INIT_STRING", /* 54 */ "ADD_CHAR", /* 55 */ "ADD_STRING", /* 56 */ "ADD_VAR", /* 57 */ "BEGIN_SILENCE", /* 58 */ "END_SILENCE", /* 59 */ "INIT_FCALL_BY_NAME", /* 60 */ "DO_FCALL", /* 61 */ "DO_FCALL_BY_NAME", /* 62 */ "RETURN", /* 63 */ "RECV", /* 64 */ "RECV_INIT", /* 65 */ "SEND_VAL", /* 66 */ "SEND_VAR", /* 67 */ "SEND_REF", /* 68 */ "NEW", /* 69 */ "JMP_NO_CTOR", /* 70 */ "FREE", /* 71 */ "INIT_ARRAY", /* 72 */ "ADD_ARRAY_ELEMENT", /* 73 */ "INCLUDE_OR_EVAL", /* 74 */ "UNSET_VAR", /* 75 */ "UNSET_DIM_OBJ", /* 76 */ "UNDEF", /* 77 */ "FE_RESET", /* 78 */ "FE_FETCH", /* 79 */ "EXIT", /* 80 */ "FETCH_R", /* 81 */ "FETCH_DIM_R", /* 82 */ "FETCH_OBJ_R", /* 83 */ "FETCH_W", /* 84 */ "FETCH_DIM_W", /* 85 */ "FETCH_OBJ_W", /* 86 */ "FETCH_RW", /* 87 */ "FETCH_DIM_RW", /* 88 */ "FETCH_OBJ_RW", /* 89 */ "FETCH_IS", /* 90 */ "FETCH_DIM_IS", /* 91 */ "FETCH_OBJ_IS", /* 92 */ "FETCH_FUNC_ARG", /* 93 */ "FETCH_DIM_FUNC_ARG", /* 94 */ "FETCH_OBJ_FUNC_ARG", /* 95 */ "FETCH_UNSET", /* 96 */ "FETCH_DIM_UNSET", /* 97 */ "FETCH_OBJ_UNSET", /* 98 */ "FETCH_DIM_TMP_VAR", /* 99 */ "FETCH_CONSTANT", /* 100 */ "UNDEF", /* 101 */ "EXT_STMT", /* 102 */ "EXT_FCALL_BEGIN", /* 103 */ "EXT_FCALL_END", /* 104 */ "EXT_NOP", /* 105 */ "TICKS", /* 106 */ "SEND_VAR_NO_REF", /* 107 */ "CATCH", /* 108 */ "THROW", /* 109 */ "FETCH_CLASS", /* 110 */ "CLONE", /* 111 */ "INIT_CTOR_CALL", /* 112 */ "INIT_METHOD_CALL", /* 113 */ "INIT_STATIC_METHOD_CALL", /* 114 */ "ISSET_ISEMPTY_VAR", /* 115 */ "ISSET_ISEMPTY_DIM_OBJ", /* 116 */ "UNDEF", /* 117 */ "UNDEF", /* 118 */ "UNDEF", /* 119 */ "UNDEF", /* 120 */ "UNDEF", /* 121 */ "UNDEF", /* 122 */ "UNDEF", /* 123 */ "UNDEF", /* 124 */ "UNDEF", /* 125 */ "UNDEF", /* 126 */ "UNDEF", /* 127 */ "UNDEF", /* 128 */ "UNDEF", /* 129 */ "UNDEF", /* 130 */ "UNDEF", /* 131 */ "UNDEF", /* 132 */ "PRE_INC_OBJ", /* 133 */ "PRE_DEC_OBJ", /* 134 */ "POST_INC_OBJ", /* 135 */ "POST_DEC_OBJ", /* 136 */ "ASSIGN_OBJ", /* 137 */ "OP_DATA", /* 138 */ "INSTANCEOF", /* 139 */ "DECLARE_CLASS", /* 140 */ "DECLARE_INHERITED_CLASS", /* 141 */ "DECLARE_FUNCTION", /* 142 */ "RAISE_ABSTRACT_ERROR", /* 143 */ "UNDEF", /* 144 */ "ADD_INTERFACE", /* 145 */ "UNDEF", /* 146 */ "VERIFY_ABSTRACT_CLASS", /* 147 */ "ASSIGN_DIM", /* 148 */ "ISSET_ISEMPTY_PROP_OBJ", /* 149 */ "HANDLE_EXCEPTION" }; xcache-3.1.0/xcache/xc_const_string_opcodes_php5.1.h0000644000175000010010000000657612157744741020621 0ustar mOoNone/* size = 151 */ static const char *const xc_opcode_names[] = { /* 0 */ "NOP", /* 1 */ "ADD", /* 2 */ "SUB", /* 3 */ "MUL", /* 4 */ "DIV", /* 5 */ "MOD", /* 6 */ "SL", /* 7 */ "SR", /* 8 */ "CONCAT", /* 9 */ "BW_OR", /* 10 */ "BW_AND", /* 11 */ "BW_XOR", /* 12 */ "BW_NOT", /* 13 */ "BOOL_NOT", /* 14 */ "BOOL_XOR", /* 15 */ "IS_IDENTICAL", /* 16 */ "IS_NOT_IDENTICAL", /* 17 */ "IS_EQUAL", /* 18 */ "IS_NOT_EQUAL", /* 19 */ "IS_SMALLER", /* 20 */ "IS_SMALLER_OR_EQUAL", /* 21 */ "CAST", /* 22 */ "QM_ASSIGN", /* 23 */ "ASSIGN_ADD", /* 24 */ "ASSIGN_SUB", /* 25 */ "ASSIGN_MUL", /* 26 */ "ASSIGN_DIV", /* 27 */ "ASSIGN_MOD", /* 28 */ "ASSIGN_SL", /* 29 */ "ASSIGN_SR", /* 30 */ "ASSIGN_CONCAT", /* 31 */ "ASSIGN_BW_OR", /* 32 */ "ASSIGN_BW_AND", /* 33 */ "ASSIGN_BW_XOR", /* 34 */ "PRE_INC", /* 35 */ "PRE_DEC", /* 36 */ "POST_INC", /* 37 */ "POST_DEC", /* 38 */ "ASSIGN", /* 39 */ "ASSIGN_REF", /* 40 */ "ECHO", /* 41 */ "PRINT", /* 42 */ "JMP", /* 43 */ "JMPZ", /* 44 */ "JMPNZ", /* 45 */ "JMPZNZ", /* 46 */ "JMPZ_EX", /* 47 */ "JMPNZ_EX", /* 48 */ "CASE", /* 49 */ "SWITCH_FREE", /* 50 */ "BRK", /* 51 */ "CONT", /* 52 */ "BOOL", /* 53 */ "INIT_STRING", /* 54 */ "ADD_CHAR", /* 55 */ "ADD_STRING", /* 56 */ "ADD_VAR", /* 57 */ "BEGIN_SILENCE", /* 58 */ "END_SILENCE", /* 59 */ "INIT_FCALL_BY_NAME", /* 60 */ "DO_FCALL", /* 61 */ "DO_FCALL_BY_NAME", /* 62 */ "RETURN", /* 63 */ "RECV", /* 64 */ "RECV_INIT", /* 65 */ "SEND_VAL", /* 66 */ "SEND_VAR", /* 67 */ "SEND_REF", /* 68 */ "NEW", /* 69 */ "UNDEF", /* 70 */ "FREE", /* 71 */ "INIT_ARRAY", /* 72 */ "ADD_ARRAY_ELEMENT", /* 73 */ "INCLUDE_OR_EVAL", /* 74 */ "UNSET_VAR", /* 75 */ "UNSET_DIM", /* 76 */ "UNSET_OBJ", /* 77 */ "FE_RESET", /* 78 */ "FE_FETCH", /* 79 */ "EXIT", /* 80 */ "FETCH_R", /* 81 */ "FETCH_DIM_R", /* 82 */ "FETCH_OBJ_R", /* 83 */ "FETCH_W", /* 84 */ "FETCH_DIM_W", /* 85 */ "FETCH_OBJ_W", /* 86 */ "FETCH_RW", /* 87 */ "FETCH_DIM_RW", /* 88 */ "FETCH_OBJ_RW", /* 89 */ "FETCH_IS", /* 90 */ "FETCH_DIM_IS", /* 91 */ "FETCH_OBJ_IS", /* 92 */ "FETCH_FUNC_ARG", /* 93 */ "FETCH_DIM_FUNC_ARG", /* 94 */ "FETCH_OBJ_FUNC_ARG", /* 95 */ "FETCH_UNSET", /* 96 */ "FETCH_DIM_UNSET", /* 97 */ "FETCH_OBJ_UNSET", /* 98 */ "FETCH_DIM_TMP_VAR", /* 99 */ "FETCH_CONSTANT", /* 100 */ "UNDEF", /* 101 */ "EXT_STMT", /* 102 */ "EXT_FCALL_BEGIN", /* 103 */ "EXT_FCALL_END", /* 104 */ "EXT_NOP", /* 105 */ "TICKS", /* 106 */ "SEND_VAR_NO_REF", /* 107 */ "CATCH", /* 108 */ "THROW", /* 109 */ "FETCH_CLASS", /* 110 */ "CLONE", /* 111 */ "UNDEF", /* 112 */ "INIT_METHOD_CALL", /* 113 */ "INIT_STATIC_METHOD_CALL", /* 114 */ "ISSET_ISEMPTY_VAR", /* 115 */ "ISSET_ISEMPTY_DIM_OBJ", /* 116 */ "UNDEF", /* 117 */ "UNDEF", /* 118 */ "UNDEF", /* 119 */ "UNDEF", /* 120 */ "UNDEF", /* 121 */ "UNDEF", /* 122 */ "UNDEF", /* 123 */ "UNDEF", /* 124 */ "UNDEF", /* 125 */ "UNDEF", /* 126 */ "UNDEF", /* 127 */ "UNDEF", /* 128 */ "UNDEF", /* 129 */ "UNDEF", /* 130 */ "UNDEF", /* 131 */ "UNDEF", /* 132 */ "PRE_INC_OBJ", /* 133 */ "PRE_DEC_OBJ", /* 134 */ "POST_INC_OBJ", /* 135 */ "POST_DEC_OBJ", /* 136 */ "ASSIGN_OBJ", /* 137 */ "OP_DATA", /* 138 */ "INSTANCEOF", /* 139 */ "DECLARE_CLASS", /* 140 */ "DECLARE_INHERITED_CLASS", /* 141 */ "DECLARE_FUNCTION", /* 142 */ "RAISE_ABSTRACT_ERROR", /* 143 */ "UNDEF", /* 144 */ "ADD_INTERFACE", /* 145 */ "UNDEF", /* 146 */ "VERIFY_ABSTRACT_CLASS", /* 147 */ "ASSIGN_DIM", /* 148 */ "ISSET_ISEMPTY_PROP_OBJ", /* 149 */ "HANDLE_EXCEPTION", /* 150 */ "USER_OPCODE" }; xcache-3.1.0/xcache/xc_const_string_opcodes_php5.2.h0000644000175000010010000000657612206607320020604 0ustar mOoNone/* size = 151 */ static const char *const xc_opcode_names[] = { /* 0 */ "NOP", /* 1 */ "ADD", /* 2 */ "SUB", /* 3 */ "MUL", /* 4 */ "DIV", /* 5 */ "MOD", /* 6 */ "SL", /* 7 */ "SR", /* 8 */ "CONCAT", /* 9 */ "BW_OR", /* 10 */ "BW_AND", /* 11 */ "BW_XOR", /* 12 */ "BW_NOT", /* 13 */ "BOOL_NOT", /* 14 */ "BOOL_XOR", /* 15 */ "IS_IDENTICAL", /* 16 */ "IS_NOT_IDENTICAL", /* 17 */ "IS_EQUAL", /* 18 */ "IS_NOT_EQUAL", /* 19 */ "IS_SMALLER", /* 20 */ "IS_SMALLER_OR_EQUAL", /* 21 */ "CAST", /* 22 */ "QM_ASSIGN", /* 23 */ "ASSIGN_ADD", /* 24 */ "ASSIGN_SUB", /* 25 */ "ASSIGN_MUL", /* 26 */ "ASSIGN_DIV", /* 27 */ "ASSIGN_MOD", /* 28 */ "ASSIGN_SL", /* 29 */ "ASSIGN_SR", /* 30 */ "ASSIGN_CONCAT", /* 31 */ "ASSIGN_BW_OR", /* 32 */ "ASSIGN_BW_AND", /* 33 */ "ASSIGN_BW_XOR", /* 34 */ "PRE_INC", /* 35 */ "PRE_DEC", /* 36 */ "POST_INC", /* 37 */ "POST_DEC", /* 38 */ "ASSIGN", /* 39 */ "ASSIGN_REF", /* 40 */ "ECHO", /* 41 */ "PRINT", /* 42 */ "JMP", /* 43 */ "JMPZ", /* 44 */ "JMPNZ", /* 45 */ "JMPZNZ", /* 46 */ "JMPZ_EX", /* 47 */ "JMPNZ_EX", /* 48 */ "CASE", /* 49 */ "SWITCH_FREE", /* 50 */ "BRK", /* 51 */ "CONT", /* 52 */ "BOOL", /* 53 */ "INIT_STRING", /* 54 */ "ADD_CHAR", /* 55 */ "ADD_STRING", /* 56 */ "ADD_VAR", /* 57 */ "BEGIN_SILENCE", /* 58 */ "END_SILENCE", /* 59 */ "INIT_FCALL_BY_NAME", /* 60 */ "DO_FCALL", /* 61 */ "DO_FCALL_BY_NAME", /* 62 */ "RETURN", /* 63 */ "RECV", /* 64 */ "RECV_INIT", /* 65 */ "SEND_VAL", /* 66 */ "SEND_VAR", /* 67 */ "SEND_REF", /* 68 */ "NEW", /* 69 */ "UNDEF", /* 70 */ "FREE", /* 71 */ "INIT_ARRAY", /* 72 */ "ADD_ARRAY_ELEMENT", /* 73 */ "INCLUDE_OR_EVAL", /* 74 */ "UNSET_VAR", /* 75 */ "UNSET_DIM", /* 76 */ "UNSET_OBJ", /* 77 */ "FE_RESET", /* 78 */ "FE_FETCH", /* 79 */ "EXIT", /* 80 */ "FETCH_R", /* 81 */ "FETCH_DIM_R", /* 82 */ "FETCH_OBJ_R", /* 83 */ "FETCH_W", /* 84 */ "FETCH_DIM_W", /* 85 */ "FETCH_OBJ_W", /* 86 */ "FETCH_RW", /* 87 */ "FETCH_DIM_RW", /* 88 */ "FETCH_OBJ_RW", /* 89 */ "FETCH_IS", /* 90 */ "FETCH_DIM_IS", /* 91 */ "FETCH_OBJ_IS", /* 92 */ "FETCH_FUNC_ARG", /* 93 */ "FETCH_DIM_FUNC_ARG", /* 94 */ "FETCH_OBJ_FUNC_ARG", /* 95 */ "FETCH_UNSET", /* 96 */ "FETCH_DIM_UNSET", /* 97 */ "FETCH_OBJ_UNSET", /* 98 */ "FETCH_DIM_TMP_VAR", /* 99 */ "FETCH_CONSTANT", /* 100 */ "UNDEF", /* 101 */ "EXT_STMT", /* 102 */ "EXT_FCALL_BEGIN", /* 103 */ "EXT_FCALL_END", /* 104 */ "EXT_NOP", /* 105 */ "TICKS", /* 106 */ "SEND_VAR_NO_REF", /* 107 */ "CATCH", /* 108 */ "THROW", /* 109 */ "FETCH_CLASS", /* 110 */ "CLONE", /* 111 */ "UNDEF", /* 112 */ "INIT_METHOD_CALL", /* 113 */ "INIT_STATIC_METHOD_CALL", /* 114 */ "ISSET_ISEMPTY_VAR", /* 115 */ "ISSET_ISEMPTY_DIM_OBJ", /* 116 */ "UNDEF", /* 117 */ "UNDEF", /* 118 */ "UNDEF", /* 119 */ "UNDEF", /* 120 */ "UNDEF", /* 121 */ "UNDEF", /* 122 */ "UNDEF", /* 123 */ "UNDEF", /* 124 */ "UNDEF", /* 125 */ "UNDEF", /* 126 */ "UNDEF", /* 127 */ "UNDEF", /* 128 */ "UNDEF", /* 129 */ "UNDEF", /* 130 */ "UNDEF", /* 131 */ "UNDEF", /* 132 */ "PRE_INC_OBJ", /* 133 */ "PRE_DEC_OBJ", /* 134 */ "POST_INC_OBJ", /* 135 */ "POST_DEC_OBJ", /* 136 */ "ASSIGN_OBJ", /* 137 */ "OP_DATA", /* 138 */ "INSTANCEOF", /* 139 */ "DECLARE_CLASS", /* 140 */ "DECLARE_INHERITED_CLASS", /* 141 */ "DECLARE_FUNCTION", /* 142 */ "RAISE_ABSTRACT_ERROR", /* 143 */ "UNDEF", /* 144 */ "ADD_INTERFACE", /* 145 */ "UNDEF", /* 146 */ "VERIFY_ABSTRACT_CLASS", /* 147 */ "ASSIGN_DIM", /* 148 */ "ISSET_ISEMPTY_PROP_OBJ", /* 149 */ "HANDLE_EXCEPTION", /* 150 */ "USER_OPCODE" }; xcache-3.1.0/xcache/xc_const_string_opcodes_php5.3.h0000644000175000010010000000677412206607320020605 0ustar mOoNone/* size = 154 */ static const char *const xc_opcode_names[] = { /* 0 */ "NOP", /* 1 */ "ADD", /* 2 */ "SUB", /* 3 */ "MUL", /* 4 */ "DIV", /* 5 */ "MOD", /* 6 */ "SL", /* 7 */ "SR", /* 8 */ "CONCAT", /* 9 */ "BW_OR", /* 10 */ "BW_AND", /* 11 */ "BW_XOR", /* 12 */ "BW_NOT", /* 13 */ "BOOL_NOT", /* 14 */ "BOOL_XOR", /* 15 */ "IS_IDENTICAL", /* 16 */ "IS_NOT_IDENTICAL", /* 17 */ "IS_EQUAL", /* 18 */ "IS_NOT_EQUAL", /* 19 */ "IS_SMALLER", /* 20 */ "IS_SMALLER_OR_EQUAL", /* 21 */ "CAST", /* 22 */ "QM_ASSIGN", /* 23 */ "ASSIGN_ADD", /* 24 */ "ASSIGN_SUB", /* 25 */ "ASSIGN_MUL", /* 26 */ "ASSIGN_DIV", /* 27 */ "ASSIGN_MOD", /* 28 */ "ASSIGN_SL", /* 29 */ "ASSIGN_SR", /* 30 */ "ASSIGN_CONCAT", /* 31 */ "ASSIGN_BW_OR", /* 32 */ "ASSIGN_BW_AND", /* 33 */ "ASSIGN_BW_XOR", /* 34 */ "PRE_INC", /* 35 */ "PRE_DEC", /* 36 */ "POST_INC", /* 37 */ "POST_DEC", /* 38 */ "ASSIGN", /* 39 */ "ASSIGN_REF", /* 40 */ "ECHO", /* 41 */ "PRINT", /* 42 */ "JMP", /* 43 */ "JMPZ", /* 44 */ "JMPNZ", /* 45 */ "JMPZNZ", /* 46 */ "JMPZ_EX", /* 47 */ "JMPNZ_EX", /* 48 */ "CASE", /* 49 */ "SWITCH_FREE", /* 50 */ "BRK", /* 51 */ "CONT", /* 52 */ "BOOL", /* 53 */ "INIT_STRING", /* 54 */ "ADD_CHAR", /* 55 */ "ADD_STRING", /* 56 */ "ADD_VAR", /* 57 */ "BEGIN_SILENCE", /* 58 */ "END_SILENCE", /* 59 */ "INIT_FCALL_BY_NAME", /* 60 */ "DO_FCALL", /* 61 */ "DO_FCALL_BY_NAME", /* 62 */ "RETURN", /* 63 */ "RECV", /* 64 */ "RECV_INIT", /* 65 */ "SEND_VAL", /* 66 */ "SEND_VAR", /* 67 */ "SEND_REF", /* 68 */ "NEW", /* 69 */ "INIT_NS_FCALL_BY_NAME", /* 70 */ "FREE", /* 71 */ "INIT_ARRAY", /* 72 */ "ADD_ARRAY_ELEMENT", /* 73 */ "INCLUDE_OR_EVAL", /* 74 */ "UNSET_VAR", /* 75 */ "UNSET_DIM", /* 76 */ "UNSET_OBJ", /* 77 */ "FE_RESET", /* 78 */ "FE_FETCH", /* 79 */ "EXIT", /* 80 */ "FETCH_R", /* 81 */ "FETCH_DIM_R", /* 82 */ "FETCH_OBJ_R", /* 83 */ "FETCH_W", /* 84 */ "FETCH_DIM_W", /* 85 */ "FETCH_OBJ_W", /* 86 */ "FETCH_RW", /* 87 */ "FETCH_DIM_RW", /* 88 */ "FETCH_OBJ_RW", /* 89 */ "FETCH_IS", /* 90 */ "FETCH_DIM_IS", /* 91 */ "FETCH_OBJ_IS", /* 92 */ "FETCH_FUNC_ARG", /* 93 */ "FETCH_DIM_FUNC_ARG", /* 94 */ "FETCH_OBJ_FUNC_ARG", /* 95 */ "FETCH_UNSET", /* 96 */ "FETCH_DIM_UNSET", /* 97 */ "FETCH_OBJ_UNSET", /* 98 */ "FETCH_DIM_TMP_VAR", /* 99 */ "FETCH_CONSTANT", /* 100 */ "GOTO", /* 101 */ "EXT_STMT", /* 102 */ "EXT_FCALL_BEGIN", /* 103 */ "EXT_FCALL_END", /* 104 */ "EXT_NOP", /* 105 */ "TICKS", /* 106 */ "SEND_VAR_NO_REF", /* 107 */ "CATCH", /* 108 */ "THROW", /* 109 */ "FETCH_CLASS", /* 110 */ "CLONE", /* 111 */ "UNDEF", /* 112 */ "INIT_METHOD_CALL", /* 113 */ "INIT_STATIC_METHOD_CALL", /* 114 */ "ISSET_ISEMPTY_VAR", /* 115 */ "ISSET_ISEMPTY_DIM_OBJ", /* 116 */ "UNDEF", /* 117 */ "UNDEF", /* 118 */ "UNDEF", /* 119 */ "UNDEF", /* 120 */ "UNDEF", /* 121 */ "UNDEF", /* 122 */ "UNDEF", /* 123 */ "UNDEF", /* 124 */ "UNDEF", /* 125 */ "UNDEF", /* 126 */ "UNDEF", /* 127 */ "UNDEF", /* 128 */ "UNDEF", /* 129 */ "UNDEF", /* 130 */ "UNDEF", /* 131 */ "UNDEF", /* 132 */ "PRE_INC_OBJ", /* 133 */ "PRE_DEC_OBJ", /* 134 */ "POST_INC_OBJ", /* 135 */ "POST_DEC_OBJ", /* 136 */ "ASSIGN_OBJ", /* 137 */ "OP_DATA", /* 138 */ "INSTANCEOF", /* 139 */ "DECLARE_CLASS", /* 140 */ "DECLARE_INHERITED_CLASS", /* 141 */ "DECLARE_FUNCTION", /* 142 */ "RAISE_ABSTRACT_ERROR", /* 143 */ "DECLARE_CONST", /* 144 */ "ADD_INTERFACE", /* 145 */ "DECLARE_INHERITED_CLASS_DELAYED", /* 146 */ "VERIFY_ABSTRACT_CLASS", /* 147 */ "ASSIGN_DIM", /* 148 */ "ISSET_ISEMPTY_PROP_OBJ", /* 149 */ "HANDLE_EXCEPTION", /* 150 */ "USER_OPCODE", /* 151 */ "UNDEF", /* 152 */ "JMP_SET", /* 153 */ "DECLARE_LAMBDA_FUNCTION" }; xcache-3.1.0/xcache/xc_const_string_opcodes_php5.4.h0000644000175000010010000000717612157744741020621 0ustar mOoNone/* size = 159 */ static const char *const xc_opcode_names[] = { /* 0 */ "NOP", /* 1 */ "ADD", /* 2 */ "SUB", /* 3 */ "MUL", /* 4 */ "DIV", /* 5 */ "MOD", /* 6 */ "SL", /* 7 */ "SR", /* 8 */ "CONCAT", /* 9 */ "BW_OR", /* 10 */ "BW_AND", /* 11 */ "BW_XOR", /* 12 */ "BW_NOT", /* 13 */ "BOOL_NOT", /* 14 */ "BOOL_XOR", /* 15 */ "IS_IDENTICAL", /* 16 */ "IS_NOT_IDENTICAL", /* 17 */ "IS_EQUAL", /* 18 */ "IS_NOT_EQUAL", /* 19 */ "IS_SMALLER", /* 20 */ "IS_SMALLER_OR_EQUAL", /* 21 */ "CAST", /* 22 */ "QM_ASSIGN", /* 23 */ "ASSIGN_ADD", /* 24 */ "ASSIGN_SUB", /* 25 */ "ASSIGN_MUL", /* 26 */ "ASSIGN_DIV", /* 27 */ "ASSIGN_MOD", /* 28 */ "ASSIGN_SL", /* 29 */ "ASSIGN_SR", /* 30 */ "ASSIGN_CONCAT", /* 31 */ "ASSIGN_BW_OR", /* 32 */ "ASSIGN_BW_AND", /* 33 */ "ASSIGN_BW_XOR", /* 34 */ "PRE_INC", /* 35 */ "PRE_DEC", /* 36 */ "POST_INC", /* 37 */ "POST_DEC", /* 38 */ "ASSIGN", /* 39 */ "ASSIGN_REF", /* 40 */ "ECHO", /* 41 */ "PRINT", /* 42 */ "JMP", /* 43 */ "JMPZ", /* 44 */ "JMPNZ", /* 45 */ "JMPZNZ", /* 46 */ "JMPZ_EX", /* 47 */ "JMPNZ_EX", /* 48 */ "CASE", /* 49 */ "SWITCH_FREE", /* 50 */ "BRK", /* 51 */ "CONT", /* 52 */ "BOOL", /* 53 */ "INIT_STRING", /* 54 */ "ADD_CHAR", /* 55 */ "ADD_STRING", /* 56 */ "ADD_VAR", /* 57 */ "BEGIN_SILENCE", /* 58 */ "END_SILENCE", /* 59 */ "INIT_FCALL_BY_NAME", /* 60 */ "DO_FCALL", /* 61 */ "DO_FCALL_BY_NAME", /* 62 */ "RETURN", /* 63 */ "RECV", /* 64 */ "RECV_INIT", /* 65 */ "SEND_VAL", /* 66 */ "SEND_VAR", /* 67 */ "SEND_REF", /* 68 */ "NEW", /* 69 */ "INIT_NS_FCALL_BY_NAME", /* 70 */ "FREE", /* 71 */ "INIT_ARRAY", /* 72 */ "ADD_ARRAY_ELEMENT", /* 73 */ "INCLUDE_OR_EVAL", /* 74 */ "UNSET_VAR", /* 75 */ "UNSET_DIM", /* 76 */ "UNSET_OBJ", /* 77 */ "FE_RESET", /* 78 */ "FE_FETCH", /* 79 */ "EXIT", /* 80 */ "FETCH_R", /* 81 */ "FETCH_DIM_R", /* 82 */ "FETCH_OBJ_R", /* 83 */ "FETCH_W", /* 84 */ "FETCH_DIM_W", /* 85 */ "FETCH_OBJ_W", /* 86 */ "FETCH_RW", /* 87 */ "FETCH_DIM_RW", /* 88 */ "FETCH_OBJ_RW", /* 89 */ "FETCH_IS", /* 90 */ "FETCH_DIM_IS", /* 91 */ "FETCH_OBJ_IS", /* 92 */ "FETCH_FUNC_ARG", /* 93 */ "FETCH_DIM_FUNC_ARG", /* 94 */ "FETCH_OBJ_FUNC_ARG", /* 95 */ "FETCH_UNSET", /* 96 */ "FETCH_DIM_UNSET", /* 97 */ "FETCH_OBJ_UNSET", /* 98 */ "FETCH_DIM_TMP_VAR", /* 99 */ "FETCH_CONSTANT", /* 100 */ "GOTO", /* 101 */ "EXT_STMT", /* 102 */ "EXT_FCALL_BEGIN", /* 103 */ "EXT_FCALL_END", /* 104 */ "EXT_NOP", /* 105 */ "TICKS", /* 106 */ "SEND_VAR_NO_REF", /* 107 */ "CATCH", /* 108 */ "THROW", /* 109 */ "FETCH_CLASS", /* 110 */ "CLONE", /* 111 */ "RETURN_BY_REF", /* 112 */ "INIT_METHOD_CALL", /* 113 */ "INIT_STATIC_METHOD_CALL", /* 114 */ "ISSET_ISEMPTY_VAR", /* 115 */ "ISSET_ISEMPTY_DIM_OBJ", /* 116 */ "UNDEF", /* 117 */ "UNDEF", /* 118 */ "UNDEF", /* 119 */ "UNDEF", /* 120 */ "UNDEF", /* 121 */ "UNDEF", /* 122 */ "UNDEF", /* 123 */ "UNDEF", /* 124 */ "UNDEF", /* 125 */ "UNDEF", /* 126 */ "UNDEF", /* 127 */ "UNDEF", /* 128 */ "UNDEF", /* 129 */ "UNDEF", /* 130 */ "UNDEF", /* 131 */ "UNDEF", /* 132 */ "PRE_INC_OBJ", /* 133 */ "PRE_DEC_OBJ", /* 134 */ "POST_INC_OBJ", /* 135 */ "POST_DEC_OBJ", /* 136 */ "ASSIGN_OBJ", /* 137 */ "OP_DATA", /* 138 */ "INSTANCEOF", /* 139 */ "DECLARE_CLASS", /* 140 */ "DECLARE_INHERITED_CLASS", /* 141 */ "DECLARE_FUNCTION", /* 142 */ "RAISE_ABSTRACT_ERROR", /* 143 */ "DECLARE_CONST", /* 144 */ "ADD_INTERFACE", /* 145 */ "DECLARE_INHERITED_CLASS_DELAYED", /* 146 */ "VERIFY_ABSTRACT_CLASS", /* 147 */ "ASSIGN_DIM", /* 148 */ "ISSET_ISEMPTY_PROP_OBJ", /* 149 */ "HANDLE_EXCEPTION", /* 150 */ "USER_OPCODE", /* 151 */ "UNDEF", /* 152 */ "JMP_SET", /* 153 */ "DECLARE_LAMBDA_FUNCTION", /* 154 */ "ADD_TRAIT", /* 155 */ "BIND_TRAITS", /* 156 */ "SEPARATE", /* 157 */ "QM_ASSIGN_VAR", /* 158 */ "JMP_SET_VAR" }; xcache-3.1.0/xcache/xc_const_string_opcodes_php5.5.h0000644000175000010010000000737312157744741020621 0ustar mOoNone/* size = 164 */ static const char *const xc_opcode_names[] = { /* 0 */ "NOP", /* 1 */ "ADD", /* 2 */ "SUB", /* 3 */ "MUL", /* 4 */ "DIV", /* 5 */ "MOD", /* 6 */ "SL", /* 7 */ "SR", /* 8 */ "CONCAT", /* 9 */ "BW_OR", /* 10 */ "BW_AND", /* 11 */ "BW_XOR", /* 12 */ "BW_NOT", /* 13 */ "BOOL_NOT", /* 14 */ "BOOL_XOR", /* 15 */ "IS_IDENTICAL", /* 16 */ "IS_NOT_IDENTICAL", /* 17 */ "IS_EQUAL", /* 18 */ "IS_NOT_EQUAL", /* 19 */ "IS_SMALLER", /* 20 */ "IS_SMALLER_OR_EQUAL", /* 21 */ "CAST", /* 22 */ "QM_ASSIGN", /* 23 */ "ASSIGN_ADD", /* 24 */ "ASSIGN_SUB", /* 25 */ "ASSIGN_MUL", /* 26 */ "ASSIGN_DIV", /* 27 */ "ASSIGN_MOD", /* 28 */ "ASSIGN_SL", /* 29 */ "ASSIGN_SR", /* 30 */ "ASSIGN_CONCAT", /* 31 */ "ASSIGN_BW_OR", /* 32 */ "ASSIGN_BW_AND", /* 33 */ "ASSIGN_BW_XOR", /* 34 */ "PRE_INC", /* 35 */ "PRE_DEC", /* 36 */ "POST_INC", /* 37 */ "POST_DEC", /* 38 */ "ASSIGN", /* 39 */ "ASSIGN_REF", /* 40 */ "ECHO", /* 41 */ "PRINT", /* 42 */ "JMP", /* 43 */ "JMPZ", /* 44 */ "JMPNZ", /* 45 */ "JMPZNZ", /* 46 */ "JMPZ_EX", /* 47 */ "JMPNZ_EX", /* 48 */ "CASE", /* 49 */ "SWITCH_FREE", /* 50 */ "BRK", /* 51 */ "CONT", /* 52 */ "BOOL", /* 53 */ "INIT_STRING", /* 54 */ "ADD_CHAR", /* 55 */ "ADD_STRING", /* 56 */ "ADD_VAR", /* 57 */ "BEGIN_SILENCE", /* 58 */ "END_SILENCE", /* 59 */ "INIT_FCALL_BY_NAME", /* 60 */ "DO_FCALL", /* 61 */ "DO_FCALL_BY_NAME", /* 62 */ "RETURN", /* 63 */ "RECV", /* 64 */ "RECV_INIT", /* 65 */ "SEND_VAL", /* 66 */ "SEND_VAR", /* 67 */ "SEND_REF", /* 68 */ "NEW", /* 69 */ "INIT_NS_FCALL_BY_NAME", /* 70 */ "FREE", /* 71 */ "INIT_ARRAY", /* 72 */ "ADD_ARRAY_ELEMENT", /* 73 */ "INCLUDE_OR_EVAL", /* 74 */ "UNSET_VAR", /* 75 */ "UNSET_DIM", /* 76 */ "UNSET_OBJ", /* 77 */ "FE_RESET", /* 78 */ "FE_FETCH", /* 79 */ "EXIT", /* 80 */ "FETCH_R", /* 81 */ "FETCH_DIM_R", /* 82 */ "FETCH_OBJ_R", /* 83 */ "FETCH_W", /* 84 */ "FETCH_DIM_W", /* 85 */ "FETCH_OBJ_W", /* 86 */ "FETCH_RW", /* 87 */ "FETCH_DIM_RW", /* 88 */ "FETCH_OBJ_RW", /* 89 */ "FETCH_IS", /* 90 */ "FETCH_DIM_IS", /* 91 */ "FETCH_OBJ_IS", /* 92 */ "FETCH_FUNC_ARG", /* 93 */ "FETCH_DIM_FUNC_ARG", /* 94 */ "FETCH_OBJ_FUNC_ARG", /* 95 */ "FETCH_UNSET", /* 96 */ "FETCH_DIM_UNSET", /* 97 */ "FETCH_OBJ_UNSET", /* 98 */ "FETCH_DIM_TMP_VAR", /* 99 */ "FETCH_CONSTANT", /* 100 */ "GOTO", /* 101 */ "EXT_STMT", /* 102 */ "EXT_FCALL_BEGIN", /* 103 */ "EXT_FCALL_END", /* 104 */ "EXT_NOP", /* 105 */ "TICKS", /* 106 */ "SEND_VAR_NO_REF", /* 107 */ "CATCH", /* 108 */ "THROW", /* 109 */ "FETCH_CLASS", /* 110 */ "CLONE", /* 111 */ "RETURN_BY_REF", /* 112 */ "INIT_METHOD_CALL", /* 113 */ "INIT_STATIC_METHOD_CALL", /* 114 */ "ISSET_ISEMPTY_VAR", /* 115 */ "ISSET_ISEMPTY_DIM_OBJ", /* 116 */ "UNDEF", /* 117 */ "UNDEF", /* 118 */ "UNDEF", /* 119 */ "UNDEF", /* 120 */ "UNDEF", /* 121 */ "UNDEF", /* 122 */ "UNDEF", /* 123 */ "UNDEF", /* 124 */ "UNDEF", /* 125 */ "UNDEF", /* 126 */ "UNDEF", /* 127 */ "UNDEF", /* 128 */ "UNDEF", /* 129 */ "UNDEF", /* 130 */ "UNDEF", /* 131 */ "UNDEF", /* 132 */ "PRE_INC_OBJ", /* 133 */ "PRE_DEC_OBJ", /* 134 */ "POST_INC_OBJ", /* 135 */ "POST_DEC_OBJ", /* 136 */ "ASSIGN_OBJ", /* 137 */ "OP_DATA", /* 138 */ "INSTANCEOF", /* 139 */ "DECLARE_CLASS", /* 140 */ "DECLARE_INHERITED_CLASS", /* 141 */ "DECLARE_FUNCTION", /* 142 */ "RAISE_ABSTRACT_ERROR", /* 143 */ "DECLARE_CONST", /* 144 */ "ADD_INTERFACE", /* 145 */ "DECLARE_INHERITED_CLASS_DELAYED", /* 146 */ "VERIFY_ABSTRACT_CLASS", /* 147 */ "ASSIGN_DIM", /* 148 */ "ISSET_ISEMPTY_PROP_OBJ", /* 149 */ "HANDLE_EXCEPTION", /* 150 */ "USER_OPCODE", /* 151 */ "UNDEF", /* 152 */ "JMP_SET", /* 153 */ "DECLARE_LAMBDA_FUNCTION", /* 154 */ "ADD_TRAIT", /* 155 */ "BIND_TRAITS", /* 156 */ "SEPARATE", /* 157 */ "QM_ASSIGN_VAR", /* 158 */ "JMP_SET_VAR", /* 159 */ "DISCARD_EXCEPTION", /* 160 */ "YIELD", /* 161 */ "GENERATOR_RETURN", /* 162 */ "FAST_CALL", /* 163 */ "FAST_RET" }; xcache-3.1.0/xcache/xc_const_string_opcodes_php6.x.h0000644000175000010010000000717612157744741020726 0ustar mOoNone/* size = 159 */ static const char *const xc_opcode_names[] = { /* 0 */ "NOP", /* 1 */ "ADD", /* 2 */ "SUB", /* 3 */ "MUL", /* 4 */ "DIV", /* 5 */ "MOD", /* 6 */ "SL", /* 7 */ "SR", /* 8 */ "CONCAT", /* 9 */ "BW_OR", /* 10 */ "BW_AND", /* 11 */ "BW_XOR", /* 12 */ "BW_NOT", /* 13 */ "BOOL_NOT", /* 14 */ "BOOL_XOR", /* 15 */ "IS_IDENTICAL", /* 16 */ "IS_NOT_IDENTICAL", /* 17 */ "IS_EQUAL", /* 18 */ "IS_NOT_EQUAL", /* 19 */ "IS_SMALLER", /* 20 */ "IS_SMALLER_OR_EQUAL", /* 21 */ "CAST", /* 22 */ "QM_ASSIGN", /* 23 */ "ASSIGN_ADD", /* 24 */ "ASSIGN_SUB", /* 25 */ "ASSIGN_MUL", /* 26 */ "ASSIGN_DIV", /* 27 */ "ASSIGN_MOD", /* 28 */ "ASSIGN_SL", /* 29 */ "ASSIGN_SR", /* 30 */ "ASSIGN_CONCAT", /* 31 */ "ASSIGN_BW_OR", /* 32 */ "ASSIGN_BW_AND", /* 33 */ "ASSIGN_BW_XOR", /* 34 */ "PRE_INC", /* 35 */ "PRE_DEC", /* 36 */ "POST_INC", /* 37 */ "POST_DEC", /* 38 */ "ASSIGN", /* 39 */ "ASSIGN_REF", /* 40 */ "ECHO", /* 41 */ "PRINT", /* 42 */ "JMP", /* 43 */ "JMPZ", /* 44 */ "JMPNZ", /* 45 */ "JMPZNZ", /* 46 */ "JMPZ_EX", /* 47 */ "JMPNZ_EX", /* 48 */ "CASE", /* 49 */ "SWITCH_FREE", /* 50 */ "BRK", /* 51 */ "CONT", /* 52 */ "BOOL", /* 53 */ "INIT_STRING", /* 54 */ "ADD_CHAR", /* 55 */ "ADD_STRING", /* 56 */ "ADD_VAR", /* 57 */ "BEGIN_SILENCE", /* 58 */ "END_SILENCE", /* 59 */ "INIT_FCALL_BY_NAME", /* 60 */ "DO_FCALL", /* 61 */ "DO_FCALL_BY_NAME", /* 62 */ "RETURN", /* 63 */ "RECV", /* 64 */ "RECV_INIT", /* 65 */ "SEND_VAL", /* 66 */ "SEND_VAR", /* 67 */ "SEND_REF", /* 68 */ "NEW", /* 69 */ "INIT_NS_FCALL_BY_NAME", /* 70 */ "FREE", /* 71 */ "INIT_ARRAY", /* 72 */ "ADD_ARRAY_ELEMENT", /* 73 */ "INCLUDE_OR_EVAL", /* 74 */ "UNSET_VAR", /* 75 */ "UNSET_DIM", /* 76 */ "UNSET_OBJ", /* 77 */ "FE_RESET", /* 78 */ "FE_FETCH", /* 79 */ "EXIT", /* 80 */ "FETCH_R", /* 81 */ "FETCH_DIM_R", /* 82 */ "FETCH_OBJ_R", /* 83 */ "FETCH_W", /* 84 */ "FETCH_DIM_W", /* 85 */ "FETCH_OBJ_W", /* 86 */ "FETCH_RW", /* 87 */ "FETCH_DIM_RW", /* 88 */ "FETCH_OBJ_RW", /* 89 */ "FETCH_IS", /* 90 */ "FETCH_DIM_IS", /* 91 */ "FETCH_OBJ_IS", /* 92 */ "FETCH_FUNC_ARG", /* 93 */ "FETCH_DIM_FUNC_ARG", /* 94 */ "FETCH_OBJ_FUNC_ARG", /* 95 */ "FETCH_UNSET", /* 96 */ "FETCH_DIM_UNSET", /* 97 */ "FETCH_OBJ_UNSET", /* 98 */ "FETCH_DIM_TMP_VAR", /* 99 */ "FETCH_CONSTANT", /* 100 */ "GOTO", /* 101 */ "EXT_STMT", /* 102 */ "EXT_FCALL_BEGIN", /* 103 */ "EXT_FCALL_END", /* 104 */ "EXT_NOP", /* 105 */ "TICKS", /* 106 */ "SEND_VAR_NO_REF", /* 107 */ "CATCH", /* 108 */ "THROW", /* 109 */ "FETCH_CLASS", /* 110 */ "CLONE", /* 111 */ "RETURN_BY_REF", /* 112 */ "INIT_METHOD_CALL", /* 113 */ "INIT_STATIC_METHOD_CALL", /* 114 */ "ISSET_ISEMPTY_VAR", /* 115 */ "ISSET_ISEMPTY_DIM_OBJ", /* 116 */ "UNDEF", /* 117 */ "UNDEF", /* 118 */ "UNDEF", /* 119 */ "UNDEF", /* 120 */ "UNDEF", /* 121 */ "UNDEF", /* 122 */ "UNDEF", /* 123 */ "UNDEF", /* 124 */ "UNDEF", /* 125 */ "UNDEF", /* 126 */ "UNDEF", /* 127 */ "UNDEF", /* 128 */ "UNDEF", /* 129 */ "UNDEF", /* 130 */ "UNDEF", /* 131 */ "UNDEF", /* 132 */ "PRE_INC_OBJ", /* 133 */ "PRE_DEC_OBJ", /* 134 */ "POST_INC_OBJ", /* 135 */ "POST_DEC_OBJ", /* 136 */ "ASSIGN_OBJ", /* 137 */ "OP_DATA", /* 138 */ "INSTANCEOF", /* 139 */ "DECLARE_CLASS", /* 140 */ "DECLARE_INHERITED_CLASS", /* 141 */ "DECLARE_FUNCTION", /* 142 */ "RAISE_ABSTRACT_ERROR", /* 143 */ "DECLARE_CONST", /* 144 */ "ADD_INTERFACE", /* 145 */ "DECLARE_INHERITED_CLASS_DELAYED", /* 146 */ "VERIFY_ABSTRACT_CLASS", /* 147 */ "ASSIGN_DIM", /* 148 */ "ISSET_ISEMPTY_PROP_OBJ", /* 149 */ "HANDLE_EXCEPTION", /* 150 */ "USER_OPCODE", /* 151 */ "UNDEF", /* 152 */ "JMP_SET", /* 153 */ "DECLARE_LAMBDA_FUNCTION", /* 154 */ "ADD_TRAIT", /* 155 */ "BIND_TRAITS", /* 156 */ "SEPARATE", /* 157 */ "QM_ASSIGN_VAR", /* 158 */ "JMP_SET_VAR" }; xcache-3.1.0/xcache/xc_extension.c0000644000175000010010000000342512157744741015273 0ustar mOoNone #include "xc_extension.h" #include "xcache.h" #include "util/xc_trace.h" int xcache_zend_extension_add(zend_extension *new_extension, zend_bool prepend) /* {{{ */ { zend_extension extension; extension = *new_extension; extension.handle = 0; zend_extension_dispatch_message(ZEND_EXTMSG_NEW_EXTENSION, &extension); if (prepend) { zend_llist_prepend_element(&zend_extensions, &extension); } else { zend_llist_add_element(&zend_extensions, &extension); } TRACE("%s", "registered"); return SUCCESS; } /* }}} */ static int xc_ptr_compare_func(void *p1, void *p2) /* {{{ */ { return p1 == p2; } /* }}} */ static int xc_zend_extension_remove(zend_extension *extension) /* {{{ */ { llist_dtor_func_t dtor; assert(extension); dtor = zend_extensions.dtor; /* avoid dtor */ zend_extensions.dtor = NULL; zend_llist_del_element(&zend_extensions, extension, xc_ptr_compare_func); zend_extensions.dtor = dtor; return SUCCESS; } /* }}} */ int xcache_zend_extension_remove(zend_extension *extension) /* {{{ */ { zend_extension *ext = zend_get_extension(extension->name); if (!ext) { return FAILURE; } if (ext->shutdown) { ext->shutdown(ext); } xc_zend_extension_remove(ext); return SUCCESS; } /* }}} */ void xcache_llist_prepend(zend_llist *l, zend_llist_element *element) /* {{{ */ { element->next = l->head; element->prev = NULL; if (l->head) { l->head->prev = element; } else { l->tail = element; } l->head = element; ++l->count; } /* }}} */ void xcache_llist_unlink(zend_llist *l, zend_llist_element *element) /* {{{ */ { if ((element)->prev) { (element)->prev->next = (element)->next; } else { (l)->head = (element)->next; } if ((element)->next) { (element)->next->prev = (element)->prev; } else { (l)->tail = (element)->prev; } --l->count; } /* }}} */ xcache-3.1.0/xcache/xc_extension.h0000644000175000010010000000110212157744741015266 0ustar mOoNone#ifndef XC_EXTENSION_H_9885D3A6DE7C469D13E34AF331E02BB8 #define XC_EXTENSION_H_9885D3A6DE7C469D13E34AF331E02BB8 #if _MSC_VER > 1000 #pragma once #endif /* _MSC_VER > 1000 */ #include "util/xc_stack.h" #include "zend_extensions.h" int xcache_zend_extension_add(zend_extension *new_extension, zend_bool prepend); int xcache_zend_extension_remove(zend_extension *extension); void xcache_llist_prepend(zend_llist *l, zend_llist_element *element); void xcache_llist_unlink(zend_llist *l, zend_llist_element *element); #endif /* XC_EXTENSION_H_9885D3A6DE7C469D13E34AF331E02BB8 */ xcache-3.1.0/xcache/xc_ini.c0000644000175000010010000000113612157744741014033 0ustar mOoNone#include "xc_ini.h" PHP_INI_MH(xcache_OnUpdateDummy) { return SUCCESS; } PHP_INI_MH(xcache_OnUpdateULong) { zend_ulong *p = (zend_ulong *) mh_arg1; *p = (zend_ulong) atoi(new_value); return SUCCESS; } PHP_INI_MH(xcache_OnUpdateBool) { zend_bool *p = (zend_bool *)mh_arg1; if (strncasecmp("on", new_value, sizeof("on"))) { *p = (zend_bool) atoi(new_value); } else { *p = (zend_bool) 1; } return SUCCESS; } PHP_INI_MH(xcache_OnUpdateString) { char **p = (char**)mh_arg1; if (*p) { pefree(*p, 1); } *p = pemalloc(strlen(new_value) + 1, 1); strcpy(*p, new_value); return SUCCESS; } xcache-3.1.0/xcache/xc_ini.h0000644000175000010010000000071112206607320014020 0ustar mOoNone#ifndef XC_INI_H_E208B8E597E7FAD950D249BE9C6B6F53 #define XC_INI_H_E208B8E597E7FAD950D249BE9C6B6F53 #if _MSC_VER > 1000 #pragma once #endif /* _MSC_VER > 1000 */ #include "php.h" #include "php_ini.h" PHP_INI_MH(xcache_OnUpdateDummy); PHP_INI_MH(xcache_OnUpdateULong); PHP_INI_MH(xcache_OnUpdateBool); PHP_INI_MH(xcache_OnUpdateString); #ifndef ZEND_ENGINE_2 #define OnUpdateLong OnUpdateInt #endif #endif /* XC_INI_H_E208B8E597E7FAD950D249BE9C6B6F53 */ xcache-3.1.0/xcache/xc_malloc.c0000644000175000010010000001257512220455233014516 0ustar mOoNone#define XC_SHM_IMPL _xc_malloc_shm_t #define _xc_allocator_t _xc_allocator_malloc_t #include #include #include #include "xc_shm.h" #include "xc_allocator.h" #ifndef TEST #include "xcache.h" #endif #include "util/xc_align.h" struct _xc_allocator_malloc_t { const xc_allocator_vtable_t *vtable; xc_shm_t *shm; xc_memsize_t size; xc_memsize_t avail; /* total free */ }; /* {{{ _xc_malloc_shm_t */ struct _xc_malloc_shm_t { xc_shm_handlers_t *handlers; xc_shmsize_t size; xc_shmsize_t memoffset; #ifndef TEST HashTable blocks; #endif }; /* }}} */ #ifndef TEST # define CHECK(x, e) do { if ((x) == NULL) { zend_error(E_ERROR, "XCache: " e); goto err; } } while (0) #else # define CHECK(x, e) do { if ((x) == NULL) { fprintf(stderr, "%s\n", "XCache: " e); goto err; } } while (0) #endif static void *xc_add_to_blocks(xc_allocator_t *allocator, void *p, size_t size) /* {{{ */ { if (p) { allocator->avail -= size; #ifndef TEST zend_hash_add(&allocator->shm->blocks, (void *) &p, sizeof(p), (void *) &size, sizeof(size), NULL); #endif } return p; } /* }}} */ static void xc_del_from_blocks(xc_allocator_t *allocator, void *p) /* {{{ */ { #ifdef TEST /* TODO: allocator->avail += size; */ #else zend_hash_del(&allocator->shm->blocks, (void *) &p, sizeof(p)); #endif } /* }}} */ static XC_ALLOCATOR_MALLOC(xc_allocator_malloc_malloc) /* {{{ */ { if (allocator->avail < size) { return NULL; } return xc_add_to_blocks(allocator, malloc(size), size); } /* }}} */ static XC_ALLOCATOR_FREE(xc_allocator_malloc_free) /* {{{ return block size freed */ { xc_del_from_blocks(allocator, (void *) p); free((void *) p); return 0; } /* }}} */ static XC_ALLOCATOR_CALLOC(xc_allocator_malloc_calloc) /* {{{ */ { if (allocator->avail < size) { return NULL; } return xc_add_to_blocks(allocator, calloc(memb, size), size); } /* }}} */ static XC_ALLOCATOR_REALLOC(xc_allocator_malloc_realloc) /* {{{ */ { return xc_add_to_blocks(allocator, realloc((void *) p, size), size); } /* }}} */ static XC_ALLOCATOR_AVAIL(xc_allocator_malloc_avail) /* {{{ */ { return allocator->avail; } /* }}} */ static XC_ALLOCATOR_SIZE(xc_allocator_malloc_size) /* {{{ */ { return allocator->size; } /* }}} */ static XC_ALLOCATOR_FREEBLOCK_FIRST(xc_allocator_malloc_freeblock_first) /* {{{ */ { return (void *) -1; } /* }}} */ static XC_ALLOCATOR_FREEBLOCK_NEXT(xc_allocator_malloc_freeblock_next) /* {{{ */ { return NULL; } /* }}} */ static XC_ALLOCATOR_BLOCK_SIZE(xc_allocator_malloc_block_size) /* {{{ */ { return 0; } /* }}} */ static XC_ALLOCATOR_BLOCK_OFFSET(xc_allocator_malloc_block_offset) /* {{{ */ { return 0; } /* }}} */ static XC_ALLOCATOR_INIT(xc_allocator_malloc_init) /* {{{ */ { #define MINSIZE (ALIGN(sizeof(xc_allocator_t))) /* requires at least the header and 1 tail block */ if (size < MINSIZE) { fprintf(stderr, "xc_allocator_malloc_init requires %lu bytes at least\n", (unsigned long) MINSIZE); return NULL; } allocator->shm = shm; allocator->size = size; allocator->avail = size - MINSIZE; #undef MINSIZE return allocator; } /* }}} */ static XC_ALLOCATOR_DESTROY(xc_allocator_malloc_destroy) /* {{{ */ { } /* }}} */ static XC_SHM_CAN_READONLY(xc_malloc_can_readonly) /* {{{ */ { return 0; } /* }}} */ static XC_SHM_IS_READWRITE(xc_malloc_is_readwrite) /* {{{ */ { #ifndef TEST HashPosition pos; size_t *psize; char **ptr; zend_hash_internal_pointer_reset_ex(&shm->blocks, &pos); while (zend_hash_get_current_data_ex(&shm->blocks, (void **) &psize, &pos) == SUCCESS) { zend_hash_get_current_key_ex(&shm->blocks, (void *) &ptr, NULL, NULL, 0, &pos); if ((char *) p >= *ptr && (char *) p < *ptr + *psize) { return 1; } zend_hash_move_forward_ex(&shm->blocks, &pos); } #endif return 0; } /* }}} */ static XC_SHM_IS_READONLY(xc_malloc_is_readonly) /* {{{ */ { return 0; } /* }}} */ static XC_SHM_TO_READWRITE(xc_malloc_to_readwrite) /* {{{ */ { return p; } /* }}} */ static XC_SHM_TO_READONLY(xc_malloc_to_readonly) /* {{{ */ { return p; } /* }}} */ static XC_SHM_DESTROY(xc_malloc_destroy) /* {{{ */ { #ifndef TEST zend_hash_destroy(&shm->blocks); #endif free(shm); return; } /* }}} */ static XC_SHM_INIT(xc_malloc_init) /* {{{ */ { xc_shm_t *shm; CHECK(shm = calloc(1, sizeof(xc_shm_t)), "shm OOM"); shm->size = size; #ifndef TEST zend_hash_init(&shm->blocks, 64, NULL, NULL, 1); #endif return shm; err: return NULL; } /* }}} */ static XC_SHM_MEMINIT(xc_malloc_meminit) /* {{{ */ { void *mem; if (shm->memoffset + size > shm->size) { #ifndef TEST zend_error(E_ERROR, "XCache: internal error at %s#%d", __FILE__, __LINE__); #endif return NULL; } shm->memoffset += size; CHECK(mem = calloc(1, size), "mem OOM"); return mem; err: return NULL; } /* }}} */ static XC_SHM_MEMDESTROY(xc_malloc_memdestroy) /* {{{ */ { free(mem); } /* }}} */ static xc_allocator_vtable_t xc_allocator_malloc_vtable = XC_ALLOCATOR_VTABLE(allocator_malloc); #ifndef TEST static xc_shm_handlers_t xc_shm_malloc_handlers = XC_SHM_HANDLERS(malloc); #endif void xc_allocator_malloc_register() /* {{{ */ { if (xc_allocator_register("malloc", &xc_allocator_malloc_vtable) == 0) { #ifndef TEST zend_error(E_ERROR, "XCache: failed to register malloc mem_scheme"); #endif } } /* }}} */ #ifndef TEST void xc_shm_malloc_register() /* {{{ */ { if (xc_shm_scheme_register("malloc", &xc_shm_malloc_handlers) == 0) { zend_error(E_ERROR, "XCache: failed to register malloc shm_scheme"); } } /* }}} */ #endif xcache-3.1.0/xcache/xc_mutex.c0000644000175000010010000002031112213477010014373 0ustar mOoNone#include "xc_mutex.h" #include "xcache.h" #include #include #include #ifdef ZEND_WIN32 # include #else # include # include # include #endif /* {{{ detect what type of mutex is needed */ #ifdef ZTS # define XC_MUTEX_NEED_TS #endif #ifdef HAVE_FORK # define XC_MUTEX_NEED_INTERPROCESS #endif #if defined(XC_MUTEX_NEED_TS) && defined(XC_MUTEX_NEED_INTERPROCESS) /* the check is not even needed for non-threaded env */ # define XC_MUTEX_HAVE_INTERPROCESS_SWITCH #endif /* }}} */ /* {{{ detect which mutex is needed */ #if defined(XC_MUTEX_NEED_TS) && defined(XC_MUTEX_NEED_INTERPROCESS) # ifdef PTHREADS # define XC_MUTEX_USE_PTHREAD # ifndef _POSIX_THREAD_PROCESS_SHARED # define XC_MUTEX_USE_FCNTL # endif # else # define XC_MUTEX_USE_TSRM # define XC_MUTEX_USE_FCNTL # endif #elif defined(XC_MUTEX_NEED_TS) # define XC_MUTEX_USE_TSRM #elif defined(XC_MUTEX_NEED_INTERPROCESS) # define XC_MUTEX_USE_FCNTL #else # define XC_MUTEX_USE_NOOP #endif /* }}} */ /* {{{ fcntl mutex impl */ #ifdef XC_MUTEX_USE_FCNTL #ifndef ZEND_WIN32 typedef int HANDLE; # ifndef INVALID_HANDLE_VALUE # define INVALID_HANDLE_VALUE -1 # endif #else # define close(h) CloseHandle(h) # define open(filename, mode, permission) CreateFile(filename, \ GENERIC_READ | GENERIC_WRITE, \ FILE_SHARE_READ | FILE_SHARE_WRITE, \ NULL, \ OPEN_ALWAYS, \ FILE_ATTRIBUTE_NORMAL, \ NULL) #endif typedef struct { HANDLE fd; #ifdef __CYGWIN__ /* store the path for unlink() later */ char *pathname; #endif } xc_fcntl_mutex_t; #ifndef ZEND_WIN32 # define LCK_WR F_WRLCK # define LCK_RD F_RDLCK # define LCK_UN F_UNLCK # define LCK_NB 0 static inline int dolock(xc_fcntl_mutex_t *fcntl_mutex, int type) { int ret; struct flock lock; lock.l_type = type; lock.l_start = 0; lock.l_whence = SEEK_SET; lock.l_len = 1; lock.l_pid = 0; do { ret = fcntl(fcntl_mutex->fd, F_SETLKW, &lock); } while (ret < 0 && errno == EINTR); return ret; } #else # include # include # include # include # include # undef errno # define errno GetLastError() # define getuid() 0 # define LCK_WR LOCKFILE_EXCLUSIVE_LOCK # define LCK_RD 0 # define LCK_UN 0 # define LCK_NB LOCKFILE_FAIL_IMMEDIATELY static inline int dolock(xc_fcntl_mutex_t *fcntl_mutex, int type) { static OVERLAPPED offset = {0, 0, 0, 0, NULL}; if (type == LCK_UN) { return UnlockFileEx(fcntl_mutex->fd, 0, 1, 0, &offset); } else { return LockFileEx(fcntl_mutex->fd, type, 0, 1, 0, &offset); } } #endif /* }}} */ static zend_bool xc_fcntl_init(xc_fcntl_mutex_t *fcntl_mutex, const char *pathname) /* {{{ */ { HANDLE fd; int size; char *myname; if (pathname == NULL) { static int instanceId = 0; const char default_tmpdir[] = { DEFAULT_SLASH, 't', 'm', 'p', '\0' }; const char *tmpdir; tmpdir = getenv("TEMP"); if (!tmpdir) { tmpdir = getenv("TMP"); if (!tmpdir) { tmpdir = default_tmpdir; } } size = strlen(tmpdir) + sizeof("/.xcache.mutex") - 1 + 3 * 10 + 100; myname = malloc(size); snprintf(myname, size - 1, "%s%c.xcache.%d.%d.%d.mutex", tmpdir, DEFAULT_SLASH, (int) getuid(), (int) getpid(), ++instanceId); pathname = myname; } else { myname = NULL; } fd = open(pathname, O_RDWR|O_CREAT, 0666); if (fd != INVALID_HANDLE_VALUE) { fcntl_mutex->fd = fd; #ifdef __CYGWIN__ size = strlen(pathname) + 1; fcntl_mutex->pathname = malloc(size); memcpy(fcntl_mutex->pathname, pathname, size); #else unlink(pathname); #endif } else { zend_error(E_ERROR, "xc_fcntl_create: open(%s, O_RDWR|O_CREAT, 0666) failed:", pathname); fcntl_mutex = NULL; } if (myname) { free(myname); } return fcntl_mutex ? 1 : 0; } /* }}} */ static void xc_fcntl_destroy(xc_fcntl_mutex_t *fcntl_mutex) /* {{{ */ { close(fcntl_mutex->fd); #ifdef __CYGWIN__ unlink(fcntl_mutex->pathname); free(fcntl_mutex->pathname); #endif } /* }}} */ static void xc_fcntl_mutex(xc_fcntl_mutex_t *fcntl_mutex) /* {{{ */ { if (dolock(fcntl_mutex, LCK_WR) < 0) { zend_error(E_ERROR, "xc_fcntl_mutex failed errno:%d", errno); } } /* }}} */ static void xc_fcntl_rdlock(xc_fcntl_mutex_t *fcntl_mutex) /* {{{ */ { if (dolock(fcntl_mutex, LCK_RD) < 0) { zend_error(E_ERROR, "xc_fcntl_mutex failed errno:%d", errno); } } /* }}} */ static void xc_fcntl_unlock(xc_fcntl_mutex_t *fcntl_mutex) /* {{{ */ { if (dolock(fcntl_mutex, LCK_UN) < 0) { zend_error(E_ERROR, "xc_fcntl_unlock failed errno:%d", errno); } } /* }}} */ #endif /* XC_MUTEX_USE_FCNTL */ struct _xc_mutex_t { #ifdef XC_MUTEX_USE_NOOP int dummy; #endif #ifdef XC_MUTEX_HAVE_INTERPROCESS_SWITCH zend_bool want_inter_process; /* whether the lock is created for inter process usage */ #endif zend_bool shared; /* shared, or locally allocated */ #ifdef XC_MUTEX_USE_TSRM MUTEX_T tsrm_mutex; #endif #ifdef XC_MUTEX_USE_PTHREAD pthread_mutex_t pthread_mutex; #endif #ifdef XC_MUTEX_USE_FCNTL xc_fcntl_mutex_t fcntl_mutex; #endif #ifndef NDEBUG zend_bool locked; #endif }; #ifdef XC_MUTEX_HAVE_INTERPROCESS_SWITCH # define xc_want_inter_process() (mutex->want_inter_process) #elif defined(HAVE_FORK) # define xc_want_inter_process() 1 #else # define xc_want_inter_process() 0 #endif size_t xc_mutex_size(void) /* {{{ */ { return sizeof(xc_mutex_t); } /* }}} */ xc_mutex_t *xc_mutex_init(xc_mutex_t *const shared_mutex, const char *pathname, unsigned char want_inter_process) /* {{{ */ { xc_mutex_t *mutex = NULL; #ifndef HAVE_FORK want_inter_process = 0; #endif /* if interprocessed is needed, shared_mutex is required to be a pre-allocated memory on shm * this function can always return non-shared memory if necessary despite shared memory is given */ /* when inter-process is wanted, pthread lives in shm */ #ifdef XC_MUTEX_USE_PTHREAD if (want_inter_process) { assert(shared_mutex); mutex = shared_mutex; mutex->shared = 1; } else #endif { /* all other mutex assumed live locally */ mutex = calloc(1, sizeof(*mutex)); mutex->shared = 0; #ifdef XC_MUTEX_HAVE_INTERPROCESS_SWITCH mutex->want_inter_process = want_inter_process; #endif } #ifdef XC_MUTEX_USE_PTHREAD { /* If you see mutex leak using valgrind, see xc_mutex_destroy function */ pthread_mutexattr_t psharedm; pthread_mutexattr_init(&psharedm); pthread_mutexattr_setpshared(&psharedm, xc_want_inter_process() ? PTHREAD_PROCESS_PRIVATE : PTHREAD_PROCESS_SHARED); pthread_mutex_init(&mutex->pthread_mutex, &psharedm); } #endif #ifdef XC_MUTEX_USE_TSRM mutex->tsrm_mutex = tsrm_mutex_alloc(); #endif #ifdef XC_MUTEX_USE_FCNTL if (xc_want_inter_process()) { xc_fcntl_init(&mutex->fcntl_mutex, pathname); } #endif #ifndef NDEBUG mutex->locked = 0; #endif return mutex; } /* }}} */ void xc_mutex_destroy(xc_mutex_t *mutex) /* {{{ */ { assert(mutex); /* intended to not destroy mutex when mutex is shared between process */ if (!mutex->shared) { #ifdef XC_MUTEX_USE_PTHREAD pthread_mutex_destroy(&mutex->pthread_mutex); #endif #ifdef XC_MUTEX_USE_TSRM tsrm_mutex_free(mutex->tsrm_mutex); #endif } #ifdef XC_MUTEX_USE_FCNTL if (xc_want_inter_process()) { xc_fcntl_destroy(&mutex->fcntl_mutex); } #endif if (!mutex->shared) { free(mutex); } } /* }}} */ void xc_mutex_lock(xc_mutex_t *mutex) /* {{{ */ { #ifdef XC_MUTEX_USE_PTHREAD if (pthread_mutex_lock(&mutex->pthread_mutex) < 0) { zend_error(E_ERROR, "xc_mutex failed errno:%d", errno); } #endif #ifdef XC_MUTEX_USE_TSRM if (tsrm_mutex_lock(mutex->tsrm_mutex) < 0) { zend_error(E_ERROR, "xc_mutex failed errno:%d", errno); } #endif #ifdef XC_MUTEX_USE_FCNTL if (xc_want_inter_process()) { xc_fcntl_mutex(&mutex->fcntl_mutex); } #endif #ifndef NDEBUG assert(!mutex->locked); mutex->locked = 1; assert(mutex->locked); #endif } /* }}} */ void xc_mutex_unlock(xc_mutex_t *mutex) /* {{{ */ { #ifndef NDEBUG assert(mutex->locked); mutex->locked = 0; assert(!mutex->locked); #endif #ifdef XC_MUTEX_USE_FCNTL if (xc_want_inter_process()) { xc_fcntl_unlock(&mutex->fcntl_mutex); } #endif #ifdef XC_MUTEX_USE_TSRM if (tsrm_mutex_unlock(mutex->tsrm_mutex) < 0) { zend_error(E_ERROR, "xc_mutex_unlock failed errno:%d", errno); } #endif #ifdef XC_MUTEX_USE_PTHREAD if (pthread_mutex_unlock(&mutex->pthread_mutex) < 0) { zend_error(E_ERROR, "xc_mutex_unlock failed errno:%d", errno); } #endif } /* }}} */ xcache-3.1.0/xcache/xc_mutex.h0000644000175000010010000000104212213477010014400 0ustar mOoNone#ifndef XC_MUTEX_H_1913F3DED68715D7CDA5A055E79FE0FF #define XC_MUTEX_H_1913F3DED68715D7CDA5A055E79FE0FF #if _MSC_VER > 1000 #pragma once #endif /* _MSC_VER > 1000 */ #include typedef struct _xc_mutex_t xc_mutex_t; size_t xc_mutex_size(void); xc_mutex_t *xc_mutex_init(xc_mutex_t *shared_mutex, const char *pathname, unsigned char want_inter_process); void xc_mutex_destroy(xc_mutex_t *mutex); void xc_mutex_lock(xc_mutex_t *mutex); void xc_mutex_unlock(xc_mutex_t *mutex); #endif /* XC_MUTEX_H_1913F3DED68715D7CDA5A055E79FE0FF */ xcache-3.1.0/xcache/xc_opcode_spec.c0000644000175000010010000000242012206607320015516 0ustar mOoNone#include "xcache.h" #include "xc_opcode_spec.h" #include "xc_const_string.h" /* {{{ opcode_spec */ #define OPSPEC(ext, op1, op2, res) { OPSPEC_##ext, OPSPEC_##op1, OPSPEC_##op2, OPSPEC_##res }, #ifdef ZEND_ENGINE_2 # define OPSPEC_VAR_2 OPSPEC_STD #else # define OPSPEC_VAR_2 OPSPEC_VAR #endif #ifdef ZEND_ENGINE_2_4 #undef OPSPEC_FETCH #define OPSPEC_FETCH OPSPEC_STD #endif #include "xc_opcode_spec_def.h" zend_uchar xc_get_opcode_spec_count() { return sizeof(xc_opcode_spec) / sizeof(xc_opcode_spec[0]); } const xc_opcode_spec_t *xc_get_opcode_spec(zend_uchar opcode) { #ifndef NDEBUG if (xc_get_opcode_count() != xc_get_opcode_spec_count()) { fprintf(stderr, "count mismatch: xc_get_opcode_count=%d, xc_get_opcode_spec_count=%d\n", xc_get_opcode_count(), xc_get_opcode_spec_count()); } #endif assert(xc_get_opcode_count() == xc_get_opcode_spec_count()); assert(opcode < xc_get_opcode_spec_count()); return &xc_opcode_spec[opcode]; } /* }}} */ /* {{{ op_spec */ #define OPSPECS_DEF_NAME(name) #name, static const char *xc_op_spec[] = { OPSPECS(OPSPECS_DEF_NAME) }; zend_uchar xc_get_op_spec_count() { return sizeof(xc_op_spec) / sizeof(xc_op_spec[0]); } const char *xc_get_op_spec(zend_uchar spec) { assert(spec < xc_get_op_spec_count()); return xc_op_spec[spec]; } /* }}} */ xcache-3.1.0/xcache/xc_opcode_spec.h0000644000175000010010000000161112220455233015524 0ustar mOoNone#include "php.h" #define OPSPECS(OPSPEC) \ OPSPEC(STD) \ OPSPEC(UNUSED) \ OPSPEC(OPLINE) \ OPSPEC(FCALL) \ OPSPEC(INIT_FCALL) \ OPSPEC(ARG) \ OPSPEC(CAST) \ OPSPEC(FETCH) \ OPSPEC(DECLARE) \ OPSPEC(SEND) \ OPSPEC(SEND_NOREF) \ OPSPEC(FCLASS) \ OPSPEC(UCLASS) \ OPSPEC(CLASS) \ OPSPEC(FE) \ OPSPEC(IFACE) \ OPSPEC(ISSET) \ OPSPEC(BIT) \ OPSPEC(VAR) \ OPSPEC(TMP) \ OPSPEC(JMPADDR) \ OPSPEC(BRK) \ OPSPEC(CONT) \ OPSPEC(INCLUDE) \ OPSPEC(ASSIGN) \ OPSPEC(FETCHTYPE) #define OPSPECS_DEF_ENUM(name) OPSPEC_##name, typedef enum { OPSPECS(OPSPECS_DEF_ENUM) OPSPEC_DUMMY } xc_op_spec_t; typedef struct { xc_op_spec_t ext; xc_op_spec_t op1; xc_op_spec_t op2; xc_op_spec_t res; } xc_opcode_spec_t; const xc_opcode_spec_t *xc_get_opcode_spec(zend_uchar opcode); zend_uchar xc_get_opcode_spec_count(); zend_uchar xc_get_op_spec_count(); const char *xc_get_op_spec(zend_uchar spec); xcache-3.1.0/xcache/xc_opcode_spec_def.h0000644000175000010010000005053412220455233016352 0ustar mOoNonestatic const xc_opcode_spec_t xc_opcode_spec[] = { OPSPEC( UNUSED, UNUSED, UNUSED, UNUSED) /* 0 NOP */ OPSPEC( UNUSED, STD, STD, TMP) /* 1 ADD */ OPSPEC( UNUSED, STD, STD, TMP) /* 2 SUB */ OPSPEC( UNUSED, STD, STD, TMP) /* 3 MUL */ OPSPEC( UNUSED, STD, STD, TMP) /* 4 DIV */ OPSPEC( UNUSED, STD, STD, TMP) /* 5 MOD */ OPSPEC( UNUSED, STD, STD, TMP) /* 6 SL */ OPSPEC( UNUSED, STD, STD, TMP) /* 7 SR */ OPSPEC( UNUSED, STD, STD, TMP) /* 8 CONCAT */ OPSPEC( UNUSED, STD, STD, TMP) /* 9 BW_OR */ OPSPEC( UNUSED, STD, STD, TMP) /* 10 BW_AND */ OPSPEC( UNUSED, STD, STD, TMP) /* 11 BW_XOR */ OPSPEC( UNUSED, STD, UNUSED, TMP) /* 12 BW_NOT */ OPSPEC( UNUSED, STD, STD, TMP) /* 13 BOOL_NOT */ OPSPEC( UNUSED, STD, STD, TMP) /* 14 BOOL_XOR */ OPSPEC( UNUSED, STD, STD, TMP) /* 15 IS_IDENTICAL */ OPSPEC( UNUSED, STD, STD, TMP) /* 16 IS_NOT_IDENTICAL */ OPSPEC( UNUSED, STD, STD, TMP) /* 17 IS_EQUAL */ OPSPEC( UNUSED, STD, STD, TMP) /* 18 IS_NOT_EQUAL */ OPSPEC( UNUSED, STD, STD, TMP) /* 19 IS_SMALLER */ OPSPEC( UNUSED, STD, STD, TMP) /* 20 IS_SMALLER_OR_EQUAL */ OPSPEC( CAST, STD, UNUSED, TMP) /* 21 CAST */ OPSPEC( UNUSED, STD, UNUSED, TMP) /* 22 QM_ASSIGN */ #ifdef ZEND_ENGINE_2 OPSPEC( ASSIGN, STD, STD, VAR) /* 23 ASSIGN_ADD */ OPSPEC( ASSIGN, STD, STD, VAR) /* 24 ASSIGN_SUB */ OPSPEC( ASSIGN, STD, STD, VAR) /* 25 ASSIGN_MUL */ OPSPEC( ASSIGN, STD, STD, VAR) /* 26 ASSIGN_DIV */ OPSPEC( ASSIGN, STD, STD, VAR) /* 27 ASSIGN_MOD */ OPSPEC( ASSIGN, STD, STD, VAR) /* 28 ASSIGN_SL */ OPSPEC( ASSIGN, STD, STD, VAR) /* 29 ASSIGN_SR */ OPSPEC( ASSIGN, STD, STD, VAR) /* 30 ASSIGN_CONCAT */ OPSPEC( ASSIGN, STD, STD, VAR) /* 31 ASSIGN_BW_OR */ OPSPEC( ASSIGN, STD, STD, VAR) /* 32 ASSIGN_BW_AND */ OPSPEC( ASSIGN, STD, STD, VAR) /* 33 ASSIGN_BW_XOR */ #else OPSPEC( UNUSED, VAR, STD, VAR) OPSPEC( UNUSED, VAR, STD, VAR) OPSPEC( UNUSED, VAR, STD, VAR) OPSPEC( UNUSED, VAR, STD, VAR) OPSPEC( UNUSED, VAR, STD, VAR) OPSPEC( UNUSED, VAR, STD, VAR) OPSPEC( UNUSED, VAR, STD, VAR) OPSPEC( UNUSED, VAR, STD, VAR) OPSPEC( UNUSED, VAR, STD, VAR) OPSPEC( UNUSED, VAR, STD, VAR) OPSPEC( UNUSED, VAR, STD, VAR) #endif OPSPEC( UNUSED, VAR, UNUSED, VAR) /* 34 PRE_INC */ OPSPEC( UNUSED, VAR, UNUSED, VAR) /* 35 PRE_DEC */ OPSPEC( UNUSED, VAR, UNUSED, TMP) /* 36 POST_INC */ OPSPEC( UNUSED, VAR, UNUSED, TMP) /* 37 POST_DEC */ OPSPEC( UNUSED, VAR, STD, VAR) /* 38 ASSIGN */ OPSPEC( UNUSED, VAR, VAR, VAR) /* 39 ASSIGN_REF */ OPSPEC( UNUSED, STD, UNUSED, UNUSED) /* 40 ECHO */ OPSPEC( UNUSED, STD, UNUSED, TMP) /* 41 PRINT */ #ifdef ZEND_ENGINE_2 OPSPEC( UNUSED, JMPADDR, UNUSED, UNUSED) /* 42 JMP */ OPSPEC( UNUSED, STD, JMPADDR, UNUSED) /* 43 JMPZ */ OPSPEC( UNUSED, STD, JMPADDR, UNUSED) /* 44 JMPNZ */ #else OPSPEC( UNUSED, OPLINE, UNUSED, UNUSED) OPSPEC( UNUSED, STD, OPLINE, UNUSED) OPSPEC( UNUSED, STD, OPLINE, UNUSED) #endif OPSPEC( OPLINE, STD, OPLINE, UNUSED) /* 45 JMPZNZ */ #ifdef ZEND_ENGINE_2 OPSPEC( UNUSED, STD, JMPADDR, TMP) /* 46 JMPZ_EX */ OPSPEC( UNUSED, STD, JMPADDR, TMP) /* 47 JMPNZ_EX */ #else OPSPEC( UNUSED, STD, OPLINE, TMP) OPSPEC( UNUSED, STD, OPLINE, TMP) #endif OPSPEC( UNUSED, STD, STD, TMP) /* 48 CASE */ OPSPEC( BIT, STD, UNUSED, UNUSED) /* 49 SWITCH_FREE */ OPSPEC( UNUSED, BRK, STD, UNUSED) /* 50 BRK */ OPSPEC( UNUSED, CONT, STD, UNUSED) /* 51 CONT */ OPSPEC( UNUSED, STD, UNUSED, TMP) /* 52 BOOL */ OPSPEC( UNUSED, UNUSED, UNUSED, TMP) /* 53 INIT_STRING */ OPSPEC( UNUSED, STD, STD, TMP) /* 54 ADD_CHAR */ OPSPEC( UNUSED, STD, STD, TMP) /* 55 ADD_STRING */ OPSPEC( UNUSED, STD, STD, TMP) /* 56 ADD_VAR */ OPSPEC( UNUSED, UNUSED, UNUSED, TMP) /* 57 BEGIN_SILENCE */ OPSPEC( UNUSED, TMP, UNUSED, UNUSED) /* 58 END_SILENCE */ OPSPEC(INIT_FCALL, STD, STD, UNUSED) /* 59 INIT_FCALL_BY_NAME */ #ifdef ZEND_ENGINE_2 OPSPEC( FCALL, STD, OPLINE, VAR) /* 60 DO_FCALL */ OPSPEC( FCALL, STD, OPLINE, VAR) /* 61 DO_FCALL_BY_NAME */ #else OPSPEC( FCALL, STD, UNUSED, VAR) OPSPEC( FCALL, STD, UNUSED, VAR) #endif OPSPEC( UNUSED, STD, UNUSED, UNUSED) /* 62 RETURN */ OPSPEC( UNUSED, ARG, UNUSED, VAR) /* 63 RECV */ OPSPEC( UNUSED, ARG, STD, VAR) /* 64 RECV_INIT */ OPSPEC( SEND, STD, ARG, UNUSED) /* 65 SEND_VAL */ OPSPEC( SEND, VAR, ARG, UNUSED) /* 66 SEND_VAR */ OPSPEC( SEND, VAR, ARG, UNUSED) /* 67 SEND_REF */ #ifdef ZEND_ENGINE_2 OPSPEC( UNUSED, CLASS, UNUSED, VAR) /* 68 NEW */ #else OPSPEC( UNUSED, STD, UNUSED, VAR) #endif #ifdef ZEND_ENGINE_2_3 OPSPEC( STD, STD, STD, UNUSED) /* 69 INIT_NS_FCALL_BY_NAME */ #elif defined(ZEND_ENGINE_2_1) OPSPEC( UNUSED, UNUSED, UNUSED, UNUSED) #else OPSPEC( UNUSED, STD, OPLINE, UNUSED) /* 69 JMP_NO_CTOR */ #endif OPSPEC( UNUSED, TMP, UNUSED, UNUSED) /* 70 FREE */ OPSPEC( BIT, STD, STD, TMP) /* 71 INIT_ARRAY */ OPSPEC( BIT, STD, STD, TMP) /* 72 ADD_ARRAY_ELEMENT */ OPSPEC( UNUSED, STD, INCLUDE, VAR) /* 73 INCLUDE_OR_EVAL */ #ifdef ZEND_ENGINE_2_1 /* php 5.1 and up */ # ifdef ZEND_ENGINE_2_4 OPSPEC( FETCHTYPE, STD, STD, UNUSED) /* 74 UNSET_VAR */ # else OPSPEC( UNUSED, STD, FETCH, UNUSED) /* 74 UNSET_VAR */ # endif OPSPEC( STD, STD, STD, UNUSED) /* 75 UNSET_DIM */ OPSPEC( STD, STD, STD, UNUSED) /* 76 UNSET_OBJ */ OPSPEC( BIT, STD, OPLINE, VAR) /* 77 FE_RESET */ #else /* <= php 5.0 */ OPSPEC( UNUSED, STD, UNUSED, UNUSED) /* 74 UNSET_VAR */ /* though there is no ISSET_ISEMPTY in php 5.0 it's better to leave it here i guess */ OPSPEC( UNUSED, VAR, STD, UNUSED) OPSPEC( UNUSED, VAR, ISSET, TMP) OPSPEC( BIT, STD, UNUSED, VAR) /* 77 FE_RESET */ #endif OPSPEC( FE, STD, OPLINE, TMP) /* 78 FE_FETCH */ OPSPEC( UNUSED, STD, UNUSED, UNUSED) /* 79 EXIT */ #ifdef ZEND_ENGINE_2_4 OPSPEC( FETCHTYPE, STD, STD, VAR) /* 80 FETCH_R */ #else OPSPEC( UNUSED, STD, FETCH, VAR) /* 80 FETCH_R */ #endif OPSPEC( FETCH, VAR, STD, VAR) /* 81 FETCH_DIM_R */ OPSPEC( UNUSED, VAR_2, STD, VAR) /* 82 FETCH_OBJ_R */ #ifdef ZEND_ENGINE_2_4 OPSPEC( FETCHTYPE, STD, STD, VAR) /* 83 FETCH_W */ #else OPSPEC( UNUSED, STD, FETCH, VAR) /* 83 FETCH_W */ #endif OPSPEC( UNUSED, VAR, STD, VAR) /* 84 FETCH_DIM_W */ OPSPEC( UNUSED, VAR_2, STD, VAR) /* 85 FETCH_OBJ_W */ #ifdef ZEND_ENGINE_2_4 OPSPEC( FETCHTYPE, STD, STD, VAR) /* 86 FETCH_RW */ #else OPSPEC( UNUSED, STD, FETCH, VAR) /* 86 FETCH_RW */ #endif OPSPEC( UNUSED, VAR, STD, VAR) /* 87 FETCH_DIM_RW */ OPSPEC( UNUSED, VAR_2, STD, VAR) /* 88 FETCH_OBJ_RW */ #ifdef ZEND_ENGINE_2_4 OPSPEC( FETCHTYPE, STD, STD, VAR) /* 89 FETCH_IS */ #else OPSPEC( UNUSED, STD, FETCH, VAR) /* 89 FETCH_IS */ #endif OPSPEC( UNUSED, VAR, STD, VAR) /* 90 FETCH_DIM_IS */ OPSPEC( UNUSED, VAR_2, STD, VAR) /* 91 FETCH_OBJ_IS */ #ifdef ZEND_ENGINE_2_4 OPSPEC( ARG, STD, STD, VAR) /* 92 FETCH_FUNC_ARG */ #else OPSPEC( ARG, STD, FETCH, VAR) /* 92 FETCH_FUNC_ARG */ #endif OPSPEC( ARG, VAR, STD, VAR) /* 93 FETCH_DIM_FUNC_ARG */ OPSPEC( ARG, VAR_2, STD, VAR) /* 94 FETCH_OBJ_FUNC_ARG */ #ifdef ZEND_ENGINE_2_4 OPSPEC( FETCHTYPE, STD, STD, VAR) /* 95 FETCH_UNSET */ #else OPSPEC( UNUSED, STD, FETCH, VAR) /* 95 FETCH_UNSET */ #endif OPSPEC( UNUSED, VAR, STD, VAR) /* 96 FETCH_DIM_UNSET */ OPSPEC( UNUSED, VAR_2, STD, VAR) /* 97 FETCH_OBJ_UNSET */ OPSPEC( UNUSED, STD, STD, VAR) /* 98 FETCH_DIM_TMP_VAR */ #ifdef ZEND_ENGINE_2_3 OPSPEC( UNUSED, VAR_2, STD, TMP) /* 99 FETCH_CONSTANT */ #elif defined(ZEND_ENGINE_2) OPSPEC( UNUSED, UCLASS, STD, TMP) /* 99 FETCH_CONSTANT */ #else OPSPEC( UNUSED, STD, UNUSED, TMP) /* 99 FETCH_CONSTANT */ #endif #ifdef ZEND_ENGINE_2_3 OPSPEC( STD, JMPADDR, STD, UNUSED) /* 100 GOTO */ #else OPSPEC( DECLARE, STD, STD, UNUSED) /* 100 DECLARE_FUNCTION_OR_CLASS */ #endif OPSPEC( STD, STD, STD, STD) /* 101 EXT_STMT */ OPSPEC( STD, STD, STD, STD) /* 102 EXT_FCALL_BEGIN */ OPSPEC( STD, STD, STD, STD) /* 103 EXT_FCALL_END */ OPSPEC( UNUSED, UNUSED, UNUSED, UNUSED) /* 104 EXT_NOP */ OPSPEC( UNUSED, STD, UNUSED, UNUSED) /* 105 TICKS */ OPSPEC(SEND_NOREF, VAR, ARG, UNUSED) /* 106 SEND_VAR_NO_REF */ #ifndef ZEND_ENGINE_2 OPSPEC( UNUSED, UNUSED, UNUSED, UNUSED) /* 107 UNDEF */ OPSPEC( UNUSED, UNUSED, UNUSED, UNUSED) /* 108 UNDEF */ OPSPEC( UNUSED, UNUSED, UNUSED, UNUSED) /* 109 UNDEF */ OPSPEC( FCALL, STD, OPLINE, VAR) /* 61 DO_FCALL_BY_FUNC */ OPSPEC(INIT_FCALL, STD, STD, UNUSED) /* 111 INIT_FCALL_BY_FUNC */ OPSPEC( UNUSED, UNUSED, UNUSED, UNUSED) /* 112 UNDEF */ #else /* ZEND_ENGINE_2 */ # ifdef ZEND_ENGINE_2_4 OPSPEC( OPLINE, STD, STD, UNUSED) /* 107 CATCH */ # else OPSPEC( OPLINE, CLASS, STD, UNUSED) /* 107 CATCH */ # endif OPSPEC( UNUSED, STD, OPLINE, UNUSED) /* 108 THROW */ OPSPEC( FCLASS, STD, STD, CLASS) /* 109 FETCH_CLASS */ OPSPEC( UNUSED, STD, UNUSED, VAR) /* 110 CLONE */ # ifdef ZEND_ENGINE_2_4 OPSPEC( UNUSED, STD, UNUSED, UNUSED) /* 111 RETURN_BY_REF */ # else OPSPEC( UNUSED, STD, UNUSED, UNUSED) /* 111 INIT_CTOR_CALL */ # endif OPSPEC( UNUSED, STD, STD, VAR) /* 112 INIT_METHOD_CALL */ # ifdef ZEND_ENGINE_2_3 OPSPEC( UNUSED, STD, STD, UNUSED) /* 113 INIT_STATIC_METHOD_CALL */ # else OPSPEC( UNUSED, UCLASS, STD, UNUSED) /* 113 INIT_STATIC_METHOD_CALL */ # endif # ifdef ZEND_ENGINE_2_4 OPSPEC( ISSET, STD, STD, TMP) /* 114 ISSET_ISEMPTY_VAR */ # else OPSPEC( ISSET, STD, FETCH, TMP) /* 114 ISSET_ISEMPTY_VAR */ # endif OPSPEC( ISSET, STD, STD, TMP) /* 115 ISSET_ISEMPTY_DIM_OBJ */ OPSPEC( UNUSED, CLASS, STD, UNUSED) /* 116 IMPORT_FUNCTION */ OPSPEC( UNUSED, CLASS, STD, UNUSED) /* 117 IMPORT_CLASS */ OPSPEC( UNUSED, CLASS, STD, UNUSED) /* 118 IMPORT_CONST */ OPSPEC( STD, STD, STD, STD) /* 119 OP_119 */ OPSPEC( STD, STD, STD, STD) /* 120 OP_120 */ OPSPEC( UNUSED, STD, STD, VAR) /* 121 ASSIGN_ADD_OBJ */ OPSPEC( UNUSED, STD, STD, VAR) /* 122 ASSIGN_SUB_OBJ */ OPSPEC( UNUSED, STD, STD, VAR) /* 123 ASSIGN_MUL_OBJ */ OPSPEC( UNUSED, STD, STD, VAR) /* 124 ASSIGN_DIV_OBJ */ OPSPEC( UNUSED, STD, STD, VAR) /* 125 ASSIGN_MOD_OBJ */ OPSPEC( UNUSED, STD, STD, VAR) /* 126 ASSIGN_SL_OBJ */ OPSPEC( UNUSED, STD, STD, VAR) /* 127 ASSIGN_SR_OBJ */ OPSPEC( UNUSED, STD, STD, VAR) /* 128 ASSIGN_CONCAT_OBJ */ OPSPEC( UNUSED, STD, STD, VAR) /* 129 ASSIGN_BW_OR_OBJ */ OPSPEC( UNUSED, STD, STD, VAR) /* 130 ASSIGN_BW_AND_OBJ */ OPSPEC( UNUSED, STD, STD, VAR) /* 131 ASSIGN_BW_XOR_OBJ */ OPSPEC( UNUSED, STD, STD, VAR) /* 132 PRE_INC_OBJ */ OPSPEC( UNUSED, STD, STD, VAR) /* 133 PRE_DEC_OBJ */ OPSPEC( UNUSED, STD, STD, TMP) /* 134 POST_INC_OBJ */ OPSPEC( UNUSED, STD, STD, TMP) /* 135 POST_DEC_OBJ */ OPSPEC( UNUSED, STD, STD, VAR) /* 136 ASSIGN_OBJ */ OPSPEC( UNUSED, STD, STD, STD) /* 137 OP_DATA */ OPSPEC( UNUSED, STD, CLASS, TMP) /* 138 INSTANCEOF */ OPSPEC( UNUSED, STD, STD, CLASS) /* 139 DECLARE_CLASS */ OPSPEC( CLASS, STD, STD, CLASS) /* 140 DECLARE_INHERITED_CLASS */ OPSPEC( UNUSED, STD, STD, UNUSED) /* 141 DECLARE_FUNCTION */ OPSPEC( UNUSED, UNUSED, UNUSED, UNUSED) /* 142 RAISE_ABSTRACT_ERROR */ # ifdef ZEND_ENGINE_2_3 OPSPEC( DECLARE, STD, STD, UNUSED) /* 143 DECLARE_CONST */ # else OPSPEC( UNUSED, UNUSED, UNUSED, UNUSED) /* 143 UNDEF-143 */ # endif # ifdef ZEND_ENGINE_2_3 OPSPEC( IFACE, CLASS, STD, UNUSED) /* 144 ADD_INTERFACE */ # else OPSPEC( IFACE, CLASS, CLASS, UNUSED) /* 144 ADD_INTERFACE */ # endif # ifdef ZEND_ENGINE_2_3 OPSPEC( CLASS, STD, STD, OPLINE) /* 145 DECLARE_INHERITED_CLASS_DELAYED */ # else OPSPEC( UNUSED, CLASS, STD, UNUSED) /* 145 VERIFY_INSTANCEOF */ # endif OPSPEC( UNUSED, CLASS, UNUSED, UNUSED) /* 146 VERIFY_ABSTRACT_CLASS */ OPSPEC( UNUSED, STD, STD, VAR) /* 147 ASSIGN_DIM */ OPSPEC( ISSET, STD, STD, TMP) /* 148 ISSET_ISEMPTY_PROP_OBJ */ OPSPEC( STD, UNUSED, UNUSED, STD) /* 149 HANDLE_EXCEPTION */ #endif /* ZEND_ENGINE_2 */ #ifdef ZEND_ENGINE_2_1 OPSPEC( STD, UNUSED, UNUSED, STD) /* 150 USER_OPCODE */ #endif #ifdef ZEND_ENGINE_2_3 OPSPEC( UNUSED, UNUSED, UNUSED, UNUSED) /* 151 UNDEF */ OPSPEC( UNUSED, STD, JMPADDR, TMP) /* 152 JMP_SET */ OPSPEC( UNUSED, STD, STD, TMP) /* 153 DECLARE_LAMBDA_FUNCTION */ #endif #ifdef ZEND_ENGINE_2_4 OPSPEC( UNUSED, UNUSED, UNUSED, UNUSED) /* 154 ADD_TRAIT */ OPSPEC( UNUSED, UNUSED, UNUSED, UNUSED) /* 155 BIND_TRAITS */ OPSPEC( UNUSED, UNUSED, UNUSED, UNUSED) /* 156 SEPARATE */ OPSPEC( UNUSED, UNUSED, UNUSED, UNUSED) /* 157 QM_ASSIGN_VAR */ OPSPEC( UNUSED, UNUSED, UNUSED, UNUSED) /* 158 JMP_SET_VAR */ #endif #ifdef ZEND_ENGINE_2_5 OPSPEC( UNUSED, UNUSED, UNUSED, UNUSED) /* 159 DISCARD_EXCEPTION */ OPSPEC( UNUSED, STD, STD, UNUSED) /* 160 YIELD */ OPSPEC( UNUSED, STD, UNUSED, UNUSED) /* 161 GENERATOR_RETURN */ OPSPEC( UNUSED, JMPADDR, UNUSED, UNUSED) /* 162 FAST_CALL */ OPSPEC( UNUSED, UNUSED, UNUSED, UNUSED) /* 163 FAST_RET */ #endif }; xcache-3.1.0/xcache/xc_processor.c0000644000175000010010000000003412157744741015267 0ustar mOoNone#include "xc_processor.c.h" xcache-3.1.0/xcache/xc_sandbox.c0000644000175000010010000003276712206607320014712 0ustar mOoNone #include "xcache.h" #include "xc_sandbox.h" #include "xc_utils.h" #include "xcache_globals.h" /* utilities used by sandbox */ static void (*old_zend_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args) = NULL; static void call_old_zend_error_cb(int type, const char *error_filename, const uint error_lineno, const char *format, ...) /* {{{ */ { va_list args; va_start(args, format); old_zend_error_cb(type, error_filename, error_lineno, format, args); } /* }}} */ #ifdef ZEND_ENGINE_2_1 static zend_bool xc_auto_global_callback(ZEND_24(NOTHING, const) char *name, uint name_len TSRMLS_DC) /* {{{ */ { return 0; } /* }}} */ static int xc_auto_global_arm(zend_auto_global *auto_global TSRMLS_DC) /* {{{ */ { if (auto_global->auto_global_callback) { auto_global->armed = 1; auto_global->auto_global_callback = xc_auto_global_callback; } else { auto_global->armed = 0; } return ZEND_HASH_APPLY_KEEP; } /* }}} */ #endif #ifdef HAVE_XCACHE_CONSTANT static void xc_free_zend_constant(zend_constant *c) /* {{{ */ { if (!(c->flags & CONST_PERSISTENT)) { zval_dtor(&c->value); } free(ZSTR_V(c->name)); } /* }}} */ #endif typedef struct _xc_sandbox_t { /* sandbox {{{ */ ZEND_24(NOTHING, const) char *filename; HashTable orig_included_files; HashTable *tmp_included_files; #ifdef HAVE_XCACHE_CONSTANT HashTable *orig_zend_constants; HashTable tmp_zend_constants; #endif HashTable *orig_function_table; HashTable *orig_class_table; HashTable *orig_auto_globals; HashTable tmp_function_table; HashTable tmp_class_table; HashTable tmp_auto_globals; #ifdef HAVE_XCACHE_CONSTANT Bucket *tmp_internal_constant_tail; #endif Bucket *tmp_internal_function_tail; Bucket *tmp_internal_class_tail; #ifdef XCACHE_ERROR_CACHING int orig_user_error_handler_error_reporting; zend_uint compilererror_cnt; zend_uint compilererror_size; xc_compilererror_t *compilererrors; #endif #ifdef ZEND_COMPILE_IGNORE_INTERNAL_CLASSES zend_uint orig_compiler_options; #endif struct _xc_sandbox_t *parent; } xc_sandbox_t; #undef TG #undef OG #define TG(x) (sandbox->tmp_##x) #define OG(x) (sandbox->orig_##x) /* }}} */ #ifdef XCACHE_ERROR_CACHING static void xc_sandbox_error_cb(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args) /* {{{ */ { xc_compilererror_t *compilererror; xc_sandbox_t *sandbox; TSRMLS_FETCH(); sandbox = (xc_sandbox_t *) XG(sandbox); if (!sandbox) { old_zend_error_cb(type, error_filename, error_lineno, format, args); return; } switch (type) { #ifdef E_STRICT case E_STRICT: #endif #ifdef E_DEPRECATED case E_DEPRECATED: #endif if (sandbox->compilererror_cnt <= sandbox->compilererror_size) { if (sandbox->compilererror_size) { sandbox->compilererror_size += 16; sandbox->compilererrors = erealloc(sandbox->compilererrors, sandbox->compilererror_size * sizeof(sandbox->compilererrors)); } else { sandbox->compilererror_size = 16; sandbox->compilererrors = emalloc(sandbox->compilererror_size * sizeof(sandbox->compilererrors)); } } compilererror = &sandbox->compilererrors[sandbox->compilererror_cnt++]; compilererror->type = type; compilererror->lineno = error_lineno; compilererror->error_len = vspprintf(&compilererror->error, 0, format, args); break; default: { /* give up, and user handler is not supported in this case */ zend_uint i; zend_uint old_lineno = CG(zend_lineno); for (i = 0; i < sandbox->compilererror_cnt; i ++) { compilererror = &sandbox->compilererrors[i]; CG(zend_lineno) = compilererror->lineno; call_old_zend_error_cb(compilererror->type, error_filename, error_lineno, "%s", compilererror->error); efree(compilererror->error); } if (sandbox->compilererrors) { efree(sandbox->compilererrors); sandbox->compilererrors = NULL; } sandbox->compilererror_cnt = 0; sandbox->compilererror_size = 0; CG(zend_lineno) = old_lineno; old_zend_error_cb(type, error_filename, error_lineno, format, args); break; } } } /* }}} */ #endif static xc_sandbox_t *xc_sandbox_init(xc_sandbox_t *sandbox, ZEND_24(NOTHING, const) char *filename TSRMLS_DC) /* {{{ */ { HashTable *h; assert(sandbox); memset(sandbox, 0, sizeof(sandbox[0])); memcpy(&OG(included_files), &EG(included_files), sizeof(EG(included_files))); #ifdef HAVE_XCACHE_CONSTANT OG(zend_constants) = EG(zend_constants); EG(zend_constants) = &TG(zend_constants); #endif OG(function_table) = CG(function_table); CG(function_table) = &TG(function_table); OG(class_table) = CG(class_table); CG(class_table) = &TG(class_table); EG(class_table) = CG(class_table); #ifdef ZEND_ENGINE_2_1 OG(auto_globals) = CG(auto_globals); CG(auto_globals) = &TG(auto_globals); #endif TG(included_files) = &EG(included_files); zend_hash_init_ex(TG(included_files), 5, NULL, NULL, 0, 1); #ifdef HAVE_XCACHE_CONSTANT h = OG(zend_constants); zend_hash_init_ex(&TG(zend_constants), 20, NULL, (dtor_func_t) xc_free_zend_constant, h->persistent, h->bApplyProtection); xc_copy_internal_zend_constants(&TG(zend_constants), &XG(internal_constant_table)); TG(internal_constant_tail) = TG(zend_constants).pListTail; #endif h = OG(function_table); zend_hash_init_ex(&TG(function_table), 128, NULL, ZEND_FUNCTION_DTOR, h->persistent, h->bApplyProtection); { zend_function tmp_func; zend_hash_copy(&TG(function_table), &XG(internal_function_table), NULL, (void *) &tmp_func, sizeof(tmp_func)); } TG(internal_function_tail) = TG(function_table).pListTail; h = OG(class_table); zend_hash_init_ex(&TG(class_table), 16, NULL, ZEND_CLASS_DTOR, h->persistent, h->bApplyProtection); #if 0 && TODO { xc_cest_t tmp_cest; zend_hash_copy(&TG(class_table), &XG(internal_class_table), NULL, (void *) &tmp_cest, sizeof(tmp_cest)); } #endif TG(internal_class_tail) = TG(class_table).pListTail; #ifdef ZEND_ENGINE_2_1 /* shallow copy, don't destruct */ h = OG(auto_globals); zend_hash_init_ex(&TG(auto_globals), 8, NULL, NULL, h->persistent, h->bApplyProtection); { zend_auto_global tmp_autoglobal; zend_hash_copy(&TG(auto_globals), OG(auto_globals), NULL, (void *) &tmp_autoglobal, sizeof(tmp_autoglobal)); zend_hash_apply(&TG(auto_globals), (apply_func_t) xc_auto_global_arm TSRMLS_CC); } #endif sandbox->filename = filename; #ifdef XCACHE_ERROR_CACHING sandbox->orig_user_error_handler_error_reporting = EG(user_error_handler_error_reporting); EG(user_error_handler_error_reporting) = 0; sandbox->compilererror_cnt = 0; sandbox->compilererror_size = 0; #endif #ifdef ZEND_COMPILE_IGNORE_INTERNAL_CLASSES sandbox->orig_compiler_options = CG(compiler_options); /* Using ZEND_COMPILE_IGNORE_INTERNAL_CLASSES for ZEND_FETCH_CLASS_RT_NS_CHECK */ CG(compiler_options) |= ZEND_COMPILE_IGNORE_INTERNAL_CLASSES | ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION | ZEND_COMPILE_DELAYED_BINDING; #endif sandbox->parent = XG(sandbox); XG(sandbox) = (void *) sandbox; XG(initial_compile_file_called) = 0; return sandbox; } /* }}} */ #ifndef ZEND_COMPILE_DELAYED_BINDING static void xc_early_binding_cb(zend_op *opline, int oplineno, void *data TSRMLS_DC) /* {{{ */ { xc_sandbox_t *sandbox = (xc_sandbox_t *) data; xc_do_early_binding(CG(active_op_array), OG(class_table), oplineno TSRMLS_CC); } /* }}} */ #endif static void xc_sandbox_install(xc_sandbox_t *sandbox TSRMLS_DC) /* {{{ */ { zend_uint i; Bucket *b; #ifdef HAVE_XCACHE_CONSTANT for (b = TG(zend_constants).pListHead; b != NULL && b != TG(internal_constant_tail); b = b->pListNext) { zend_constant *c = (zend_constant*) b->pData; xc_free_zend_constant(c); } b = TG(internal_constant_tail) ? TG(internal_constant_tail)->pListNext : TG(zend_constants).pListHead; /* install constants */ while (b != NULL) { zend_constant *c = (zend_constant*) b->pData; xc_install_constant(sandbox->filename, c, BUCKET_KEY_TYPE(b), ZSTR(BUCKET_KEY_S(b)), b->nKeyLength, b->h TSRMLS_CC); b = b->pListNext; } #endif b = TG(internal_function_tail) ? TG(internal_function_tail)->pListNext : TG(function_table).pListHead; /* install function */ while (b != NULL) { zend_function *func = (zend_function*) b->pData; xc_install_function(sandbox->filename, func, BUCKET_KEY_TYPE(b), ZSTR(BUCKET_KEY_S(b)), b->nKeyLength, b->h TSRMLS_CC); b = b->pListNext; } b = TG(internal_class_tail) ? TG(internal_class_tail)->pListNext : TG(class_table).pListHead; /* install class */ while (b != NULL) { xc_install_class(sandbox->filename, (xc_cest_t*) b->pData, -1, BUCKET_KEY_TYPE(b), ZSTR(BUCKET_KEY_S(b)), b->nKeyLength, b->h TSRMLS_CC); b = b->pListNext; } #ifdef ZEND_ENGINE_2_1 /* trigger auto_globals jit */ for (b = TG(auto_globals).pListHead; b != NULL; b = b->pListNext) { zend_auto_global *auto_global = (zend_auto_global *) b->pData; /* check if actived */ if (auto_global->auto_global_callback && !auto_global->armed) { zend_u_is_auto_global(BUCKET_KEY_TYPE(b), ZSTR(BUCKET_KEY_S(b)), auto_global->name_len TSRMLS_CC); } } #endif /* CG(compiler_options) applies only if initial_compile_file_called */ if (XG(initial_compile_file_called)) { #ifdef ZEND_COMPILE_DELAYED_BINDING zend_do_delayed_early_binding(CG(active_op_array) TSRMLS_CC); #else xc_undo_pass_two(CG(active_op_array) TSRMLS_CC); xc_foreach_early_binding_class(CG(active_op_array), xc_early_binding_cb, (void *) sandbox TSRMLS_CC); xc_redo_pass_two(CG(active_op_array) TSRMLS_CC); #endif } #ifdef XCACHE_ERROR_CACHING /* restore trigger errors */ for (i = 0; i < sandbox->compilererror_cnt; i ++) { xc_compilererror_t *error = &sandbox->compilererrors[i]; CG(zend_lineno) = error->lineno; zend_error(error->type, "%s", error->error); } CG(zend_lineno) = 0; #endif i = 1; /* still needed because in zend_language_scanner.l, require()/include() check file_handle.handle.stream.handle */ zend_hash_add(&OG(included_files), sandbox->filename, strlen(sandbox->filename) + 1, (void *)&i, sizeof(int), NULL); } /* }}} */ static void xc_sandbox_free(xc_sandbox_t *sandbox, zend_op_array *op_array TSRMLS_DC) /* {{{ */ { XG(sandbox) = sandbox->parent; #ifdef XCACHE_ERROR_CACHING EG(user_error_handler_error_reporting) = sandbox->orig_user_error_handler_error_reporting; #endif /* restore first first install function/class */ #ifdef HAVE_XCACHE_CONSTANT EG(zend_constants) = OG(zend_constants); #endif CG(function_table) = OG(function_table); CG(class_table) = OG(class_table); EG(class_table) = CG(class_table); #ifdef ZEND_ENGINE_2_1 CG(auto_globals) = OG(auto_globals); #endif if (op_array) { zend_op_array *old_active_op_array = CG(active_op_array); CG(in_compilation) = 1; CG(compiled_filename) = ZEND_24(NOTHING, (char *)) sandbox->filename; CG(zend_lineno) = 0; CG(active_op_array) = op_array; xc_sandbox_install(sandbox TSRMLS_CC); CG(active_op_array) = old_active_op_array; CG(in_compilation) = 0; CG(compiled_filename) = NULL; /* no free as it's installed */ #ifdef HAVE_XCACHE_CONSTANT TG(zend_constants).pDestructor = NULL; #endif TG(function_table).pDestructor = NULL; TG(class_table).pDestructor = NULL; } /* destroy all the tmp */ #ifdef HAVE_XCACHE_CONSTANT zend_hash_destroy(&TG(zend_constants)); #endif zend_hash_destroy(&TG(function_table)); zend_hash_destroy(&TG(class_table)); #ifdef ZEND_ENGINE_2_1 zend_hash_destroy(&TG(auto_globals)); #endif zend_hash_destroy(TG(included_files)); /* restore orig here, as EG/CG holded tmp before */ memcpy(&EG(included_files), &OG(included_files), sizeof(EG(included_files))); #ifdef XCACHE_ERROR_CACHING if (sandbox->compilererrors) { zend_uint i; for (i = 0; i < sandbox->compilererror_cnt; i ++) { efree(sandbox->compilererrors[i].error); } efree(sandbox->compilererrors); } #endif #ifdef ZEND_COMPILE_IGNORE_INTERNAL_CLASSES CG(compiler_options) = sandbox->orig_compiler_options; #endif } /* }}} */ zend_op_array *xc_sandbox(xc_sandboxed_func_t sandboxed_func, void *data, ZEND_24(NOTHING, const) char *filename TSRMLS_DC) /* {{{ */ { xc_sandbox_t sandbox; zend_op_array *op_array = NULL; zend_bool catched = 0; memset(&sandbox, 0, sizeof(sandbox)); zend_try { xc_sandbox_init(&sandbox, filename TSRMLS_CC); op_array = sandboxed_func(data TSRMLS_CC); } zend_catch { catched = 1; } zend_end_try(); xc_sandbox_free(&sandbox, op_array TSRMLS_CC); if (catched) { zend_bailout(); } return op_array; } /* }}} */ const Bucket *xc_sandbox_user_function_begin(TSRMLS_D) /* {{{ */ { xc_sandbox_t *sandbox = (xc_sandbox_t *) XG(sandbox); assert(sandbox); return TG(internal_function_tail) ? TG(internal_function_tail)->pListNext : TG(function_table).pListHead; } /* }}} */ const Bucket *xc_sandbox_user_class_begin(TSRMLS_D) /* {{{ */ { xc_sandbox_t *sandbox = (xc_sandbox_t *) XG(sandbox); assert(sandbox); return TG(internal_class_tail) ? TG(internal_class_tail)->pListNext : TG(class_table).pListHead; } /* }}} */ #ifdef XCACHE_ERROR_CACHING xc_compilererror_t *xc_sandbox_compilererrors(TSRMLS_D) /* {{{ */ { xc_sandbox_t *sandbox = (xc_sandbox_t *) XG(sandbox); assert(sandbox); return sandbox->compilererrors; } /* }}} */ zend_uint xc_sandbox_compilererror_cnt(TSRMLS_D) /* {{{ */ { xc_sandbox_t *sandbox = (xc_sandbox_t *) XG(sandbox); assert(sandbox); return sandbox->compilererror_cnt; } /* }}} */ #endif /* MINIT/MSHUTDOWN */ int xc_sandbox_module_init(int module_number TSRMLS_DC) /* {{{ */ { #ifdef XCACHE_ERROR_CACHING old_zend_error_cb = zend_error_cb; zend_error_cb = xc_sandbox_error_cb; #endif return SUCCESS; } /* }}} */ void xc_sandbox_module_shutdown() /* {{{ */ { #ifdef XCACHE_ERROR_CACHING if (zend_error_cb == xc_sandbox_error_cb) { zend_error_cb = old_zend_error_cb; } #endif } /* }}} */ xcache-3.1.0/xcache/xc_sandbox.h0000644000175000010010000000201312157744741014712 0ustar mOoNone#ifndef XC_SANDBOX_H_3AFE4094B1D005188B909F9B6538599C #define XC_SANDBOX_H_3AFE4094B1D005188B909F9B6538599C #if _MSC_VER > 1000 #pragma once #endif /* _MSC_VER > 1000 */ /* Purpose: run specified function in compiler sandbox, restore everything to previous state after it returns */ #include "xc_compatibility.h" int xc_sandbox_module_init(int module_number TSRMLS_DC); void xc_sandbox_module_shutdown(); /* return op_array to install */ typedef zend_op_array *(*xc_sandboxed_func_t)(void *data TSRMLS_DC); zend_op_array *xc_sandbox(xc_sandboxed_func_t sandboxed_func, void *data, ZEND_24(NOTHING, const) char *filename TSRMLS_DC); const Bucket *xc_sandbox_user_function_begin(TSRMLS_D); const Bucket *xc_sandbox_user_class_begin(TSRMLS_D); zend_uint xc_sandbox_compilererror_cnt(TSRMLS_D); #ifdef XCACHE_ERROR_CACHING struct _xc_compilererror_t; struct _xc_compilererror_t *xc_sandbox_compilererrors(TSRMLS_D); zend_uint xc_sandbox_compilererror_cnt(TSRMLS_D); #endif #endif /* XC_SANDBOX_H_3AFE4094B1D005188B909F9B6538599C */ xcache-3.1.0/xcache/xc_shm.c0000644000175000010010000000401212220455233014021 0ustar mOoNone#ifdef TEST # ifdef HAVE_CONFIG_H # include # endif # include # include #else # include "xcache.h" #endif #include "xc_shm.h" #include #include #include struct _xc_shm_scheme_t { const char *name; const xc_shm_handlers_t *handlers; }; static xc_shm_scheme_t xc_shm_schemes[10]; void xc_shm_init_modules() /* {{{ */ { extern void xc_allocator_init(); #ifdef HAVE_XCACHE_TEST extern void xc_shm_malloc_register(); #endif extern void xc_shm_mmap_register(); memset(xc_shm_schemes, 0, sizeof(xc_shm_schemes)); xc_allocator_init(); #ifdef HAVE_XCACHE_TEST xc_shm_malloc_register(); #endif xc_shm_mmap_register(); } /* }}} */ int xc_shm_scheme_register(const char *name, const xc_shm_handlers_t *handlers) /* {{{ */ { int i; for (i = 0; i < 10; i ++) { if (!xc_shm_schemes[i].name) { xc_shm_schemes[i].name = name; xc_shm_schemes[i].handlers = handlers; return 1; } } return 0; } /* }}} */ const xc_shm_handlers_t *xc_shm_scheme_find(const char *name) /* {{{ */ { int i; for (i = 0; i < 10 && xc_shm_schemes[i].name; i ++) { if (strcmp(xc_shm_schemes[i].name, name) == 0) { return xc_shm_schemes[i].handlers; } } return NULL; } /* }}} */ xc_shm_scheme_t *xc_shm_scheme_first() /* {{{ */ { return xc_shm_schemes; } /* }}} */ xc_shm_scheme_t *xc_shm_scheme_next(xc_shm_scheme_t *scheme) /* {{{ */ { scheme ++; return scheme->name ? scheme : NULL; } /* }}} */ const char *xc_shm_scheme_name(xc_shm_scheme_t *scheme) /* {{{ */ { assert(scheme); return scheme->name; } /* }}} */ xc_shm_t *xc_shm_init(const char *type, xc_shmsize_t size, int readonly_protection, const void *arg1, const void *arg2) /* {{{ */ { const xc_shm_handlers_t *handlers = xc_shm_scheme_find(type); if (handlers) { xc_shm_t *shm = handlers->init(size, readonly_protection, arg1, arg2); if (shm) { shm->handlers = handlers; } return shm; } return NULL; } /* }}} */ void xc_shm_destroy(xc_shm_t *shm) /* {{{ */ { shm->handlers->destroy(shm); } /* }}} */ xcache-3.1.0/xcache/xc_shm.h0000644000175000010010000000424412157744741014053 0ustar mOoNone#ifndef XC_SHM_H #define XC_SHM_H #include typedef struct _xc_shm_handlers_t xc_shm_handlers_t; #ifndef XC_SHM_IMPL struct _xc_shm_t { const xc_shm_handlers_t *handlers; }; #define XC_SHM_IMPL _xc_shm_t #endif typedef struct XC_SHM_IMPL xc_shm_t; typedef size_t xc_shmsize_t; /* shm */ #define XC_SHM_CAN_READONLY(func) int func(xc_shm_t *shm) #define XC_SHM_IS_READWRITE(func) int func(xc_shm_t *shm, const void *p) #define XC_SHM_IS_READONLY(func) int func(xc_shm_t *shm, const void *p) #define XC_SHM_TO_READWRITE(func) void *func(xc_shm_t *shm, void *p) #define XC_SHM_TO_READONLY(func) void *func(xc_shm_t *shm, void *p) #define XC_SHM_INIT(func) xc_shm_t *func(xc_shmsize_t size, int readonly_protection, const void *arg1, const void *arg2) #define XC_SHM_DESTROY(func) void func(xc_shm_t *shm) #define XC_SHM_MEMINIT(func) void *func(xc_shm_t *shm, xc_shmsize_t size) #define XC_SHM_MEMDESTROY(func) void func(void *mem) #define XC_SHM_HANDLERS(name) { \ xc_##name##_can_readonly \ , xc_##name##_is_readwrite \ , xc_##name##_is_readonly \ , xc_##name##_to_readwrite \ , xc_##name##_to_readonly \ \ , xc_##name##_init \ , xc_##name##_destroy \ \ , xc_##name##_meminit \ , xc_##name##_memdestroy \ } struct _xc_shm_handlers_t { XC_SHM_CAN_READONLY((*can_readonly)); XC_SHM_IS_READWRITE((*is_readwrite)); XC_SHM_IS_READONLY((*is_readonly)); XC_SHM_TO_READWRITE((*to_readwrite)); XC_SHM_TO_READONLY((*to_readonly)); XC_SHM_INIT((*init)); XC_SHM_DESTROY((*destroy)); XC_SHM_MEMINIT((*meminit)); XC_SHM_MEMDESTROY((*memdestroy)); }; typedef struct _xc_shm_scheme_t xc_shm_scheme_t; void xc_shm_init_modules(); int xc_shm_scheme_register(const char *name, const xc_shm_handlers_t *handlers); const xc_shm_handlers_t *xc_shm_scheme_find(const char *name); xc_shm_scheme_t *xc_shm_scheme_first(); xc_shm_scheme_t *xc_shm_scheme_next(xc_shm_scheme_t *scheme); const char *xc_shm_scheme_name(xc_shm_scheme_t *scheme); xc_shm_t *xc_shm_init(const char *type, xc_shmsize_t size, int readonly_protection, const void *arg1, const void *arg2); void xc_shm_destroy(xc_shm_t *shm); #endif xcache-3.1.0/xcache/xc_shm_mmap.c0000644000175000010010000001522612157744740015061 0ustar mOoNone #include #include #include #include #include /* mmap */ #ifdef ZEND_WIN32 # define ftruncate chsize # define getuid() 0 # include # define XCacheCreateFileMapping(size, perm, name) \ CreateFileMapping(INVALID_HANDLE_VALUE, NULL, perm, (sizeof(xc_shmsize_t) > 4) ? size >> 32 : 0, size & 0xffffffff, name) # define XCACHE_MAP_FAILED NULL # define munmap(p, s) UnmapViewOfFile(p) #else # include /* make sure to mark(change) it to NULL to keep consistent */ # define XCACHE_MAP_FAILED MAP_FAILED #endif #include #include #include #ifndef ZEND_WIN32 #include #endif #include "php.h" #define XC_SHM_IMPL _xc_mmap_shm_t #include "xc_shm.h" #include "xc_utils.h" #ifndef max #define max(a, b) ((a) < (b) ? (b) : (a)) #endif /* {{{ xc_shm_t */ struct _xc_mmap_shm_t { xc_shm_handlers_t *handlers; zend_bool disabled; void *ptr; void *ptr_ro; long diff; xc_shmsize_t size; xc_shmsize_t memoffset; char *name; #ifdef ZEND_WIN32 HANDLE hmap; HANDLE hmap_ro; #else int newfile; #endif }; /* }}} */ #define CHECK(x, e) do { if ((x) == NULL) { zend_error(E_ERROR, "XCache: " e); goto err; } } while (0) #define PTR_ADD(ptr, v) (((char *) (ptr)) + (v)) #define PTR_SUB(ptr, v) (((char *) (ptr)) - (v)) static XC_SHM_CAN_READONLY(xc_mmap_can_readonly) /* {{{ */ { return shm->ptr_ro != NULL; } /* }}} */ static XC_SHM_IS_READWRITE(xc_mmap_is_readwrite) /* {{{ */ { return p >= shm->ptr && (char *)p < (char *)shm->ptr + shm->size; } /* }}} */ static XC_SHM_IS_READONLY(xc_mmap_is_readonly) /* {{{ */ { return xc_mmap_can_readonly(shm) && p >= shm->ptr_ro && (char *)p < (char *)shm->ptr_ro + shm->size; } /* }}} */ static XC_SHM_TO_READWRITE(xc_mmap_to_readwrite) /* {{{ */ { if (shm->diff) { assert(xc_mmap_is_readonly(shm, p)); p = PTR_SUB(p, shm->diff); } assert(xc_mmap_is_readwrite(shm, p)); return p; } /* }}} */ static XC_SHM_TO_READONLY(xc_mmap_to_readonly) /* {{{ */ { assert(xc_mmap_is_readwrite(shm, p)); if (shm->diff) { p = PTR_ADD(p, shm->diff); assert(xc_mmap_is_readonly(shm, p)); } return p; } /* }}} */ static XC_SHM_DESTROY(xc_mmap_destroy) /* {{{ */ { if (shm->ptr_ro) { munmap(shm->ptr_ro, shm->size); /* shm->ptr_ro = NULL; */ } if (shm->ptr) { /* shm->size depends on shm->ptr */ munmap(shm->ptr, shm->size); /* shm->ptr = NULL; */ } #ifdef ZEND_WIN32 if (shm->hmap) { CloseHandle(shm->hmap); } if (shm->hmap_ro) { CloseHandle(shm->hmap_ro); } #endif if (shm->name) { #ifndef ZEND_WIN32 # ifdef __CYGWIN__ if (shm->newfile) { unlink(shm->name); } # endif #endif free(shm->name); } /* shm->size = NULL; shm->diff = 0; */ free(shm); return; } /* }}} */ static XC_SHM_INIT(xc_mmap_init) /* {{{ */ { #ifdef ZEND_WIN32 # define TMP_PATH "XCache" #else # define TMP_PATH "/tmp/XCache" int fd = -1; #endif xc_shm_t *shm = NULL; int ro_ok; volatile void *romem; char tmpname[sizeof(TMP_PATH) - 1 + 4 * 10 + 100] = { 0 }; const char *errstr = NULL; const char *path = (const char *) arg1; static int instanceId = 0; CHECK(shm = calloc(1, sizeof(xc_shm_t)), "shm OOM"); shm->size = size; if (path == NULL || !path[0]) { snprintf(tmpname, sizeof(tmpname) - 1, "%s.%d.%d.%d", TMP_PATH, (int) getuid(), (int) getpid(), ++instanceId); path = tmpname; } #ifdef ZEND_WIN32 else { snprintf(tmpname, sizeof(tmpname) - 1, "%s.%d.%d.%d", path, (int) getuid(), (int) getpid(), ++instanceId); path = tmpname; } #endif shm->name = strdup(path); #ifndef ZEND_WIN32 # define XCACHE_MMAP_PERMISSION (S_IRUSR | S_IWUSR) fd = open(shm->name, O_RDWR, XCACHE_MMAP_PERMISSION); if (fd == -1) { /* do not create file in /dev */ if (strncmp(shm->name, "/dev", 4) == 0) { perror(shm->name); errstr = "Cannot open file set by xcache.mmap_path, check the xcache.size/var_size against system limitation"; goto err; } fd = open(shm->name, O_CREAT | O_RDWR, XCACHE_MMAP_PERMISSION); shm->newfile = 1; if (fd == -1) { perror(shm->name); errstr = "Cannot open or create file set by xcache.mmap_path, check the path permission or check xcache.size/var_size against system limitation"; goto err; } } if (ftruncate(fd, size) != 0 && errno != EINVAL) { perror(shm->name); errstr = "Failed to ftruncate the file"; goto err; } #endif #ifdef ZEND_WIN32 shm->hmap = XCacheCreateFileMapping(size, PAGE_READWRITE, shm->name); shm->ptr = (LPSTR) MapViewOfFile(shm->hmap, FILE_MAP_WRITE, 0, 0, 0); #else shm->ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); #endif if (shm->ptr == XCACHE_MAP_FAILED) { perror(shm->name); errstr = "Failed creating file mapping"; shm->ptr = NULL; goto err; } /* {{{ readonly protection, mmap it readonly and check if ptr_ro works */ if (readonly_protection) { ro_ok = 0; #ifdef ZEND_WIN32 shm->hmap_ro = XCacheCreateFileMapping(size, PAGE_READONLY, shm->name); shm->ptr_ro = (LPSTR) MapViewOfFile(shm->hmap_ro, FILE_MAP_READ, 0, 0, 0); #else shm->ptr_ro = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); #endif if (shm->ptr_ro == XCACHE_MAP_FAILED) { shm->ptr_ro = NULL; } romem = shm->ptr_ro; do { if (romem == NULL || romem == shm->ptr) { break; } *(char *)shm->ptr = 1; if (*(char *)romem != 1) { break; } *(char *)shm->ptr = 2; if (*(char *)romem != 2) { break; } ro_ok = 1; } while (0); if (ro_ok) { shm->diff = PTR_SUB(shm->ptr_ro, (char *) shm->ptr); /* no overlap */ assert((xc_shmsize_t) abs(shm->diff) >= size); } else { if (shm->ptr_ro) { munmap(shm->ptr_ro, size); } #ifdef ZEND_WIN32 if (shm->hmap_ro) { CloseHandle(shm->hmap_ro); } #endif shm->ptr_ro = NULL; shm->diff = 0; } } /* }}} */ #ifndef ZEND_WIN32 close(fd); # ifndef __CYGWIN__ if (shm->newfile) { unlink(shm->name); } # endif #endif return shm; err: #ifndef ZEND_WIN32 if (fd != -1) { close(fd); } #endif if (shm) { xc_mmap_destroy(shm); } if (errstr) { fprintf(stderr, "%s\n", errstr); zend_error(E_ERROR, "%s", errstr); } return NULL; } /* }}} */ static XC_SHM_MEMINIT(xc_mmap_meminit) /* {{{ */ { void *mem; if (shm->memoffset + size > shm->size) { zend_error(E_ERROR, "XCache: internal error at %s#%d", __FILE__, __LINE__); return NULL; } mem = PTR_ADD(shm->ptr, shm->memoffset); shm->memoffset += size; return mem; } /* }}} */ static XC_SHM_MEMDESTROY(xc_mmap_memdestroy) /* {{{ */ { } /* }}} */ static xc_shm_handlers_t xc_shm_mmap_handlers = XC_SHM_HANDLERS(mmap); void xc_shm_mmap_register() /* {{{ */ { if (xc_shm_scheme_register("mmap", &xc_shm_mmap_handlers) == 0) { zend_error(E_ERROR, "XCache: failed to register mmap shm_scheme"); } return; } /* }}} */ xcache-3.1.0/xcache/xc_utils.c0000644000175000010010000004132612220455233014403 0ustar mOoNone #include "xcache.h" #include "xcache_globals.h" #include "xc_utils.h" #ifdef ZEND_ENGINE_2_1 #include "zend_vm.h" #endif #include "xc_opcode_spec.h" #include "util/xc_trace.h" #ifndef max #define max(a, b) ((a) < (b) ? (b) : (a)) #endif #ifndef ZEND_VM_SET_OPCODE_HANDLER # define ZEND_VM_SET_OPCODE_HANDLER(opline) do { } while (0) #endif #ifdef ZEND_ENGINE_2_4 # define OP_ZVAL_DTOR(op) do { } while(0) #else # define OP_ZVAL_DTOR(op) do { \ Z_UNSET_ISREF(Z_OP_CONSTANT(op)); \ zval_dtor(&Z_OP_CONSTANT(op)); \ } while(0) #endif /* }}} */ xc_compile_result_t *xc_compile_result_init(xc_compile_result_t *cr, /* {{{ */ zend_op_array *op_array, HashTable *function_table, HashTable *class_table) { assert(cr); cr->op_array = op_array; cr->function_table = function_table; cr->class_table = class_table; return cr; } /* }}} */ xc_compile_result_t *xc_compile_result_init_cur(xc_compile_result_t *cr, zend_op_array *op_array TSRMLS_DC) /* {{{ */ { assert(cr); return xc_compile_result_init(cr, op_array, CG(function_table), CG(class_table)); } /* }}} */ void xc_compile_result_free(xc_compile_result_t *cr) /* {{{ */ { } /* }}} */ typedef struct { apply_func_t applyer; } xc_apply_func_info; static int xc_apply_function(zend_function *zf, xc_apply_func_info *fi TSRMLS_DC) /* {{{ */ { switch (zf->type) { case ZEND_USER_FUNCTION: case ZEND_EVAL_CODE: return fi->applyer(&zf->op_array TSRMLS_CC); break; case ZEND_INTERNAL_FUNCTION: case ZEND_OVERLOADED_FUNCTION: break; EMPTY_SWITCH_DEFAULT_CASE(); } return 0; } /* }}} */ typedef struct { xc_apply_func_info fi; zend_class_entry *ce; } xc_apply_method_info; int xc_apply_method(zend_function *zf, xc_apply_method_info *mi TSRMLS_DC) /* {{{ */ { /* avoid duplicate apply for shadowed method */ #ifdef ZEND_ENGINE_2 if (mi->ce != zf->common.scope) { /* fprintf(stderr, "avoided duplicate %s\n", zf->common.function_name); */ return 0; } #else char *name = zf->common.function_name; int name_s = strlen(name) + 1; zend_class_entry *ce; zend_function *ptr; for (ce = mi->ce->parent; ce; ce = ce->parent) { if (zend_hash_find(&ce->function_table, name, name_s, (void **) &ptr) == SUCCESS) { if (ptr->op_array.refcount == zf->op_array.refcount) { return 0; } } } #endif return xc_apply_function(zf, &mi->fi TSRMLS_CC); } /* }}} */ static int xc_apply_cest(xc_cest_t *cest, xc_apply_func_info *fi TSRMLS_DC) /* {{{ */ { xc_apply_method_info mi; mi.fi = *fi; mi.ce = CestToCePtr(*cest); zend_hash_apply_with_argument(&(CestToCePtr(*cest)->function_table), (apply_func_arg_t) xc_apply_method, &mi TSRMLS_CC); return 0; } /* }}} */ int xc_apply_op_array(xc_compile_result_t *cr, apply_func_t applyer TSRMLS_DC) /* {{{ */ { xc_apply_func_info fi; fi.applyer = applyer; zend_hash_apply_with_argument(cr->function_table, (apply_func_arg_t) xc_apply_function, &fi TSRMLS_CC); zend_hash_apply_with_argument(cr->class_table, (apply_func_arg_t) xc_apply_cest, &fi TSRMLS_CC); return applyer(cr->op_array TSRMLS_CC); } /* }}} */ int xc_undo_pass_two(zend_op_array *op_array TSRMLS_DC) /* {{{ */ { #ifdef ZEND_ENGINE_2 zend_op *opline, *opline_end; #endif #ifdef ZEND_ENGINE_2_4 if (!(op_array->fn_flags & ZEND_ACC_DONE_PASS_TWO)) { return 0; } #else if (!op_array->done_pass_two) { return 0; } #endif #ifdef ZEND_ENGINE_2 opline = op_array->opcodes; opline_end = opline + op_array->last; while (opline < opline_end) { # ifdef ZEND_ENGINE_2_4 if (opline->op1_type == IS_CONST) { opline->op1.constant = opline->op1.literal - op_array->literals; } if (opline->op2_type == IS_CONST) { opline->op2.constant = opline->op2.literal - op_array->literals; } # endif switch (opline->opcode) { # ifdef ZEND_GOTO case ZEND_GOTO: # endif case ZEND_JMP: # ifdef ZEND_FAST_CALL case ZEND_FAST_CALL: # endif assert(Z_OP(opline->op1).jmp_addr >= op_array->opcodes); assert((zend_uint) (Z_OP(opline->op1).jmp_addr - op_array->opcodes) < op_array->last); Z_OP(opline->op1).opline_num = Z_OP(opline->op1).jmp_addr - op_array->opcodes; break; case ZEND_JMPZ: case ZEND_JMPNZ: case ZEND_JMPZ_EX: case ZEND_JMPNZ_EX: # ifdef ZEND_JMP_SET case ZEND_JMP_SET: # endif # ifdef ZEND_JMP_SET_VAR case ZEND_JMP_SET_VAR: # endif assert(Z_OP(opline->op2).jmp_addr >= op_array->opcodes); assert((zend_uint) (Z_OP(opline->op2).jmp_addr - op_array->opcodes) < op_array->last); Z_OP(opline->op2).opline_num = Z_OP(opline->op2).jmp_addr - op_array->opcodes; break; } opline++; } #endif /* ZEND_ENGINE_2 */ #ifdef ZEND_ENGINE_2_4 op_array->fn_flags &= ~ZEND_ACC_DONE_PASS_TWO; #else op_array->done_pass_two = 0; #endif return 0; } /* }}} */ int xc_redo_pass_two(zend_op_array *op_array TSRMLS_DC) /* {{{ */ { #ifdef ZEND_ENGINE_2 zend_op *opline, *opline_end; #endif #ifdef ZEND_ENGINE_2_4 zend_literal *literal = op_array->literals; #endif #ifdef ZEND_ENGINE_2_4 if ((op_array->fn_flags & ZEND_ACC_DONE_PASS_TWO)) { return 0; } #else if (op_array->done_pass_two) { return 0; } #endif /* op_array->opcodes = (zend_op *) erealloc(op_array->opcodes, sizeof(zend_op)*op_array->last); op_array->size = op_array->last; */ #ifdef ZEND_ENGINE_2_4 if (literal) { zend_literal *literal_end = literal + op_array->last_literal; while (literal < literal_end) { Z_SET_ISREF(literal->constant); Z_SET_REFCOUNT(literal->constant, 2); /* Make sure is_ref won't be reset */ literal++; } } #endif #ifdef ZEND_ENGINE_2 opline = op_array->opcodes; opline_end = opline + op_array->last; while (opline < opline_end) { # ifdef ZEND_ENGINE_2_4 if (opline->op1_type == IS_CONST) { opline->op1.literal = op_array->literals + opline->op1.constant; } if (opline->op2_type == IS_CONST) { opline->op2.literal = op_array->literals + opline->op2.constant; } # else if (Z_OP_TYPE(opline->op1) == IS_CONST) { Z_SET_ISREF(Z_OP_CONSTANT(opline->op1)); Z_SET_REFCOUNT(Z_OP_CONSTANT(opline->op1), 2); /* Make sure is_ref won't be reset */ } if (Z_OP_TYPE(opline->op2) == IS_CONST) { Z_SET_ISREF(Z_OP_CONSTANT(opline->op2)); Z_SET_REFCOUNT(Z_OP_CONSTANT(opline->op2), 2); } # endif switch (opline->opcode) { # ifdef ZEND_GOTO case ZEND_GOTO: # endif case ZEND_JMP: # ifdef ZEND_FAST_CALL case ZEND_FAST_CALL: # endif assert(Z_OP(opline->op1).opline_num < op_array->last); Z_OP(opline->op1).jmp_addr = op_array->opcodes + Z_OP(opline->op1).opline_num; break; case ZEND_JMPZ: case ZEND_JMPNZ: case ZEND_JMPZ_EX: case ZEND_JMPNZ_EX: # ifdef ZEND_JMP_SET case ZEND_JMP_SET: # endif # ifdef ZEND_JMP_SET_VAR case ZEND_JMP_SET_VAR: # endif assert(Z_OP(opline->op2).opline_num < op_array->last); Z_OP(opline->op2).jmp_addr = op_array->opcodes + Z_OP(opline->op2).opline_num; break; } /* ZEND_VM_SET_OPCODE_HANDLER(opline); this is not undone, don't redo. only do this for loader */ opline++; } #endif /* ZEND_ENGINE_2 */ #ifdef ZEND_ENGINE_2_4 op_array->fn_flags |= ZEND_ACC_DONE_PASS_TWO; #else op_array->done_pass_two = 1; #endif return 0; } /* }}} */ static void xc_fix_opcode_ex_znode(int tofix, xc_op_spec_t spec, Z_OP_TYPEOF_TYPE *op_type, znode_op *op, int type TSRMLS_DC) /* {{{ */ { #ifdef ZEND_ENGINE_2 if ((*op_type != IS_UNUSED && (spec == OPSPEC_UCLASS || spec == OPSPEC_CLASS)) || spec == OPSPEC_FETCH) { if (tofix) { switch (*op_type) { case IS_VAR: case IS_TMP_VAR: break; default: /* TODO: data lost, find a way to keep it */ /* assert(*op_type == IS_CONST); */ *op_type = IS_TMP_VAR; } } } switch (*op_type) { case IS_TMP_VAR: case IS_VAR: if (tofix) { Z_OP(*op).var /= sizeof(temp_variable); } else { Z_OP(*op).var *= sizeof(temp_variable); } } #endif } /* }}} */ static void xc_fix_opcode_ex(zend_op_array *op_array, int tofix TSRMLS_DC) /* {{{ */ { zend_op *opline; zend_uint i; opline = op_array->opcodes; for (i = 0; i < op_array->last; i ++, opline ++) { /* 3rd optimizer may have ... */ if (opline->opcode < xc_get_opcode_spec_count()) { const xc_opcode_spec_t *spec; spec = xc_get_opcode_spec(opline->opcode); xc_fix_opcode_ex_znode(tofix, spec->op1, &Z_OP_TYPE(opline->op1), &opline->op1, 0 TSRMLS_CC); xc_fix_opcode_ex_znode(tofix, spec->op2, &Z_OP_TYPE(opline->op2), &opline->op2, 1 TSRMLS_CC); xc_fix_opcode_ex_znode(tofix, spec->res, &Z_OP_TYPE(opline->result), &opline->result, 2 TSRMLS_CC); } } } /* }}} */ int xc_fix_opcode(zend_op_array *op_array TSRMLS_DC) /* {{{ */ { xc_fix_opcode_ex(op_array, 1 TSRMLS_CC); return 0; } /* }}} */ int xc_undo_fix_opcode(zend_op_array *op_array TSRMLS_DC) /* {{{ */ { xc_fix_opcode_ex(op_array, 0 TSRMLS_CC); return 0; } /* }}} */ #ifndef ZEND_COMPILE_DELAYED_BINDING int xc_foreach_early_binding_class(zend_op_array *op_array, xc_foreach_early_binding_class_cb callback, void *data TSRMLS_DC) /* {{{ */ { zend_op *opline, *begin, *opline_end, *next = NULL; opline = begin = op_array->opcodes; opline_end = opline + op_array->last; while (opline < opline_end) { switch (opline->opcode) { #ifdef ZEND_GOTO case ZEND_GOTO: #endif case ZEND_JMP: #ifdef ZEND_FAST_CALL case ZEND_FAST_CALL: #endif next = begin + Z_OP(opline->op1).opline_num; break; case ZEND_JMPZNZ: next = begin + max(Z_OP(opline->op2).opline_num, opline->extended_value); break; case ZEND_JMPZ: case ZEND_JMPNZ: case ZEND_JMPZ_EX: case ZEND_JMPNZ_EX: #ifdef ZEND_JMP_SET case ZEND_JMP_SET: #endif #ifdef ZEND_JMP_SET_VAR case ZEND_JMP_SET_VAR: #endif next = begin + Z_OP(opline->op2).opline_num; break; case ZEND_RETURN: opline = opline_end; break; #ifdef ZEND_ENGINE_2 case ZEND_DECLARE_INHERITED_CLASS: callback(opline, opline - begin, data TSRMLS_CC); break; #else case ZEND_DECLARE_FUNCTION_OR_CLASS: if (opline->extended_value == ZEND_DECLARE_INHERITED_CLASS) { callback(opline, opline - begin, data TSRMLS_CC); } break; #endif } if (opline < next) { opline = next; } else { opline ++; } } return SUCCESS; } /* }}} */ int xc_do_early_binding(zend_op_array *op_array, HashTable *class_table, int oplineno TSRMLS_DC) /* {{{ */ { zend_op *opline; TRACE("binding %d", oplineno); assert(oplineno >= 0); /* do early binding */ opline = &(op_array->opcodes[oplineno]); switch (opline->opcode) { #ifdef ZEND_ENGINE_2 case ZEND_DECLARE_INHERITED_CLASS: { zval *parent_name; zend_class_entry **pce; /* don't early-bind classes that implement interfaces */ if ((opline + 1)->opcode == ZEND_FETCH_CLASS && (opline + 2)->opcode == ZEND_ADD_INTERFACE) { return FAILURE; } parent_name = &(Z_OP_CONSTANT((opline - 1)->op2)); TRACE("binding with parent %s", Z_STRVAL_P(parent_name)); if (zend_lookup_class(Z_STRVAL_P(parent_name), Z_STRLEN_P(parent_name), &pce TSRMLS_CC) == FAILURE) { return FAILURE; } if (do_bind_inherited_class(opline, class_table, *pce, 1 TSRMLS_CC) == NULL) { return FAILURE; } } /* clear unnecessary ZEND_FETCH_CLASS opcode */ if (opline > op_array->opcodes && (opline - 1)->opcode == ZEND_FETCH_CLASS) { zend_op *fetch_class_opline = opline - 1; TRACE("%s %p", Z_STRVAL(Z_OP_CONSTANT(fetch_class_opline->op2)), Z_STRVAL(Z_OP_CONSTANT(fetch_class_opline->op2))); OP_ZVAL_DTOR(fetch_class_opline->op2); fetch_class_opline->opcode = ZEND_NOP; ZEND_VM_SET_OPCODE_HANDLER(fetch_class_opline); memset(&fetch_class_opline->op1, 0, sizeof(znode)); memset(&fetch_class_opline->op2, 0, sizeof(znode)); SET_UNUSED(fetch_class_opline->op1); SET_UNUSED(fetch_class_opline->op2); SET_UNUSED(fetch_class_opline->result); } /* clear unnecessary ZEND_VERIFY_ABSTRACT_CLASS opcode */ if ((opline + 1)->opcode == ZEND_VERIFY_ABSTRACT_CLASS) { zend_op *abstract_op = opline + 1; memset(abstract_op, 0, sizeof(abstract_op[0])); abstract_op->lineno = 0; SET_UNUSED(abstract_op->op1); SET_UNUSED(abstract_op->op2); SET_UNUSED(abstract_op->result); abstract_op->opcode = ZEND_NOP; ZEND_VM_SET_OPCODE_HANDLER(abstract_op); } #else case ZEND_DECLARE_FUNCTION_OR_CLASS: if (do_bind_function_or_class(opline, NULL, class_table, 1) == FAILURE) { return FAILURE; } #endif break; default: return FAILURE; } zend_hash_del(class_table, Z_OP_CONSTANT(opline->op1).value.str.val, Z_OP_CONSTANT(opline->op1).value.str.len); OP_ZVAL_DTOR(opline->op1); OP_ZVAL_DTOR(opline->op2); opline->opcode = ZEND_NOP; ZEND_VM_SET_OPCODE_HANDLER(opline); memset(&opline->op1, 0, sizeof(znode)); memset(&opline->op2, 0, sizeof(znode)); SET_UNUSED(opline->op1); SET_UNUSED(opline->op2); return SUCCESS; } /* }}} */ #endif #ifdef HAVE_XCACHE_CONSTANT void xc_install_constant(ZEND_24(NOTHING, const) char *filename, zend_constant *constant, zend_uchar type, const24_zstr key, uint len, ulong h TSRMLS_DC) /* {{{ */ { if (zend_u_hash_add(EG(zend_constants), type, key, len, constant, sizeof(zend_constant), NULL ) == FAILURE) { CG(zend_lineno) = 0; #ifdef IS_UNICODE zend_error(E_NOTICE, "Constant %R already defined", type, key); #else zend_error(E_NOTICE, "Constant %s already defined", key); #endif free(ZSTR_V(constant->name)); if (!(constant->flags & CONST_PERSISTENT)) { zval_dtor(&constant->value); } } } /* }}} */ #endif void xc_install_function(ZEND_24(NOTHING, const) char *filename, zend_function *func, zend_uchar type, const24_zstr key, uint len, ulong h TSRMLS_DC) /* {{{ */ { zend_bool istmpkey; if (func->type == ZEND_USER_FUNCTION) { #ifdef IS_UNICODE istmpkey = (type == IS_STRING && ZSTR_S(key)[0] == 0) || ZSTR_U(key)[0] == 0; #else istmpkey = ZSTR_S(key)[0] == 0; #endif if (istmpkey) { zend_u_hash_update(CG(function_table), type, key, len, func, sizeof(zend_op_array), NULL ); } else if (zend_u_hash_add(CG(function_table), type, key, len, func, sizeof(zend_op_array), NULL ) == FAILURE) { CG(zend_lineno) = ZESW(func->op_array.opcodes[0].lineno, func->op_array.line_start); #ifdef IS_UNICODE zend_error(E_ERROR, "Cannot redeclare %R()", type, key); #else zend_error(E_ERROR, "Cannot redeclare %s()", key); #endif } } } /* }}} */ ZESW(xc_cest_t *, void) xc_install_class(ZEND_24(NOTHING, const) char *filename, xc_cest_t *cest, int oplineno, zend_uchar type, const24_zstr key, uint len, ulong h TSRMLS_DC) /* {{{ */ { zend_bool istmpkey; zend_class_entry *cep = CestToCePtr(*cest); ZESW(void *stored_ce_ptr, NOTHING); #ifdef IS_UNICODE istmpkey = (type == IS_STRING && ZSTR_S(key)[0] == 0) || ZSTR_U(key)[0] == 0; #else istmpkey = ZSTR_S(key)[0] == 0; #endif if (istmpkey) { zend_u_hash_quick_update(CG(class_table), type, key, len, h, cest, sizeof(xc_cest_t), ZESW(&stored_ce_ptr, NULL) ); #ifndef ZEND_COMPILE_DELAYED_BINDING if (oplineno != -1) { xc_do_early_binding(CG(active_op_array), CG(class_table), oplineno TSRMLS_CC); } #endif } else if (zend_u_hash_quick_add(CG(class_table), type, key, len, h, cest, sizeof(xc_cest_t), ZESW(&stored_ce_ptr, NULL) ) == FAILURE) { CG(zend_lineno) = ZESW(0, Z_CLASS_INFO(*cep).line_start); #ifdef IS_UNICODE zend_error(E_ERROR, "Cannot redeclare class %R", type, cep->name); #else zend_error(E_ERROR, "Cannot redeclare class %s", cep->name); #endif assert(oplineno == -1); } ZESW(return (xc_cest_t *) stored_ce_ptr, NOTHING); } /* }}} */ void xc_hash_copy_if(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size, xc_if_func_t checker) /* {{{ */ { Bucket *p; void *new_entry; zend_bool setTargetPointer; setTargetPointer = !target->pInternalPointer; p = source->pListHead; while (p) { if (checker(p->pData)) { if (p->nKeyLength) { zend_u_hash_quick_update(target, p->key.type, ZSTR(BUCKET_KEY_S(p)), p->nKeyLength, p->h, p->pData, size, &new_entry); } else { zend_hash_index_update(target, p->h, p->pData, size, &new_entry); } if (pCopyConstructor) { pCopyConstructor(new_entry); } if (setTargetPointer && source->pInternalPointer == p) { target->pInternalPointer = new_entry; } } p = p->pListNext; } if (!target->pInternalPointer) { target->pInternalPointer = target->pListHead; } } /* }}} */ #ifdef HAVE_XCACHE_CONSTANT static zend_bool xc_is_internal_zend_constant(zend_constant *c) /* {{{ */ { return (c->flags & CONST_PERSISTENT) ? 1 : 0; } /* }}} */ void xc_zend_constant_ctor(zend_constant *c) /* {{{ */ { assert((c->flags & CONST_PERSISTENT)); ZSTR_U(c->name) = UNISW(zend_strndup, zend_ustrndup)(ZSTR_U(c->name), c->name_len - 1); } /* }}} */ void xc_zend_constant_dtor(zend_constant *c) /* {{{ */ { free(ZSTR_V(c->name)); } /* }}} */ void xc_copy_internal_zend_constants(HashTable *target, HashTable *source) /* {{{ */ { zend_constant tmp_const; xc_hash_copy_if(target, source, (copy_ctor_func_t) xc_zend_constant_ctor, (void *) &tmp_const, sizeof(zend_constant), (xc_if_func_t) xc_is_internal_zend_constant); } /* }}} */ #endif xcache-3.1.0/xcache/xc_utils.h0000644000175000010010000000467412206607320014415 0ustar mOoNone#include "xcache.h" #include "xc_compatibility.h" #define XCACHE_STRS(str) (str), sizeof(str) #define XCACHE_STRL(str) (str), (sizeof(str) - 1) typedef zend_op_array *(zend_compile_file_t)(zend_file_handle *h, int type TSRMLS_DC); typedef struct _xc_compilererror_t { int type; uint lineno; int error_len; char *error; } xc_compilererror_t; typedef struct _xc_compile_result_t { zend_op_array *op_array; HashTable *function_table; HashTable *class_table; } xc_compile_result_t; xc_compile_result_t *xc_compile_result_init(xc_compile_result_t *cr, zend_op_array *op_array, HashTable *function_table, HashTable *class_table); void xc_compile_result_free(xc_compile_result_t *cr); xc_compile_result_t *xc_compile_result_init_cur(xc_compile_result_t *cr, zend_op_array *op_array TSRMLS_DC); /* apply func */ int xc_apply_op_array(xc_compile_result_t *cr, apply_func_t applyer TSRMLS_DC); int xc_undo_pass_two(zend_op_array *op_array TSRMLS_DC); int xc_redo_pass_two(zend_op_array *op_array TSRMLS_DC); int xc_fix_opcode(zend_op_array *op_array TSRMLS_DC); int xc_undo_fix_opcode(zend_op_array *op_array TSRMLS_DC); zend_uchar xc_get_fixed_opcode(zend_uchar opcode, int line); typedef void (*xc_foreach_early_binding_class_cb)(zend_op *opline, int oplineno, void *data TSRMLS_DC); int xc_foreach_early_binding_class(zend_op_array *op_array, xc_foreach_early_binding_class_cb callback, void *data TSRMLS_DC); /* installer */ #ifdef HAVE_XCACHE_CONSTANT void xc_install_constant(ZEND_24(NOTHING, const) char *filename, zend_constant *constant, zend_uchar type, const24_zstr key, uint len, ulong h TSRMLS_DC); #endif void xc_install_function(ZEND_24(NOTHING, const) char *filename, zend_function *func, zend_uchar type, const24_zstr key, uint len, ulong h TSRMLS_DC); ZESW(xc_cest_t *, void) xc_install_class(ZEND_24(NOTHING, const) char *filename, xc_cest_t *cest, int oplineno, zend_uchar type, const24_zstr key, uint len, ulong h TSRMLS_DC); typedef zend_bool (*xc_if_func_t)(void *data); void xc_hash_copy_if(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size, xc_if_func_t checker); #ifdef HAVE_XCACHE_CONSTANT void xc_zend_constant_ctor(zend_constant *c); void xc_zend_constant_dtor(zend_constant *c); void xc_copy_internal_zend_constants(HashTable *target, HashTable *source); #endif #ifndef ZEND_COMPILE_DELAYED_BINDING int xc_do_early_binding(zend_op_array *op_array, HashTable *class_table, int oplineno TSRMLS_DC); #endif xcache-3.1.0/xcache-test.ini0000644000175000010010000000122012225452352014054 0ustar mOoNonedate.timezone = Asia/Shanghai memory_limit = 256M error_reporting = E_ALL|E_STRICT|E_DEPRECATED display_errors = On [xcache] extension_dir="./.libs/" extension=xcache.so xcache.cacher = On xcache.test = 1 xcache.stat = 1 xcache.experimental = On xcache.size = 64M xcache.count = 2 xcache.var_size = 1M xcache.var_count = 2 xcache.var_slots = 1000 ; xcache.mmap_path = "/dev/zero" xcache.mmap_path = "/tmp/xcache" xcache.readonly_protection = Off xcache.optimizer = On xcache.coredump_directory = "/tmp/" ;xcache.coveragedump_directory = "/tmp/pcov/" xcache.coverager = On xcache.admin.user = "test" xcache.admin.pass = "098f6bcd4621d373cade4e832627b4f6" xcache-3.1.0/xcache-zh-gb2312.ini0000644000175000010010000000501612157744737014442 0ustar mOoNone;; ļֻ, php.ini ԱЧ [xcache-common] ;; windows : extension = xcache.so ;; Windows ϵͳ: ; extension = php_xcache.dll [xcache.admin] xcache.admin.enable_auth = On xcache.admin.user = "mOo" ; xcache.admin.pass = md5($) ; ¼ʹ $your_password xcache.admin.pass = "" [xcache] ; Ķѡ ini ޸, гĶĬֵ, ˵ ; ѡײڴ湲ʵַ xcache.shm_scheme = "mmap" ; : xcache.size=0 ; : xcache.size=64M ֮ (>0ֵ) ͬʱעϵͳ mmap xcache.size = 60M ; Ϊ cpu (cat /proc/cpuinfo |grep -c processor) xcache.count = 1 ; ֻǸ hash οֵ, ʵʴ洢Ŀ(phpű/)ɳ xcache.slots = 8K ; Ŀ ttl, 0= xcache.ttl = 0 ; ɨĿʱ, 0=ɨ, ֵΪλ xcache.gc_interval = 0 ; ͬ, ֻԱ xcache.var_size = 4M xcache.var_count = 1 xcache.var_slots = 8K ; xcache_*() ttl Ĭֵ xcache.var_ttl = 0 ; xcache_*() ttl . 0= xcache.var_maxttl = 0 xcache.var_gc_interval = 300 ; /dev/zero ʱЧ xcache.readonly_protection = Off ; *nix ϵͳ, xcache.mmap_path ļ·Ŀ¼. (Զ/) ; ReadonlyProtection, ʹ "/dev/*", ʹ "/tmp/xcache" ; ͬ php 鲻Ṳͬһ /tmp/xcache ; Win32 ϵͳ, xcache.mmap_path=MAP, ļ·. ʹ XCache ۱ͻ xcache.mmap_path = "/dev/zero" ; XCache 쳣ʱ. Ϊ() "/tmp/phpcore/" (ܱ php дļ) xcache.coredump_directory = "" ; Windows. XCache Ա, 򱣳Ĭֵ xcache.coredump_type = 0 ; 쳣ʱԶֹ xcache.disable_on_crash = Off ; ʵԹ () xcache.experimental = Off ; Request ɸ. ini_set, .htaccess xcache.cacher = On xcache.stat = On xcache.optimizer = Off [xcache.coverager] ; ܿ󽵵 ; xcache.coverager == On && xcache.coveragedump_directory == "ǿֵ" ʱܲŻ ; per request settings. ini_set, .htaccess ; ô̸ϢɼԼ xcache_coverager_start/stop/get/clean() Ⱥ xcache.coverager = Off xcache.coverager_autostart = On ; php ini ļ ; ȷĿ¼ܱ coverage viewer űȡ (ע open_basedir) xcache.coveragedump_directory = "" xcache-3.1.0/xcache.c0000644000175000010010000006256012220455234012555 0ustar mOoNone/* {{{ macros */ #include #include #include #include #include "xcache.h" #ifdef HAVE_XCACHE_OPTIMIZER # include "mod_optimizer/xc_optimizer.h" #endif #ifdef HAVE_XCACHE_CACHER # include "mod_cacher/xc_cacher.h" #endif #ifdef HAVE_XCACHE_COVERAGER # include "mod_coverager/xc_coverager.h" #endif #ifdef HAVE_XCACHE_DISASSEMBLER # include "mod_disassembler/xc_disassembler.h" #endif #include "xcache_globals.h" #include "xcache/xc_extension.h" #include "xcache/xc_ini.h" #include "xcache/xc_const_string.h" #include "xcache/xc_opcode_spec.h" #include "xcache/xc_utils.h" #include "util/xc_stack.h" #include "php.h" #include "ext/standard/info.h" #include "ext/standard/php_string.h" #include "SAPI.h" /* }}} */ /* {{{ globals */ static char *xc_coredump_dir = NULL; #ifdef ZEND_WIN32 static zend_ulong xc_coredump_type = 0; #endif static zend_bool xc_disable_on_crash = 0; static zend_compile_file_t *old_compile_file = NULL; zend_bool xc_test = 0; ZEND_DECLARE_MODULE_GLOBALS(xcache) /* }}} */ static zend_op_array *xc_check_initial_compile_file(zend_file_handle *h, int type TSRMLS_DC) /* {{{ */ { XG(initial_compile_file_called) = 1; return old_compile_file(h, type TSRMLS_CC); } /* }}} */ /* devel helper function */ #if 0 static void xc_list_extensions() /* {{{ */ { zend_llist_element *element; zend_extension *ext; fprintf(stderr, "extensions:\n"); for (element = zend_extensions.head; element; element = element->next) { ext = (zend_extension *) element->data; fprintf(stderr, " - %s\n", ext->name); } } /* }}} */ #endif /* module helper function */ static int xc_init_constant(int module_number TSRMLS_DC) /* {{{ */ { typedef struct { const char *prefix; zend_uchar (*getsize)(); const char *(*get)(zend_uchar i); } xc_nameinfo_t; xc_nameinfo_t nameinfos[] = { { "", xc_get_op_type_count, xc_get_op_type }, { "", xc_get_data_type_count, xc_get_data_type }, { "", xc_get_opcode_count, xc_get_opcode }, { "OPSPEC_", xc_get_op_spec_count, xc_get_op_spec }, { NULL, NULL, NULL } }; int undefdone = 0; xc_nameinfo_t *p; for (p = nameinfos; p->getsize; p ++) { zend_uchar i, count; char const_name[96]; int const_name_len; count = p->getsize(); for (i = 0; i < count; i ++) { const char *name = p->get(i); if (!name) continue; if (strcmp(name, "UNDEF") == 0) { if (undefdone) continue; undefdone = 1; } const_name_len = snprintf(const_name, sizeof(const_name), "XC_%s%s", p->prefix, name); zend_register_long_constant(const_name, const_name_len+1, i, CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC); } } zend_register_long_constant(XCACHE_STRS("XC_SIZEOF_TEMP_VARIABLE"), sizeof(temp_variable), CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC); zend_register_stringl_constant(XCACHE_STRS("XCACHE_VERSION"), XCACHE_STRL(XCACHE_VERSION), CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC); zend_register_stringl_constant(XCACHE_STRS("XCACHE_MODULES"), XCACHE_STRL(XCACHE_MODULES), CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC); return 0; } /* }}} */ /* {{{ PHP_GINIT_FUNCTION(xcache) */ #ifdef __GNUC__ #pragma GCC push_options #pragma GCC diagnostic ignored "-Wshadow" #endif #ifdef PHP_GINIT_FUNCTION static PHP_GINIT_FUNCTION(xcache) #else static void xc_init_globals(zend_xcache_globals* xcache_globals TSRMLS_DC) #endif { #ifdef __GNUC__ #pragma GCC pop_options #endif memset(xcache_globals, 0, sizeof(zend_xcache_globals)); #ifdef HAVE_XCACHE_CONSTANT zend_hash_init_ex(&xcache_globals->internal_constant_table, 1, NULL, (dtor_func_t) xc_zend_constant_dtor, 1, 0); #endif zend_hash_init_ex(&xcache_globals->internal_function_table, 1, NULL, NULL, 1, 0); zend_hash_init_ex(&xcache_globals->internal_class_table, 1, NULL, NULL, 1, 0); } /* }}} */ /* {{{ PHP_GSHUTDOWN_FUNCTION(xcache) */ static #ifdef PHP_GSHUTDOWN_FUNCTION PHP_GSHUTDOWN_FUNCTION(xcache) #else void xc_shutdown_globals(zend_xcache_globals* xcache_globals TSRMLS_DC) #endif { size_t i; if (xcache_globals->php_holds != NULL) { for (i = 0; i < xcache_globals->php_holds_size; i ++) { xc_stack_destroy(&xcache_globals->php_holds[i]); } free(xcache_globals->php_holds); xcache_globals->php_holds = NULL; xcache_globals->php_holds_size = 0; } if (xcache_globals->var_holds != NULL) { for (i = 0; i < xcache_globals->var_holds_size; i ++) { xc_stack_destroy(&xcache_globals->var_holds[i]); } free(xcache_globals->var_holds); xcache_globals->var_holds = NULL; xcache_globals->var_holds_size = 0; } if (xcache_globals->internal_table_copied) { #ifdef HAVE_XCACHE_CONSTANT zend_hash_destroy(&xcache_globals->internal_constant_table); #endif zend_hash_destroy(&xcache_globals->internal_function_table); zend_hash_destroy(&xcache_globals->internal_class_table); } } /* }}} */ /* {{{ proto int xcache_get_refcount(mixed variable) XCache internal uses only: Get reference count of variable */ PHP_FUNCTION(xcache_get_refcount) { zval *variable; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &variable) == FAILURE) { RETURN_NULL(); } RETURN_LONG(Z_REFCOUNT(*variable)); } /* }}} */ /* {{{ proto bool xcache_get_isref(mixed variable) XCache internal uses only: Check if variable data is marked referenced */ #ifdef ZEND_BEGIN_ARG_INFO_EX ZEND_BEGIN_ARG_INFO_EX(arginfo_xcache_get_isref, 0, 0, 1) ZEND_ARG_INFO(1, variable) ZEND_END_ARG_INFO() #else static unsigned char arginfo_xcache_get_isref[] = { 1, BYREF_FORCE }; #endif PHP_FUNCTION(xcache_get_isref) { zval *variable; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &variable) == FAILURE) { RETURN_NULL(); } RETURN_BOOL(Z_ISREF(*variable) && Z_REFCOUNT(*variable) >= 3); } /* }}} */ #ifdef HAVE_XCACHE_DPRINT /* {{{ proto bool xcache_dprint(mixed value) Prints variable (or value) internal struct (debug only) */ #include "xc_processor.h" PHP_FUNCTION(xcache_dprint) { zval *value; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) == FAILURE) { return; } xc_dprint_zval(value, 0 TSRMLS_CC); } /* }}} */ #endif /* {{{ proto string xcache_asm(string filename) */ #ifdef HAVE_XCACHE_ASSEMBLER PHP_FUNCTION(xcache_asm) { } #endif /* }}} */ /* {{{ proto string xcache_encode(string filename) Encode php file into XCache opcode encoded format */ #ifdef HAVE_XCACHE_ENCODER PHP_FUNCTION(xcache_encode) { } #endif /* }}} */ /* {{{ proto bool xcache_decode_file(string filename) Decode(load) opcode from XCache encoded format file */ #ifdef HAVE_XCACHE_DECODER PHP_FUNCTION(xcache_decode_file) { } #endif /* }}} */ /* {{{ proto bool xcache_decode_string(string data) Decode(load) opcode from XCache encoded format data */ #ifdef HAVE_XCACHE_DECODER PHP_FUNCTION(xcache_decode_string) { } #endif /* }}} */ /* {{{ xc_call_getter */ typedef const char *(xc_name_getter_t)(zend_uchar type); static void xc_call_getter(xc_name_getter_t getter, int count, INTERNAL_FUNCTION_PARAMETERS) { long spec; const char *name; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &spec) == FAILURE) { return; } if (spec >= 0 && spec < count) { name = getter((zend_uchar) spec); if (name) { /* RETURN_STRING */ int len = (int) strlen(name); return_value->value.str.len = len; return_value->value.str.val = estrndup(name, len); return_value->type = IS_STRING; return; } } RETURN_NULL(); } /* }}} */ /* {{{ proto string xcache_get_op_type(int op_type) */ PHP_FUNCTION(xcache_get_op_type) { xc_call_getter(xc_get_op_type, xc_get_op_type_count(), INTERNAL_FUNCTION_PARAM_PASSTHRU); } /* }}} */ /* {{{ proto string xcache_get_data_type(int type) */ PHP_FUNCTION(xcache_get_data_type) { xc_call_getter(xc_get_data_type, xc_get_data_type_count(), INTERNAL_FUNCTION_PARAM_PASSTHRU); } /* }}} */ /* {{{ proto string xcache_get_opcode(int opcode) */ PHP_FUNCTION(xcache_get_opcode) { xc_call_getter(xc_get_opcode, xc_get_opcode_count(), INTERNAL_FUNCTION_PARAM_PASSTHRU); } /* }}} */ /* {{{ proto string xcache_get_op_spec(int op_type) */ PHP_FUNCTION(xcache_get_op_spec) { xc_call_getter(xc_get_op_spec, xc_get_op_spec_count(), INTERNAL_FUNCTION_PARAM_PASSTHRU); } /* }}} */ /* {{{ proto string xcache_get_opcode_spec(int opcode) */ PHP_FUNCTION(xcache_get_opcode_spec) { long spec; const xc_opcode_spec_t *opspec; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &spec) == FAILURE) { return; } if ((zend_uchar) spec <= xc_get_opcode_spec_count()) { opspec = xc_get_opcode_spec((zend_uchar) spec); if (opspec) { array_init(return_value); add_assoc_long_ex(return_value, XCACHE_STRS("ext"), opspec->ext); add_assoc_long_ex(return_value, XCACHE_STRS("op1"), opspec->op1); add_assoc_long_ex(return_value, XCACHE_STRS("op2"), opspec->op2); add_assoc_long_ex(return_value, XCACHE_STRS("res"), opspec->res); return; } } RETURN_NULL(); } /* }}} */ /* {{{ proto mixed xcache_get_special_value(zval value) XCache internal use only: For decompiler to get static value with type fixed */ PHP_FUNCTION(xcache_get_special_value) { zval *value; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) == FAILURE) { return; } switch ((Z_TYPE_P(value) & IS_CONSTANT_TYPE_MASK)) { case IS_CONSTANT: *return_value = *value; zval_copy_ctor(return_value); return_value->type = UNISW(IS_STRING, UG(unicode) ? IS_UNICODE : IS_STRING); break; case IS_CONSTANT_ARRAY: *return_value = *value; zval_copy_ctor(return_value); return_value->type = IS_ARRAY; break; default: if ((Z_TYPE_P(value) & ~IS_CONSTANT_TYPE_MASK)) { *return_value = *value; zval_copy_ctor(return_value); return_value->type &= IS_CONSTANT_TYPE_MASK; } else { RETURN_NULL(); } } } /* }}} */ /* {{{ proto int xcache_get_type(zval value) XCache internal use only for disassembler to get variable type in engine level */ PHP_FUNCTION(xcache_get_type) { zval *value; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) == FAILURE) { return; } RETURN_LONG(Z_TYPE_P(value)); } /* }}} */ /* {{{ proto string xcache_coredump(int op_type) */ PHP_FUNCTION(xcache_coredump) { if (xc_test) { char *null_ptr = NULL; *null_ptr = 0; raise(SIGSEGV); } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "xcache.test must be enabled to test xcache_coredump()"); } } /* }}} */ /* {{{ proto string xcache_is_autoglobal(string name) */ PHP_FUNCTION(xcache_is_autoglobal) { zval *name; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &name) == FAILURE) { return; } #ifdef IS_UNICODE convert_to_unicode(name); #else convert_to_string(name); #endif RETURN_BOOL(zend_u_hash_exists(CG(auto_globals), UG(unicode), Z_STRVAL_P(name), Z_STRLEN_P(name) + 1)); } /* }}} */ static zend_function_entry xcache_functions[] = /* {{{ */ { PHP_FE(xcache_coredump, NULL) #ifdef HAVE_XCACHE_ASSEMBLER PHP_FE(xcache_asm, NULL) #endif #ifdef HAVE_XCACHE_ENCODER PHP_FE(xcache_encode, NULL) #endif #ifdef HAVE_XCACHE_DECODER PHP_FE(xcache_decode_file, NULL) PHP_FE(xcache_decode_string, NULL) #endif PHP_FE(xcache_get_special_value, NULL) PHP_FE(xcache_get_type, NULL) PHP_FE(xcache_get_op_type, NULL) PHP_FE(xcache_get_data_type, NULL) PHP_FE(xcache_get_opcode, NULL) PHP_FE(xcache_get_opcode_spec, NULL) PHP_FE(xcache_is_autoglobal, NULL) PHP_FE(xcache_get_refcount, NULL) PHP_FE(xcache_get_isref, arginfo_xcache_get_isref) #ifdef HAVE_XCACHE_DPRINT PHP_FE(xcache_dprint, NULL) #endif PHP_FE_END }; /* }}} */ #ifdef ZEND_WIN32 #include "dbghelp.h" typedef BOOL (WINAPI *MINIDUMPWRITEDUMP)(HANDLE hProcess, DWORD dwPid, HANDLE hFile, MINIDUMP_TYPE DumpType, CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam ); static PTOP_LEVEL_EXCEPTION_FILTER oldFilter = NULL; static HMODULE dbghelpModule = NULL; static char crash_dumpPath[_MAX_PATH] = { 0 }; static MINIDUMPWRITEDUMP dbghelp_MiniDumpWriteDump = NULL; static LONG WINAPI miniDumperFilter(struct _EXCEPTION_POINTERS *pExceptionInfo) /* {{{ */ { HANDLE fileHandle; LONG ret = EXCEPTION_CONTINUE_SEARCH; SetUnhandledExceptionFilter(oldFilter); /* create the file */ fileHandle = CreateFile(crash_dumpPath, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (fileHandle != INVALID_HANDLE_VALUE) { MINIDUMP_EXCEPTION_INFORMATION exceptionInformation; MINIDUMP_TYPE type = xc_coredump_type ? xc_coredump_type : (MiniDumpNormal|MiniDumpWithDataSegs|MiniDumpWithIndirectlyReferencedMemory); BOOL ok; exceptionInformation.ThreadId = GetCurrentThreadId(); exceptionInformation.ExceptionPointers = pExceptionInfo; exceptionInformation.ClientPointers = FALSE; /* write the dump */ ok = dbghelp_MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), fileHandle, type, &exceptionInformation, NULL, NULL); CloseHandle(fileHandle); if (ok) { zend_error(E_ERROR, "Saved dump file to '%s'", crash_dumpPath); ret = EXCEPTION_EXECUTE_HANDLER; } else { zend_error(E_ERROR, "Failed to save dump file to '%s' (error %d)", crash_dumpPath, GetLastError()); } } else { zend_error(E_ERROR, "Failed to create dump file '%s' (error %d)", crash_dumpPath, GetLastError()); } if (xc_disable_on_crash) { xc_disable_on_crash = 0; xc_cacher_disable(); } return ret; } /* }}} */ static void xcache_restore_crash_handler() /* {{{ */ { if (oldFilter) { SetUnhandledExceptionFilter(oldFilter); oldFilter = NULL; } } /* }}} */ static void xcache_init_crash_handler() /* {{{ */ { /* firstly see if dbghelp.dll is around and has the function we need look next to the EXE first, as the one in System32 might be old (e.g. Windows 2000) */ char dbghelpPath[_MAX_PATH]; if (GetModuleFileName(NULL, dbghelpPath, _MAX_PATH)) { char *slash = strchr(dbghelpPath, '\\'); if (slash) { strcpy(slash + 1, "DBGHELP.DLL"); dbghelpModule = LoadLibrary(dbghelpPath); } } if (!dbghelpModule) { /* load any version we can */ dbghelpModule = LoadLibrary("DBGHELP.DLL"); if (!dbghelpModule) { zend_error(E_ERROR, "Unable to enable crash dump saver: %s", "DBGHELP.DLL not found"); return; } } dbghelp_MiniDumpWriteDump = (MINIDUMPWRITEDUMP)GetProcAddress(dbghelpModule, "MiniDumpWriteDump"); if (!dbghelp_MiniDumpWriteDump) { zend_error(E_ERROR, "Unable to enable crash dump saver: %s", "DBGHELP.DLL too old. Get updated dll and put it aside of php_xcache.dll"); return; } #ifdef XCACHE_VERSION_REVISION #define REVISION "r" XCACHE_VERSION_REVISION #else #define REVISION "" #endif sprintf(crash_dumpPath, "%s\\php-%s-xcache-%s%s-%lu-%lu.dmp", xc_coredump_dir, zend_get_module_version("standard"), XCACHE_VERSION, REVISION, (unsigned long) time(NULL), (unsigned long) GetCurrentProcessId()); #undef REVISION oldFilter = SetUnhandledExceptionFilter(&miniDumperFilter); } /* }}} */ #else /* old signal handlers {{{ */ typedef void (*xc_sighandler_t)(int); #define FOREACH_SIG(sig) static xc_sighandler_t old_##sig##_handler = NULL #include "util/xc_foreachcoresig.h" #undef FOREACH_SIG /* }}} */ static void xcache_signal_handler(int sig); static void xcache_restore_crash_handler() /* {{{ */ { #define FOREACH_SIG(sig) do { \ if (old_##sig##_handler != xcache_signal_handler) { \ signal(sig, old_##sig##_handler); \ } \ else { \ signal(sig, SIG_DFL); \ } \ } while (0) #include "util/xc_foreachcoresig.h" #undef FOREACH_SIG } /* }}} */ static void xcache_init_crash_handler() /* {{{ */ { #define FOREACH_SIG(sig) \ old_##sig##_handler = signal(sig, xcache_signal_handler) #include "util/xc_foreachcoresig.h" #undef FOREACH_SIG } /* }}} */ static void xcache_signal_handler(int sig) /* {{{ */ { xcache_restore_crash_handler(); if (xc_coredump_dir && xc_coredump_dir[0]) { if (chdir(xc_coredump_dir) != 0) { /* error, but nothing can do about it * and should'nt print anything which might SEGV again */ } } if (xc_disable_on_crash) { xc_disable_on_crash = 0; xc_cacher_disable(); } raise(sig); } /* }}} */ #endif /* {{{ incompatible zend extensions handling */ typedef struct { const char *name; startup_func_t old_startup; } xc_incompatible_zend_extension_info_t; static xc_incompatible_zend_extension_info_t xc_incompatible_zend_extensions[] = { { "Zend Extension Manager", NULL }, { "Zend Optimizer", NULL }, { "the ionCube PHP Loader", NULL } }; static xc_incompatible_zend_extension_info_t *xc_get_incompatible_zend_extension_info(const char *name) { size_t i; for (i = 0; i < sizeof(xc_incompatible_zend_extensions) / sizeof(xc_incompatible_zend_extensions[0]); ++i) { xc_incompatible_zend_extension_info_t *incompatible_zend_extension_info = &xc_incompatible_zend_extensions[i]; if (strcmp(incompatible_zend_extension_info->name, name) == 0) { return incompatible_zend_extension_info; } } return NULL; } /* }}} */ static void xc_zend_llist_add_element(zend_llist *list, zend_llist_element *element) /* {{{ */ { if (!zend_extensions.head) { zend_extensions.head = zend_extensions.tail = element; } else { zend_extensions.tail->next = element; element->prev = zend_extensions.tail; zend_extensions.tail = element; } } /* }}} */ static int xc_incompatible_zend_extension_startup_hook(zend_extension *extension) /* {{{ */ { xc_incompatible_zend_extension_info_t *incompatible_zend_extension_info = xc_get_incompatible_zend_extension_info(extension->name); int status; zend_bool catched = 0; zend_llist saved_zend_extensions_container; /* without elements */ zend_llist_element **saved_zend_extensions_elments; size_t new_zend_extensions_elments_count; zend_llist_element **new_zend_extensions_elments; zend_extension *ext; size_t i; zend_llist_element *element; TSRMLS_FETCH(); /* restore startup hack */ extension->startup = incompatible_zend_extension_info->old_startup; incompatible_zend_extension_info->old_startup = NULL; assert(extension->startup); /* save extensions list */ saved_zend_extensions_container = zend_extensions; saved_zend_extensions_elments = malloc(sizeof(zend_llist_element *) * saved_zend_extensions_container.count); for (i = 0, element = saved_zend_extensions_container.head; element; ++i, element = element->next) { saved_zend_extensions_elments[i] = element; } /* hide all XCache extensions from it */ zend_extensions.head = NULL; zend_extensions.tail = NULL; zend_extensions.count = 0; for (i = 0; i < saved_zend_extensions_container.count; ++i) { element = saved_zend_extensions_elments[i]; element->next = element->prev = NULL; ext = (zend_extension *) element->data; if (!(strcmp(ext->name, XCACHE_NAME) == 0 || strncmp(ext->name, XCACHE_NAME " ", sizeof(XCACHE_NAME " ") - 1) == 0)) { xc_zend_llist_add_element(&zend_extensions, element); ++zend_extensions.count; } } assert(extension->startup != xc_incompatible_zend_extension_startup_hook); zend_try { status = extension->startup(extension); } zend_catch { catched = 1; } zend_end_try(); /* save newly added extensions added by this extension*/ new_zend_extensions_elments_count = zend_extensions.count - 1; new_zend_extensions_elments = NULL; if (new_zend_extensions_elments_count) { new_zend_extensions_elments = malloc(sizeof(zend_llist_element *) * new_zend_extensions_elments_count); element = zend_extensions.head; for (i = 0, element = element->next; element; ++i, element = element->next) { new_zend_extensions_elments[i] = element; } } /* restore original extension list*/ zend_extensions = saved_zend_extensions_container; zend_extensions.head = NULL; zend_extensions.tail = NULL; zend_extensions.count = 0; for (i = 0; i < saved_zend_extensions_container.count; ++i) { element = saved_zend_extensions_elments[i]; element->next = element->prev = NULL; xc_zend_llist_add_element(&zend_extensions, element); ++zend_extensions.count; ext = (zend_extension *) element->data; if (ext == extension && new_zend_extensions_elments_count) { /* add new created extension */ size_t j; for (j = 0; j < new_zend_extensions_elments_count; ++j) { element = new_zend_extensions_elments[j]; element->next = element->prev = NULL; xc_zend_llist_add_element(&zend_extensions, element); ++zend_extensions.count; } } } free(saved_zend_extensions_elments); if (new_zend_extensions_elments) { free(new_zend_extensions_elments); } if (catched) { zend_bailout(); } return status; } /* }}} */ static int xc_zend_startup(zend_extension *extension) /* {{{ */ { zend_llist_position lpos; zend_extension *ext; ext = (zend_extension *) zend_extensions.head->data; if (strcmp(ext->name, XCACHE_NAME) != 0) { zend_error(E_WARNING, "XCache failed to load itself as the before \"%s\". compatibility downgraded", ext->name); } old_compile_file = zend_compile_file; zend_compile_file = xc_check_initial_compile_file; for (ext = (zend_extension *) zend_llist_get_first_ex(&zend_extensions, &lpos); ext; ext = (zend_extension *) zend_llist_get_next_ex(&zend_extensions, &lpos)) { xc_incompatible_zend_extension_info_t *incompatible_zend_extension_info = xc_get_incompatible_zend_extension_info(ext->name); if (incompatible_zend_extension_info) { assert(!incompatible_zend_extension_info->old_startup); incompatible_zend_extension_info->old_startup = ext->startup; ext->startup = xc_incompatible_zend_extension_startup_hook; } } return SUCCESS; } /* }}} */ static void xc_zend_shutdown(zend_extension *extension) /* {{{ */ { } /* }}} */ /* {{{ zend extension definition structure */ static zend_extension xc_zend_extension_entry = { XCACHE_NAME, XCACHE_VERSION, XCACHE_AUTHOR, XCACHE_URL, XCACHE_COPYRIGHT, xc_zend_startup, xc_zend_shutdown, NULL, /* activate_func_t */ NULL, /* deactivate_func_t */ NULL, /* message_handler_func_t */ NULL, /* op_array_handler_func_t */ NULL, /* statement_handler_func_t */ NULL, /* fcall_begin_handler_func_t */ NULL, /* fcall_end_handler_func_t */ NULL, /* op_array_ctor_func_t */ NULL, /* op_array_dtor_func_t */ STANDARD_ZEND_EXTENSION_PROPERTIES }; /* }}} */ /* {{{ PHP_INI */ PHP_INI_BEGIN() PHP_INI_ENTRY1 ("xcache.coredump_directory", "", PHP_INI_SYSTEM, xcache_OnUpdateString, &xc_coredump_dir) #ifdef ZEND_WIN32 PHP_INI_ENTRY1 ("xcache.coredump_type", "0", PHP_INI_SYSTEM, xcache_OnUpdateULong, &xc_coredump_type) #endif PHP_INI_ENTRY1_EX ("xcache.disable_on_crash", "0", PHP_INI_SYSTEM, xcache_OnUpdateBool, &xc_disable_on_crash, zend_ini_boolean_displayer_cb) PHP_INI_ENTRY1_EX ("xcache.test", "0", PHP_INI_SYSTEM, xcache_OnUpdateBool, &xc_test, zend_ini_boolean_displayer_cb) STD_PHP_INI_BOOLEAN("xcache.experimental", "0", PHP_INI_ALL, OnUpdateBool, experimental, zend_xcache_globals, xcache_globals) PHP_INI_END() /* }}} */ static PHP_MINFO_FUNCTION(xcache) /* {{{ */ { php_info_print_table_start(); php_info_print_table_row(2, "XCache Version", XCACHE_VERSION); #ifdef XCACHE_VERSION_REVISION php_info_print_table_row(2, "Revision", "r" XCACHE_VERSION_REVISION); #endif php_info_print_table_row(2, "Modules Built", XCACHE_MODULES); php_info_print_table_end(); DISPLAY_INI_ENTRIES(); } /* }}} */ static PHP_MINIT_FUNCTION(xcache) /* {{{ */ { #ifndef PHP_GINIT ZEND_INIT_MODULE_GLOBALS(xcache, xc_init_globals, xc_shutdown_globals); #endif REGISTER_INI_ENTRIES(); if (xc_coredump_dir && xc_coredump_dir[0]) { xcache_init_crash_handler(); } if (strcmp(sapi_module.name, "cli") == 0) { char *env; if ((env = getenv("XCACHE_TEST")) != NULL) { xc_test = (zend_bool) atoi(env); } } xc_init_constant(module_number TSRMLS_CC); xc_shm_init_modules(); /* must be the first */ xcache_zend_extension_add(&xc_zend_extension_entry, 1); #ifdef HAVE_XCACHE_OPTIMIZER xc_optimizer_startup_module(); #endif #ifdef HAVE_XCACHE_CACHER xc_cacher_startup_module(); #endif #ifdef HAVE_XCACHE_COVERAGER xc_coverager_startup_module(); #endif #ifdef HAVE_XCACHE_DISASSEMBLER xc_disassembler_startup_module(); #endif return SUCCESS; } /* }}} */ static PHP_MSHUTDOWN_FUNCTION(xcache) /* {{{ */ { if (old_compile_file && zend_compile_file == xc_check_initial_compile_file) { zend_compile_file = old_compile_file; old_compile_file = NULL; } if (xc_coredump_dir && xc_coredump_dir[0]) { xcache_restore_crash_handler(); } if (xc_coredump_dir) { pefree(xc_coredump_dir, 1); xc_coredump_dir = NULL; } #ifndef PHP_GINIT # ifdef ZTS ts_free_id(xcache_globals_id); # else xc_shutdown_globals(&xcache_globals TSRMLS_CC); # endif #endif UNREGISTER_INI_ENTRIES(); xcache_zend_extension_remove(&xc_zend_extension_entry); return SUCCESS; } /* }}} */ /* {{{ module dependencies */ #ifdef STANDARD_MODULE_HEADER_EX static zend_module_dep xcache_module_deps[] = { ZEND_MOD_REQUIRED("standard") ZEND_MOD_CONFLICTS("apc") ZEND_MOD_CONFLICTS("eAccelerator") ZEND_MOD_CONFLICTS("Turck MMCache") ZEND_MOD_END }; #endif /* }}} */ /* {{{ module definition structure */ zend_module_entry xcache_module_entry = { #ifdef STANDARD_MODULE_HEADER_EX STANDARD_MODULE_HEADER_EX, NULL, xcache_module_deps, #else STANDARD_MODULE_HEADER, #endif XCACHE_NAME, xcache_functions, PHP_MINIT(xcache), PHP_MSHUTDOWN(xcache), NULL, /* RINIT */ NULL, /* RSHUTDOWN */ PHP_MINFO(xcache), XCACHE_VERSION, #ifdef PHP_GINIT PHP_MODULE_GLOBALS(xcache), PHP_GINIT(xcache), PHP_GSHUTDOWN(xcache), #endif #ifdef ZEND_ENGINE_2 NULL /* ZEND_MODULE_POST_ZEND_DEACTIVATE_N */, #else NULL, NULL, #endif STANDARD_MODULE_PROPERTIES_EX }; #ifdef COMPILE_DL_XCACHE ZEND_GET_MODULE(xcache) #endif /* }}} */ xcache-3.1.0/xcache.h0000644000175000010010000000130512225456104012552 0ustar mOoNone#ifndef __XCACHE_H #define __XCACHE_H #define XCACHE_NAME "XCache" #ifndef XCACHE_VERSION # define XCACHE_VERSION "3.1.0" #endif #define XCACHE_AUTHOR "mOo" #define XCACHE_COPYRIGHT "Copyright (c) 2005-2013" #define XCACHE_URL "http://xcache.lighttpd.net" #define XCACHE_WIKI_URL XCACHE_URL "/wiki" #include "php.h" #if defined(E_STRICT) || defined(E_DEPRECATED) #define XCACHE_ERROR_CACHING #endif #ifdef HAVE_CONFIG_H #include #endif #include "xcache/xc_shm.h" #include "xcache/xc_mutex.h" #include "xcache/xc_compatibility.h" extern zend_module_entry xcache_module_entry; #define phpext_xcache_ptr &xcache_module_entry extern zend_bool xc_test; #endif /* __XCACHE_H */ xcache-3.1.0/xcache.ini0000644000175000010010000000605012220455231013077 0ustar mOoNone;; this is an example, it won't work unless properly configured into php.ini [xcache-common] ;; non-Windows example: extension = xcache.so ;; Windows example: ; extension = php_xcache.dll [xcache.admin] xcache.admin.enable_auth = On ; use http://xcache.lighttpd.net/demo/cacher/mkpassword.php to generate your encrypted password xcache.admin.user = "mOo" xcache.admin.pass = "md5 encrypted password" [xcache] ; ini only settings, all the values here is default unless explained ; select low level shm implemenation xcache.shm_scheme = "mmap" ; to disable: xcache.size=0 ; to enable : xcache.size=64M etc (any size > 0) and your system mmap allows xcache.size = 60M ; set to cpu count (cat /proc/cpuinfo |grep -c processor) xcache.count = 1 ; just a hash hints, you can always store count(items) > slots xcache.slots = 8K ; ttl of the cache item, 0=forever xcache.ttl = 0 ; interval of gc scanning expired items, 0=no scan, other values is in seconds xcache.gc_interval = 0 ; same as aboves but for variable cache xcache.var_size = 4M xcache.var_count = 1 xcache.var_slots = 8K ; default value for $ttl parameter of xcache_*() functions xcache.var_ttl = 0 ; hard limit ttl that cannot be exceed by xcache_*() functions. 0=unlimited xcache.var_maxttl = 0 xcache.var_gc_interval = 300 ; mode:0, const string specified by xcache.var_namespace ; mode:1, $_SERVER[xcache.var_namespace] ; mode:2, uid or gid (specified by xcache.var_namespace) xcache.var_namespace_mode = 0 xcache.var_namespace = "" ; N/A for /dev/zero xcache.readonly_protection = Off ; for *nix, xcache.mmap_path is a file path, not directory. (auto create/overwrite) ; Use something like "/tmp/xcache" instead of "/dev/*" if you want to turn on ReadonlyProtection ; different process group of php won't share the same /tmp/xcache ; for win32, xcache.mmap_path=anonymous map name, not file path xcache.mmap_path = "/dev/zero" ; Useful when XCache crash. leave it blank(disabled) or "/tmp/phpcore/" (writable by php) xcache.coredump_directory = "" ; Windows only. leave it as 0 (default) until you're told by XCache dev xcache.coredump_type = 0 ; disable cache after crash xcache.disable_on_crash = Off ; enable experimental documented features for each release if available xcache.experimental = Off ; per request settings. can ini_set, .htaccess etc xcache.cacher = On xcache.stat = On xcache.optimizer = Off [xcache.coverager] ; enabling this feature will impact performance ; enabled only if xcache.coverager == On && xcache.coveragedump_directory == "non-empty-value" ; per request settings. can ini_set, .htaccess etc ; enable coverage data collecting and xcache_coverager_start/stop/get/clean() functions xcache.coverager = Off xcache.coverager_autostart = On ; set in php ini file only ; make sure it's readable (open_basedir is checked) by coverage viewer script xcache.coveragedump_directory = "" xcache-3.1.0/xcache_globals.h0000644000175000010010000000245512220455233014261 0ustar mOoNone#include "util/xc_stack.h" ZEND_BEGIN_MODULE_GLOBALS(xcache) zend_bool initial_compile_file_called; /* true if origin_compile_file is called */ zend_bool cacher; /* true if enabled */ zend_bool stat; zend_bool experimental; #ifdef HAVE_XCACHE_OPTIMIZER zend_bool optimizer; /* true if enabled */ #endif #ifdef HAVE_XCACHE_COVERAGER zend_bool coverager; zend_bool coverager_autostart; zend_bool coverager_started; HashTable *coverages; /* coverages[file][line] = times */ #endif #ifndef ZEND_WIN32 pid_t holds_pid; #endif xc_stack_t *php_holds; zend_uint php_holds_size; xc_stack_t *var_holds; zend_uint var_holds_size; time_t request_time; long var_ttl; #ifdef IS_UNCODE zval uvar_namespace_hard; zval uvar_namespace_soft; #endif zval var_namespace_hard; zval var_namespace_soft; zend_llist gc_op_arrays; #ifdef ZEND_ACC_ALIAS zend_llist gc_class_entries; #endif #ifdef HAVE_XCACHE_CONSTANT HashTable internal_constant_table; #endif HashTable internal_function_table; HashTable internal_class_table; zend_bool internal_table_copied; void *sandbox; zend_uint op_array_dummy_refcount_holder; ZEND_END_MODULE_GLOBALS(xcache) ZEND_EXTERN_MODULE_GLOBALS(xcache) #ifdef ZTS # define XG(v) TSRMG(xcache_globals_id, zend_xcache_globals *, v) #else # define XG(v) (xcache_globals.v) #endif