initial import to online
git-svn-id: svn://svn.lighttpd.net/xcache/trunk@1 c26eb9a1-5813-0410-bd6c-c2e55f420ca7
This commit is contained in:
commit
4389208e02
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,26 @@
|
|||
# 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
|
|
@ -0,0 +1,28 @@
|
|||
XCACHE_PROC_SRC=$(srcdir)/processor/main.m4
|
||||
XCACHE_PROC_OUT=$(builddir)/processor.out
|
||||
XCACHE_PROC_C=$(builddir)/processor_real.c
|
||||
XCACHE_PROC_H=$(builddir)/processor.h
|
||||
XCACHE_INCLUDES_SRC=$(srcdir)/includes.c
|
||||
XCACHE_INCLUDES_I=$(builddir)/includes.i
|
||||
XCACHE_STRUCT_OUT=$(builddir)/structinfo.m4
|
||||
|
||||
$(XCACHE_INCLUDES_I): $(XCACHE_INCLUDES_SRC) $(srcdir)/xcache.h
|
||||
$(CC) -I. -I$(srcdir) $(COMMON_FLAGS) $(CFLAGS_CLEAN) $(EXTRA_CFLAGS) -E $(XCACHE_INCLUDES_SRC) -o $(XCACHE_INCLUDES_I)
|
||||
|
||||
$(XCACHE_STRUCT_OUT): $(XCACHE_INCLUDES_I) $(srcdir)/mkstructinfo.awk
|
||||
$(AWK) -f $(srcdir)/mkstructinfo.awk < $(XCACHE_INCLUDES_I) > $(XCACHE_STRUCT_OUT)
|
||||
|
||||
$(XCACHE_PROC_OUT): $(XCACHE_PROC_SRC) $(XCACHE_STRUCT_OUT) $(XCACHE_PROC_SOURCES)
|
||||
m4 -I$(srcdir)/processor/ -I$(builddir)/ -I$(srcdir)/ $(XCACHE_ENABLE_TEST) -E $(XCACHE_PROC_SRC) > $(XCACHE_PROC_OUT).tmp && mv -f $(XCACHE_PROC_OUT).tmp $(XCACHE_PROC_OUT)
|
||||
|
||||
$(XCACHE_PROC_H): $(XCACHE_PROC_OUT)
|
||||
grep -F 'export: ' $(XCACHE_PROC_OUT) | sed -r 's/.*export:(.*):export.*/\1/g' | $(XCACHE_INDENT) > $(XCACHE_PROC_H).tmp && mv -f $(XCACHE_PROC_H).tmp $(XCACHE_PROC_H)
|
||||
|
||||
$(XCACHE_PROC_C): $(XCACHE_PROC_OUT) $(XCACHE_PROC_H)
|
||||
cat $(XCACHE_PROC_OUT) | $(XCACHE_INDENT) > $(XCACHE_PROC_C).tmp && mv -f $(XCACHE_PROC_C).tmp $(XCACHE_PROC_C)
|
||||
|
||||
$(builddir)/processor.lo: $(XCACHE_PROC_C) $(XCACHE_PROC_H) $(srcdir)/processor.c
|
||||
|
||||
$(builddir)/disassembler.lo: $(XCACHE_PROC_H) $(srcdir)/processor.c
|
||||
|
||||
$(builddir)/xcache.lo: $(XCACHE_PROC_H) $(srcdir)/myshm.h $(srcdir)/stack.h $(srcdir)/xcache_globals.h $(srcdir)/xcache.c
|
|
@ -0,0 +1,18 @@
|
|||
#ifndef __ALIGN_H
|
||||
#define __ALIGN_H
|
||||
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 /* __ALIGN_H */
|
|
@ -0,0 +1,61 @@
|
|||
dnl
|
||||
dnl $Id:$
|
||||
dnl vim:ts=2:sw=2:expandtab
|
||||
|
||||
AC_DEFUN([XCACHE_OPTION], [
|
||||
PHP_ARG_ENABLE(xcache-$1, for XCACHE $1,
|
||||
[ --enable-xcache-$2 XCACHE: $4], no, no)
|
||||
if test "$PHP_$3" = "yes"; then
|
||||
xcache_sources="$xcache_sources $1.c"
|
||||
AC_DEFINE([HAVE_$3], 1, [Define for XCACHE: $4])
|
||||
fi
|
||||
])dnl
|
||||
|
||||
PHP_ARG_ENABLE(xcache, for XCACHE support,
|
||||
[ --enable-xcache Include XCACHE support.])
|
||||
|
||||
if test "$PHP_XCACHE" != "no"; then
|
||||
xcache_sources="processor.c \
|
||||
xcache.c \
|
||||
mmap.c \
|
||||
mem.c \
|
||||
const_string.c \
|
||||
opcode_spec.c \
|
||||
stack.c \
|
||||
utils.c \
|
||||
lock.c \
|
||||
"
|
||||
XCACHE_OPTION([optimizer], [optimizer ], [XCACHE_OPTIMIZER], [(N/A)])
|
||||
XCACHE_OPTION([coverage], [coverage ], [XCACHE_COVERAGE], [Enable code coverage dumper, NOT for production server])
|
||||
XCACHE_OPTION([assembler], [assembler ], [XCACHE_ASSEMBLER], [(N/A)])
|
||||
XCACHE_OPTION([disassembler], [disassembler], [XCACHE_DISASSEMBLER], [Enable opcode to php variable dumper, NOT for production server])
|
||||
XCACHE_OPTION([encoder], [encoder ], [XCACHE_ENCODER], [(N/A)])
|
||||
XCACHE_OPTION([decoder], [decoder ], [XCACHE_DECODER], [(N/A)])
|
||||
|
||||
PHP_NEW_EXTENSION(xcache, $xcache_sources, $ext_shared)
|
||||
PHP_ADD_MAKEFILE_FRAGMENT()
|
||||
|
||||
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" = "yes"; then
|
||||
XCACHE_ENABLE_TEST=-DXCACHE_ENABLE_TEST
|
||||
AC_DEFINE([HAVE_XCACHE_TEST], 1, [Define to enable XCACHE self test])
|
||||
else
|
||||
XCACHE_ENABLE_TEST=
|
||||
fi
|
||||
PHP_SUBST([XCACHE_ENABLE_TEST])
|
||||
|
||||
AC_PATH_PROGS(INDENT, [indent cat])
|
||||
case $INDENT in
|
||||
*/indent[)]
|
||||
XCACHE_INDENT="$INDENT -kr --use-tabs --tab-size 4 -sob -nce"
|
||||
;;
|
||||
*[)]
|
||||
XCACHE_INDENT=cat
|
||||
;;
|
||||
esac
|
||||
PHP_SUBST([XCACHE_INDENT])
|
||||
|
||||
XCACHE_PROC_SOURCES=`ls $ac_srcdir/processor/*.m4`
|
||||
PHP_SUBST([XCACHE_PROC_SOURCES])
|
||||
fi
|
|
@ -0,0 +1,114 @@
|
|||
#include "xcache.h"
|
||||
#include "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
|
||||
};
|
||||
|
||||
int 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",
|
||||
/* 3 */ "IS_BOOL",
|
||||
/* 4 */ "IS_ARRAY",
|
||||
/* 5 */ "IS_OBJECT",
|
||||
/* 6 */ "IS_STRING",
|
||||
/* 7 */ "IS_RESOURCE",
|
||||
/* 8 */ "IS_CONSTANT",
|
||||
/* 9 */ "IS_CONSTANT_ARRAY",
|
||||
/* 10 */ "IS_UNICODE",
|
||||
#if 0
|
||||
/* 11 */ "",
|
||||
/* 12 */ "",
|
||||
/* 13 */ "",
|
||||
/* 14 */ "",
|
||||
/* 15 */ "", "", "", "", "",
|
||||
|
||||
/* IS_CONSTANT_INDEX */
|
||||
/* 20 */ "CIDX IS_NULL",
|
||||
/* 21 */ "CIDX IS_LONG",
|
||||
/* 22 */ "CIDX IS_DOUBLE",
|
||||
/* 23 */ "CIDX IS_BOOL",
|
||||
/* 24 */ "CIDX IS_ARRAY",
|
||||
/* 25 */ "CIDX IS_OBJECT",
|
||||
/* 26 */ "CIDX IS_STRING",
|
||||
/* 27 */ "CIDX IS_RESOURCE",
|
||||
/* 28 */ "CIDX IS_CONSTANT",
|
||||
/* 29 */ "CIDX IS_CONSTANT_ARRAY"
|
||||
/* 20 */ "CIDX IS_UNICODE",
|
||||
#endif
|
||||
};
|
||||
|
||||
int 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)
|
||||
{
|
||||
#if 0
|
||||
if (data_type & IS_CONSTANT_INDEX) {
|
||||
data_type = (data_type & ~IS_CONSTANT_INDEX) + 20;
|
||||
}
|
||||
#endif
|
||||
data_type &= ~IS_CONSTANT_INDEX;
|
||||
return data_type_names[data_type];
|
||||
}
|
||||
/* }}} */
|
||||
/* {{{ xc_get_opcode */
|
||||
#if PHP_MAJAR_VERSION >= 6
|
||||
# include "const_string_opcodes_php6.x.h"
|
||||
#else
|
||||
# ifdef ZEND_ENGINE_2_1
|
||||
# include "const_string_opcodes_php5.1.h"
|
||||
# else
|
||||
# ifdef ZEND_ENGINE_2
|
||||
# include "const_string_opcodes_php5.0.h"
|
||||
# else
|
||||
# include "const_string_opcodes_php4.x.h"
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
int 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];
|
||||
}
|
||||
/* }}} */
|
|
@ -0,0 +1,8 @@
|
|||
#include "php.h"
|
||||
|
||||
int xc_get_op_type_count();
|
||||
const char *xc_get_op_type(zend_uchar op_type);
|
||||
int xc_get_data_type_count();
|
||||
const char *xc_get_data_type(zend_uchar data_type);
|
||||
int xc_get_opcode_count();
|
||||
const char *xc_get_opcode(zend_uchar opcode);
|
|
@ -0,0 +1,116 @@
|
|||
/* size = 112 */
|
||||
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"
|
||||
};
|
|
@ -0,0 +1,154 @@
|
|||
/* 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 */ "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"
|
||||
};
|
|
@ -0,0 +1,155 @@
|
|||
/* 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",
|
||||
/* 151 */ "U_NORMALIZE"
|
||||
};
|
|
@ -0,0 +1,425 @@
|
|||
#include <stdio.h>
|
||||
#include "xcache.h"
|
||||
#include "ext/standard/flock_compat.h"
|
||||
#ifdef HAVE_SYS_FILE_H
|
||||
# include <sys/file.h>
|
||||
#endif
|
||||
#include "stack.h"
|
||||
#include "xcache_globals.h"
|
||||
#include "coverage.h"
|
||||
#include "utils.h"
|
||||
typedef HashTable *coverage_t;
|
||||
#define PCOV_HEADER_MAGIC 0x564f4350
|
||||
|
||||
char *xc_coveragedump_dir = NULL;
|
||||
static zend_compile_file_t *origin_compile_file;
|
||||
|
||||
#undef DEBUG
|
||||
/* dumper */
|
||||
static void xc_destroy_coverage(void *pDest) /* {{{ */
|
||||
{
|
||||
coverage_t cov = *(coverage_t*) pDest;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "destroy %p\n", cov);
|
||||
#endif
|
||||
zend_hash_destroy(cov);
|
||||
efree(cov);
|
||||
}
|
||||
/* }}} */
|
||||
PHPAPI void xcache_mkdirs_ex(char *root, int rootlen, char *path, int pathlen TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
char *fullpath;
|
||||
struct stat st;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "mkdirs %s %d %s %d\n", root, rootlen, path, pathlen);
|
||||
#endif
|
||||
fullpath = do_alloca(rootlen + pathlen + 1);
|
||||
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;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "mkdir %s\n", fullpath);
|
||||
#endif
|
||||
php_stream_mkdir(fullpath, 0700, REPORT_ERRORS, NULL);
|
||||
}
|
||||
free_alloca(fullpath);
|
||||
}
|
||||
/* }}} */
|
||||
static void xc_coverage_save_cov(char *srcfile, char *outfilename, coverage_t cov TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
long *buf = NULL, *p;
|
||||
long covlines, *phits;
|
||||
int fd = -1;
|
||||
int 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) {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "new file\n");
|
||||
#endif
|
||||
}
|
||||
else if (outstat.st_size) {
|
||||
len = outstat.st_size;
|
||||
contents = emalloc(len);
|
||||
if (read(fd, (void *) contents, len) != len) {
|
||||
goto bailout;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "oldsize %d\n", (int) len);
|
||||
#endif
|
||||
do {
|
||||
p = (long *) contents;
|
||||
len -= sizeof(long);
|
||||
if (len < 0) {
|
||||
break;
|
||||
}
|
||||
if (*p++ != PCOV_HEADER_MAGIC) {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "wrong magic in file %s\n", outfilename);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
p += 2; /* skip covliens */
|
||||
len -= sizeof(long) * 2;
|
||||
if (len < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
for (; len >= sizeof(long) * 2; len -= sizeof(long) * 2, p += 2) {
|
||||
if (zend_hash_index_find(cov, p[0], (void**)&phits) == SUCCESS) {
|
||||
if (p[1] <= 0) {
|
||||
/* already marked */
|
||||
continue;
|
||||
}
|
||||
if (*phits > 0) {
|
||||
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;
|
||||
if (*phits <= 0) {
|
||||
*p++ = 0;
|
||||
}
|
||||
else {
|
||||
*p++ = *phits;
|
||||
covlines ++;
|
||||
}
|
||||
zend_hash_move_forward_ex(cov, &pos);
|
||||
}
|
||||
p = buf + 1;
|
||||
p[0] = 0;
|
||||
p[1] = covlines;
|
||||
|
||||
ftruncate(fd, 0);
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
write(fd, (char *) buf, size);
|
||||
|
||||
bailout:
|
||||
if (contents) efree(contents);
|
||||
if (fd >= 0) close(fd);
|
||||
if (buf) efree(buf);
|
||||
}
|
||||
/* }}} */
|
||||
void xc_coverage_request_init(TSRMLS_D) /* {{{ */
|
||||
{
|
||||
if (XG(coveragedumper)) {
|
||||
XG(coverages) = emalloc(sizeof(HashTable));
|
||||
zend_hash_init(XG(coverages), 0, NULL, xc_destroy_coverage, 0);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
void xc_coverage_request_shutdown(TSRMLS_D) /* {{{ */
|
||||
{
|
||||
coverage_t *pcov;
|
||||
zstr s;
|
||||
char *outfilename;
|
||||
int dumpdir_len, outfilelen, size, alloc_len = 0;
|
||||
|
||||
if (!XG(coverages)) {
|
||||
return;
|
||||
}
|
||||
if (XG(coveragedumper)) {
|
||||
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(XG(coverages));
|
||||
while (zend_hash_get_current_data(XG(coverages), (void **) &pcov) == SUCCESS) {
|
||||
zend_hash_get_current_key_ex(XG(coverages), &s, &size, NULL, 0, NULL);
|
||||
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");
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "outfilename %s\n", outfilename);
|
||||
#endif
|
||||
xc_coverage_save_cov(ZSTR_S(s), outfilename, *pcov TSRMLS_CC);
|
||||
zend_hash_move_forward(XG(coverages));
|
||||
}
|
||||
}
|
||||
|
||||
zend_hash_destroy(XG(coverages));
|
||||
efree(XG(coverages));
|
||||
XG(coverages) = NULL;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* helper func to store hits into coverages */
|
||||
static coverage_t xc_coverage_get(char *filename TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
int len = strlen(filename) + 1;
|
||||
coverage_t cov, *pcov;
|
||||
|
||||
if (zend_hash_find(XG(coverages), filename, len, (void **) &pcov) == SUCCESS) {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "got coverage %s %p\n", filename, *pcov);
|
||||
#endif
|
||||
return *pcov;
|
||||
}
|
||||
else {
|
||||
cov = emalloc(sizeof(HashTable));
|
||||
zend_hash_init(cov, 0, NULL, NULL, 0);
|
||||
zend_hash_add(XG(coverages), filename, len, (void **) &cov, sizeof(cov), NULL);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "new coverage %s %p\n", filename, cov);
|
||||
#endif
|
||||
return cov;
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
static void xc_coverage_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) {
|
||||
/* already marked */
|
||||
return;
|
||||
}
|
||||
if (*poldhits != -1) {
|
||||
hits += *poldhits;
|
||||
}
|
||||
}
|
||||
zend_hash_index_update(cov, line, &hits, sizeof(hits), NULL);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static int xc_coverage_get_op_array_size_no_tail(zend_op_array *op_array) /* {{{ */
|
||||
{
|
||||
zend_uint size;
|
||||
|
||||
size = op_array->size;
|
||||
#ifdef ZEND_ENGINE_2
|
||||
if (op_array->opcodes[size - 1].opcode == ZEND_HANDLE_EXCEPTION) {
|
||||
size --;
|
||||
#endif
|
||||
if (op_array->opcodes[size - 1].opcode == ZEND_RETURN) {
|
||||
size --;
|
||||
/* it's not real php statement */
|
||||
if (op_array->opcodes[size - 1].opcode == ZEND_EXT_STMT) {
|
||||
size --;
|
||||
}
|
||||
}
|
||||
#ifdef ZEND_ENGINE_2
|
||||
}
|
||||
#endif
|
||||
return size;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* prefill */
|
||||
static int xc_coverage_init_op_array(zend_op_array *op_array TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_uint size;
|
||||
coverage_t cov;
|
||||
int i;
|
||||
|
||||
if (op_array->type != ZEND_USER_FUNCTION) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size = xc_coverage_get_op_array_size_no_tail(op_array);
|
||||
cov = xc_coverage_get(op_array->filename);
|
||||
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_coverage_add_hits(cov, op_array->opcodes[i].lineno, -1 TSRMLS_CC);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/* }}} */
|
||||
static void xc_coverage_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_coverage_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 = origin_compile_file(h, type TSRMLS_CC);
|
||||
if (XG(coveragedumper) && XG(coverages)) {
|
||||
xc_coverage_init_compile_result(op_array TSRMLS_CC);
|
||||
}
|
||||
return op_array;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* hits */
|
||||
void xc_coverage_handle_ext_stmt(zend_op_array *op_array, zend_uchar op) /* {{{ */
|
||||
{
|
||||
if (XG(coveragedumper) && XG(coverages)) {
|
||||
TSRMLS_FETCH();
|
||||
int size = xc_coverage_get_op_array_size_no_tail(op_array);
|
||||
int oplineno = (*EG(opline_ptr)) - op_array->opcodes;
|
||||
if (oplineno < size) {
|
||||
xc_coverage_add_hits(xc_coverage_get(op_array->filename), (*EG(opline_ptr))->lineno, 1 TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* init/destroy */
|
||||
int xc_coverage_init(int module_number TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
if (xc_coveragedump_dir) {
|
||||
int len = strlen(xc_coveragedump_dir);
|
||||
if (len) {
|
||||
if (xc_coveragedump_dir[len - 1] == '/') {
|
||||
xc_coveragedump_dir[len - 1] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
if (xc_coveragedump_dir && xc_coveragedump_dir[0]) {
|
||||
origin_compile_file = zend_compile_file;
|
||||
zend_compile_file = xc_compile_file_for_coverage;
|
||||
CG(extended_info) = 1;
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
void xc_coverage_destroy() /* {{{ */
|
||||
{
|
||||
if (origin_compile_file == xc_compile_file_for_coverage) {
|
||||
zend_compile_file = origin_compile_file;
|
||||
}
|
||||
if (xc_coveragedump_dir) {
|
||||
pefree(xc_coveragedump_dir, 1);
|
||||
xc_coveragedump_dir = NULL;
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* user api */
|
||||
PHP_FUNCTION(xcache_coverage_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 -= sizeof(long);
|
||||
if (len < 0) {
|
||||
return;
|
||||
}
|
||||
if (*p++ != PCOV_HEADER_MAGIC) {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "wrong magic in xcache_coverage_decode");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
for (; len >= sizeof(long) * 2; len -= sizeof(long) * 2, p += 2) {
|
||||
add_index_long(return_value, p[0], p[1]);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
#include "php.h"
|
||||
#include "xcache.h"
|
||||
|
||||
extern char *xc_coveragedump_dir;
|
||||
|
||||
void xc_coverage_handle_ext_stmt(zend_op_array *op_array, zend_uchar op);
|
||||
int xc_coverage_init(int module_number TSRMLS_DC);
|
||||
void xc_coverage_destroy();
|
||||
void xc_coverage_request_init(TSRMLS_D);
|
||||
void xc_coverage_request_shutdown(TSRMLS_D);
|
||||
PHP_FUNCTION(xcache_coverage_decode);
|
|
@ -0,0 +1,154 @@
|
|||
#include "disassembler.h"
|
||||
#include "xcache.h"
|
||||
#include "utils.h"
|
||||
#include "processor.h"
|
||||
|
||||
#define return_value dst
|
||||
|
||||
static void xc_dasm(zval *dst, zend_op_array *op_array TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
Bucket *b;
|
||||
zval *zv, *list;
|
||||
xc_compile_result_t cr;
|
||||
int bufsize = 2;
|
||||
char *buf;
|
||||
int keysize;
|
||||
|
||||
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(dst);
|
||||
|
||||
ALLOC_INIT_ZVAL(zv);
|
||||
array_init(zv);
|
||||
xc_dasm_zend_op_array(zv, op_array TSRMLS_CC);
|
||||
add_assoc_zval_ex(dst, ZEND_STRS("op_array"), zv);
|
||||
|
||||
ALLOC_INIT_ZVAL(list);
|
||||
array_init(list);
|
||||
xc_dasm_HashTable_zend_function(list, CG(function_table) TSRMLS_CC);
|
||||
add_assoc_zval_ex(dst, ZEND_STRS("function_table"), list);
|
||||
|
||||
buf = emalloc(bufsize);
|
||||
ALLOC_INIT_ZVAL(list);
|
||||
array_init(list);
|
||||
for (b = CG(class_table)->pListHead; b; b = b->pListNext) {
|
||||
ALLOC_INIT_ZVAL(zv);
|
||||
array_init(zv);
|
||||
xc_dasm_zend_class_entry(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(b), keysize);
|
||||
buf[keysize - 2] = buf[keysize - 1] = ""[0];
|
||||
keysize = b->nKeyLength;
|
||||
#ifdef IS_UNICODE
|
||||
if (BUCKET_KEY_TYPE(b) == IS_UNICODE) {
|
||||
if (buf[0] == ""[0] && buf[1] == ""[0]) {
|
||||
keysize ++;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
if (buf[0] == ""[0]) {
|
||||
keysize ++;
|
||||
}
|
||||
}
|
||||
add_u_assoc_zval_ex(list, BUCKET_KEY_TYPE(b), buf, b->nKeyLength, zv);
|
||||
}
|
||||
efree(buf);
|
||||
add_assoc_zval_ex(dst, ZEND_STRS("class_table"), list);
|
||||
|
||||
/*xc_apply_op_array(&cr, (apply_func_t) xc_redo_pass_two TSRMLS_CC);*/
|
||||
xc_compile_result_free(&cr);
|
||||
|
||||
return;
|
||||
}
|
||||
/* }}} */
|
||||
void xc_dasm_string(zval *dst, zval *source TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
int catched;
|
||||
zend_op_array *op_array = NULL;
|
||||
xc_sandbox_t sandbox;
|
||||
char *eval_name = zend_make_compiled_string_description("runtime-created function" TSRMLS_CC);
|
||||
|
||||
xc_sandbox_init(&sandbox, eval_name TSRMLS_CC);
|
||||
|
||||
catched = 0;
|
||||
zend_try {
|
||||
op_array = compile_string(source, eval_name TSRMLS_CC);
|
||||
} zend_catch {
|
||||
catched = 1;
|
||||
} zend_end_try();
|
||||
|
||||
if (catched || !op_array) {
|
||||
goto err_compile;
|
||||
}
|
||||
|
||||
xc_dasm(dst, op_array TSRMLS_CC);
|
||||
|
||||
/* free */
|
||||
efree(eval_name);
|
||||
destroy_op_array(op_array TSRMLS_CC);
|
||||
efree(op_array);
|
||||
xc_sandbox_free(&sandbox, 0 TSRMLS_CC);
|
||||
return;
|
||||
|
||||
err_compile:
|
||||
efree(eval_name);
|
||||
xc_sandbox_free(&sandbox, 0 TSRMLS_CC);
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
/* }}} */
|
||||
void xc_dasm_file(zval *dst, const char *filename TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
int catched;
|
||||
zend_op_array *op_array = NULL;
|
||||
xc_sandbox_t sandbox;
|
||||
zval *zfilename;
|
||||
|
||||
MAKE_STD_ZVAL(zfilename);
|
||||
zfilename->value.str.val = estrdup(filename);
|
||||
zfilename->value.str.len = strlen(filename);
|
||||
zfilename->type = IS_STRING;
|
||||
|
||||
xc_sandbox_init(&sandbox, zfilename->value.str.val TSRMLS_CC);
|
||||
|
||||
catched = 0;
|
||||
zend_try {
|
||||
op_array = compile_filename(ZEND_REQUIRE, zfilename TSRMLS_CC);
|
||||
} zend_catch {
|
||||
catched = 1;
|
||||
} zend_end_try();
|
||||
|
||||
if (catched || !op_array) {
|
||||
goto err_compile;
|
||||
}
|
||||
|
||||
xc_dasm(dst, op_array TSRMLS_CC);
|
||||
|
||||
/* free */
|
||||
destroy_op_array(op_array TSRMLS_CC);
|
||||
efree(op_array);
|
||||
xc_sandbox_free(&sandbox, 0 TSRMLS_CC);
|
||||
zval_dtor(zfilename);
|
||||
FREE_ZVAL(zfilename);
|
||||
return;
|
||||
|
||||
err_compile:
|
||||
xc_sandbox_free(&sandbox, 0 TSRMLS_CC);
|
||||
|
||||
zval_dtor(zfilename);
|
||||
FREE_ZVAL(zfilename);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
/* }}} */
|
|
@ -0,0 +1,4 @@
|
|||
#include "php.h"
|
||||
|
||||
void xc_dasm_string(zval *return_value, zval *code TSRMLS_DC);
|
||||
void xc_dasm_file(zval *return_value, const char *filename TSRMLS_DC);
|
|
@ -0,0 +1,2 @@
|
|||
#include "xcache.h"
|
||||
#include "zend_compile.h"
|
|
@ -0,0 +1,129 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#include <php.h>
|
||||
#ifndef ZEND_WIN32
|
||||
typedef int HANDLE;
|
||||
#endif
|
||||
#include "lock.h"
|
||||
|
||||
struct _xc_lock_t {
|
||||
HANDLE fd;
|
||||
char *pathname;
|
||||
};
|
||||
|
||||
#ifndef ZEND_WIN32
|
||||
# include <unistd.h>
|
||||
# include <fcntl.h>
|
||||
# include <errno.h>
|
||||
static inline int dolock(xc_lock_t *lck, 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(lck->fd, F_SETLKW, &lock);
|
||||
} while (ret < 0 && errno == EINTR);
|
||||
return ret;
|
||||
}
|
||||
/* }}} */
|
||||
#define LCK_WR F_WRLCK
|
||||
#define LCK_RD F_RDLCK
|
||||
#define LCK_UN F_UNLCK
|
||||
#define LCK_NB 0
|
||||
#else
|
||||
|
||||
# include <win32/flock.h>
|
||||
# include <io.h>
|
||||
# include <fcntl.h>
|
||||
# include <sys/types.h>
|
||||
# include <sys/stat.h>
|
||||
# define errno GetLastError()
|
||||
static inline int dolock(xc_lock_t *lck, int type) /* {{{ */
|
||||
{
|
||||
static OVERLAPPED offset = {0, 0, 0, 0, NULL};
|
||||
|
||||
if (type == LCK_UN) {
|
||||
return UnlockFileEx((HANDLE)fd, 0, 1, 0, &offset);
|
||||
}
|
||||
else {
|
||||
return LockFileEx((HANDLE)fd, type, 0, 1, 0, &offset);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
#define LCK_WR LOCKFILE_EXCLUSIVE_LOCK
|
||||
#define LCK_RD 0
|
||||
#define LCK_UN 0
|
||||
#define LCK_NB LOCKFILE_FAIL_IMMEDIATELY
|
||||
#endif
|
||||
|
||||
xc_lock_t *xc_fcntl_init(const char *pathname) /* {{{ */
|
||||
{
|
||||
HANDLE fd;
|
||||
char myname[sizeof("/tmp/.xcache.lock") - 1 + 20];
|
||||
|
||||
if (pathname == NULL) {
|
||||
static int i = 0;
|
||||
snprintf(myname, sizeof(myname) - 1, "/tmp/.xcache.%d.%d.lock", (int) getuid(), i ++);
|
||||
pathname = myname;
|
||||
}
|
||||
|
||||
fd = open(pathname, O_RDWR|O_CREAT, 0666);
|
||||
|
||||
if (fd > 0) {
|
||||
xc_lock_t *lck = malloc(sizeof(lck[0]));
|
||||
int size;
|
||||
|
||||
#ifndef __CYGWIN__
|
||||
unlink(pathname);
|
||||
#endif
|
||||
lck->fd = fd;
|
||||
size = strlen(pathname) + 1;
|
||||
lck->pathname = malloc(size);
|
||||
memcpy(lck->pathname, pathname, size);
|
||||
return lck;
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "xc_fcntl_create: open(%s, O_RDWR|O_CREAT, 0666) failed:", pathname);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
void xc_fcntl_destroy(xc_lock_t *lck) /* {{{ */
|
||||
{
|
||||
close(lck->fd);
|
||||
#ifdef __CYGWIN__
|
||||
unlink(lck->pathname);
|
||||
#endif
|
||||
free(lck->pathname);
|
||||
free(lck);
|
||||
}
|
||||
/* }}} */
|
||||
void xc_fcntl_lock(xc_lock_t *lck) /* {{{ */
|
||||
{
|
||||
if (dolock(lck, LCK_WR) < 0) {
|
||||
fprintf(stderr, "xc_fcntl_lock failed errno:%d", errno);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
void xc_fcntl_rdlock(xc_lock_t *lck) /* {{{ */
|
||||
{
|
||||
if (dolock(lck, LCK_RD) < 0) {
|
||||
fprintf(stderr, "xc_fcntl_lock failed errno:%d", errno);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
void xc_fcntl_unlock(xc_lock_t *lck) /* {{{ */
|
||||
{
|
||||
if (dolock(lck, LCK_UN) < 0) {
|
||||
fprintf(stderr, "xc_fcntl_unlock failed errno:%d", errno);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
|
@ -0,0 +1,11 @@
|
|||
typedef struct _xc_lock_t xc_lock_t;
|
||||
|
||||
xc_lock_t *xc_fcntl_init(const char *pathname);
|
||||
void xc_fcntl_destroy(xc_lock_t *lck);
|
||||
void xc_fcntl_lock(xc_lock_t *lck);
|
||||
void xc_fcntl_unlock(xc_lock_t *lck);
|
||||
|
||||
#define xc_lock_init(name) xc_fcntl_init(name)
|
||||
#define xc_lock_destroy(fd) xc_fcntl_destroy(fd)
|
||||
#define xc_lock(fd) xc_fcntl_lock(fd)
|
||||
#define xc_unlock(fd) xc_fcntl_unlock(fd)
|
|
@ -0,0 +1,43 @@
|
|||
#!/usr/bin/make -if
|
||||
# vim:syntax=make
|
||||
SELF=MAKELEVEL=0 ./make.devel
|
||||
|
||||
# You should copy make.inc from make.inc.default
|
||||
include make.inc
|
||||
|
||||
all: opcode_spec_def const_string tags
|
||||
|
||||
clean: clean_const_string
|
||||
rm -f tags opcode_spec_def.h
|
||||
|
||||
const_string:
|
||||
@-$(SELF) const_string_opcodes_php4.x.h
|
||||
@-$(SELF) const_string_opcodes_php5.0.h
|
||||
@-$(SELF) const_string_opcodes_php5.1.h
|
||||
@-$(SELF) const_string_opcodes_php6.x.h
|
||||
|
||||
clean_const_string:
|
||||
rm -f const_string_opcodes_php4.x.h const_string_opcodes_php5.0.h const_string_opcodes_php5.1.h const_string_opcodes_php6.x.h
|
||||
|
||||
const_string_opcodes_php4.x.h: $(PHP4_x_DIR)/Zend/zend_compile.h
|
||||
./mkopcode.awk < $(PHP4_x_DIR)/Zend/zend_compile.h > const_string_opcodes_php4.x.h
|
||||
|
||||
const_string_opcodes_php5.0.h: $(PHP5_0_DIR)/Zend/zend_vm_def.h
|
||||
./mkopcode.awk < $(PHP5_0_DIR)/Zend/zend_vm_def.h > const_string_opcodes_php5.0.h
|
||||
|
||||
const_string_opcodes_php5.1.h: $(PHP5_1_DIR)/Zend/zend_vm_def.h
|
||||
./mkopcode.awk < $(PHP5_1_DIR)/Zend/zend_vm_def.h > const_string_opcodes_php5.1.h
|
||||
|
||||
const_string_opcodes_php6.x.h: $(PHP6_x_DIR)/Zend/zend_vm_def.h
|
||||
./mkopcode.awk < $(PHP6_x_DIR)/Zend/zend_vm_def.h > const_string_opcodes_php6.x.h
|
||||
|
||||
tags:
|
||||
test -d $(PHP_DEVEL_DIR) && ctags -R . $(PHP_DEVEL_DIR)/main $(PHP_DEVEL_DIR)/Zend $(PHP_DEVEL_DIR)/TSRM $(PHP_DEVEL_DIR)/ext/standard || ctags -R .
|
||||
|
||||
opcode_spec_def:
|
||||