diff options
| author | Andrea Faulds <ajf@ajf.me> | 2014-11-01 22:49:53 +0000 |
|---|---|---|
| committer | Andrea Faulds <ajf@ajf.me> | 2014-11-01 22:49:53 +0000 |
| commit | 71566b994f965d61b9f7dfbf8c6279e89a703113 (patch) | |
| tree | f4ed6d80e3c36fa5f1bada5f1b80f852874c4d4a /Zend | |
| parent | 820a464f1d29d737d94addb207e03c236e0d8654 (diff) | |
| parent | f9a77b71e24d918981a9503d51db74c419a017ab (diff) | |
| download | php-git-71566b994f965d61b9f7dfbf8c6279e89a703113.tar.gz | |
Merge branch 'master' into zppFailOnOverflow
Diffstat (limited to 'Zend')
131 files changed, 11914 insertions, 12472 deletions
diff --git a/Zend/Makefile.am b/Zend/Makefile.am index 65c4113497..2a76db36b1 100644 --- a/Zend/Makefile.am +++ b/Zend/Makefile.am @@ -8,7 +8,7 @@ noinst_LTLIBRARIES=libZend.la libZend_la_SOURCES=\ zend_language_parser.y zend_language_scanner.l \ zend_ini_parser.y zend_ini_scanner.l \ - zend_alloc.c zend_compile.c zend_constants.c zend_dynamic_array.c \ + zend_alloc.c zend_compile.c zend_constants.c \ zend_execute.c zend_execute_API.c zend_highlight.c zend_llist.c \ zend_vm_opcodes.c zend_opcode.c zend_operators.c zend_ptr_stack.c zend_stack.c \ zend_variables.c zend.c zend_API.c zend_extensions.c zend_hash.c \ diff --git a/Zend/Zend.dsp b/Zend/Zend.dsp deleted file mode 100644 index c1b3f2a9f7..0000000000 --- a/Zend/Zend.dsp +++ /dev/null @@ -1,626 +0,0 @@ -# Microsoft Developer Studio Project File - Name="Zend" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Static Library" 0x0104
-
-CFG=Zend - Win32 Release_inline
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "Zend.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "Zend.mak" CFG="Zend - Win32 Release_inline"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "Zend - Win32 Release" (based on "Win32 (x86) Static Library")
-!MESSAGE "Zend - Win32 Debug" (based on "Win32 (x86) Static Library")
-!MESSAGE "Zend - Win32 Release_inline" (based on "Win32 (x86) Static Library")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "Zend - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDebug" /D "_MBCS" /D "_LIB" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /D "NDebug" /D "_LIB" /D "Zend_EXPORTS" /D ZEND_DEBUG=0 /D "LIBZEND_EXPORTS" /D "TSRM_EXPORTS" /D "WIN32" /D "_MBCS" /D "ZEND_WIN32" /FR /FD /c
-# SUBTRACT CPP /YX
-# ADD BASE RSC /l 0x40d /d "NDebug"
-# ADD RSC /l 0x40d /d "NDebug"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo
-
-!ELSEIF "$(CFG)" == "Zend - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_Debug" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
-# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "." /D "_Debug" /D "_LIB" /D "LIBZEND_EXPORTS" /D "TSRM_EXPORTS" /D ZEND_DEBUG=1 /D "ZEND_WIN32" /D "WIN32" /D "_MBCS" /FR /YX /FD /GZ /c
-# ADD BASE RSC /l 0x40d /d "_Debug"
-# ADD RSC /l 0x40d /d "_Debug"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo
-
-!ELSEIF "$(CFG)" == "Zend - Win32 Release_inline"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Output_Dir "Zend___Win32_Release_inline"
-# PROP BASE Intermediate_Dir "Zend___Win32_Release_inline"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Output_Dir "Release_inline"
-# PROP Intermediate_Dir "Release_inline"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I "." /D "NDebug" /D "_LIB" /D "Zend_EXPORTS" /D ZEND_DEBUG=0 /D "LIBZEND_EXPORTS" /D "TSRM_EXPORTS" /D "WIN32" /D "_MBCS" /FR /FD /c
-# SUBTRACT BASE CPP /YX
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /D "NDebug" /D "_LIB" /D "Zend_EXPORTS" /D "LIBZEND_EXPORTS" /D "TSRM_EXPORTS" /D ZEND_DEBUG=0 /D "ZEND_WIN32_FORCE_INLINE" /D "WIN32" /D "_MBCS" /D "ZEND_WIN32" /FR /FD /c
-# SUBTRACT CPP /YX
-# ADD BASE RSC /l 0x40d /d "NDebug"
-# ADD RSC /l 0x40d /d "NDebug"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo
-
-!ENDIF
-
-# Begin Target
-
-# Name "Zend - Win32 Release"
-# Name "Zend - Win32 Debug"
-# Name "Zend - Win32 Release_inline"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=.\zend.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_alloc.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_API.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_ast.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_builtin_functions.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_closures.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_compile.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_constants.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_default_classes.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_dynamic_array.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_execute.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_execute_API.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_extensions.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_float.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_generators.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_hash.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_highlight.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_indent.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_inheritance.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_ini.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_ini_parser.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_ini_scanner.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_interfaces.c
-# End Source File
-# Begin Source File
-
-SOURCE=".\zend_language_parser.c"
-# End Source File
-# Begin Source File
-
-SOURCE=".\zend_language_scanner.c"
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_list.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_llist.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_object_handlers.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_objects.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_objects_API.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_opcode.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_operators.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_ptr_stack.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_qsort.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_sprintf.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_stack.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_stream.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_string.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_strtod.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_ts_hash.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_variables.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_vm_opcodes.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_virtual_cwd.c
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE=.\FlexLexer.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_alloc.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_API.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_builtin_functions.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_compile.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_config.w32.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_constants.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_default_classes.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_dynamic_array.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_errors.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_execute.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_execute_locks.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_extensions.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_globals.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_globals_macros.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_hash.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_highlight.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_indent.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_ini.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_ini_parser.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_ini_scanner.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_interfaces.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_istdiostream.h
-# End Source File
-# Begin Source File
-
-SOURCE=".\zend_language_parser.h"
-# End Source File
-# Begin Source File
-
-SOURCE=".\zend_language_scanner.h"
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_list.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_llist.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_modules.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_object_handlers.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_objects.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_objects_API.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_operators.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_ptr_stack.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_qsort.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_stack.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_stream.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_string.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_strtod.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_ts_hash.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_variables.h
-# End Source File
-# End Group
-# Begin Group "Parsers"
-
-# PROP Default_Filter "y"
-# Begin Source File
-
-SOURCE=.\zend_ini_parser.y
-
-!IF "$(CFG)" == "Zend - Win32 Release"
-
-!ELSEIF "$(CFG)" == "Zend - Win32 Debug"
-
-# Begin Custom Build
-InputDir=.
-InputPath=.\zend_ini_parser.y
-
-BuildCmds= \
- bison --output=zend_ini_parser.c -v -d -p ini_ zend_ini_parser.y
-
-"$(InputDir)\zend_ini_parser.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- $(BuildCmds)
-
-"$(InputDir)\zend_ini_parser.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- $(BuildCmds)
-# End Custom Build
-
-!ELSEIF "$(CFG)" == "Zend - Win32 Release_inline"
-
-!ENDIF
-
-# End Source File
-# Begin Source File
-
-SOURCE=".\zend_language_parser.y"
-
-!IF "$(CFG)" == "Zend - Win32 Release"
-
-# Begin Custom Build
-InputDir=.
-InputPath=".\zend_language_parser.y"
-
-BuildCmds= \
- bison --output=zend_language_parser.c -v -d -p zend zend_language_parser.y
-
-"$(InputDir)\zend_language_parser.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- $(BuildCmds)
-
-"$(InputDir)\zend_language_parser.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- $(BuildCmds)
-# End Custom Build
-
-!ELSEIF "$(CFG)" == "Zend - Win32 Debug"
-
-# Begin Custom Build
-InputDir=.
-InputPath=".\zend_language_parser.y"
-
-BuildCmds= \
- bison --output=zend_language_parser.c -v -d -p zend zend_language_parser.y
-
-"$(InputDir)\zend_language_parser.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- $(BuildCmds)
-
-"$(InputDir)\zend_language_parser.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- $(BuildCmds)
-# End Custom Build
-
-!ELSEIF "$(CFG)" == "Zend - Win32 Release_inline"
-
-# Begin Custom Build
-InputDir=.
-InputPath=".\zend_language_parser.y"
-
-BuildCmds= \
- bison --output=zend_language_parser.c -v -d -p zend zend_language_parser.y
-
-"$(InputDir)\zend_language_parser.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- $(BuildCmds)
-
-"$(InputDir)\zend_language_parser.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- $(BuildCmds)
-# End Custom Build
-
-!ENDIF
-
-# End Source File
-# End Group
-# Begin Group "Scanners"
-
-# PROP Default_Filter "l"
-# Begin Source File
-
-SOURCE=.\flex.skl
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_ini_scanner.l
-
-!IF "$(CFG)" == "Zend - Win32 Release"
-
-!ELSEIF "$(CFG)" == "Zend - Win32 Debug"
-
-# Begin Custom Build
-InputPath=.\zend_ini_scanner.l
-
-"zend_ini_scanner.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- flex -B -i -Sflex.skl -Pini_ -ozend_ini_scanner.c zend_ini_scanner.l
-
-# End Custom Build
-
-!ELSEIF "$(CFG)" == "Zend - Win32 Release_inline"
-
-!ENDIF
-
-# End Source File
-# Begin Source File
-
-SOURCE=".\zend_language_scanner.l"
-
-!IF "$(CFG)" == "Zend - Win32 Release"
-
-# Begin Custom Build
-InputPath=".\zend_language_scanner.l"
-
-"zend_language_scanner.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- flex -i -Pzend -ozend_language_scanner.c zend_language_scanner.l
-
-# End Custom Build
-
-!ELSEIF "$(CFG)" == "Zend - Win32 Debug"
-
-# Begin Custom Build
-InputPath=".\zend_language_scanner.l"
-
-"zend_language_scanner.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- flex -i -Pzend -ozend_language_scanner.c zend_language_scanner.l
-
-# End Custom Build
-
-!ELSEIF "$(CFG)" == "Zend - Win32 Release_inline"
-
-# Begin Custom Build
-InputPath=".\zend_language_scanner.l"
-
-"zend_language_scanner.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- flex -i -Pzend -ozend_language_scanner.c zend_language_scanner.l
-
-# End Custom Build
-
-!ENDIF
-
-# End Source File
-# End Group
-# Begin Group "Text Files"
-
-# PROP Default_Filter ""
-# Begin Source File
-
-SOURCE=.\ZEND_BUGS
-# End Source File
-# Begin Source File
-
-SOURCE=.\ZEND_CHANGES
-# End Source File
-# Begin Source File
-
-SOURCE=.\ZEND_TODO
-# End Source File
-# End Group
-# Begin Group "Resources"
-
-# PROP Default_Filter ""
-# Begin Source File
-
-SOURCE=.\zend.ico
-# End Source File
-# End Group
-# End Target
-# End Project
diff --git a/Zend/ZendTS.dsp b/Zend/ZendTS.dsp deleted file mode 100644 index 4c6ef92465..0000000000 --- a/Zend/ZendTS.dsp +++ /dev/null @@ -1,752 +0,0 @@ -# Microsoft Developer Studio Project File - Name="ZendTS" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Static Library" 0x0104
-
-CFG=ZendTS - Win32 Release_TSDbg
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "ZendTS.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "ZendTS.mak" CFG="ZendTS - Win32 Release_TSDbg"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "ZendTS - Win32 Release_TS" (based on "Win32 (x86) Static Library")
-!MESSAGE "ZendTS - Win32 Debug_TS" (based on "Win32 (x86) Static Library")
-!MESSAGE "ZendTS - Win32 Release_TS_inline" (based on "Win32 (x86) Static Library")
-!MESSAGE "ZendTS - Win32 Release_TSDbg" (based on "Win32 (x86) Static Library")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "ZendTS - Win32 Release_TS"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Output_Dir "Release_TS"
-# PROP BASE Intermediate_Dir "Release_TS"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Output_Dir "Release_TS"
-# PROP Intermediate_Dir "Release_TS"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDebug_TS" /D "_MBCS" /D "_LIB" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /D "NDebug_TS" /D ZEND_DEBUG=0 /D _WIN32_WINNT=0x400 /D "_LIB" /D "TSRM_EXPORTS" /D "LIBZEND_EXPORTS" /D "ZTS" /D "ZEND_WIN32" /D "WIN32" /D "_MBCS" /FR /FD /c
-# SUBTRACT CPP /YX
-# ADD BASE RSC /l 0x40d /d "NDebug_TS"
-# ADD RSC /l 0x40d /d "NDebug_TS"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo
-
-!ELSEIF "$(CFG)" == "ZendTS - Win32 Debug_TS"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Output_Dir "Debug_TS"
-# PROP BASE Intermediate_Dir "Debug_TS"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Output_Dir "Debug_TS"
-# PROP Intermediate_Dir "Debug_TS"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_Debug_TS" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
-# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "." /D "_Debug_TS" /D ZEND_DEBUG=1 /D "_LIB" /D "TSRM_EXPORTS" /D "LIBZEND_EXPORTS" /D "ZTS" /D "ZEND_WIN32" /D "WIN32" /D "_MBCS" /FR /YX /FD /GZ /c
-# ADD BASE RSC /l 0x40d /d "_Debug_TS"
-# ADD RSC /l 0x40d /d "_Debug_TS"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo
-
-!ELSEIF "$(CFG)" == "ZendTS - Win32 Release_TS_inline"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Output_Dir "ZendTS___Win32_Release_TS_inline"
-# PROP BASE Intermediate_Dir "ZendTS___Win32_Release_TS_inline"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Output_Dir "Release_TS_inline"
-# PROP Intermediate_Dir "Release_TS_inline"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I "." /D "NDebug_TS" /D "_LIB" /D "TSRM_EXPORTS" /D "LIBZEND_EXPORTS" /D "ZTS" /D "WIN32" /D "_MBCS" /D ZEND_DEBUG=0 /FR /FD /c
-# SUBTRACT BASE CPP /YX
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /D "NDebug_TS" /D ZEND_DEBUG=0 /D "ZEND_WIN32_FORCE_INLINE" /D _WIN32_WINNT=0x400 /D "_LIB" /D "TSRM_EXPORTS" /D "LIBZEND_EXPORTS" /D "ZTS" /D "ZEND_WIN32" /D "WIN32" /D "_MBCS" /FR /FD /c
-# SUBTRACT CPP /YX
-# ADD BASE RSC /l 0x40d /d "NDebug_TS"
-# ADD RSC /l 0x40d /d "NDebug_TS"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo
-
-!ELSEIF "$(CFG)" == "ZendTS - Win32 Release_TSDbg"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Output_Dir "ZendTS___Win32_Release_TSDbg"
-# PROP BASE Intermediate_Dir "ZendTS___Win32_Release_TSDbg"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Output_Dir "Release_TSDbg"
-# PROP Intermediate_Dir "Release_TSDbg"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I "." /D "NDebug_TS" /D ZEND_DEBUG=0 /D _WIN32_WINNT=0x400 /D "_LIB" /D "TSRM_EXPORTS" /D "LIBZEND_EXPORTS" /D "ZTS" /D "ZEND_WIN32" /D "WIN32" /D "_MBCS" /FR /FD /c
-# SUBTRACT BASE CPP /YX
-# ADD CPP /nologo /MD /W3 /GX /Zi /Od /I "." /D "NDebug_TS" /D ZEND_DEBUG=0 /D _WIN32_WINNT=0x400 /D "_LIB" /D "TSRM_EXPORTS" /D "LIBZEND_EXPORTS" /D "ZTS" /D "ZEND_WIN32" /D "WIN32" /D "_MBCS" /FR /FD /c
-# SUBTRACT CPP /YX
-# ADD BASE RSC /l 0x40d /d "NDebug_TS"
-# ADD RSC /l 0x40d /d "NDebug_TS"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo
-
-!ENDIF
-
-# Begin Target
-
-# Name "ZendTS - Win32 Release_TS"
-# Name "ZendTS - Win32 Debug_TS"
-# Name "ZendTS - Win32 Release_TS_inline"
-# Name "ZendTS - Win32 Release_TSDbg"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=.\zend.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_alloc.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_ast.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_API.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_builtin_functions.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_closures.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_compile.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_constants.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_default_classes.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_dynamic_array.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_exceptions.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_execute.c
-# ADD CPP /I "..\TSRM"
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_execute_API.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_extensions.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_generators.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_hash.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_highlight.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_indent.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_inheritance.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_ini.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_ini_parser.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_ini_scanner.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_interfaces.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_iterators.c
-# End Source File
-# Begin Source File
-
-SOURCE=".\zend_language_parser.c"
-# End Source File
-# Begin Source File
-
-SOURCE=".\zend_language_scanner.c"
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_list.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_llist.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_object_handlers.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_objects.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_objects_API.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_opcode.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_operators.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_ptr_stack.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_qsort.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_sprintf.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_stack.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_stream.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_string.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_strtod.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_ts_hash.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_variables.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_vm_opcodes.c
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE=.\FlexLexer.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_alloc.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_API.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_builtin_functions.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_compile.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_config.w32.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_constants.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_default_classes.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_dynamic_array.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_errors.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_exceptions.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_execute.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_extensions.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_globals.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_globals_macros.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_hash.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_highlight.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_indent.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_ini.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_ini_parser.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_ini_scanner.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_interfaces.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_istdiostream.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_iterators.h
-# End Source File
-# Begin Source File
-
-SOURCE=".\zend_language_parser.h"
-# End Source File
-# Begin Source File
-
-SOURCE=".\zend_language_scanner.h"
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_list.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_llist.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_modules.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_object_handlers.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_objects.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_objects_API.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_operators.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_ptr_stack.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_qsort.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_stack.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_stream.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_string.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_strtod.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_ts_hash.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_variables.h
-# End Source File
-# End Group
-# Begin Group "Parsers"
-
-# PROP Default_Filter "y"
-# Begin Source File
-
-SOURCE=.\zend_ini_parser.y
-
-!IF "$(CFG)" == "ZendTS - Win32 Release_TS"
-
-# Begin Custom Build
-InputDir=.
-InputPath=.\zend_ini_parser.y
-
-BuildCmds= \
- bison --output=zend_ini_parser.c -v -d -p ini_ zend_ini_parser.y
-
-"$(InputDir)\zend_ini_parser.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- $(BuildCmds)
-
-"$(InputDir)\zend_ini_parser.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- $(BuildCmds)
-# End Custom Build
-
-!ELSEIF "$(CFG)" == "ZendTS - Win32 Debug_TS"
-
-# Begin Custom Build
-InputDir=.
-InputPath=.\zend_ini_parser.y
-
-BuildCmds= \
- bison --output=zend_ini_parser.c -v -d -p ini_ zend_ini_parser.y
-
-"$(InputDir)\zend_ini_parser.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- $(BuildCmds)
-
-"$(InputDir)\zend_ini_parser.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- $(BuildCmds)
-# End Custom Build
-
-!ELSEIF "$(CFG)" == "ZendTS - Win32 Release_TS_inline"
-
-# Begin Custom Build
-InputDir=.
-InputPath=.\zend_ini_parser.y
-
-BuildCmds= \
- bison --output=zend_ini_parser.c -v -d -p ini_ zend_ini_parser.y
-
-"$(InputDir)\zend_ini_parser.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- $(BuildCmds)
-
-"$(InputDir)\zend_ini_parser.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- $(BuildCmds)
-# End Custom Build
-
-!ELSEIF "$(CFG)" == "ZendTS - Win32 Release_TSDbg"
-
-# Begin Custom Build
-InputDir=.
-InputPath=.\zend_ini_parser.y
-
-BuildCmds= \
- bison --output=zend_ini_parser.c -v -d -p ini_ zend_ini_parser.y
-
-"$(InputDir)\zend_ini_parser.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- $(BuildCmds)
-
-"$(InputDir)\zend_ini_parser.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- $(BuildCmds)
-# End Custom Build
-
-!ENDIF
-
-# End Source File
-# Begin Source File
-
-SOURCE=".\zend_language_parser.y"
-
-!IF "$(CFG)" == "ZendTS - Win32 Release_TS"
-
-# Begin Custom Build
-InputDir=.
-InputPath=".\zend_language_parser.y"
-
-BuildCmds= \
- bison --output=zend_language_parser.c -v -d -p zend zend_language_parser.y
-
-"$(InputDir)\zend_language_parser.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- $(BuildCmds)
-
-"$(InputDir)\zend_language_parser.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- $(BuildCmds)
-# End Custom Build
-
-!ELSEIF "$(CFG)" == "ZendTS - Win32 Debug_TS"
-
-# Begin Custom Build
-InputDir=.
-InputPath=".\zend_language_parser.y"
-
-BuildCmds= \
- bison --output=zend_language_parser.c -v -d -p zend zend_language_parser.y
-
-"$(InputDir)\zend_language_parser.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- $(BuildCmds)
-
-"$(InputDir)\zend_language_parser.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- $(BuildCmds)
-# End Custom Build
-
-!ELSEIF "$(CFG)" == "ZendTS - Win32 Release_TS_inline"
-
-# Begin Custom Build
-InputDir=.
-InputPath=".\zend_language_parser.y"
-
-BuildCmds= \
- bison --output=zend_language_parser.c -v -d -p zend zend_language_parser.y
-
-"$(InputDir)\zend_language_parser.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- $(BuildCmds)
-
-"$(InputDir)\zend_language_parser.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- $(BuildCmds)
-# End Custom Build
-
-!ELSEIF "$(CFG)" == "ZendTS - Win32 Release_TSDbg"
-
-# Begin Custom Build
-InputDir=.
-InputPath=".\zend_language_parser.y"
-
-BuildCmds= \
- bison --output=zend_language_parser.c -v -d -p zend zend_language_parser.y
-
-"$(InputDir)\zend_language_parser.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- $(BuildCmds)
-
-"$(InputDir)\zend_language_parser.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- $(BuildCmds)
-# End Custom Build
-
-!ENDIF
-
-# End Source File
-# End Group
-# Begin Group "Scanners"
-
-# PROP Default_Filter "l"
-# Begin Source File
-
-SOURCE=.\flex.skl
-# End Source File
-# Begin Source File
-
-SOURCE=.\zend_ini_scanner.l
-
-!IF "$(CFG)" == "ZendTS - Win32 Release_TS"
-
-# Begin Custom Build
-InputPath=.\zend_ini_scanner.l
-
-"zend_ini_scanner.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- flex -B -i -Sflex.skl -Pini_ -ozend_ini_scanner.c zend_ini_scanner.l
-
-# End Custom Build
-
-!ELSEIF "$(CFG)" == "ZendTS - Win32 Debug_TS"
-
-# Begin Custom Build
-InputPath=.\zend_ini_scanner.l
-
-"zend_ini_scanner.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- flex -B -i -Sflex.skl -Pini_ -ozend_ini_scanner.c zend_ini_scanner.l
-
-# End Custom Build
-
-!ELSEIF "$(CFG)" == "ZendTS - Win32 Release_TS_inline"
-
-# Begin Custom Build
-InputPath=.\zend_ini_scanner.l
-
-"zend_ini_scanner.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- flex -B -i -Sflex.skl -Pini_ -ozend_ini_scanner.c zend_ini_scanner.l
-
-# End Custom Build
-
-!ELSEIF "$(CFG)" == "ZendTS - Win32 Release_TSDbg"
-
-# Begin Custom Build
-InputPath=.\zend_ini_scanner.l
-
-"zend_ini_scanner.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- flex -B -i -Sflex.skl -Pini_ -ozend_ini_scanner.c zend_ini_scanner.l
-
-# End Custom Build
-
-!ENDIF
-
-# End Source File
-# Begin Source File
-
-SOURCE=".\zend_language_scanner.l"
-
-!IF "$(CFG)" == "ZendTS - Win32 Release_TS"
-
-# Begin Custom Build
-InputPath=".\zend_language_scanner.l"
-
-"zend_language_scanner.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- flex -B -i -Sflex.skl -Pzend -ozend_language_scanner.c zend_language_scanner.l
-
-# End Custom Build
-
-!ELSEIF "$(CFG)" == "ZendTS - Win32 Debug_TS"
-
-# Begin Custom Build
-InputPath=".\zend_language_scanner.l"
-
-"zend_language_scanner.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- flex -B -i -Sflex.skl -Pzend -ozend_language_scanner.c zend_language_scanner.l
-
-# End Custom Build
-
-!ELSEIF "$(CFG)" == "ZendTS - Win32 Release_TS_inline"
-
-# Begin Custom Build
-InputPath=".\zend_language_scanner.l"
-
-"zend_language_scanner.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- flex -B -i -Sflex.skl -Pzend -ozend_language_scanner.c zend_language_scanner.l
-
-# End Custom Build
-
-!ELSEIF "$(CFG)" == "ZendTS - Win32 Release_TSDbg"
-
-# Begin Custom Build
-InputPath=".\zend_language_scanner.l"
-
-"zend_language_scanner.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- flex -B -i -Sflex.skl -Pzend -ozend_language_scanner.c zend_language_scanner.l
-
-# End Custom Build
-
-!ENDIF
-
-# End Source File
-# End Group
-# Begin Group "Text Files"
-
-# PROP Default_Filter ""
-# Begin Source File
-
-SOURCE=.\LICENSE
-# End Source File
-# Begin Source File
-
-SOURCE=.\ZEND_BUGS
-# End Source File
-# Begin Source File
-
-SOURCE=.\ZEND_CHANGES
-# End Source File
-# End Group
-# Begin Group "Resources"
-
-# PROP Default_Filter ""
-# Begin Source File
-
-SOURCE=.\zend.ico
-# End Source File
-# End Group
-# End Target
-# End Project
diff --git a/Zend/tests/bug39304.phpt b/Zend/tests/bug39304.phpt index 5540135fa4..2e9ebcdee4 100644 --- a/Zend/tests/bug39304.phpt +++ b/Zend/tests/bug39304.phpt @@ -8,9 +8,5 @@ echo "I am alive"; ?> --EXPECTF-- Notice: Uninitialized string offset: 0 in %sbug39304.php on line %d - -Notice: Uninitialized string offset: 0 in %sbug39304.php on line %d - -Notice: Uninitialized string offset: 1 in %sbug39304.php on line %d I am alive diff --git a/Zend/tests/bug39304_2_4.phpt b/Zend/tests/bug39304_2_4.phpt index cc0709b424..917c64e2cd 100644 --- a/Zend/tests/bug39304_2_4.phpt +++ b/Zend/tests/bug39304_2_4.phpt @@ -10,9 +10,5 @@ Bug #39304 (Segmentation fault with list unpacking of string offset) ?> --EXPECTF-- Notice: Uninitialized string offset: 0 in %sbug39304_2_4.php on line %d - -Notice: Uninitialized string offset: 0 in %sbug39304_2_4.php on line %d - -Notice: Uninitialized string offset: 1 in %sbug39304_2_4.php on line %d -string(0) "" -string(0) "" +NULL +NULL diff --git a/Zend/tests/bug68118.phpt b/Zend/tests/bug68118.phpt new file mode 100644 index 0000000000..c56e70a112 --- /dev/null +++ b/Zend/tests/bug68118.phpt @@ -0,0 +1,21 @@ +--TEST-- +Bug #68118: $a->foo .= 'test'; can leave $a->foo undefined +--FILE-- +<?php + +set_error_handler(function() { + $obj = new stdClass; + $obj->test = 'meow'; + return true; +}); + +$a = new stdClass; +$a->undefined .= 'test'; +var_dump($a); + +?> +--EXPECT-- +object(stdClass)#2 (1) { + ["undefined"]=> + string(4) "test" +} diff --git a/Zend/tests/bug68148.phpt b/Zend/tests/bug68148.phpt new file mode 100644 index 0000000000..fcbf69bb87 --- /dev/null +++ b/Zend/tests/bug68148.phpt @@ -0,0 +1,17 @@ +--TEST-- +Bug #68148: $this is null inside include +--FILE-- +<?php + +class Test { + public function method() { + eval('var_dump($this);'); + } +} + +(new Test)->method(); + +?> +--EXPECT-- +object(Test)#1 (0) { +} diff --git a/Zend/tests/bug68162.phpt b/Zend/tests/bug68162.phpt new file mode 100644 index 0000000000..24e412f18d --- /dev/null +++ b/Zend/tests/bug68162.phpt @@ -0,0 +1,14 @@ +--TEST-- +Bug #68162: isset($$varname) always true +--FILE-- +<?php + +$name = 'var'; +var_dump(isset($$name)); +$var = 42; +var_dump(isset($$name)); + +?> +--EXPECT-- +bool(false) +bool(true) diff --git a/Zend/tests/bug68163.phpt b/Zend/tests/bug68163.phpt new file mode 100644 index 0000000000..2ea0da33d6 --- /dev/null +++ b/Zend/tests/bug68163.phpt @@ -0,0 +1,13 @@ +--TEST-- +Bug #68163: Using reference as object property name +--FILE-- +<?php + +$obj = (object) ['foo' => 'bar']; +$foo = 'foo'; +$ref =& $foo; +var_dump($obj->$foo); + +?> +--EXPECT-- +string(3) "bar" diff --git a/Zend/tests/bug68191.phpt b/Zend/tests/bug68191.phpt new file mode 100644 index 0000000000..198c5c7dce --- /dev/null +++ b/Zend/tests/bug68191.phpt @@ -0,0 +1,21 @@ +--TEST-- +Bug #68191: Broken reference across objects +--FILE-- +<?php + +$obj = new stdClass; + +$obj->prop1 = 'abc'; +$obj->prop2 =& $obj->prop1; +$obj->prop2 .= 'xyz'; +var_dump($obj->prop1); + +$obj->prop3 = 1; +$obj->prop4 =& $obj->prop3; +++$obj->prop4; +var_dump($obj->prop3); + +?> +--EXPECT-- +string(6) "abcxyz" +int(2) diff --git a/Zend/tests/bug68215.phpt b/Zend/tests/bug68215.phpt new file mode 100644 index 0000000000..c4e8da8515 --- /dev/null +++ b/Zend/tests/bug68215.phpt @@ -0,0 +1,91 @@ +--TEST-- +Bug #68215 (Behavior of foreach has changed) +--FILE-- +<?php +$arr = array( + 'a' => array( + 'a' => 'apple', + 'b' => 'banana', + 'c' => 'cranberry', + 'd' => 'mango', + 'e' => 'pineapple' + ), + 'b' => array( + 'a' => 'apple', + 'b' => 'banana', + 'c' => 'cranberry', + 'd' => 'mango', + 'e' => 'pineapple' + ), + 'c' => 'cranberry', + 'd' => 'mango', + 'e' => 'pineapple' +); + +function test(&$child, $entry) +{ + $i = 1; + + foreach ($child AS $key => $fruit) + { + if (!is_numeric($key)) + { + $child[$i] = $fruit; + unset($child[$key]); + $i++; + } + } +} + +$i = 1; + +foreach ($arr AS $key => $fruit) +{ + $arr[$i] = $fruit; + + if (is_array($fruit)) + { + test($arr[$i], $fruit); + } + + unset($arr[$key]); + $i++; +} + +var_dump($arr); +?> +--EXPECT-- +array(5) { + [1]=> + array(5) { + [1]=> + string(5) "apple" + [2]=> + string(6) "banana" + [3]=> + string(9) "cranberry" + [4]=> + string(5) "mango" + [5]=> + string(9) "pineapple" + } + [2]=> + array(5) { + [1]=> + string(5) "apple" + [2]=> + string(6) "banana" + [3]=> + string(9) "cranberry" + [4]=> + string(5) "mango" + [5]=> + string(9) "pineapple" + } + [3]=> + string(9) "cranberry" + [4]=> + string(5) "mango" + [5]=> + string(9) "pineapple" +} diff --git a/Zend/tests/bug68262.phpt b/Zend/tests/bug68262.phpt new file mode 100644 index 0000000000..8d009f621e --- /dev/null +++ b/Zend/tests/bug68262.phpt @@ -0,0 +1,24 @@ +--TEST-- +Bug #68262: Broken reference across cloned objects +--FILE-- +<?php + +class C { + public $p; +} + +$first = new C; +$first->p = 'init'; + +$clone = clone $first; +$ref =& $first->p; +unset($ref); + +$clone = clone $first; +$clone->p = 'foo'; + +var_dump($first->p); + +?> +--EXPECT-- +string(4) "init" diff --git a/Zend/tests/builtin_in_write_context_error1.phpt b/Zend/tests/builtin_in_write_context_error1.phpt new file mode 100644 index 0000000000..eed03cc3c1 --- /dev/null +++ b/Zend/tests/builtin_in_write_context_error1.phpt @@ -0,0 +1,10 @@ +--TEST-- +Cannot use built-in functions in write context (assignment) +--FILE-- +<?php + +strlen("foo")[0] = 1; + +?> +--EXPECTF-- +Fatal error: Cannot use result of built-in function in write context in %s on line %d diff --git a/Zend/tests/builtin_in_write_context_error2.phpt b/Zend/tests/builtin_in_write_context_error2.phpt new file mode 100644 index 0000000000..aac23e4f4e --- /dev/null +++ b/Zend/tests/builtin_in_write_context_error2.phpt @@ -0,0 +1,10 @@ +--TEST-- +Cannot use built-in functions in write context (reference) +--FILE-- +<?php + +$ref =& strlen("foo"); + +?> +--EXPECTF-- +Fatal error: Cannot use result of built-in function in write context in %s on line %d diff --git a/Zend/tests/bw_or_assign_with_ref.phpt b/Zend/tests/bw_or_assign_with_ref.phpt new file mode 100644 index 0000000000..27ccf6299b --- /dev/null +++ b/Zend/tests/bw_or_assign_with_ref.phpt @@ -0,0 +1,14 @@ +--TEST-- +Bitwise or assign with referenced value +--FILE-- +<?php + +$num1 = 1; +$num2 = '2'; +$ref =& $num2; +$num1 |= $num2; +var_dump($num1); + +?> +--EXPECT-- +int(3) diff --git a/Zend/tests/class_name_as_scalar_error_007.phpt b/Zend/tests/class_name_as_scalar_error_007.phpt new file mode 100644 index 0000000000..2bfa5f38f8 --- /dev/null +++ b/Zend/tests/class_name_as_scalar_error_007.phpt @@ -0,0 +1,10 @@ +--TEST-- +Cannot access self::class when no class scope is active +--FILE-- +<?php + +var_dump(self::class); + +?> +--EXPECTF-- +Fatal error: Cannot access self::class when no class scope is active in %s on line %d diff --git a/Zend/tests/constant_expressions_dynamic.phpt b/Zend/tests/constant_expressions_dynamic.phpt index 21c9216cc1..d4e06ee258 100644 --- a/Zend/tests/constant_expressions_dynamic.phpt +++ b/Zend/tests/constant_expressions_dynamic.phpt @@ -2,10 +2,76 @@ Dynamic Constant Expressions --FILE-- <?php -const FOO = 1; -const BAR = FOO | 2; -echo BAR; +const C_0 = 0; +const C_1 = 1; +const C_foo = "foo"; +const C_arr = [0 => 0, "foo" => "foo"]; + +const T_1 = C_1 | 2; +const T_2 = C_1 . "foo"; +const T_3 = C_1 > 1; +const T_4 = C_1 >= 1; +const T_5 = -C_1; +const T_6 = +C_1; +const T_7 = +C_foo; +const T_8 = !C_1; +const T_9 = C_0 || 0; +const T_10 = C_1 || 0; +const T_11 = C_0 && 1; +const T_12 = C_1 && 1; +const T_13 = C_0 ? "foo" : "bar"; +const T_14 = C_1 ? "foo" : "bar"; +const T_15 = C_0 ?: "bar"; +const T_16 = C_1 ?: "bar"; +const T_17 = C_arr[0]; +const T_18 = C_arr["foo"]; +const T_19 = [ + C_0, + "foo" => "foo", + 42 => 42, + 3.14 => 3.14, + null => null, + false => false, + true => true, +]; + +var_dump( + T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9, T_10, + T_11, T_12, T_13, T_14, T_15, T_16, T_17, T_18, T_19 +); + ?> ---EXPECTF-- -3 +--EXPECT-- +int(3) +string(4) "1foo" +bool(false) +bool(true) +int(-1) +int(1) +int(0) +bool(false) +bool(false) +bool(true) +bool(false) +bool(true) +string(3) "bar" +string(3) "foo" +string(3) "bar" +int(1) +int(0) +string(3) "foo" +array(6) { + [0]=> + bool(false) + ["foo"]=> + string(3) "foo" + [42]=> + int(42) + [3]=> + float(3.14) + [""]=> + NULL + [1]=> + bool(true) +} diff --git a/Zend/tests/constant_expressions_dynamic_class_name_error.phpt b/Zend/tests/constant_expressions_dynamic_class_name_error.phpt new file mode 100644 index 0000000000..3ce5844649 --- /dev/null +++ b/Zend/tests/constant_expressions_dynamic_class_name_error.phpt @@ -0,0 +1,11 @@ +--TEST-- +Dynamic class names can't be used in compile-time constant refs +--FILE-- +<?php + +$foo = 'test'; +const C = $foo::BAR; + +?> +--EXPECTF-- +Fatal error: Dynamic class names are not allowed in compile-time class constant references in %s on line %d diff --git a/Zend/tests/constant_expressions_invalid_offset_type_error.phpt b/Zend/tests/constant_expressions_invalid_offset_type_error.phpt new file mode 100644 index 0000000000..440eabc652 --- /dev/null +++ b/Zend/tests/constant_expressions_invalid_offset_type_error.phpt @@ -0,0 +1,11 @@ +--TEST-- +Can't use arrays as key for constant array +--FILE-- +<?php + +const C1 = 1; // force dynamic evaluation +const C2 = [C1, [] => 1]; + +?> +--EXPECTF-- +Fatal error: Illegal offset type in %s on line %d diff --git a/Zend/tests/constant_expressions_static_class_name_error.phpt b/Zend/tests/constant_expressions_static_class_name_error.phpt new file mode 100644 index 0000000000..f03a88b87e --- /dev/null +++ b/Zend/tests/constant_expressions_static_class_name_error.phpt @@ -0,0 +1,10 @@ +--TEST-- +Cannot use static::FOO in constant expressions +--FILE-- +<?php + +const C = static::FOO; + +?> +--EXPECTF-- +Fatal error: "static::" is not allowed in compile-time constants in %s on line %d diff --git a/Zend/tests/debug_backtrace_with_include_and_this.phpt b/Zend/tests/debug_backtrace_with_include_and_this.phpt new file mode 100644 index 0000000000..171ad9f451 --- /dev/null +++ b/Zend/tests/debug_backtrace_with_include_and_this.phpt @@ -0,0 +1,39 @@ +--TEST-- +debug_backtrace segmentation fault with include and error handler +--FILE-- +<?php +class CLWrapper { + function stream_open($path, $mode, $options, $opened_path) { + return false; + } +} + +class CL { + public function load($class) { + if (!include($class)) { + throw new Exception('Failed loading '.$class); + } + } +} + +stream_wrapper_register('class', 'CLWrapper'); +set_error_handler(function($code, $msg, $file, $line) { + $bt= debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2); + echo "ERR#$code: $msg @ ", $bt[1]['function'], "\n"; +}); + +try { + (new CL())->load('class://non.existant.Class'); +} catch (CLException $e) { + echo $e."\n"; +} +--EXPECTF-- +ERR#2: include(class://non.existant.Class): failed to open stream: "CLWrapper::stream_open" call failed @ include +ERR#2: include(): Failed opening 'class://non.existant.Class' for inclusion (include_path='%s') @ include + +Fatal error: Uncaught exception 'Exception' with message 'Failed loading class://non.existant.Class' in %s +Stack trace: +#0 %s(%d): CL->load('class://non.exi...') +#1 {main} + thrown in %s on line %d + diff --git a/Zend/tests/dereference_002.phpt b/Zend/tests/dereference_002.phpt index da13decc39..cc0f27d534 100644 --- a/Zend/tests/dereference_002.phpt +++ b/Zend/tests/dereference_002.phpt @@ -76,4 +76,4 @@ NULL Notice: Undefined offset: 3 in %s on line %d -Fatal error: Call to a member function bar() on null in %s on line %d +Catchable fatal error: Call to a member function bar() on null in %s on line %d diff --git a/Zend/tests/double_array_cast.phpt b/Zend/tests/double_array_cast.phpt new file mode 100644 index 0000000000..aaee8cd919 --- /dev/null +++ b/Zend/tests/double_array_cast.phpt @@ -0,0 +1,18 @@ +--TEST-- +Double array cast +--FILE-- +<?php + +$array = [1, 2, $x = 3]; +var_dump((array) (array) $array); + +?> +--EXPECT-- +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} diff --git a/Zend/tests/duplicate_label_error.phpt b/Zend/tests/duplicate_label_error.phpt new file mode 100644 index 0000000000..c89d7a6991 --- /dev/null +++ b/Zend/tests/duplicate_label_error.phpt @@ -0,0 +1,12 @@ +--TEST-- +Duplicate labels are not allowed +--FILE-- +<?php + +foo: +foo: +goto foo; + +?> +--EXPECTF-- +Fatal error: Label 'foo' already defined in %s on line %d diff --git a/Zend/tests/exception_with_by_ref_message.phpt b/Zend/tests/exception_with_by_ref_message.phpt new file mode 100644 index 0000000000..f15c3e2719 --- /dev/null +++ b/Zend/tests/exception_with_by_ref_message.phpt @@ -0,0 +1,21 @@ +--TEST-- +Exception with by-ref message +--FILE-- +<?php + +class MyException extends Exception +{ + public function __construct(&$msg) { + $this->message =& $msg; + } +} + +$msg = 'Message'; +throw new MyException($msg); + +?> +--EXPECTF-- +Fatal error: Uncaught exception 'MyException' with message 'Message' in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/foreach_list_002.phpt b/Zend/tests/foreach_list_002.phpt index bc17d94268..1a7be521b2 100644 --- a/Zend/tests/foreach_list_002.phpt +++ b/Zend/tests/foreach_list_002.phpt @@ -18,9 +18,5 @@ foreach($array as list(, $a)) { int(1) int(3) string(1) "b" - -Notice: Uninitialized string offset: 1 in %sforeach_list_002.php on line %d -string(0) "" - -Notice: Uninitialized string offset: 1 in %sforeach_list_002.php on line %d -string(0) "" +NULL +NULL diff --git a/Zend/tests/gc_029_zts.phpt b/Zend/tests/gc_029_zts.phpt index fc77e1f3bd..5d16e83348 100644 --- a/Zend/tests/gc_029_zts.phpt +++ b/Zend/tests/gc_029_zts.phpt @@ -34,4 +34,4 @@ unset($bar); var_dump(gc_collect_cycles()); ?> --EXPECT-- -int(3) +int(6) diff --git a/Zend/tests/gc_033.phpt b/Zend/tests/gc_033.phpt index bcd1541254..dee426a385 100644 --- a/Zend/tests/gc_033.phpt +++ b/Zend/tests/gc_033.phpt @@ -1,5 +1,7 @@ --TEST-- GC 033: Crash in GC while run with phpspec +--XFAIL-- +Full GC root buffer not handled correctly yet --FILE-- <?php $a = new stdClass(); diff --git a/Zend/tests/incdec_ref_property.phpt b/Zend/tests/incdec_ref_property.phpt new file mode 100644 index 0000000000..a73b2912ab --- /dev/null +++ b/Zend/tests/incdec_ref_property.phpt @@ -0,0 +1,27 @@ +--TEST-- +Incrementing and decrementing a referenced property +--FILE-- +<?php + +$obj = new stdClass; +$obj->prop = 1; +$ref =& $obj->prop; +var_dump(++$obj->prop); +var_dump($obj->prop); +var_dump($obj->prop++); +var_dump($obj->prop); +var_dump(--$obj->prop); +var_dump($obj->prop); +var_dump($obj->prop--); +var_dump($obj->prop); + +?> +--EXPECT-- +int(2) +int(2) +int(2) +int(3) +int(2) +int(2) +int(2) +int(1) diff --git a/Zend/tests/line_const_in_array.phpt b/Zend/tests/line_const_in_array.phpt new file mode 100644 index 0000000000..181f67e3da --- /dev/null +++ b/Zend/tests/line_const_in_array.phpt @@ -0,0 +1,21 @@ +--TEST-- +Use of __LINE__ in arrays +--FILE-- +<?php + +var_dump([ + __LINE__, + __LINE__, + __LINE__, +]); + +?> +--EXPECT-- +array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) +} diff --git a/Zend/tests/list_005.phpt b/Zend/tests/list_005.phpt index ec5640a60a..a3b0d57434 100644 --- a/Zend/tests/list_005.phpt +++ b/Zend/tests/list_005.phpt @@ -35,9 +35,9 @@ var_dump($a, $b, $c); ?> --EXPECTF-- -string(1) "f" -string(1) "o" -string(1) "o" +NULL +NULL +NULL ---- NULL NULL diff --git a/Zend/tests/list_007.phpt b/Zend/tests/list_007.phpt index 35a25bce65..cc712406ec 100644 --- a/Zend/tests/list_007.phpt +++ b/Zend/tests/list_007.phpt @@ -8,6 +8,5 @@ list($x, $y) = function() { }; var_dump($x, $y); ?> ---EXPECT-- -NULL -NULL +--EXPECTF-- +Fatal error: Cannot use object of type Closure as array in %slist_007.php on line 3 diff --git a/Zend/tests/list_destructuring_to_special_variables.phpt b/Zend/tests/list_destructuring_to_special_variables.phpt new file mode 100644 index 0000000000..4418c967c2 --- /dev/null +++ b/Zend/tests/list_destructuring_to_special_variables.phpt @@ -0,0 +1,49 @@ +--TEST-- +list() can be used to destructure to string offsets, __set and ArrayAccess::offsetSet +--FILE-- +<?php + +class Obj { + public $values = []; + public function __set($name, $value) { + $this->values[$name] = $value; + } +} + +class Arr implements ArrayAccess { + public $values = []; + public function offsetSet($name, $value) { + $this->values[$name] = $value; + } + public function offsetGet($name) {} + public function offsetExists($name) {} + public function offsetUnset($name) {} +} + +$str = 'ab'; +list($str[0], $str[1]) = ['x', 'y']; +var_dump($str); + +$obj = new Obj; +list($obj->foo, $obj->bar) = ['foo', 'bar']; +var_dump($obj->values); + +$arr = new Arr; +list($arr['foo'], $arr['bar']) = ['foo', 'bar']; +var_dump($arr->values); + +?> +--EXPECT-- +string(2) "xy" +array(2) { + ["foo"]=> + string(3) "foo" + ["bar"]=> + string(3) "bar" +} +array(2) { + ["foo"]=> + string(3) "foo" + ["bar"]=> + string(3) "bar" +} diff --git a/Zend/tests/magic_const_in_global_scope.phpt b/Zend/tests/magic_const_in_global_scope.phpt new file mode 100644 index 0000000000..31f7eae6d7 --- /dev/null +++ b/Zend/tests/magic_const_in_global_scope.phpt @@ -0,0 +1,26 @@ +--TEST-- +Test use of magic constants in the global scope +--FILE-- +<?php + +var_dump( + __LINE__, + __FILE__, + __DIR__, + __FUNCTION__, + __METHOD__, + __CLASS__, + __TRAIT__, + __NAMESPACE__ +); + +?> +--EXPECTF-- +int(4) +string(%d) "%s" +string(%d) "%s" +string(0) "" +string(0) "" +string(0) "" +string(0) "" +string(0) "" diff --git a/Zend/tests/methods-on-non-objects-args-catch.phpt b/Zend/tests/methods-on-non-objects-args-catch.phpt new file mode 100644 index 0000000000..853d2d5602 --- /dev/null +++ b/Zend/tests/methods-on-non-objects-args-catch.phpt @@ -0,0 +1,18 @@ +--TEST-- +Catch method calls on non-objects raise recoverable errors +--FILE-- +<?php +set_error_handler(function($code, $message) { + var_dump($code, $message); +}); + +$x= null; +var_dump($x->method(1, 2, 3)); +echo "Alive\n"; +?> +--EXPECTF-- + +int(4096) +string(%d) "Call to a member function method() on null" +NULL +Alive diff --git a/Zend/tests/methods-on-non-objects-array-access.phpt b/Zend/tests/methods-on-non-objects-array-access.phpt new file mode 100755 index 0000000000..be87457c6c --- /dev/null +++ b/Zend/tests/methods-on-non-objects-array-access.phpt @@ -0,0 +1,18 @@ +--TEST-- +Catch method calls on non-objects inside array access +--FILE-- +<?php +set_error_handler(function($code, $message) { + var_dump($code, $message); +}); + +$x= null; +$a= [null => 'OK']; +var_dump($a[$x->method()]); +echo "Alive\n"; +?> +--EXPECTF-- +int(4096) +string(%d) "Call to a member function method() on null" +string(2) "OK" +Alive
\ No newline at end of file diff --git a/Zend/tests/methods-on-non-objects-array-creation.phpt b/Zend/tests/methods-on-non-objects-array-creation.phpt new file mode 100755 index 0000000000..74cbb9c179 --- /dev/null +++ b/Zend/tests/methods-on-non-objects-array-creation.phpt @@ -0,0 +1,35 @@ +--TEST-- +Catch method calls on non-objects inside array creation +--FILE-- +<?php +set_error_handler(function($code, $message) { + var_dump($code, $message); +}); + +$x= null; +var_dump([$x->method() => 'OK']); +var_dump([$x->method(), $x->method(), $x->method()]); +echo "Alive\n"; +?> +--EXPECTF-- +int(4096) +string(%d) "Call to a member function method() on null" +array(1) { + [""]=> + string(2) "OK" +} +int(4096) +string(%d) "Call to a member function method() on null" +int(4096) +string(%d) "Call to a member function method() on null" +int(4096) +string(%d) "Call to a member function method() on null" +array(3) { + [0]=> + NULL + [1]=> + NULL + [2]=> + NULL +} +Alive
\ No newline at end of file diff --git a/Zend/tests/methods-on-non-objects-as-arg.phpt b/Zend/tests/methods-on-non-objects-as-arg.phpt new file mode 100755 index 0000000000..13b83cb06e --- /dev/null +++ b/Zend/tests/methods-on-non-objects-as-arg.phpt @@ -0,0 +1,47 @@ +--TEST-- +Catch method calls on non-objects as argument +--FILE-- +<?php +function nesting() { + return func_get_args(); +} +set_error_handler(function($code, $message) { + static $i= 0; + echo 'Called #'.(++$i)."\n"; +}); + +$x= null; +var_dump(nesting($x->method())); +var_dump(nesting(nesting($x->method()))); +var_dump(nesting($x->method(nesting($x->method())))); +var_dump(nesting($x->method(), $x->method())); +echo "Alive\n"; +?> +--EXPECTF-- +Called #1 +array(1) { + [0]=> + NULL +} +Called #2 +array(1) { + [0]=> + array(1) { + [0]=> + NULL + } +} +Called #3 +array(1) { + [0]=> + NULL +} +Called #4 +Called #5 +array(2) { + [0]=> + NULL + [1]=> + NULL +} +Alive diff --git a/Zend/tests/methods-on-non-objects-call-user-func.phpt b/Zend/tests/methods-on-non-objects-call-user-func.phpt new file mode 100644 index 0000000000..f76b7d43a0 --- /dev/null +++ b/Zend/tests/methods-on-non-objects-call-user-func.phpt @@ -0,0 +1,13 @@ +--TEST-- +call_user_func() in combination with "Call to a member function method() on a non-object" +--FILE-- +<?php +$comparator= null; +var_dump(call_user_func([$comparator, 'compare'], 1, 2)); +echo "Alive\n"; +?> +--EXPECTF-- +Warning: call_user_func() expects parameter 1 to be a valid callback, first array member is not a valid class name or object in %s on line %d +NULL +Alive + diff --git a/Zend/tests/methods-on-non-objects-catch.phpt b/Zend/tests/methods-on-non-objects-catch.phpt new file mode 100644 index 0000000000..bbfadac107 --- /dev/null +++ b/Zend/tests/methods-on-non-objects-catch.phpt @@ -0,0 +1,18 @@ +--TEST-- +Catch method calls on non-objects raise recoverable errors +--FILE-- +<?php +set_error_handler(function($code, $message) { + var_dump($code, $message); +}); + +$x= null; +var_dump($x->method()); +echo "Alive\n"; +?> +--EXPECTF-- + +int(4096) +string(%d) "Call to a member function method() on null" +NULL +Alive diff --git a/Zend/tests/methods-on-non-objects-chain.phpt b/Zend/tests/methods-on-non-objects-chain.phpt new file mode 100644 index 0000000000..30da254cd5 --- /dev/null +++ b/Zend/tests/methods-on-non-objects-chain.phpt @@ -0,0 +1,22 @@ +--TEST-- +Catch chained method calls on non-objects raise recoverable errors +--FILE-- +<?php +set_error_handler(function($code, $message) { + var_dump($code, $message); +}); + +$x= null; +var_dump($x->method()->chained()->invocations()); +echo "Alive\n"; +?> +--EXPECTF-- + +int(4096) +string(%d) "Call to a member function method() on null" +int(4096) +string(%d) "Call to a member function chained() on null" +int(4096) +string(%d) "Call to a member function invocations() on null" +NULL +Alive diff --git a/Zend/tests/methods-on-non-objects-concat.phpt b/Zend/tests/methods-on-non-objects-concat.phpt new file mode 100755 index 0000000000..4ff47aa454 --- /dev/null +++ b/Zend/tests/methods-on-non-objects-concat.phpt @@ -0,0 +1,18 @@ +--TEST-- +Catch method calls on non-objects inside concatenation +--FILE-- +<?php +set_error_handler(function($code, $message) { + var_dump($code, $message); +}); + +$x= null; +echo "Before\n".$x->method()."After\n"; +echo "Alive\n"; +?> +--EXPECTF-- +int(4096) +string(%d) "Call to a member function method() on null" +Before +After +Alive
\ No newline at end of file diff --git a/Zend/tests/methods-on-non-objects-dynamic.phpt b/Zend/tests/methods-on-non-objects-dynamic.phpt new file mode 100755 index 0000000000..11c5c9f44b --- /dev/null +++ b/Zend/tests/methods-on-non-objects-dynamic.phpt @@ -0,0 +1,23 @@ +--TEST-- +Catch method calls on non-objects with dynamic lookups +--FILE-- +<?php +set_error_handler(function($code, $message) { + static $i= 0; + echo 'Called #'.(++$i)."\n"; +}); + +$arr= [null, 'method']; +var_dump($arr[0]->{$arr[1]}()); + +$fun= function() { return null; }; +var_dump($fun()->{'method'}()); + +echo "Alive\n"; +?> +--EXPECTF-- +Called #1 +NULL +Called #2 +NULL +Alive diff --git a/Zend/tests/methods-on-non-objects-eval.phpt b/Zend/tests/methods-on-non-objects-eval.phpt new file mode 100644 index 0000000000..8ee494c434 --- /dev/null +++ b/Zend/tests/methods-on-non-objects-eval.phpt @@ -0,0 +1,18 @@ +--TEST-- +Indirect call inside eval to member function on non-object +--FILE-- +<?php +set_error_handler(function($code, $message) { + var_dump($code, $message); +}); + +$x= null; +var_dump(eval('$x->method(1, 2, 3);')); +echo "Alive\n"; +?> +--EXPECTF-- + +int(4096) +string(%d) "Call to a member function method() on null" +NULL +Alive diff --git a/Zend/tests/methods-on-non-objects-in-echo.phpt b/Zend/tests/methods-on-non-objects-in-echo.phpt new file mode 100755 index 0000000000..a0267c0ea5 --- /dev/null +++ b/Zend/tests/methods-on-non-objects-in-echo.phpt @@ -0,0 +1,18 @@ +--TEST-- +Catch method calls on non-objects inside echo +--FILE-- +<?php +set_error_handler(function($code, $message) { + var_dump($code, $message); +}); + +$x= null; +echo "Before\n", $x->method(), "After\n"; +echo "Alive\n"; +?> +--EXPECTF-- +Before +int(4096) +string(%d) "Call to a member function method() on null" +After +Alive
\ No newline at end of file diff --git a/Zend/tests/methods-on-non-objects-nested-calls-dyn.phpt b/Zend/tests/methods-on-non-objects-nested-calls-dyn.phpt new file mode 100755 index 0000000000..267104f1b3 --- /dev/null +++ b/Zend/tests/methods-on-non-objects-nested-calls-dyn.phpt @@ -0,0 +1,37 @@ +--TEST-- +Catch method calls on non-objects with nested dynamic calls +--FILE-- +<?php +function nested() { + throw new LogicException('Should not be called'); +} +set_error_handler(function($code, $message) { + static $i= 0; + echo 'Called #'.(++$i)."\n"; +}); + +$x= null; + +$closure= function() { return nested(); }; +var_dump($x->method($closure())); + +$lambda= create_function('', 'return nested();'); +var_dump($x->method($lambda())); + +$func= 'nested'; +var_dump($x->method($func())); + +var_dump($x->method(call_user_func('nested'))); + +echo "Alive\n"; +?> +--EXPECTF-- +Called #1 +NULL +Called #2 +NULL +Called #3 +NULL +Called #4 +NULL +Alive diff --git a/Zend/tests/methods-on-non-objects-nested-calls-new.phpt b/Zend/tests/methods-on-non-objects-nested-calls-new.phpt new file mode 100755 index 0000000000..d8e3dd21bf --- /dev/null +++ b/Zend/tests/methods-on-non-objects-nested-calls-new.phpt @@ -0,0 +1,37 @@ +--TEST-- +Catch method calls on non-objects with nested calls to new +--FILE-- +<?php +class Nesting { +} +set_error_handler(function($code, $message) { + static $i= 0; + echo 'Called #'.(++$i)."\n"; +}); + +$x= null; +var_dump($x->method(new Nesting())); +var_dump($x->method(new Nesting(), new Nesting())); +var_dump($x->method(new Nesting(new Nesting()))); +var_dump($x->method(new Nesting($x->nested()))); +var_dump($x->method(new Nesting($x->nested(new Nesting())))); +var_dump($x->method($x->nested(new Nesting($x->deep())))); +var_dump($x->method([new Nesting()])); +echo "Alive\n"; +?> +--EXPECTF-- +Called #1 +NULL +Called #2 +NULL +Called #3 +NULL +Called #4 +NULL +Called #5 +NULL +Called #6 +NULL +Called #7 +NULL +Alive diff --git a/Zend/tests/methods-on-non-objects-nested-calls-nonct.phpt b/Zend/tests/methods-on-non-objects-nested-calls-nonct.phpt new file mode 100755 index 0000000000..a4529eecdc --- /dev/null +++ b/Zend/tests/methods-on-non-objects-nested-calls-nonct.phpt @@ -0,0 +1,43 @@ +--TEST-- +Catch method calls on non-objects with nested non-compile-time-resolveable calls +--FILE-- +<?php +require('methods-on-non-objects-nested.inc'); + +set_error_handler(function($code, $message) { + static $i= 0; + echo 'Called #'.(++$i)."\n"; +}); + +$x= null; + +var_dump($x->method(nested())); + +$closure= function() { return nested(); }; +var_dump($x->method($closure())); + +$lambda= create_function('', 'return nested();'); +var_dump($x->method($lambda())); + +$func= 'nested'; +var_dump($x->method($func())); + +var_dump($x->method(call_user_func('nested'))); +var_dump($x->method(call_user_func_array('nested', []))); + +echo "Alive\n"; +?> +--EXPECTF-- +Called #1 +NULL +Called #2 +NULL +Called #3 +NULL +Called #4 +NULL +Called #5 +NULL +Called #6 +NULL +Alive diff --git a/Zend/tests/methods-on-non-objects-nested-calls-ns.phpt b/Zend/tests/methods-on-non-objects-nested-calls-ns.phpt new file mode 100755 index 0000000000..b16f579fa9 --- /dev/null +++ b/Zend/tests/methods-on-non-objects-nested-calls-ns.phpt @@ -0,0 +1,26 @@ +--TEST-- +Catch method calls on non-objects with nested calls to namespaced functions with core counterparts +--FILE-- +<?php namespace test; +function strlen($str) { + throw new LogicException('Should not be called'); +} +set_error_handler(function($code, $message) { + static $i= 0; + echo 'Called #'.(++$i)."\n"; +}); + +$x= null; +var_dump($x->method(strlen('Test'))); +var_dump($x->method(strlen('Test'), strlen('Test'))); +var_dump($x->method([strlen('Test')])); +echo "Alive\n"; +?> +--EXPECTF-- +Called #1 +NULL +Called #2 +NULL +Called #3 +NULL +Alive diff --git a/Zend/tests/methods-on-non-objects-nested-calls-static.phpt b/Zend/tests/methods-on-non-objects-nested-calls-static.phpt new file mode 100755 index 0000000000..64972ee871 --- /dev/null +++ b/Zend/tests/methods-on-non-objects-nested-calls-static.phpt @@ -0,0 +1,33 @@ +--TEST-- +Catch method calls on non-objects with nested calls to static methods +--FILE-- +<?php +class Nesting { + static function nested() { + throw new LogicException('Should not be called'); + } +} +set_error_handler(function($code, $message) { + static $i= 0; + echo 'Called #'.(++$i)."\n"; +}); + +$x= null; +$class= 'Nesting'; +$method= 'nested'; +var_dump($x->method(Nesting::nested())); +var_dump($x->method($class::nested())); +var_dump($x->method($class::{$method}())); +var_dump($x->method([Nesting::nested()])); +echo "Alive\n"; +?> +--EXPECTF-- +Called #1 +NULL +Called #2 +NULL +Called #3 +NULL +Called #4 +NULL +Alive diff --git a/Zend/tests/methods-on-non-objects-nested-calls.phpt b/Zend/tests/methods-on-non-objects-nested-calls.phpt new file mode 100644 index 0000000000..b25aeafd9c --- /dev/null +++ b/Zend/tests/methods-on-non-objects-nested-calls.phpt @@ -0,0 +1,47 @@ +--TEST-- +Catch method calls on non-objects with nested function and method calls +--FILE-- +<?php +function nested() { + throw new LogicException('Should not be called'); +} +set_error_handler(function($code, $message) { + static $i= 0; + echo 'Called #'.(++$i)."\n"; +}); + +$x= null; +var_dump($x->method(nested())); +var_dump($x->method(nested(), nested())); +var_dump($x->method(nested(nested()))); +var_dump($x->method($x->nested())); +var_dump($x->method($x->nested(), $x->nested())); +var_dump($x->method($x->nested(nested()))); +var_dump($x->method($x->nested($x->deep()))); +var_dump($x->method($x->nested(nested($x->deep())))); +var_dump($x->method(nested(nested($x->nested())))); +var_dump($x->method([nested()])); +echo "Alive\n"; +?> +--EXPECTF-- +Called #1 +NULL +Called #2 +NULL +Called #3 +NULL +Called #4 +NULL +Called #5 +NULL +Called #6 +NULL +Called #7 +NULL +Called #8 +NULL +Called #9 +NULL +Called #10 +NULL +Alive diff --git a/Zend/tests/methods-on-non-objects-nested.inc b/Zend/tests/methods-on-non-objects-nested.inc new file mode 100755 index 0000000000..8511414b82 --- /dev/null +++ b/Zend/tests/methods-on-non-objects-nested.inc @@ -0,0 +1,4 @@ +<?php +function nested() { + throw new LogicException('Should not be called'); +}
\ No newline at end of file diff --git a/Zend/tests/methods-on-non-objects-return-unused.phpt b/Zend/tests/methods-on-non-objects-return-unused.phpt new file mode 100755 index 0000000000..ab2951f94f --- /dev/null +++ b/Zend/tests/methods-on-non-objects-return-unused.phpt @@ -0,0 +1,17 @@ +--TEST-- +Catch method calls on non-objects without using return value +--INI-- +report_memleaks=1 +--FILE-- +<?php +set_error_handler(function($code, $message) { + echo "Caught\n"; +}); + +$x= null; +$x->method(); +echo "Alive\n"; +?> +--EXPECTF-- +Caught +Alive diff --git a/Zend/tests/methods-on-non-objects-throw.phpt b/Zend/tests/methods-on-non-objects-throw.phpt new file mode 100644 index 0000000000..874f57cb24 --- /dev/null +++ b/Zend/tests/methods-on-non-objects-throw.phpt @@ -0,0 +1,29 @@ +--TEST-- +Convert errors to exceptions from method calls on non-objects raise recoverable errors +--FILE-- +<?php +set_error_handler(function($code, $message) { + echo "Raising...\n"; + if (0 === strncmp('Call', $message, 4)) { + throw new BadMethodCallException($message); + } else if (0 === strncmp('Argument', $message, 8)) { + throw new InvalidArgumentException($message); + } else { + trigger_error($message, E_USER_ERROR); + } +}, E_RECOVERABLE_ERROR); + +$x= null; +echo "Calling...\n"; +try { + $x->method(); +} catch (BadMethodCallException $e) { + echo "Caught expected ", $e->getMessage(), "!\n"; +} +echo "Alive\n"; +?> +--EXPECTF-- +Calling... +Raising... +Caught expected Call to a member function method() on null! +Alive diff --git a/Zend/tests/methods-on-non-objects-usort.phpt b/Zend/tests/methods-on-non-objects-usort.phpt new file mode 100644 index 0000000000..760d481b27 --- /dev/null +++ b/Zend/tests/methods-on-non-objects-usort.phpt @@ -0,0 +1,43 @@ +--TEST-- +usort() in combination with "Call to a member function method() on null" +--FILE-- +<?php +set_error_handler(function($code, $message) { + var_dump($code, $message); +}); + +$comparator= null; +$list= [1, 4, 2, 3, -1]; +usort($list, function($a, $b) use ($comparator) { + return $comparator->compare($a, $b); +}); +var_dump($list); +echo "Alive\n"; +?> +--EXPECTF-- +int(4096) +string(43) "Call to a member function compare() on null" +int(4096) +string(43) "Call to a member function compare() on null" +int(4096) +string(43) "Call to a member function compare() on null" +int(4096) +string(43) "Call to a member function compare() on null" +int(4096) +string(43) "Call to a member function compare() on null" +int(4096) +string(43) "Call to a member function compare() on null" +array(5) { + [0]=> + int(-1) + [1]=> + int(3) + [2]=> + int(2) + [3]=> + int(4) + [4]=> + int(1) +} +Alive + diff --git a/Zend/tests/methods-on-non-objects.phpt b/Zend/tests/methods-on-non-objects.phpt new file mode 100644 index 0000000000..01031b8b1d --- /dev/null +++ b/Zend/tests/methods-on-non-objects.phpt @@ -0,0 +1,12 @@ +--TEST-- +Method calls on non-objects raise recoverable errors +--FILE-- +<?php + +$x= null; +$x->method(); +echo "Should not get here!\n"; +?> +--EXPECTF-- + +Catchable fatal error: Call to a member function method() on null in %s on line %d diff --git a/Zend/tests/object_array_cast.phpt b/Zend/tests/object_array_cast.phpt new file mode 100644 index 0000000000..1cf3dbbd9c --- /dev/null +++ b/Zend/tests/object_array_cast.phpt @@ -0,0 +1,47 @@ +--TEST-- +(object) (array) and (array) (object) casts +--FILE-- +<?php + +$arr = [1, 2, 3]; +var_dump((object) (array) $arr); +var_dump($arr); + +$obj = (object) [1, 2, 3]; +var_dump((array) (object) $obj); +var_dump($obj); + +?> +--EXPECT-- +object(stdClass)#1 (3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +object(stdClass)#1 (3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} diff --git a/Zend/tests/special_name_error1.phpt b/Zend/tests/special_name_error1.phpt new file mode 100644 index 0000000000..63bf5a63fd --- /dev/null +++ b/Zend/tests/special_name_error1.phpt @@ -0,0 +1,10 @@ +--TEST-- +Cannot use special class name as namespace +--FILE-- +<?php + +namespace self; + +?> +--EXPECTF-- +Fatal error: Cannot use 'self' as namespace name in %s on line %d diff --git a/Zend/tests/special_name_error2.phpt b/Zend/tests/special_name_error2.phpt new file mode 100644 index 0000000000..08122b3249 --- /dev/null +++ b/Zend/tests/special_name_error2.phpt @@ -0,0 +1,10 @@ +--TEST-- +Cannot use special class name as alias +--FILE-- +<?php + +use Foo\Bar as self; + +?> +--EXPECTF-- +Fatal error: Cannot use Foo\Bar as self because 'self' is a special class name in %s on line %d diff --git a/Zend/tests/special_name_error3.phpt b/Zend/tests/special_name_error3.phpt new file mode 100644 index 0000000000..74e69f1938 --- /dev/null +++ b/Zend/tests/special_name_error3.phpt @@ -0,0 +1,10 @@ +--TEST-- +Cannot use special class name as trait name +--FILE-- +<?php + +trait self {} + +?> +--EXPECTF-- +Fatal error: Cannot use 'self' as class name as it is reserved in %s on line %d diff --git a/Zend/tests/this_as_lexical_var_error.phpt b/Zend/tests/this_as_lexical_var_error.phpt new file mode 100644 index 0000000000..d0e0106dae --- /dev/null +++ b/Zend/tests/this_as_lexical_var_error.phpt @@ -0,0 +1,14 @@ +--TEST-- +Cannot use $this as lexical variable +--FILE-- +<?php + +class Foo { + public function fn() { + return function() use ($this) {}; + } +} + +?> +--EXPECTF-- +Fatal error: Cannot use $this as lexical variable in %s on line %d diff --git a/Zend/tests/varSyntax/indirectFcall.phpt b/Zend/tests/varSyntax/indirectFcall.phpt index 4cc5c1171a..5d616d59a2 100644 --- a/Zend/tests/varSyntax/indirectFcall.phpt +++ b/Zend/tests/varSyntax/indirectFcall.phpt @@ -34,6 +34,7 @@ $obj = new Test; ['Test', 'id']()()('var_dump')(11); 'id'()('id')('var_dump')(12); ('i' . 'd')()('var_dump')(13); +'\id'('var_dump')(14); ?> --EXPECT-- @@ -51,3 +52,4 @@ int(10) int(11) int(12) int(13) +int(14) diff --git a/Zend/tests/varSyntax/staticMember.phpt b/Zend/tests/varSyntax/staticMember.phpt index 22a1fa2b13..e32417771a 100644 --- a/Zend/tests/varSyntax/staticMember.phpt +++ b/Zend/tests/varSyntax/staticMember.phpt @@ -19,6 +19,7 @@ var_dump($A_str::$b); var_dump($A_obj::$b); var_dump(('A' . '')::$b); var_dump('A'::$b); +var_dump('\A'::$b); var_dump('A'[0]::$b); var_dump(A::$$b_str); var_dump(A::$$c_str[1]); @@ -33,5 +34,6 @@ int(0) int(0) int(0) int(0) +int(0) int(1) int(0) diff --git a/Zend/tests/varvars_by_ref.phpt b/Zend/tests/varvars_by_ref.phpt new file mode 100644 index 0000000000..3ee4776aba --- /dev/null +++ b/Zend/tests/varvars_by_ref.phpt @@ -0,0 +1,17 @@ +--TEST-- +Accessing variable variables using referenced names +--FILE-- +<?php + +$name = 'var'; +$ref =& $name; + +$$name = 42; +var_dump(isset($$name)); +unset($$name); +var_dump(isset($$name)); + +?> +--EXPECT-- +bool(true) +bool(false) diff --git a/Zend/zend.c b/Zend/zend.c index 9e414f9027..f429b2d2a4 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -216,89 +216,20 @@ ZEND_API int zend_make_printable_zval(zval *expr, zval *expr_copy TSRMLS_DC) /* { if (Z_TYPE_P(expr) == IS_STRING) { return 0; + } else { + ZVAL_STR(expr_copy, _zval_get_string_func(expr TSRMLS_CC)); + return 1; } - -again: - switch (Z_TYPE_P(expr)) { - case IS_NULL: - case IS_FALSE: - ZVAL_EMPTY_STRING(expr_copy); - break; - case IS_TRUE: - if (CG(one_char_string)['1']) { - ZVAL_INTERNED_STR(expr_copy, CG(one_char_string)['1']); - } else { - ZVAL_NEW_STR(expr_copy, zend_string_init("1", 1, 0)); - } - break; - case IS_RESOURCE: { - char buf[sizeof("Resource id #") + MAX_LENGTH_OF_LONG]; - int len; - - len = snprintf(buf, sizeof(buf), "Resource id #" ZEND_LONG_FMT, Z_RES_HANDLE_P(expr)); - ZVAL_NEW_STR(expr_copy, zend_string_init(buf, len, 0)); - } - break; - case IS_ARRAY: - zend_error(E_NOTICE, "Array to string conversion"); - // TODO: use interned string ??? - ZVAL_NEW_STR(expr_copy, zend_string_init("Array", sizeof("Array") - 1, 0)); - break; - case IS_OBJECT: - if (Z_OBJ_HANDLER_P(expr, cast_object)) { - Z_ADDREF_P(expr); - if (Z_OBJ_HANDLER_P(expr, cast_object)(expr, expr_copy, IS_STRING TSRMLS_CC) == SUCCESS) { - zval_ptr_dtor(expr); - break; - } - zval_ptr_dtor(expr); - } - if (!Z_OBJ_HANDLER_P(expr, cast_object) && Z_OBJ_HANDLER_P(expr, get)) { - zval rv; - zval *z = Z_OBJ_HANDLER_P(expr, get)(expr, &rv TSRMLS_CC); - - Z_ADDREF_P(z); - if (Z_TYPE_P(z) != IS_OBJECT) { - if (zend_make_printable_zval(z, expr_copy TSRMLS_CC)) { - zval_ptr_dtor(z); - } else { - ZVAL_ZVAL(expr_copy, z, 0, 1); - } - return 1; - } - zval_ptr_dtor(z); - } - zend_error(EG(exception) ? E_ERROR : E_RECOVERABLE_ERROR, "Object of class %s could not be converted to string", Z_OBJCE_P(expr)->name->val); - ZVAL_EMPTY_STRING(expr_copy); - break; - case IS_DOUBLE: - ZVAL_DUP(expr_copy, expr); - zend_locale_sprintf_double(expr_copy ZEND_FILE_LINE_CC); - break; - case IS_REFERENCE: - expr = Z_REFVAL_P(expr); - if (Z_TYPE_P(expr) == IS_STRING) { - ZVAL_STR_COPY(expr_copy, Z_STR_P(expr)); - return 1; - } - goto again; - break; - default: - ZVAL_DUP(expr_copy, expr); - convert_to_string(expr_copy); - break; - } - return 1; } /* }}} */ -ZEND_API int zend_print_zval(zval *expr, int indent TSRMLS_DC) /* {{{ */ +ZEND_API size_t zend_print_zval(zval *expr, int indent TSRMLS_DC) /* {{{ */ { return zend_print_zval_ex(zend_write, expr, indent TSRMLS_CC); } /* }}} */ -ZEND_API int zend_print_zval_ex(zend_write_func_t write_func, zval *expr, int indent TSRMLS_DC) /* {{{ */ +ZEND_API size_t zend_print_zval_ex(zend_write_func_t write_func, zval *expr, int indent TSRMLS_DC) /* {{{ */ { zend_string *str = zval_get_string(expr); size_t len = str->len; @@ -332,19 +263,10 @@ ZEND_API void zend_print_flat_zval_r(zval *expr TSRMLS_DC) /* {{{ */ case IS_OBJECT: { HashTable *properties = NULL; - zend_string *class_name = NULL; + zend_string *class_name = Z_OBJ_HANDLER_P(expr, get_class_name)(Z_OBJ_P(expr) TSRMLS_CC); + zend_printf("%s Object (", class_name->val); + zend_string_release(class_name); - if (Z_OBJ_HANDLER_P(expr, get_class_name)) { - class_name = Z_OBJ_HANDLER_P(expr, get_class_name)(Z_OBJ_P(expr), 0 TSRMLS_CC); - } - if (class_name) { - zend_printf("%s Object (", class_name->val); - } else { - zend_printf("%s Object (", "Unknown Class"); - } - if (class_name) { - zend_string_release(class_name); - } if (Z_OBJ_HANDLER_P(expr, get_properties)) { properties = Z_OBJPROP_P(expr); } @@ -393,21 +315,13 @@ ZEND_API void zend_print_zval_r_ex(zend_write_func_t write_func, zval *expr, int case IS_OBJECT: { HashTable *properties; - zend_string *class_name = NULL; int is_temp; - if (Z_OBJ_HANDLER_P(expr, get_class_name)) { - class_name = Z_OBJ_HANDLER_P(expr, get_class_name)(Z_OBJ_P(expr), 0 TSRMLS_CC); - } - if (class_name) { - ZEND_PUTS_EX(class_name->val); - } else { - ZEND_PUTS_EX("Unknown Class"); - } + zend_string *class_name = Z_OBJ_HANDLER_P(expr, get_class_name)(Z_OBJ_P(expr) TSRMLS_CC); + ZEND_PUTS_EX(class_name->val); + zend_string_release(class_name); + ZEND_PUTS_EX(" Object\n"); - if (class_name) { - zend_string_release(class_name); - } if ((properties = Z_OBJDEBUG_P(expr, is_temp)) == NULL) { break; } @@ -441,11 +355,9 @@ static FILE *zend_fopen_wrapper(const char *filename, char **opened_path TSRMLS_ /* }}} */ #ifdef ZTS -static zend_bool asp_tags_default = 0; -static zend_bool short_tags_default = 1; +static zend_bool short_tags_default = 1; static uint32_t compiler_options_default = ZEND_COMPILE_DEFAULT; #else -# define asp_tags_default 0 # define short_tags_default 1 # define compiler_options_default ZEND_COMPILE_DEFAULT #endif @@ -453,7 +365,6 @@ static uint32_t compiler_options_default = ZEND_COMPILE_DEFAULT; static void zend_set_default_compile_time_values(TSRMLS_D) /* {{{ */ { /* default compile-time values */ - CG(asp_tags) = asp_tags_default; CG(short_tags) = short_tags_default; CG(compiler_options) = compiler_options_default; } @@ -516,10 +427,7 @@ static void compiler_globals_ctor(zend_compiler_globals *compiler_globals TSRMLS compiler_globals->script_encoding_list = NULL; #ifdef ZTS - compiler_globals->empty_string = zend_string_alloc(sizeof("")-1, 1); - compiler_globals->empty_string->val[0] = '\000'; - zend_string_hash_val(compiler_globals->empty_string); - compiler_globals->empty_string->gc.u.v.flags |= IS_STR_INTERNED; + zend_interned_empty_string_init(&compiler_globals->empty_string TSRMLS_CC); memset(compiler_globals->one_char_string, 0, sizeof(compiler_globals->one_char_string)); #endif @@ -549,7 +457,7 @@ static void compiler_globals_dtor(zend_compiler_globals *compiler_globals TSRMLS compiler_globals->last_static_member = 0; #ifdef ZTS - zend_string_release(compiler_globals->empty_string); + zend_interned_empty_string_free(&compiler_globals->empty_string TSRMLS_CC); #endif } /* }}} */ @@ -790,7 +698,6 @@ void zend_post_startup(TSRMLS_D) /* {{{ */ *GLOBAL_CLASS_TABLE = *compiler_globals->class_table; *GLOBAL_CONSTANTS_TABLE = *executor_globals->zend_constants; - asp_tags_default = CG(asp_tags); short_tags_default = CG(short_tags); compiler_options_default = CG(compiler_options); @@ -886,7 +793,7 @@ void zend_shutdown(TSRMLS_D) /* {{{ */ void zend_set_utility_values(zend_utility_values *utility_values) /* {{{ */ { zend_uv = *utility_values; - zend_uv.import_use_extension_length = strlen(zend_uv.import_use_extension); + zend_uv.import_use_extension_length = (uint)strlen(zend_uv.import_use_extension); } /* }}} */ @@ -915,16 +822,16 @@ ZEND_API void _zend_bailout(char *filename, uint lineno) /* {{{ */ /* }}} */ END_EXTERN_C() -void zend_append_version_info(const zend_extension *extension) /* {{{ */ +ZEND_API void zend_append_version_info(const zend_extension *extension) /* {{{ */ { char *new_info; uint new_info_length; - new_info_length = sizeof(" with v, , by \n") + new_info_length = (uint)(sizeof(" with v, , by \n") + strlen(extension->name) + strlen(extension->version) + strlen(extension->copyright) - + strlen(extension->author); + + strlen(extension->author)); new_info = (char *) malloc(new_info_length + 1); @@ -1190,7 +1097,7 @@ static void zend_error_va_list(int type, const char *format, va_list args) # endif #endif va_copy(usr_copy, args); - len = zend_vspprintf(&str, 0, format, usr_copy); + len = (int)zend_vspprintf(&str, 0, format, usr_copy); ZVAL_NEW_STR(¶ms[1], zend_string_init(str, len, 0)); efree(str); #ifdef va_copy diff --git a/Zend/zend.h b/Zend/zend.h index 517d419665..b5de33fb43 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -52,14 +52,13 @@ # define HANDLE_UNBLOCK_INTERRUPTIONS() ZEND_SIGNAL_UNBLOCK_INTERRUPTIONS() #endif -#define INTERNAL_FUNCTION_PARAMETERS uint32_t param_count, zval *return_value TSRMLS_DC -#define INTERNAL_FUNCTION_PARAM_PASSTHRU param_count, return_value TSRMLS_CC +#define INTERNAL_FUNCTION_PARAMETERS zend_execute_data *execute_data, zval *return_value TSRMLS_DC +#define INTERNAL_FUNCTION_PARAM_PASSTHRU execute_data, return_value TSRMLS_CC #define USED_RET() \ - (!EG(current_execute_data) || \ - !EG(current_execute_data)->prev_execute_data || \ - !ZEND_USER_CODE(EG(current_execute_data)->prev_execute_data->func->common.type) || \ - !(EG(current_execute_data)->prev_execute_data->opline->result_type & EXT_TYPE_UNUSED)) + (!EX(prev_execute_data) || \ + !ZEND_USER_CODE(EX(prev_execute_data)->func->common.type) || \ + !(EX(prev_execute_data)->opline->result_type & EXT_TYPE_UNUSED)) #ifdef HAVE_NORETURN # if defined(ZEND_WIN32) @@ -198,7 +197,7 @@ typedef struct _zend_utility_values { zend_bool html_errors; } zend_utility_values; -typedef int (*zend_write_func_t)(const char *str, uint str_length); +typedef int (*zend_write_func_t)(const char *str, size_t str_length); #define zend_bailout() _zend_bailout(__FILE__, __LINE__) @@ -229,8 +228,8 @@ ZEND_API void _zend_bailout(char *filename, uint lineno); ZEND_API char *get_zend_version(void); ZEND_API int zend_make_printable_zval(zval *expr, zval *expr_copy TSRMLS_DC); -ZEND_API int zend_print_zval(zval *expr, int indent TSRMLS_DC); -ZEND_API int zend_print_zval_ex(zend_write_func_t write_func, zval *expr, int indent TSRMLS_DC); +ZEND_API size_t zend_print_zval(zval *expr, int indent TSRMLS_DC); +ZEND_API size_t zend_print_zval_ex(zend_write_func_t write_func, zval *expr, int indent TSRMLS_DC); ZEND_API void zend_print_zval_r(zval *expr, int indent TSRMLS_DC); ZEND_API void zend_print_flat_zval_r(zval *expr TSRMLS_DC); ZEND_API void zend_print_zval_r_ex(zend_write_func_t write_func, zval *expr, int indent TSRMLS_DC); diff --git a/Zend/zend_API.c b/Zend/zend_API.c index dce707d96f..5d71383860 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -196,32 +196,6 @@ ZEND_API char *zend_zval_type_name(const zval *arg) /* {{{ */ } /* }}} */ -ZEND_API zend_class_entry *zend_get_class_entry(const zend_object *zobject TSRMLS_DC) /* {{{ */ -{ - if (zobject->handlers->get_class_entry) { - return zobject->handlers->get_class_entry(zobject TSRMLS_CC); - } else { - zend_error(E_ERROR, "Class entry requested for an object without PHP class"); - return NULL; - } -} -/* }}} */ - -/* returns 1 if you need to copy result, 0 if it's already a copy */ -ZEND_API zend_string *zend_get_object_classname(const zend_object *object TSRMLS_DC) /* {{{ */ -{ - zend_string *ret; - - if (object->handlers->get_class_name != NULL) { - ret = object->handlers->get_class_name(object, 0 TSRMLS_CC); - if (ret) { - return ret; - } - } - return zend_get_class_entry(object TSRMLS_CC)->name; -} -/* }}} */ - static int parse_arg_object_to_string(zval *arg, char **p, size_t *pl, int type TSRMLS_DC) /* {{{ */ { if (Z_OBJ_HANDLER_P(arg, cast_object)) { @@ -1278,9 +1252,9 @@ ZEND_API void object_properties_init_ex(zend_object *object, HashTable *properti ZEND_HASH_FOREACH_STR_KEY_VAL(properties, key, prop) { property_info = zend_get_property_info(object->ce, key, 1 TSRMLS_CC); - if (property_info && - (property_info->flags & ZEND_ACC_STATIC) == 0 && - property_info->offset >= 0) { + if (property_info != ZEND_WRONG_PROPERTY_INFO && + property_info && + (property_info->flags & ZEND_ACC_STATIC) == 0) { ZVAL_COPY_VALUE(&object->properties_table[property_info->offset], prop); ZVAL_INDIRECT(prop, &object->properties_table[property_info->offset]); } @@ -1297,9 +1271,9 @@ ZEND_API void object_properties_load(zend_object *object, HashTable *properties ZEND_HASH_FOREACH_STR_KEY_VAL(properties, key, prop) { property_info = zend_get_property_info(object->ce, key, 1 TSRMLS_CC); - if (property_info && - (property_info->flags & ZEND_ACC_STATIC) == 0 && - property_info->offset >= 0) { + if (property_info != ZEND_WRONG_PROPERTY_INFO && + property_info && + (property_info->flags & ZEND_ACC_STATIC) == 0) { zval_ptr_dtor(&object->properties_table[property_info->offset]); ZVAL_COPY_VALUE(&object->properties_table[property_info->offset], prop); zval_add_ref(&object->properties_table[property_info->offset]); @@ -1366,7 +1340,7 @@ ZEND_API int add_assoc_function(zval *arg, const char *key, void (*function_ptr) } /* }}} */ -ZEND_API int add_assoc_long_ex(zval *arg, const char *key, uint key_len, zend_long n) /* {{{ */ +ZEND_API int add_assoc_long_ex(zval *arg, const char *key, size_t key_len, zend_long n) /* {{{ */ { zval *ret, tmp; @@ -1376,7 +1350,7 @@ ZEND_API int add_assoc_long_ex(zval *arg, const char *key, uint key_len, zend_lo } /* }}} */ -ZEND_API int add_assoc_null_ex(zval *arg, const char *key, uint key_len) /* {{{ */ +ZEND_API int add_assoc_null_ex(zval *arg, const char *key, size_t key_len) /* {{{ */ { zval *ret, tmp; @@ -1386,7 +1360,7 @@ ZEND_API int add_assoc_null_ex(zval *arg, const char *key, uint key_len) /* {{{ } /* }}} */ -ZEND_API int add_assoc_bool_ex(zval *arg, const char *key, uint key_len, int b) /* {{{ */ +ZEND_API int add_assoc_bool_ex(zval *arg, const char *key, size_t key_len, int b) /* {{{ */ { zval *ret, tmp; @@ -1396,7 +1370,7 @@ ZEND_API int add_assoc_bool_ex(zval *arg, const char *key, uint key_len, int b) } /* }}} */ -ZEND_API int add_assoc_resource_ex(zval *arg, const char *key, uint key_len, zend_resource *r) /* {{{ */ +ZEND_API int add_assoc_resource_ex(zval *arg, const char *key, size_t key_len, zend_resource *r) /* {{{ */ { zval *ret, tmp; @@ -1406,7 +1380,7 @@ ZEND_API int add_assoc_resource_ex(zval *arg, const char *key, uint key_len, zen } /* }}} */ -ZEND_API int add_assoc_double_ex(zval *arg, const char *key, uint key_len, double d) /* {{{ */ +ZEND_API int add_assoc_double_ex(zval *arg, const char *key, size_t key_len, double d) /* {{{ */ { zval *ret, tmp; @@ -1416,7 +1390,7 @@ ZEND_API int add_assoc_double_ex(zval *arg, const char *key, uint key_len, doubl } /* }}} */ -ZEND_API int add_assoc_str_ex(zval *arg, const char *key, uint key_len, zend_string *str) /* {{{ */ +ZEND_API int add_assoc_str_ex(zval *arg, const char *key, size_t key_len, zend_string *str) /* {{{ */ { zval *ret, tmp; @@ -1426,7 +1400,7 @@ ZEND_API int add_assoc_str_ex(zval *arg, const char *key, uint key_len, zend_str } /* }}} */ -ZEND_API int add_assoc_string_ex(zval *arg, const char *key, uint key_len, char *str) /* {{{ */ +ZEND_API int add_assoc_string_ex(zval *arg, const char *key, size_t key_len, char *str) /* {{{ */ { zval *ret, tmp; @@ -1436,7 +1410,7 @@ ZEND_API int add_assoc_string_ex(zval *arg, const char *key, uint key_len, char } /* }}} */ -ZEND_API int add_assoc_stringl_ex(zval *arg, const char *key, uint key_len, char *str, size_t length) /* {{{ */ +ZEND_API int add_assoc_stringl_ex(zval *arg, const char *key, size_t key_len, char *str, size_t length) /* {{{ */ { zval *ret, tmp; @@ -1446,7 +1420,7 @@ ZEND_API int add_assoc_stringl_ex(zval *arg, const char *key, uint key_len, char } /* }}} */ -ZEND_API int add_assoc_zval_ex(zval *arg, const char *key, uint key_len, zval *value) /* {{{ */ +ZEND_API int add_assoc_zval_ex(zval *arg, const char *key, size_t key_len, zval *value) /* {{{ */ { zval *ret; @@ -1719,7 +1693,7 @@ ZEND_API int array_set_zval_key(HashTable *ht, zval *key, zval *value TSRMLS_DC) } /* }}} */ -ZEND_API int add_property_long_ex(zval *arg, const char *key, uint key_len, zend_long n TSRMLS_DC) /* {{{ */ +ZEND_API int add_property_long_ex(zval *arg, const char *key, size_t key_len, zend_long n TSRMLS_DC) /* {{{ */ { zval tmp; zval z_key; @@ -1733,7 +1707,7 @@ ZEND_API int add_property_long_ex(zval *arg, const char *key, uint key_len, zend } /* }}} */ -ZEND_API int add_property_bool_ex(zval *arg, const char *key, uint key_len, zend_long b TSRMLS_DC) /* {{{ */ +ZEND_API int add_property_bool_ex(zval *arg, const char *key, size_t key_len, zend_long b TSRMLS_DC) /* {{{ */ { zval tmp; zval z_key; @@ -1747,7 +1721,7 @@ ZEND_API int add_property_bool_ex(zval *arg, const char *key, uint key_len, zend } /* }}} */ -ZEND_API int add_property_null_ex(zval *arg, const char *key, uint key_len TSRMLS_DC) /* {{{ */ +ZEND_API int add_property_null_ex(zval *arg, const char *key, size_t key_len TSRMLS_DC) /* {{{ */ { zval tmp; zval z_key; @@ -1761,7 +1735,7 @@ ZEND_API int add_property_null_ex(zval *arg, const char *key, uint key_len TSRML } /* }}} */ -ZEND_API int add_property_resource_ex(zval *arg, const char *key, uint key_len, zend_resource *r TSRMLS_DC) /* {{{ */ +ZEND_API int add_property_resource_ex(zval *arg, const char *key, size_t key_len, zend_resource *r TSRMLS_DC) /* {{{ */ { zval tmp; zval z_key; @@ -1775,7 +1749,7 @@ ZEND_API int add_property_resource_ex(zval *arg, const char *key, uint key_len, } /* }}} */ -ZEND_API int add_property_double_ex(zval *arg, const char *key, uint key_len, double d TSRMLS_DC) /* {{{ */ +ZEND_API int add_property_double_ex(zval *arg, const char *key, size_t key_len, double d TSRMLS_DC) /* {{{ */ { zval tmp; zval z_key; @@ -1789,7 +1763,7 @@ ZEND_API int add_property_double_ex(zval *arg, const char *key, uint key_len, do } /* }}} */ -ZEND_API int add_property_str_ex(zval *arg, const char *key, uint key_len, zend_string *str TSRMLS_DC) /* {{{ */ +ZEND_API int add_property_str_ex(zval *arg, const char *key, size_t key_len, zend_string *str TSRMLS_DC) /* {{{ */ { zval tmp; zval z_key; @@ -1803,7 +1777,7 @@ ZEND_API int add_property_str_ex(zval *arg, const char *key, uint key_len, zend_ } /* }}} */ -ZEND_API int add_property_string_ex(zval *arg, const char *key, uint key_len, const char *str TSRMLS_DC) /* {{{ */ +ZEND_API int add_property_string_ex(zval *arg, const char *key, size_t key_len, const char *str TSRMLS_DC) /* {{{ */ { zval tmp; zval z_key; @@ -1817,7 +1791,7 @@ ZEND_API int add_property_string_ex(zval *arg, const char *key, uint key_len, co } /* }}} */ -ZEND_API int add_property_stringl_ex(zval *arg, const char *key, uint key_len, const char *str, size_t length TSRMLS_DC) /* {{{ */ +ZEND_API int add_property_stringl_ex(zval *arg, const char *key, size_t key_len, const char *str, size_t length TSRMLS_DC) /* {{{ */ { zval tmp; zval z_key; @@ -1831,7 +1805,7 @@ ZEND_API int add_property_stringl_ex(zval *arg, const char *key, uint key_len, c } /* }}} */ -ZEND_API int add_property_zval_ex(zval *arg, const char *key, uint key_len, zval *value TSRMLS_DC) /* {{{ */ +ZEND_API int add_property_zval_ex(zval *arg, const char *key, size_t key_len, zval *value TSRMLS_DC) /* {{{ */ { zval z_key; @@ -1844,7 +1818,7 @@ ZEND_API int add_property_zval_ex(zval *arg, const char *key, uint key_len, zval ZEND_API int zend_startup_module_ex(zend_module_entry *module TSRMLS_DC) /* {{{ */ { - int name_len; + size_t name_len; zend_string *lcname; if (module->module_started) { @@ -2031,7 +2005,7 @@ ZEND_API void zend_destroy_modules(void) /* {{{ */ ZEND_API zend_module_entry* zend_register_module_ex(zend_module_entry *module TSRMLS_DC) /* {{{ */ { - int name_len; + size_t name_len; zend_string *lcname; zend_module_entry *module_ptr; @@ -2100,7 +2074,7 @@ ZEND_API zend_module_entry* zend_register_internal_module(zend_module_entry *mod ZEND_API void zend_check_magic_method_implementation(const zend_class_entry *ce, const zend_function *fptr, int error_type TSRMLS_DC) /* {{{ */ { char lcname[16]; - int name_len; + size_t name_len; /* we don't care if the function name is longer, in fact lowercasing only * the beginning of the name speeds up the check process */ @@ -2172,9 +2146,9 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio int error_type; zend_function *ctor = NULL, *dtor = NULL, *clone = NULL, *__get = NULL, *__set = NULL, *__unset = NULL, *__isset = NULL, *__call = NULL, *__callstatic = NULL, *__tostring = NULL, *__debugInfo = NULL; zend_string *lowercase_name; - int fname_len; + size_t fname_len; const char *lc_class_name = NULL; - int class_name_len = 0; + size_t class_name_len = 0; if (type==MODULE_PERSISTENT) { error_type = E_CORE_WARNING; @@ -2447,7 +2421,7 @@ ZEND_API void zend_unregister_functions(const zend_function_entry *functions, in int i=0; HashTable *target_function_table = function_table; zend_string *lowercase_name; - int fname_len; + size_t fname_len; if (!target_function_table) { target_function_table = CG(function_table); @@ -2653,7 +2627,7 @@ ZEND_API void zend_post_deactivate_modules(TSRMLS_D) /* {{{ */ /* }}} */ /* return the next free module number */ -int zend_next_free_module(void) /* {{{ */ +ZEND_API int zend_next_free_module(void) /* {{{ */ { return zend_hash_num_elements(&module_registry) + 1; } @@ -2729,7 +2703,7 @@ ZEND_API zend_class_entry *zend_register_internal_interface(zend_class_entry *or } /* }}} */ -ZEND_API int zend_register_class_alias_ex(const char *name, int name_len, zend_class_entry *ce TSRMLS_DC) /* {{{ */ +ZEND_API int zend_register_class_alias_ex(const char *name, size_t name_len, zend_class_entry *ce TSRMLS_DC) /* {{{ */ { zend_string *lcname; @@ -2784,21 +2758,15 @@ ZEND_API ZEND_FUNCTION(display_disabled_function) } /* }}} */ -static zend_function_entry disabled_function[] = { - ZEND_FE(display_disabled_function, NULL) - ZEND_FE_END -}; - -ZEND_API int zend_disable_function(char *function_name, uint function_name_length TSRMLS_DC) /* {{{ */ +ZEND_API int zend_disable_function(char *function_name, size_t function_name_length TSRMLS_DC) /* {{{ */ { - int ret; - - ret = zend_hash_str_del(CG(function_table), function_name, function_name_length); - if (ret == FAILURE) { - return FAILURE; + zend_internal_function *func; + if ((func = zend_hash_str_find_ptr(CG(function_table), function_name, function_name_length))) { + func->arg_info = NULL; + func->handler = ZEND_FN(display_disabled_function); + return SUCCESS; } - disabled_function[0].fname = function_name; - return zend_register_functions(NULL, disabled_function, CG(function_table), MODULE_PERSISTENT TSRMLS_CC); + return FAILURE; } /* }}} */ @@ -2822,7 +2790,7 @@ static const zend_function_entry disabled_class_new[] = { ZEND_FE_END }; -ZEND_API int zend_disable_class(char *class_name, uint class_name_length TSRMLS_DC) /* {{{ */ +ZEND_API int zend_disable_class(char *class_name, size_t class_name_length TSRMLS_DC) /* {{{ */ { zend_class_entry *disabled_class; zend_string *key; @@ -2844,7 +2812,7 @@ static int zend_is_callable_check_class(zend_string *name, zend_fcall_info_cache { int ret = 0; zend_class_entry *ce; - int name_len = name->len; + size_t name_len = name->len; zend_string *lcname; ALLOCA_FLAG(use_heap); @@ -2858,8 +2826,8 @@ static int zend_is_callable_check_class(zend_string *name, zend_fcall_info_cache } else { fcc->called_scope = EG(current_execute_data) ? EG(current_execute_data)->called_scope : NULL; fcc->calling_scope = EG(scope); - if (!fcc->object && Z_OBJ(EG(This))) { - fcc->object = Z_OBJ(EG(This)); + if (!fcc->object && EG(current_execute_data) && Z_OBJ(EG(current_execute_data)->This)) { + fcc->object = Z_OBJ(EG(current_execute_data)->This); } ret = 1; } @@ -2871,8 +2839,8 @@ static int zend_is_callable_check_class(zend_string *name, zend_fcall_info_cache } else { fcc->called_scope = EG(current_execute_data) ? EG(current_execute_data)->called_scope : NULL; fcc->calling_scope = EG(scope)->parent; - if (!fcc->object && Z_OBJ(EG(This))) { - fcc->object = Z_OBJ(EG(This)); + if (!fcc->object && EG(current_execute_data) && Z_OBJ(EG(current_execute_data)->This)) { + fcc->object = Z_OBJ(EG(current_execute_data)->This); } *strict_class = 1; ret = 1; @@ -2883,8 +2851,8 @@ static int zend_is_callable_check_class(zend_string *name, zend_fcall_info_cache } else { fcc->called_scope = EG(current_execute_data)->called_scope; fcc->calling_scope = EG(current_execute_data)->called_scope; - if (!fcc->object && Z_OBJ(EG(This))) { - fcc->object = Z_OBJ(EG(This)); + if (!fcc->object && Z_OBJ(EG(current_execute_data)->This)) { + fcc->object = Z_OBJ(EG(current_execute_data)->This); } *strict_class = 1; ret = 1; @@ -2898,13 +2866,13 @@ static int zend_is_callable_check_class(zend_string *name, zend_fcall_info_cache } scope = ex ? ex->func->common.scope : NULL; fcc->calling_scope = ce; - if (scope && !fcc->object && Z_OBJ(EG(This)) && - instanceof_function(Z_OBJCE(EG(This)), scope TSRMLS_CC) && + if (scope && !fcc->object && EG(current_execute_data) && Z_OBJ(EG(current_execute_data)->This) && + instanceof_function(Z_OBJCE(EG(current_execute_data)->This), scope TSRMLS_CC) && instanceof_function(scope, fcc->calling_scope TSRMLS_CC)) { - fcc->object = Z_OBJ(EG(This)); - fcc->called_scope = Z_OBJCE(EG(This)); + fcc->object = Z_OBJ(EG(current_execute_data)->This); + fcc->called_scope = Z_OBJCE(EG(current_execute_data)->This); } else { - fcc->called_scope = fcc->object ? zend_get_class_entry(fcc->object TSRMLS_CC) : fcc->calling_scope; + fcc->called_scope = fcc->object ? fcc->object->ce : fcc->calling_scope; } *strict_class = 1; ret = 1; @@ -2923,7 +2891,7 @@ static int zend_is_callable_check_func(int check_flags, zval *callable, zend_fca zend_string *mname, *cname; zend_string *lmname; const char *colon; - int clen, mlen; + size_t clen, mlen; zend_class_entry *last_scope; HashTable *ftable; int call_via_handler = 0; @@ -3047,7 +3015,7 @@ static int zend_is_callable_check_func(int check_flags, zval *callable, zend_fca ((fcc->object && fcc->calling_scope->__call) || (!fcc->object && fcc->calling_scope->__callstatic)))) { if (fcc->function_handler->op_array.fn_flags & ZEND_ACC_PRIVATE) { - if (!zend_check_private(fcc->function_handler, fcc->object ? zend_get_class_entry(fcc->object TSRMLS_CC) : EG(scope), lmname TSRMLS_CC)) { + if (!zend_check_private(fcc->function_handler, fcc->object ? fcc->object->ce : EG(scope), lmname TSRMLS_CC)) { retval = 0; fcc->function_handler = NULL; goto get_function_via_handler; @@ -3103,10 +3071,9 @@ get_function_via_handler: if (fcc->function_handler) { retval = 1; call_via_handler = (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0; - if (call_via_handler && !fcc->object && Z_OBJ(EG(This)) && - Z_OBJ_HT(EG(This))->get_class_entry && - instanceof_function(Z_OBJCE(EG(This)), fcc->calling_scope TSRMLS_CC)) { - fcc->object = Z_OBJ(EG(This)); + if (call_via_handler && !fcc->object && EG(current_execute_data) && Z_OBJ(EG(current_execute_data)->This) && + instanceof_function(Z_OBJCE(EG(current_execute_data)->This), fcc->calling_scope TSRMLS_CC)) { + fcc->object = Z_OBJ(EG(current_execute_data)->This); } } } @@ -3135,15 +3102,15 @@ get_function_via_handler: if ((check_flags & IS_CALLABLE_CHECK_IS_STATIC) != 0) { retval = 0; } - if (Z_OBJ(EG(This)) && instanceof_function(Z_OBJCE(EG(This)), fcc->calling_scope TSRMLS_CC)) { - fcc->object = Z_OBJ(EG(This)); + if (EG(current_execute_data) && Z_OBJ(EG(current_execute_data)->This) && instanceof_function(Z_OBJCE(EG(current_execute_data)->This), fcc->calling_scope TSRMLS_CC)) { + fcc->object = Z_OBJ(EG(current_execute_data)->This); if (error) { - zend_spprintf(error, 0, "non-static method %s::%s() %s be called statically, assuming $this from compatible context %s", fcc->calling_scope->name->val, fcc->function_handler->common.function_name->val, verb, Z_OBJCE(EG(This))->name->val); + zend_spprintf(error, 0, "non-static method %s::%s() %s be called statically, assuming $this from compatible context %s", fcc->calling_scope->name->val, fcc->function_handler->common.function_name->val, verb, Z_OBJCE(EG(current_execute_data)->This)->name->val); if (severity == E_ERROR) { retval = 0; } } else if (retval) { - zend_error(severity, "Non-static method %s::%s() %s be called statically, assuming $this from compatible context %s", fcc->calling_scope->name->val, fcc->function_handler->common.function_name->val, verb, Z_OBJCE(EG(This))->name->val); + zend_error(severity, "Non-static method %s::%s() %s be called statically, assuming $this from compatible context %s", fcc->calling_scope->name->val, fcc->function_handler->common.function_name->val, verb, Z_OBJCE(EG(current_execute_data)->This)->name->val); } } else { if (error) { @@ -3158,7 +3125,7 @@ get_function_via_handler: } if (retval && (check_flags & IS_CALLABLE_CHECK_NO_ACCESS) == 0) { if (fcc->function_handler->op_array.fn_flags & ZEND_ACC_PRIVATE) { - if (!zend_check_private(fcc->function_handler, fcc->object ? zend_get_class_entry(fcc->object TSRMLS_CC) : EG(scope), lmname TSRMLS_CC)) { + if (!zend_check_private(fcc->function_handler, fcc->object ? fcc->object->ce : EG(scope), lmname TSRMLS_CC)) { if (error) { if (*error) { efree(*error); @@ -3191,7 +3158,7 @@ get_function_via_handler: zend_string_release(mname); if (fcc->object) { - fcc->called_scope = zend_get_class_entry(fcc->object TSRMLS_CC); + fcc->called_scope = fcc->object->ce; } if (retval) { fcc->initialized = 1; @@ -3232,7 +3199,7 @@ ZEND_API zend_bool zend_is_callable_ex(zval *callable, zend_object *object, uint case IS_STRING: if (object) { fcc->object = object; - fcc->calling_scope = zend_get_class_entry(object TSRMLS_CC); + fcc->calling_scope = object->ce; if (callable_name) { char *ptr; @@ -3610,7 +3577,7 @@ ZEND_API int zend_fcall_info_call(zend_fcall_info *fci, zend_fcall_info_cache *f ZEND_API const char *zend_get_module_version(const char *module_name) /* {{{ */ { zend_string *lname; - int name_len = strlen(module_name); + size_t name_len = strlen(module_name); zend_module_entry *module; lname = zend_string_alloc(name_len, 0); @@ -3698,7 +3665,7 @@ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, zend_string *name, z } /* }}} */ -ZEND_API int zend_declare_property(zend_class_entry *ce, const char *name, int name_length, zval *property, int access_type TSRMLS_DC) /* {{{ */ +ZEND_API int zend_declare_property(zend_class_entry *ce, const char *name, size_t name_length, zval *property, int access_type TSRMLS_DC) /* {{{ */ { zend_string *key = zend_string_init(name, name_length, ce->type & ZEND_INTERNAL_CLASS); int ret = zend_declare_property_ex(ce, key, property, access_type, NULL TSRMLS_CC); @@ -3707,7 +3674,7 @@ ZEND_API int zend_declare_property(zend_class_entry *ce, const char *name, int n } /* }}} */ -ZEND_API int zend_declare_property_null(zend_class_entry *ce, const char *name, int name_length, int access_type TSRMLS_DC) /* {{{ */ +ZEND_API int zend_declare_property_null(zend_class_entry *ce, const char *name, size_t name_length, int access_type TSRMLS_DC) /* {{{ */ { zval property; @@ -3716,7 +3683,7 @@ ZEND_API int zend_declare_property_null(zend_class_entry *ce, const char *name, } /* }}} */ -ZEND_API int zend_declare_property_bool(zend_class_entry *ce, const char *name, int name_length, zend_long value, int access_type TSRMLS_DC) /* {{{ */ +ZEND_API int zend_declare_property_bool(zend_class_entry *ce, const char *name, size_t name_length, zend_long value, int access_type TSRMLS_DC) /* {{{ */ { zval property; @@ -3725,7 +3692,7 @@ ZEND_API int zend_declare_property_bool(zend_class_entry *ce, const char *name, } /* }}} */ -ZEND_API int zend_declare_property_long(zend_class_entry *ce, const char *name, int name_length, zend_long value, int access_type TSRMLS_DC) /* {{{ */ +ZEND_API int zend_declare_property_long(zend_class_entry *ce, const char *name, size_t name_length, zend_long value, int access_type TSRMLS_DC) /* {{{ */ { zval property; @@ -3734,7 +3701,7 @@ ZEND_API int zend_declare_property_long(zend_class_entry *ce, const char *name, } /* }}} */ -ZEND_API int zend_declare_property_double(zend_class_entry *ce, const char *name, int name_length, double value, int access_type TSRMLS_DC) /* {{{ */ +ZEND_API int zend_declare_property_double(zend_class_entry *ce, const char *name, size_t name_length, double value, int access_type TSRMLS_DC) /* {{{ */ { zval property; @@ -3743,7 +3710,7 @@ ZEND_API int zend_declare_property_double(zend_class_entry *ce, const char *name } /* }}} */ -ZEND_API int zend_declare_property_string(zend_class_entry *ce, const char *name, int name_length, const char *value, int access_type TSRMLS_DC) /* {{{ */ +ZEND_API int zend_declare_property_string(zend_class_entry *ce, const char *name, size_t name_length, const char *value, int access_type TSRMLS_DC) /* {{{ */ { zval property; @@ -3752,7 +3719,7 @@ ZEND_API int zend_declare_property_string(zend_class_entry *ce, const char *name } /* }}} */ -ZEND_API int zend_declare_property_stringl(zend_class_entry *ce, const char *name, int name_length, const char *value, size_t value_len, int access_type TSRMLS_DC) /* {{{ */ +ZEND_API int zend_declare_property_stringl(zend_class_entry *ce, const char *name, size_t name_length, const char *value, size_t value_len, int access_type TSRMLS_DC) /* {{{ */ { zval property; @@ -3822,7 +3789,7 @@ ZEND_API int zend_declare_class_constant_string(zend_class_entry *ce, const char } /* }}} */ -ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, const char *name, int name_length, zval *value TSRMLS_DC) /* {{{ */ +ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zval *value TSRMLS_DC) /* {{{ */ { zval property; zend_class_entry *old_scope = EG(scope); @@ -3830,8 +3797,7 @@ ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, const EG(scope) = scope; if (!Z_OBJ_HT_P(object)->write_property) { - zend_string *class_name = zend_get_object_classname(Z_OBJ_P(object) TSRMLS_CC); - zend_error(E_CORE_ERROR, "Property %s of class %s cannot be updated", name, class_name->val); + zend_error(E_CORE_ERROR, "Property %s of class %s cannot be updated", name, Z_OBJCE_P(object)->name->val); } ZVAL_STRINGL(&property, name, name_length); Z_OBJ_HT_P(object)->write_property(object, &property, value, NULL TSRMLS_CC); @@ -3841,7 +3807,7 @@ ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, const } /* }}} */ -ZEND_API void zend_update_property_null(zend_class_entry *scope, zval *object, const char *name, int name_length TSRMLS_DC) /* {{{ */ +ZEND_API void zend_update_property_null(zend_class_entry *scope, zval *object, const char *name, size_t name_length TSRMLS_DC) /* {{{ */ { zval tmp; @@ -3850,7 +3816,7 @@ ZEND_API void zend_update_property_null(zend_class_entry *scope, zval *object, c } /* }}} */ -ZEND_API void zend_update_property_bool(zend_class_entry *scope, zval *object, const char *name, int name_length, zend_long value TSRMLS_DC) /* {{{ */ +ZEND_API void zend_update_property_bool(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zend_long value TSRMLS_DC) /* {{{ */ { zval tmp; @@ -3859,7 +3825,7 @@ ZEND_API void zend_update_property_bool(zend_class_entry *scope, zval *object, c } /* }}} */ -ZEND_API void zend_update_property_long(zend_class_entry *scope, zval *object, const char *name, int name_length, zend_long value TSRMLS_DC) /* {{{ */ +ZEND_API void zend_update_property_long(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zend_long value TSRMLS_DC) /* {{{ */ { zval tmp; @@ -3868,7 +3834,7 @@ ZEND_API void zend_update_property_long(zend_class_entry *scope, zval *object, c } /* }}} */ -ZEND_API void zend_update_property_double(zend_class_entry *scope, zval *object, const char *name, int name_length, double value TSRMLS_DC) /* {{{ */ +ZEND_API void zend_update_property_double(zend_class_entry *scope, zval *object, const char *name, size_t name_length, double value TSRMLS_DC) /* {{{ */ { zval tmp; @@ -3877,7 +3843,7 @@ ZEND_API void zend_update_property_double(zend_class_entry *scope, zval *object, } /* }}} */ -ZEND_API void zend_update_property_str(zend_class_entry *scope, zval *object, const char *name, int name_length, zend_string *value TSRMLS_DC) /* {{{ */ +ZEND_API void zend_update_property_str(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zend_string *value TSRMLS_DC) /* {{{ */ { zval tmp; @@ -3886,7 +3852,7 @@ ZEND_API void zend_update_property_str(zend_class_entry *scope, zval *object, co } /* }}} */ -ZEND_API void zend_update_property_string(zend_class_entry *scope, zval *object, const char *name, int name_length, const char *value TSRMLS_DC) /* {{{ */ +ZEND_API void zend_update_property_string(zend_class_entry *scope, zval *object, const char *name, size_t name_length, const char *value TSRMLS_DC) /* {{{ */ { zval tmp; @@ -3896,7 +3862,7 @@ ZEND_API void zend_update_property_string(zend_class_entry *scope, zval *object, } /* }}} */ -ZEND_API void zend_update_property_stringl(zend_class_entry *scope, zval *object, const char *name, int name_length, const char *value, size_t value_len TSRMLS_DC) /* {{{ */ +ZEND_API void zend_update_property_stringl(zend_class_entry *scope, zval *object, const char *name, size_t name_length, const char *value, size_t value_len TSRMLS_DC) /* {{{ */ { zval tmp; @@ -3906,7 +3872,7 @@ ZEND_API void zend_update_property_stringl(zend_class_entry *scope, zval *object } /* }}} */ -ZEND_API int zend_update_static_property(zend_class_entry *scope, const char *name, int name_length, zval *value TSRMLS_DC) /* {{{ */ +ZEND_API int zend_update_static_property(zend_class_entry *scope, const char *name, size_t name_length, zval *value TSRMLS_DC) /* {{{ */ { zval *property; zend_class_entry *old_scope = EG(scope); @@ -3930,9 +3896,11 @@ ZEND_API int zend_update_static_property(zend_class_entry *scope, const char *na zval garbage; ZVAL_COPY_VALUE(&garbage, property); - Z_ADDREF_P(value); - if (Z_ISREF_P(value)) { - SEPARATE_ZVAL(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + if (Z_ISREF_P(value)) { + SEPARATE_ZVAL(value); + } } ZVAL_COPY_VALUE(property, value); zval_ptr_dtor(&garbage); @@ -3943,7 +3911,7 @@ ZEND_API int zend_update_static_property(zend_class_entry *scope, const char *na } /* }}} */ -ZEND_API int zend_update_static_property_null(zend_class_entry *scope, const char *name, int name_length TSRMLS_DC) /* {{{ */ +ZEND_API int zend_update_static_property_null(zend_class_entry *scope, const char *name, size_t name_length TSRMLS_DC) /* {{{ */ { zval tmp; @@ -3952,7 +3920,7 @@ ZEND_API int zend_update_static_property_null(zend_class_entry *scope, const cha } /* }}} */ -ZEND_API int zend_update_static_property_bool(zend_class_entry *scope, const char *name, int name_length, zend_long value TSRMLS_DC) /* {{{ */ +ZEND_API int zend_update_static_property_bool(zend_class_entry *scope, const char *name, size_t name_length, zend_long value TSRMLS_DC) /* {{{ */ { zval tmp; @@ -3961,7 +3929,7 @@ ZEND_API int zend_update_static_property_bool(zend_class_entry *scope, const cha } /* }}} */ -ZEND_API int zend_update_static_property_long(zend_class_entry *scope, const char *name, int name_length, zend_long value TSRMLS_DC) /* {{{ */ +ZEND_API int zend_update_static_property_long(zend_class_entry *scope, const char *name, size_t name_length, zend_long value TSRMLS_DC) /* {{{ */ { zval tmp; @@ -3970,7 +3938,7 @@ ZEND_API int zend_update_static_property_long(zend_class_entry *scope, const cha } /* }}} */ -ZEND_API int zend_update_static_property_double(zend_class_entry *scope, const char *name, int name_length, double value TSRMLS_DC) /* {{{ */ +ZEND_API int zend_update_static_property_double(zend_class_entry *scope, const char *name, size_t name_length, double value TSRMLS_DC) /* {{{ */ { zval tmp; @@ -3979,7 +3947,7 @@ ZEND_API int zend_update_static_property_double(zend_class_entry *scope, const c } /* }}} */ -ZEND_API int zend_update_static_property_string(zend_class_entry *scope, const char *name, int name_length, const char *value TSRMLS_DC) /* {{{ */ +ZEND_API int zend_update_static_property_string(zend_class_entry *scope, const char *name, size_t name_length, const char *value TSRMLS_DC) /* {{{ */ { zval tmp; @@ -3989,7 +3957,7 @@ ZEND_API int zend_update_static_property_string(zend_class_entry *scope, const c } /* }}} */ -ZEND_API int zend_update_static_property_stringl(zend_class_entry *scope, const char *name, int name_length, const char *value, size_t value_len TSRMLS_DC) /* {{{ */ +ZEND_API int zend_update_static_property_stringl(zend_class_entry *scope, const char *name, size_t name_length, const char *value, size_t value_len TSRMLS_DC) /* {{{ */ { zval tmp; @@ -3999,7 +3967,7 @@ ZEND_API int zend_update_static_property_stringl(zend_class_entry *scope, const } /* }}} */ -ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, const char *name, int name_length, zend_bool silent TSRMLS_DC) /* {{{ */ +ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zend_bool silent TSRMLS_DC) /* {{{ */ { zval property, *value; zend_class_entry *old_scope = EG(scope); @@ -4008,8 +3976,7 @@ ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, const c EG(scope) = scope; if (!Z_OBJ_HT_P(object)->read_property) { - zend_string *class_name = zend_get_object_classname(Z_OBJ_P(object) TSRMLS_CC); - zend_error(E_CORE_ERROR, "Property %s of class %s cannot be read", name, class_name->val); + zend_error(E_CORE_ERROR, "Property %s of class %s cannot be read", name, Z_OBJCE_P(object)->name->val); } ZVAL_STRINGL(&property, name, name_length); @@ -4021,7 +3988,7 @@ ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, const c } /* }}} */ -ZEND_API zval *zend_read_static_property(zend_class_entry *scope, const char *name, int name_length, zend_bool silent TSRMLS_DC) /* {{{ */ +ZEND_API zval *zend_read_static_property(zend_class_entry *scope, const char *name, size_t name_length, zend_bool silent TSRMLS_DC) /* {{{ */ { zval *property; zend_class_entry *old_scope = EG(scope); @@ -4149,6 +4116,39 @@ ZEND_API zend_string *zend_resolve_method_name(zend_class_entry *ce, zend_functi } /* }}} */ +ZEND_API void zend_ctor_make_null(zend_execute_data *execute_data) /* {{{ */ +{ + if (EX(return_value)) { +/* + if (Z_TYPE_P(EX(return_value)) == IS_OBJECT) { + zend_object *object = Z_OBJ_P(EX(return_value)); + zend_execute_data *ex = EX(prev_execute_data); + + while (ex && Z_OBJ(ex->This) == object) { + if (ex->func) { + if (ZEND_USER_CODE(ex->func->type)) { + if (ex->func->op_array.this_var != -1) { + zval *this_var = EX_VAR_2(ex, ex->func->op_array.this_var); + if (this_var != EX(return_value)) { + zval_ptr_dtor(this_var); + ZVAL_NULL(this_var); + } + } + } + } + Z_OBJ(ex->This) = NULL; + ZVAL_NULL(&ex->This); + ex = ex->prev_execute_data; + } + } +*/ + zval_ptr_dtor(EX(return_value)); + Z_OBJ_P(EX(return_value)) = NULL; + ZVAL_NULL(EX(return_value)); + } +} +/* }}} */ + /* * Local variables: * tab-width: 4 diff --git a/Zend/zend_API.h b/Zend/zend_API.h index 97a069b463..371d1d8ae8 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -229,7 +229,7 @@ typedef struct _zend_fcall_info_cache { #define ZEND_FCI_INITIALIZED(fci) ((fci).size != 0) -int zend_next_free_module(void); +ZEND_API int zend_next_free_module(void); BEGIN_EXTERN_C() ZEND_API int zend_get_parameters(int ht, int param_count, ...); @@ -276,15 +276,15 @@ ZEND_API zend_class_entry *zend_register_internal_class_ex(zend_class_entry *cla ZEND_API zend_class_entry *zend_register_internal_interface(zend_class_entry *orig_class_entry TSRMLS_DC); ZEND_API void zend_class_implements(zend_class_entry *class_entry TSRMLS_DC, int num_interfaces, ...); -ZEND_API int zend_register_class_alias_ex(const char *name, int name_len, zend_class_entry *ce TSRMLS_DC); +ZEND_API int zend_register_class_alias_ex(const char *name, size_t name_len, zend_class_entry *ce TSRMLS_DC); #define zend_register_class_alias(name, ce) \ zend_register_class_alias_ex(name, sizeof(name)-1, ce TSRMLS_CC) #define zend_register_ns_class_alias(ns, name, ce) \ zend_register_class_alias_ex(ZEND_NS_NAME(ns, name), sizeof(ZEND_NS_NAME(ns, name))-1, ce TSRMLS_CC) -ZEND_API int zend_disable_function(char *function_name, uint function_name_length TSRMLS_DC); -ZEND_API int zend_disable_class(char *class_name, uint class_name_length TSRMLS_DC); +ZEND_API int zend_disable_function(char *function_name, size_t function_name_length TSRMLS_DC); +ZEND_API int zend_disable_class(char *class_name, size_t class_name_length TSRMLS_DC); ZEND_API void zend_wrong_param_count(TSRMLS_D); @@ -301,13 +301,13 @@ ZEND_API zend_bool zend_make_callable(zval *callable, zend_string **callable_nam ZEND_API const char *zend_get_module_version(const char *module_name); ZEND_API int zend_get_module_started(const char *module_name); ZEND_API int zend_declare_property_ex(zend_class_entry *ce, zend_string *name, zval *property, int access_type, zend_string *doc_comment TSRMLS_DC); -ZEND_API int zend_declare_property(zend_class_entry *ce, const char *name, int name_length, zval *property, int access_type TSRMLS_DC); -ZEND_API int zend_declare_property_null(zend_class_entry *ce, const char *name, int name_length, int access_type TSRMLS_DC); -ZEND_API int zend_declare_property_bool(zend_class_entry *ce, const char *name, int name_length, zend_long value, int access_type TSRMLS_DC); -ZEND_API int zend_declare_property_long(zend_class_entry *ce, const char *name, int name_length, zend_long value, int access_type TSRMLS_DC); -ZEND_API int zend_declare_property_double(zend_class_entry *ce, const char *name, int name_length, double value, int access_type TSRMLS_DC); -ZEND_API int zend_declare_property_string(zend_class_entry *ce, const char *name, int name_length, const char *value, int access_type TSRMLS_DC); -ZEND_API int zend_declare_property_stringl(zend_class_entry *ce, const char *name, int name_length, const char *value, size_t value_len, int access_type TSRMLS_DC); +ZEND_API int zend_declare_property(zend_class_entry *ce, const char *name, size_t name_length, zval *property, int access_type TSRMLS_DC); +ZEND_API int zend_declare_property_null(zend_class_entry *ce, const char *name, size_t name_length, int access_type TSRMLS_DC); +ZEND_API int zend_declare_property_bool(zend_class_entry *ce, const char *name, size_t name_length, zend_long value, int access_type TSRMLS_DC); +ZEND_API int zend_declare_property_long(zend_class_entry *ce, const char *name, size_t name_length, zend_long value, int access_type TSRMLS_DC); +ZEND_API int zend_declare_property_double(zend_class_entry *ce, const char *name, size_t name_length, double value, int access_type TSRMLS_DC); +ZEND_API int zend_declare_property_string(zend_class_entry *ce, const char *name, size_t name_length, const char *value, int access_type TSRMLS_DC); +ZEND_API int zend_declare_property_stringl(zend_class_entry *ce, const char *name, size_t name_length, const char *value, size_t value_len, int access_type TSRMLS_DC); ZEND_API int zend_declare_class_constant(zend_class_entry *ce, const char *name, size_t name_length, zval *value TSRMLS_DC); ZEND_API int zend_declare_class_constant_null(zend_class_entry *ce, const char *name, size_t name_length TSRMLS_DC); @@ -318,37 +318,36 @@ ZEND_API int zend_declare_class_constant_stringl(zend_class_entry *ce, const cha ZEND_API int zend_declare_class_constant_string(zend_class_entry *ce, const char *name, size_t name_length, const char *value TSRMLS_DC); ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC); -ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, const char *name, int name_length, zval *value TSRMLS_DC); -ZEND_API void zend_update_property_null(zend_class_entry *scope, zval *object, const char *name, int name_length TSRMLS_DC); -ZEND_API void zend_update_property_bool(zend_class_entry *scope, zval *object, const char *name, int name_length, zend_long value TSRMLS_DC); -ZEND_API void zend_update_property_long(zend_class_entry *scope, zval *object, const char *name, int name_length, zend_long value TSRMLS_DC); -ZEND_API void zend_update_property_double(zend_class_entry *scope, zval *object, const char *name, int name_length, double value TSRMLS_DC); -ZEND_API void zend_update_property_str(zend_class_entry *scope, zval *object, const char *name, int name_length, zend_string *value TSRMLS_DC); -ZEND_API void zend_update_property_string(zend_class_entry *scope, zval *object, const char *name, int name_length, const char *value TSRMLS_DC); -ZEND_API void zend_update_property_stringl(zend_class_entry *scope, zval *object, const char *name, int name_length, const char *value, size_t value_length TSRMLS_DC); - -ZEND_API int zend_update_static_property(zend_class_entry *scope, const char *name, int name_length, zval *value TSRMLS_DC); -ZEND_API int zend_update_static_property_null(zend_class_entry *scope, const char *name, int name_length TSRMLS_DC); -ZEND_API int zend_update_static_property_bool(zend_class_entry *scope, const char *name, int name_length, zend_long value TSRMLS_DC); -ZEND_API int zend_update_static_property_long(zend_class_entry *scope, const char *name, int name_length, zend_long value TSRMLS_DC); -ZEND_API int zend_update_static_property_double(zend_class_entry *scope, const char *name, int name_length, double value TSRMLS_DC); -ZEND_API int zend_update_static_property_string(zend_class_entry *scope, const char *name, int name_length, const char *value TSRMLS_DC); -ZEND_API int zend_update_static_property_stringl(zend_class_entry *scope, const char *name, int name_length, const char *value, size_t value_length TSRMLS_DC); - -ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, const char *name, int name_length, zend_bool silent TSRMLS_DC); - -ZEND_API zval *zend_read_static_property(zend_class_entry *scope, const char *name, int name_length, zend_bool silent TSRMLS_DC); - -ZEND_API zend_class_entry *zend_get_class_entry(const zend_object *object TSRMLS_DC); -ZEND_API zend_string *zend_get_object_classname(const zend_object *object TSRMLS_DC); +ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zval *value TSRMLS_DC); +ZEND_API void zend_update_property_null(zend_class_entry *scope, zval *object, const char *name, size_t name_length TSRMLS_DC); +ZEND_API void zend_update_property_bool(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zend_long value TSRMLS_DC); +ZEND_API void zend_update_property_long(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zend_long value TSRMLS_DC); +ZEND_API void zend_update_property_double(zend_class_entry *scope, zval *object, const char *name, size_t name_length, double value TSRMLS_DC); +ZEND_API void zend_update_property_str(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zend_string *value TSRMLS_DC); +ZEND_API void zend_update_property_string(zend_class_entry *scope, zval *object, const char *name, size_t name_length, const char *value TSRMLS_DC); +ZEND_API void zend_update_property_stringl(zend_class_entry *scope, zval *object, const char *name, size_t name_length, const char *value, size_t value_length TSRMLS_DC); + +ZEND_API int zend_update_static_property(zend_class_entry *scope, const char *name, size_t name_length, zval *value TSRMLS_DC); +ZEND_API int zend_update_static_property_null(zend_class_entry *scope, const char *name, size_t name_length TSRMLS_DC); +ZEND_API int zend_update_static_property_bool(zend_class_entry *scope, const char *name, size_t name_length, zend_long value TSRMLS_DC); +ZEND_API int zend_update_static_property_long(zend_class_entry *scope, const char *name, size_t name_length, zend_long value TSRMLS_DC); +ZEND_API int zend_update_static_property_double(zend_class_entry *scope, const char *name, size_t name_length, double value TSRMLS_DC); +ZEND_API int zend_update_static_property_string(zend_class_entry *scope, const char *name, size_t name_length, const char *value TSRMLS_DC); +ZEND_API int zend_update_static_property_stringl(zend_class_entry *scope, const char *name, size_t name_length, const char *value, size_t value_length TSRMLS_DC); + +ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zend_bool silent TSRMLS_DC); + +ZEND_API zval *zend_read_static_property(zend_class_entry *scope, const char *name, size_t name_length, zend_bool silent TSRMLS_DC); + ZEND_API char *zend_get_type_by_const(int type); -#define getThis() (Z_OBJ(EG(This)) ? &EG(This) : NULL) +#define getThis() (Z_OBJ(EX(This)) ? &EX(This) : NULL) +#define ZEND_IS_METHOD_CALL() (EX(func)->common.scope != NULL) #define WRONG_PARAM_COUNT ZEND_WRONG_PARAM_COUNT() #define WRONG_PARAM_COUNT_WITH_RETVAL(ret) ZEND_WRONG_PARAM_COUNT_WITH_RETVAL(ret) -#define ARG_COUNT(dummy) (param_count) -#define ZEND_NUM_ARGS() (param_count) +#define ARG_COUNT(dummy) EX(num_args) +#define ZEND_NUM_ARGS() EX(num_args) #define ZEND_WRONG_PARAM_COUNT() { zend_wrong_param_count(TSRMLS_C); return; } #define ZEND_WRONG_PARAM_COUNT_WITH_RETVAL(ret) { zend_wrong_param_count(TSRMLS_C); return ret; } @@ -374,15 +373,15 @@ ZEND_API void zend_merge_properties(zval *obj, HashTable *properties TSRMLS_DC); /* no longer supported */ ZEND_API int add_assoc_function(zval *arg, const char *key, void (*function_ptr)(INTERNAL_FUNCTION_PARAMETERS)); -ZEND_API int add_assoc_long_ex(zval *arg, const char *key, uint key_len, zend_long n); -ZEND_API int add_assoc_null_ex(zval *arg, const char *key, uint key_len); -ZEND_API int add_assoc_bool_ex(zval *arg, const char *key, uint key_len, int b); -ZEND_API int add_assoc_resource_ex(zval *arg, const char *key, uint key_len, zend_resource *r); -ZEND_API int add_assoc_double_ex(zval *arg, const char *key, uint key_len, double d); -ZEND_API int add_assoc_str_ex(zval *arg, const char *key, uint key_len, zend_string *str); -ZEND_API int add_assoc_string_ex(zval *arg, const char *key, uint key_len, char *str); -ZEND_API int add_assoc_stringl_ex(zval *arg, const char *key, uint key_len, char *str, size_t length); -ZEND_API int add_assoc_zval_ex(zval *arg, const char *key, uint key_len, zval *value); +ZEND_API int add_assoc_long_ex(zval *arg, const char *key, size_t key_len, zend_long n); +ZEND_API int add_assoc_null_ex(zval *arg, const char *key, size_t key_len); +ZEND_API int add_assoc_bool_ex(zval *arg, const char *key, size_t key_len, int b); +ZEND_API int add_assoc_resource_ex(zval *arg, const char *key, size_t key_len, zend_resource *r); +ZEND_API int add_assoc_double_ex(zval *arg, const char *key, size_t key_len, double d); +ZEND_API int add_assoc_str_ex(zval *arg, const char *key, size_t key_len, zend_string *str); +ZEND_API int add_assoc_string_ex(zval *arg, const char *key, size_t key_len, char *str); +ZEND_API int add_assoc_stringl_ex(zval *arg, const char *key, size_t key_len, char *str, size_t length); +ZEND_API int add_assoc_zval_ex(zval *arg, const char *key, size_t key_len, zval *value); #define add_assoc_long(__arg, __key, __n) add_assoc_long_ex(__arg, __key, strlen(__key), __n) #define add_assoc_null(__arg, __key) add_assoc_null_ex(__arg, __key, strlen(__key)) @@ -434,15 +433,15 @@ ZEND_API zval *add_get_index_stringl(zval *arg, zend_ulong idx, const char *str, ZEND_API int array_set_zval_key(HashTable *ht, zval *key, zval *value TSRMLS_DC); -ZEND_API int add_property_long_ex(zval *arg, const char *key, uint key_len, zend_long l TSRMLS_DC); -ZEND_API int add_property_null_ex(zval *arg, const char *key, uint key_len TSRMLS_DC); -ZEND_API int add_property_bool_ex(zval *arg, const char *key, uint key_len, zend_long b TSRMLS_DC); -ZEND_API int add_property_resource_ex(zval *arg, const char *key, uint key_len, zend_resource *r TSRMLS_DC); -ZEND_API int add_property_double_ex(zval *arg, const char *key, uint key_len, double d TSRMLS_DC); -ZEND_API int add_property_str_ex(zval *arg, const char *key, uint key_len, zend_string *str TSRMLS_DC); -ZEND_API int add_property_string_ex(zval *arg, const char *key, uint key_len, const char *str TSRMLS_DC); -ZEND_API int add_property_stringl_ex(zval *arg, const char *key, uint key_len, const char *str, size_t length TSRMLS_DC); -ZEND_API int add_property_zval_ex(zval *arg, const char *key, uint key_len, zval *value TSRMLS_DC); +ZEND_API int add_property_long_ex(zval *arg, const char *key, size_t key_len, zend_long l TSRMLS_DC); +ZEND_API int add_property_null_ex(zval *arg, const char *key, size_t key_len TSRMLS_DC); +ZEND_API int add_property_bool_ex(zval *arg, const char *key, size_t key_len, zend_long b TSRMLS_DC); +ZEND_API int add_property_resource_ex(zval *arg, const char *key, size_t key_len, zend_resource *r TSRMLS_DC); +ZEND_API int add_property_double_ex(zval *arg, const char *key, size_t key_len, double d TSRMLS_DC); +ZEND_API int add_property_str_ex(zval *arg, const char *key, size_t key_len, zend_string *str TSRMLS_DC); +ZEND_API int add_property_string_ex(zval *arg, const char *key, size_t key_len, const char *str TSRMLS_DC); +ZEND_API int add_property_stringl_ex(zval *arg, const char *key, size_t key_len, const char *str, size_t length TSRMLS_DC); +ZEND_API int add_property_zval_ex(zval *arg, const char *key, size_t key_len, zval *value TSRMLS_DC); #define add_property_long(__arg, __key, __n) add_property_long_ex(__arg, __key, strlen(__key), __n TSRMLS_CC) #define add_property_null(__arg, __key) add_property_null_ex(__arg, __key, strlen(__key) TSRMLS_CC) @@ -452,7 +451,7 @@ ZEND_API int add_property_zval_ex(zval *arg, const char *key, uint key_len, zval #define add_property_str(__arg, __key, __str) add_property_str_ex(__arg, __key, strlen(__key), __str TSRMLS_CC) #define add_property_string(__arg, __key, __str) add_property_string_ex(__arg, __key, strlen(__key), __str TSRMLS_CC) #define add_property_stringl(__arg, __key, __str, __length) add_property_stringl_ex(__arg, __key, strlen(__key), __str, __length TSRMLS_CC) -#define add_property_zval(__arg, __key, __value) add_property_zval_ex(__arg, __key, strlen(__key), __value TSRMLS_CC) +#define add_property_zval(__arg, __key, __value) add_property_zval_ex(__arg, __key, strlen(__key), __value TSRMLS_CC) ZEND_API int call_user_function(HashTable *function_table, zval *object, zval *function_name, zval *retval_ptr, uint32_t param_count, zval params[] TSRMLS_DC); @@ -531,6 +530,8 @@ ZEND_API int zend_set_local_var_str(const char *name, int len, zval *value, int ZEND_API zend_string *zend_find_alias_name(zend_class_entry *ce, zend_string *name); ZEND_API zend_string *zend_resolve_method_name(zend_class_entry *ce, zend_function *f); +ZEND_API void zend_ctor_make_null(zend_execute_data *execute_data); + #define add_method(arg, key, method) add_assoc_function((arg), (key), (method)) ZEND_API ZEND_FUNCTION(display_disabled_function); @@ -639,26 +640,8 @@ END_EXTERN_C() } while (0) /* May be used in internal constructors to make them return NULL */ -#if 1 // support for directly called constructors only ??? -#define ZEND_CTOR_MAKE_NULL() do { \ - if (EG(current_execute_data)->return_value) { \ - zval_ptr_dtor(EG(current_execute_data)->return_value); \ - ZVAL_NULL(EG(current_execute_data)->return_value); \ - } \ - } while (0) -#else // attempt to support calls to parent::__construct() ??? - // see: ext/date/tests/bug67118.phpt -#define ZEND_CTOR_MAKE_NULL() do { \ - if (EG(current_execute_data)->return_value) { \ - zval_ptr_dtor(EG(current_execute_data)->return_value); \ - ZVAL_NULL(EG(current_execute_data)->return_value); \ - } else if (EG(current_execute_data)->prev_execute_data && \ - EG(current_execute_data)->prev_execute_data->object == \ - EG(current_execute_data)->object) { \ - EG(current_execute_data)->prev_execute_data->object = NULL; \ - } \ - } while (0) -#endif +#define ZEND_CTOR_MAKE_NULL() \ + zend_ctor_make_null(execute_data) #define RETURN_ZVAL_FAST(z) { RETVAL_ZVAL_FAST(z); return; } @@ -729,7 +712,7 @@ ZEND_API int _z_param_class(zval *arg, zend_class_entry **pce, int num, int chec const int _flags = (flags); \ int _min_num_args = (min_num_args); \ int _max_num_args = (max_num_args); \ - int _num_args = EG(current_execute_data)->num_args; \ + int _num_args = EX(num_args); \ int _i; \ zval *_real_arg, *_arg = NULL; \ zend_expected_type _expected_type = IS_UNDEF; \ @@ -756,7 +739,7 @@ ZEND_API int _z_param_class(zval *arg, zend_class_entry **pce, int num, int chec break; \ } \ _i = 0; \ - _real_arg = ZEND_CALL_ARG(EG(current_execute_data), 0); + _real_arg = ZEND_CALL_ARG(execute_data, 0); #define ZEND_PARSE_PARAMETERS_START(min_num_args, max_num_args) \ ZEND_PARSE_PARAMETERS_START_EX(0, min_num_args, max_num_args) diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index ac403617a6..cd8cc50000 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -119,6 +119,9 @@ # define ZEND_MM_CUSTOM 1 /* support for custom memory allocator */ /* USE_ZEND_ALLOC=0 may switch to system malloc() */ #endif +#ifndef ZEND_MM_STORAGE +# define ZEND_MM_STORAGE 1 /* support for custom memory storage */ +#endif #ifndef ZEND_MM_ERROR # define ZEND_MM_ERROR 1 /* report system errors */ #endif @@ -217,6 +220,9 @@ struct _zend_mm_heap { #if ZEND_MM_CUSTOM int use_custom_heap; #endif +#if ZEND_MM_STORAGE + zend_mm_storage *storage; +#endif #if ZEND_MM_STAT size_t size; /* current memory usage */ size_t peak; /* peak memory usage */ @@ -476,7 +482,11 @@ static void zend_mm_munmap(void *addr, size_t size) static zend_always_inline int zend_mm_bitset_nts(zend_mm_bitset bitset) { #if defined(__GNUC__) +# if SIZEOF_ZEND_LONG == SIZEOF_LONG return __builtin_ctzl(~bitset); +# else + return __builtin_ctzll(~bitset); +# endif #elif defined(_WIN32) unsigned long index; @@ -513,7 +523,11 @@ static zend_always_inline int zend_mm_bitset_nts(zend_mm_bitset bitset) static zend_always_inline int zend_mm_bitset_ntz(zend_mm_bitset bitset) { #if defined(__GNUC__) +# if SIZEOF_ZEND_LONG == SIZEOF_LONG return __builtin_ctzl(bitset); +# else + return __builtin_ctzll(bitset); +# endif #elif defined(_WIN32) unsigned long index; @@ -709,7 +723,7 @@ static zend_always_inline int zend_mm_bitset_is_free_range(zend_mm_bitset *bitse /* Chunks */ /**********/ -static void *zend_mm_chunk_alloc(size_t size, size_t alignment) +static void *zend_mm_chunk_alloc_int(size_t size, size_t alignment) { void *ptr = zend_mm_mmap(size); @@ -753,6 +767,40 @@ static void *zend_mm_chunk_alloc(size_t size, size_t alignment) } } +static void *zend_mm_chunk_alloc(zend_mm_heap *heap, size_t size, size_t alignment) +{ +#if ZEND_MM_STORAGE + if (UNEXPECTED(heap->storage)) { + void *ptr = heap->storage->chunk_alloc(heap->storage, size, alignment); + ZEND_ASSERT(((zend_uintptr_t)((char*)ptr + (alignment-1)) & (alignment-1)) == (zend_uintptr_t)ptr); + return ptr; + } +#endif + return zend_mm_chunk_alloc_int(size, alignment); +} + +static void zend_mm_chunk_free(zend_mm_heap *heap, void *addr, size_t size) +{ +#if ZEND_MM_STORAGE + if (UNEXPECTED(heap->storage)) { + heap->storage->chunk_free(heap->storage, addr, size); + return; + } +#endif + zend_mm_munmap(addr, size); +} + +static void zend_mm_chunk_truncate(zend_mm_heap *heap, void *addr, size_t old_size, size_t new_size) +{ +#if ZEND_MM_STORAGE + if (UNEXPECTED(heap->storage)) { + heap->storage->chunk_truncate(heap->storage, addr, old_size, new_size); + return; + } +#endif + zend_mm_munmap((char*)addr + new_size, old_size - new_size); +} + static zend_always_inline void zend_mm_chunk_init(zend_mm_heap *heap, zend_mm_chunk *chunk) { chunk->heap = heap; @@ -922,23 +970,23 @@ not_found: if (heap->real_size + ZEND_MM_CHUNK_SIZE > heap->limit) { if (heap->overflow == 0) { #if ZEND_DEBUG - zend_mm_safe_error(heap, "Allowed memory size of " ZEND_ULONG_FMT " bytes exhausted at %s:%d (tried to allocate " ZEND_ULONG_FMT " bytes)", heap->limit, __zend_filename, __zend_lineno, size); + zend_mm_safe_error(heap, "Allowed memory size of %zu bytes exhausted at %s:%d (tried to allocate %zu bytes)", heap->limit, __zend_filename, __zend_lineno, size); #else - zend_mm_safe_error(heap, "Allowed memory size of " ZEND_ULONG_FMT " bytes exhausted (tried to allocate " ZEND_ULONG_FMT " bytes)", heap->limit, ZEND_MM_PAGE_SIZE * pages_count); + zend_mm_safe_error(heap, "Allowed memory size of %zu bytes exhausted (tried to allocate %zu bytes)", heap->limit, ZEND_MM_PAGE_SIZE * pages_count); #endif return NULL; } } #endif - chunk = (zend_mm_chunk*)zend_mm_chunk_alloc(ZEND_MM_CHUNK_SIZE, ZEND_MM_CHUNK_SIZE); + chunk = (zend_mm_chunk*)zend_mm_chunk_alloc(heap, ZEND_MM_CHUNK_SIZE, ZEND_MM_CHUNK_SIZE); if (UNEXPECTED(chunk == NULL)) { /* insufficient memory */ #if !ZEND_MM_LIMIT zend_mm_safe_error(heap, "Out of memory"); #elif ZEND_DEBUG - zend_mm_safe_error(heap, "Out of memory (allocated %ld) at %s:%d (tried to allocate %lu bytes)", heap->real_size, __zend_filename, __zend_lineno, size); + zend_mm_safe_error(heap, "Out of memory (allocated %zu) at %s:%d (tried to allocate %zu bytes)", heap->real_size, __zend_filename, __zend_lineno, size); #else - zend_mm_safe_error(heap, "Out of memory (allocated %ld) (tried to allocate %lu bytes)", heap->real_size, ZEND_MM_PAGE_SIZE * pages_count); + zend_mm_safe_error(heap, "Out of memory (allocated %zu) (tried to allocate %zu bytes)", heap->real_size, ZEND_MM_PAGE_SIZE * pages_count); #endif return NULL; } @@ -980,7 +1028,7 @@ found: static zend_always_inline void *zend_mm_alloc_large(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) { - int pages_count = ZEND_MM_SIZE_TO_NUM(size, ZEND_MM_PAGE_SIZE); + int pages_count = (int)ZEND_MM_SIZE_TO_NUM(size, ZEND_MM_PAGE_SIZE); #if ZEND_DEBUG void *ptr = zend_mm_alloc_pages(heap, pages_count, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); #else @@ -1021,11 +1069,11 @@ static void zend_mm_free_pages(zend_mm_heap *heap, zend_mm_chunk *chunk, int pag heap->real_size -= ZEND_MM_CHUNK_SIZE; #endif if (!heap->cached_chunks || chunk->num > heap->cached_chunks->num) { - zend_mm_munmap(chunk, ZEND_MM_CHUNK_SIZE); + zend_mm_chunk_free(heap, chunk, ZEND_MM_CHUNK_SIZE); } else { //TODO: select the best chunk to delete??? chunk->next = heap->cached_chunks->next; - zend_mm_munmap(heap->cached_chunks, ZEND_MM_CHUNK_SIZE); + zend_mm_chunk_free(heap, heap->cached_chunks, ZEND_MM_CHUNK_SIZE); heap->cached_chunks = chunk; } } @@ -1213,7 +1261,7 @@ static zend_always_inline zend_mm_debug_info *zend_mm_get_debug_info(zend_mm_hea ZEND_MM_CHECK(page_offset != 0, "zend_mm_heap corrupted"); chunk = (zend_mm_chunk*)ZEND_MM_ALIGNED_BASE(ptr, ZEND_MM_CHUNK_SIZE); - page_num = page_offset / ZEND_MM_PAGE_SIZE; + page_num = (int)(page_offset / ZEND_MM_PAGE_SIZE); info = chunk->map[page_num]; ZEND_MM_CHECK(chunk->heap == heap, "zend_mm_heap corrupted"); if (EXPECTED(info & ZEND_MM_IS_SRUN)) { @@ -1278,7 +1326,7 @@ static zend_always_inline void zend_mm_free_heap(zend_mm_heap *heap, void *ptr Z } } else { zend_mm_chunk *chunk = (zend_mm_chunk*)ZEND_MM_ALIGNED_BASE(ptr, ZEND_MM_CHUNK_SIZE); - int page_num = page_offset / ZEND_MM_PAGE_SIZE; + int page_num = (int)(page_offset / ZEND_MM_PAGE_SIZE); zend_mm_page_info info = chunk->map[page_num]; ZEND_MM_CHECK(chunk->heap == heap, "zend_mm_heap corrupted"); @@ -1309,7 +1357,7 @@ static size_t zend_mm_size(zend_mm_heap *heap, void *ptr ZEND_FILE_LINE_DC ZEND_ zend_mm_page_info info; chunk = (zend_mm_chunk*)ZEND_MM_ALIGNED_BASE(ptr, ZEND_MM_CHUNK_SIZE); - page_num = page_offset / ZEND_MM_PAGE_SIZE; + page_num = (int)(page_offset / ZEND_MM_PAGE_SIZE); info = chunk->map[page_num]; ZEND_MM_CHECK(chunk->heap == heap, "zend_mm_heap corrupted"); if (EXPECTED(info & ZEND_MM_IS_SRUN)) { @@ -1357,7 +1405,7 @@ static void *zend_mm_realloc_heap(zend_mm_heap *heap, void *ptr, size_t size ZEN #ifndef _WIN32 } else if (new_size < old_size) { /* unmup tail */ - zend_mm_munmap((char*)ptr + new_size, old_size - new_size); + zend_mm_chunk_truncate(heap, ptr, old_size, new_size); #if ZEND_MM_STAT || ZEND_MM_LIMIT heap->real_size -= old_size - new_size; #endif @@ -1375,9 +1423,9 @@ static void *zend_mm_realloc_heap(zend_mm_heap *heap, void *ptr, size_t size ZEN if (heap->real_size + (new_size - old_size) > heap->limit) { if (heap->overflow == 0) { #if ZEND_DEBUG - zend_mm_safe_error(heap, "Allowed memory size of " ZEND_ULONG_FMT " bytes exhausted at %s:%d (tried to allocate " ZEND_ULONG_FMT " bytes)", heap->limit, __zend_filename, __zend_lineno, size); + zend_mm_safe_error(heap, "Allowed memory size of %zu bytes exhausted at %s:%d (tried to allocate %zu bytes)", heap->limit, __zend_filename, __zend_lineno, size); #else - zend_mm_safe_error(heap, "Allowed memory size of " ZEND_ULONG_FMT " bytes exhausted (tried to allocate " ZEND_ULONG_FMT " bytes)", heap->limit, size); + zend_mm_safe_error(heap, "Allowed memory size of %zu bytes exhausted (tried to allocate %zu bytes)", heap->limit, size); #endif return NULL; } @@ -1403,7 +1451,7 @@ static void *zend_mm_realloc_heap(zend_mm_heap *heap, void *ptr, size_t size ZEN } } else { zend_mm_chunk *chunk = (zend_mm_chunk*)ZEND_MM_ALIGNED_BASE(ptr, ZEND_MM_CHUNK_SIZE); - int page_num = page_offset / ZEND_MM_PAGE_SIZE; + int page_num = (int)(page_offset / ZEND_MM_PAGE_SIZE); zend_mm_page_info info = chunk->map[page_num]; #if ZEND_DEBUG size_t real_size = size; @@ -1446,8 +1494,8 @@ static void *zend_mm_realloc_heap(zend_mm_heap *heap, void *ptr, size_t size ZEN return ptr; } else if (new_size < old_size) { /* free tail pages */ - int new_pages_count = new_size / ZEND_MM_PAGE_SIZE; - int rest_pages_count = (old_size - new_size) / ZEND_MM_PAGE_SIZE; + int new_pages_count = (int)(new_size / ZEND_MM_PAGE_SIZE); + int rest_pages_count = (int)((old_size - new_size) / ZEND_MM_PAGE_SIZE); #if ZEND_MM_STAT heap->size -= rest_pages_count * ZEND_MM_PAGE_SIZE; @@ -1465,8 +1513,8 @@ static void *zend_mm_realloc_heap(zend_mm_heap *heap, void *ptr, size_t size ZEN #endif return ptr; } else /* if (new_size > old_size) */ { - int new_pages_count = new_size / ZEND_MM_PAGE_SIZE; - int old_pages_count = old_size / ZEND_MM_PAGE_SIZE; + int new_pages_count = (int)(new_size / ZEND_MM_PAGE_SIZE); + int old_pages_count = (int)(old_size / ZEND_MM_PAGE_SIZE); /* try to allocate tail pages after this block */ if (page_num + new_pages_count <= ZEND_MM_PAGES && @@ -1601,23 +1649,23 @@ static void *zend_mm_alloc_huge(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_D if (heap->real_size + new_size > heap->limit) { if (heap->overflow == 0) { #if ZEND_DEBUG - zend_mm_safe_error(heap, "Allowed memory size of " ZEND_ULONG_FMT " bytes exhausted at %s:%d (tried to allocate %lu bytes)", heap->limit, __zend_filename, __zend_lineno, size); + zend_mm_safe_error(heap, "Allowed memory size of %zu bytes exhausted at %s:%d (tried to allocate %zu bytes)", heap->limit, __zend_filename, __zend_lineno, size); #else - zend_mm_safe_error(heap, "Allowed memory size of " ZEND_ULONG_FMT " bytes exhausted (tried to allocate %lu bytes)", heap->limit, size); + zend_mm_safe_error(heap, "Allowed memory size of %zu bytes exhausted (tried to allocate %zu bytes)", heap->limit, size); #endif return NULL; } } #endif - ptr = zend_mm_chunk_alloc(new_size, ZEND_MM_CHUNK_SIZE); + ptr = zend_mm_chunk_alloc(heap, new_size, ZEND_MM_CHUNK_SIZE); if (UNEXPECTED(ptr == NULL)) { /* insufficient memory */ #if !ZEND_MM_LIMIT zend_mm_safe_error(heap, "Out of memory"); #elif ZEND_DEBUG - zend_mm_safe_error(heap, "Out of memory (allocated %ld) at %s:%d (tried to allocate %lu bytes)", heap->real_size, __zend_filename, __zend_lineno, size); + zend_mm_safe_error(heap, "Out of memory (allocated %zu) at %s:%d (tried to allocate %zu bytes)", heap->real_size, __zend_filename, __zend_lineno, size); #else - zend_mm_safe_error(heap, "Out of memory (allocated %ld) (tried to allocate %lu bytes)", heap->real_size, size); + zend_mm_safe_error(heap, "Out of memory (allocated %zu) (tried to allocate %zu bytes)", heap->real_size, size); #endif return NULL; } @@ -1651,7 +1699,7 @@ static void zend_mm_free_huge(zend_mm_heap *heap, void *ptr ZEND_FILE_LINE_DC ZE ZEND_MM_CHECK(ZEND_MM_ALIGNED_OFFSET(ptr, ZEND_MM_CHUNK_SIZE) == 0, "zend_mm_heap corrupted"); size = zend_mm_del_huge_block(heap, ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); - zend_mm_munmap(ptr, size); + zend_mm_chunk_free(heap, ptr, size); #if ZEND_MM_STAT || ZEND_MM_LIMIT heap->real_size -= size; #endif @@ -1664,9 +1712,9 @@ static void zend_mm_free_huge(zend_mm_heap *heap, void *ptr ZEND_FILE_LINE_DC ZE /* Initialization */ /******************/ -zend_mm_heap *zend_mm_init(void) +static zend_mm_heap *zend_mm_init(void) { - zend_mm_chunk *chunk = (zend_mm_chunk*)zend_mm_chunk_alloc(ZEND_MM_CHUNK_SIZE, ZEND_MM_CHUNK_SIZE); + zend_mm_chunk *chunk = (zend_mm_chunk*)zend_mm_chunk_alloc_int(ZEND_MM_CHUNK_SIZE, ZEND_MM_CHUNK_SIZE); zend_mm_heap *heap; if (UNEXPECTED(chunk == NULL)) { @@ -1709,6 +1757,9 @@ zend_mm_heap *zend_mm_init(void) #if ZEND_MM_CUSTOM heap->use_custom_heap = 0; #endif +#if ZEND_MM_STORAGE + heap->storage = NULL; +#endif heap->huge_list = NULL; return heap; } @@ -1807,7 +1858,7 @@ static void zend_mm_check_leaks(zend_mm_heap *heap TSRMLS_DC) } list = list->next; - zend_mm_munmap(q->ptr, q->size); + zend_mm_chunk_free(heap, q->ptr, q->size); zend_mm_free_heap(heap, q, NULL, 0, NULL, 0); } @@ -1906,7 +1957,7 @@ void zend_mm_shutdown(zend_mm_heap *heap, int full, int silent TSRMLS_DC) while (list) { zend_mm_huge_list *q = list; list = list->next; - zend_mm_munmap(q->ptr, q->size); + zend_mm_chunk_free(heap, q->ptr, q->size); } /* move all chunks except of the first one into the cache */ @@ -1925,10 +1976,20 @@ void zend_mm_shutdown(zend_mm_heap *heap, int full, int silent TSRMLS_DC) while (heap->cached_chunks) { p = heap->cached_chunks; heap->cached_chunks = p->next; - zend_mm_munmap(p, ZEND_MM_CHUNK_SIZE); + zend_mm_chunk_free(heap, p, ZEND_MM_CHUNK_SIZE); } /* free the first chunk */ - zend_mm_munmap(heap->main_chunk, ZEND_MM_CHUNK_SIZE); +#if ZEND_MM_STORAGE + if (UNEXPECTED(heap->storage)) { + zend_mm_storage *storage = heap->storage; + zend_mm_chunk_free(heap, heap->main_chunk, ZEND_MM_CHUNK_SIZE); + storage->dtor(storage); + } else { + zend_mm_chunk_free(heap, heap->main_chunk, ZEND_MM_CHUNK_SIZE); + } +#else + zend_mm_chunk_free(heap, heap->main_chunk, ZEND_MM_CHUNK_SIZE); +#endif } else { zend_mm_heap old_heap; @@ -1938,7 +1999,7 @@ void zend_mm_shutdown(zend_mm_heap *heap, int full, int silent TSRMLS_DC) heap->cached_chunks) { p = heap->cached_chunks; heap->cached_chunks = p->next; - zend_mm_munmap(p, ZEND_MM_CHUNK_SIZE); + zend_mm_chunk_free(heap, p, ZEND_MM_CHUNK_SIZE); heap->cached_chunks_count--; } /* clear cached chunks */ @@ -1979,22 +2040,22 @@ void zend_mm_shutdown(zend_mm_heap *heap, int full, int silent TSRMLS_DC) /* PUBLIC API */ /**************/ -ZEND_API void *_zend_mm_alloc(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) +ZEND_API void* ZEND_FASTCALL _zend_mm_alloc(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) { return zend_mm_alloc_heap(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); } -ZEND_API void _zend_mm_free(zend_mm_heap *heap, void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) +ZEND_API void ZEND_FASTCALL _zend_mm_free(zend_mm_heap *heap, void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) { zend_mm_free_heap(heap, ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); } -void *_zend_mm_realloc(zend_mm_heap *heap, void *ptr, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) +void* ZEND_FASTCALL _zend_mm_realloc(zend_mm_heap *heap, void *ptr, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) { return zend_mm_realloc_heap(heap, ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); } -ZEND_API size_t _zend_mm_block_size(zend_mm_heap *heap, void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) +ZEND_API size_t ZEND_FASTCALL _zend_mm_block_size(zend_mm_heap *heap, void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) { return zend_mm_size(heap, ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); } @@ -2370,6 +2431,98 @@ ZEND_API void zend_mm_set_custom_handlers(zend_mm_heap *heap, #endif } +ZEND_API void zend_mm_get_custom_handlers(zend_mm_heap *heap, + void* (**_malloc)(size_t), + void (**_free)(void*), + void* (**_realloc)(void*, size_t)) +{ +#if ZEND_MM_CUSTOM + zend_mm_heap *_heap = (zend_mm_heap*)heap; + + if (heap->use_custom_heap) { + *_malloc = _heap->_malloc; + *_free = _heap->_free; + *_realloc = _heap->_realloc; + } else { + *_malloc = NULL; + *_free = NULL; + *_realloc = NULL; + } +#else + *_malloc = NULL; + *_free = NULL; + *_realloc = NULL; +#endif +} + +ZEND_API zend_mm_storage *zend_mm_get_storage(zend_mm_heap *heap) +{ +#if ZEND_MM_CUSTOM + return heap->storage; +#else + return NULL +#endif +} + +ZEND_API zend_mm_heap *zend_mm_startup(void) +{ + return zend_mm_init(); +} + +ZEND_API zend_mm_heap *zend_mm_startup_ex(zend_mm_storage *storage) +{ +#if ZEND_MM_STORAGE + zend_mm_chunk *chunk = (zend_mm_chunk*)storage->chunk_alloc(storage, ZEND_MM_CHUNK_SIZE, ZEND_MM_CHUNK_SIZE); + zend_mm_heap *heap; + + if (UNEXPECTED(chunk == NULL)) { +#if ZEND_MM_ERROR +#ifdef _WIN32 + stderr_last_error("Can't initialize heap"); +#else + fprintf(stderr, "\nCan't initialize heap: [%d] %s\n", errno, strerror(errno)); +#endif +#endif + return NULL; + } + heap = &chunk->heap_slot; + chunk->heap = heap; + chunk->next = chunk; + chunk->prev = chunk; + chunk->free_pages = ZEND_MM_PAGES - ZEND_MM_FIRST_PAGE; + chunk->free_tail = ZEND_MM_FIRST_PAGE; + chunk->num = 0; + chunk->free_map[0] = (Z_L(1) << ZEND_MM_FIRST_PAGE) - 1; + chunk->map[0] = ZEND_MM_LRUN(ZEND_MM_FIRST_PAGE); + heap->main_chunk = chunk; + heap->cached_chunks = NULL; + heap->chunks_count = 1; + heap->peak_chunks_count = 1; + heap->cached_chunks_count = 0; + heap->avg_chunks_count = 1.0; +#if ZEND_MM_STAT || ZEND_MM_LIMIT + heap->real_size = ZEND_MM_CHUNK_SIZE; +#endif +#if ZEND_MM_STAT + heap->real_peak = ZEND_MM_CHUNK_SIZE; + heap->size = 0; + heap->peak = 0; +#endif +#if ZEND_MM_LIMIT + heap->limit = (Z_L(-1) >> Z_L(1)); + heap->overflow = 0; +#endif +#if ZEND_MM_CUSTOM + heap->use_custom_heap = 0; +#endif + heap->storage = storage; + heap->huge_list = NULL; + return heap; +#else + return NULL; +#endif +} + /* * Local variables: * tab-width: 4 diff --git a/Zend/zend_alloc.h b/Zend/zend_alloc.h index d50d3d5cb8..c9918955ab 100644 --- a/Zend/zend_alloc.h +++ b/Zend/zend_alloc.h @@ -238,10 +238,10 @@ typedef struct _zend_mm_heap zend_mm_heap; ZEND_API zend_mm_heap *zend_mm_startup(void); ZEND_API void zend_mm_shutdown(zend_mm_heap *heap, int full_shutdown, int silent TSRMLS_DC); -ZEND_API void *_zend_mm_alloc(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC; -ZEND_API void _zend_mm_free(zend_mm_heap *heap, void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); -ZEND_API void *_zend_mm_realloc(zend_mm_heap *heap, void *p, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); -ZEND_API size_t _zend_mm_block_size(zend_mm_heap *heap, void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); +ZEND_API void* ZEND_FASTCALL _zend_mm_alloc(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC; +ZEND_API void ZEND_FASTCALL _zend_mm_free(zend_mm_heap *heap, void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); +ZEND_API void* ZEND_FASTCALL _zend_mm_realloc(zend_mm_heap *heap, void *p, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); +ZEND_API size_t ZEND_FASTCALL _zend_mm_block_size(zend_mm_heap *heap, void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); #define zend_mm_alloc(heap, size) _zend_mm_alloc((heap), (size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC) #define zend_mm_free(heap, p) _zend_mm_free((heap), (p) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC) @@ -259,6 +259,27 @@ ZEND_API void zend_mm_set_custom_handlers(zend_mm_heap *heap, void* (*_malloc)(size_t), void (*_free)(void*), void* (*_realloc)(void*, size_t)); +ZEND_API void zend_mm_get_custom_handlers(zend_mm_heap *heap, + void* (**_malloc)(size_t), + void (**_free)(void*), + void* (**_realloc)(void*, size_t)); + +typedef struct _zend_mm_storage zend_mm_storage; + +typedef void* (*zend_mm_chunk_alloc_t)(zend_mm_storage *storage, size_t size, size_t alignment); +typedef void (*zend_mm_chunk_free_t)(zend_mm_storage *storage, void *chunk, size_t size); +typedef void (*zend_mm_chunk_truncate_t)(zend_mm_storage *storage, void *chunk, size_t old_size, size_t new_size); +typedef void (*zend_mm_storage_dtor_t)(zend_mm_storage *storage); + +struct _zend_mm_storage { + zend_mm_chunk_alloc_t chunk_alloc; + zend_mm_chunk_free_t chunk_free; + zend_mm_chunk_truncate_t chunk_truncate; + zend_mm_storage_dtor_t dtor; +}; + +ZEND_API zend_mm_storage *zend_mm_get_storage(zend_mm_heap *heap); +ZEND_API zend_mm_heap *zend_mm_startup_ex(zend_mm_storage *storage); END_EXTERN_C() diff --git a/Zend/zend_ast.h b/Zend/zend_ast.h index 716b385210..6bd6850d83 100644 --- a/Zend/zend_ast.h +++ b/Zend/zend_ast.h @@ -115,6 +115,7 @@ enum _zend_ast_kind { ZEND_AST_NEW, ZEND_AST_INSTANCEOF, ZEND_AST_YIELD, + ZEND_AST_COALESCE, ZEND_AST_STATIC, ZEND_AST_WHILE, @@ -220,7 +221,9 @@ static zend_always_inline zval *zend_ast_get_zval(zend_ast *ast) { return &((zend_ast_zval *) ast)->val; } static zend_always_inline zend_string *zend_ast_get_str(zend_ast *ast) { - return Z_STR_P(zend_ast_get_zval(ast)); + zval *zv = zend_ast_get_zval(ast); + ZEND_ASSERT(Z_TYPE_P(zv) == IS_STRING); + return Z_STR_P(zv); } static zend_always_inline uint32_t zend_ast_get_num_children(zend_ast *ast) { diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index 91ab77e6c5..ddec6a7ddb 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -400,9 +400,9 @@ ZEND_FUNCTION(gc_disable) Get the number of arguments that were passed to the function */ ZEND_FUNCTION(func_num_args) { - zend_execute_data *ex = EG(current_execute_data)->prev_execute_data; + zend_execute_data *ex = EX(prev_execute_data); - if (ex->frame_kind == VM_FRAME_NESTED_FUNCTION || ex->frame_kind == VM_FRAME_TOP_FUNCTION) { + if (VM_FRAME_KIND(ex->frame_info) == VM_FRAME_NESTED_FUNCTION || VM_FRAME_KIND(ex->frame_info) == VM_FRAME_TOP_FUNCTION) { RETURN_LONG(ex->num_args); } else { zend_error(E_WARNING, "func_num_args(): Called from the global scope - no function context"); @@ -429,8 +429,8 @@ ZEND_FUNCTION(func_get_arg) RETURN_FALSE; } - ex = EG(current_execute_data)->prev_execute_data; - if (ex->frame_kind != VM_FRAME_NESTED_FUNCTION && ex->frame_kind != VM_FRAME_TOP_FUNCTION) { + ex = EX(prev_execute_data); + if (VM_FRAME_KIND(ex->frame_info) != VM_FRAME_NESTED_FUNCTION && VM_FRAME_KIND(ex->frame_info) != VM_FRAME_TOP_FUNCTION) { zend_error(E_WARNING, "func_get_arg(): Called from the global scope - no function context"); RETURN_FALSE; } @@ -462,9 +462,9 @@ ZEND_FUNCTION(func_get_args) zval *p; uint32_t arg_count, first_extra_arg; uint32_t i; - zend_execute_data *ex = EG(current_execute_data)->prev_execute_data; + zend_execute_data *ex = EX(prev_execute_data); - if (ex->frame_kind != VM_FRAME_NESTED_FUNCTION && ex->frame_kind != VM_FRAME_TOP_FUNCTION) { + if (VM_FRAME_KIND(ex->frame_info) != VM_FRAME_NESTED_FUNCTION && VM_FRAME_KIND(ex->frame_info) != VM_FRAME_TOP_FUNCTION) { zend_error(E_WARNING, "func_get_args(): Called from the global scope - no function context"); RETURN_FALSE; } @@ -811,7 +811,7 @@ ZEND_FUNCTION(get_class) } } - RETURN_STR(zend_get_object_classname(Z_OBJ_P(obj) TSRMLS_CC)); + RETURN_STR(zend_string_copy(Z_OBJCE_P(obj)->name)); } /* }}} */ @@ -823,8 +823,8 @@ ZEND_FUNCTION(get_called_class) return; } - if (EG(current_execute_data)->called_scope) { - RETURN_STR(zend_string_copy(EG(current_execute_data)->called_scope->name)); + if (EX(called_scope)) { + RETURN_STR(zend_string_copy(EX(called_scope)->name)); } else if (!EG(scope)) { zend_error(E_WARNING, "get_called_class() called from outside a class"); } @@ -838,7 +838,6 @@ ZEND_FUNCTION(get_parent_class) { zval *arg; zend_class_entry *ce = NULL; - zend_string *name; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z", &arg) == FAILURE) { return; @@ -854,12 +853,7 @@ ZEND_FUNCTION(get_parent_class) } if (Z_TYPE_P(arg) == IS_OBJECT) { - if (Z_OBJ_HT_P(arg)->get_class_name - && (name = Z_OBJ_HT_P(arg)->get_class_name(Z_OBJ_P(arg), 1 TSRMLS_CC)) != NULL) { - RETURN_STR(name); - } else { - ce = zend_get_class_entry(Z_OBJ_P(arg) TSRMLS_CC); - } + ce = Z_OBJ_P(arg)->ce; } else if (Z_TYPE_P(arg) == IS_STRING) { ce = zend_lookup_class(Z_STR_P(arg) TSRMLS_CC); } @@ -905,7 +899,7 @@ static void is_a_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool only_subclass) /* if (!instance_ce) { RETURN_FALSE; } - } else if (Z_TYPE_P(obj) == IS_OBJECT && HAS_CLASS_ENTRY(*obj)) { + } else if (Z_TYPE_P(obj) == IS_OBJECT) { instance_ce = Z_OBJCE_P(obj); } else { RETURN_FALSE; @@ -1065,7 +1059,7 @@ ZEND_FUNCTION(get_object_vars) } /* }}} */ -static int same_name(const char *key, const char *name, uint32_t name_len) /* {{{ */ +static int same_name(const char *key, const char *name, size_t name_len) /* {{{ */ { char *lcname = zend_str_tolower_dup(name, name_len); int ret = memcmp(lcname, key, name_len) == 0; @@ -1089,10 +1083,6 @@ ZEND_FUNCTION(get_class_methods) } if (Z_TYPE_P(klass) == IS_OBJECT) { - /* TBI!! new object handlers */ - if (!HAS_CLASS_ENTRY(*klass)) { - RETURN_FALSE; - } ce = Z_OBJCE_P(klass); } else if (Z_TYPE_P(klass) == IS_STRING) { ce = zend_lookup_class(Z_STR_P(klass) TSRMLS_CC); @@ -1112,7 +1102,7 @@ ZEND_FUNCTION(get_class_methods) zend_check_protected(mptr->common.scope, EG(scope))) || ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) && EG(scope) == mptr->common.scope)))) { - uint len = mptr->common.function_name->len; + size_t len = mptr->common.function_name->len; /* Do not display old-style inherited constructors */ if (!key) { @@ -1761,7 +1751,7 @@ static int copy_function_name(zval *zv TSRMLS_DC, int num_args, va_list args, ze Returns an array of all defined functions */ ZEND_FUNCTION(get_defined_functions) { - zval internal, user, *ret; + zval internal, user; if (zend_parse_parameters_none() == FAILURE) { return; @@ -1773,23 +1763,8 @@ ZEND_FUNCTION(get_defined_functions) zend_hash_apply_with_arguments(EG(function_table) TSRMLS_CC, copy_function_name, 2, &internal, &user); - ret = zend_hash_str_add_new(Z_ARRVAL_P(return_value), "internal", sizeof("internal")-1, &internal); - - if (!ret) { - zval_ptr_dtor(&internal); - zval_ptr_dtor(&user); - zval_dtor(return_value); - zend_error(E_WARNING, "Cannot add internal functions to return value from get_defined_functions()"); - RETURN_FALSE; - } - - ret = zend_hash_str_add_new(Z_ARRVAL_P(return_value), "user", sizeof("user")-1, &user); - if (!ret) { - zval_ptr_dtor(&user); - zval_dtor(return_value); - zend_error(E_WARNING, "Cannot add user functions to return value from get_defined_functions()"); - RETURN_FALSE; - } + zend_hash_str_add_new(Z_ARRVAL_P(return_value), "internal", sizeof("internal")-1, &internal); + zend_hash_str_add_new(Z_ARRVAL_P(return_value), "user", sizeof("user")-1, &user); } /* }}} */ @@ -1855,6 +1830,10 @@ ZEND_FUNCTION(create_function) RETURN_FALSE; } (*func->refcount)++; + static_variables = func->static_variables; + func->static_variables = NULL; + zend_hash_str_del(EG(function_table), LAMBDA_TEMP_FUNCNAME, sizeof(LAMBDA_TEMP_FUNCNAME)-1); + func->static_variables = static_variables; function_name = zend_string_alloc(sizeof("0lambda_")+MAX_LENGTH_OF_LONG, 0); function_name->val[0] = '\0'; @@ -1862,10 +1841,6 @@ ZEND_FUNCTION(create_function) do { function_name->len = snprintf(function_name->val + 1, sizeof("lambda_")+MAX_LENGTH_OF_LONG, "lambda_%d", ++EG(lambda_count)) + 1; } while (zend_hash_add_ptr(EG(function_table), function_name, func) == NULL); - static_variables = func->static_variables; - func->static_variables = NULL; - zend_hash_str_del(EG(function_table), LAMBDA_TEMP_FUNCNAME, sizeof(LAMBDA_TEMP_FUNCNAME)-1); - func->static_variables = static_variables; RETURN_STR(function_name); } else { zend_hash_str_del(EG(function_table), LAMBDA_TEMP_FUNCNAME, sizeof(LAMBDA_TEMP_FUNCNAME)-1); @@ -2147,7 +2122,7 @@ ZEND_FUNCTION(debug_print_backtrace) } ZVAL_UNDEF(&arg_array); - ptr = EG(current_execute_data)->prev_execute_data; + ptr = EX(prev_execute_data); /* skip debug_backtrace() */ call = ptr; @@ -2187,7 +2162,7 @@ ZEND_FUNCTION(debug_print_backtrace) } /* $this may be passed into regular internal functions */ - object = call->object; + object = Z_OBJ(call->This); if (object && call && call->func->type == ZEND_INTERNAL_FUNCTION && @@ -2200,9 +2175,7 @@ ZEND_FUNCTION(debug_print_backtrace) function_name = (func->common.scope && func->common.scope->trait_aliases) ? zend_resolve_method_name( - (object ? - zend_get_class_entry(object TSRMLS_CC) : - func->common.scope), func)->val : + (object ? object->ce : func->common.scope), func)->val : (func->common.function_name ? func->common.function_name->val : NULL); } else { @@ -2215,7 +2188,7 @@ ZEND_FUNCTION(debug_print_backtrace) if (func->common.scope) { class_name = func->common.scope->name; } else { - class_name = zend_get_object_classname(object TSRMLS_CC); + class_name = object->ce->name; } call_type = "->"; @@ -2322,7 +2295,6 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int zend_function *func; const char *function_name; const char *filename; - zend_string *class_name; const char *include_filename = NULL; zval stack_frame; @@ -2409,8 +2381,9 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int } /* $this may be passed into regular internal functions */ - object = call ? call->object : NULL; + object = call ? Z_OBJ(call->This) : NULL; if (object && + call->func && call->func->type == ZEND_INTERNAL_FUNCTION && !call->func->common.scope) { object = NULL; @@ -2421,9 +2394,7 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int function_name = (func->common.scope && func->common.scope->trait_aliases) ? zend_resolve_method_name( - (object ? - zend_get_class_entry(object TSRMLS_CC) : - func->common.scope), func)->val : + (object ? object->ce : func->common.scope), func)->val : (func->common.function_name ? func->common.function_name->val : NULL); } else { @@ -2438,8 +2409,7 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int if (func->common.scope) { add_assoc_str_ex(&stack_frame, "class", sizeof("class")-1, zend_string_copy(func->common.scope->name)); } else { - class_name = zend_get_object_classname(object TSRMLS_CC); - add_assoc_str_ex(&stack_frame, "class", sizeof("class")-1, zend_string_copy(class_name)); + add_assoc_str_ex(&stack_frame, "class", sizeof("class")-1, zend_string_copy(object->ce->name)); } if ((options & DEBUG_BACKTRACE_PROVIDE_OBJECT) != 0) { diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index cab31ce1c0..e4827f83b7 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -47,7 +47,7 @@ static zend_object_handlers closure_handlers; ZEND_METHOD(Closure, __invoke) /* {{{ */ { - zend_function *func = EG(current_execute_data)->func; + zend_function *func = EX(func); zval *arguments; arguments = emalloc(sizeof(zval) * ZEND_NUM_ARGS()); @@ -140,7 +140,7 @@ ZEND_METHOD(Closure, bind) } if (scope_arg != NULL) { /* scope argument was given */ - if (IS_ZEND_STD_OBJECT(*scope_arg)) { + if (Z_TYPE_P(scope_arg) == IS_OBJECT) { ce = Z_OBJCE_P(scope_arg); } else if (Z_TYPE_P(scope_arg) == IS_NULL) { ce = NULL; diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 7b8004533a..babf39ff40 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -132,6 +132,19 @@ static zend_string *zend_build_runtime_definition_key(zend_string *name, unsigne } /* }}} */ +static zend_bool zend_get_unqualified_name(const zend_string *name, const char **result, size_t *result_len) /* {{{ */ +{ + const char *ns_separator = zend_memrchr(name->val, '\\', name->len); + if (ns_separator != NULL) { + *result = ns_separator + 1; + *result_len = name->val + name->len - *result; + return 1; + } + + return 0; +} +/* }}} */ + static void init_compiler_declarables(TSRMLS_D) /* {{{ */ { ZVAL_LONG(&CG(declarables).ticks, 0); @@ -319,82 +332,63 @@ int zend_add_literal(zend_op_array *op_array, zval *zv TSRMLS_DC) /* {{{ */ } /* }}} */ -static int zend_add_func_name_literal(zend_op_array *op_array, zval *zv TSRMLS_DC) /* {{{ */ +static inline int zend_add_literal_string(zend_op_array *op_array, zend_string **str TSRMLS_DC) /* {{{ */ { int ret; - zend_string *lc_name; - zval c; - - if (op_array->last_literal > 0 && - &op_array->literals[op_array->last_literal - 1] == zv && - Z_CACHE_SLOT(op_array->literals[op_array->last_literal - 1]) == -1) { - /* we already have function name as last literal (do nothing) */ - ret = op_array->last_literal - 1; - } else { - ret = zend_add_literal(op_array, zv TSRMLS_CC); - } + zval zv; + ZVAL_STR(&zv, *str); + ret = zend_add_literal(op_array, &zv TSRMLS_CC); + *str = Z_STR(zv); + return ret; +} - lc_name = zend_string_alloc(Z_STRLEN_P(zv), 0); - zend_str_tolower_copy(lc_name->val, Z_STRVAL_P(zv), Z_STRLEN_P(zv)); - ZVAL_NEW_STR(&c, lc_name); - zend_add_literal(CG(active_op_array), &c TSRMLS_CC); +static int zend_add_func_name_literal(zend_op_array *op_array, zend_string *name TSRMLS_DC) /* {{{ */ +{ + /* Original name */ + int ret = zend_add_literal_string(op_array, &name TSRMLS_CC); + + /* Lowercased name */ + zend_string *lc_name = zend_string_alloc(name->len, 0); + zend_str_tolower_copy(lc_name->val, name->val, name->len); + zend_add_literal_string(op_array, &lc_name TSRMLS_CC); return ret; } /* }}} */ -static int zend_add_ns_func_name_literal(zend_op_array *op_array, zval *zv TSRMLS_DC) /* {{{ */ +static int zend_add_ns_func_name_literal(zend_op_array *op_array, zend_string *name TSRMLS_DC) /* {{{ */ { - int ret; - zend_string *lc_name; - const char *ns_separator; - int lc_len; - zval c; - - if (op_array->last_literal > 0 && - &op_array->literals[op_array->last_literal - 1] == zv && - Z_CACHE_SLOT(op_array->literals[op_array->last_literal - 1]) == -1) { - /* we already have function name as last literal (do nothing) */ - ret = op_array->last_literal - 1; - } else { - ret = zend_add_literal(op_array, zv TSRMLS_CC); - } + const char *unqualified_name; + size_t unqualified_name_len; - lc_name = zend_string_alloc(Z_STRLEN_P(zv), 0); - zend_str_tolower_copy(lc_name->val, Z_STRVAL_P(zv), Z_STRLEN_P(zv)); - ZVAL_NEW_STR(&c, lc_name); - zend_add_literal(CG(active_op_array), &c TSRMLS_CC); + /* Original name */ + int ret = zend_add_literal_string(op_array, &name TSRMLS_CC); - ns_separator = (const char*)zend_memrchr(Z_STRVAL_P(zv), '\\', Z_STRLEN_P(zv)); + /* Lowercased name */ + zend_string *lc_name = zend_string_alloc(name->len, 0); + zend_str_tolower_copy(lc_name->val, name->val, name->len); + zend_add_literal_string(op_array, &lc_name TSRMLS_CC); - if (ns_separator != NULL) { - ns_separator += 1; - lc_len = Z_STRLEN_P(zv) - (ns_separator - Z_STRVAL_P(zv)); - lc_name = zend_string_alloc(lc_len, 0); - zend_str_tolower_copy(lc_name->val, ns_separator, lc_len); - ZVAL_NEW_STR(&c, lc_name); - zend_add_literal(CG(active_op_array), &c TSRMLS_CC); + /* Lowercased unqualfied name */ + if (zend_get_unqualified_name(name, &unqualified_name, &unqualified_name_len)) { + lc_name = zend_string_alloc(unqualified_name_len, 0); + zend_str_tolower_copy(lc_name->val, unqualified_name, unqualified_name_len); + zend_add_literal_string(op_array, &lc_name TSRMLS_CC); } return ret; } /* }}} */ -static int zend_add_class_name_literal(zend_op_array *op_array, zend_string *name TSRMLS_DC) /* {{{ */ { - int ret; - zend_string *lc_name; - - zval zv; - ZVAL_STR(&zv, name); - - ret = zend_add_literal(op_array, &zv TSRMLS_CC); - name = Z_STR(zv); /* Load new name string in case it was interned */ +static int zend_add_class_name_literal(zend_op_array *op_array, zend_string *name TSRMLS_DC) /* {{{ */ +{ + /* Original name */ + int ret = zend_add_literal_string(op_array, &name TSRMLS_CC); - lc_name = zend_string_alloc(name->len, 0); + /* Lowercased name */ + zend_string *lc_name = zend_string_alloc(name->len, 0); zend_str_tolower_copy(lc_name->val, name->val, name->len); - - ZVAL_NEW_STR(&zv, lc_name); - zend_add_literal(CG(active_op_array), &zv TSRMLS_CC); + zend_add_literal_string(op_array, &lc_name TSRMLS_CC); zend_alloc_cache_slot(ret TSRMLS_CC); @@ -402,72 +396,44 @@ static int zend_add_class_name_literal(zend_op_array *op_array, zend_string *nam } /* }}} */ -static int zend_add_const_name_literal(zend_op_array *op_array, zval *zv, int unqualified TSRMLS_DC) /* {{{ */ +static int zend_add_const_name_literal(zend_op_array *op_array, zend_string *name, zend_bool unqualified TSRMLS_DC) /* {{{ */ { - int ret; - char *name; zend_string *tmp_name; - const char *ns_separator; - int name_len, ns_len; - zval c; - - if (op_array->last_literal > 0 && - &op_array->literals[op_array->last_literal - 1] == zv && - Z_CACHE_SLOT(op_array->literals[op_array->last_literal - 1]) == -1) { - /* we already have function name as last literal (do nothing) */ - ret = op_array->last_literal - 1; - } else { - ret = zend_add_literal(op_array, zv TSRMLS_CC); - } - /* skip leading '\\' */ - if (Z_STRVAL_P(zv)[0] == '\\') { - name_len = Z_STRLEN_P(zv) - 1; - name = Z_STRVAL_P(zv) + 1; - } else { - name_len = Z_STRLEN_P(zv); - name = Z_STRVAL_P(zv); - } - ns_separator = zend_memrchr(name, '\\', name_len); - if (ns_separator) { - ns_len = ns_separator - name; - } else { - ns_len = 0; - } + int ret = zend_add_literal_string(op_array, &name TSRMLS_CC); + + size_t ns_len = 0, after_ns_len = name->len; + const char *after_ns = zend_memrchr(name->val, '\\', name->len); + if (after_ns) { + after_ns += 1; + ns_len = after_ns - name->val - 1; + after_ns_len = name->len - ns_len - 1; - if (ns_len) { /* lowercased namespace name & original constant name */ - tmp_name = zend_string_init(name, name_len, 0); + tmp_name = zend_string_init(name->val, name->len, 0); zend_str_tolower(tmp_name->val, ns_len); - ZVAL_NEW_STR(&c, tmp_name); - zend_add_literal(CG(active_op_array), &c TSRMLS_CC); + zend_add_literal_string(op_array, &tmp_name TSRMLS_CC); /* lowercased namespace name & lowercased constant name */ - tmp_name = zend_string_alloc(name_len, 0); - zend_str_tolower_copy(tmp_name->val, name, name_len); - ZVAL_NEW_STR(&c, tmp_name); - zend_add_literal(CG(active_op_array), &c TSRMLS_CC); - } + tmp_name = zend_string_alloc(name->len, 0); + zend_str_tolower_copy(tmp_name->val, name->val, name->len); + zend_add_literal_string(op_array, &tmp_name TSRMLS_CC); - if (ns_len) { if (!unqualified) { return ret; } - ns_len++; - name += ns_len; - name_len -= ns_len; + } else { + after_ns = name->val; } - /* original constant name */ - tmp_name = zend_string_init(name, name_len, 0); - ZVAL_NEW_STR(&c, tmp_name); - zend_add_literal(CG(active_op_array), &c TSRMLS_CC); + /* original unqualified constant name */ + tmp_name = zend_string_init(after_ns, after_ns_len, 0); + zend_add_literal_string(op_array, &tmp_name TSRMLS_CC); - /* lowercased constant name */ - tmp_name = zend_string_alloc(name_len, 0); - zend_str_tolower_copy(tmp_name->val, name, name_len); - ZVAL_NEW_STR(&c, tmp_name); - zend_add_literal(CG(active_op_array), &c TSRMLS_CC); + /* lowercased unqualified constant name */ + tmp_name = zend_string_alloc(after_ns_len, 0); + zend_str_tolower_copy(tmp_name->val, after_ns, after_ns_len); + zend_add_literal_string(op_array, &tmp_name TSRMLS_CC); return ret; } @@ -536,8 +502,7 @@ void zend_do_free(znode *op1 TSRMLS_DC) /* {{{ */ && opline->result.var == op1->u.op.var) { if (opline->opcode == ZEND_FETCH_R || opline->opcode == ZEND_FETCH_DIM_R || - opline->opcode == ZEND_FETCH_OBJ_R || - opline->opcode == ZEND_QM_ASSIGN) { + opline->opcode == ZEND_FETCH_OBJ_R) { /* It's very rare and useless case. It's better to use additional FREE opcode and simplify the FETCH handlers their selves */ @@ -549,16 +514,18 @@ void zend_do_free(znode *op1 TSRMLS_DC) /* {{{ */ opline->result_type |= EXT_TYPE_UNUSED; } } else { - while (opline>CG(active_op_array)->opcodes) { - if (opline->opcode == ZEND_FETCH_DIM_R - && opline->op1_type == IS_VAR - && opline->op1.var == op1->u.op.var) { - /* This should the end of a list() construct - * Mark its result as unused - */ - opline->extended_value = ZEND_FETCH_STANDARD; - break; - } else if (opline->result_type==IS_VAR + while (opline >= CG(active_op_array)->opcodes) { + if (opline->opcode == ZEND_FETCH_LIST && + opline->op1_type == IS_VAR && + opline->op1.var == op1->u.op.var) { + opline = get_next_op(CG(active_op_array) TSRMLS_CC); + + opline->opcode = ZEND_FREE; + SET_NODE(opline->op1, op1); + SET_UNUSED(opline->op2); + return; + } + if (opline->result_type==IS_VAR && opline->result.var == op1->u.op.var) { if (opline->opcode == ZEND_NEW) { opline->result_type |= EXT_TYPE_UNUSED; @@ -630,12 +597,16 @@ zend_string *zend_prefix_with_ns(zend_string *name TSRMLS_DC) { } } -void *zend_hash_find_ptr_lc(HashTable *ht, char *str, size_t len) { +void *zend_hash_find_ptr_lc(HashTable *ht, const char *str, size_t len) { void *result; - zend_string *lcname = zend_string_alloc(len, 0); + zend_string *lcname; + ALLOCA_FLAG(use_heap); + + STR_ALLOCA_ALLOC(lcname, len, use_heap); zend_str_tolower_copy(lcname->val, str, len); result = zend_hash_find_ptr(ht, lcname); - zend_string_free(lcname); + STR_ALLOCA_FREE(lcname, use_heap); + return result; } @@ -859,7 +830,7 @@ static int generate_free_loop_var(znode *var TSRMLS_DC) /* {{{ */ { zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); - opline->opcode = var->op_type == IS_TMP_VAR ? ZEND_FREE : ZEND_SWITCH_FREE; + opline->opcode = ZEND_FREE; SET_NODE(opline->op1, var); SET_UNUSED(opline->op2); } @@ -1136,7 +1107,7 @@ ZEND_API zend_string *zend_mangle_property_name(const char *src1, size_t src1_le } /* }}} */ -static int zend_strnlen(const char* s, size_t maxlen) /* {{{ */ +static size_t zend_strnlen(const char* s, size_t maxlen) /* {{{ */ { size_t len = 0; while (*s++ && maxlen--) len++; @@ -1185,57 +1156,45 @@ ZEND_API int zend_unmangle_property_name_ex(const zend_string *name, const char } /* }}} */ -static zend_constant *zend_get_ct_const(zend_string *name, int all_internal_constants_substitution TSRMLS_DC) /* {{{ */ +static zend_constant *zend_lookup_reserved_const(const char *name, size_t len TSRMLS_DC) /* {{{ */ { - zend_constant *c = NULL; - char *lookup_name; - - if (name->val[0] == '\\') { - c = zend_hash_str_find_ptr(EG(zend_constants), name->val + 1, name->len - 1); - if (!c) { - lookup_name = zend_str_tolower_dup(name->val + 1, name->len - 1); - c = zend_hash_str_find_ptr(EG(zend_constants), lookup_name, name->len - 1); - efree(lookup_name); - - if (c && (c->flags & CONST_CT_SUBST) && !(c->flags & CONST_CS)) { - return c; - } - return NULL; - } - } else if ((c = zend_hash_find_ptr(EG(zend_constants), name)) == NULL) { - lookup_name = zend_str_tolower_dup(name->val, name->len); - c = zend_hash_str_find_ptr(EG(zend_constants), lookup_name, name->len); - efree(lookup_name); - - if (c && (c->flags & CONST_CT_SUBST) && !(c->flags & CONST_CS)) { - return c; - } - return NULL; - } - - if (c->flags & CONST_CT_SUBST) { - return c; - } - if (all_internal_constants_substitution && - (c->flags & CONST_PERSISTENT) && - !(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION) && - !Z_CONSTANT(c->value)) { + zend_constant *c = zend_hash_find_ptr_lc(EG(zend_constants), name, len); + if (c && !(c->flags & CONST_CS) && (c->flags & CONST_CT_SUBST)) { return c; } return NULL; } /* }}} */ -static int zend_constant_ct_subst(znode *result, zval *const_name, int all_internal_constants_substitution TSRMLS_DC) /* {{{ */ +static zend_bool zend_try_ct_eval_const(zval *zv, zend_string *name, zend_bool is_fully_qualified TSRMLS_DC) /* {{{ */ { - zend_constant *c = zend_get_ct_const(Z_STR_P(const_name), - all_internal_constants_substitution TSRMLS_CC); + zend_constant *c; - if (c) { - result->op_type = IS_CONST; - ZVAL_DUP(&result->u.constant, &c->value); - return 1; + if (!(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION)) { + /* Substitute case-sensitive (or lowercase) persistent constants */ + c = zend_hash_find_ptr(EG(zend_constants), name); + if (c && (c->flags & CONST_PERSISTENT)) { + ZVAL_DUP(zv, &c->value); + return 1; + } + } + + { + /* Substitute true, false and null (including unqualified usage in namespaces) */ + const char *lookup_name = name->val; + size_t lookup_len = name->len; + + if (!is_fully_qualified) { + zend_get_unqualified_name(name, &lookup_name, &lookup_len); + } + + c = zend_lookup_reserved_const(lookup_name, lookup_len TSRMLS_CC); + if (c) { + ZVAL_DUP(zv, &c->value); + return 1; + } } + return 0; } /* }}} */ @@ -1389,9 +1348,6 @@ again: if (LANG_SCNG(yy_text)[LANG_SCNG(yy_leng)-1] != '>') { CG(increment_lineno) = 1; } - if (CG(has_bracketed_namespaces) && !CG(in_namespace)) { - goto again; - } retval = ';'; /* implicit ; */ break; case T_OPEN_TAG_WITH_ECHO: @@ -1685,11 +1641,8 @@ static void zend_adjust_for_fetch_type(zend_op *opline, uint32_t type) /* {{{ */ case BP_VAR_R: return; case BP_VAR_W: - opline->opcode += 3; - return; case BP_VAR_REF: opline->opcode += 3; - opline->extended_value |= ZEND_FETCH_MAKE_REF; return; case BP_VAR_RW: opline->opcode += 6; @@ -1766,7 +1719,9 @@ static zend_op *zend_emit_op_tmp(znode *result, zend_uchar opcode, znode *op1, z SET_NODE(opline->op2, op2); } - zend_make_tmp_result(result, opline TSRMLS_CC); + if (result) { + zend_make_tmp_result(result, opline TSRMLS_CC); + } return opline; } @@ -2067,6 +2022,22 @@ static void zend_separate_if_call_and_write(znode *node, zend_ast *ast, uint32_t /* }}} */ void zend_delayed_compile_var(znode *result, zend_ast *ast, uint32_t type TSRMLS_DC); +void zend_compile_assign(znode *result, zend_ast *ast TSRMLS_DC); +static void zend_compile_list_assign(znode *result, zend_ast *ast, znode *expr_node TSRMLS_DC); + +static inline void zend_emit_assign_znode(zend_ast *var_ast, znode *value_node TSRMLS_DC) /* {{{ */ +{ + znode dummy_node; + if (var_ast->kind == ZEND_AST_LIST) { + zend_compile_list_assign(&dummy_node, var_ast, value_node TSRMLS_CC); + } else { + zend_ast *assign_ast = zend_ast_create(ZEND_AST_ASSIGN, var_ast, + zend_ast_create_znode(value_node)); + zend_compile_assign(&dummy_node, assign_ast TSRMLS_CC); + } + zend_do_free(&dummy_node TSRMLS_CC); +} +/* }}} */ static zend_op *zend_delayed_compile_dim(znode *result, zend_ast *ast, uint32_t type TSRMLS_DC) /* {{{ */ { @@ -2202,20 +2173,6 @@ void zend_compile_static_prop(znode *result, zend_ast *ast, uint32_t type TSRMLS } /* }}} */ -static inline zend_uchar get_list_fetch_opcode(zend_uchar op_type) /* {{{ */ -{ - switch (op_type) { - case IS_VAR: - case IS_CV: - return ZEND_FETCH_DIM_R; - case IS_TMP_VAR: - case IS_CONST: - return ZEND_FETCH_DIM_TMP_VAR; - EMPTY_SWITCH_DEFAULT_CASE() - } -} -/* }}} */ - static void zend_compile_list_assign(znode *result, zend_ast *ast, znode *expr_node TSRMLS_DC) /* {{{ */ { zend_ast_list *list = zend_ast_get_list(ast); @@ -2227,8 +2184,7 @@ static void zend_compile_list_assign(znode *result, zend_ast *ast, znode *expr_n for (i = 0; i < list->children; ++i) { zend_ast *var_ast = list->child[i]; - znode fetch_result, dim_node, var_node, assign_result; - zend_op *opline; + znode fetch_result, dim_node; if (var_ast == NULL) { continue; @@ -2241,21 +2197,8 @@ static void zend_compile_list_assign(znode *result, zend_ast *ast, znode *expr_n Z_TRY_ADDREF(expr_node->u.constant); } - opline = zend_emit_op(&fetch_result, - get_list_fetch_opcode(expr_node->op_type), expr_node, &dim_node TSRMLS_CC); - opline->extended_value |= ZEND_FETCH_ADD_LOCK; - - if (var_ast->kind != ZEND_AST_LIST) { - if (is_this_fetch(var_ast)) { - zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this"); - } - zend_compile_var(&var_node, var_ast, BP_VAR_W TSRMLS_CC); - zend_emit_op(&assign_result, ZEND_ASSIGN, &var_node, &fetch_result TSRMLS_CC); - zend_do_free(&assign_result TSRMLS_CC); - } else { - zend_compile_list_assign(&assign_result, var_ast, &fetch_result TSRMLS_CC); - zend_do_free(&assign_result TSRMLS_CC); - } + zend_emit_op(&fetch_result, ZEND_FETCH_LIST, expr_node, &dim_node TSRMLS_CC); + zend_emit_assign_znode(var_ast, &fetch_result TSRMLS_CC); } *result = *expr_node; } @@ -2335,8 +2278,6 @@ void zend_compile_assign(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */ opline->opcode = ZEND_ASSIGN_DIM; opline = zend_emit_op_data(&expr_node TSRMLS_CC); - opline->op2.var = get_temporary_variable(CG(active_op_array)); - opline->op2_type = IS_VAR; return; case ZEND_AST_PROP: offset = zend_delayed_compile_begin(TSRMLS_C); @@ -2357,16 +2298,6 @@ void zend_compile_assign(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */ } /* }}} */ -static inline void zend_emit_assign_znode(zend_ast *var_ast, znode *value_node TSRMLS_DC) /* {{{ */ -{ - znode dummy_node; - zend_ast *assign_ast = zend_ast_create(ZEND_AST_ASSIGN, var_ast, - zend_ast_create_znode(value_node)); - zend_compile_assign(&dummy_node, assign_ast TSRMLS_CC); - zend_do_free(&dummy_node TSRMLS_CC); -} -/* }}} */ - void zend_compile_assign_ref(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */ { zend_ast *target_ast = ast->child[0]; @@ -2383,6 +2314,10 @@ void zend_compile_assign_ref(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */ zend_compile_var(&target_node, target_ast, BP_VAR_W TSRMLS_CC); zend_compile_var(&source_node, source_ast, BP_VAR_REF TSRMLS_CC); + if (source_node.op_type != IS_VAR && zend_is_call(source_ast)) { + zend_error_noreturn(E_COMPILE_ERROR, "Cannot use result of built-in function in write context"); + } + opline = zend_emit_op(result, ZEND_ASSIGN_REF, &target_node, &source_node TSRMLS_CC); if (!result) { opline->result_type |= EXT_TYPE_UNUSED; @@ -2434,8 +2369,6 @@ void zend_compile_compound_assign(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ opline->extended_value = ZEND_ASSIGN_DIM; opline = zend_emit_op_data(&expr_node TSRMLS_CC); - opline->op2.var = get_temporary_variable(CG(active_op_array)); - opline->op2_type = IS_VAR; return; case ZEND_AST_PROP: offset = zend_delayed_compile_begin(TSRMLS_C); @@ -2596,7 +2529,7 @@ void zend_compile_ns_call(znode *result, znode *name_node, zend_ast *args_ast TS SET_UNUSED(opline->op1); opline->op2_type = IS_CONST; opline->op2.constant = zend_add_ns_func_name_literal( - CG(active_op_array), &name_node->u.constant TSRMLS_CC); + CG(active_op_array), Z_STR(name_node->u.constant) TSRMLS_CC); zend_alloc_cache_slot(opline->op2.constant TSRMLS_CC); zend_compile_call_common(result, args_ast, NULL TSRMLS_CC); @@ -2610,8 +2543,8 @@ void zend_compile_dynamic_call(znode *result, znode *name_node, zend_ast *args_a SET_UNUSED(opline->op1); if (name_node->op_type == IS_CONST && Z_TYPE(name_node->u.constant) == IS_STRING) { opline->op2_type = IS_CONST; - opline->op2.constant - = zend_add_func_name_literal(CG(active_op_array), &name_node->u.constant TSRMLS_CC); + opline->op2.constant = zend_add_func_name_literal(CG(active_op_array), + Z_STR(name_node->u.constant) TSRMLS_CC); zend_alloc_cache_slot(opline->op2.constant TSRMLS_CC); } else { SET_NODE(opline->op2, name_node); @@ -2697,13 +2630,13 @@ int zend_compile_func_defined(znode *result, zend_ast_list *args TSRMLS_DC) /* { } /* }}} */ -static int zend_try_compile_ct_bound_init_user_func(znode *result, zend_ast *name_ast, uint32_t num_args TSRMLS_DC) /* {{{ */ +static int zend_try_compile_ct_bound_init_user_func(zend_ast *name_ast, uint32_t num_args TSRMLS_DC) /* {{{ */ { zend_string *name, *lcname; zend_function *fbc; zend_op *opline; - if (name_ast->kind != ZEND_AST_CONST || Z_TYPE_P(zend_ast_get_zval(name_ast)) != IS_STRING) { + if (name_ast->kind != ZEND_AST_ZVAL || Z_TYPE_P(zend_ast_get_zval(name_ast)) != IS_STRING) { return FAILURE; } @@ -2720,20 +2653,22 @@ static int zend_try_compile_ct_bound_init_user_func(znode *result, zend_ast *nam } opline = zend_emit_op(NULL, ZEND_INIT_FCALL, NULL, NULL TSRMLS_CC); + opline->extended_value = num_args; + opline->op2_type = IS_CONST; LITERAL_STR(opline->op2, lcname); - opline->extended_value = num_args; + zend_alloc_cache_slot(opline->op2.constant TSRMLS_CC); return SUCCESS; } /* }}} */ -static void zend_compile_init_user_func(znode *result, zend_ast *name_ast, uint32_t num_args, zend_string *orig_func_name TSRMLS_DC) /* {{{ */ +static void zend_compile_init_user_func(zend_ast *name_ast, uint32_t num_args, zend_string *orig_func_name TSRMLS_DC) /* {{{ */ { zend_op *opline; znode name_node; - if (zend_try_compile_ct_bound_init_user_func(result, name_ast, num_args TSRMLS_CC) == SUCCESS) { + if (zend_try_compile_ct_bound_init_user_func(name_ast, num_args TSRMLS_CC) == SUCCESS) { return; } @@ -2755,7 +2690,7 @@ int zend_compile_func_cufa(znode *result, zend_ast_list *args, zend_string *lcna return FAILURE; } - zend_compile_init_user_func(NULL, args->child[0], 1, lcname TSRMLS_CC); + zend_compile_init_user_func(args->child[0], 1, lcname TSRMLS_CC); zend_compile_expr(&arg_node, args->child[1] TSRMLS_CC); zend_emit_op(NULL, ZEND_SEND_ARRAY, &arg_node, NULL TSRMLS_CC); zend_emit_op(result, ZEND_DO_FCALL, NULL, NULL TSRMLS_CC); @@ -2773,7 +2708,7 @@ int zend_compile_func_cuf(znode *result, zend_ast_list *args, zend_string *lcnam return FAILURE; } - zend_compile_init_user_func(NULL, args->child[0], args->children - 1, lcname TSRMLS_CC); + zend_compile_init_user_func(args->child[0], args->children - 1, lcname TSRMLS_CC); for (i = 1; i < args->children; ++i) { zend_ast *arg_ast = args->child[i]; znode arg_node; @@ -2923,8 +2858,8 @@ void zend_compile_method_call(znode *result, zend_ast *ast, uint32_t type TSRMLS } opline->op2_type = IS_CONST; - opline->op2.constant = - zend_add_func_name_literal(CG(active_op_array), &method_node.u.constant TSRMLS_CC); + opline->op2.constant = zend_add_func_name_literal(CG(active_op_array), + Z_STR(method_node.u.constant) TSRMLS_CC); zend_alloc_polymorphic_cache_slot(opline->op2.constant TSRMLS_CC); } else { SET_NODE(opline->op2, &method_node); @@ -2978,8 +2913,8 @@ void zend_compile_static_call(znode *result, zend_ast *ast, uint32_t type TSRMLS if (method_node.op_type == IS_CONST) { opline->op2_type = IS_CONST; - opline->op2.constant = - zend_add_func_name_literal(CG(active_op_array), &method_node.u.constant TSRMLS_CC); + opline->op2.constant = zend_add_func_name_literal(CG(active_op_array), + Z_STR(method_node.u.constant) TSRMLS_CC); if (opline->op1_type == IS_CONST) { zend_alloc_cache_slot(opline->op2.constant TSRMLS_CC); } else { @@ -3002,10 +2937,23 @@ void zend_compile_new(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */ zend_op *opline; uint32_t opnum; - zend_compile_class_ref(&class_node, class_ast TSRMLS_CC); + if (zend_is_const_default_class_ref(class_ast)) { + class_node.op_type = IS_CONST; + ZVAL_STR(&class_node.u.constant, zend_resolve_class_name_ast(class_ast TSRMLS_CC)); + } else { + zend_compile_class_ref(&class_node, class_ast TSRMLS_CC); + } opnum = get_next_op_number(CG(active_op_array)); - zend_emit_op(result, ZEND_NEW, &class_node, NULL TSRMLS_CC); + opline = zend_emit_op(result, ZEND_NEW, NULL, NULL TSRMLS_CC); + + if (class_node.op_type == IS_CONST) { + opline->op1_type = IS_CONST; + opline->op1.constant = zend_add_class_name_literal( + CG(active_op_array), Z_STR(class_node.u.constant) TSRMLS_CC); + } else { + SET_NODE(opline->op1, &class_node); + } zend_compile_call_common(&ctor_result, args_ast, NULL TSRMLS_CC); zend_do_free(&ctor_result TSRMLS_CC); @@ -3183,7 +3131,7 @@ void zend_compile_return(zend_ast *ast TSRMLS_DC) /* {{{ */ if (expr_ast) { if (zend_is_call(expr_ast)) { opline->extended_value = ZEND_RETURNS_FUNCTION; - } else if (!zend_is_variable(expr_ast)) { + } else if (by_ref && !zend_is_variable(expr_ast)) { opline->extended_value = ZEND_RETURNS_VALUE; } } @@ -3259,11 +3207,9 @@ void zend_compile_goto(zend_ast *ast TSRMLS_DC) /* {{{ */ void zend_compile_label(zend_ast *ast TSRMLS_DC) /* {{{ */ { - zval *label = zend_ast_get_zval(ast->child[0]); + zend_string *label = zend_ast_get_str(ast->child[0]); zend_label dest; - ZEND_ASSERT(Z_TYPE_P(label) == IS_STRING); - if (!CG(context).labels) { ALLOC_HASHTABLE(CG(context).labels); zend_hash_init(CG(context).labels, 8, NULL, ptr_dtor, 0); @@ -3272,8 +3218,8 @@ void zend_compile_label(zend_ast *ast TSRMLS_DC) /* {{{ */ dest.brk_cont = CG(context).current_brk_cont; dest.opline_num = get_next_op_number(CG(active_op_array)); - if (!zend_hash_add_mem(CG(context).labels, Z_STR_P(label), &dest, sizeof(zend_label))) { - zend_error_noreturn(E_COMPILE_ERROR, "Label '%s' already defined", Z_STRVAL_P(label)); + if (!zend_hash_add_mem(CG(context).labels, label, &dest, sizeof(zend_label))) { + zend_error_noreturn(E_COMPILE_ERROR, "Label '%s' already defined", label->val); } } /* }}} */ @@ -3390,7 +3336,7 @@ void zend_compile_foreach(zend_ast *ast TSRMLS_DC) /* {{{ */ zend_bool is_variable = zend_is_variable(expr_ast) && !zend_is_call(expr_ast) && zend_can_write_to_variable(expr_ast); - znode expr_node, reset_node, value_node, key_node, dummy_node; + znode expr_node, reset_node, value_node, key_node; zend_op *opline; uint32_t opnum_reset, opnum_fetch; @@ -3448,10 +3394,7 @@ void zend_compile_foreach(zend_ast *ast TSRMLS_DC) /* {{{ */ zend_make_tmp_result(&key_node, opline TSRMLS_CC); } - if (value_ast->attr == ZEND_AST_LIST) { - zend_compile_list_assign(&dummy_node, value_ast, &value_node TSRMLS_CC); - zend_do_free(&dummy_node TSRMLS_CC); - } else if (by_ref) { + if (by_ref) { zend_emit_assign_ref_znode(value_ast, &value_node TSRMLS_CC); } else { zend_emit_assign_znode(value_ast, &value_node TSRMLS_CC); @@ -3593,7 +3536,7 @@ void zend_compile_switch(zend_ast *ast TSRMLS_DC) /* {{{ */ zend_end_loop(get_next_op_number(CG(active_op_array)), 1 TSRMLS_CC); if (expr_node.op_type == IS_VAR || expr_node.op_type == IS_TMP_VAR) { - zend_emit_op(NULL, expr_node.op_type == IS_TMP_VAR ? ZEND_FREE : ZEND_SWITCH_FREE, + zend_emit_op(NULL, ZEND_FREE, &expr_node, NULL TSRMLS_CC); } else if (expr_node.op_type == IS_CONST) { zval_dtor(&expr_node.u.constant); @@ -3875,7 +3818,7 @@ void zend_compile_params(zend_ast *ast TSRMLS_DC) /* {{{ */ arg_info = &arg_infos[i]; arg_info->name = estrndup(name->val, name->len); - arg_info->name_len = name->len; + arg_info->name_len = (uint32_t)name->len; arg_info->pass_by_reference = is_ref; arg_info->is_variadic = is_variadic; arg_info->type_hint = 0; @@ -3919,7 +3862,7 @@ void zend_compile_params(zend_ast *ast TSRMLS_DC) /* {{{ */ arg_info->type_hint = IS_OBJECT; arg_info->class_name = estrndup(class_name->val, class_name->len); - arg_info->class_name_len = class_name->len; + arg_info->class_name_len = (uint32_t)class_name->len; zend_string_release(class_name); @@ -3982,8 +3925,6 @@ void zend_begin_method_decl(zend_op_array *op_array, zend_string *name, zend_boo } if (op_array->fn_flags & ZEND_ACC_ABSTRACT) { - //zend_op *opline; - if (op_array->fn_flags & ZEND_ACC_PRIVATE) { zend_error_noreturn(E_COMPILE_ERROR, "%s function %s::%s() cannot be declared private", in_interface ? "Interface" : "Abstract", ce->name->val, name->val); @@ -3995,11 +3936,6 @@ void zend_begin_method_decl(zend_op_array *op_array, zend_string *name, zend_boo } ce->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS; - - /*opline = get_next_op(op_array TSRMLS_CC); - opline->opcode = ZEND_RAISE_ABSTRACT_ERROR; - SET_UNUSED(opline->op1); - SET_UNUSED(opline->op2);*/ } else if (!has_body) { zend_error_noreturn(E_COMPILE_ERROR, "Non-abstract method %s::%s() must contain body", ce->name->val, name->val); @@ -4459,7 +4395,6 @@ void zend_compile_use_trait(zend_ast *ast TSRMLS_DC) /* {{{ */ opline = get_next_op(CG(active_op_array) TSRMLS_CC); opline->opcode = ZEND_ADD_TRAIT; SET_NODE(opline->op1, &CG(implementing_class)); - opline->extended_value = ZEND_FETCH_CLASS_TRAIT; opline->op2_type = IS_CONST; opline->op2.constant = zend_add_class_name_literal(CG(active_op_array), zend_resolve_class_name_ast(trait_ast TSRMLS_CC) TSRMLS_CC); @@ -4508,7 +4443,6 @@ void zend_compile_implements(znode *class_node, zend_ast *ast TSRMLS_DC) /* {{{ } opline = zend_emit_op(NULL, ZEND_ADD_INTERFACE, class_node, NULL TSRMLS_CC); - opline->extended_value = ZEND_FETCH_CLASS_INTERFACE; opline->op2_type = IS_CONST; opline->op2.constant = zend_add_class_name_literal(CG(active_op_array), zend_resolve_class_name_ast(class_ast TSRMLS_CC) TSRMLS_CC); @@ -4705,6 +4639,8 @@ static HashTable *zend_get_import_ht(uint32_t type TSRMLS_DC) /* {{{ */ return CG(current_import_const); EMPTY_SWITCH_DEFAULT_CASE() } + + return NULL; } /* }}} */ @@ -4719,6 +4655,8 @@ static char *zend_get_use_type_str(uint32_t type) /* {{{ */ return " const"; EMPTY_SWITCH_DEFAULT_CASE() } + + return " unknown"; } /* }}} */ @@ -4752,10 +4690,11 @@ void zend_compile_use(zend_ast *ast TSRMLS_DC) /* {{{ */ if (new_name_ast) { new_name = zend_string_copy(zend_ast_get_str(new_name_ast)); } else { - /* The form "use A\B" is eqivalent to "use A\B as B" */ - const char *p = zend_memrchr(old_name->val, '\\', old_name->len); - if (p) { - new_name = zend_string_init(p + 1, old_name->len - (p - old_name->val + 1), 0); + const char *unqualified_name; + size_t unqualified_name_len; + if (zend_get_unqualified_name(old_name, &unqualified_name, &unqualified_name_len)) { + /* The form "use A\B" is eqivalent to "use A\B as B" */ + new_name = zend_string_init(unqualified_name, unqualified_name_len, 0); } else { new_name = zend_string_copy(old_name); @@ -4859,7 +4798,7 @@ void zend_compile_const_decl(zend_ast *ast TSRMLS_DC) /* {{{ */ value_node.op_type = IS_CONST; zend_const_expr_to_zval(value_zv, value_ast TSRMLS_CC); - if (zend_get_ct_const(name, 0 TSRMLS_CC)) { + if (zend_lookup_reserved_const(name->val, name->len TSRMLS_CC)) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare constant '%s'", name->val); } @@ -4986,7 +4925,7 @@ static zend_bool zend_try_ct_eval_magic_const(zval *zv, zend_ast *ast TSRMLS_DC) switch (ast->attr) { case T_LINE: - ZVAL_LONG(zv, CG(zend_lineno)); + ZVAL_LONG(zv, ast->lineno); break; case T_FILE: ZVAL_STR_COPY(zv, CG(compiled_filename)); @@ -5316,7 +5255,7 @@ void zend_compile_cast(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */ zend_compile_expr(&expr_node, expr_ast TSRMLS_CC); - opline = zend_emit_op(result, ZEND_CAST, &expr_node, NULL TSRMLS_CC); + opline = zend_emit_op_tmp(result, ZEND_CAST, &expr_node, NULL TSRMLS_CC); opline->extended_value = ast->attr; } /* }}} */ @@ -5335,13 +5274,13 @@ static void zend_compile_shorthand_conditional(znode *result, zend_ast *ast TSRM zend_compile_expr(&cond_node, cond_ast TSRMLS_CC); opnum_jmp_set = get_next_op_number(CG(active_op_array)); - zend_emit_op(result, ZEND_JMP_SET, &cond_node, NULL TSRMLS_CC); + zend_emit_op_tmp(result, ZEND_JMP_SET, &cond_node, NULL TSRMLS_CC); zend_compile_expr(&false_node, false_ast TSRMLS_CC); opline_jmp_set = &CG(active_op_array)->opcodes[opnum_jmp_set]; opline_jmp_set->op2.opline_num = get_next_op_number(CG(active_op_array)) + 1; - opline_qm_assign = zend_emit_op(NULL, ZEND_QM_ASSIGN, &false_node, NULL TSRMLS_CC); + opline_qm_assign = zend_emit_op_tmp(NULL, ZEND_QM_ASSIGN, &false_node, NULL TSRMLS_CC); SET_NODE(opline_qm_assign->result, result); } /* }}} */ @@ -5368,7 +5307,7 @@ void zend_compile_conditional(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */ zend_compile_expr(&true_node, true_ast TSRMLS_CC); opnum_qm_assign1 = get_next_op_number(CG(active_op_array)); - zend_emit_op(result, ZEND_QM_ASSIGN, &true_node, NULL TSRMLS_CC); + zend_emit_op_tmp(result, ZEND_QM_ASSIGN, &true_node, NULL TSRMLS_CC); opnum_jmp = zend_emit_jump(0 TSRMLS_CC); @@ -5384,6 +5323,30 @@ void zend_compile_conditional(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */ } /* }}} */ +void zend_compile_coalesce(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */ +{ + zend_ast *expr_ast = ast->child[0]; + zend_ast *default_ast = ast->child[1]; + + znode expr_node, default_node; + zend_op *opline; + uint32_t opnum; + + zend_compile_var(&expr_node, expr_ast, BP_VAR_IS TSRMLS_CC); + + opnum = get_next_op_number(CG(active_op_array)); + zend_emit_op_tmp(result, ZEND_COALESCE, &expr_node, NULL TSRMLS_CC); + + zend_compile_expr(&default_node, default_ast TSRMLS_CC); + + opline = zend_emit_op_tmp(NULL, ZEND_QM_ASSIGN, &default_node, NULL TSRMLS_CC); + SET_NODE(opline->result, result); + + opline = &CG(active_op_array)->opcodes[opnum]; + opline->op2.opline_num = get_next_op_number(CG(active_op_array)); +} +/* }}} */ + void zend_compile_print(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */ { zend_ast *expr_ast = ast->child[0]; @@ -5465,10 +5428,23 @@ void zend_compile_instanceof(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */ "instanceof expects an object instance, constant given"); } - opline = zend_compile_class_ref(&class_node, class_ast TSRMLS_CC); - opline->extended_value |= ZEND_FETCH_CLASS_NO_AUTOLOAD; + if (zend_is_const_default_class_ref(class_ast)) { + class_node.op_type = IS_CONST; + ZVAL_STR(&class_node.u.constant, zend_resolve_class_name_ast(class_ast TSRMLS_CC)); + } else { + opline = zend_compile_class_ref(&class_node, class_ast TSRMLS_CC); + opline->extended_value |= ZEND_FETCH_CLASS_NO_AUTOLOAD; + } + + opline = zend_emit_op_tmp(result, ZEND_INSTANCEOF, &obj_node, NULL TSRMLS_CC); - zend_emit_op_tmp(result, ZEND_INSTANCEOF, &obj_node, &class_node TSRMLS_CC); + if (class_node.op_type == IS_CONST) { + opline->op2_type = IS_CONST; + opline->op2.constant = zend_add_class_name_literal( + CG(active_op_array), Z_STR(class_node.u.constant) TSRMLS_CC); + } else { + SET_NODE(opline->op2, &class_node); + } } /* }}} */ @@ -5588,7 +5564,7 @@ void zend_compile_array(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */ { zend_ast_list *list = zend_ast_get_list(ast); zend_op *opline; - uint32_t i, opnum_init; + uint32_t i, opnum_init = -1; zend_bool packed = 1; if (zend_try_ct_eval_array(&result->u.constant, ast TSRMLS_CC)) { @@ -5596,8 +5572,6 @@ void zend_compile_array(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */ return; } - opnum_init = get_next_op_number(CG(active_op_array)); - for (i = 0; i < list->children; ++i) { zend_ast *elem_ast = list->child[i]; zend_ast *value_ast = elem_ast->child[0]; @@ -5620,6 +5594,7 @@ void zend_compile_array(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */ } if (i == 0) { + opnum_init = get_next_op_number(CG(active_op_array)); opline = zend_emit_op_tmp(result, ZEND_INIT_ARRAY, &value_node, key_node_ptr TSRMLS_CC); opline->extended_value = list->children << ZEND_ARRAY_SIZE_SHIFT; } else { @@ -5641,6 +5616,7 @@ void zend_compile_array(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */ /* Add a flag to INIT_ARRAY if we know this array cannot be packed */ if (!packed) { + ZEND_ASSERT(opnum_init != -1); opline = &CG(active_op_array)->opcodes[opnum_init]; opline->extended_value |= ZEND_ARRAY_NOT_PACKED; } @@ -5650,17 +5626,17 @@ void zend_compile_array(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */ void zend_compile_const(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */ { zend_ast *name_ast = ast->child[0]; - zend_string *orig_name = zend_ast_get_str(name_ast); - zend_bool is_fully_qualified; - zval resolved_name; zend_op *opline; - ZVAL_STR(&resolved_name, zend_resolve_const_name( - orig_name, name_ast->attr, &is_fully_qualified TSRMLS_CC)); + zend_bool is_fully_qualified; + zend_string *orig_name = zend_ast_get_str(name_ast); + zend_string *resolved_name = zend_resolve_const_name( + orig_name, name_ast->attr, &is_fully_qualified TSRMLS_CC); - if (zend_constant_ct_subst(result, &resolved_name, 1 TSRMLS_CC)) { - zval_dtor(&resolved_name); + if (zend_try_ct_eval_const(&result->u.constant, resolved_name, is_fully_qualified TSRMLS_CC)) { + result->op_type = IS_CONST; + zend_string_release(resolved_name); return; } @@ -5669,16 +5645,16 @@ void zend_compile_const(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */ if (is_fully_qualified) { opline->op2.constant = zend_add_const_name_literal( - CG(active_op_array), &resolved_name, 0 TSRMLS_CC); + CG(active_op_array), resolved_name, 0 TSRMLS_CC); } else { opline->extended_value = IS_CONSTANT_UNQUALIFIED; if (CG(current_namespace)) { opline->extended_value |= IS_CONSTANT_IN_NAMESPACE; opline->op2.constant = zend_add_const_name_literal( - CG(active_op_array), &resolved_name, 1 TSRMLS_CC); + CG(active_op_array), resolved_name, 1 TSRMLS_CC); } else { opline->op2.constant = zend_add_const_name_literal( - CG(active_op_array), &resolved_name, 0 TSRMLS_CC); + CG(active_op_array), resolved_name, 0 TSRMLS_CC); } } zend_alloc_cache_slot(opline->op2.constant TSRMLS_CC); @@ -5849,7 +5825,7 @@ void zend_compile_const_expr_class_const(zend_ast **ast_ptr TSRMLS_DC) /* {{{ */ zend_ast *ast = *ast_ptr; zend_ast *class_ast = ast->child[0]; zend_ast *const_ast = ast->child[1]; - zend_string *class_name = zend_ast_get_str(class_ast); + zend_string *class_name; zend_string *const_name = zend_ast_get_str(const_ast); zval result; int fetch_type; @@ -5859,6 +5835,7 @@ void zend_compile_const_expr_class_const(zend_ast **ast_ptr TSRMLS_DC) /* {{{ */ "Dynamic class names are not allowed in compile-time class constant references"); } + class_name = zend_ast_get_str(class_ast); fetch_type = zend_get_class_fetch_type(class_name); if (ZEND_FETCH_CLASS_STATIC == fetch_type) { @@ -5889,21 +5866,20 @@ void zend_compile_const_expr_const(zend_ast **ast_ptr TSRMLS_DC) /* {{{ */ { zend_ast *ast = *ast_ptr; zend_ast *name_ast = ast->child[0]; - zval *orig_name = zend_ast_get_zval(name_ast); + zend_string *orig_name = zend_ast_get_str(name_ast); zend_bool is_fully_qualified; - znode result; - zval resolved_name; + zval result, resolved_name; + ZVAL_STR(&resolved_name, zend_resolve_const_name( + orig_name, name_ast->attr, &is_fully_qualified TSRMLS_CC)); - if (zend_constant_ct_subst(&result, orig_name, 0 TSRMLS_CC)) { + if (zend_try_ct_eval_const(&result, Z_STR(resolved_name), is_fully_qualified TSRMLS_CC)) { + zend_string_release(Z_STR(resolved_name)); zend_ast_destroy(ast); - *ast_ptr = zend_ast_create_zval(&result.u.constant); + *ast_ptr = zend_ast_create_zval(&result); return; } - ZVAL_STR(&resolved_name, zend_resolve_const_name( - Z_STR_P(orig_name), name_ast->attr, &is_fully_qualified TSRMLS_CC)); - Z_TYPE_INFO(resolved_name) = IS_CONSTANT_EX; if (!is_fully_qualified) { Z_CONST_FLAGS(resolved_name) = IS_CONSTANT_UNQUALIFIED; @@ -6218,6 +6194,9 @@ void zend_compile_expr(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */ case ZEND_AST_CONDITIONAL: zend_compile_conditional(result, ast TSRMLS_CC); return; + case ZEND_AST_COALESCE: + zend_compile_coalesce(result, ast TSRMLS_CC); + return; case ZEND_AST_PRINT: zend_compile_print(result, ast TSRMLS_CC); return; @@ -6384,15 +6363,20 @@ void zend_eval_const_expr(zend_ast **ast_ptr TSRMLS_DC) /* {{{ */ return; } break; - case ZEND_AST_CONST: { - znode result_node; + case ZEND_AST_CONST: + { + zend_ast *name_ast = ast->child[0]; + zend_bool is_fully_qualified; + zend_string *resolved_name = zend_resolve_const_name( + zend_ast_get_str(name_ast), name_ast->attr, &is_fully_qualified TSRMLS_CC); - if (!zend_constant_ct_subst(&result_node, zend_ast_get_zval(ast->child[0]), 0 TSRMLS_CC)) { + if (!zend_try_ct_eval_const(&result, resolved_name, is_fully_qualified TSRMLS_CC)) { + zend_string_release(resolved_name); return; } - zend_ast_destroy(ast); - *ast_ptr = zend_ast_create_zval(&result_node.u.constant); - return; + + zend_string_release(resolved_name); + break; } default: return; diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 333be9cc52..bc9b88227f 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -59,11 +59,9 @@ typedef union _znode_op { uint32_t constant; uint32_t var; uint32_t num; - zend_ulong hash; uint32_t opline_num; /* Needs to be signed */ zend_op *jmp_addr; zval *zv; - void *ptr; /* Used for passing pointers from the compile to execution phase, currently used for traits */ } znode_op; typedef struct _znode { /* used only during compilation */ @@ -100,8 +98,6 @@ void zend_compile_var(znode *node, zend_ast *ast, uint32_t type TSRMLS_DC); void zend_eval_const_expr(zend_ast **ast_ptr TSRMLS_DC); void zend_const_expr_to_zval(zval *result, zend_ast *ast TSRMLS_DC); -typedef struct _zend_execute_data zend_execute_data; - #define ZEND_OPCODE_HANDLER_ARGS zend_execute_data *execute_data TSRMLS_DC #define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU execute_data TSRMLS_CC @@ -223,6 +219,9 @@ typedef struct _zend_try_catch_element { /* op_array has finally blocks */ #define ZEND_ACC_HAS_FINALLY_BLOCK 0x20000000 +/* internal function is allocated at arena */ +#define ZEND_ACC_ARENA_ALLOCATED 0x20000000 + #define ZEND_CE_IS_TRAIT(ce) (((ce)->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) char *zend_visibility_string(uint32_t fn_flags); @@ -359,23 +358,29 @@ struct _zend_execute_data { zend_execute_data *call; /* current call */ void **run_time_cache; zend_function *func; /* executed op_array */ - uint32_t num_args; - zend_uchar flags; - zend_uchar frame_kind; + zval This; zend_class_entry *called_scope; - zend_object *object; - zend_execute_data *prev_nested_call; zend_execute_data *prev_execute_data; + uint32_t frame_info; + uint32_t num_args; zval *return_value; zend_class_entry *scope; /* function scope (self) */ zend_array *symbol_table; const zend_op *fast_ret; /* used by FAST_CALL/FAST_RET (finally keyword) */ zend_object *delayed_exception; - zval old_error_reporting; + uint32_t silence_op_num; + uint32_t old_error_reporting; }; -#define ZEND_CALL_CTOR (1 << 0) -#define ZEND_CALL_CTOR_RESULT_UNUSED (1 << 1) +#define VM_FRAME_KIND_MASK 0x000000ff +#define VM_FRAME_FLAGS_MASK 0xffffff00 + +#define ZEND_CALL_CTOR (1 << 8) +#define ZEND_CALL_CTOR_RESULT_UNUSED (1 << 9) + +#define VM_FRAME_INFO(kind, flags) ((kind) | (flags)) +#define VM_FRAME_KIND(info) ((info) & VM_FRAME_KIND_MASK) +#define VM_FRAME_FLAGS(info) ((info) & VM_FRAME_FLAGS_MASK) #define ZEND_CALL_FRAME_SLOT \ ((ZEND_MM_ALIGNED_SIZE(sizeof(zend_execute_data)) + ZEND_MM_ALIGNED_SIZE(sizeof(zval)) - 1) / ZEND_MM_ALIGNED_SIZE(sizeof(zval))) @@ -383,7 +388,7 @@ struct _zend_execute_data { #define ZEND_CALL_ARG(call, n) \ (((zval*)(call)) + ((n) + (ZEND_CALL_FRAME_SLOT - 1))) -#define EX(element) execute_data.element +#define EX(element) ((execute_data)->element) #define EX_VAR_2(ex, n) ((zval*)(((char*)(ex)) + ((int)(n)))) #define EX_VAR_NUM_2(ex, n) (((zval*)(ex)) + (ZEND_CALL_FRAME_SLOT + ((int)(n)))) @@ -614,8 +619,6 @@ int zend_add_literal(zend_op_array *op_array, zval *zv TSRMLS_DC); #define ZEND_FETCH_TYPE_MASK 0x70000000 #define ZEND_FETCH_STANDARD 0x00000000 -#define ZEND_FETCH_ADD_LOCK 0x08000000 -#define ZEND_FETCH_MAKE_REF 0x04000000 #define ZEND_ISSET 0x02000000 #define ZEND_ISEMPTY 0x01000000 diff --git a/Zend/zend_constants.c b/Zend/zend_constants.c index 164901f898..61cc49e5c5 100644 --- a/Zend/zend_constants.c +++ b/Zend/zend_constants.c @@ -161,7 +161,7 @@ void clean_non_persistent_constants(TSRMLS_D) } } -ZEND_API void zend_register_null_constant(const char *name, uint name_len, int flags, int module_number TSRMLS_DC) +ZEND_API void zend_register_null_constant(const char *name, size_t name_len, int flags, int module_number TSRMLS_DC) { zend_constant c; @@ -172,7 +172,7 @@ ZEND_API void zend_register_null_constant(const char *name, uint name_len, int f zend_register_constant(&c TSRMLS_CC); } -ZEND_API void zend_register_bool_constant(const char *name, uint name_len, zend_bool bval, int flags, int module_number TSRMLS_DC) +ZEND_API void zend_register_bool_constant(const char *name, size_t name_len, zend_bool bval, int flags, int module_number TSRMLS_DC) { zend_constant c; @@ -183,7 +183,7 @@ ZEND_API void zend_register_bool_constant(const char *name, uint name_len, zend_ zend_register_constant(&c TSRMLS_CC); } -ZEND_API void zend_register_long_constant(const char *name, uint name_len, zend_long lval, int flags, int module_number TSRMLS_DC) +ZEND_API void zend_register_long_constant(const char *name, size_t name_len, zend_long lval, int flags, int module_number TSRMLS_DC) { zend_constant c; @@ -195,7 +195,7 @@ ZEND_API void zend_register_long_constant(const char *name, uint name_len, zend_ } -ZEND_API void zend_register_double_constant(const char *name, uint name_len, double dval, int flags, int module_number TSRMLS_DC) +ZEND_API void zend_register_double_constant(const char *name, size_t name_len, double dval, int flags, int module_number TSRMLS_DC) { zend_constant c; @@ -207,7 +207,7 @@ ZEND_API void zend_register_double_constant(const char *name, uint name_len, dou } -ZEND_API void zend_register_stringl_constant(const char *name, uint name_len, char *strval, uint strlen, int flags, int module_number TSRMLS_DC) +ZEND_API void zend_register_stringl_constant(const char *name, size_t name_len, char *strval, size_t strlen, int flags, int module_number TSRMLS_DC) { zend_constant c; @@ -219,12 +219,12 @@ ZEND_API void zend_register_stringl_constant(const char *name, uint name_len, ch } -ZEND_API void zend_register_string_constant(const char *name, uint name_len, char *strval, int flags, int module_number TSRMLS_DC) +ZEND_API void zend_register_string_constant(const char *name, size_t name_len, char *strval, int flags, int module_number TSRMLS_DC) { zend_register_stringl_constant(name, name_len, strval, strlen(strval), flags, module_number TSRMLS_CC); } -static zend_constant *zend_get_special_constant(const char *name, uint name_len TSRMLS_DC) +static zend_constant *zend_get_special_constant(const char *name, size_t name_len TSRMLS_DC) { zend_constant *c; static char haltoff[] = "__COMPILER_HALT_OFFSET__"; @@ -236,7 +236,7 @@ static zend_constant *zend_get_special_constant(const char *name, uint name_len /* Returned constants may be cached, so they have to be stored */ if (EG(scope) && EG(scope)->name) { - int const_name_len; + size_t const_name_len; zend_string *const_name; const_name_len = sizeof("\0__CLASS__") + EG(scope)->name->len; @@ -265,7 +265,7 @@ static zend_constant *zend_get_special_constant(const char *name, uint name_len !memcmp(name, "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__")-1)) { const char *cfilename; zend_string *haltname; - int clen; + size_t clen; cfilename = zend_get_executed_filename(TSRMLS_C); clen = strlen(cfilename); @@ -281,7 +281,7 @@ static zend_constant *zend_get_special_constant(const char *name, uint name_len } -ZEND_API zval *zend_get_constant_str(const char *name, uint name_len TSRMLS_DC) +ZEND_API zval *zend_get_constant_str(const char *name, size_t name_len TSRMLS_DC) { zend_constant *c; ALLOCA_FLAG(use_heap) @@ -330,7 +330,7 @@ ZEND_API zval *zend_get_constant_ex(zend_string *cname, zend_class_entry *scope, zend_class_entry *ce = NULL; zend_string *class_name; const char *name = cname->val; - uint name_len = cname->len; + size_t name_len = cname->len; /* Skip leading \\ */ if (name[0] == '\\') { @@ -342,7 +342,7 @@ ZEND_API zval *zend_get_constant_ex(zend_string *cname, zend_class_entry *scope, if ((colon = zend_memrchr(name, ':', name_len)) && colon > name && (*(colon - 1) == ':')) { int class_name_len = colon - name - 1; - int const_name_len = name_len - class_name_len - 2; + size_t const_name_len = name_len - class_name_len - 2; zend_string *constant_name = zend_string_init(colon + 1, const_name_len, 0); char *lcname; zval *ret_constant = NULL; @@ -408,10 +408,10 @@ ZEND_API zval *zend_get_constant_ex(zend_string *cname, zend_class_entry *scope, if ((colon = zend_memrchr(name, '\\', name_len)) != NULL) { /* compound constant name */ int prefix_len = colon - name; - int const_name_len = name_len - prefix_len - 1; + size_t const_name_len = name_len - prefix_len - 1; const char *constant_name = colon + 1; char *lcname; - int lcname_len; + size_t lcname_len; ALLOCA_FLAG(use_heap) lcname_len = prefix_len + 1 + const_name_len; diff --git a/Zend/zend_constants.h b/Zend/zend_constants.h index d81476f3f4..6d5542e1ec 100644 --- a/Zend/zend_constants.h +++ b/Zend/zend_constants.h @@ -66,14 +66,14 @@ int zend_shutdown_constants(TSRMLS_D); void zend_register_standard_constants(TSRMLS_D); void clean_non_persistent_constants(TSRMLS_D); ZEND_API zval *zend_get_constant(zend_string *name TSRMLS_DC); -ZEND_API zval *zend_get_constant_str(const char *name, uint name_len TSRMLS_DC); +ZEND_API zval *zend_get_constant_str(const char *name, size_t name_len TSRMLS_DC); ZEND_API zval *zend_get_constant_ex(zend_string *name, zend_class_entry *scope, zend_ulong flags TSRMLS_DC); -ZEND_API void zend_register_bool_constant(const char *name, uint name_len, zend_bool bval, int flags, int module_number TSRMLS_DC); -ZEND_API void zend_register_null_constant(const char *name, uint name_len, int flags, int module_number TSRMLS_DC); -ZEND_API void zend_register_long_constant(const char *name, uint name_len, zend_long lval, int flags, int module_number TSRMLS_DC); -ZEND_API void zend_register_double_constant(const char *name, uint name_len, double dval, int flags, int module_number TSRMLS_DC); -ZEND_API void zend_register_string_constant(const char *name, uint name_len, char *strval, int flags, int module_number TSRMLS_DC); -ZEND_API void zend_register_stringl_constant(const char *name, uint name_len, char *strval, uint strlen, int flags, int module_number TSRMLS_DC); +ZEND_API void zend_register_bool_constant(const char *name, size_t name_len, zend_bool bval, int flags, int module_number TSRMLS_DC); +ZEND_API void zend_register_null_constant(const char *name, size_t name_len, int flags, int module_number TSRMLS_DC); +ZEND_API void zend_register_long_constant(const char *name, size_t name_len, zend_long lval, int flags, int module_number TSRMLS_DC); +ZEND_API void zend_register_double_constant(const char *name, size_t name_len, double dval, int flags, int module_number TSRMLS_DC); +ZEND_API void zend_register_string_constant(const char *name, size_t name_len, char *strval, int flags, int module_number TSRMLS_DC); +ZEND_API void zend_register_stringl_constant(const char *name, size_t name_len, char *strval, size_t strlen, int flags, int module_number TSRMLS_DC); ZEND_API int zend_register_constant(zend_constant *c TSRMLS_DC); void zend_copy_constants(HashTable *target, HashTable *sourc); zend_constant *zend_quick_get_constant(const zval *key, zend_ulong flags TSRMLS_DC); diff --git a/Zend/zend_dynamic_array.c b/Zend/zend_dynamic_array.c deleted file mode 100644 index db81b00a73..0000000000 --- a/Zend/zend_dynamic_array.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | Zend Engine | - +----------------------------------------------------------------------+ - | Copyright (c) 1998-2014 Zend Technologies Ltd. (http://www.zend.com) | - +----------------------------------------------------------------------+ - | This source file is subject to version 2.00 of the Zend license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.zend.com/license/2_00.txt. | - | If you did not receive a copy of the Zend license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@zend.com so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Authors: Andi Gutmans <andi@zend.com> | - | Zeev Suraski <zeev@zend.com> | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#include "zend.h" - -typedef struct _dynamic_array { - char *array; - unsigned int element_size; - unsigned int current; - unsigned int allocated; -} dynamic_array; - -ZEND_API int zend_dynamic_array_init(dynamic_array *da, unsigned int element_size, unsigned int size) -{ - da->element_size = element_size; - da->allocated = size; - da->current = 0; - da->array = (char *) emalloc(size*element_size); - if (da->array == NULL) { - return 1; - } - return 0; -} - -ZEND_API void *zend_dynamic_array_push(dynamic_array *da) -{ - if (da->current == da->allocated) { - da->allocated *= 2; - da->array = (char *) erealloc(da->array, da->allocated*da->element_size); - } - return (void *)(da->array+(da->current++)*da->element_size); -} - -ZEND_API void *zend_dynamic_array_pop(dynamic_array *da) -{ - return (void *)(da->array+(--(da->current))*da->element_size); - -} - -ZEND_API void *zend_dynamic_array_get_element(dynamic_array *da, unsigned int index) -{ - if (index >= da->current) { - return NULL; - } - return (void *)(da->array+index*da->element_size); -} - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * indent-tabs-mode: t - * End: - */ diff --git a/Zend/zend_dynamic_array.h b/Zend/zend_dynamic_array.h deleted file mode 100644 index e69eb18768..0000000000 --- a/Zend/zend_dynamic_array.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | Zend Engine | - +----------------------------------------------------------------------+ - | Copyright (c) 1998-2014 Zend Technologies Ltd. (http://www.zend.com) | - +----------------------------------------------------------------------+ - | This source file is subject to version 2.00 of the Zend license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.zend.com/license/2_00.txt. | - | If you did not receive a copy of the Zend license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@zend.com so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Authors: Andi Gutmans <andi@zend.com> | - | Zeev Suraski <zeev@zend.com> | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#ifndef ZEND_DYNAMIC_ARRAY_H -#define ZEND_DYNAMIC_ARRAY_H - -typedef struct _dynamic_array { - char *array; - unsigned int element_size; - unsigned int last_used; - unsigned int allocated; -} dynamic_array; - -BEGIN_EXTERN_C() -ZEND_API int zend_dynamic_array_init(dynamic_array *da, unsigned int element_size, unsigned int size); -ZEND_API void *zend_dynamic_array_push(dynamic_array *da); -ZEND_API void *zend_dynamic_array_pop(dynamic_array *da); -ZEND_API void *zend_dynamic_array_get_element(dynamic_array *da, unsigned int index); -END_EXTERN_C() - -#endif /* ZEND_DYNAMIC_ARRAY_H */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * indent-tabs-mode: t - * End: - */ diff --git a/Zend/zend_exceptions.c b/Zend/zend_exceptions.c index 999b6d790e..4159a46d3c 100644 --- a/Zend/zend_exceptions.c +++ b/Zend/zend_exceptions.c @@ -85,15 +85,12 @@ void zend_exception_restore(TSRMLS_D) /* {{{ */ } /* }}} */ -void zend_throw_exception_internal(zval *exception TSRMLS_DC) /* {{{ */ +ZEND_API void zend_throw_exception_internal(zval *exception TSRMLS_DC) /* {{{ */ { #ifdef HAVE_DTRACE if (DTRACE_EXCEPTION_THROWN_ENABLED()) { - zend_string *classname; - if (exception != NULL) { - classname = zend_get_object_classname(Z_OBJ_P(exception) TSRMLS_CC); - DTRACE_EXCEPTION_THROWN(classname->val); + DTRACE_EXCEPTION_THROWN(Z_OBJ_P(exception)->ce->name->val); } else { DTRACE_EXCEPTION_THROWN(NULL); } @@ -266,14 +263,10 @@ ZEND_METHOD(error_exception, __construct) return; \ } -static void _default_exception_get_entry(zval *object, char *name, int name_len, zval *return_value TSRMLS_DC) /* {{{ */ -{ - zval *value; - - value = zend_read_property(default_exception_ce, object, name, name_len, 0 TSRMLS_CC); - ZVAL_COPY(return_value, value); -} -/* }}} */ +#define GET_PROPERTY(object, name) \ + zend_read_property(default_exception_ce, (object), name, sizeof(name) - 1, 0 TSRMLS_CC) +#define GET_PROPERTY_SILENT(object, name) \ + zend_read_property(default_exception_ce, (object), name, sizeof(name) - 1, 1 TSRMLS_CC) /* {{{ proto string Exception::getFile() Get the file in which the exception occurred */ @@ -281,7 +274,7 @@ ZEND_METHOD(exception, getFile) { DEFAULT_0_PARAMS; - _default_exception_get_entry(getThis(), "file", sizeof("file")-1, return_value TSRMLS_CC); + ZVAL_COPY(return_value, GET_PROPERTY(getThis(), "file")); } /* }}} */ @@ -291,7 +284,7 @@ ZEND_METHOD(exception, getLine) { DEFAULT_0_PARAMS; - _default_exception_get_entry(getThis(), "line", sizeof("line")-1, return_value TSRMLS_CC); + ZVAL_COPY(return_value, GET_PROPERTY(getThis(), "line")); } /* }}} */ @@ -301,7 +294,7 @@ ZEND_METHOD(exception, getMessage) { DEFAULT_0_PARAMS; - _default_exception_get_entry(getThis(), "message", sizeof("message")-1, return_value TSRMLS_CC); + ZVAL_COPY(return_value, GET_PROPERTY(getThis(), "message")); } /* }}} */ @@ -311,7 +304,7 @@ ZEND_METHOD(exception, getCode) { DEFAULT_0_PARAMS; - _default_exception_get_entry(getThis(), "code", sizeof("code")-1, return_value TSRMLS_CC); + ZVAL_COPY(return_value, GET_PROPERTY(getThis(), "code")); } /* }}} */ @@ -321,7 +314,7 @@ ZEND_METHOD(exception, getTrace) { DEFAULT_0_PARAMS; - _default_exception_get_entry(getThis(), "trace", sizeof("trace")-1, return_value TSRMLS_CC); + ZVAL_COPY(return_value, GET_PROPERTY(getThis(), "trace")); } /* }}} */ @@ -331,7 +324,7 @@ ZEND_METHOD(error_exception, getSeverity) { DEFAULT_0_PARAMS; - _default_exception_get_entry(getThis(), "severity", sizeof("severity")-1, return_value TSRMLS_CC); + ZVAL_COPY(return_value, GET_PROPERTY(getThis(), "severity")); } /* }}} */ @@ -407,7 +400,7 @@ static void smart_str_append_escaped(smart_str *str, const char *s, size_t l) { static void _build_trace_args(zval *arg, smart_str *str TSRMLS_DC) /* {{{ */ { - /* the trivial way would be to do: + /* the trivial way would be to do * convert_to_string_ex(arg); * append it and kill the now tmp arg. * but that could cause some E_NOTICE and also damn long lines. @@ -456,7 +449,7 @@ static void _build_trace_args(zval *arg, smart_str *str TSRMLS_DC) /* {{{ */ break; case IS_OBJECT: smart_str_appends(str, "Object("); - smart_str_append(str, zend_get_object_classname(Z_OBJ_P(arg) TSRMLS_CC)); + smart_str_append(str, Z_OBJCE_P(arg)->name); smart_str_appends(str, "), "); break; } @@ -556,12 +549,9 @@ ZEND_METHOD(exception, getTraceAsString) Return previous Exception or NULL. */ ZEND_METHOD(exception, getPrevious) { - zval *previous; - DEFAULT_0_PARAMS; - previous = zend_read_property(default_exception_ce, getThis(), "previous", sizeof("previous")-1, 1 TSRMLS_CC); - RETURN_ZVAL(previous, 1, 0); + ZVAL_COPY(return_value, GET_PROPERTY_SILENT(getThis(), "previous")); } /* }}} */ size_t zend_spprintf(char **message, size_t max_len, const char *format, ...) /* {{{ */ @@ -592,8 +582,8 @@ zend_string *zend_strpprintf(size_t max_len, const char *format, ...) /* {{{ */ Obtain the string representation of the Exception object */ ZEND_METHOD(exception, __toString) { - zval message, file, line, trace, *exception; - zend_string *str, *prev_str; + zval trace, *exception; + zend_string *str; zend_fcall_info fci; zval fname; @@ -605,14 +595,10 @@ ZEND_METHOD(exception, __toString) ZVAL_STRINGL(&fname, "gettraceasstring", sizeof("gettraceasstring")-1); while (exception && Z_TYPE_P(exception) == IS_OBJECT) { - prev_str = str; - _default_exception_get_entry(exception, "message", sizeof("message")-1, &message TSRMLS_CC); - _default_exception_get_entry(exception, "file", sizeof("file")-1, &file TSRMLS_CC); - _default_exception_get_entry(exception, "line", sizeof("line")-1, &line TSRMLS_CC); - - convert_to_string_ex(&message); - convert_to_string_ex(&file); - convert_to_long_ex(&line); + zend_string *prev_str = str; + zend_string *message = zval_get_string(GET_PROPERTY(exception, "message")); + zend_string *file = zval_get_string(GET_PROPERTY(exception, "file")); + zend_long line = zval_get_long(GET_PROPERTY(exception, "line")); fci.size = sizeof(fci); fci.function_table = &Z_OBJCE_P(exception)->function_table; @@ -631,26 +617,26 @@ ZEND_METHOD(exception, __toString) ZVAL_UNDEF(&trace); } - if (Z_STRLEN(message) > 0) { - str = zend_strpprintf(0, "exception '%s' with message '%s' in %s:%ld\nStack trace:\n%s%s%s", - Z_OBJCE_P(exception)->name->val, Z_STRVAL(message), Z_STRVAL(file), Z_LVAL(line), + if (message->len > 0) { + str = zend_strpprintf(0, "exception '%s' with message '%s' in %s:" ZEND_LONG_FMT + "\nStack trace:\n%s%s%s", + Z_OBJCE_P(exception)->name->val, message->val, file->val, line, (Z_TYPE(trace) == IS_STRING && Z_STRLEN(trace)) ? Z_STRVAL(trace) : "#0 {main}\n", prev_str->len ? "\n\nNext " : "", prev_str->val); } else { - str = zend_strpprintf(0, "exception '%s' in %s:%ld\nStack trace:\n%s%s%s", - Z_OBJCE_P(exception)->name->val, Z_STRVAL(file), Z_LVAL(line), + str = zend_strpprintf(0, "exception '%s' in %s:" ZEND_LONG_FMT + "\nStack trace:\n%s%s%s", + Z_OBJCE_P(exception)->name->val, file->val, line, (Z_TYPE(trace) == IS_STRING && Z_STRLEN(trace)) ? Z_STRVAL(trace) : "#0 {main}\n", prev_str->len ? "\n\nNext " : "", prev_str->val); } - zend_string_release(prev_str); - zval_dtor(&message); - zval_dtor(&file); - zval_dtor(&line); - - exception = zend_read_property(default_exception_ce, exception, "previous", sizeof("previous")-1, 0 TSRMLS_CC); + zend_string_release(prev_str); + zend_string_release(message); + zend_string_release(file); zval_ptr_dtor(&trace); + exception = GET_PROPERTY(exception, "previous"); } zval_dtor(&fname); @@ -816,7 +802,9 @@ ZEND_API void zend_exception_error(zend_object *ex, int severity TSRMLS_DC) /* { ZVAL_OBJ(&exception, ex); ce_exception = Z_OBJCE(exception); if (instanceof_function(ce_exception, default_exception_ce TSRMLS_CC)) { - zval tmp, *str, *file, *line; + zval tmp; + zend_string *str, *file = NULL; + zend_long line = 0; EG(exception) = NULL; @@ -836,28 +824,28 @@ ZEND_API void zend_exception_error(zend_object *ex, int severity TSRMLS_DC) /* { ZVAL_OBJ(&zv, EG(exception)); /* do the best we can to inform about the inner exception */ if (instanceof_function(ce_exception, default_exception_ce TSRMLS_CC)) { - file = zend_read_property(default_exception_ce, &zv, "file", sizeof("file")-1, 1 TSRMLS_CC); - line = zend_read_property(default_exception_ce, &zv, "line", sizeof("line")-1, 1 TSRMLS_CC); + file = zval_get_string(GET_PROPERTY_SILENT(&zv, "file")); + line = zval_get_long(GET_PROPERTY_SILENT(&zv, "line")); + } - convert_to_string_ex(file); - file = (Z_STRLEN_P(file) > 0) ? file : NULL; - line = (Z_TYPE_P(line) == IS_LONG) ? line : NULL; - } else { - file = NULL; - line = NULL; + zend_error_va(E_WARNING, (file && file->len > 0) ? file->val : NULL, line, + "Uncaught %s in exception handling during call to %s::__tostring()", + Z_OBJCE(zv)->name->val, ce_exception->name->val); + + if (file) { + zend_string_release(file); } - zend_error_va(E_WARNING, file ? Z_STRVAL_P(file) : NULL, line ? Z_LVAL_P(line) : 0, "Uncaught %s in exception handling during call to %s::__tostring()", Z_OBJCE(zv)->name->val, ce_exception->name->val); } - str = zend_read_property(default_exception_ce, &exception, "string", sizeof("string")-1, 1 TSRMLS_CC); - file = zend_read_property(default_exception_ce, &exception, "file", sizeof("file")-1, 1 TSRMLS_CC); - line = zend_read_property(default_exception_ce, &exception, "line", sizeof("line")-1, 1 TSRMLS_CC); + str = zval_get_string(GET_PROPERTY_SILENT(&exception, "string")); + file = zval_get_string(GET_PROPERTY_SILENT(&exception, "file")); + line = zval_get_long(GET_PROPERTY_SILENT(&exception, "line")); - convert_to_string_ex(str); - convert_to_string_ex(file); - convert_to_long_ex(line); + zend_error_va(severity, (file && file->len > 0) ? file->val : NULL, line, + "Uncaught %s\n thrown", str->val); - zend_error_va(severity, (Z_STRLEN_P(file) > 0) ? Z_STRVAL_P(file) : NULL, Z_LVAL_P(line), "Uncaught %s\n thrown", Z_STRVAL_P(str)); + zend_string_release(str); + zend_string_release(file); } else { zend_error(severity, "Uncaught exception '%s'", ce_exception->name->val); } diff --git a/Zend/zend_exceptions.h b/Zend/zend_exceptions.h index 5aa6544e5d..3118ce1053 100644 --- a/Zend/zend_exceptions.h +++ b/Zend/zend_exceptions.h @@ -30,7 +30,7 @@ ZEND_API void zend_exception_set_previous(zend_object *exception, zend_object *a ZEND_API void zend_exception_save(TSRMLS_D); ZEND_API void zend_exception_restore(TSRMLS_D); -void zend_throw_exception_internal(zval *exception TSRMLS_DC); +ZEND_API void zend_throw_exception_internal(zval *exception TSRMLS_DC); void zend_register_default_exception(TSRMLS_D); diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 031ba54d69..61a605971e 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -100,15 +100,6 @@ static const zend_internal_function zend_pass_function = { #define FREE_OP(should_free) \ if (should_free.var) { \ - if ((zend_uintptr_t)should_free.var & 1L) { \ - zval_dtor((zval*)((zend_uintptr_t)should_free.var & ~1L)); \ - } else { \ - zval_ptr_dtor_nogc(should_free.var); \ - } \ - } - -#define FREE_OP_IF_VAR(should_free) \ - if (should_free.var != NULL && (((zend_uintptr_t)should_free.var & 1L) == 0)) { \ zval_ptr_dtor_nogc(should_free.var); \ } @@ -117,10 +108,6 @@ static const zend_internal_function zend_pass_function = { zval_ptr_dtor_nogc(should_free.var); \ } -#define TMP_FREE(z) (zval*)(((zend_uintptr_t)(z)) | 1L) - -#define IS_TMP_FREE(should_free) ((zend_uintptr_t)should_free.var & 1L) - /* End of zend_execute_locks.h */ #define CV_DEF_OF(i) (EX(func)->op_array.vars[i]) @@ -136,8 +123,60 @@ static const zend_internal_function zend_pass_function = { #define DECODE_CTOR(ce) \ ((zend_class_entry*)(((zend_uintptr_t)(ce)) & ~(CTOR_CALL_BIT|CTOR_USED_BIT))) -#undef EX -#define EX(element) execute_data->element +#define ZEND_VM_STACK_PAGE_SLOTS (16 * 1024) /* should be a power of 2 */ + +#define ZEND_VM_STACK_PAGE_SIZE (ZEND_VM_STACK_PAGE_SLOTS * sizeof(zval)) + +#define ZEND_VM_STACK_FREE_PAGE_SIZE \ + ((ZEND_VM_STACK_PAGE_SLOTS - ZEND_VM_STACK_HEADER_SLOTS) * sizeof(zval)) + +#define ZEND_VM_STACK_PAGE_ALIGNED_SIZE(size) \ + (((size) + (ZEND_VM_STACK_FREE_PAGE_SIZE - 1)) & ~ZEND_VM_STACK_PAGE_SIZE) + +static zend_always_inline zend_vm_stack zend_vm_stack_new_page(size_t size, zend_vm_stack prev) { + zend_vm_stack page = (zend_vm_stack)emalloc(size); + + page->top = ZEND_VM_STACK_ELEMETS(page); + page->end = (zval*)((char*)page + size); + page->prev = prev; + return page; +} + +ZEND_API void zend_vm_stack_init(TSRMLS_D) +{ + EG(vm_stack) = zend_vm_stack_new_page(ZEND_VM_STACK_PAGE_SIZE, NULL); + EG(vm_stack)->top++; + EG(vm_stack_top) = EG(vm_stack)->top; + EG(vm_stack_end) = EG(vm_stack)->end; +} + +ZEND_API void zend_vm_stack_destroy(TSRMLS_D) +{ + zend_vm_stack stack = EG(vm_stack); + + while (stack != NULL) { + zend_vm_stack p = stack->prev; + efree(stack); + stack = p; + } +} + +ZEND_API void* zend_vm_stack_extend(size_t size TSRMLS_DC) +{ + zend_vm_stack stack; + void *ptr; + + stack = EG(vm_stack); + stack->top = EG(vm_stack_top); + EG(vm_stack) = stack = zend_vm_stack_new_page( + EXPECTED(size < ZEND_VM_STACK_FREE_PAGE_SIZE) ? + ZEND_VM_STACK_PAGE_SIZE : ZEND_VM_STACK_PAGE_ALIGNED_SIZE(size), + stack); + ptr = stack->top; + EG(vm_stack_top) = (void*)(((char*)ptr) + size); + EG(vm_stack_end) = stack->end; + return ptr; +} ZEND_API zval* zend_get_compiled_variable_value(const zend_execute_data *execute_data, uint32_t var) { @@ -362,7 +401,7 @@ static inline zval *_get_zval_ptr(int op_type, const znode_op *node, const zend_ break; case IS_TMP_VAR: ret = EX_VAR(node->var); - should_free->var = TMP_FREE(ret); + should_free->var = ret; return ret; break; case IS_VAR: @@ -392,7 +431,7 @@ static inline zval *_get_zval_ptr_deref(int op_type, const znode_op *node, const break; case IS_TMP_VAR: ret = EX_VAR(node->var); - should_free->var = TMP_FREE(ret); + should_free->var = ret; return ret; break; case IS_VAR: @@ -439,22 +478,22 @@ static inline zval *_get_zval_ptr_ptr(int op_type, const znode_op *node, const z } } -static zend_always_inline zval *_get_obj_zval_ptr_unused(TSRMLS_D) +static zend_always_inline zval *_get_obj_zval_ptr_unused(zend_execute_data *execute_data TSRMLS_DC) { - if (EXPECTED(Z_OBJ(EG(This)) != NULL)) { - return &EG(This); + if (EXPECTED(Z_OBJ(EX(This)) != NULL)) { + return &EX(This); } else { zend_error_noreturn(E_ERROR, "Using $this when not in object context"); return NULL; } } -static inline zval *_get_obj_zval_ptr(int op_type, znode_op *op, const zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC) +static inline zval *_get_obj_zval_ptr(int op_type, znode_op *op, zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC) { if (op_type == IS_UNUSED) { - if (EXPECTED(Z_OBJ(EG(This)) != NULL)) { + if (EXPECTED(Z_OBJ(EX(This)) != NULL)) { should_free->var = NULL; - return &EG(This); + return &EX(This); } else { zend_error_noreturn(E_ERROR, "Using $this when not in object context"); } @@ -462,12 +501,12 @@ static inline zval *_get_obj_zval_ptr(int op_type, znode_op *op, const zend_exec return get_zval_ptr(op_type, op, execute_data, should_free, type); } -static inline zval *_get_obj_zval_ptr_ptr(int op_type, const znode_op *node, const zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC) +static inline zval *_get_obj_zval_ptr_ptr(int op_type, const znode_op *node, zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC) { if (op_type == IS_UNUSED) { - if (EXPECTED(Z_OBJ(EG(This)) != NULL)) { + if (EXPECTED(Z_OBJ(EX(This)) != NULL)) { should_free->var = NULL; - return &EG(This); + return &EX(This); } else { zend_error_noreturn(E_ERROR, "Using $this when not in object context"); } @@ -478,10 +517,13 @@ static inline zval *_get_obj_zval_ptr_ptr(int op_type, const znode_op *node, con static inline void zend_assign_to_variable_reference(zval *variable_ptr, zval *value_ptr TSRMLS_DC) { if (EXPECTED(variable_ptr != value_ptr)) { + zend_reference *ref; ZVAL_MAKE_REF(value_ptr); Z_ADDREF_P(value_ptr); + ref = Z_REF_P(value_ptr); + zval_ptr_dtor(variable_ptr); - ZVAL_REF(variable_ptr, Z_REF_P(value_ptr)); + ZVAL_REF(variable_ptr, ref); } else { ZVAL_MAKE_REF(variable_ptr); } @@ -505,13 +547,13 @@ static inline zval* make_real_object(zval *object_ptr TSRMLS_DC) return object; } -ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, zend_ulong fetch_type, char **class_name, zend_class_entry **pce TSRMLS_DC) +ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, char **class_name, zend_class_entry **pce TSRMLS_DC) { zend_string *key; ALLOCA_FLAG(use_heap); STR_ALLOCA_INIT(key, cur_arg_info->class_name, cur_arg_info->class_name_len, use_heap); - *pce = zend_fetch_class(key, (fetch_type | ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD) TSRMLS_CC); + *pce = zend_fetch_class(key, (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD) TSRMLS_CC); STR_ALLOCA_FREE(key, use_heap); *class_name = (*pce) ? (*pce)->name->val : (char*)cur_arg_info->class_name; @@ -554,7 +596,7 @@ ZEND_API void zend_verify_arg_error(int error_type, const zend_function *zf, uin } } -static void zend_verify_arg_type(zend_function *zf, uint32_t arg_num, zval *arg, zend_ulong fetch_type TSRMLS_DC) +static void zend_verify_arg_type(zend_function *zf, uint32_t arg_num, zval *arg TSRMLS_DC) { zend_arg_info *cur_arg_info; char *need_msg; @@ -577,12 +619,12 @@ static void zend_verify_arg_type(zend_function *zf, uint32_t arg_num, zval *arg, ZVAL_DEREF(arg); if (Z_TYPE_P(arg) == IS_OBJECT) { - need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC); + need_msg = zend_verify_arg_class_kind(cur_arg_info, &class_name, &ce TSRMLS_CC); if (!ce || !instanceof_function(Z_OBJCE_P(arg), ce TSRMLS_CC)) { zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, "instance of ", Z_OBJCE_P(arg)->name->val, arg TSRMLS_CC); } } else if (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null) { - need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC); + need_msg = zend_verify_arg_class_kind(cur_arg_info, &class_name, &ce TSRMLS_CC); zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, zend_zval_type_name(arg), "", arg TSRMLS_CC); } } else if (cur_arg_info->type_hint) { @@ -603,7 +645,7 @@ static void zend_verify_arg_type(zend_function *zf, uint32_t arg_num, zval *arg, } } -static inline int zend_verify_missing_arg_type(zend_function *zf, uint32_t arg_num, zend_ulong fetch_type TSRMLS_DC) +static inline int zend_verify_missing_arg_type(zend_function *zf, uint32_t arg_num TSRMLS_DC) { zend_arg_info *cur_arg_info; char *need_msg; @@ -624,7 +666,7 @@ static inline int zend_verify_missing_arg_type(zend_function *zf, uint32_t arg_n if (cur_arg_info->class_name) { char *class_name; - need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC); + need_msg = zend_verify_arg_class_kind(cur_arg_info, &class_name, &ce TSRMLS_CC); zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, "none", "", NULL TSRMLS_CC); return 0; } else if (cur_arg_info->type_hint) { @@ -645,7 +687,7 @@ static inline int zend_verify_missing_arg_type(zend_function *zf, uint32_t arg_n static void zend_verify_missing_arg(zend_execute_data *execute_data, uint32_t arg_num TSRMLS_DC) { if (EXPECTED(!(EX(func)->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS)) || - zend_verify_missing_arg_type(EX(func), arg_num, EX(opline)->extended_value TSRMLS_CC)) { + zend_verify_missing_arg_type(EX(func), arg_num TSRMLS_CC)) { const char *class_name = EX(func)->common.scope ? EX(func)->common.scope->name->val : ""; const char *space = EX(func)->common.scope ? "::" : ""; const char *func_name = EX(func)->common.function_name ? EX(func)->common.function_name->val : "main"; @@ -659,49 +701,50 @@ static void zend_verify_missing_arg(zend_execute_data *execute_data, uint32_t ar } } -static inline void zend_assign_to_object(zval *retval, zval *object_ptr, zval *property_name, int value_type, const znode_op *value_op, const zend_execute_data *execute_data, int opcode, void **cache_slot TSRMLS_DC) +static zend_always_inline void zend_assign_to_object(zval *retval, zval *object, uint32_t object_op_type, zval *property_name, int value_type, const znode_op *value_op, const zend_execute_data *execute_data, int opcode, void **cache_slot TSRMLS_DC) { zend_free_op free_value; zval *value = get_zval_ptr(value_type, value_op, execute_data, &free_value, BP_VAR_R); zval tmp; - zval *object = object_ptr; - ZVAL_DEREF(object); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - if (UNEXPECTED(object == &EG(error_zval))) { - if (retval) { - ZVAL_NULL(retval); + if (object_op_type != IS_UNUSED) { + ZVAL_DEREF(object); + if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (UNEXPECTED(object == &EG(error_zval))) { + if (retval) { + ZVAL_NULL(retval); + } + FREE_OP(free_value); + return; } - FREE_OP(free_value); - return; - } - if (EXPECTED(Z_TYPE_P(object) == IS_NULL || - Z_TYPE_P(object) == IS_FALSE || - (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) { - zend_object *obj; - - zval_ptr_dtor(object); - object_init(object); - Z_ADDREF_P(object); - obj = Z_OBJ_P(object); - zend_error(E_WARNING, "Creating default object from empty value"); - if (GC_REFCOUNT(obj) == 1) { - /* the enclosing container was deleted, obj is unreferenced */ + if (EXPECTED(Z_TYPE_P(object) == IS_NULL || + Z_TYPE_P(object) == IS_FALSE || + (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) { + zend_object *obj; + + zval_ptr_dtor(object); + object_init(object); + Z_ADDREF_P(object); + obj = Z_OBJ_P(object); + zend_error(E_WARNING, "Creating default object from empty value"); + if (GC_REFCOUNT(obj) == 1) { + /* the enclosing container was deleted, obj is unreferenced */ + if (retval) { + ZVAL_NULL(retval); + } + FREE_OP(free_value); + OBJ_RELEASE(obj); + return; + } + Z_DELREF_P(object); + } else { + zend_error(E_WARNING, "Attempt to assign property of non-object"); if (retval) { ZVAL_NULL(retval); } FREE_OP(free_value); - OBJ_RELEASE(obj); return; } - Z_DELREF_P(object); - } else { - zend_error(E_WARNING, "Attempt to assign property of non-object"); - if (retval) { - ZVAL_NULL(retval); - } - FREE_OP(free_value); - return; } } @@ -744,10 +787,12 @@ static inline void zend_assign_to_object(zval *retval, zval *object_ptr, zval *p ZVAL_COPY(retval, value); } zval_ptr_dtor(value); - FREE_OP_IF_VAR(free_value); + if (value_type == IS_VAR) { + FREE_OP(free_value); + } } -static void zend_assign_to_string_offset(zval *str, zend_long offset, zval *value, int value_type, zval *result TSRMLS_DC) +static void zend_assign_to_string_offset(zval *str, zend_long offset, zval *value, zval *result TSRMLS_DC) { zend_string *old_str; @@ -779,12 +824,6 @@ static void zend_assign_to_string_offset(zval *str, zend_long offset, zval *valu zend_string_release(tmp); } else { Z_STRVAL_P(str)[offset] = Z_STRVAL_P(value)[0]; - if (value_type == IS_TMP_VAR) { - /* we can safely free final_value here - * because separation is done only - * in case value_type == IS_VAR */ - zval_dtor(value); - } } /* * the value of an assignment to a string offset is undefined @@ -824,7 +863,7 @@ static zend_always_inline zval* zend_assign_to_variable(zval *variable_ptr, zval return variable_ptr; } garbage = Z_COUNTED_P(variable_ptr); - if (GC_REFCOUNT(garbage) == 1) { + if (--GC_REFCOUNT(garbage) == 0) { ZVAL_COPY_VALUE(variable_ptr, value); if (value_type == IS_CONST) { /* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */ @@ -836,10 +875,9 @@ static zend_always_inline zval* zend_assign_to_variable(zval *variable_ptr, zval Z_ADDREF_P(variable_ptr); } } - _zval_dtor_func(garbage ZEND_FILE_LINE_CC); + _zval_dtor_func_for_ptr(garbage ZEND_FILE_LINE_CC); return variable_ptr; } else { /* we need to split */ - GC_REFCOUNT(garbage)--; /* optimized version of GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr) */ if ((Z_COLLECTABLE_P(variable_ptr)) && UNEXPECTED(!GC_INFO(garbage))) { @@ -1010,12 +1048,61 @@ str_index: return retval; } -static zend_always_inline zval *zend_fetch_dimension_address(zval *result, zval *container_ptr, zval *dim, int dim_type, int type, int is_ref, int allow_str_offset TSRMLS_DC) +static zend_never_inline zend_long zend_check_string_offset(zval *container, zval *dim, int type TSRMLS_DC) +{ + zend_long offset; + + if (dim == NULL) { + zend_error_noreturn(E_ERROR, "[] operator not supported for strings"); + } + + if (UNEXPECTED(Z_TYPE_P(dim) != IS_LONG)) { + switch(Z_TYPE_P(dim)) { + case IS_STRING: + if (IS_LONG == is_numeric_string(Z_STRVAL_P(dim), Z_STRLEN_P(dim), NULL, NULL, -1)) { + break; + } + if (type != BP_VAR_UNSET) { + zend_error(E_WARNING, "Illegal string offset '%s'", Z_STRVAL_P(dim)); + } + break; + case IS_DOUBLE: + case IS_NULL: + case IS_FALSE: + case IS_TRUE: + zend_error(E_NOTICE, "String offset cast occurred"); + break; + default: + zend_error(E_WARNING, "Illegal offset type"); + break; + } + + offset = zval_get_long(dim); + } else { + offset = Z_LVAL_P(dim); + } + + return offset; +} + +static zend_always_inline zend_long zend_fetch_string_offset(zval *container, zval *dim, int type TSRMLS_DC) +{ + zend_long offset = zend_check_string_offset(container, dim, type TSRMLS_CC); + + if (Z_REFCOUNTED_P(container)) { + if (Z_REFCOUNT_P(container) > 1) { + Z_DELREF_P(container); + zval_copy_ctor_func(container); + } + Z_ADDREF_P(container); + } + return offset; +} + +static zend_always_inline void zend_fetch_dimension_address(zval *result, zval *container, zval *dim, int dim_type, int type TSRMLS_DC) { zval *retval; - zval *container = container_ptr; - ZVAL_DEREF(container); if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { SEPARATE_ARRAY(container); fetch_from_array: @@ -1028,64 +1115,19 @@ fetch_from_array: } else { retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, dim_type, type TSRMLS_CC); } - if (is_ref) { - ZVAL_MAKE_REF(retval); - } ZVAL_INDIRECT(result, retval); } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { - zend_long offset; - if (type != BP_VAR_UNSET && UNEXPECTED(Z_STRLEN_P(container) == 0)) { - zval_dtor(container); + zval_ptr_dtor_nogc(container); convert_to_array: ZVAL_NEW_ARR(container); zend_hash_init(Z_ARRVAL_P(container), 8, NULL, ZVAL_PTR_DTOR, 0); goto fetch_from_array; } - if (dim == NULL) { - zend_error_noreturn(E_ERROR, "[] operator not supported for strings"); - } - - if (UNEXPECTED(Z_TYPE_P(dim) != IS_LONG)) { - switch(Z_TYPE_P(dim)) { - case IS_STRING: - if (IS_LONG == is_numeric_string(Z_STRVAL_P(dim), Z_STRLEN_P(dim), NULL, NULL, -1)) { - break; - } - if (type != BP_VAR_UNSET) { - zend_error(E_WARNING, "Illegal string offset '%s'", Z_STRVAL_P(dim)); - } - break; - case IS_DOUBLE: - case IS_NULL: - case IS_FALSE: - case IS_TRUE: - zend_error(E_NOTICE, "String offset cast occurred"); - break; - default: - zend_error(E_WARNING, "Illegal offset type"); - break; - } - - offset = zval_get_long(dim); - } else { - offset = Z_LVAL_P(dim); - } - - if (allow_str_offset) { - if (Z_REFCOUNTED_P(container)) { - if (Z_REFCOUNT_P(container) > 1) { - Z_DELREF_P(container); - zval_copy_ctor_func(container); - } - Z_ADDREF_P(container); - } - ZVAL_LONG(result, offset); - return container; /* assignment to string offset */ - } else { - ZVAL_INDIRECT(result, NULL); /* wrong string offset */ - } + zend_check_string_offset(container, dim, type TSRMLS_CC); + + ZVAL_INDIRECT(result, NULL); /* wrong string offset */ } else if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (!Z_OBJ_HT_P(container)->read_dimension) { zend_error_noreturn(E_ERROR, "Cannot use object as array"); @@ -1116,9 +1158,6 @@ convert_to_array: } } if (result != retval) { - if (is_ref) { - ZVAL_MAKE_REF(retval); - } ZVAL_INDIRECT(result, retval); } } else { @@ -1147,32 +1186,21 @@ convert_to_array: ZVAL_INDIRECT(result, &EG(error_zval)); } } - return NULL; /* not an assignment to string offset */ } static zend_never_inline void zend_fetch_dimension_address_W(zval *result, zval *container_ptr, zval *dim, int dim_type TSRMLS_DC) { - zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_W, 0, 0 TSRMLS_CC); -} - -static zend_never_inline zval *zend_fetch_dimension_address_W_str(zval *result, zval *container_ptr, zval *dim, int dim_type TSRMLS_DC) -{ - return zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_W, 0, 1 TSRMLS_CC); -} - -static zend_never_inline void zend_fetch_dimension_address_W_ref(zval *result, zval *container_ptr, zval *dim, int dim_type TSRMLS_DC) -{ - zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_W, 1, 0 TSRMLS_CC); + zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_W TSRMLS_CC); } static zend_never_inline void zend_fetch_dimension_address_RW(zval *result, zval *container_ptr, zval *dim, int dim_type TSRMLS_DC) { - zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_RW, 0, 0 TSRMLS_CC); + zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_RW TSRMLS_CC); } static zend_never_inline void zend_fetch_dimension_address_UNSET(zval *result, zval *container_ptr, zval *dim, int dim_type TSRMLS_DC) { - zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_UNSET, 0, 0 TSRMLS_CC); + zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_UNSET TSRMLS_CC); } static zend_always_inline void zend_fetch_dimension_address_read(zval *result, zval *container, zval *dim, int dim_type, int type TSRMLS_DC) @@ -1235,14 +1263,13 @@ static zend_always_inline void zend_fetch_dimension_address_read(zval *result, z } else { retval = Z_OBJ_HT_P(container)->read_dimension(container, dim, type, result TSRMLS_CC); - if (result) { - if (retval) { - if (result != retval) { - ZVAL_COPY(result, retval); - } - } else { - ZVAL_NULL(result); + ZEND_ASSERT(result != NULL); + if (retval) { + if (result != retval) { + ZVAL_COPY(result, retval); } + } else { + ZVAL_NULL(result); } } } else { @@ -1265,57 +1292,47 @@ ZEND_API void zend_fetch_dimension_by_zval(zval *result, zval *container, zval * zend_fetch_dimension_address_read_R(result, container, dim, IS_TMP_VAR TSRMLS_CC); } -static void zend_fetch_property_address(zval *result, zval *container_ptr, zval *prop_ptr, void **cache_slot, int type, int is_ref TSRMLS_DC) +static zend_always_inline void zend_fetch_property_address(zval *result, zval *container, uint32_t container_op_type, zval *prop_ptr, void **cache_slot, int type TSRMLS_DC) { - zval *container = container_ptr; - - ZVAL_DEREF(container); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { - if (UNEXPECTED(container == &EG(error_zval))) { - ZVAL_INDIRECT(result, &EG(error_zval)); - return; - } + if (container_op_type != IS_UNUSED) { + ZVAL_DEREF(container); + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { + if (UNEXPECTED(container == &EG(error_zval))) { + ZVAL_INDIRECT(result, &EG(error_zval)); + return; + } - /* this should modify object only if it's empty */ - if (type != BP_VAR_UNSET && - EXPECTED((Z_TYPE_P(container) == IS_NULL || - Z_TYPE_P(container) == IS_FALSE || - (Z_TYPE_P(container) == IS_STRING && Z_STRLEN_P(container)==0)))) { - zval_ptr_dtor_nogc(container); - object_init(container); - } else { - zend_error(E_WARNING, "Attempt to modify property of non-object"); - ZVAL_INDIRECT(result, &EG(error_zval)); - return; + /* this should modify object only if it's empty */ + if (type != BP_VAR_UNSET && + EXPECTED((Z_TYPE_P(container) == IS_NULL || + Z_TYPE_P(container) == IS_FALSE || + (Z_TYPE_P(container) == IS_STRING && Z_STRLEN_P(container)==0)))) { + zval_ptr_dtor_nogc(container); + object_init(container); + } else { + zend_error(E_WARNING, "Attempt to modify property of non-object"); + ZVAL_INDIRECT(result, &EG(error_zval)); + return; + } } } - if (EXPECTED(Z_OBJ_HT_P(container)->get_property_ptr_ptr)) { zval *ptr = Z_OBJ_HT_P(container)->get_property_ptr_ptr(container, prop_ptr, type, cache_slot TSRMLS_CC); if (NULL == ptr) { if (Z_OBJ_HT_P(container)->read_property && (ptr = Z_OBJ_HT_P(container)->read_property(container, prop_ptr, type, cache_slot, result TSRMLS_CC)) != NULL) { if (ptr != result) { - if (is_ref && ptr != &EG(uninitialized_zval)) { - ZVAL_MAKE_REF(ptr); - } ZVAL_INDIRECT(result, ptr); } } else { zend_error_noreturn(E_ERROR, "Cannot access undefined property for object with overloaded property access"); } } else { - if (is_ref) { - ZVAL_MAKE_REF(ptr); - } ZVAL_INDIRECT(result, ptr); } } else if (EXPECTED(Z_OBJ_HT_P(container)->read_property)) { zval *ptr = Z_OBJ_HT_P(container)->read_property(container, prop_ptr, type, cache_slot, result TSRMLS_CC); if (ptr != result) { - if (is_ref && ptr != &EG(uninitialized_zval)) { - ZVAL_MAKE_REF(ptr); - } ZVAL_INDIRECT(result, ptr); } } else { @@ -1337,13 +1354,9 @@ static inline zend_brk_cont_element* zend_brk_cont(int nest_levels, int array_of if (nest_levels>1) { zend_op *brk_opline = &op_array->opcodes[jmp_to->brk]; - if (brk_opline->opcode == ZEND_SWITCH_FREE) { - if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) { - zval_ptr_dtor(EX_VAR(brk_opline->op1.var)); - } - } else if (brk_opline->opcode == ZEND_FREE) { + if (brk_opline->opcode == ZEND_FREE) { if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) { - zval_dtor(EX_VAR(brk_opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(brk_opline->op1.var)); } } } @@ -1390,14 +1403,14 @@ ZEND_API opcode_handler_t *zend_opcode_handlers; ZEND_API void execute_internal(zend_execute_data *execute_data, zval *return_value TSRMLS_DC) { - execute_data->func->internal_function.handler(execute_data->num_args, return_value TSRMLS_CC); + execute_data->func->internal_function.handler(execute_data, return_value TSRMLS_CC); } -void zend_clean_and_cache_symbol_table(zend_array *symbol_table TSRMLS_DC) /* {{{ */ +ZEND_API void zend_clean_and_cache_symbol_table(zend_array *symbol_table TSRMLS_DC) /* {{{ */ { if (EG(symtable_cache_ptr) >= EG(symtable_cache_limit)) { zend_hash_destroy(&symbol_table->ht); - FREE_HASHTABLE(symbol_table); + efree_size(symbol_table, sizeof(zend_array)); } else { /* clean before putting into the cache, since clean could call dtors, which could use cached hash */ @@ -1446,19 +1459,17 @@ void zend_free_compiled_variables(zend_execute_data *execute_data TSRMLS_DC) /* * +----------------------------------------+ */ -static zend_always_inline void i_init_func_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value, vm_frame_kind frame_kind TSRMLS_DC) /* {{{ */ +static zend_always_inline void i_init_func_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value TSRMLS_DC) /* {{{ */ { uint32_t first_extra_arg, num_args; ZEND_ASSERT(EX(func) == (zend_function*)op_array); - ZEND_ASSERT(EX(object) == Z_OBJ(EG(This))); + ZEND_ASSERT(EX(scope) == EG(scope)); EX(opline) = op_array->opcodes; EX(call) = NULL; - EX(frame_kind) = frame_kind; EX(return_value) = return_value; - EX(scope) = EG(scope); EX(delayed_exception) = NULL; - ZVAL_UNDEF(&EX(old_error_reporting)); + EX(silence_op_num) = -1; /* Handle arguments */ first_extra_arg = op_array->num_args; @@ -1492,7 +1503,7 @@ static zend_always_inline void i_init_func_execute_data(zend_execute_data *execu } /* Initialize CV variables (skip arguments) */ - if (EXPECTED(num_args < op_array->last_var)) { + if (EXPECTED((int)num_args < op_array->last_var)) { zval *var = EX_VAR_NUM(num_args); zval *end = EX_VAR_NUM(op_array->last_var); @@ -1502,9 +1513,9 @@ static zend_always_inline void i_init_func_execute_data(zend_execute_data *execu } while (var != end); } - if (op_array->this_var != -1 && EX(object)) { - ZVAL_OBJ(EX_VAR(op_array->this_var), EX(object)); - GC_REFCOUNT(EX(object))++; + if (op_array->this_var != -1 && Z_OBJ(EX(This))) { + ZVAL_OBJ(EX_VAR(op_array->this_var), Z_OBJ(EX(This))); + GC_REFCOUNT(Z_OBJ(EX(This)))++; } if (!op_array->run_time_cache && op_array->last_cache_slot) { @@ -1516,21 +1527,24 @@ static zend_always_inline void i_init_func_execute_data(zend_execute_data *execu } /* }}} */ -static zend_always_inline void i_init_code_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value, vm_frame_kind frame_kind TSRMLS_DC) /* {{{ */ +static zend_always_inline void i_init_code_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value TSRMLS_DC) /* {{{ */ { ZEND_ASSERT(EX(func) == (zend_function*)op_array); - ZEND_ASSERT(EX(object) == Z_OBJ(EG(This))); EX(opline) = op_array->opcodes; EX(call) = NULL; - EX(frame_kind) = frame_kind; EX(return_value) = return_value; EX(scope) = EG(scope); EX(delayed_exception) = NULL; - ZVAL_UNDEF(&EX(old_error_reporting)); + EX(silence_op_num) = -1; zend_attach_symbol_table(execute_data); + if (op_array->this_var != -1 && Z_OBJ(EX(This))) { + ZVAL_OBJ(EX_VAR(op_array->this_var), Z_OBJ(EX(This))); + GC_REFCOUNT(Z_OBJ(EX(This)))++; + } + if (!op_array->run_time_cache && op_array->last_cache_slot) { op_array->run_time_cache = ecalloc(op_array->last_cache_slot, sizeof(void*)); } @@ -1540,18 +1554,16 @@ static zend_always_inline void i_init_code_execute_data(zend_execute_data *execu } /* }}} */ -static zend_always_inline void i_init_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value, vm_frame_kind frame_kind TSRMLS_DC) /* {{{ */ +static zend_always_inline void i_init_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value TSRMLS_DC) /* {{{ */ { ZEND_ASSERT(EX(func) == (zend_function*)op_array); - ZEND_ASSERT(EX(object) == Z_OBJ(EG(This))); EX(opline) = op_array->opcodes; EX(call) = NULL; - EX(frame_kind) = frame_kind; EX(return_value) = return_value; EX(scope) = EG(scope); EX(delayed_exception) = NULL; - ZVAL_UNDEF(&EX(old_error_reporting)); + EX(silence_op_num) = -1; if (UNEXPECTED(EX(symbol_table) != NULL)) { zend_attach_symbol_table(execute_data); @@ -1590,7 +1602,7 @@ static zend_always_inline void i_init_execute_data(zend_execute_data *execute_da } /* Initialize CV variables (skip arguments) */ - if (EXPECTED(num_args < op_array->last_var)) { + if (EXPECTED((int)num_args < op_array->last_var)) { zval *var = EX_VAR_NUM(num_args); zval *end = EX_VAR_NUM(op_array->last_var); @@ -1599,11 +1611,11 @@ static zend_always_inline void i_init_execute_data(zend_execute_data *execute_da var++; } while (var != end); } + } - if (op_array->this_var != -1 && EX(object)) { - ZVAL_OBJ(EX_VAR(op_array->this_var), EX(object)); - GC_REFCOUNT(EX(object))++; - } + if (op_array->this_var != -1 && Z_OBJ(EX(This))) { + ZVAL_OBJ(EX_VAR(op_array->this_var), Z_OBJ(EX(This))); + GC_REFCOUNT(Z_OBJ(EX(This)))++; } if (!op_array->run_time_cache && op_array->last_cache_slot) { @@ -1632,18 +1644,22 @@ ZEND_API zend_execute_data *zend_create_generator_execute_data(zend_execute_data */ zend_execute_data *execute_data; uint32_t num_args = call->num_args; + size_t stack_size = (ZEND_CALL_FRAME_SLOT + MAX(op_array->last_var + op_array->T, num_args)) * sizeof(zval); - EG(argument_stack) = zend_vm_stack_new_page( - MAX(ZEND_VM_STACK_PAGE_SIZE, - ZEND_CALL_FRAME_SLOT + MAX(op_array->last_var + op_array->T, num_args))); - EG(argument_stack)->prev = NULL; + EG(vm_stack) = zend_vm_stack_new_page( + EXPECTED(stack_size < ZEND_VM_STACK_FREE_PAGE_SIZE) ? + ZEND_VM_STACK_PAGE_SIZE : + ZEND_VM_STACK_PAGE_ALIGNED_SIZE(stack_size), + NULL); + EG(vm_stack_top) = EG(vm_stack)->top; + EG(vm_stack_end) = EG(vm_stack)->end; execute_data = zend_vm_stack_push_call_frame( + VM_FRAME_TOP_FUNCTION, (zend_function*)op_array, num_args, - call->flags, call->called_scope, - call->object, + Z_OBJ(call->This), NULL TSRMLS_CC); EX(num_args) = num_args; @@ -1659,17 +1675,18 @@ ZEND_API zend_execute_data *zend_create_generator_execute_data(zend_execute_data } EX(symbol_table) = NULL; + EX(scope) = EG(scope); - i_init_func_execute_data(execute_data, op_array, return_value, VM_FRAME_TOP_FUNCTION TSRMLS_CC); + i_init_func_execute_data(execute_data, op_array, return_value TSRMLS_CC); return execute_data; } /* }}} */ -ZEND_API void zend_init_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value, vm_frame_kind frame_kind TSRMLS_DC) /* {{{ */ +ZEND_API void zend_init_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value TSRMLS_DC) /* {{{ */ { EX(prev_execute_data) = EG(current_execute_data); - i_init_execute_data(execute_data, op_array, return_value, frame_kind TSRMLS_CC); + i_init_execute_data(execute_data, op_array, return_value TSRMLS_CC); } /* }}} */ @@ -1683,12 +1700,10 @@ static zend_always_inline zend_bool zend_is_by_ref_func_arg_fetch(const zend_op static zend_execute_data *zend_vm_stack_copy_call_frame(zend_execute_data *call, uint32_t passed_args, uint32_t additional_args TSRMLS_DC) /* {{{ */ { zend_execute_data *new_call; - int used_stack = (EG(argument_stack)->top - (zval*)call) + additional_args; + int used_stack = (EG(vm_stack_top) - (zval*)call) + additional_args; /* copy call frame into new stack segment */ - zend_vm_stack_extend(used_stack TSRMLS_CC); - new_call = (zend_execute_data*)EG(argument_stack)->top; - EG(argument_stack)->top += used_stack; + new_call = zend_vm_stack_extend(used_stack * sizeof(zval) TSRMLS_CC); *new_call = *call; if (passed_args) { zval *src = ZEND_CALL_ARG(call, 1); @@ -1702,13 +1717,13 @@ static zend_execute_data *zend_vm_stack_copy_call_frame(zend_execute_data *call, } /* delete old call_frame from previous stack segment */ - EG(argument_stack)->prev->top = (zval*)call; + EG(vm_stack)->prev->top = (zval*)call; /* delete previous stack segment if it becames empty */ - if (UNEXPECTED(EG(argument_stack)->prev->top == ZEND_VM_STACK_ELEMETS(EG(argument_stack)->prev))) { - zend_vm_stack r = EG(argument_stack)->prev; + if (UNEXPECTED(EG(vm_stack)->prev->top == ZEND_VM_STACK_ELEMETS(EG(vm_stack)->prev))) { + zend_vm_stack r = EG(vm_stack)->prev; - EG(argument_stack)->prev = r->prev; + EG(vm_stack)->prev = r->prev; efree(r); } @@ -1718,8 +1733,8 @@ static zend_execute_data *zend_vm_stack_copy_call_frame(zend_execute_data *call, static zend_always_inline void zend_vm_stack_extend_call_frame(zend_execute_data **call, uint32_t passed_args, uint32_t additional_args TSRMLS_DC) /* {{{ */ { - if (EXPECTED(EG(argument_stack)->end - EG(argument_stack)->top > additional_args)) { - EG(argument_stack)->top += additional_args; + if (EXPECTED(EG(vm_stack_end) - EG(vm_stack_top) > additional_args)) { + EG(vm_stack_top) += additional_args; } else { *call = zend_vm_stack_copy_call_frame(*call, passed_args, additional_args TSRMLS_CC); } diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index 334a4ccc03..982413e032 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -35,7 +35,7 @@ ZEND_API extern void (*zend_execute_internal)(zend_execute_data *execute_data, z void init_executor(TSRMLS_D); void shutdown_executor(TSRMLS_D); void shutdown_destructors(TSRMLS_D); -ZEND_API void zend_init_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value, vm_frame_kind frame_kind TSRMLS_DC); +ZEND_API void zend_init_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value TSRMLS_DC); ZEND_API zend_execute_data *zend_create_generator_execute_data(zend_execute_data *call, zend_op_array *op_array, zval *return_value TSRMLS_DC); ZEND_API void zend_execute(zend_op_array *op_array, zval *return_value TSRMLS_DC); ZEND_API void execute_ex(zend_execute_data *execute_data TSRMLS_DC); @@ -44,11 +44,11 @@ ZEND_API int zend_is_true(zval *op TSRMLS_DC); ZEND_API zend_class_entry *zend_lookup_class(zend_string *name TSRMLS_DC); ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, const zval *key, int use_autoload TSRMLS_DC); ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSRMLS_DC); -ZEND_API int zend_eval_stringl(char *str, int str_len, zval *retval_ptr, char *string_name TSRMLS_DC); +ZEND_API int zend_eval_stringl(char *str, size_t str_len, zval *retval_ptr, char *string_name TSRMLS_DC); ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC); -ZEND_API int zend_eval_stringl_ex(char *str, int str_len, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC); +ZEND_API int zend_eval_stringl_ex(char *str, size_t str_len, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC); -ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, zend_ulong fetch_type, char **class_name, zend_class_entry **pce TSRMLS_DC); +ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, char **class_name, zend_class_entry **pce TSRMLS_DC); ZEND_API void zend_verify_arg_error(int error_type, const zend_function *zf, uint32_t arg_num, const char *need_msg, const char *need_kind, const char *given_msg, const char *given_kind, zval *arg TSRMLS_DC); static zend_always_inline void i_zval_ptr_dtor(zval *zval_ptr ZEND_FILE_LINE_DC TSRMLS_DC) @@ -98,24 +98,22 @@ again: result = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0); break; case IS_OBJECT: - if (IS_ZEND_STD_OBJECT(*op)) { - if (Z_OBJ_HT_P(op)->cast_object) { - zval tmp; - if (Z_OBJ_HT_P(op)->cast_object(op, &tmp, _IS_BOOL TSRMLS_CC) == SUCCESS) { - result = Z_TYPE(tmp) == IS_TRUE; - break; - } - zend_error(E_RECOVERABLE_ERROR, "Object of class %s could not be converted to boolean", Z_OBJ_P(op)->ce->name->val); - } else if (Z_OBJ_HT_P(op)->get) { - zval rv; - zval *tmp = Z_OBJ_HT_P(op)->get(op, &rv TSRMLS_CC); - if (Z_TYPE_P(tmp) != IS_OBJECT) { - /* for safety - avoid loop */ - convert_to_boolean(tmp); - result = Z_TYPE_P(tmp) == IS_TRUE; - zval_ptr_dtor(tmp); - break; - } + if (Z_OBJ_HT_P(op)->cast_object) { + zval tmp; + if (Z_OBJ_HT_P(op)->cast_object(op, &tmp, _IS_BOOL TSRMLS_CC) == SUCCESS) { + result = Z_TYPE(tmp) == IS_TRUE; + break; + } + zend_error(E_RECOVERABLE_ERROR, "Object of class %s could not be converted to boolean", Z_OBJ_P(op)->ce->name->val); + } else if (Z_OBJ_HT_P(op)->get) { + zval rv; + zval *tmp = Z_OBJ_HT_P(op)->get(op, &rv TSRMLS_CC); + if (Z_TYPE_P(tmp) != IS_OBJECT) { + /* for safety - avoid loop */ + convert_to_boolean(tmp); + result = Z_TYPE_P(tmp) == IS_TRUE; + zval_ptr_dtor(tmp); + break; } } result = 1; @@ -137,68 +135,34 @@ ZEND_API int zval_update_constant_no_inline_change(zval *pp, zend_class_entry *s ZEND_API int zval_update_constant_ex(zval *pp, zend_bool inline_change, zend_class_entry *scope TSRMLS_DC); /* dedicated Zend executor functions - do not use! */ -#define ZEND_VM_STACK_PAGE_SIZE (16 * 1024) /* should be a power of 2 */ - struct _zend_vm_stack { zval *top; zval *end; zend_vm_stack prev; }; -#define ZEND_VM_STACK_HEADER_SLOT \ +#define ZEND_VM_STACK_HEADER_SLOTS \ ((ZEND_MM_ALIGNED_SIZE(sizeof(struct _zend_vm_stack)) + ZEND_MM_ALIGNED_SIZE(sizeof(zval)) - 1) / ZEND_MM_ALIGNED_SIZE(sizeof(zval))) #define ZEND_VM_STACK_ELEMETS(stack) \ - (((zval*)(stack)) + ZEND_VM_STACK_HEADER_SLOT) - -#define ZEND_VM_STACK_GROW_IF_NEEDED(count) \ - do { \ - if (UNEXPECTED(((count) * ZEND_MM_ALIGNED_SIZE(sizeof(zval))) > \ - (size_t)(((char*)EG(argument_stack)->end) - \ - ((char*)EG(argument_stack)->top)))) { \ - zend_vm_stack_extend((count) TSRMLS_CC); \ - } \ - } while (0) - -static zend_always_inline zend_vm_stack zend_vm_stack_new_page(int count) { - zend_vm_stack page = (zend_vm_stack)emalloc(count * ZEND_MM_ALIGNED_SIZE(sizeof(zval))); + (((zval*)(stack)) + ZEND_VM_STACK_HEADER_SLOTS) - page->top = ZEND_VM_STACK_ELEMETS(page); - page->end = (zval*)page + count; - page->prev = NULL; - return page; -} - -static zend_always_inline void zend_vm_stack_init(TSRMLS_D) -{ - EG(argument_stack) = zend_vm_stack_new_page(ZEND_VM_STACK_PAGE_SIZE); - EG(argument_stack)->top++; -} +ZEND_API void zend_vm_stack_init(TSRMLS_D); +ZEND_API void zend_vm_stack_destroy(TSRMLS_D); +ZEND_API void* zend_vm_stack_extend(size_t size TSRMLS_DC); -static zend_always_inline void zend_vm_stack_destroy(TSRMLS_D) +static zend_always_inline zval* zend_vm_stack_alloc(size_t size TSRMLS_DC) { - zend_vm_stack stack = EG(argument_stack); + char *top = (char*)EG(vm_stack_top); - while (stack != NULL) { - zend_vm_stack p = stack->prev; - efree(stack); - stack = p; + if (UNEXPECTED(size > (size_t)(((char*)EG(vm_stack_end)) - top))) { + return (zval*)zend_vm_stack_extend(size TSRMLS_CC); } + EG(vm_stack_top) = (zval*)(top + size); + return (zval*)top; } -static zend_always_inline void zend_vm_stack_extend(uint32_t count TSRMLS_DC) -{ - uint32_t size = count * ZEND_MM_ALIGNED_SIZE(sizeof(zval)); - zend_vm_stack p = zend_vm_stack_new_page( - (size >= (ZEND_VM_STACK_PAGE_SIZE - ZEND_VM_STACK_HEADER_SLOT) * ZEND_MM_ALIGNED_SIZE(sizeof(zval))) ? - (size + ((ZEND_VM_STACK_HEADER_SLOT + ZEND_VM_STACK_PAGE_SIZE) * ZEND_MM_ALIGNED_SIZE(sizeof(zval))) - 1) & - ~((ZEND_VM_STACK_PAGE_SIZE * ZEND_MM_ALIGNED_SIZE(sizeof(zval))) - 1) : - ZEND_VM_STACK_PAGE_SIZE); - p->prev = EG(argument_stack); - EG(argument_stack) = p; -} - -static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame(zend_function *func, uint32_t num_args, zend_uchar flags, zend_class_entry *called_scope, zend_object *object, zend_execute_data *prev TSRMLS_DC) +static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame(uint32_t frame_info, zend_function *func, uint32_t num_args, zend_class_entry *called_scope, zend_object *object, zend_execute_data *prev TSRMLS_DC) { uint32_t used_stack = ZEND_CALL_FRAME_SLOT + num_args; zend_execute_data *call; @@ -206,15 +170,13 @@ static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame(zend_ if (ZEND_USER_CODE(func->type)) { used_stack += func->op_array.last_var + func->op_array.T - MIN(func->op_array.num_args, num_args); } - ZEND_VM_STACK_GROW_IF_NEEDED(used_stack); - call = (zend_execute_data*)EG(argument_stack)->top; - EG(argument_stack)->top += used_stack; + call = (zend_execute_data*)zend_vm_stack_alloc(used_stack * sizeof(zval) TSRMLS_CC); call->func = func; - call->num_args = 0; - call->flags = flags; + ZVAL_OBJ(&call->This, object); call->called_scope = called_scope; - call->object = object; - call->prev_nested_call = prev; + call->prev_execute_data = prev; + call->frame_info = frame_info; + call->num_args = 0; return call; } @@ -249,13 +211,16 @@ static zend_always_inline void zend_vm_stack_free_args(zend_execute_data *call T static zend_always_inline void zend_vm_stack_free_call_frame(zend_execute_data *call TSRMLS_DC) { - if (UNEXPECTED(ZEND_VM_STACK_ELEMETS(EG(argument_stack)) == (zval*)call)) { - zend_vm_stack p = EG(argument_stack); + zend_vm_stack p = EG(vm_stack); + if (UNEXPECTED(ZEND_VM_STACK_ELEMETS(p) == (zval*)call)) { + zend_vm_stack prev = p->prev; - EG(argument_stack) = p->prev; + EG(vm_stack_top) = prev->top; + EG(vm_stack_end) = prev->end; + EG(vm_stack) = prev; efree(p); } else { - EG(argument_stack)->top = (zval*)call; + EG(vm_stack_top) = (zval*)call; } } @@ -282,11 +247,6 @@ void zend_shutdown_timeout_thread(void); #define WM_UNREGISTER_ZEND_TIMEOUT (WM_USER+2) #endif -/* The following tries to resolve the classname of a zval of type object. - * Since it is slow it should be only used in error messages. - */ -#define Z_OBJ_CLASS_NAME_P(obj) (((obj) && (obj)->handlers->get_class_entry != NULL && (obj)->handlers->get_class_entry) ? (obj)->handlers->get_class_entry(obj TSRMLS_CC)->name->val : "") - ZEND_API zval* zend_get_compiled_variable_value(const zend_execute_data *execute_data_ptr, uint32_t var); #define ZEND_USER_OPCODE_CONTINUE 0 /* execute next opcode */ @@ -310,7 +270,7 @@ ZEND_API zval *zend_get_zval_ptr(int op_type, const znode_op *node, const zend_e ZEND_API int zend_do_fcall(ZEND_OPCODE_HANDLER_ARGS); -void zend_clean_and_cache_symbol_table(zend_array *symbol_table TSRMLS_DC); +ZEND_API void zend_clean_and_cache_symbol_table(zend_array *symbol_table TSRMLS_DC); void zend_free_compiled_variables(zend_execute_data *execute_data TSRMLS_DC); #define CACHED_PTR(num) \ diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index f59a10179b..5edc65e93e 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -187,8 +187,6 @@ void init_executor(TSRMLS_D) /* {{{ */ EG(scope) = NULL; - ZVAL_OBJ(&EG(This), NULL); - EG(active) = 1; } /* }}} */ @@ -523,7 +521,7 @@ ZEND_API int zval_update_constant_ex(zval *p, zend_bool inline_change, zend_clas } else if (Z_TYPE_P(p) == IS_CONSTANT) { int refcount; - SEPARATE_ZVAL_IF_NOT_REF(p); + SEPARATE_ZVAL_NOREF(p); MARK_CONSTANT_VISITED(p); refcount = Z_REFCOUNTED_P(p) ? Z_REFCOUNT_P(p) : 1; const_value = zend_get_constant_ex(Z_STR_P(p), scope, Z_CONST_FLAGS_P(p) TSRMLS_CC); @@ -531,7 +529,7 @@ ZEND_API int zval_update_constant_ex(zval *p, zend_bool inline_change, zend_clas char *actual = Z_STRVAL_P(p); if ((colon = (char*)zend_memrchr(Z_STRVAL_P(p), ':', Z_STRLEN_P(p)))) { - int len; + size_t len; zend_error(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(p)); len = Z_STRLEN_P(p) - ((colon - Z_STRVAL_P(p)) + 1); @@ -546,7 +544,7 @@ ZEND_API int zval_update_constant_ex(zval *p, zend_bool inline_change, zend_clas } else { zend_string *save = Z_STR_P(p); char *slash; - int actual_len = Z_STRLEN_P(p); + size_t actual_len = Z_STRLEN_P(p); if ((Z_CONST_FLAGS_P(p) & IS_CONSTANT_UNQUALIFIED) && (slash = (char *)zend_memrchr(actual, '\\', actual_len))) { actual = slash + 1; actual_len -= (actual - Z_STRVAL_P(p)); @@ -601,7 +599,7 @@ ZEND_API int zval_update_constant_ex(zval *p, zend_bool inline_change, zend_clas if (Z_REFCOUNTED_P(p)) Z_SET_REFCOUNT_P(p, refcount); } else if (Z_TYPE_P(p) == IS_CONSTANT_AST) { zval tmp; - SEPARATE_ZVAL_IF_NOT_REF(p); + SEPARATE_ZVAL_NOREF(p); zend_ast_evaluate(&tmp, Z_ASTVAL_P(p), scope TSRMLS_CC); if (inline_change) { @@ -663,7 +661,6 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS zend_execute_data *call, dummy_execute_data; zend_fcall_info_cache fci_cache_local; zend_function *func; - zend_object *orig_object; zend_class_entry *orig_scope; zval tmp; @@ -685,7 +682,6 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS break; } - orig_object = Z_OBJ(EG(This)); orig_scope = EG(scope); /* Initialize execute_data */ @@ -703,7 +699,6 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS dummy_execute_data = *EG(current_execute_data); dummy_execute_data.prev_execute_data = EG(current_execute_data); dummy_execute_data.call = NULL; - dummy_execute_data.prev_nested_call = NULL; dummy_execute_data.opline = NULL; dummy_execute_data.func = NULL; EG(current_execute_data) = &dummy_execute_data; @@ -741,7 +736,8 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS } func = fci_cache->function_handler; - call = zend_vm_stack_push_call_frame(func, fci->param_count, 0, fci_cache->called_scope, fci_cache->object, NULL TSRMLS_CC); + call = zend_vm_stack_push_call_frame(VM_FRAME_TOP_FUNCTION, + func, fci->param_count, fci_cache->called_scope, fci_cache->object, NULL TSRMLS_CC); calling_scope = fci_cache->calling_scope; fci->object = fci_cache->object; if (fci->object && @@ -834,19 +830,22 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS call->num_args = fci->param_count; EG(scope) = calling_scope; - if (!fci->object || - (func->common.fn_flags & ZEND_ACC_STATIC)) { - Z_OBJ(EG(This)) = call->object = NULL; + if (func->common.fn_flags & ZEND_ACC_STATIC) { + fci->object = NULL; + } + if (!fci->object) { + Z_OBJ(call->This) = NULL; + Z_TYPE_INFO(call->This) = IS_UNDEF; } else { - Z_OBJ(EG(This)) = fci->object; - Z_ADDREF(EG(This)); + ZVAL_OBJ(&call->This, fci->object); + GC_REFCOUNT(fci->object)++; } if (func->type == ZEND_USER_FUNCTION) { EG(scope) = func->common.scope; call->symbol_table = fci->symbol_table; if (EXPECTED((func->op_array.fn_flags & ZEND_ACC_GENERATOR) == 0)) { - zend_init_execute_data(call, &func->op_array, fci->retval, VM_FRAME_TOP_FUNCTION TSRMLS_CC); + zend_init_execute_data(call, &func->op_array, fci->retval TSRMLS_CC); zend_execute_ex(call TSRMLS_CC); } else { zend_generator_create_zval(call, &func->op_array, fci->retval TSRMLS_CC); @@ -862,7 +861,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS EG(current_execute_data) = call; if (EXPECTED(zend_execute_internal == NULL)) { /* saves one function call if zend_execute_internal is not used */ - func->internal_function.handler(fci->param_count, fci->retval TSRMLS_CC); + func->internal_function.handler(call, fci->retval TSRMLS_CC); } else { zend_execute_internal(call, fci->retval TSRMLS_CC); } @@ -892,7 +891,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS if (fci->object) { call->prev_execute_data = EG(current_execute_data); EG(current_execute_data) = call; - fci->object->handlers->call_method(func->common.function_name, fci->object, fci->param_count, fci->retval TSRMLS_CC); + fci->object->handlers->call_method(func->common.function_name, fci->object, call, fci->retval TSRMLS_CC); EG(current_execute_data) = call->prev_execute_data; } else { zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object"); @@ -912,11 +911,10 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS } } - if (Z_OBJ(EG(This))) { - zval_ptr_dtor(&EG(This)); + if (fci->object) { + OBJ_RELEASE(fci->object); } - Z_OBJ(EG(This)) = orig_object; EG(scope) = orig_scope; if (EG(current_execute_data) == &dummy_execute_data) { EG(current_execute_data) = dummy_execute_data.prev_execute_data; @@ -1057,7 +1055,7 @@ ZEND_API zend_class_entry *zend_lookup_class(zend_string *name TSRMLS_DC) /* {{{ } /* }}} */ -ZEND_API int zend_eval_stringl(char *str, int str_len, zval *retval_ptr, char *string_name TSRMLS_DC) /* {{{ */ +ZEND_API int zend_eval_stringl(char *str, size_t str_len, zval *retval_ptr, char *string_name TSRMLS_DC) /* {{{ */ { zval pv; zend_op_array *new_op_array; @@ -1125,7 +1123,7 @@ ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSR } /* }}} */ -ZEND_API int zend_eval_stringl_ex(char *str, int str_len, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC) /* {{{ */ +ZEND_API int zend_eval_stringl_ex(char *str, size_t str_len, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC) /* {{{ */ { int result; diff --git a/Zend/zend_extensions.h b/Zend/zend_extensions.h index e210839870..792a8a6164 100644 --- a/Zend/zend_extensions.h +++ b/Zend/zend_extensions.h @@ -111,7 +111,7 @@ END_EXTERN_C() ZEND_API extern zend_llist zend_extensions; void zend_extension_dtor(zend_extension *extension); -void zend_append_version_info(const zend_extension *extension); +ZEND_API void zend_append_version_info(const zend_extension *extension); int zend_startup_extensions_mechanism(void); int zend_startup_extensions(void); void zend_shutdown_extensions(TSRMLS_D); diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index 449a374683..b38657f7b7 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -52,24 +52,14 @@ static void zend_generator_cleanup_unfinished_execution(zend_generator *generato if (brk_cont->start < 0) { continue; - } else if (brk_cont->start > op_num) { + } else if ((uint32_t)brk_cont->start > op_num) { break; - } else if (brk_cont->brk > op_num) { + } else if (brk_cont->brk >= 0 && (uint32_t)brk_cont->brk > op_num) { zend_op *brk_opline = op_array->opcodes + brk_cont->brk; - switch (brk_opline->opcode) { - case ZEND_SWITCH_FREE: - { - zval *var = EX_VAR_2(execute_data, brk_opline->op1.var); - zval_ptr_dtor(var); - } - break; - case ZEND_FREE: - { - zval *var = EX_VAR_2(execute_data, brk_opline->op1.var); - zval_dtor(var); - } - break; + if (brk_opline->opcode == ZEND_FREE) { + zval *var = EX_VAR_2(execute_data, brk_opline->op1.var); + zval_ptr_dtor_nogc(var); } } } @@ -78,10 +68,10 @@ static void zend_generator_cleanup_unfinished_execution(zend_generator *generato /* If yield was used as a function argument there may be active * method calls those objects need to be freed */ while (execute_data->call) { - if (execute_data->call->object) { - OBJ_RELEASE(execute_data->call->object); + if (Z_OBJ(execute_data->call->This)) { + OBJ_RELEASE(Z_OBJ(execute_data->call->This)); } - execute_data->call = execute_data->call->prev_nested_call; + execute_data->call = execute_data->call->prev_execute_data; } } /* }}} */ @@ -108,8 +98,8 @@ ZEND_API void zend_generator_close(zend_generator *generator, zend_bool finished zend_clean_and_cache_symbol_table(execute_data->symbol_table TSRMLS_CC); } - if (execute_data->object) { - OBJ_RELEASE(execute_data->object); + if (Z_OBJ(execute_data->This)) { + OBJ_RELEASE(Z_OBJ(execute_data->This)); } /* A fatal error / die occurred during the generator execution. Trying to clean @@ -227,8 +217,9 @@ ZEND_API void zend_generator_create_zval(zend_execute_data *call, zend_op_array zend_generator *generator; zend_execute_data *current_execute_data; zend_execute_data *execute_data; - zend_vm_stack current_stack = EG(argument_stack); + zend_vm_stack current_stack = EG(vm_stack); + current_stack->top = EG(vm_stack_top); /* Create a clone of closure, because it may be destroyed */ if (op_array->fn_flags & ZEND_ACC_CLOSURE) { zend_op_array *op_array_copy = (zend_op_array*)emalloc(sizeof(zend_op_array)); @@ -261,16 +252,19 @@ ZEND_API void zend_generator_create_zval(zend_execute_data *call, zend_op_array object_init_ex(return_value, zend_ce_generator); - if (Z_OBJ(EG(This))) { - Z_ADDREF(EG(This)); + if (Z_OBJ(call->This)) { + Z_ADDREF(call->This); } /* Save execution context in generator object. */ generator = (zend_generator *) Z_OBJ_P(return_value); execute_data->prev_execute_data = NULL; generator->execute_data = execute_data; - generator->stack = EG(argument_stack); - EG(argument_stack) = current_stack; + generator->stack = EG(vm_stack); + generator->stack->top = EG(vm_stack_top); + EG(vm_stack_top) = current_stack->top; + EG(vm_stack_end) = current_stack->end; + EG(vm_stack) = current_stack; /* EX(return_value) keeps pointer to zend_object (not a real zval) */ execute_data->return_value = (zval*)generator; @@ -302,17 +296,16 @@ ZEND_API void zend_generator_resume(zend_generator *generator TSRMLS_DC) /* {{{ { /* Backup executor globals */ zend_execute_data *original_execute_data = EG(current_execute_data); - zend_object *original_This; zend_class_entry *original_scope = EG(scope); - zend_vm_stack original_stack = EG(argument_stack); - - original_This = Z_OBJ(EG(This)); + zend_vm_stack original_stack = EG(vm_stack); + original_stack->top = EG(vm_stack_top); /* Set executor globals */ EG(current_execute_data) = generator->execute_data; - Z_OBJ(EG(This)) = generator->execute_data->object; EG(scope) = generator->execute_data->scope; - EG(argument_stack) = generator->stack; + EG(vm_stack_top) = generator->stack->top; + EG(vm_stack_end) = generator->stack->end; + EG(vm_stack) = generator->stack; /* We want the backtrace to look as if the generator function was * called from whatever method we are current running (e.g. next()). @@ -332,9 +325,10 @@ ZEND_API void zend_generator_resume(zend_generator *generator TSRMLS_DC) /* {{{ /* Restore executor globals */ EG(current_execute_data) = original_execute_data; - Z_OBJ(EG(This)) = original_This; EG(scope) = original_scope; - EG(argument_stack) = original_stack; + EG(vm_stack_top) = original_stack->top; + EG(vm_stack_end) = original_stack->end; + EG(vm_stack) = original_stack; /* If an exception was thrown in the generator we have to internally * rethrow it in the parent scope. */ diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index 69e1cf9e68..89abb445e9 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -91,7 +91,6 @@ struct _zend_compiler_globals { zend_bool parse_error; zend_bool in_compilation; zend_bool short_tags; - zend_bool asp_tags; zend_declarables declarables; @@ -165,16 +164,18 @@ struct _zend_executor_globals { JMP_BUF *bailout; int error_reporting; - int orig_error_reporting; int exit_status; HashTable *function_table; /* function symbol table */ HashTable *class_table; /* class table */ HashTable *zend_constants; /* constants table */ - zend_class_entry *scope; + zval *vm_stack_top; + zval *vm_stack_end; + zend_vm_stack vm_stack; - zval This; + struct _zend_execute_data *current_execute_data; + zend_class_entry *scope; zend_long precision; @@ -195,8 +196,6 @@ struct _zend_executor_globals { HashTable regular_list; HashTable persistent_list; - zend_vm_stack argument_stack; - int user_error_handler_error_reporting; zval user_error_handler; zval user_exception_handler; @@ -221,12 +220,8 @@ struct _zend_executor_globals { const zend_op *opline_before_exception; zend_op exception_op[3]; - struct _zend_execute_data *current_execute_data; - struct _zend_module_entry *current_module; - zend_property_info std_property_info; - zend_bool active; zend_bool valid_symbol_table; diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c index 6304737f04..6dc0941c6f 100644 --- a/Zend/zend_hash.c +++ b/Zend/zend_hash.c @@ -99,19 +99,34 @@ static const uint32_t uninitialized_bucket = {INVALID_IDX}; ZEND_API void _zend_hash_init(HashTable *ht, uint32_t nSize, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC) { - uint32_t i = 3; - - SET_INCONSISTENT(HT_OK); - - if (nSize >= 0x80000000) { + /* Use big enough power of 2 */ +#ifdef PHP_WIN32 + if (nSize <= 8) { + ht->nTableSize = 8; + } else if (nSize >= 0x80000000) { /* prevent overflow */ ht->nTableSize = 0x80000000; } else { - while ((1U << i) < nSize) { - i++; + ht->nTableSize = 1U << __lzcnt(nSize); + if (ht->nTableSize < nSize) { + ht->nTableSize <<= 1; } - ht->nTableSize = 1 << i; } +#else + /* size should be between 8 and 0x80000000 */ + nSize = (nSize <= 8 ? 8 : (nSize >= 0x80000000 ? 0x80000000 : nSize)); +# if defined(__GNUC__) + ht->nTableSize = 0x2 << (__builtin_clz(nSize - 1) ^ 0x1f); +# else + nSize -= 1; + nSize |= (nSize >> 1); + nSize |= (nSize >> 2); + nSize |= (nSize >> 4); + nSize |= (nSize >> 8); + nSize |= (nSize >> 16); + ht->nTableSize = nSize + 1; +# endif +#endif ht->nTableMask = 0; /* 0 means that ht->arBuckets is uninitialized */ ht->nNumUsed = 0; @@ -121,11 +136,7 @@ ZEND_API void _zend_hash_init(HashTable *ht, uint32_t nSize, dtor_func_t pDestru ht->arHash = (uint32_t*)&uninitialized_bucket; ht->pDestructor = pDestructor; ht->nInternalPointer = INVALID_IDX; - if (persistent) { - ht->u.flags = HASH_FLAG_PERSISTENT | HASH_FLAG_APPLY_PROTECTION; - } else { - ht->u.flags = HASH_FLAG_APPLY_PROTECTION; - } + ht->u.flags = (persistent ? HASH_FLAG_PERSISTENT : 0) | HASH_FLAG_APPLY_PROTECTION; } static void zend_hash_packed_grow(HashTable *ht) @@ -444,11 +455,15 @@ static zend_always_inline zval *_zend_hash_index_add_or_update_i(HashTable *ht, HANDLE_BLOCK_INTERRUPTIONS(); /* incremental initialization of empty Buckets */ - if (h >= ht->nNumUsed) { - Bucket *q = ht->arData + ht->nNumUsed; - while (q != p) { - ZVAL_UNDEF(&q->val); - q++; + if ((flag & (HASH_ADD_NEW|HASH_ADD_NEXT)) == (HASH_ADD_NEW|HASH_ADD_NEXT)) { + ht->nNumUsed = h + 1; + } else if (h >= ht->nNumUsed) { + if (h > ht->nNumUsed) { + Bucket *q = ht->arData + ht->nNumUsed; + while (q != p) { + ZVAL_UNDEF(&q->val); + q++; + } } ht->nNumUsed = h + 1; } @@ -537,12 +552,12 @@ ZEND_API zval *_zend_hash_index_update(HashTable *ht, zend_ulong h, zval *pData ZEND_API zval *_zend_hash_next_index_insert(HashTable *ht, zval *pData ZEND_FILE_LINE_DC) { - return _zend_hash_index_add_or_update_i(ht, ht->nNextFreeElement, pData, HASH_ADD ZEND_FILE_LINE_RELAY_CC); + return _zend_hash_index_add_or_update_i(ht, ht->nNextFreeElement, pData, HASH_ADD | HASH_ADD_NEXT ZEND_FILE_LINE_RELAY_CC); } ZEND_API zval *_zend_hash_next_index_insert_new(HashTable *ht, zval *pData ZEND_FILE_LINE_DC) { - return _zend_hash_index_add_or_update_i(ht, ht->nNextFreeElement, pData, HASH_ADD | HASH_ADD_NEW ZEND_FILE_LINE_RELAY_CC); + return _zend_hash_index_add_or_update_i(ht, ht->nNextFreeElement, pData, HASH_ADD | HASH_ADD_NEW | HASH_ADD_NEXT ZEND_FILE_LINE_RELAY_CC); } static void zend_hash_do_resize(HashTable *ht) @@ -1745,11 +1760,12 @@ ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t co return result; } } else { /* string indices */ - result = (p1->key ? p1->key->len : 0) - (p2->key ? p2->key->len : 0); - if (result != 0) { + size_t len0 = (p1->key ? p1->key->len : 0); + size_t len1 = (p2->key ? p2->key->len : 0); + if (len0 != len1) { HASH_UNPROTECT_RECURSION(ht1); HASH_UNPROTECT_RECURSION(ht2); - return result; + return len0 > len1 ? 1 : -1; } result = memcmp(p1->key->val, p2->key->val, p1->key->len); if (result != 0) { diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h index 5c27873aa1..0ed47b424d 100644 --- a/Zend/zend_hash.h +++ b/Zend/zend_hash.h @@ -32,6 +32,7 @@ #define HASH_ADD (1<<1) #define HASH_UPDATE_INDIRECT (1<<2) #define HASH_ADD_NEW (1<<3) +#define HASH_ADD_NEXT (1<<4) #define INVALID_IDX ((uint32_t) -1) @@ -170,9 +171,10 @@ ZEND_API void zend_hash_internal_pointer_reset_ex(HashTable *ht, HashPosition *p ZEND_API void zend_hash_internal_pointer_end_ex(HashTable *ht, HashPosition *pos); typedef struct _HashPointer { - HashPosition pos; - HashTable *ht; - zend_ulong h; + HashPosition pos; + HashTable *ht; + zend_ulong h; + zend_string *key; } HashPointer; #define zend_hash_has_more_elements(ht) \ @@ -221,6 +223,8 @@ void zend_hash_display_pListTail(const HashTable *ht); void zend_hash_display(const HashTable *ht); #endif +ZEND_API int _zend_handle_numeric_str_ex(const char *key, size_t length, zend_ulong *idx); + END_EXTERN_C() #define ZEND_INIT_SYMTABLE(ht) \ @@ -229,8 +233,6 @@ END_EXTERN_C() #define ZEND_INIT_SYMTABLE_EX(ht, n, persistent) \ zend_hash_init(ht, n, NULL, ZVAL_PTR_DTOR, persistent) -ZEND_API int _zend_handle_numeric_str_ex(const char *key, size_t length, zend_ulong *idx); - static zend_always_inline int _zend_handle_numeric_str(const char *key, size_t length, zend_ulong *idx) { register const char *tmp = key; @@ -275,7 +277,7 @@ static zend_always_inline int zend_hash_exists_ind(const HashTable *ht, zend_str } -static zend_always_inline zval *zend_hash_str_find_ind(const HashTable *ht, const char *str, int len) +static zend_always_inline zval *zend_hash_str_find_ind(const HashTable *ht, const char *str, size_t len) { zval *zv; @@ -368,7 +370,7 @@ static zend_always_inline int zend_symtable_exists(HashTable *ht, zend_string *k } -static zend_always_inline zval *zend_symtable_str_update(HashTable *ht, const char *str, int len, zval *pData) +static zend_always_inline zval *zend_symtable_str_update(HashTable *ht, const char *str, size_t len, zval *pData) { zend_ulong idx; @@ -380,7 +382,7 @@ static zend_always_inline zval *zend_symtable_str_update(HashTable *ht, const ch } -static zend_always_inline zval *zend_symtable_str_update_ind(HashTable *ht, const char *str, int len, zval *pData) +static zend_always_inline zval *zend_symtable_str_update_ind(HashTable *ht, const char *str, size_t len, zval *pData) { zend_ulong idx; @@ -392,7 +394,7 @@ static zend_always_inline zval *zend_symtable_str_update_ind(HashTable *ht, cons } -static zend_always_inline int zend_symtable_str_del(HashTable *ht, const char *str, int len) +static zend_always_inline int zend_symtable_str_del(HashTable *ht, const char *str, size_t len) { zend_ulong idx; @@ -404,7 +406,7 @@ static zend_always_inline int zend_symtable_str_del(HashTable *ht, const char *s } -static zend_always_inline int zend_symtable_str_del_ind(HashTable *ht, const char *str, int len) +static zend_always_inline int zend_symtable_str_del_ind(HashTable *ht, const char *str, size_t len) { zend_ulong idx; @@ -416,7 +418,7 @@ static zend_always_inline int zend_symtable_str_del_ind(HashTable *ht, const cha } -static zend_always_inline zval *zend_symtable_str_find(HashTable *ht, const char *str, int len) +static zend_always_inline zval *zend_symtable_str_find(HashTable *ht, const char *str, size_t len) { zend_ulong idx; @@ -428,7 +430,7 @@ static zend_always_inline zval *zend_symtable_str_find(HashTable *ht, const char } -static zend_always_inline int zend_symtable_str_exists(HashTable *ht, const char *str, int len) +static zend_always_inline int zend_symtable_str_exists(HashTable *ht, const char *str, size_t len) { zend_ulong idx; @@ -457,7 +459,7 @@ static zend_always_inline void *zend_hash_add_new_ptr(HashTable *ht, zend_string return zv ? Z_PTR_P(zv) : NULL; } -static zend_always_inline void *zend_hash_str_add_ptr(HashTable *ht, const char *str, int len, void *pData) +static zend_always_inline void *zend_hash_str_add_ptr(HashTable *ht, const char *str, size_t len, void *pData) { zval tmp, *zv; @@ -475,7 +477,7 @@ static zend_always_inline void *zend_hash_update_ptr(HashTable *ht, zend_string return zv ? Z_PTR_P(zv) : NULL; } -static zend_always_inline void *zend_hash_str_update_ptr(HashTable *ht, const char *str, int len, void *pData) +static zend_always_inline void *zend_hash_str_update_ptr(HashTable *ht, const char *str, size_t len, void *pData) { zval tmp, *zv; @@ -497,7 +499,7 @@ static zend_always_inline void *zend_hash_add_mem(HashTable *ht, zend_string *ke return NULL; } -static zend_always_inline void *zend_hash_str_add_mem(HashTable *ht, const char *str, int len, void *pData, size_t size) +static zend_always_inline void *zend_hash_str_add_mem(HashTable *ht, const char *str, size_t len, void *pData, size_t size) { zval tmp, *zv; @@ -519,7 +521,7 @@ static zend_always_inline void *zend_hash_update_mem(HashTable *ht, zend_string return zend_hash_update_ptr(ht, key, p); } -static zend_always_inline void *zend_hash_str_update_mem(HashTable *ht, const char *str, int len, void *pData, size_t size) +static zend_always_inline void *zend_hash_str_update_mem(HashTable *ht, const char *str, size_t len, void *pData, size_t size) { void *p; @@ -537,6 +539,19 @@ static zend_always_inline void *zend_hash_index_update_ptr(HashTable *ht, zend_u return zv ? Z_PTR_P(zv) : NULL; } +static zend_always_inline void *zend_hash_index_add_mem(HashTable *ht, zend_ulong h, void *pData, size_t size) +{ + zval tmp, *zv; + + ZVAL_PTR(&tmp, NULL); + if ((zv = zend_hash_index_add(ht, h, &tmp))) { + Z_PTR_P(zv) = pemalloc(size, ht->u.flags & HASH_FLAG_PERSISTENT); + memcpy(Z_PTR_P(zv), pData, size); + return Z_PTR_P(zv); + } + return NULL; +} + static zend_always_inline void *zend_hash_next_index_insert_ptr(HashTable *ht, void *pData) { zval tmp, *zv; @@ -576,7 +591,7 @@ static zend_always_inline void *zend_hash_find_ptr(const HashTable *ht, zend_str return zv ? Z_PTR_P(zv) : NULL; } -static zend_always_inline void *zend_hash_str_find_ptr(const HashTable *ht, const char *str, int len) +static zend_always_inline void *zend_hash_str_find_ptr(const HashTable *ht, const char *str, size_t len) { zval *zv; @@ -592,7 +607,7 @@ static zend_always_inline void *zend_hash_index_find_ptr(const HashTable *ht, ze return zv ? Z_PTR_P(zv) : NULL; } -static zend_always_inline void *zend_symtable_str_find_ptr(HashTable *ht, const char *str, int len) +static zend_always_inline void *zend_symtable_str_find_ptr(HashTable *ht, const char *str, size_t len) { zend_ulong idx; @@ -694,6 +709,11 @@ static zend_always_inline void *zend_hash_get_current_data_ptr_ex(HashTable *ht, _key = _p->key; \ _val = _z; +#define ZEND_HASH_FOREACH_NUM_KEY_PTR(ht, _h, _ptr) \ + ZEND_HASH_FOREACH(ht, 0); \ + _h = _p->h; \ + _ptr = Z_PTR_P(_z); + #define ZEND_HASH_FOREACH_STR_KEY_PTR(ht, _key, _ptr) \ ZEND_HASH_FOREACH(ht, 0); \ _key = _p->key; \ diff --git a/Zend/zend_highlight.c b/Zend/zend_highlight.c index 26c34686a6..79a552635f 100644 --- a/Zend/zend_highlight.c +++ b/Zend/zend_highlight.c @@ -54,7 +54,7 @@ ZEND_API void zend_html_putc(char c) } -ZEND_API void zend_html_puts(const char *s, uint len TSRMLS_DC) +ZEND_API void zend_html_puts(const char *s, size_t len TSRMLS_DC) { const unsigned char *ptr = (const unsigned char*)s, *end = ptr + len; unsigned char *filtered = NULL; diff --git a/Zend/zend_highlight.h b/Zend/zend_highlight.h index 1a35505135..3e91fd71f4 100644 --- a/Zend/zend_highlight.h +++ b/Zend/zend_highlight.h @@ -44,7 +44,7 @@ ZEND_API void zend_strip(TSRMLS_D); ZEND_API int highlight_file(char *filename, zend_syntax_highlighter_ini *syntax_highlighter_ini TSRMLS_DC); ZEND_API int highlight_string(zval *str, zend_syntax_highlighter_ini *syntax_highlighter_ini, char *str_name TSRMLS_DC); ZEND_API void zend_html_putc(char c); -ZEND_API void zend_html_puts(const char *s, uint len TSRMLS_DC); +ZEND_API void zend_html_puts(const char *s, size_t len TSRMLS_DC); END_EXTERN_C() extern zend_syntax_highlighter_ini syntax_highlighter_ini; diff --git a/Zend/zend_indent.c b/Zend/zend_indent.c index 5ebc4527e2..93c10108f8 100644 --- a/Zend/zend_indent.c +++ b/Zend/zend_indent.c @@ -52,9 +52,9 @@ ZEND_API void zend_indent(TSRMLS_D) zval token; int token_type; int in_string=0; - int nest_level=0; - int emit_whitespace[256]; - int i; + unsigned int nest_level=0; + unsigned int emit_whitespace[256]; + unsigned int i; memset(emit_whitespace, 0, sizeof(int)*256); diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 5cc970ee92..c6f8c6ae15 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -119,8 +119,14 @@ static void do_inherit_parent_constructor(zend_class_entry *ce TSRMLS_DC) /* {{{ if ((function = zend_hash_str_find_ptr(&ce->parent->function_table, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1)) != NULL) { /* inherit parent's constructor */ if (function->type == ZEND_INTERNAL_FUNCTION) { - new_function = pemalloc(sizeof(zend_internal_function), 1); - memcpy(new_function, function, sizeof(zend_internal_function)); + if (ce->type & ZEND_INTERNAL_CLASS) { + new_function = pemalloc(sizeof(zend_internal_function), 1); + memcpy(new_function, function, sizeof(zend_internal_function)); + } else { + new_function = zend_arena_alloc(&CG(arena), sizeof(zend_internal_function)); + memcpy(new_function, function, sizeof(zend_internal_function)); + new_function->common.fn_flags |= ZEND_ACC_ARENA_ALLOCATED; + } } else { new_function = zend_arena_alloc(&CG(arena), sizeof(zend_op_array)); memcpy(new_function, function, sizeof(zend_op_array)); @@ -141,8 +147,19 @@ static void do_inherit_parent_constructor(zend_class_entry *ce TSRMLS_DC) /* {{{ (function = zend_hash_find_ptr(&ce->parent->function_table, lc_parent_class_name)) != NULL) { if (function->common.fn_flags & ZEND_ACC_CTOR) { /* inherit parent's constructor */ - new_function = pemalloc(sizeof(zend_function), function->type == ZEND_INTERNAL_FUNCTION); - memcpy(new_function, function, sizeof(zend_function)); + if (function->type == ZEND_INTERNAL_FUNCTION) { + if (ce->type & ZEND_INTERNAL_CLASS) { + new_function = pemalloc(sizeof(zend_internal_function), 1); + memcpy(new_function, function, sizeof(zend_internal_function)); + } else { + new_function = zend_arena_alloc(&CG(arena), sizeof(zend_internal_function)); + memcpy(new_function, function, sizeof(zend_internal_function)); + new_function->common.fn_flags |= ZEND_ACC_ARENA_ALLOCATED; + } + } else { + new_function = zend_arena_alloc(&CG(arena), sizeof(zend_op_array)); + memcpy(new_function, function, sizeof(zend_op_array)); + } zend_hash_update_ptr(&ce->function_table, lc_parent_class_name, new_function); function_add_ref(new_function); } @@ -170,13 +187,19 @@ char *zend_visibility_string(uint32_t fn_flags) /* {{{ */ } /* }}} */ -static zend_function *do_inherit_method(zend_function *old_function TSRMLS_DC) /* {{{ */ +static zend_function *do_inherit_method(zend_function *old_function, zend_class_entry *ce TSRMLS_DC) /* {{{ */ { zend_function *new_function; if (old_function->type == ZEND_INTERNAL_FUNCTION) { - new_function = pemalloc(sizeof(zend_internal_function), 1); - memcpy(new_function, old_function, sizeof(zend_internal_function)); + if (ce->type & ZEND_INTERNAL_CLASS) { + new_function = pemalloc(sizeof(zend_internal_function), 1); + memcpy(new_function, old_function, sizeof(zend_internal_function)); + } else { + new_function = zend_arena_alloc(&CG(arena), sizeof(zend_internal_function)); + memcpy(new_function, old_function, sizeof(zend_internal_function)); + new_function->common.fn_flags |= ZEND_ACC_ARENA_ALLOCATED; + } } else { new_function = zend_arena_alloc(&CG(arena), sizeof(zend_op_array)); memcpy(new_function, old_function, sizeof(zend_op_array)); @@ -349,7 +372,7 @@ static zend_string *zend_get_function_declaration(zend_function *fptr TSRMLS_DC) for (i = 0; i < fptr->common.num_args;) { if (arg_info->class_name) { const char *class_name; - uint32_t class_name_len; + size_t class_name_len; if (!strcasecmp(arg_info->class_name, "self") && fptr->common.scope) { class_name = fptr->common.scope->name->val; class_name_len = fptr->common.scope->name->len; @@ -796,7 +819,7 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent ZEND_HASH_FOREACH_STR_KEY_PTR(&parent_ce->function_table, key, func) { if (do_inherit_method_check(&ce->function_table, func, key, ce)) { - zend_function *new_func = do_inherit_method(func TSRMLS_CC); + zend_function *new_func = do_inherit_method(func, ce TSRMLS_CC); zend_hash_add_new_ptr(&ce->function_table, key, new_func); } } ZEND_HASH_FOREACH_END(); @@ -884,7 +907,7 @@ ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry ZEND_HASH_FOREACH_STR_KEY_PTR(&iface->function_table, key, func) { if (do_inherit_method_check(&ce->function_table, func, key, ce)) { - zend_function *new_func = do_inherit_method(func TSRMLS_CC); + zend_function *new_func = do_inherit_method(func, ce TSRMLS_CC); zend_hash_add_new_ptr(&ce->function_table, key, new_func); } } ZEND_HASH_FOREACH_END(); diff --git a/Zend/zend_ini.c b/Zend/zend_ini.c index e60e58d2aa..0b13f43315 100644 --- a/Zend/zend_ini.c +++ b/Zend/zend_ini.c @@ -658,7 +658,7 @@ ZEND_API ZEND_INI_MH(OnUpdateLong) /* {{{ */ p = (zend_long *) (base+(size_t) mh_arg1); - *p = zend_atol(new_value->val, new_value->len); + *p = zend_atol(new_value->val, (int)new_value->len); return SUCCESS; } /* }}} */ @@ -674,7 +674,7 @@ ZEND_API ZEND_INI_MH(OnUpdateLongGEZero) /* {{{ */ base = (char *) ts_resource(*((int *) mh_arg2)); #endif - tmp = zend_atol(new_value->val, new_value->len); + tmp = zend_atol(new_value->val, (int)new_value->len); if (tmp < 0) { return FAILURE; } diff --git a/Zend/zend_ini_parser.y b/Zend/zend_ini_parser.y index e343fcd92a..d04988442f 100644 --- a/Zend/zend_ini_parser.y +++ b/Zend/zend_ini_parser.y @@ -43,6 +43,11 @@ int ini_parse(void); #define ZEND_INI_PARSER_CB (CG(ini_parser_param))->ini_parser_cb #define ZEND_INI_PARSER_ARG (CG(ini_parser_param))->arg +#ifdef _MSC_VER +#define YYMALLOC malloc +#define YYFREE free +#endif + /* {{{ zend_ini_do_op() */ static void zend_ini_do_op(char type, zval *result, zval *op1, zval *op2) @@ -99,8 +104,8 @@ static void zend_ini_init_string(zval *result) */ static void zend_ini_add_string(zval *result, zval *op1, zval *op2) { - int op1_len = Z_STRLEN_P(op1); - int length = op1_len + Z_STRLEN_P(op2); + int op1_len = (int)Z_STRLEN_P(op1); + int length = op1_len + (int)Z_STRLEN_P(op2); ZVAL_NEW_STR(result, zend_string_realloc(Z_STR_P(op1), length, 1)); memcpy(Z_STRVAL_P(result)+op1_len, Z_STRVAL_P(op2), Z_STRLEN_P(op2)); @@ -168,7 +173,7 @@ static void ini_error(const char *msg) currently_parsed_filename = zend_ini_scanner_get_filename(TSRMLS_C); if (currently_parsed_filename) { - error_buf_len = 128 + strlen(msg) + strlen(currently_parsed_filename); /* should be more than enough */ + error_buf_len = 128 + (int)strlen(msg) + (int)strlen(currently_parsed_filename); /* should be more than enough */ error_buf = (char *) emalloc(error_buf_len); sprintf(error_buf, "%s in %s on line %d\n", msg, currently_parsed_filename, zend_ini_scanner_get_lineno(TSRMLS_C)); diff --git a/Zend/zend_ini_scanner.c b/Zend/zend_ini_scanner.c index 2abf1140fc..61e7575dad 100644 --- a/Zend/zend_ini_scanner.c +++ b/Zend/zend_ini_scanner.c @@ -283,7 +283,7 @@ int zend_ini_open_file_for_scanning(zend_file_handle *fh, int scanner_mode TSRML return FAILURE; } - yy_scan_buffer(buf, size TSRMLS_CC); + yy_scan_buffer(buf, (unsigned int)size TSRMLS_CC); return SUCCESS; } @@ -293,7 +293,7 @@ int zend_ini_open_file_for_scanning(zend_file_handle *fh, int scanner_mode TSRML */ int zend_ini_prepare_string_for_scanning(char *str, int scanner_mode TSRMLS_DC) { - int len = strlen(str); + int len = (int)strlen(str); if (init_ini_scanner(scanner_mode, NULL TSRMLS_CC) == FAILURE) { return FAILURE; diff --git a/Zend/zend_ini_scanner.l b/Zend/zend_ini_scanner.l index 3bfb1557b1..79d82764b1 100644 --- a/Zend/zend_ini_scanner.l +++ b/Zend/zend_ini_scanner.l @@ -281,7 +281,7 @@ int zend_ini_open_file_for_scanning(zend_file_handle *fh, int scanner_mode TSRML return FAILURE; } - yy_scan_buffer(buf, size TSRMLS_CC); + yy_scan_buffer(buf, (unsigned int)size TSRMLS_CC); return SUCCESS; } @@ -291,7 +291,7 @@ int zend_ini_open_file_for_scanning(zend_file_handle *fh, int scanner_mode TSRML */ int zend_ini_prepare_string_for_scanning(char *str, int scanner_mode TSRMLS_DC) { - int len = strlen(str); + int len = (int)strlen(str); if (init_ini_scanner(scanner_mode, NULL TSRMLS_CC) == FAILURE) { return FAILURE; diff --git a/Zend/zend_interfaces.c b/Zend/zend_interfaces.c index 26507ad23b..f076289201 100644 --- a/Zend/zend_interfaces.c +++ b/Zend/zend_interfaces.c @@ -31,7 +31,7 @@ ZEND_API zend_class_entry *zend_ce_serializable; /* {{{ zend_call_method Only returns the returned zval if retval_ptr != NULL */ -ZEND_API zval* zend_call_method(zval *object, zend_class_entry *obj_ce, zend_function **fn_proxy, const char *function_name, int function_name_len, zval *retval_ptr, int param_count, zval* arg1, zval* arg2 TSRMLS_DC) +ZEND_API zval* zend_call_method(zval *object, zend_class_entry *obj_ce, zend_function **fn_proxy, const char *function_name, size_t function_name_len, zval *retval_ptr, int param_count, zval* arg1, zval* arg2 TSRMLS_DC) { int result; zend_fcall_info fci; @@ -282,8 +282,7 @@ ZEND_API zend_object_iterator *zend_user_it_get_new_iterator(zend_class_entry *c zend_class_entry *ce_it; zend_user_it_new_iterator(ce, object, &iterator TSRMLS_CC); - ce_it = (Z_TYPE(iterator) == IS_OBJECT && - Z_OBJ_HT(iterator)->get_class_entry) ? Z_OBJCE(iterator) : NULL; + ce_it = (Z_TYPE(iterator) == IS_OBJECT) ? Z_OBJCE(iterator) : NULL; if (!ce_it || !ce_it->get_iterator || (ce_it->get_iterator == zend_user_it_get_new_iterator && Z_OBJ(iterator) == Z_OBJ_P(object))) { if (!EG(exception)) { diff --git a/Zend/zend_interfaces.h b/Zend/zend_interfaces.h index 9bfef0990d..dff05bc701 100644 --- a/Zend/zend_interfaces.h +++ b/Zend/zend_interfaces.h @@ -38,7 +38,7 @@ typedef struct _zend_user_iterator { zval value; } zend_user_iterator; -ZEND_API zval* zend_call_method(zval *object_pp, zend_class_entry *obj_ce, zend_function **fn_proxy, const char *function_name, int function_name_len, zval *retval, int param_count, zval* arg1, zval* arg2 TSRMLS_DC); +ZEND_API zval* zend_call_method(zval *object_pp, zend_class_entry *obj_ce, zend_function **fn_proxy, const char *function_name, size_t function_name_len, zval *retval, int param_count, zval* arg1, zval* arg2 TSRMLS_DC); #define zend_call_method_with_0_params(obj, obj_ce, fn_proxy, function_name, retval) \ zend_call_method(obj, obj_ce, fn_proxy, function_name, sizeof(function_name)-1, retval, 0, NULL, NULL TSRMLS_CC) diff --git a/Zend/zend_iterators.c b/Zend/zend_iterators.c index c2f51c4dd6..8edd5dbdc4 100644 --- a/Zend/zend_iterators.c +++ b/Zend/zend_iterators.c @@ -47,7 +47,6 @@ static zend_object_handlers iterator_object_handlers = { NULL, /* method get */ NULL, /* call */ NULL, /* get ctor */ - NULL, /* get_ce */ NULL, /* get class name */ NULL, /* compare */ NULL, /* cast */ diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index 6bfef2219e..88286203da 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -43,6 +43,11 @@ static YYSIZE_T zend_yytnamerr(char*, const char*); #define YYERROR_VERBOSE #define YYSTYPE zend_parser_stack_elem +#ifdef _MSC_VER +#define YYMALLOC malloc +#define YYFREE free +#endif + %} %pure_parser @@ -67,6 +72,7 @@ static YYSIZE_T zend_yytnamerr(char*, const char*); %right T_YIELD %left '=' T_PLUS_EQUAL T_MINUS_EQUAL T_MUL_EQUAL T_DIV_EQUAL T_CONCAT_EQUAL T_MOD_EQUAL T_AND_EQUAL T_OR_EQUAL T_XOR_EQUAL T_SL_EQUAL T_SR_EQUAL T_POW_EQUAL %left '?' ':' +%right T_COALESCE %left T_BOOLEAN_OR %left T_BOOLEAN_AND %left '|' @@ -221,6 +227,7 @@ static YYSIZE_T zend_yytnamerr(char*, const char*); %token T_NS_C "__NAMESPACE__ (T_NS_C)" %token T_NS_SEPARATOR "\\ (T_NS_SEPARATOR)" %token T_ELLIPSIS "... (T_ELLIPSIS)" +%token T_COALESCE "?? (T_COALESCE)" %token T_POW "** (T_POW)" %token T_POW_EQUAL "**= (T_POW_EQUAL)" @@ -827,6 +834,8 @@ expr_without_variable: { $$ = zend_ast_create(ZEND_AST_CONDITIONAL, $1, $3, $5); } | expr '?' ':' expr { $$ = zend_ast_create(ZEND_AST_CONDITIONAL, $1, NULL, $4); } + | expr T_COALESCE expr + { $$ = zend_ast_create(ZEND_AST_COALESCE, $1, $3); } | internal_functions_in_yacc { $$ = $1; } | T_INT_CAST expr { $$ = zend_ast_create_cast(IS_LONG, $2); } | T_DOUBLE_CAST expr { $$ = zend_ast_create_cast(IS_DOUBLE, $2); } @@ -1183,7 +1192,7 @@ static YYSIZE_T zend_yytnamerr(char *yyres, const char *yystr) str = LANG_SCNG(yy_text); end = memchr(str, '\n', LANG_SCNG(yy_leng)); - yystr_len = yystrlen(yystr); + yystr_len = (unsigned int)yystrlen(yystr); if ((tok1 = memchr(yystr, '(', yystr_len)) != NULL && (tok2 = zend_memrchr(yystr, ')', yystr_len)) != NULL) { diff --git a/Zend/zend_language_scanner.c b/Zend/zend_language_scanner.c index 5bd2798cde..7a7c04b0d2 100644 --- a/Zend/zend_language_scanner.c +++ b/Zend/zend_language_scanner.c @@ -286,7 +286,8 @@ static const zend_encoding *zend_multibyte_detect_utf_encoding(const unsigned ch /* utf-16 or utf-32? */ p = script; - while ((p-script) < script_size) { + assert(p >= script); + while ((size_t)(p-script) < script_size) { p = memchr(p, 0, script_size-(p-script)-2); if (!p) { break; @@ -302,7 +303,8 @@ static const zend_encoding *zend_multibyte_detect_utf_encoding(const unsigned ch /* BE or LE? */ p = script; - while ((p-script) < script_size) { + assert(p >= script); + while ((size_t)(p-script) < script_size) { if (*p == '\0' && *(p+wchar_size-1) != '\0') { /* BE */ le = 0; @@ -522,7 +524,7 @@ ZEND_API int open_file_for_scanning(zend_file_handle *file_handle TSRMLS_DC) } } SCNG(yy_start) = (unsigned char *)buf - offset; - yy_scan_buffer(buf, size TSRMLS_CC); + yy_scan_buffer(buf, (unsigned int)size TSRMLS_CC); } else { zend_error_noreturn(E_COMPILE_ERROR, "zend_stream_mmap() failed"); } @@ -683,7 +685,7 @@ ZEND_API int zend_prepare_string_for_scanning(zval *str, char *filename TSRMLS_D } } - yy_scan_buffer(buf, size TSRMLS_CC); + yy_scan_buffer(buf, (unsigned int)size TSRMLS_CC); new_compiled_filename = zend_string_init(filename, strlen(filename), 0); zend_set_compiled_filename(new_compiled_filename TSRMLS_CC); @@ -991,8 +993,6 @@ int lex_scan(zval *zendlval TSRMLS_DC) restart: SCNG(yy_text) = YYCURSOR; -yymore_restart: - #line 998 "Zend/zend_language_scanner.c" { @@ -1037,64 +1037,19 @@ yymore_restart: } /* *********************************** */ yyc_INITIAL: - { - static const unsigned char yybm[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 128, 128, 0, 0, 128, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 128, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }; - YYDEBUG(0, *YYCURSOR); - YYFILL(8); - yych = *YYCURSOR; - if (yych != '<') goto yy4; - YYDEBUG(2, *YYCURSOR); - yyaccept = 0; - yych = *(YYMARKER = ++YYCURSOR); - if (yych <= '?') { - if (yych == '%') goto yy7; - if (yych >= '?') goto yy5; - } else { - if (yych <= 'S') { - if (yych >= 'S') goto yy9; - } else { - if (yych == 's') goto yy9; - } - } + YYDEBUG(0, *YYCURSOR); + YYFILL(7); + yych = *YYCURSOR; + if (yych != '<') goto yy4; + YYDEBUG(2, *YYCURSOR); + ++YYCURSOR; + if ((yych = *YYCURSOR) == '?') goto yy5; yy3: - YYDEBUG(3, *YYCURSOR); - yyleng = YYCURSOR - SCNG(yy_text); -#line 1663 "Zend/zend_language_scanner.l" - { + YYDEBUG(3, *YYCURSOR); + yyleng = YYCURSOR - SCNG(yy_text); +#line 1633 "Zend/zend_language_scanner.l" + { if (YYCURSOR > YYLIMIT) { return 0; } @@ -1106,39 +1061,23 @@ inline_char_handler: YYCURSOR = ptr ? ptr + 1 : YYLIMIT; - if (YYCURSOR < YYLIMIT) { - switch (*YYCURSOR) { - case '?': - if (CG(short_tags) || !strncasecmp((char*)YYCURSOR + 1, "php", 3) || (*(YYCURSOR + 1) == '=')) { /* Assume [ \t\n\r] follows "php" */ - break; - } - continue; - case '%': - if (CG(asp_tags)) { - break; - } - continue; - case 's': - case 'S': - /* Probably NOT an opening PHP <script> tag, so don't end the HTML chunk yet - * If it is, the PHP <script> tag rule checks for any HTML scanned before it */ - YYCURSOR--; - yymore(); - default: - continue; - } - - YYCURSOR--; + if (YYCURSOR >= YYLIMIT) { + break; } - break; + if (*YYCURSOR == '?') { + if (CG(short_tags) || !strncasecmp((char*)YYCURSOR + 1, "php", 3) || (*(YYCURSOR + 1) == '=')) { /* Assume [ \t\n\r] follows "php" */ + + YYCURSOR--; + break; + } + } } -inline_html: yyleng = YYCURSOR - SCNG(yy_text); if (SCNG(output_filter)) { - int readsize; + size_t readsize; char *s = NULL; size_t sz = 0; // TODO: avoid reallocation ??? @@ -1154,26 +1093,26 @@ inline_html: HANDLE_NEWLINES(yytext, yyleng); return T_INLINE_HTML; } -#line 1158 "Zend/zend_language_scanner.c" +#line 1097 "Zend/zend_language_scanner.c" yy4: - YYDEBUG(4, *YYCURSOR); - yych = *++YYCURSOR; - goto yy3; + YYDEBUG(4, *YYCURSOR); + yych = *++YYCURSOR; + goto yy3; yy5: - YYDEBUG(5, *YYCURSOR); - yyaccept = 1; - yych = *(YYMARKER = ++YYCURSOR); - if (yych <= 'O') { - if (yych == '=') goto yy45; - } else { - if (yych <= 'P') goto yy47; - if (yych == 'p') goto yy47; - } + YYDEBUG(5, *YYCURSOR); + yyaccept = 0; + yych = *(YYMARKER = ++YYCURSOR); + if (yych <= 'O') { + if (yych == '=') goto yy7; + } else { + if (yych <= 'P') goto yy9; + if (yych == 'p') goto yy9; + } yy6: - YYDEBUG(6, *YYCURSOR); - yyleng = YYCURSOR - SCNG(yy_text); -#line 1654 "Zend/zend_language_scanner.l" - { + YYDEBUG(6, *YYCURSOR); + yyleng = YYCURSOR - SCNG(yy_text); +#line 1624 "Zend/zend_language_scanner.l" + { if (CG(short_tags)) { BEGIN(ST_IN_SCRIPTING); return T_OPEN_TAG; @@ -1181,309 +1120,60 @@ yy6: goto inline_char_handler; } } -#line 1185 "Zend/zend_language_scanner.c" +#line 1124 "Zend/zend_language_scanner.c" yy7: - YYDEBUG(7, *YYCURSOR); - ++YYCURSOR; - if ((yych = *YYCURSOR) == '=') goto yy43; - YYDEBUG(8, *YYCURSOR); - yyleng = YYCURSOR - SCNG(yy_text); -#line 1637 "Zend/zend_language_scanner.l" - { - if (CG(asp_tags)) { - BEGIN(ST_IN_SCRIPTING); - return T_OPEN_TAG; - } else { - goto inline_char_handler; - } + YYDEBUG(7, *YYCURSOR); + ++YYCURSOR; + YYDEBUG(8, *YYCURSOR); + yyleng = YYCURSOR - SCNG(yy_text); +#line 1611 "Zend/zend_language_scanner.l" + { + BEGIN(ST_IN_SCRIPTING); + return T_OPEN_TAG_WITH_ECHO; } -#line 1201 "Zend/zend_language_scanner.c" +#line 1135 "Zend/zend_language_scanner.c" yy9: - YYDEBUG(9, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'C') goto yy11; - if (yych == 'c') goto yy11; + YYDEBUG(9, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'H') goto yy11; + if (yych == 'h') goto yy11; yy10: - YYDEBUG(10, *YYCURSOR); - YYCURSOR = YYMARKER; - if (yyaccept <= 0) { - goto yy3; - } else { - goto yy6; - } + YYDEBUG(10, *YYCURSOR); + YYCURSOR = YYMARKER; + goto yy6; yy11: - YYDEBUG(11, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'R') goto yy12; - if (yych != 'r') goto yy10; + YYDEBUG(11, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'P') goto yy12; + if (yych != 'p') goto yy10; yy12: - YYDEBUG(12, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'I') goto yy13; - if (yych != 'i') goto yy10; -yy13: - YYDEBUG(13, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'P') goto yy14; - if (yych != 'p') goto yy10; -yy14: - YYDEBUG(14, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'T') goto yy15; - if (yych != 't') goto yy10; -yy15: - YYDEBUG(15, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'L') goto yy10; - if (yych == 'l') goto yy10; - goto yy17; -yy16: - YYDEBUG(16, *YYCURSOR); - ++YYCURSOR; - YYFILL(8); - yych = *YYCURSOR; -yy17: - YYDEBUG(17, *YYCURSOR); - if (yybm[0+yych] & 128) { - goto yy16; - } - if (yych == 'L') goto yy18; - if (yych != 'l') goto yy10; -yy18: - YYDEBUG(18, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'A') goto yy19; - if (yych != 'a') goto yy10; -yy19: - YYDEBUG(19, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'N') goto yy20; - if (yych != 'n') goto yy10; -yy20: - YYDEBUG(20, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'G') goto yy21; - if (yych != 'g') goto yy10; -yy21: - YYDEBUG(21, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'U') goto yy22; - if (yych != 'u') goto yy10; -yy22: - YYDEBUG(22, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'A') goto yy23; - if (yych != 'a') goto yy10; -yy23: - YYDEBUG(23, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'G') goto yy24; - if (yych != 'g') goto yy10; -yy24: - YYDEBUG(24, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'E') goto yy25; - if (yych != 'e') goto yy10; -yy25: - YYDEBUG(25, *YYCURSOR); - ++YYCURSOR; - YYFILL(1); - yych = *YYCURSOR; - YYDEBUG(26, *YYCURSOR); - if (yych <= '\r') { - if (yych <= 0x08) goto yy10; - if (yych <= '\n') goto yy25; - if (yych <= '\f') goto yy10; - goto yy25; - } else { - if (yych <= ' ') { - if (yych <= 0x1F) goto yy10; - goto yy25; - } else { - if (yych != '=') goto yy10; - } - } -yy27: - YYDEBUG(27, *YYCURSOR); - ++YYCURSOR; - YYFILL(5); - yych = *YYCURSOR; - YYDEBUG(28, *YYCURSOR); - if (yych <= '!') { - if (yych <= '\f') { - if (yych <= 0x08) goto yy10; - if (yych <= '\n') goto yy27; - goto yy10; - } else { - if (yych <= '\r') goto yy27; - if (yych == ' ') goto yy27; - goto yy10; - } - } else { - if (yych <= 'O') { - if (yych <= '"') goto yy30; - if (yych == '\'') goto yy31; - goto yy10; - } else { - if (yych <= 'P') goto yy29; - if (yych != 'p') goto yy10; - } - } -yy29: - YYDEBUG(29, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'H') goto yy42; - if (yych == 'h') goto yy42; - goto yy10; -yy30: - YYDEBUG(30, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'P') goto yy39; - if (yych == 'p') goto yy39; - goto yy10; -yy31: - YYDEBUG(31, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'P') goto yy32; - if (yych != 'p') goto yy10; -yy32: - YYDEBUG(32, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'H') goto yy33; - if (yych != 'h') goto yy10; -yy33: - YYDEBUG(33, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'P') goto yy34; - if (yych != 'p') goto yy10; -yy34: - YYDEBUG(34, *YYCURSOR); - yych = *++YYCURSOR; - if (yych != '\'') goto yy10; -yy35: - YYDEBUG(35, *YYCURSOR); - ++YYCURSOR; - YYFILL(1); - yych = *YYCURSOR; - YYDEBUG(36, *YYCURSOR); - if (yych <= '\r') { - if (yych <= 0x08) goto yy10; - if (yych <= '\n') goto yy35; - if (yych <= '\f') goto yy10; - goto yy35; - } else { - if (yych <= ' ') { - if (yych <= 0x1F) goto yy10; - goto yy35; - } else { - if (yych != '>') goto yy10; - } - } - YYDEBUG(37, *YYCURSOR); - ++YYCURSOR; - YYDEBUG(38, *YYCURSOR); - yyleng = YYCURSOR - SCNG(yy_text); -#line 1606 "Zend/zend_language_scanner.l" - { - YYCTYPE *bracket = (YYCTYPE*)zend_memrchr(yytext, '<', yyleng - (sizeof("script language=php>") - 1)); - - if (bracket != SCNG(yy_text)) { - /* Handle previously scanned HTML, as possible <script> tags found are assumed to not be PHP's */ - YYCURSOR = bracket; - goto inline_html; - } - - HANDLE_NEWLINES(yytext, yyleng); - BEGIN(ST_IN_SCRIPTING); - return T_OPEN_TAG; -} -#line 1401 "Zend/zend_language_scanner.c" -yy39: - YYDEBUG(39, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'H') goto yy40; - if (yych != 'h') goto yy10; -yy40: - YYDEBUG(40, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'P') goto yy41; - if (yych != 'p') goto yy10; -yy41: - YYDEBUG(41, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == '"') goto yy35; - goto yy10; -yy42: - YYDEBUG(42, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'P') goto yy35; - if (yych == 'p') goto yy35; - goto yy10; -yy43: - YYDEBUG(43, *YYCURSOR); - ++YYCURSOR; - YYDEBUG(44, *YYCURSOR); - yyleng = YYCURSOR - SCNG(yy_text); -#line 1621 "Zend/zend_language_scanner.l" - { - if (CG(asp_tags)) { - BEGIN(ST_IN_SCRIPTING); - return T_OPEN_TAG_WITH_ECHO; + YYDEBUG(12, *YYCURSOR); + yych = *++YYCURSOR; + if (yych <= '\f') { + if (yych <= 0x08) goto yy10; + if (yych >= '\v') goto yy10; } else { - goto inline_char_handler; + if (yych <= '\r') goto yy15; + if (yych != ' ') goto yy10; } -} -#line 1437 "Zend/zend_language_scanner.c" -yy45: - YYDEBUG(45, *YYCURSOR); - ++YYCURSOR; - YYDEBUG(46, *YYCURSOR); - yyleng = YYCURSOR - SCNG(yy_text); -#line 1631 "Zend/zend_language_scanner.l" - { - BEGIN(ST_IN_SCRIPTING); - return T_OPEN_TAG_WITH_ECHO; -} -#line 1448 "Zend/zend_language_scanner.c" -yy47: - YYDEBUG(47, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'H') goto yy48; - if (yych != 'h') goto yy10; -yy48: - YYDEBUG(48, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'P') goto yy49; - if (yych != 'p') goto yy10; -yy49: - YYDEBUG(49, *YYCURSOR); - yych = *++YYCURSOR; - if (yych <= '\f') { - if (yych <= 0x08) goto yy10; - if (yych >= '\v') goto yy10; - } else { - if (yych <= '\r') goto yy52; - if (yych != ' ') goto yy10; - } -yy50: - YYDEBUG(50, *YYCURSOR); - ++YYCURSOR; -yy51: - YYDEBUG(51, *YYCURSOR); - yyleng = YYCURSOR - SCNG(yy_text); -#line 1647 "Zend/zend_language_scanner.l" - { +yy13: + YYDEBUG(13, *YYCURSOR); + ++YYCURSOR; +yy14: + YYDEBUG(14, *YYCURSOR); + yyleng = YYCURSOR - SCNG(yy_text); +#line 1617 "Zend/zend_language_scanner.l" + { HANDLE_NEWLINE(yytext[yyleng-1]); BEGIN(ST_IN_SCRIPTING); return T_OPEN_TAG; } -#line 1481 "Zend/zend_language_scanner.c" -yy52: - YYDEBUG(52, *YYCURSOR); - ++YYCURSOR; - if ((yych = *YYCURSOR) == '\n') goto yy50; - goto yy51; - } +#line 1172 "Zend/zend_language_scanner.c" +yy15: + YYDEBUG(15, *YYCURSOR); + ++YYCURSOR; + if ((yych = *YYCURSOR) == '\n') goto yy13; + goto yy14; /* *********************************** */ yyc_ST_BACKQUOTE: { @@ -1521,34 +1211,34 @@ yyc_ST_BACKQUOTE: 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, }; - YYDEBUG(53, *YYCURSOR); + YYDEBUG(16, *YYCURSOR); YYFILL(2); yych = *YYCURSOR; if (yych <= '_') { - if (yych != '$') goto yy60; + if (yych != '$') goto yy23; } else { - if (yych <= '`') goto yy58; - if (yych == '{') goto yy57; - goto yy60; + if (yych <= '`') goto yy21; + if (yych == '{') goto yy20; + goto yy23; } - YYDEBUG(55, *YYCURSOR); + YYDEBUG(18, *YYCURSOR); ++YYCURSOR; if ((yych = *YYCURSOR) <= '_') { - if (yych <= '@') goto yy56; - if (yych <= 'Z') goto yy63; - if (yych >= '_') goto yy63; + if (yych <= '@') goto yy19; + if (yych <= 'Z') goto yy26; + if (yych >= '_') goto yy26; } else { if (yych <= 'z') { - if (yych >= 'a') goto yy63; + if (yych >= 'a') goto yy26; } else { - if (yych <= '{') goto yy66; - if (yych >= 0x7F) goto yy63; + if (yych <= '{') goto yy29; + if (yych >= 0x7F) goto yy26; } } -yy56: - YYDEBUG(56, *YYCURSOR); +yy19: + YYDEBUG(19, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2106 "Zend/zend_language_scanner.l" +#line 2044 "Zend/zend_language_scanner.l" { if (YYCURSOR > YYLIMIT) { return 0; @@ -1589,118 +1279,118 @@ yy56: zend_scan_escape_string(zendlval, yytext, yyleng, '`' TSRMLS_CC); return T_ENCAPSED_AND_WHITESPACE; } -#line 1593 "Zend/zend_language_scanner.c" -yy57: - YYDEBUG(57, *YYCURSOR); +#line 1283 "Zend/zend_language_scanner.c" +yy20: + YYDEBUG(20, *YYCURSOR); yych = *++YYCURSOR; - if (yych == '$') goto yy61; - goto yy56; -yy58: - YYDEBUG(58, *YYCURSOR); + if (yych == '$') goto yy24; + goto yy19; +yy21: + YYDEBUG(21, *YYCURSOR); ++YYCURSOR; - YYDEBUG(59, *YYCURSOR); + YYDEBUG(22, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2050 "Zend/zend_language_scanner.l" +#line 1988 "Zend/zend_language_scanner.l" { BEGIN(ST_IN_SCRIPTING); return '`'; } -#line 1609 "Zend/zend_language_scanner.c" -yy60: - YYDEBUG(60, *YYCURSOR); +#line 1299 "Zend/zend_language_scanner.c" +yy23: + YYDEBUG(23, *YYCURSOR); yych = *++YYCURSOR; - goto yy56; -yy61: - YYDEBUG(61, *YYCURSOR); + goto yy19; +yy24: + YYDEBUG(24, *YYCURSOR); ++YYCURSOR; - YYDEBUG(62, *YYCURSOR); + YYDEBUG(25, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2037 "Zend/zend_language_scanner.l" +#line 1975 "Zend/zend_language_scanner.l" { Z_LVAL_P(zendlval) = (zend_long) '{'; yy_push_state(ST_IN_SCRIPTING TSRMLS_CC); yyless(1); return T_CURLY_OPEN; } -#line 1626 "Zend/zend_language_scanner.c" -yy63: - YYDEBUG(63, *YYCURSOR); +#line 1316 "Zend/zend_language_scanner.c" +yy26: + YYDEBUG(26, *YYCURSOR); yyaccept = 0; YYMARKER = ++YYCURSOR; YYFILL(3); yych = *YYCURSOR; - YYDEBUG(64, *YYCURSOR); + YYDEBUG(27, *YYCURSOR); if (yybm[0+yych] & 128) { - goto yy63; + goto yy26; } - if (yych == '-') goto yy68; - if (yych == '[') goto yy70; -yy65: - YYDEBUG(65, *YYCURSOR); + if (yych == '-') goto yy31; + if (yych == '[') goto yy33; +yy28: + YYDEBUG(28, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1744 "Zend/zend_language_scanner.l" +#line 1698 "Zend/zend_language_scanner.l" { zend_copy_value(zendlval, (yytext+1), (yyleng-1)); return T_VARIABLE; } -#line 1647 "Zend/zend_language_scanner.c" -yy66: - YYDEBUG(66, *YYCURSOR); +#line 1337 "Zend/zend_language_scanner.c" +yy29: + YYDEBUG(29, *YYCURSOR); ++YYCURSOR; - YYDEBUG(67, *YYCURSOR); + YYDEBUG(30, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1460 "Zend/zend_language_scanner.l" +#line 1464 "Zend/zend_language_scanner.l" { yy_push_state(ST_LOOKING_FOR_VARNAME TSRMLS_CC); return T_DOLLAR_OPEN_CURLY_BRACES; } -#line 1658 "Zend/zend_language_scanner.c" -yy68: - YYDEBUG(68, *YYCURSOR); +#line 1348 "Zend/zend_language_scanner.c" +yy31: + YYDEBUG(31, *YYCURSOR); yych = *++YYCURSOR; - if (yych == '>') goto yy72; -yy69: - YYDEBUG(69, *YYCURSOR); + if (yych == '>') goto yy35; +yy32: + YYDEBUG(32, *YYCURSOR); YYCURSOR = YYMARKER; - goto yy65; -yy70: - YYDEBUG(70, *YYCURSOR); + goto yy28; +yy33: + YYDEBUG(33, *YYCURSOR); ++YYCURSOR; - YYDEBUG(71, *YYCURSOR); + YYDEBUG(34, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1737 "Zend/zend_language_scanner.l" +#line 1691 "Zend/zend_language_scanner.l" { yyless(yyleng - 1); yy_push_state(ST_VAR_OFFSET TSRMLS_CC); zend_copy_value(zendlval, (yytext+1), (yyleng-1)); return T_VARIABLE; } -#line 1679 "Zend/zend_language_scanner.c" -yy72: - YYDEBUG(72, *YYCURSOR); +#line 1369 "Zend/zend_language_scanner.c" +yy35: + YYDEBUG(35, *YYCURSOR); yych = *++YYCURSOR; if (yych <= '_') { - if (yych <= '@') goto yy69; - if (yych <= 'Z') goto yy73; - if (yych <= '^') goto yy69; + if (yych <= '@') goto yy32; + if (yych <= 'Z') goto yy36; + if (yych <= '^') goto yy32; } else { - if (yych <= '`') goto yy69; - if (yych <= 'z') goto yy73; - if (yych <= '~') goto yy69; + if (yych <= '`') goto yy32; + if (yych <= 'z') goto yy36; + if (yych <= '~') goto yy32; } -yy73: - YYDEBUG(73, *YYCURSOR); +yy36: + YYDEBUG(36, *YYCURSOR); ++YYCURSOR; - YYDEBUG(74, *YYCURSOR); + YYDEBUG(37, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1728 "Zend/zend_language_scanner.l" +#line 1682 "Zend/zend_language_scanner.l" { yyless(yyleng - 3); yy_push_state(ST_LOOKING_FOR_PROPERTY TSRMLS_CC); zend_copy_value(zendlval, (yytext+1), (yyleng-1)); return T_VARIABLE; } -#line 1704 "Zend/zend_language_scanner.c" +#line 1394 "Zend/zend_language_scanner.c" } /* *********************************** */ yyc_ST_DOUBLE_QUOTES: @@ -1739,36 +1429,36 @@ yyc_ST_DOUBLE_QUOTES: 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, }; - YYDEBUG(75, *YYCURSOR); + YYDEBUG(38, *YYCURSOR); YYFILL(2); yych = *YYCURSOR; if (yych <= '#') { - if (yych == '"') goto yy80; - goto yy82; + if (yych == '"') goto yy43; + goto yy45; } else { - if (yych <= '$') goto yy77; - if (yych == '{') goto yy79; - goto yy82; + if (yych <= '$') goto yy40; + if (yych == '{') goto yy42; + goto yy45; } -yy77: - YYDEBUG(77, *YYCURSOR); +yy40: + YYDEBUG(40, *YYCURSOR); ++YYCURSOR; if ((yych = *YYCURSOR) <= '_') { - if (yych <= '@') goto yy78; - if (yych <= 'Z') goto yy85; - if (yych >= '_') goto yy85; + if (yych <= '@') goto yy41; + if (yych <= 'Z') goto yy48; + if (yych >= '_') goto yy48; } else { if (yych <= 'z') { - if (yych >= 'a') goto yy85; + if (yych >= 'a') goto yy48; } else { - if (yych <= '{') goto yy88; - if (yych >= 0x7F) goto yy85; + if (yych <= '{') goto yy51; + if (yych >= 0x7F) goto yy48; } } -yy78: - YYDEBUG(78, *YYCURSOR); +yy41: + YYDEBUG(41, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2056 "Zend/zend_language_scanner.l" +#line 1994 "Zend/zend_language_scanner.l" { if (GET_DOUBLE_QUOTES_SCANNED_LENGTH()) { YYCURSOR += GET_DOUBLE_QUOTES_SCANNED_LENGTH() - 1; @@ -1817,129 +1507,129 @@ double_quotes_scan_done: zend_scan_escape_string(zendlval, yytext, yyleng, '"' TSRMLS_CC); return T_ENCAPSED_AND_WHITESPACE; } -#line 1821 "Zend/zend_language_scanner.c" -yy79: - YYDEBUG(79, *YYCURSOR); +#line 1511 "Zend/zend_language_scanner.c" +yy42: + YYDEBUG(42, *YYCURSOR); yych = *++YYCURSOR; - if (yych == '$') goto yy83; - goto yy78; -yy80: - YYDEBUG(80, *YYCURSOR); + if (yych == '$') goto yy46; + goto yy41; +yy43: + YYDEBUG(43, *YYCURSOR); ++YYCURSOR; - YYDEBUG(81, *YYCURSOR); + YYDEBUG(44, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2045 "Zend/zend_language_scanner.l" +#line 1983 "Zend/zend_language_scanner.l" { BEGIN(ST_IN_SCRIPTING); return '"'; } -#line 1837 "Zend/zend_language_scanner.c" -yy82: - YYDEBUG(82, *YYCURSOR); +#line 1527 "Zend/zend_language_scanner.c" +yy45: + YYDEBUG(45, *YYCURSOR); yych = *++YYCURSOR; - goto yy78; -yy83: - YYDEBUG(83, *YYCURSOR); + goto yy41; +yy46: + YYDEBUG(46, *YYCURSOR); ++YYCURSOR; - YYDEBUG(84, *YYCURSOR); + YYDEBUG(47, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2037 "Zend/zend_language_scanner.l" +#line 1975 "Zend/zend_language_scanner.l" { Z_LVAL_P(zendlval) = (zend_long) '{'; yy_push_state(ST_IN_SCRIPTING TSRMLS_CC); yyless(1); return T_CURLY_OPEN; } -#line 1854 "Zend/zend_language_scanner.c" -yy85: - YYDEBUG(85, *YYCURSOR); +#line 1544 "Zend/zend_language_scanner.c" +yy48: + YYDEBUG(48, *YYCURSOR); yyaccept = 0; YYMARKER = ++YYCURSOR; YYFILL(3); yych = *YYCURSOR; - YYDEBUG(86, *YYCURSOR); + YYDEBUG(49, *YYCURSOR); if (yybm[0+yych] & 128) { - goto yy85; + goto yy48; } - if (yych == '-') goto yy90; - if (yych == '[') goto yy92; -yy87: - YYDEBUG(87, *YYCURSOR); + if (yych == '-') goto yy53; + if (yych == '[') goto yy55; +yy50: + YYDEBUG(50, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1744 "Zend/zend_language_scanner.l" +#line 1698 "Zend/zend_language_scanner.l" { zend_copy_value(zendlval, (yytext+1), (yyleng-1)); return T_VARIABLE; } -#line 1875 "Zend/zend_language_scanner.c" -yy88: - YYDEBUG(88, *YYCURSOR); +#line 1565 "Zend/zend_language_scanner.c" +yy51: + YYDEBUG(51, *YYCURSOR); ++YYCURSOR; - YYDEBUG(89, *YYCURSOR); + YYDEBUG(52, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1460 "Zend/zend_language_scanner.l" +#line 1464 "Zend/zend_language_scanner.l" { yy_push_state(ST_LOOKING_FOR_VARNAME TSRMLS_CC); return T_DOLLAR_OPEN_CURLY_BRACES; } -#line 1886 "Zend/zend_language_scanner.c" -yy90: - YYDEBUG(90, *YYCURSOR); +#line 1576 "Zend/zend_language_scanner.c" +yy53: + YYDEBUG(53, *YYCURSOR); yych = *++YYCURSOR; - if (yych == '>') goto yy94; -yy91: - YYDEBUG(91, *YYCURSOR); + if (yych == '>') goto yy57; +yy54: + YYDEBUG(54, *YYCURSOR); YYCURSOR = YYMARKER; - goto yy87; -yy92: - YYDEBUG(92, *YYCURSOR); + goto yy50; +yy55: + YYDEBUG(55, *YYCURSOR); ++YYCURSOR; - YYDEBUG(93, *YYCURSOR); + YYDEBUG(56, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1737 "Zend/zend_language_scanner.l" +#line 1691 "Zend/zend_language_scanner.l" { yyless(yyleng - 1); yy_push_state(ST_VAR_OFFSET TSRMLS_CC); zend_copy_value(zendlval, (yytext+1), (yyleng-1)); return T_VARIABLE; } -#line 1907 "Zend/zend_language_scanner.c" -yy94: - YYDEBUG(94, *YYCURSOR); +#line 1597 "Zend/zend_language_scanner.c" +yy57: + YYDEBUG(57, *YYCURSOR); yych = *++YYCURSOR; if (yych <= '_') { - if (yych <= '@') goto yy91; - if (yych <= 'Z') goto yy95; - if (yych <= '^') goto yy91; + if (yych <= '@') goto yy54; + if (yych <= 'Z') goto yy58; + if (yych <= '^') goto yy54; } else { - if (yych <= '`') goto yy91; - if (yych <= 'z') goto yy95; - if (yych <= '~') goto yy91; + if (yych <= '`') goto yy54; + if (yych <= 'z') goto yy58; + if (yych <= '~') goto yy54; } -yy95: - YYDEBUG(95, *YYCURSOR); +yy58: + YYDEBUG(58, *YYCURSOR); ++YYCURSOR; - YYDEBUG(96, *YYCURSOR); + YYDEBUG(59, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1728 "Zend/zend_language_scanner.l" +#line 1682 "Zend/zend_language_scanner.l" { yyless(yyleng - 3); yy_push_state(ST_LOOKING_FOR_PROPERTY TSRMLS_CC); zend_copy_value(zendlval, (yytext+1), (yyleng-1)); return T_VARIABLE; } -#line 1932 "Zend/zend_language_scanner.c" +#line 1622 "Zend/zend_language_scanner.c" } /* *********************************** */ yyc_ST_END_HEREDOC: - YYDEBUG(97, *YYCURSOR); + YYDEBUG(60, *YYCURSOR); YYFILL(1); yych = *YYCURSOR; - YYDEBUG(99, *YYCURSOR); + YYDEBUG(62, *YYCURSOR); ++YYCURSOR; - YYDEBUG(100, *YYCURSOR); + YYDEBUG(63, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2023 "Zend/zend_language_scanner.l" +#line 1961 "Zend/zend_language_scanner.l" { zend_heredoc_label *heredoc_label = zend_ptr_stack_pop(&SCNG(heredoc_label_stack)); @@ -1952,7 +1642,7 @@ yyc_ST_END_HEREDOC: BEGIN(ST_IN_SCRIPTING); return T_END_HEREDOC; } -#line 1956 "Zend/zend_language_scanner.c" +#line 1646 "Zend/zend_language_scanner.c" /* *********************************** */ yyc_ST_HEREDOC: { @@ -1990,31 +1680,31 @@ yyc_ST_HEREDOC: 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, }; - YYDEBUG(101, *YYCURSOR); + YYDEBUG(64, *YYCURSOR); YYFILL(2); yych = *YYCURSOR; - if (yych == '$') goto yy103; - if (yych == '{') goto yy105; - goto yy106; -yy103: - YYDEBUG(103, *YYCURSOR); + if (yych == '$') goto yy66; + if (yych == '{') goto yy68; + goto yy69; +yy66: + YYDEBUG(66, *YYCURSOR); ++YYCURSOR; if ((yych = *YYCURSOR) <= '_') { - if (yych <= '@') goto yy104; - if (yych <= 'Z') goto yy109; - if (yych >= '_') goto yy109; + if (yych <= '@') goto yy67; + if (yych <= 'Z') goto yy72; + if (yych >= '_') goto yy72; } else { if (yych <= 'z') { - if (yych >= 'a') goto yy109; + if (yych >= 'a') goto yy72; } else { - if (yych <= '{') goto yy112; - if (yych >= 0x7F) goto yy109; + if (yych <= '{') goto yy75; + if (yych >= 0x7F) goto yy72; } } -yy104: - YYDEBUG(104, *YYCURSOR); +yy67: + YYDEBUG(67, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2148 "Zend/zend_language_scanner.l" +#line 2086 "Zend/zend_language_scanner.l" { int newline = 0; @@ -2087,107 +1777,107 @@ heredoc_scan_done: zend_scan_escape_string(zendlval, yytext, yyleng - newline, 0 TSRMLS_CC); return T_ENCAPSED_AND_WHITESPACE; } -#line 2091 "Zend/zend_language_scanner.c" -yy105: - YYDEBUG(105, *YYCURSOR); +#line 1781 "Zend/zend_language_scanner.c" +yy68: + YYDEBUG(68, *YYCURSOR); yych = *++YYCURSOR; - if (yych == '$') goto yy107; - goto yy104; -yy106: - YYDEBUG(106, *YYCURSOR); + if (yych == '$') goto yy70; + goto yy67; +yy69: + YYDEBUG(69, *YYCURSOR); yych = *++YYCURSOR; - goto yy104; -yy107: - YYDEBUG(107, *YYCURSOR); + goto yy67; +yy70: + YYDEBUG(70, *YYCURSOR); ++YYCURSOR; - YYDEBUG(108, *YYCURSOR); + YYDEBUG(71, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2037 "Zend/zend_language_scanner.l" +#line 1975 "Zend/zend_language_scanner.l" { Z_LVAL_P(zendlval) = (zend_long) '{'; yy_push_state(ST_IN_SCRIPTING TSRMLS_CC); yyless(1); return T_CURLY_OPEN; } -#line 2113 "Zend/zend_language_scanner.c" -yy109: - YYDEBUG(109, *YYCURSOR); +#line 1803 "Zend/zend_language_scanner.c" +yy72: + YYDEBUG(72, *YYCURSOR); yyaccept = 0; YYMARKER = ++YYCURSOR; YYFILL(3); yych = *YYCURSOR; - YYDEBUG(110, *YYCURSOR); + YYDEBUG(73, *YYCURSOR); if (yybm[0+yych] & 128) { - goto yy109; + goto yy72; } - if (yych == '-') goto yy114; - if (yych == '[') goto yy116; -yy111: - YYDEBUG(111, *YYCURSOR); + if (yych == '-') goto yy77; + if (yych == '[') goto yy79; +yy74: + YYDEBUG(74, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1744 "Zend/zend_language_scanner.l" +#line 1698 "Zend/zend_language_scanner.l" { zend_copy_value(zendlval, (yytext+1), (yyleng-1)); return T_VARIABLE; } -#line 2134 "Zend/zend_language_scanner.c" -yy112: - YYDEBUG(112, *YYCURSOR); +#line 1824 "Zend/zend_language_scanner.c" +yy75: + YYDEBUG(75, *YYCURSOR); ++YYCURSOR; - YYDEBUG(113, *YYCURSOR); + YYDEBUG(76, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1460 "Zend/zend_language_scanner.l" +#line 1464 "Zend/zend_language_scanner.l" { yy_push_state(ST_LOOKING_FOR_VARNAME TSRMLS_CC); return T_DOLLAR_OPEN_CURLY_BRACES; } -#line 2145 "Zend/zend_language_scanner.c" -yy114: - YYDEBUG(114, *YYCURSOR); +#line 1835 "Zend/zend_language_scanner.c" +yy77: + YYDEBUG(77, *YYCURSOR); yych = *++YYCURSOR; - if (yych == '>') goto yy118; -yy115: - YYDEBUG(115, *YYCURSOR); + if (yych == '>') goto yy81; +yy78: + YYDEBUG(78, *YYCURSOR); YYCURSOR = YYMARKER; - goto yy111; -yy116: - YYDEBUG(116, *YYCURSOR); + goto yy74; +yy79: + YYDEBUG(79, *YYCURSOR); ++YYCURSOR; - YYDEBUG(117, *YYCURSOR); + YYDEBUG(80, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1737 "Zend/zend_language_scanner.l" +#line 1691 "Zend/zend_language_scanner.l" { yyless(yyleng - 1); yy_push_state(ST_VAR_OFFSET TSRMLS_CC); zend_copy_value(zendlval, (yytext+1), (yyleng-1)); return T_VARIABLE; } -#line 2166 "Zend/zend_language_scanner.c" -yy118: - YYDEBUG(118, *YYCURSOR); +#line 1856 "Zend/zend_language_scanner.c" +yy81: + YYDEBUG(81, *YYCURSOR); yych = *++YYCURSOR; if (yych <= '_') { - if (yych <= '@') goto yy115; - if (yych <= 'Z') goto yy119; - if (yych <= '^') goto yy115; + if (yych <= '@') goto yy78; + if (yych <= 'Z') goto yy82; + if (yych <= '^') goto yy78; } else { - if (yych <= '`') goto yy115; - if (yych <= 'z') goto yy119; - if (yych <= '~') goto yy115; + if (yych <= '`') goto yy78; + if (yych <= 'z') goto yy82; + if (yych <= '~') goto yy78; } -yy119: - YYDEBUG(119, *YYCURSOR); +yy82: + YYDEBUG(82, *YYCURSOR); ++YYCURSOR; - YYDEBUG(120, *YYCURSOR); + YYDEBUG(83, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1728 "Zend/zend_language_scanner.l" +#line 1682 "Zend/zend_language_scanner.l" { yyless(yyleng - 3); yy_push_state(ST_LOOKING_FOR_PROPERTY TSRMLS_CC); zend_copy_value(zendlval, (yytext+1), (yyleng-1)); return T_VARIABLE; } -#line 2191 "Zend/zend_language_scanner.c" +#line 1881 "Zend/zend_language_scanner.c" } /* *********************************** */ yyc_ST_IN_SCRIPTING: @@ -2226,7 +1916,7 @@ yyc_ST_IN_SCRIPTING: 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, }; - YYDEBUG(121, *YYCURSOR); + YYDEBUG(84, *YYCURSOR); YYFILL(16); yych = *YYCURSOR; YYDEBUG(-1, yych); @@ -2259,32 +1949,32 @@ yyc_ST_IN_SCRIPTING: case 0x1C: case 0x1D: case 0x1E: - case 0x1F: goto yy184; + case 0x1F: goto yy147; case '\t': case '\n': case '\r': - case ' ': goto yy140; - case '!': goto yy154; - case '"': goto yy180; - case '#': goto yy176; - case '$': goto yy165; - case '%': goto yy159; - case '&': goto yy160; - case '\'': goto yy178; - case '(': goto yy148; + case ' ': goto yy103; + case '!': goto yy118; + case '"': goto yy143; + case '#': goto yy139; + case '$': goto yy129; + case '%': goto yy123; + case '&': goto yy124; + case '\'': goto yy141; + case '(': goto yy112; case ')': case ',': case ';': case '@': case '[': case ']': - case '~': goto yy166; - case '*': goto yy157; - case '+': goto yy153; - case '-': goto yy138; - case '.': goto yy145; - case '/': goto yy158; - case '0': goto yy172; + case '~': goto yy130; + case '*': goto yy121; + case '+': goto yy117; + case '-': goto yy101; + case '.': goto yy108; + case '/': goto yy122; + case '0': goto yy135; case '1': case '2': case '3': @@ -2293,599 +1983,594 @@ yyc_ST_IN_SCRIPTING: case '6': case '7': case '8': - case '9': goto yy174; - case ':': goto yy142; - case '<': goto yy155; - case '=': goto yy151; - case '>': goto yy156; - case '?': goto yy167; + case '9': goto yy137; + case ':': goto yy105; + case '<': goto yy119; + case '=': goto yy115; + case '>': goto yy120; + case '?': goto yy109; case 'A': - case 'a': goto yy133; + case 'a': goto yy96; case 'B': - case 'b': goto yy135; + case 'b': goto yy98; case 'C': - case 'c': goto yy127; + case 'c': goto yy90; case 'D': - case 'd': goto yy125; + case 'd': goto yy88; case 'E': - case 'e': goto yy123; + case 'e': goto yy86; case 'F': - case 'f': goto yy126; + case 'f': goto yy89; case 'G': - case 'g': goto yy136; + case 'g': goto yy99; case 'I': - case 'i': goto yy131; + case 'i': goto yy94; case 'L': - case 'l': goto yy152; + case 'l': goto yy116; case 'N': - case 'n': goto yy146; + case 'n': goto yy110; case 'O': - case 'o': goto yy163; + case 'o': goto yy127; case 'P': - case 'p': goto yy137; + case 'p': goto yy100; case 'R': - case 'r': goto yy128; + case 'r': goto yy91; case 'S': - case 's': goto yy134; + case 's': goto yy97; case 'T': - case 't': goto yy130; + case 't': goto yy93; case 'U': - case 'u': goto yy149; + case 'u': goto yy113; case 'V': - case 'v': goto yy147; + case 'v': goto yy111; case 'W': - case 'w': goto yy132; + case 'w': goto yy95; case 'X': - case 'x': goto yy164; + case 'x': goto yy128; case 'Y': - case 'y': goto yy129; - case '\\': goto yy143; - case '^': goto yy162; - case '_': goto yy150; - case '`': goto yy182; - case '{': goto yy168; - case '|': goto yy161; - case '}': goto yy170; - default: goto yy175; - } -yy123: - YYDEBUG(123, *YYCURSOR); + case 'y': goto yy92; + case '\\': goto yy106; + case '^': goto yy126; + case '_': goto yy114; + case '`': goto yy145; + case '{': goto yy131; + case '|': goto yy125; + case '}': goto yy133; + default: goto yy138; + } +yy86: + YYDEBUG(86, *YYCURSOR); ++YYCURSOR; YYDEBUG(-1, yych); switch ((yych = *YYCURSOR)) { case 'C': - case 'c': goto yy742; + case 'c': goto yy695; case 'L': - case 'l': goto yy743; + case 'l': goto yy696; case 'M': - case 'm': goto yy744; + case 'm': goto yy697; case 'N': - case 'n': goto yy745; + case 'n': goto yy698; case 'V': - case 'v': goto yy746; + case 'v': goto yy699; case 'X': - case 'x': goto yy747; - default: goto yy187; + case 'x': goto yy700; + default: goto yy150; } -yy124: - YYDEBUG(124, *YYCURSOR); +yy87: + YYDEBUG(87, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1767 "Zend/zend_language_scanner.l" +#line 1721 "Zend/zend_language_scanner.l" { zend_copy_value(zendlval, yytext, yyleng); return T_STRING; } -#line 2379 "Zend/zend_language_scanner.c" -yy125: - YYDEBUG(125, *YYCURSOR); +#line 2069 "Zend/zend_language_scanner.c" +yy88: + YYDEBUG(88, *YYCURSOR); yych = *++YYCURSOR; if (yych <= 'O') { if (yych <= 'H') { - if (yych == 'E') goto yy724; - goto yy187; + if (yych == 'E') goto yy677; + goto yy150; } else { - if (yych <= 'I') goto yy725; - if (yych <= 'N') goto yy187; - goto yy726; + if (yych <= 'I') goto yy678; + if (yych <= 'N') goto yy150; + goto yy679; } } else { if (yych <= 'h') { - if (yych == 'e') goto yy724; - goto yy187; + if (yych == 'e') goto yy677; + goto yy150; } else { - if (yych <= 'i') goto yy725; - if (yych == 'o') goto yy726; - goto yy187; + if (yych <= 'i') goto yy678; + if (yych == 'o') goto yy679; + goto yy150; } } -yy126: - YYDEBUG(126, *YYCURSOR); +yy89: + YYDEBUG(89, *YYCURSOR); yych = *++YYCURSOR; if (yych <= 'U') { if (yych <= 'N') { - if (yych == 'I') goto yy700; - goto yy187; + if (yych == 'I') goto yy653; + goto yy150; } else { - if (yych <= 'O') goto yy701; - if (yych <= 'T') goto yy187; - goto yy702; + if (yych <= 'O') goto yy654; + if (yych <= 'T') goto yy150; + goto yy655; } } else { if (yych <= 'n') { - if (yych == 'i') goto yy700; - goto yy187; + if (yych == 'i') goto yy653; + goto yy150; } else { - if (yych <= 'o') goto yy701; - if (yych == 'u') goto yy702; - goto yy187; + if (yych <= 'o') goto yy654; + if (yych == 'u') goto yy655; + goto yy150; } } -yy127: - YYDEBUG(127, *YYCURSOR); +yy90: + YYDEBUG(90, *YYCURSOR); yych = *++YYCURSOR; if (yych <= 'O') { if (yych <= 'K') { - if (yych == 'A') goto yy665; - goto yy187; + if (yych == 'A') goto yy618; + goto yy150; } else { - if (yych <= 'L') goto yy666; - if (yych <= 'N') goto yy187; - goto yy667; + if (yych <= 'L') goto yy619; + if (yych <= 'N') goto yy150; + goto yy620; } } else { if (yych <= 'k') { - if (yych == 'a') goto yy665; - goto yy187; + if (yych == 'a') goto yy618; + goto yy150; } else { - if (yych <= 'l') goto yy666; - if (yych == 'o') goto yy667; - goto yy187; + if (yych <= 'l') goto yy619; + if (yych == 'o') goto yy620; + goto yy150; } } -yy128: - YYDEBUG(128, *YYCURSOR); +yy91: + YYDEBUG(91, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy647; - if (yych == 'e') goto yy647; - goto yy187; -yy129: - YYDEBUG(129, *YYCURSOR); + if (yych == 'E') goto yy600; + if (yych == 'e') goto yy600; + goto yy150; +yy92: + YYDEBUG(92, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'I') goto yy642; - if (yych == 'i') goto yy642; - goto yy187; -yy130: - YYDEBUG(130, *YYCURSOR); + if (yych == 'I') goto yy595; + if (yych == 'i') goto yy595; + goto yy150; +yy93: + YYDEBUG(93, *YYCURSOR); yych = *++YYCURSOR; if (yych <= 'R') { - if (yych == 'H') goto yy630; - if (yych <= 'Q') goto yy187; - goto yy631; + if (yych == 'H') goto yy583; + if (yych <= 'Q') goto yy150; + goto yy584; } else { if (yych <= 'h') { - if (yych <= 'g') goto yy187; - goto yy630; + if (yych <= 'g') goto yy150; + goto yy583; } else { - if (yych == 'r') goto yy631; - goto yy187; + if (yych == 'r') goto yy584; + goto yy150; } } -yy131: - YYDEBUG(131, *YYCURSOR); +yy94: + YYDEBUG(94, *YYCURSOR); yych = *++YYCURSOR; if (yych <= 'S') { if (yych <= 'L') { - if (yych == 'F') goto yy577; - goto yy187; + if (yych == 'F') goto yy530; + goto yy150; } else { - if (yych <= 'M') goto yy579; - if (yych <= 'N') goto yy580; - if (yych <= 'R') goto yy187; - goto yy581; + if (yych <= 'M') goto yy532; + if (yych <= 'N') goto yy533; + if (yych <= 'R') goto yy150; + goto yy534; } } else { if (yych <= 'm') { - if (yych == 'f') goto yy577; - if (yych <= 'l') goto yy187; - goto yy579; + if (yych == 'f') goto yy530; + if (yych <= 'l') goto yy150; + goto yy532; } else { - if (yych <= 'n') goto yy580; - if (yych == 's') goto yy581; - goto yy187; + if (yych <= 'n') goto yy533; + if (yych == 's') goto yy534; + goto yy150; } } -yy132: - YYDEBUG(132, *YYCURSOR); +yy95: + YYDEBUG(95, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'H') goto yy572; - if (yych == 'h') goto yy572; - goto yy187; -yy133: - YYDEBUG(133, *YYCURSOR); + if (yych == 'H') goto yy525; + if (yych == 'h') goto yy525; + goto yy150; +yy96: + YYDEBUG(96, *YYCURSOR); yych = *++YYCURSOR; if (yych <= 'S') { if (yych <= 'M') { - if (yych == 'B') goto yy554; - goto yy187; + if (yych == 'B') goto yy507; + goto yy150; } else { - if (yych <= 'N') goto yy555; - if (yych <= 'Q') goto yy187; - if (yych <= 'R') goto yy556; - goto yy557; + if (yych <= 'N') goto yy508; + if (yych <= 'Q') goto yy150; + if (yych <= 'R') goto yy509; + goto yy510; } } else { if (yych <= 'n') { - if (yych == 'b') goto yy554; - if (yych <= 'm') goto yy187; - goto yy555; + if (yych == 'b') goto yy507; + if (yych <= 'm') goto yy150; + goto yy508; } else { - if (yych <= 'q') goto yy187; - if (yych <= 'r') goto yy556; - if (yych <= 's') goto yy557; - goto yy187; + if (yych <= 'q') goto yy150; + if (yych <= 'r') goto yy509; + if (yych <= 's') goto yy510; + goto yy150; } } -yy134: - YYDEBUG(134, *YYCURSOR); +yy97: + YYDEBUG(97, *YYCURSOR); yych = *++YYCURSOR; if (yych <= 'W') { - if (yych == 'T') goto yy542; - if (yych <= 'V') goto yy187; - goto yy543; + if (yych == 'T') goto yy495; + if (yych <= 'V') goto yy150; + goto yy496; } else { if (yych <= 't') { - if (yych <= 's') goto yy187; - goto yy542; + if (yych <= 's') goto yy150; + goto yy495; } else { - if (yych == 'w') goto yy543; - goto yy187; + if (yych == 'w') goto yy496; + goto yy150; } } -yy135: - YYDEBUG(135, *YYCURSOR); +yy98: + YYDEBUG(98, *YYCURSOR); yyaccept = 0; yych = *(YYMARKER = ++YYCURSOR); if (yych <= ';') { if (yych <= '"') { - if (yych <= '!') goto yy187; - goto yy534; + if (yych <= '!') goto yy150; + goto yy487; } else { - if (yych == '\'') goto yy535; - goto yy187; + if (yych == '\'') goto yy488; + goto yy150; } } else { if (yych <= 'R') { - if (yych <= '<') goto yy533; - if (yych <= 'Q') goto yy187; - goto yy536; + if (yych <= '<') goto yy486; + if (yych <= 'Q') goto yy150; + goto yy489; } else { - if (yych == 'r') goto yy536; - goto yy187; + if (yych == 'r') goto yy489; + goto yy150; } } -yy136: - YYDEBUG(136, *YYCURSOR); +yy99: + YYDEBUG(99, *YYCURSOR); yych = *++YYCURSOR; if (yych <= 'O') { - if (yych == 'L') goto yy523; - if (yych <= 'N') goto yy187; - goto yy524; + if (yych == 'L') goto yy476; + if (yych <= 'N') goto yy150; + goto yy477; } else { if (yych <= 'l') { - if (yych <= 'k') goto yy187; - goto yy523; + if (yych <= 'k') goto yy150; + goto yy476; } else { - if (yych == 'o') goto yy524; - goto yy187; + if (yych == 'o') goto yy477; + goto yy150; } } -yy137: - YYDEBUG(137, *YYCURSOR); +yy100: + YYDEBUG(100, *YYCURSOR); yych = *++YYCURSOR; if (yych <= 'U') { - if (yych == 'R') goto yy499; - if (yych <= 'T') goto yy187; - goto yy500; + if (yych == 'R') goto yy452; + if (yych <= 'T') goto yy150; + goto yy453; } else { if (yych <= 'r') { - if (yych <= 'q') goto yy187; - goto yy499; + if (yych <= 'q') goto yy150; + goto yy452; } else { - if (yych == 'u') goto yy500; - goto yy187; + if (yych == 'u') goto yy453; + goto yy150; } } -yy138: - YYDEBUG(138, *YYCURSOR); +yy101: + YYDEBUG(101, *YYCURSOR); ++YYCURSOR; if ((yych = *YYCURSOR) <= '<') { - if (yych == '-') goto yy495; + if (yych == '-') goto yy448; } else { - if (yych <= '=') goto yy493; - if (yych <= '>') goto yy497; + if (yych <= '=') goto yy446; + if (yych <= '>') goto yy450; } -yy139: - YYDEBUG(139, *YYCURSOR); +yy102: + YYDEBUG(102, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1449 "Zend/zend_language_scanner.l" +#line 1453 "Zend/zend_language_scanner.l" { return yytext[0]; } -#line 2615 "Zend/zend_language_scanner.c" -yy140: - YYDEBUG(140, *YYCURSOR); +#line 2305 "Zend/zend_language_scanner.c" +yy103: + YYDEBUG(103, *YYCURSOR); ++YYCURSOR; yych = *YYCURSOR; - goto yy492; -yy141: - YYDEBUG(141, *YYCURSOR); + goto yy445; +yy104: + YYDEBUG(104, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1172 "Zend/zend_language_scanner.l" { HANDLE_NEWLINES(yytext, yyleng); return T_WHITESPACE; } -#line 2629 "Zend/zend_language_scanner.c" -yy142: - YYDEBUG(142, *YYCURSOR); +#line 2319 "Zend/zend_language_scanner.c" +yy105: + YYDEBUG(105, *YYCURSOR); yych = *++YYCURSOR; - if (yych == ':') goto yy489; - goto yy139; -yy143: - YYDEBUG(143, *YYCURSOR); + if (yych == ':') goto yy442; + goto yy102; +yy106: + YYDEBUG(106, *YYCURSOR); ++YYCURSOR; - YYDEBUG(144, *YYCURSOR); + YYDEBUG(107, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1197 "Zend/zend_language_scanner.l" { return T_NS_SEPARATOR; } -#line 2644 "Zend/zend_language_scanner.c" -yy145: - YYDEBUG(145, *YYCURSOR); +#line 2334 "Zend/zend_language_scanner.c" +yy108: + YYDEBUG(108, *YYCURSOR); yyaccept = 1; yych = *(YYMARKER = ++YYCURSOR); if (yych <= '/') { - if (yych == '.') goto yy486; - goto yy139; + if (yych == '.') goto yy439; + goto yy102; } else { - if (yych <= '9') goto yy482; - if (yych == '=') goto yy484; - goto yy139; + if (yych <= '9') goto yy435; + if (yych == '=') goto yy437; + goto yy102; } -yy146: - YYDEBUG(146, *YYCURSOR); +yy109: + YYDEBUG(109, *YYCURSOR); + yych = *++YYCURSOR; + if (yych <= '=') goto yy102; + if (yych <= '>') goto yy429; + if (yych <= '?') goto yy431; + goto yy102; +yy110: + YYDEBUG(110, *YYCURSOR); yych = *++YYCURSOR; if (yych <= 'E') { - if (yych == 'A') goto yy470; - if (yych <= 'D') goto yy187; - goto yy471; + if (yych == 'A') goto yy417; + if (yych <= 'D') goto yy150; + goto yy418; } else { if (yych <= 'a') { - if (yych <= '`') goto yy187; - goto yy470; + if (yych <= '`') goto yy150; + goto yy417; } else { - if (yych == 'e') goto yy471; - goto yy187; + if (yych == 'e') goto yy418; + goto yy150; } } -yy147: - YYDEBUG(147, *YYCURSOR); +yy111: + YYDEBUG(111, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'A') goto yy467; - if (yych == 'a') goto yy467; - goto yy187; -yy148: - YYDEBUG(148, *YYCURSOR); + if (yych == 'A') goto yy414; + if (yych == 'a') goto yy414; + goto yy150; +yy112: + YYDEBUG(112, *YYCURSOR); yyaccept = 1; yych = *(YYMARKER = ++YYCURSOR); if (yych <= 'S') { if (yych <= 'D') { if (yych <= ' ') { - if (yych == '\t') goto yy392; - if (yych <= 0x1F) goto yy139; - goto yy392; + if (yych == '\t') goto yy339; + if (yych <= 0x1F) goto yy102; + goto yy339; } else { - if (yych <= '@') goto yy139; - if (yych == 'C') goto yy139; - goto yy392; + if (yych <= '@') goto yy102; + if (yych == 'C') goto yy102; + goto yy339; } } else { if (yych <= 'I') { - if (yych == 'F') goto yy392; - if (yych <= 'H') goto yy139; - goto yy392; + if (yych == 'F') goto yy339; + if (yych <= 'H') goto yy102; + goto yy339; } else { - if (yych == 'O') goto yy392; - if (yych <= 'Q') goto yy139; - goto yy392; + if (yych == 'O') goto yy339; + if (yych <= 'Q') goto yy102; + goto yy339; } } } else { if (yych <= 'f') { if (yych <= 'b') { - if (yych == 'U') goto yy392; - if (yych <= '`') goto yy139; - goto yy392; + if (yych == 'U') goto yy339; + if (yych <= '`') goto yy102; + goto yy339; } else { - if (yych == 'd') goto yy392; - if (yych <= 'e') goto yy139; - goto yy392; + if (yych == 'd') goto yy339; + if (yych <= 'e') goto yy102; + goto yy339; } } else { if (yych <= 'o') { - if (yych == 'i') goto yy392; - if (yych <= 'n') goto yy139; - goto yy392; + if (yych == 'i') goto yy339; + if (yych <= 'n') goto yy102; + goto yy339; } else { if (yych <= 's') { - if (yych <= 'q') goto yy139; - goto yy392; + if (yych <= 'q') goto yy102; + goto yy339; } else { - if (yych == 'u') goto yy392; - goto yy139; + if (yych == 'u') goto yy339; + goto yy102; } } } } -yy149: - YYDEBUG(149, *YYCURSOR); +yy113: + YYDEBUG(113, *YYCURSOR); yych = *++YYCURSOR; if (yych <= 'S') { - if (yych == 'N') goto yy383; - if (yych <= 'R') goto yy187; - goto yy384; + if (yych == 'N') goto yy330; + if (yych <= 'R') goto yy150; + goto yy331; } else { if (yych <= 'n') { - if (yych <= 'm') goto yy187; - goto yy383; + if (yych <= 'm') goto yy150; + goto yy330; } else { - if (yych == 's') goto yy384; - goto yy187; + if (yych == 's') goto yy331; + goto yy150; } } -yy150: - YYDEBUG(150, *YYCURSOR); +yy114: + YYDEBUG(114, *YYCURSOR); yych = *++YYCURSOR; - if (yych == '_') goto yy301; - goto yy187; -yy151: - YYDEBUG(151, *YYCURSOR); + if (yych == '_') goto yy248; + goto yy150; +yy115: + YYDEBUG(115, *YYCURSOR); yych = *++YYCURSOR; - if (yych <= '<') goto yy139; - if (yych <= '=') goto yy295; - if (yych <= '>') goto yy297; - goto yy139; -yy152: - YYDEBUG(152, *YYCURSOR); + if (yych <= '<') goto yy102; + if (yych <= '=') goto yy242; + if (yych <= '>') goto yy244; + goto yy102; +yy116: + YYDEBUG(116, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'I') goto yy291; - if (yych == 'i') goto yy291; - goto yy187; -yy153: - YYDEBUG(153, *YYCURSOR); + if (yych == 'I') goto yy238; + if (yych == 'i') goto yy238; + goto yy150; +yy117: + YYDEBUG(117, *YYCURSOR); yych = *++YYCURSOR; - if (yych == '+') goto yy289; - if (yych == '=') goto yy287; - goto yy139; -yy154: - YYDEBUG(154, *YYCURSOR); + if (yych == '+') goto yy236; + if (yych == '=') goto yy234; + goto yy102; +yy118: + YYDEBUG(118, *YYCURSOR); yych = *++YYCURSOR; - if (yych == '=') goto yy284; - goto yy139; -yy155: - YYDEBUG(155, *YYCURSOR); - yyaccept = 1; - yych = *(YYMARKER = ++YYCURSOR); - if (yych <= ';') { - if (yych == '/') goto yy256; - goto yy139; - } else { - if (yych <= '<') goto yy254; - if (yych <= '=') goto yy257; - if (yych <= '>') goto yy259; - goto yy139; - } -yy156: - YYDEBUG(156, *YYCURSOR); + if (yych == '=') goto yy231; + goto yy102; +yy119: + YYDEBUG(119, *YYCURSOR); yych = *++YYCURSOR; - if (yych <= '<') goto yy139; - if (yych <= '=') goto yy250; - if (yych <= '>') goto yy248; - goto yy139; -yy157: - YYDEBUG(157, *YYCURSOR); + if (yych <= ';') goto yy102; + if (yych <= '<') goto yy209; + if (yych <= '=') goto yy211; + if (yych <= '>') goto yy213; + goto yy102; +yy120: + YYDEBUG(120, *YYCURSOR); yych = *++YYCURSOR; - if (yych == '*') goto yy242; - if (yych == '=') goto yy244; - goto yy139; -yy158: - YYDEBUG(158, *YYCURSOR); + if (yych <= '<') goto yy102; + if (yych <= '=') goto yy205; + if (yych <= '>') goto yy203; + goto yy102; +yy121: + YYDEBUG(121, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == '*') goto yy197; + if (yych == '=') goto yy199; + goto yy102; +yy122: + YYDEBUG(122, *YYCURSOR); yych = *++YYCURSOR; if (yych <= '.') { - if (yych == '*') goto yy234; - goto yy139; + if (yych == '*') goto yy189; + goto yy102; } else { - if (yych <= '/') goto yy236; - if (yych == '=') goto yy237; - goto yy139; + if (yych <= '/') goto yy191; + if (yych == '=') goto yy192; + goto yy102; } -yy159: - YYDEBUG(159, *YYCURSOR); +yy123: + YYDEBUG(123, *YYCURSOR); yych = *++YYCURSOR; - if (yych <= '<') goto yy139; - if (yych <= '=') goto yy230; - if (yych <= '>') goto yy228; - goto yy139; -yy160: - YYDEBUG(160, *YYCURSOR); + if (yych == '=') goto yy187; + goto yy102; +yy124: + YYDEBUG(124, *YYCURSOR); yych = *++YYCURSOR; - if (yych == '&') goto yy224; - if (yych == '=') goto yy226; - goto yy139; -yy161: - YYDEBUG(161, *YYCURSOR); + if (yych == '&') goto yy183; + if (yych == '=') goto yy185; + goto yy102; +yy125: + YYDEBUG(125, *YYCURSOR); yych = *++YYCURSOR; - if (yych == '=') goto yy222; - if (yych == '|') goto yy220; - goto yy139; -yy162: - YYDEBUG(162, *YYCURSOR); + if (yych == '=') goto yy181; + if (yych == '|') goto yy179; + goto yy102; +yy126: + YYDEBUG(126, *YYCURSOR); yych = *++YYCURSOR; - if (yych == '=') goto yy218; - goto yy139; -yy163: - YYDEBUG(163, *YYCURSOR); + if (yych == '=') goto yy177; + goto yy102; +yy127: + YYDEBUG(127, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'R') goto yy216; - if (yych == 'r') goto yy216; - goto yy187; -yy164: - YYDEBUG(164, *YYCURSOR); + if (yych == 'R') goto yy175; + if (yych == 'r') goto yy175; + goto yy150; +yy128: + YYDEBUG(128, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'O') goto yy213; - if (yych == 'o') goto yy213; - goto yy187; -yy165: - YYDEBUG(165, *YYCURSOR); + if (yych == 'O') goto yy172; + if (yych == 'o') goto yy172; + goto yy150; +yy129: + YYDEBUG(129, *YYCURSOR); yych = *++YYCURSOR; if (yych <= '_') { - if (yych <= '@') goto yy139; - if (yych <= 'Z') goto yy210; - if (yych <= '^') goto yy139; - goto yy210; + if (yych <= '@') goto yy102; + if (yych <= 'Z') goto yy169; + if (yych <= '^') goto yy102; + goto yy169; } else { - if (yych <= '`') goto yy139; - if (yych <= 'z') goto yy210; - if (yych <= '~') goto yy139; - goto yy210; + if (yych <= '`') goto yy102; + if (yych <= 'z') goto yy169; + if (yych <= '~') goto yy102; + goto yy169; } -yy166: - YYDEBUG(166, *YYCURSOR); - yych = *++YYCURSOR; - goto yy139; -yy167: - YYDEBUG(167, *YYCURSOR); +yy130: + YYDEBUG(130, *YYCURSOR); yych = *++YYCURSOR; - if (yych == '>') goto yy206; - goto yy139; -yy168: - YYDEBUG(168, *YYCURSOR); + goto yy102; +yy131: + YYDEBUG(131, *YYCURSOR); ++YYCURSOR; - YYDEBUG(169, *YYCURSOR); + YYDEBUG(132, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1454 "Zend/zend_language_scanner.l" +#line 1458 "Zend/zend_language_scanner.l" { yy_push_state(ST_IN_SCRIPTING TSRMLS_CC); return '{'; } -#line 2883 "Zend/zend_language_scanner.c" -yy170: - YYDEBUG(170, *YYCURSOR); +#line 2568 "Zend/zend_language_scanner.c" +yy133: + YYDEBUG(133, *YYCURSOR); ++YYCURSOR; - YYDEBUG(171, *YYCURSOR); + YYDEBUG(134, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1466 "Zend/zend_language_scanner.l" +#line 1470 "Zend/zend_language_scanner.l" { RESET_DOC_COMMENT(); if (!zend_stack_is_empty(&SCNG(state_stack))) { @@ -2893,35 +2578,35 @@ yy170: } return '}'; } -#line 2897 "Zend/zend_language_scanner.c" -yy172: - YYDEBUG(172, *YYCURSOR); +#line 2582 "Zend/zend_language_scanner.c" +yy135: + YYDEBUG(135, *YYCURSOR); yyaccept = 2; yych = *(YYMARKER = ++YYCURSOR); if (yych <= 'E') { if (yych <= '9') { - if (yych == '.') goto yy188; - if (yych >= '0') goto yy191; + if (yych == '.') goto yy151; + if (yych >= '0') goto yy154; } else { - if (yych == 'B') goto yy199; - if (yych >= 'E') goto yy193; + if (yych == 'B') goto yy162; + if (yych >= 'E') goto yy156; } } else { if (yych <= 'b') { - if (yych == 'X') goto yy198; - if (yych >= 'b') goto yy199; + if (yych == 'X') goto yy161; + if (yych >= 'b') goto yy162; } else { if (yych <= 'e') { - if (yych >= 'e') goto yy193; + if (yych >= 'e') goto yy156; } else { - if (yych == 'x') goto yy198; + if (yych == 'x') goto yy161; } } } -yy173: - YYDEBUG(173, *YYCURSOR); +yy136: + YYDEBUG(136, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1514 "Zend/zend_language_scanner.l" +#line 1518 "Zend/zend_language_scanner.l" { if (yyleng < MAX_LENGTH_OF_LONG - 1) { /* Won't overflow */ ZVAL_LONG(zendlval, ZEND_STRTOL(yytext, NULL, 0)); @@ -2939,35 +2624,35 @@ yy173: } return T_LNUMBER; } -#line 2943 "Zend/zend_language_scanner.c" -yy174: - YYDEBUG(174, *YYCURSOR); +#line 2628 "Zend/zend_language_scanner.c" +yy137: + YYDEBUG(137, *YYCURSOR); yyaccept = 2; yych = *(YYMARKER = ++YYCURSOR); if (yych <= '9') { - if (yych == '.') goto yy188; - if (yych <= '/') goto yy173; - goto yy191; + if (yych == '.') goto yy151; + if (yych <= '/') goto yy136; + goto yy154; } else { if (yych <= 'E') { - if (yych <= 'D') goto yy173; - goto yy193; + if (yych <= 'D') goto yy136; + goto yy156; } else { - if (yych == 'e') goto yy193; - goto yy173; + if (yych == 'e') goto yy156; + goto yy136; } } -yy175: - YYDEBUG(175, *YYCURSOR); +yy138: + YYDEBUG(138, *YYCURSOR); yych = *++YYCURSOR; - goto yy187; -yy176: - YYDEBUG(176, *YYCURSOR); + goto yy150; +yy139: + YYDEBUG(139, *YYCURSOR); ++YYCURSOR; -yy177: - YYDEBUG(177, *YYCURSOR); +yy140: + YYDEBUG(140, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1773 "Zend/zend_language_scanner.l" +#line 1727 "Zend/zend_language_scanner.l" { while (YYCURSOR < YYLIMIT) { switch (*YYCURSOR++) { @@ -2979,11 +2664,6 @@ yy177: case '\n': CG(zend_lineno)++; break; - case '%': - if (!CG(asp_tags)) { - continue; - } - /* fall through */ case '?': if (*YYCURSOR == '>') { YYCURSOR--; @@ -3001,14 +2681,14 @@ yy177: return T_COMMENT; } -#line 3005 "Zend/zend_language_scanner.c" -yy178: - YYDEBUG(178, *YYCURSOR); +#line 2685 "Zend/zend_language_scanner.c" +yy141: + YYDEBUG(141, *YYCURSOR); ++YYCURSOR; -yy179: - YYDEBUG(179, *YYCURSOR); +yy142: + YYDEBUG(142, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1857 "Zend/zend_language_scanner.l" +#line 1795 "Zend/zend_language_scanner.l" { register char *s, *t; char *end; @@ -3077,14 +2757,14 @@ yy179: } return T_CONSTANT_ENCAPSED_STRING; } -#line 3081 "Zend/zend_language_scanner.c" -yy180: - YYDEBUG(180, *YYCURSOR); +#line 2761 "Zend/zend_language_scanner.c" +yy143: + YYDEBUG(143, *YYCURSOR); ++YYCURSOR; -yy181: - YYDEBUG(181, *YYCURSOR); +yy144: + YYDEBUG(144, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1927 "Zend/zend_language_scanner.l" +#line 1865 "Zend/zend_language_scanner.l" { int bprefix = (yytext[0] != '"') ? 1 : 0; @@ -3125,24 +2805,24 @@ yy181: BEGIN(ST_DOUBLE_QUOTES); return '"'; } -#line 3129 "Zend/zend_language_scanner.c" -yy182: - YYDEBUG(182, *YYCURSOR); +#line 2809 "Zend/zend_language_scanner.c" +yy145: + YYDEBUG(145, *YYCURSOR); ++YYCURSOR; - YYDEBUG(183, *YYCURSOR); + YYDEBUG(146, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2017 "Zend/zend_language_scanner.l" +#line 1955 "Zend/zend_language_scanner.l" { BEGIN(ST_BACKQUOTE); return '`'; } -#line 3140 "Zend/zend_language_scanner.c" -yy184: - YYDEBUG(184, *YYCURSOR); +#line 2820 "Zend/zend_language_scanner.c" +yy147: + YYDEBUG(147, *YYCURSOR); ++YYCURSOR; - YYDEBUG(185, *YYCURSOR); + YYDEBUG(148, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2279 "Zend/zend_language_scanner.l" +#line 2217 "Zend/zend_language_scanner.l" { if (YYCURSOR > YYLIMIT) { return 0; @@ -3151,131 +2831,131 @@ yy184: zend_error(E_COMPILE_WARNING,"Unexpected character in input: '%c' (ASCII=%d) state=%d", yytext[0], yytext[0], YYSTATE); goto restart; } -#line 3155 "Zend/zend_language_scanner.c" -yy186: - YYDEBUG(186, *YYCURSOR); +#line 2835 "Zend/zend_language_scanner.c" +yy149: + YYDEBUG(149, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; -yy187: - YYDEBUG(187, *YYCURSOR); +yy150: + YYDEBUG(150, *YYCURSOR); if (yybm[0+yych] & 4) { - goto yy186; + goto yy149; } - goto yy124; -yy188: - YYDEBUG(188, *YYCURSOR); + goto yy87; +yy151: + YYDEBUG(151, *YYCURSOR); yyaccept = 3; YYMARKER = ++YYCURSOR; YYFILL(3); yych = *YYCURSOR; - YYDEBUG(189, *YYCURSOR); + YYDEBUG(152, *YYCURSOR); if (yybm[0+yych] & 8) { - goto yy188; + goto yy151; } - if (yych == 'E') goto yy193; - if (yych == 'e') goto yy193; -yy190: - YYDEBUG(190, *YYCURSOR); + if (yych == 'E') goto yy156; + if (yych == 'e') goto yy156; +yy153: + YYDEBUG(153, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1569 "Zend/zend_language_scanner.l" +#line 1573 "Zend/zend_language_scanner.l" { ZVAL_DOUBLE(zendlval, zend_strtod(yytext, NULL)); return T_DNUMBER; } -#line 3187 "Zend/zend_language_scanner.c" -yy191: - YYDEBUG(191, *YYCURSOR); +#line 2867 "Zend/zend_language_scanner.c" +yy154: + YYDEBUG(154, *YYCURSOR); yyaccept = 2; YYMARKER = ++YYCURSOR; YYFILL(3); yych = *YYCURSOR; - YYDEBUG(192, *YYCURSOR); + YYDEBUG(155, *YYCURSOR); if (yych <= '9') { - if (yych == '.') goto yy188; - if (yych <= '/') goto yy173; - goto yy191; + if (yych == '.') goto yy151; + if (yych <= '/') goto yy136; + goto yy154; } else { if (yych <= 'E') { - if (yych <= 'D') goto yy173; + if (yych <= 'D') goto yy136; } else { - if (yych != 'e') goto yy173; + if (yych != 'e') goto yy136; } } -yy193: - YYDEBUG(193, *YYCURSOR); +yy156: + YYDEBUG(156, *YYCURSOR); yych = *++YYCURSOR; if (yych <= ',') { - if (yych == '+') goto yy195; + if (yych == '+') goto yy158; } else { - if (yych <= '-') goto yy195; - if (yych <= '/') goto yy194; - if (yych <= '9') goto yy196; + if (yych <= '-') goto yy158; + if (yych <= '/') goto yy157; + if (yych <= '9') goto yy159; } -yy194: - YYDEBUG(194, *YYCURSOR); +yy157: + YYDEBUG(157, *YYCURSOR); YYCURSOR = YYMARKER; if (yyaccept <= 2) { if (yyaccept <= 1) { if (yyaccept <= 0) { - goto yy124; + goto yy87; } else { - goto yy139; + goto yy102; } } else { - goto yy173; + goto yy136; } } else { if (yyaccept <= 4) { if (yyaccept <= 3) { - goto yy190; + goto yy153; } else { - goto yy235; + goto yy190; } } else { - goto yy255; + goto yy210; } } -yy195: - YYDEBUG(195, *YYCURSOR); +yy158: + YYDEBUG(158, *YYCURSOR); yych = *++YYCURSOR; - if (yych <= '/') goto yy194; - if (yych >= ':') goto yy194; -yy196: - YYDEBUG(196, *YYCURSOR); + if (yych <= '/') goto yy157; + if (yych >= ':') goto yy157; +yy159: + YYDEBUG(159, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; - YYDEBUG(197, *YYCURSOR); - if (yych <= '/') goto yy190; - if (yych <= '9') goto yy196; - goto yy190; -yy198: - YYDEBUG(198, *YYCURSOR); + YYDEBUG(160, *YYCURSOR); + if (yych <= '/') goto yy153; + if (yych <= '9') goto yy159; + goto yy153; +yy161: + YYDEBUG(161, *YYCURSOR); yych = *++YYCURSOR; if (yybm[0+yych] & 32) { - goto yy203; + goto yy166; } - goto yy194; -yy199: - YYDEBUG(199, *YYCURSOR); + goto yy157; +yy162: + YYDEBUG(162, *YYCURSOR); yych = *++YYCURSOR; if (yybm[0+yych] & 16) { - goto yy200; + goto yy163; } - goto yy194; -yy200: - YYDEBUG(200, *YYCURSOR); + goto yy157; +yy163: + YYDEBUG(163, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; - YYDEBUG(201, *YYCURSOR); + YYDEBUG(164, *YYCURSOR); if (yybm[0+yych] & 16) { - goto yy200; + goto yy163; } - YYDEBUG(202, *YYCURSOR); + YYDEBUG(165, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1491 "Zend/zend_language_scanner.l" +#line 1495 "Zend/zend_language_scanner.l" { char *bin = yytext + 2; /* Skip "0b" */ int len = yyleng - 2; @@ -3298,19 +2978,19 @@ yy200: return T_DNUMBER; } } -#line 3302 "Zend/zend_language_scanner.c" -yy203: - YYDEBUG(203, *YYCURSOR); +#line 2982 "Zend/zend_language_scanner.c" +yy166: + YYDEBUG(166, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; - YYDEBUG(204, *YYCURSOR); + YYDEBUG(167, *YYCURSOR); if (yybm[0+yych] & 32) { - goto yy203; + goto yy166; } - YYDEBUG(205, *YYCURSOR); + YYDEBUG(168, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1532 "Zend/zend_language_scanner.l" +#line 1536 "Zend/zend_language_scanner.l" { char *hex = yytext + 2; /* Skip "0x" */ int len = yyleng - 2; @@ -3333,188 +3013,137 @@ yy203: return T_DNUMBER; } } -#line 3337 "Zend/zend_language_scanner.c" -yy206: - YYDEBUG(206, *YYCURSOR); - ++YYCURSOR; - if ((yych = *YYCURSOR) == '\n') goto yy208; - if (yych == '\r') goto yy209; -yy207: - YYDEBUG(207, *YYCURSOR); - yyleng = YYCURSOR - SCNG(yy_text); -#line 1840 "Zend/zend_language_scanner.l" - { - BEGIN(INITIAL); - return T_CLOSE_TAG; /* implicit ';' at php-end tag */ -} -#line 3351 "Zend/zend_language_scanner.c" -yy208: - YYDEBUG(208, *YYCURSOR); - yych = *++YYCURSOR; - goto yy207; -yy209: - YYDEBUG(209, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == '\n') goto yy208; - goto yy207; -yy210: - YYDEBUG(210, *YYCURSOR); +#line 3017 "Zend/zend_language_scanner.c" +yy169: + YYDEBUG(169, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; - YYDEBUG(211, *YYCURSOR); + YYDEBUG(170, *YYCURSOR); if (yych <= '^') { if (yych <= '9') { - if (yych >= '0') goto yy210; + if (yych >= '0') goto yy169; } else { - if (yych <= '@') goto yy212; - if (yych <= 'Z') goto yy210; + if (yych <= '@') goto yy171; + if (yych <= 'Z') goto yy169; } } else { if (yych <= '`') { - if (yych <= '_') goto yy210; + if (yych <= '_') goto yy169; } else { - if (yych <= 'z') goto yy210; - if (yych >= 0x7F) goto yy210; + if (yych <= 'z') goto yy169; + if (yych >= 0x7F) goto yy169; } } -yy212: - YYDEBUG(212, *YYCURSOR); +yy171: + YYDEBUG(171, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1744 "Zend/zend_language_scanner.l" +#line 1698 "Zend/zend_language_scanner.l" { zend_copy_value(zendlval, (yytext+1), (yyleng-1)); return T_VARIABLE; } -#line 3390 "Zend/zend_language_scanner.c" -yy213: - YYDEBUG(213, *YYCURSOR); +#line 3047 "Zend/zend_language_scanner.c" +yy172: + YYDEBUG(172, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'R') goto yy214; - if (yych != 'r') goto yy187; -yy214: - YYDEBUG(214, *YYCURSOR); + if (yych == 'R') goto yy173; + if (yych != 'r') goto yy150; +yy173: + YYDEBUG(173, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(215, *YYCURSOR); + YYDEBUG(174, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1437 "Zend/zend_language_scanner.l" +#line 1441 "Zend/zend_language_scanner.l" { return T_LOGICAL_XOR; } -#line 3408 "Zend/zend_language_scanner.c" -yy216: - YYDEBUG(216, *YYCURSOR); +#line 3065 "Zend/zend_language_scanner.c" +yy175: + YYDEBUG(175, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(217, *YYCURSOR); + YYDEBUG(176, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1429 "Zend/zend_language_scanner.l" +#line 1433 "Zend/zend_language_scanner.l" { return T_LOGICAL_OR; } -#line 3421 "Zend/zend_language_scanner.c" -yy218: - YYDEBUG(218, *YYCURSOR); +#line 3078 "Zend/zend_language_scanner.c" +yy177: + YYDEBUG(177, *YYCURSOR); ++YYCURSOR; - YYDEBUG(219, *YYCURSOR); + YYDEBUG(178, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1417 "Zend/zend_language_scanner.l" +#line 1421 "Zend/zend_language_scanner.l" { return T_XOR_EQUAL; } -#line 3431 "Zend/zend_language_scanner.c" -yy220: - YYDEBUG(220, *YYCURSOR); +#line 3088 "Zend/zend_language_scanner.c" +yy179: + YYDEBUG(179, *YYCURSOR); ++YYCURSOR; - YYDEBUG(221, *YYCURSOR); + YYDEBUG(180, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1421 "Zend/zend_language_scanner.l" +#line 1425 "Zend/zend_language_scanner.l" { return T_BOOLEAN_OR; } -#line 3441 "Zend/zend_language_scanner.c" -yy222: - YYDEBUG(222, *YYCURSOR); +#line 3098 "Zend/zend_language_scanner.c" +yy181: + YYDEBUG(181, *YYCURSOR); ++YYCURSOR; - YYDEBUG(223, *YYCURSOR); + YYDEBUG(182, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1413 "Zend/zend_language_scanner.l" +#line 1417 "Zend/zend_language_scanner.l" { return T_OR_EQUAL; } -#line 3451 "Zend/zend_language_scanner.c" -yy224: - YYDEBUG(224, *YYCURSOR); +#line 3108 "Zend/zend_language_scanner.c" +yy183: + YYDEBUG(183, *YYCURSOR); ++YYCURSOR; - YYDEBUG(225, *YYCURSOR); + YYDEBUG(184, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1425 "Zend/zend_language_scanner.l" +#line 1429 "Zend/zend_language_scanner.l" { return T_BOOLEAN_AND; } -#line 3461 "Zend/zend_language_scanner.c" -yy226: - YYDEBUG(226, *YYCURSOR); +#line 3118 "Zend/zend_language_scanner.c" +yy185: + YYDEBUG(185, *YYCURSOR); ++YYCURSOR; - YYDEBUG(227, *YYCURSOR); + YYDEBUG(186, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1409 "Zend/zend_language_scanner.l" +#line 1413 "Zend/zend_language_scanner.l" { return T_AND_EQUAL; } -#line 3471 "Zend/zend_language_scanner.c" -yy228: - YYDEBUG(228, *YYCURSOR); - ++YYCURSOR; - if ((yych = *YYCURSOR) == '\n') goto yy232; - if (yych == '\r') goto yy233; -yy229: - YYDEBUG(229, *YYCURSOR); - yyleng = YYCURSOR - SCNG(yy_text); -#line 1846 "Zend/zend_language_scanner.l" - { - if (CG(asp_tags)) { - BEGIN(INITIAL); - return T_CLOSE_TAG; /* implicit ';' at php-end tag */ - } else { - yyless(1); - return yytext[0]; - } -} -#line 3490 "Zend/zend_language_scanner.c" -yy230: - YYDEBUG(230, *YYCURSOR); +#line 3128 "Zend/zend_language_scanner.c" +yy187: + YYDEBUG(187, *YYCURSOR); ++YYCURSOR; - YYDEBUG(231, *YYCURSOR); + YYDEBUG(188, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1397 "Zend/zend_language_scanner.l" +#line 1401 "Zend/zend_language_scanner.l" { return T_MOD_EQUAL; } -#line 3500 "Zend/zend_language_scanner.c" -yy232: - YYDEBUG(232, *YYCURSOR); - yych = *++YYCURSOR; - goto yy229; -yy233: - YYDEBUG(233, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == '\n') goto yy232; - goto yy229; -yy234: - YYDEBUG(234, *YYCURSOR); +#line 3138 "Zend/zend_language_scanner.c" +yy189: + YYDEBUG(189, *YYCURSOR); yyaccept = 4; yych = *(YYMARKER = ++YYCURSOR); - if (yych == '*') goto yy239; -yy235: - YYDEBUG(235, *YYCURSOR); + if (yych == '*') goto yy194; +yy190: + YYDEBUG(190, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1807 "Zend/zend_language_scanner.l" +#line 1756 "Zend/zend_language_scanner.l" { int doc_com; @@ -3547,302 +3176,251 @@ yy235: return T_COMMENT; } -#line 3551 "Zend/zend_language_scanner.c" -yy236: - YYDEBUG(236, *YYCURSOR); +#line 3180 "Zend/zend_language_scanner.c" +yy191: + YYDEBUG(191, *YYCURSOR); yych = *++YYCURSOR; - goto yy177; -yy237: - YYDEBUG(237, *YYCURSOR); + goto yy140; +yy192: + YYDEBUG(192, *YYCURSOR); ++YYCURSOR; - YYDEBUG(238, *YYCURSOR); + YYDEBUG(193, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1389 "Zend/zend_language_scanner.l" +#line 1393 "Zend/zend_language_scanner.l" { return T_DIV_EQUAL; } -#line 3565 "Zend/zend_language_scanner.c" -yy239: - YYDEBUG(239, *YYCURSOR); +#line 3194 "Zend/zend_language_scanner.c" +yy194: + YYDEBUG(194, *YYCURSOR); yych = *++YYCURSOR; if (yybm[0+yych] & 64) { - goto yy240; + goto yy195; } - goto yy194; -yy240: - YYDEBUG(240, *YYCURSOR); + goto yy157; +yy195: + YYDEBUG(195, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; - YYDEBUG(241, *YYCURSOR); + YYDEBUG(196, *YYCURSOR); if (yybm[0+yych] & 64) { - goto yy240; + goto yy195; } - goto yy235; -yy242: - YYDEBUG(242, *YYCURSOR); + goto yy190; +yy197: + YYDEBUG(197, *YYCURSOR); ++YYCURSOR; - if ((yych = *YYCURSOR) == '=') goto yy246; - YYDEBUG(243, *YYCURSOR); + if ((yych = *YYCURSOR) == '=') goto yy201; + YYDEBUG(198, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1381 "Zend/zend_language_scanner.l" +#line 1385 "Zend/zend_language_scanner.l" { return T_POW; } -#line 3593 "Zend/zend_language_scanner.c" -yy244: - YYDEBUG(244, *YYCURSOR); +#line 3222 "Zend/zend_language_scanner.c" +yy199: + YYDEBUG(199, *YYCURSOR); ++YYCURSOR; - YYDEBUG(245, *YYCURSOR); + YYDEBUG(200, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1377 "Zend/zend_language_scanner.l" +#line 1381 "Zend/zend_language_scanner.l" { return T_MUL_EQUAL; } -#line 3603 "Zend/zend_language_scanner.c" -yy246: - YYDEBUG(246, *YYCURSOR); +#line 3232 "Zend/zend_language_scanner.c" +yy201: + YYDEBUG(201, *YYCURSOR); ++YYCURSOR; - YYDEBUG(247, *YYCURSOR); + YYDEBUG(202, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1385 "Zend/zend_language_scanner.l" +#line 1389 "Zend/zend_language_scanner.l" { return T_POW_EQUAL; } -#line 3613 "Zend/zend_language_scanner.c" -yy248: - YYDEBUG(248, *YYCURSOR); +#line 3242 "Zend/zend_language_scanner.c" +yy203: + YYDEBUG(203, *YYCURSOR); ++YYCURSOR; - if ((yych = *YYCURSOR) == '=') goto yy252; - YYDEBUG(249, *YYCURSOR); + if ((yych = *YYCURSOR) == '=') goto yy207; + YYDEBUG(204, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1445 "Zend/zend_language_scanner.l" +#line 1449 "Zend/zend_language_scanner.l" { return T_SR; } -#line 3624 "Zend/zend_language_scanner.c" -yy250: - YYDEBUG(250, *YYCURSOR); +#line 3253 "Zend/zend_language_scanner.c" +yy205: + YYDEBUG(205, *YYCURSOR); ++YYCURSOR; - YYDEBUG(251, *YYCURSOR); + YYDEBUG(206, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1365 "Zend/zend_language_scanner.l" +#line 1369 "Zend/zend_language_scanner.l" { return T_IS_GREATER_OR_EQUAL; } -#line 3634 "Zend/zend_language_scanner.c" -yy252: - YYDEBUG(252, *YYCURSOR); +#line 3263 "Zend/zend_language_scanner.c" +yy207: + YYDEBUG(207, *YYCURSOR); ++YYCURSOR; - YYDEBUG(253, *YYCURSOR); + YYDEBUG(208, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1405 "Zend/zend_language_scanner.l" +#line 1409 "Zend/zend_language_scanner.l" { return T_SR_EQUAL; } -#line 3644 "Zend/zend_language_scanner.c" -yy254: - YYDEBUG(254, *YYCURSOR); +#line 3273 "Zend/zend_language_scanner.c" +yy209: + YYDEBUG(209, *YYCURSOR); yyaccept = 5; yych = *(YYMARKER = ++YYCURSOR); - if (yych <= ';') goto yy255; - if (yych <= '<') goto yy270; - if (yych <= '=') goto yy268; -yy255: - YYDEBUG(255, *YYCURSOR); + if (yych <= ';') goto yy210; + if (yych <= '<') goto yy217; + if (yych <= '=') goto yy215; +yy210: + YYDEBUG(210, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1441 "Zend/zend_language_scanner.l" +#line 1445 "Zend/zend_language_scanner.l" { return T_SL; } -#line 3659 "Zend/zend_language_scanner.c" -yy256: - YYDEBUG(256, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'S') goto yy261; - if (yych == 's') goto yy261; - goto yy194; -yy257: - YYDEBUG(257, *YYCURSOR); +#line 3288 "Zend/zend_language_scanner.c" +yy211: + YYDEBUG(211, *YYCURSOR); ++YYCURSOR; - YYDEBUG(258, *YYCURSOR); + YYDEBUG(212, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1361 "Zend/zend_language_scanner.l" +#line 1365 "Zend/zend_language_scanner.l" { return T_IS_SMALLER_OR_EQUAL; } -#line 3675 "Zend/zend_language_scanner.c" -yy259: - YYDEBUG(259, *YYCURSOR); +#line 3298 "Zend/zend_language_scanner.c" +yy213: + YYDEBUG(213, *YYCURSOR); ++YYCURSOR; -yy260: - YYDEBUG(260, *YYCURSOR); +yy214: + YYDEBUG(214, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1357 "Zend/zend_language_scanner.l" +#line 1361 "Zend/zend_language_scanner.l" { return T_IS_NOT_EQUAL; } -#line 3686 "Zend/zend_language_scanner.c" -yy261: - YYDEBUG(261, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'C') goto yy262; - if (yych != 'c') goto yy194; -yy262: - YYDEBUG(262, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'R') goto yy263; - if (yych != 'r') goto yy194; -yy263: - YYDEBUG(263, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'I') goto yy264; - if (yych != 'i') goto yy194; -yy264: - YYDEBUG(264, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'P') goto yy265; - if (yych != 'p') goto yy194; -yy265: - YYDEBUG(265, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'T') goto yy266; - if (yych != 't') goto yy194; -yy266: - YYDEBUG(266, *YYCURSOR); - ++YYCURSOR; - YYFILL(3); - yych = *YYCURSOR; - YYDEBUG(267, *YYCURSOR); - if (yych <= '\r') { - if (yych <= 0x08) goto yy194; - if (yych <= '\n') goto yy266; - if (yych <= '\f') goto yy194; - goto yy266; - } else { - if (yych <= ' ') { - if (yych <= 0x1F) goto yy194; - goto yy266; - } else { - if (yych == '>') goto yy206; - goto yy194; - } - } -yy268: - YYDEBUG(268, *YYCURSOR); +#line 3309 "Zend/zend_language_scanner.c" +yy215: + YYDEBUG(215, *YYCURSOR); ++YYCURSOR; - YYDEBUG(269, *YYCURSOR); + YYDEBUG(216, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1401 "Zend/zend_language_scanner.l" +#line 1405 "Zend/zend_language_scanner.l" { return T_SL_EQUAL; } -#line 3741 "Zend/zend_language_scanner.c" -yy270: - YYDEBUG(270, *YYCURSOR); +#line 3319 "Zend/zend_language_scanner.c" +yy217: + YYDEBUG(217, *YYCURSOR); ++YYCURSOR; YYFILL(2); yych = *YYCURSOR; - YYDEBUG(271, *YYCURSOR); + YYDEBUG(218, *YYCURSOR); if (yybm[0+yych] & 128) { - goto yy270; + goto yy217; } if (yych <= 'Z') { if (yych <= '&') { - if (yych == '"') goto yy275; - goto yy194; + if (yych == '"') goto yy222; + goto yy157; } else { - if (yych <= '\'') goto yy274; - if (yych <= '@') goto yy194; + if (yych <= '\'') goto yy221; + if (yych <= '@') goto yy157; } } else { if (yych <= '`') { - if (yych != '_') goto yy194; + if (yych != '_') goto yy157; } else { - if (yych <= 'z') goto yy272; - if (yych <= '~') goto yy194; + if (yych <= 'z') goto yy219; + if (yych <= '~') goto yy157; } } -yy272: - YYDEBUG(272, *YYCURSOR); +yy219: + YYDEBUG(219, *YYCURSOR); ++YYCURSOR; YYFILL(2); yych = *YYCURSOR; - YYDEBUG(273, *YYCURSOR); + YYDEBUG(220, *YYCURSOR); if (yych <= '@') { if (yych <= '\f') { - if (yych == '\n') goto yy279; - goto yy194; + if (yych == '\n') goto yy226; + goto yy157; } else { - if (yych <= '\r') goto yy281; - if (yych <= '/') goto yy194; - if (yych <= '9') goto yy272; - goto yy194; + if (yych <= '\r') goto yy228; + if (yych <= '/') goto yy157; + if (yych <= '9') goto yy219; + goto yy157; } } else { if (yych <= '_') { - if (yych <= 'Z') goto yy272; - if (yych <= '^') goto yy194; - goto yy272; + if (yych <= 'Z') goto yy219; + if (yych <= '^') goto yy157; + goto yy219; } else { - if (yych <= '`') goto yy194; - if (yych <= 'z') goto yy272; - if (yych <= '~') goto yy194; - goto yy272; + if (yych <= '`') goto yy157; + if (yych <= 'z') goto yy219; + if (yych <= '~') goto yy157; + goto yy219; } } -yy274: - YYDEBUG(274, *YYCURSOR); +yy221: + YYDEBUG(221, *YYCURSOR); yych = *++YYCURSOR; - if (yych == '\'') goto yy194; - if (yych <= '/') goto yy283; - if (yych <= '9') goto yy194; - goto yy283; -yy275: - YYDEBUG(275, *YYCURSOR); + if (yych == '\'') goto yy157; + if (yych <= '/') goto yy230; + if (yych <= '9') goto yy157; + goto yy230; +yy222: + YYDEBUG(222, *YYCURSOR); yych = *++YYCURSOR; - if (yych == '"') goto yy194; - if (yych <= '/') goto yy277; - if (yych <= '9') goto yy194; - goto yy277; -yy276: - YYDEBUG(276, *YYCURSOR); + if (yych == '"') goto yy157; + if (yych <= '/') goto yy224; + if (yych <= '9') goto yy157; + goto yy224; +yy223: + YYDEBUG(223, *YYCURSOR); ++YYCURSOR; YYFILL(3); yych = *YYCURSOR; -yy277: - YYDEBUG(277, *YYCURSOR); +yy224: + YYDEBUG(224, *YYCURSOR); if (yych <= 'Z') { if (yych <= '/') { - if (yych != '"') goto yy194; + if (yych != '"') goto yy157; } else { - if (yych <= '9') goto yy276; - if (yych <= '@') goto yy194; - goto yy276; + if (yych <= '9') goto yy223; + if (yych <= '@') goto yy157; + goto yy223; } } else { if (yych <= '`') { - if (yych == '_') goto yy276; - goto yy194; + if (yych == '_') goto yy223; + goto yy157; } else { - if (yych <= 'z') goto yy276; - if (yych <= '~') goto yy194; - goto yy276; + if (yych <= 'z') goto yy223; + if (yych <= '~') goto yy157; + goto yy223; } } -yy278: - YYDEBUG(278, *YYCURSOR); +yy225: + YYDEBUG(225, *YYCURSOR); yych = *++YYCURSOR; - if (yych == '\n') goto yy279; - if (yych == '\r') goto yy281; - goto yy194; -yy279: - YYDEBUG(279, *YYCURSOR); + if (yych == '\n') goto yy226; + if (yych == '\r') goto yy228; + goto yy157; +yy226: + YYDEBUG(226, *YYCURSOR); ++YYCURSOR; -yy280: - YYDEBUG(280, *YYCURSOR); +yy227: + YYDEBUG(227, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1969 "Zend/zend_language_scanner.l" +#line 1907 "Zend/zend_language_scanner.l" { char *s; int bprefix = (yytext[0] != '<') ? 1 : 0; @@ -3889,3239 +3467,3272 @@ yy280: return T_START_HEREDOC; } -#line 3893 "Zend/zend_language_scanner.c" -yy281: - YYDEBUG(281, *YYCURSOR); +#line 3471 "Zend/zend_language_scanner.c" +yy228: + YYDEBUG(228, *YYCURSOR); yych = *++YYCURSOR; - if (yych == '\n') goto yy279; - goto yy280; -yy282: - YYDEBUG(282, *YYCURSOR); + if (yych == '\n') goto yy226; + goto yy227; +yy229: + YYDEBUG(229, *YYCURSOR); ++YYCURSOR; YYFILL(3); yych = *YYCURSOR; -yy283: - YYDEBUG(283, *YYCURSOR); +yy230: + YYDEBUG(230, *YYCURSOR); if (yych <= 'Z') { if (yych <= '/') { - if (yych == '\'') goto yy278; - goto yy194; + if (yych == '\'') goto yy225; + goto yy157; } else { - if (yych <= '9') goto yy282; - if (yych <= '@') goto yy194; - goto yy282; + if (yych <= '9') goto yy229; + if (yych <= '@') goto yy157; + goto yy229; } } else { if (yych <= '`') { - if (yych == '_') goto yy282; - goto yy194; + if (yych == '_') goto yy229; + goto yy157; } else { - if (yych <= 'z') goto yy282; - if (yych <= '~') goto yy194; - goto yy282; + if (yych <= 'z') goto yy229; + if (yych <= '~') goto yy157; + goto yy229; } } -yy284: - YYDEBUG(284, *YYCURSOR); +yy231: + YYDEBUG(231, *YYCURSOR); yych = *++YYCURSOR; - if (yych != '=') goto yy260; - YYDEBUG(285, *YYCURSOR); + if (yych != '=') goto yy214; + YYDEBUG(232, *YYCURSOR); ++YYCURSOR; - YYDEBUG(286, *YYCURSOR); + YYDEBUG(233, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1349 "Zend/zend_language_scanner.l" +#line 1353 "Zend/zend_language_scanner.l" { return T_IS_NOT_IDENTICAL; } -#line 3937 "Zend/zend_language_scanner.c" -yy287: - YYDEBUG(287, *YYCURSOR); +#line 3515 "Zend/zend_language_scanner.c" +yy234: + YYDEBUG(234, *YYCURSOR); ++YYCURSOR; - YYDEBUG(288, *YYCURSOR); + YYDEBUG(235, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1369 "Zend/zend_language_scanner.l" +#line 1373 "Zend/zend_language_scanner.l" { return T_PLUS_EQUAL; } -#line 3947 "Zend/zend_language_scanner.c" -yy289: - YYDEBUG(289, *YYCURSOR); +#line 3525 "Zend/zend_language_scanner.c" +yy236: + YYDEBUG(236, *YYCURSOR); ++YYCURSOR; - YYDEBUG(290, *YYCURSOR); + YYDEBUG(237, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1337 "Zend/zend_language_scanner.l" +#line 1341 "Zend/zend_language_scanner.l" { return T_INC; } -#line 3957 "Zend/zend_language_scanner.c" -yy291: - YYDEBUG(291, *YYCURSOR); +#line 3535 "Zend/zend_language_scanner.c" +yy238: + YYDEBUG(238, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'S') goto yy292; - if (yych != 's') goto yy187; -yy292: - YYDEBUG(292, *YYCURSOR); + if (yych == 'S') goto yy239; + if (yych != 's') goto yy150; +yy239: + YYDEBUG(239, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy293; - if (yych != 't') goto yy187; -yy293: - YYDEBUG(293, *YYCURSOR); + if (yych == 'T') goto yy240; + if (yych != 't') goto yy150; +yy240: + YYDEBUG(240, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(294, *YYCURSOR); + YYDEBUG(241, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1325 "Zend/zend_language_scanner.l" +#line 1329 "Zend/zend_language_scanner.l" { return T_LIST; } -#line 3980 "Zend/zend_language_scanner.c" -yy295: - YYDEBUG(295, *YYCURSOR); +#line 3558 "Zend/zend_language_scanner.c" +yy242: + YYDEBUG(242, *YYCURSOR); ++YYCURSOR; - if ((yych = *YYCURSOR) == '=') goto yy299; - YYDEBUG(296, *YYCURSOR); + if ((yych = *YYCURSOR) == '=') goto yy246; + YYDEBUG(243, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1353 "Zend/zend_language_scanner.l" +#line 1357 "Zend/zend_language_scanner.l" { return T_IS_EQUAL; } -#line 3991 "Zend/zend_language_scanner.c" -yy297: - YYDEBUG(297, *YYCURSOR); +#line 3569 "Zend/zend_language_scanner.c" +yy244: + YYDEBUG(244, *YYCURSOR); ++YYCURSOR; - YYDEBUG(298, *YYCURSOR); + YYDEBUG(245, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1321 "Zend/zend_language_scanner.l" +#line 1325 "Zend/zend_language_scanner.l" { return T_DOUBLE_ARROW; } -#line 4001 "Zend/zend_language_scanner.c" -yy299: - YYDEBUG(299, *YYCURSOR); +#line 3579 "Zend/zend_language_scanner.c" +yy246: + YYDEBUG(246, *YYCURSOR); ++YYCURSOR; - YYDEBUG(300, *YYCURSOR); + YYDEBUG(247, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1345 "Zend/zend_language_scanner.l" +#line 1349 "Zend/zend_language_scanner.l" { return T_IS_IDENTICAL; } -#line 4011 "Zend/zend_language_scanner.c" -yy301: - YYDEBUG(301, *YYCURSOR); +#line 3589 "Zend/zend_language_scanner.c" +yy248: + YYDEBUG(248, *YYCURSOR); yych = *++YYCURSOR; YYDEBUG(-1, yych); switch (yych) { case 'C': - case 'c': goto yy303; + case 'c': goto yy250; case 'D': - case 'd': goto yy308; + case 'd': goto yy255; case 'F': - case 'f': goto yy305; + case 'f': goto yy252; case 'H': - case 'h': goto yy302; + case 'h': goto yy249; case 'L': - case 'l': goto yy307; + case 'l': goto yy254; case 'M': - case 'm': goto yy306; + case 'm': goto yy253; case 'N': - case 'n': goto yy309; + case 'n': goto yy256; case 'T': - case 't': goto yy304; - default: goto yy187; + case 't': goto yy251; + default: goto yy150; } -yy302: - YYDEBUG(302, *YYCURSOR); +yy249: + YYDEBUG(249, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'A') goto yy370; - if (yych == 'a') goto yy370; - goto yy187; -yy303: - YYDEBUG(303, *YYCURSOR); + if (yych == 'A') goto yy317; + if (yych == 'a') goto yy317; + goto yy150; +yy250: + YYDEBUG(250, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'L') goto yy363; - if (yych == 'l') goto yy363; - goto yy187; -yy304: - YYDEBUG(304, *YYCURSOR); + if (yych == 'L') goto yy310; + if (yych == 'l') goto yy310; + goto yy150; +yy251: + YYDEBUG(251, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'R') goto yy356; - if (yych == 'r') goto yy356; - goto yy187; -yy305: - YYDEBUG(305, *YYCURSOR); + if (yych == 'R') goto yy303; + if (yych == 'r') goto yy303; + goto yy150; +yy252: + YYDEBUG(252, *YYCURSOR); yych = *++YYCURSOR; if (yych <= 'U') { - if (yych == 'I') goto yy340; - if (yych <= 'T') goto yy187; - goto yy341; + if (yych == 'I') goto yy287; + if (yych <= 'T') goto yy150; + goto yy288; } else { if (yych <= 'i') { - if (yych <= 'h') goto yy187; - goto yy340; + if (yych <= 'h') goto yy150; + goto yy287; } else { - if (yych == 'u') goto yy341; - goto yy187; + if (yych == 'u') goto yy288; + goto yy150; } } -yy306: - YYDEBUG(306, *YYCURSOR); +yy253: + YYDEBUG(253, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy332; - if (yych == 'e') goto yy332; - goto yy187; -yy307: - YYDEBUG(307, *YYCURSOR); + if (yych == 'E') goto yy279; + if (yych == 'e') goto yy279; + goto yy150; +yy254: + YYDEBUG(254, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'I') goto yy326; - if (yych == 'i') goto yy326; - goto yy187; -yy308: - YYDEBUG(308, *YYCURSOR); + if (yych == 'I') goto yy273; + if (yych == 'i') goto yy273; + goto yy150; +yy255: + YYDEBUG(255, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'I') goto yy321; - if (yych == 'i') goto yy321; - goto yy187; -yy309: - YYDEBUG(309, *YYCURSOR); + if (yych == 'I') goto yy268; + if (yych == 'i') goto yy268; + goto yy150; +yy256: + YYDEBUG(256, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'A') goto yy310; - if (yych != 'a') goto yy187; -yy310: - YYDEBUG(310, *YYCURSOR); + if (yych == 'A') goto yy257; + if (yych != 'a') goto yy150; +yy257: + YYDEBUG(257, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'M') goto yy311; - if (yych != 'm') goto yy187; -yy311: - YYDEBUG(311, *YYCURSOR); + if (yych == 'M') goto yy258; + if (yych != 'm') goto yy150; +yy258: + YYDEBUG(258, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy312; - if (yych != 'e') goto yy187; -yy312: - YYDEBUG(312, *YYCURSOR); + if (yych == 'E') goto yy259; + if (yych != 'e') goto yy150; +yy259: + YYDEBUG(259, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'S') goto yy313; - if (yych != 's') goto yy187; -yy313: - YYDEBUG(313, *YYCURSOR); + if (yych == 'S') goto yy260; + if (yych != 's') goto yy150; +yy260: + YYDEBUG(260, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'P') goto yy314; - if (yych != 'p') goto yy187; -yy314: - YYDEBUG(314, *YYCURSOR); + if (yych == 'P') goto yy261; + if (yych != 'p') goto yy150; +yy261: + YYDEBUG(261, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'A') goto yy315; - if (yych != 'a') goto yy187; -yy315: - YYDEBUG(315, *YYCURSOR); + if (yych == 'A') goto yy262; + if (yych != 'a') goto yy150; +yy262: + YYDEBUG(262, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'C') goto yy316; - if (yych != 'c') goto yy187; -yy316: - YYDEBUG(316, *YYCURSOR); + if (yych == 'C') goto yy263; + if (yych != 'c') goto yy150; +yy263: + YYDEBUG(263, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy317; - if (yych != 'e') goto yy187; -yy317: - YYDEBUG(317, *YYCURSOR); + if (yych == 'E') goto yy264; + if (yych != 'e') goto yy150; +yy264: + YYDEBUG(264, *YYCURSOR); yych = *++YYCURSOR; - if (yych != '_') goto yy187; - YYDEBUG(318, *YYCURSOR); + if (yych != '_') goto yy150; + YYDEBUG(265, *YYCURSOR); yych = *++YYCURSOR; - if (yych != '_') goto yy187; - YYDEBUG(319, *YYCURSOR); + if (yych != '_') goto yy150; + YYDEBUG(266, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(320, *YYCURSOR); + YYDEBUG(267, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1602 "Zend/zend_language_scanner.l" +#line 1606 "Zend/zend_language_scanner.l" { return T_NS_C; } -#line 4145 "Zend/zend_language_scanner.c" -yy321: - YYDEBUG(321, *YYCURSOR); +#line 3723 "Zend/zend_language_scanner.c" +yy268: + YYDEBUG(268, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'R') goto yy322; - if (yych != 'r') goto yy187; -yy322: - YYDEBUG(322, *YYCURSOR); + if (yych == 'R') goto yy269; + if (yych != 'r') goto yy150; +yy269: + YYDEBUG(269, *YYCURSOR); yych = *++YYCURSOR; - if (yych != '_') goto yy187; - YYDEBUG(323, *YYCURSOR); + if (yych != '_') goto yy150; + YYDEBUG(270, *YYCURSOR); yych = *++YYCURSOR; - if (yych != '_') goto yy187; - YYDEBUG(324, *YYCURSOR); + if (yych != '_') goto yy150; + YYDEBUG(271, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(325, *YYCURSOR); + YYDEBUG(272, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1598 "Zend/zend_language_scanner.l" +#line 1602 "Zend/zend_language_scanner.l" { return T_DIR; } -#line 4169 "Zend/zend_language_scanner.c" -yy326: - YYDEBUG(326, *YYCURSOR); +#line 3747 "Zend/zend_language_scanner.c" +yy273: + YYDEBUG(273, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'N') goto yy327; - if (yych != 'n') goto yy187; -yy327: - YYDEBUG(327, *YYCURSOR); + if (yych == 'N') goto yy274; + if (yych != 'n') goto yy150; +yy274: + YYDEBUG(274, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy328; - if (yych != 'e') goto yy187; -yy328: - YYDEBUG(328, *YYCURSOR); + if (yych == 'E') goto yy275; + if (yych != 'e') goto yy150; +yy275: + YYDEBUG(275, *YYCURSOR); yych = *++YYCURSOR; - if (yych != '_') goto yy187; - YYDEBUG(329, *YYCURSOR); + if (yych != '_') goto yy150; + YYDEBUG(276, *YYCURSOR); yych = *++YYCURSOR; - if (yych != '_') goto yy187; - YYDEBUG(330, *YYCURSOR); + if (yych != '_') goto yy150; + YYDEBUG(277, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(331, *YYCURSOR); + YYDEBUG(278, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1590 "Zend/zend_language_scanner.l" +#line 1594 "Zend/zend_language_scanner.l" { return T_LINE; } -#line 4198 "Zend/zend_language_scanner.c" -yy332: - YYDEBUG(332, *YYCURSOR); +#line 3776 "Zend/zend_language_scanner.c" +yy279: + YYDEBUG(279, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy333; - if (yych != 't') goto yy187; -yy333: - YYDEBUG(333, *YYCURSOR); + if (yych == 'T') goto yy280; + if (yych != 't') goto yy150; +yy280: + YYDEBUG(280, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'H') goto yy334; - if (yych != 'h') goto yy187; -yy334: - YYDEBUG(334, *YYCURSOR); + if (yych == 'H') goto yy281; + if (yych != 'h') goto yy150; +yy281: + YYDEBUG(281, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'O') goto yy335; - if (yych != 'o') goto yy187; -yy335: - YYDEBUG(335, *YYCURSOR); + if (yych == 'O') goto yy282; + if (yych != 'o') goto yy150; +yy282: + YYDEBUG(282, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'D') goto yy336; - if (yych != 'd') goto yy187; -yy336: - YYDEBUG(336, *YYCURSOR); + if (yych == 'D') goto yy283; + if (yych != 'd') goto yy150; +yy283: + YYDEBUG(283, *YYCURSOR); yych = *++YYCURSOR; - if (yych != '_') goto yy187; - YYDEBUG(337, *YYCURSOR); + if (yych != '_') goto yy150; + YYDEBUG(284, *YYCURSOR); yych = *++YYCURSOR; - if (yych != '_') goto yy187; - YYDEBUG(338, *YYCURSOR); + if (yych != '_') goto yy150; + YYDEBUG(285, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(339, *YYCURSOR); + YYDEBUG(286, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1586 "Zend/zend_language_scanner.l" +#line 1590 "Zend/zend_language_scanner.l" { return T_METHOD_C; } -#line 4237 "Zend/zend_language_scanner.c" -yy340: - YYDEBUG(340, *YYCURSOR); +#line 3815 "Zend/zend_language_scanner.c" +yy287: + YYDEBUG(287, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'L') goto yy351; - if (yych == 'l') goto yy351; - goto yy187; -yy341: - YYDEBUG(341, *YYCURSOR); + if (yych == 'L') goto yy298; + if (yych == 'l') goto yy298; + goto yy150; +yy288: + YYDEBUG(288, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'N') goto yy342; - if (yych != 'n') goto yy187; -yy342: - YYDEBUG(342, *YYCURSOR); + if (yych == 'N') goto yy289; + if (yych != 'n') goto yy150; +yy289: + YYDEBUG(289, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'C') goto yy343; - if (yych != 'c') goto yy187; -yy343: - YYDEBUG(343, *YYCURSOR); + if (yych == 'C') goto yy290; + if (yych != 'c') goto yy150; +yy290: + YYDEBUG(290, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy344; - if (yych != 't') goto yy187; -yy344: - YYDEBUG(344, *YYCURSOR); + if (yych == 'T') goto yy291; + if (yych != 't') goto yy150; +yy291: + YYDEBUG(291, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'I') goto yy345; - if (yych != 'i') goto yy187; -yy345: - YYDEBUG(345, *YYCURSOR); + if (yych == 'I') goto yy292; + if (yych != 'i') goto yy150; +yy292: + YYDEBUG(292, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'O') goto yy346; - if (yych != 'o') goto yy187; -yy346: - YYDEBUG(346, *YYCURSOR); + if (yych == 'O') goto yy293; + if (yych != 'o') goto yy150; +yy293: + YYDEBUG(293, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'N') goto yy347; - if (yych != 'n') goto yy187; -yy347: - YYDEBUG(347, *YYCURSOR); + if (yych == 'N') goto yy294; + if (yych != 'n') goto yy150; +yy294: + YYDEBUG(294, *YYCURSOR); yych = *++YYCURSOR; - if (yych != '_') goto yy187; - YYDEBUG(348, *YYCURSOR); + if (yych != '_') goto yy150; + YYDEBUG(295, *YYCURSOR); yych = *++YYCURSOR; - if (yych != '_') goto yy187; - YYDEBUG(349, *YYCURSOR); + if (yych != '_') goto yy150; + YYDEBUG(296, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(350, *YYCURSOR); + YYDEBUG(297, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1582 "Zend/zend_language_scanner.l" +#line 1586 "Zend/zend_language_scanner.l" { return T_FUNC_C; } -#line 4292 "Zend/zend_language_scanner.c" -yy351: - YYDEBUG(351, *YYCURSOR); +#line 3870 "Zend/zend_language_scanner.c" +yy298: + YYDEBUG(298, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy352; - if (yych != 'e') goto yy187; -yy352: - YYDEBUG(352, *YYCURSOR); + if (yych == 'E') goto yy299; + if (yych != 'e') goto yy150; +yy299: + YYDEBUG(299, *YYCURSOR); yych = *++YYCURSOR; - if (yych != '_') goto yy187; - YYDEBUG(353, *YYCURSOR); + if (yych != '_') goto yy150; + YYDEBUG(300, *YYCURSOR); yych = *++YYCURSOR; - if (yych != '_') goto yy187; - YYDEBUG(354, *YYCURSOR); + if (yych != '_') goto yy150; + YYDEBUG(301, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(355, *YYCURSOR); + YYDEBUG(302, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1594 "Zend/zend_language_scanner.l" +#line 1598 "Zend/zend_language_scanner.l" { return T_FILE; } -#line 4316 "Zend/zend_language_scanner.c" -yy356: - YYDEBUG(356, *YYCURSOR); +#line 3894 "Zend/zend_language_scanner.c" +yy303: + YYDEBUG(303, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'A') goto yy357; - if (yych != 'a') goto yy187; -yy357: - YYDEBUG(357, *YYCURSOR); + if (yych == 'A') goto yy304; + if (yych != 'a') goto yy150; +yy304: + YYDEBUG(304, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'I') goto yy358; - if (yych != 'i') goto yy187; -yy358: - YYDEBUG(358, *YYCURSOR); + if (yych == 'I') goto yy305; + if (yych != 'i') goto yy150; +yy305: + YYDEBUG(305, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy359; - if (yych != 't') goto yy187; -yy359: - YYDEBUG(359, *YYCURSOR); + if (yych == 'T') goto yy306; + if (yych != 't') goto yy150; +yy306: + YYDEBUG(306, *YYCURSOR); yych = *++YYCURSOR; - if (yych != '_') goto yy187; - YYDEBUG(360, *YYCURSOR); + if (yych != '_') goto yy150; + YYDEBUG(307, *YYCURSOR); yych = *++YYCURSOR; - if (yych != '_') goto yy187; - YYDEBUG(361, *YYCURSOR); + if (yych != '_') goto yy150; + YYDEBUG(308, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(362, *YYCURSOR); + YYDEBUG(309, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1578 "Zend/zend_language_scanner.l" +#line 1582 "Zend/zend_language_scanner.l" { return T_TRAIT_C; } -#line 4350 "Zend/zend_language_scanner.c" -yy363: - YYDEBUG(363, *YYCURSOR); +#line 3928 "Zend/zend_language_scanner.c" +yy310: + YYDEBUG(310, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'A') goto yy364; - if (yych != 'a') goto yy187; -yy364: - YYDEBUG(364, *YYCURSOR); + if (yych == 'A') goto yy311; + if (yych != 'a') goto yy150; +yy311: + YYDEBUG(311, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'S') goto yy365; - if (yych != 's') goto yy187; -yy365: - YYDEBUG(365, *YYCURSOR); + if (yych == 'S') goto yy312; + if (yych != 's') goto yy150; +yy312: + YYDEBUG(312, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'S') goto yy366; - if (yych != 's') goto yy187; -yy366: - YYDEBUG(366, *YYCURSOR); + if (yych == 'S') goto yy313; + if (yych != 's') goto yy150; +yy313: + YYDEBUG(313, *YYCURSOR); yych = *++YYCURSOR; - if (yych != '_') goto yy187; - YYDEBUG(367, *YYCURSOR); + if (yych != '_') goto yy150; + YYDEBUG(314, *YYCURSOR); yych = *++YYCURSOR; - if (yych != '_') goto yy187; - YYDEBUG(368, *YYCURSOR); + if (yych != '_') goto yy150; + YYDEBUG(315, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(369, *YYCURSOR); + YYDEBUG(316, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1574 "Zend/zend_language_scanner.l" +#line 1578 "Zend/zend_language_scanner.l" { return T_CLASS_C; } -#line 4384 "Zend/zend_language_scanner.c" -yy370: - YYDEBUG(370, *YYCURSOR); +#line 3962 "Zend/zend_language_scanner.c" +yy317: + YYDEBUG(317, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'L') goto yy371; - if (yych != 'l') goto yy187; -yy371: - YYDEBUG(371, *YYCURSOR); + if (yych == 'L') goto yy318; + if (yych != 'l') goto yy150; +yy318: + YYDEBUG(318, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy372; - if (yych != 't') goto yy187; -yy372: - YYDEBUG(372, *YYCURSOR); + if (yych == 'T') goto yy319; + if (yych != 't') goto yy150; +yy319: + YYDEBUG(319, *YYCURSOR); yych = *++YYCURSOR; - if (yych != '_') goto yy187; - YYDEBUG(373, *YYCURSOR); + if (yych != '_') goto yy150; + YYDEBUG(320, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'C') goto yy374; - if (yych != 'c') goto yy187; -yy374: - YYDEBUG(374, *YYCURSOR); + if (yych == 'C') goto yy321; + if (yych != 'c') goto yy150; +yy321: + YYDEBUG(321, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'O') goto yy375; - if (yych != 'o') goto yy187; -yy375: - YYDEBUG(375, *YYCURSOR); + if (yych == 'O') goto yy322; + if (yych != 'o') goto yy150; +yy322: + YYDEBUG(322, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'M') goto yy376; - if (yych != 'm') goto yy187; -yy376: - YYDEBUG(376, *YYCURSOR); + if (yych == 'M') goto yy323; + if (yych != 'm') goto yy150; +yy323: + YYDEBUG(323, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'P') goto yy377; - if (yych != 'p') goto yy187; -yy377: - YYDEBUG(377, *YYCURSOR); + if (yych == 'P') goto yy324; + if (yych != 'p') goto yy150; +yy324: + YYDEBUG(324, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'I') goto yy378; - if (yych != 'i') goto yy187; -yy378: - YYDEBUG(378, *YYCURSOR); + if (yych == 'I') goto yy325; + if (yych != 'i') goto yy150; +yy325: + YYDEBUG(325, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'L') goto yy379; - if (yych != 'l') goto yy187; -yy379: - YYDEBUG(379, *YYCURSOR); + if (yych == 'L') goto yy326; + if (yych != 'l') goto yy150; +yy326: + YYDEBUG(326, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy380; - if (yych != 'e') goto yy187; -yy380: - YYDEBUG(380, *YYCURSOR); + if (yych == 'E') goto yy327; + if (yych != 'e') goto yy150; +yy327: + YYDEBUG(327, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'R') goto yy381; - if (yych != 'r') goto yy187; -yy381: - YYDEBUG(381, *YYCURSOR); + if (yych == 'R') goto yy328; + if (yych != 'r') goto yy150; +yy328: + YYDEBUG(328, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(382, *YYCURSOR); + YYDEBUG(329, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1289 "Zend/zend_language_scanner.l" +#line 1293 "Zend/zend_language_scanner.l" { return T_HALT_COMPILER; } -#line 4450 "Zend/zend_language_scanner.c" -yy383: - YYDEBUG(383, *YYCURSOR); +#line 4028 "Zend/zend_language_scanner.c" +yy330: + YYDEBUG(330, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'S') goto yy387; - if (yych == 's') goto yy387; - goto yy187; -yy384: - YYDEBUG(384, *YYCURSOR); + if (yych == 'S') goto yy334; + if (yych == 's') goto yy334; + goto yy150; +yy331: + YYDEBUG(331, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy385; - if (yych != 'e') goto yy187; -yy385: - YYDEBUG(385, *YYCURSOR); + if (yych == 'E') goto yy332; + if (yych != 'e') goto yy150; +yy332: + YYDEBUG(332, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(386, *YYCURSOR); + YYDEBUG(333, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1269 "Zend/zend_language_scanner.l" +#line 1273 "Zend/zend_language_scanner.l" { return T_USE; } -#line 4474 "Zend/zend_language_scanner.c" -yy387: - YYDEBUG(387, *YYCURSOR); +#line 4052 "Zend/zend_language_scanner.c" +yy334: + YYDEBUG(334, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy388; - if (yych != 'e') goto yy187; -yy388: - YYDEBUG(388, *YYCURSOR); + if (yych == 'E') goto yy335; + if (yych != 'e') goto yy150; +yy335: + YYDEBUG(335, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy389; - if (yych != 't') goto yy187; -yy389: - YYDEBUG(389, *YYCURSOR); + if (yych == 'T') goto yy336; + if (yych != 't') goto yy150; +yy336: + YYDEBUG(336, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(390, *YYCURSOR); + YYDEBUG(337, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1317 "Zend/zend_language_scanner.l" +#line 1321 "Zend/zend_language_scanner.l" { return T_UNSET; } -#line 4497 "Zend/zend_language_scanner.c" -yy391: - YYDEBUG(391, *YYCURSOR); +#line 4075 "Zend/zend_language_scanner.c" +yy338: + YYDEBUG(338, *YYCURSOR); ++YYCURSOR; YYFILL(7); yych = *YYCURSOR; -yy392: - YYDEBUG(392, *YYCURSOR); +yy339: + YYDEBUG(339, *YYCURSOR); if (yych <= 'S') { if (yych <= 'D') { if (yych <= ' ') { - if (yych == '\t') goto yy391; - if (yych <= 0x1F) goto yy194; - goto yy391; + if (yych == '\t') goto yy338; + if (yych <= 0x1F) goto yy157; + goto yy338; } else { if (yych <= 'A') { - if (yych <= '@') goto yy194; - goto yy396; + if (yych <= '@') goto yy157; + goto yy343; } else { - if (yych <= 'B') goto yy394; - if (yych <= 'C') goto yy194; - goto yy399; + if (yych <= 'B') goto yy341; + if (yych <= 'C') goto yy157; + goto yy346; } } } else { if (yych <= 'I') { - if (yych == 'F') goto yy400; - if (yych <= 'H') goto yy194; - goto yy401; + if (yych == 'F') goto yy347; + if (yych <= 'H') goto yy157; + goto yy348; } else { if (yych <= 'O') { - if (yych <= 'N') goto yy194; - goto yy395; + if (yych <= 'N') goto yy157; + goto yy342; } else { - if (yych <= 'Q') goto yy194; - if (yych <= 'R') goto yy398; - goto yy397; + if (yych <= 'Q') goto yy157; + if (yych <= 'R') goto yy345; + goto yy344; } } } } else { if (yych <= 'f') { if (yych <= 'a') { - if (yych == 'U') goto yy393; - if (yych <= '`') goto yy194; - goto yy396; + if (yych == 'U') goto yy340; + if (yych <= '`') goto yy157; + goto yy343; } else { if (yych <= 'c') { - if (yych <= 'b') goto yy394; - goto yy194; + if (yych <= 'b') goto yy341; + goto yy157; } else { - if (yych <= 'd') goto yy399; - if (yych <= 'e') goto yy194; - goto yy400; + if (yych <= 'd') goto yy346; + if (yych <= 'e') goto yy157; + goto yy347; } } } else { if (yych <= 'q') { if (yych <= 'i') { - if (yych <= 'h') goto yy194; - goto yy401; + if (yych <= 'h') goto yy157; + goto yy348; } else { - if (yych == 'o') goto yy395; - goto yy194; + if (yych == 'o') goto yy342; + goto yy157; } } else { if (yych <= 's') { - if (yych <= 'r') goto yy398; - goto yy397; + if (yych <= 'r') goto yy345; + goto yy344; } else { - if (yych != 'u') goto yy194; + if (yych != 'u') goto yy157; } } } } -yy393: - YYDEBUG(393, *YYCURSOR); +yy340: + YYDEBUG(340, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'N') goto yy460; - if (yych == 'n') goto yy460; - goto yy194; -yy394: - YYDEBUG(394, *YYCURSOR); + if (yych == 'N') goto yy407; + if (yych == 'n') goto yy407; + goto yy157; +yy341: + YYDEBUG(341, *YYCURSOR); yych = *++YYCURSOR; if (yych <= 'O') { - if (yych == 'I') goto yy447; - if (yych <= 'N') goto yy194; - goto yy448; + if (yych == 'I') goto yy394; + if (yych <= 'N') goto yy157; + goto yy395; } else { if (yych <= 'i') { - if (yych <= 'h') goto yy194; - goto yy447; + if (yych <= 'h') goto yy157; + goto yy394; } else { - if (yych == 'o') goto yy448; - goto yy194; + if (yych == 'o') goto yy395; + goto yy157; } } -yy395: - YYDEBUG(395, *YYCURSOR); +yy342: + YYDEBUG(342, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'B') goto yy439; - if (yych == 'b') goto yy439; - goto yy194; -yy396: - YYDEBUG(396, *YYCURSOR); + if (yych == 'B') goto yy386; + if (yych == 'b') goto yy386; + goto yy157; +yy343: + YYDEBUG(343, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'R') goto yy432; - if (yych == 'r') goto yy432; - goto yy194; -yy397: - YYDEBUG(397, *YYCURSOR); + if (yych == 'R') goto yy379; + if (yych == 'r') goto yy379; + goto yy157; +yy344: + YYDEBUG(344, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy424; - if (yych == 't') goto yy424; - goto yy194; -yy398: - YYDEBUG(398, *YYCURSOR); + if (yych == 'T') goto yy371; + if (yych == 't') goto yy371; + goto yy157; +yy345: + YYDEBUG(345, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy422; - if (yych == 'e') goto yy422; - goto yy194; -yy399: - YYDEBUG(399, *YYCURSOR); + if (yych == 'E') goto yy369; + if (yych == 'e') goto yy369; + goto yy157; +yy346: + YYDEBUG(346, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'O') goto yy418; - if (yych == 'o') goto yy418; - goto yy194; -yy400: - YYDEBUG(400, *YYCURSOR); + if (yych == 'O') goto yy365; + if (yych == 'o') goto yy365; + goto yy157; +yy347: + YYDEBUG(347, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'L') goto yy411; - if (yych == 'l') goto yy411; - goto yy194; -yy401: - YYDEBUG(401, *YYCURSOR); + if (yych == 'L') goto yy358; + if (yych == 'l') goto yy358; + goto yy157; +yy348: + YYDEBUG(348, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'N') goto yy402; - if (yych != 'n') goto yy194; -yy402: - YYDEBUG(402, *YYCURSOR); + if (yych == 'N') goto yy349; + if (yych != 'n') goto yy157; +yy349: + YYDEBUG(349, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy403; - if (yych != 't') goto yy194; -yy403: - YYDEBUG(403, *YYCURSOR); + if (yych == 'T') goto yy350; + if (yych != 't') goto yy157; +yy350: + YYDEBUG(350, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy404; - if (yych != 'e') goto yy406; -yy404: - YYDEBUG(404, *YYCURSOR); + if (yych == 'E') goto yy351; + if (yych != 'e') goto yy353; +yy351: + YYDEBUG(351, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'G') goto yy409; - if (yych == 'g') goto yy409; - goto yy194; -yy405: - YYDEBUG(405, *YYCURSOR); + if (yych == 'G') goto yy356; + if (yych == 'g') goto yy356; + goto yy157; +yy352: + YYDEBUG(352, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; -yy406: - YYDEBUG(406, *YYCURSOR); +yy353: + YYDEBUG(353, *YYCURSOR); if (yych <= 0x1F) { - if (yych == '\t') goto yy405; - goto yy194; + if (yych == '\t') goto yy352; + goto yy157; } else { - if (yych <= ' ') goto yy405; - if (yych != ')') goto yy194; + if (yych <= ' ') goto yy352; + if (yych != ')') goto yy157; } - YYDEBUG(407, *YYCURSOR); + YYDEBUG(354, *YYCURSOR); ++YYCURSOR; - YYDEBUG(408, *YYCURSOR); + YYDEBUG(355, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1217 "Zend/zend_language_scanner.l" +#line 1221 "Zend/zend_language_scanner.l" { return T_INT_CAST; } -#line 4673 "Zend/zend_language_scanner.c" -yy409: - YYDEBUG(409, *YYCURSOR); +#line 4251 "Zend/zend_language_scanner.c" +yy356: + YYDEBUG(356, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy410; - if (yych != 'e') goto yy194; -yy410: - YYDEBUG(410, *YYCURSOR); + if (yych == 'E') goto yy357; + if (yych != 'e') goto yy157; +yy357: + YYDEBUG(357, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'R') goto yy405; - if (yych == 'r') goto yy405; - goto yy194; -yy411: - YYDEBUG(411, *YYCURSOR); + if (yych == 'R') goto yy352; + if (yych == 'r') goto yy352; + goto yy157; +yy358: + YYDEBUG(358, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'O') goto yy412; - if (yych != 'o') goto yy194; -yy412: - YYDEBUG(412, *YYCURSOR); + if (yych == 'O') goto yy359; + if (yych != 'o') goto yy157; +yy359: + YYDEBUG(359, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'A') goto yy413; - if (yych != 'a') goto yy194; -yy413: - YYDEBUG(413, *YYCURSOR); + if (yych == 'A') goto yy360; + if (yych != 'a') goto yy157; +yy360: + YYDEBUG(360, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy414; - if (yych != 't') goto yy194; -yy414: - YYDEBUG(414, *YYCURSOR); + if (yych == 'T') goto yy361; + if (yych != 't') goto yy157; +yy361: + YYDEBUG(361, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; - YYDEBUG(415, *YYCURSOR); + YYDEBUG(362, *YYCURSOR); if (yych <= 0x1F) { - if (yych == '\t') goto yy414; - goto yy194; + if (yych == '\t') goto yy361; + goto yy157; } else { - if (yych <= ' ') goto yy414; - if (yych != ')') goto yy194; + if (yych <= ' ') goto yy361; + if (yych != ')') goto yy157; } - YYDEBUG(416, *YYCURSOR); + YYDEBUG(363, *YYCURSOR); ++YYCURSOR; - YYDEBUG(417, *YYCURSOR); + YYDEBUG(364, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1221 "Zend/zend_language_scanner.l" +#line 1225 "Zend/zend_language_scanner.l" { return T_DOUBLE_CAST; } -#line 4721 "Zend/zend_language_scanner.c" -yy418: - YYDEBUG(418, *YYCURSOR); +#line 4299 "Zend/zend_language_scanner.c" +yy365: + YYDEBUG(365, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'U') goto yy419; - if (yych != 'u') goto yy194; -yy419: - YYDEBUG(419, *YYCURSOR); + if (yych == 'U') goto yy366; + if (yych != 'u') goto yy157; +yy366: + YYDEBUG(366, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'B') goto yy420; - if (yych != 'b') goto yy194; -yy420: - YYDEBUG(420, *YYCURSOR); + if (yych == 'B') goto yy367; + if (yych != 'b') goto yy157; +yy367: + YYDEBUG(367, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'L') goto yy421; - if (yych != 'l') goto yy194; -yy421: - YYDEBUG(421, *YYCURSOR); + if (yych == 'L') goto yy368; + if (yych != 'l') goto yy157; +yy368: + YYDEBUG(368, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy414; - if (yych == 'e') goto yy414; - goto yy194; -yy422: - YYDEBUG(422, *YYCURSOR); + if (yych == 'E') goto yy361; + if (yych == 'e') goto yy361; + goto yy157; +yy369: + YYDEBUG(369, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'A') goto yy423; - if (yych != 'a') goto yy194; -yy423: - YYDEBUG(423, *YYCURSOR); + if (yych == 'A') goto yy370; + if (yych != 'a') goto yy157; +yy370: + YYDEBUG(370, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'L') goto yy414; - if (yych == 'l') goto yy414; - goto yy194; -yy424: - YYDEBUG(424, *YYCURSOR); + if (yych == 'L') goto yy361; + if (yych == 'l') goto yy361; + goto yy157; +yy371: + YYDEBUG(371, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'R') goto yy425; - if (yych != 'r') goto yy194; -yy425: - YYDEBUG(425, *YYCURSOR); + if (yych == 'R') goto yy372; + if (yych != 'r') goto yy157; +yy372: + YYDEBUG(372, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'I') goto yy426; - if (yych != 'i') goto yy194; -yy426: - YYDEBUG(426, *YYCURSOR); + if (yych == 'I') goto yy373; + if (yych != 'i') goto yy157; +yy373: + YYDEBUG(373, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'N') goto yy427; - if (yych != 'n') goto yy194; -yy427: - YYDEBUG(427, *YYCURSOR); + if (yych == 'N') goto yy374; + if (yych != 'n') goto yy157; +yy374: + YYDEBUG(374, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'G') goto yy428; - if (yych != 'g') goto yy194; -yy428: - YYDEBUG(428, *YYCURSOR); + if (yych == 'G') goto yy375; + if (yych != 'g') goto yy157; +yy375: + YYDEBUG(375, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; - YYDEBUG(429, *YYCURSOR); + YYDEBUG(376, *YYCURSOR); if (yych <= 0x1F) { - if (yych == '\t') goto yy428; - goto yy194; + if (yych == '\t') goto yy375; + goto yy157; } else { - if (yych <= ' ') goto yy428; - if (yych != ')') goto yy194; + if (yych <= ' ') goto yy375; + if (yych != ')') goto yy157; } - YYDEBUG(430, *YYCURSOR); + YYDEBUG(377, *YYCURSOR); ++YYCURSOR; - YYDEBUG(431, *YYCURSOR); + YYDEBUG(378, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1225 "Zend/zend_language_scanner.l" +#line 1229 "Zend/zend_language_scanner.l" { return T_STRING_CAST; } -#line 4795 "Zend/zend_language_scanner.c" -yy432: - YYDEBUG(432, *YYCURSOR); +#line 4373 "Zend/zend_language_scanner.c" +yy379: + YYDEBUG(379, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'R') goto yy433; - if (yych != 'r') goto yy194; -yy433: - YYDEBUG(433, *YYCURSOR); + if (yych == 'R') goto yy380; + if (yych != 'r') goto yy157; +yy380: + YYDEBUG(380, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'A') goto yy434; - if (yych != 'a') goto yy194; -yy434: - YYDEBUG(434, *YYCURSOR); + if (yych == 'A') goto yy381; + if (yych != 'a') goto yy157; +yy381: + YYDEBUG(381, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'Y') goto yy435; - if (yych != 'y') goto yy194; -yy435: - YYDEBUG(435, *YYCURSOR); + if (yych == 'Y') goto yy382; + if (yych != 'y') goto yy157; +yy382: + YYDEBUG(382, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; - YYDEBUG(436, *YYCURSOR); + YYDEBUG(383, *YYCURSOR); if (yych <= 0x1F) { - if (yych == '\t') goto yy435; - goto yy194; + if (yych == '\t') goto yy382; + goto yy157; } else { - if (yych <= ' ') goto yy435; - if (yych != ')') goto yy194; + if (yych <= ' ') goto yy382; + if (yych != ')') goto yy157; } - YYDEBUG(437, *YYCURSOR); + YYDEBUG(384, *YYCURSOR); ++YYCURSOR; - YYDEBUG(438, *YYCURSOR); + YYDEBUG(385, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1229 "Zend/zend_language_scanner.l" +#line 1233 "Zend/zend_language_scanner.l" { return T_ARRAY_CAST; } -#line 4832 "Zend/zend_language_scanner.c" -yy439: - YYDEBUG(439, *YYCURSOR); +#line 4410 "Zend/zend_language_scanner.c" +yy386: + YYDEBUG(386, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'J') goto yy440; - if (yych != 'j') goto yy194; -yy440: - YYDEBUG(440, *YYCURSOR); + if (yych == 'J') goto yy387; + if (yych != 'j') goto yy157; +yy387: + YYDEBUG(387, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy441; - if (yych != 'e') goto yy194; -yy441: - YYDEBUG(441, *YYCURSOR); + if (yych == 'E') goto yy388; + if (yych != 'e') goto yy157; +yy388: + YYDEBUG(388, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'C') goto yy442; - if (yych != 'c') goto yy194; -yy442: - YYDEBUG(442, *YYCURSOR); + if (yych == 'C') goto yy389; + if (yych != 'c') goto yy157; +yy389: + YYDEBUG(389, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy443; - if (yych != 't') goto yy194; -yy443: - YYDEBUG(443, *YYCURSOR); + if (yych == 'T') goto yy390; + if (yych != 't') goto yy157; +yy390: + YYDEBUG(390, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; - YYDEBUG(444, *YYCURSOR); + YYDEBUG(391, *YYCURSOR); if (yych <= 0x1F) { - if (yych == '\t') goto yy443; - goto yy194; + if (yych == '\t') goto yy390; + goto yy157; } else { - if (yych <= ' ') goto yy443; - if (yych != ')') goto yy194; + if (yych <= ' ') goto yy390; + if (yych != ')') goto yy157; } - YYDEBUG(445, *YYCURSOR); + YYDEBUG(392, *YYCURSOR); ++YYCURSOR; - YYDEBUG(446, *YYCURSOR); + YYDEBUG(393, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1233 "Zend/zend_language_scanner.l" +#line 1237 "Zend/zend_language_scanner.l" { return T_OBJECT_CAST; } -#line 4874 "Zend/zend_language_scanner.c" -yy447: - YYDEBUG(447, *YYCURSOR); +#line 4452 "Zend/zend_language_scanner.c" +yy394: + YYDEBUG(394, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'N') goto yy457; - if (yych == 'n') goto yy457; - goto yy194; -yy448: - YYDEBUG(448, *YYCURSOR); + if (yych == 'N') goto yy404; + if (yych == 'n') goto yy404; + goto yy157; +yy395: + YYDEBUG(395, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'O') goto yy449; - if (yych != 'o') goto yy194; -yy449: - YYDEBUG(449, *YYCURSOR); + if (yych == 'O') goto yy396; + if (yych != 'o') goto yy157; +yy396: + YYDEBUG(396, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'L') goto yy450; - if (yych != 'l') goto yy194; -yy450: - YYDEBUG(450, *YYCURSOR); + if (yych == 'L') goto yy397; + if (yych != 'l') goto yy157; +yy397: + YYDEBUG(397, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy455; - if (yych == 'e') goto yy455; - goto yy452; -yy451: - YYDEBUG(451, *YYCURSOR); + if (yych == 'E') goto yy402; + if (yych == 'e') goto yy402; + goto yy399; +yy398: + YYDEBUG(398, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; -yy452: - YYDEBUG(452, *YYCURSOR); +yy399: + YYDEBUG(399, *YYCURSOR); if (yych <= 0x1F) { - if (yych == '\t') goto yy451; - goto yy194; + if (yych == '\t') goto yy398; + goto yy157; } else { - if (yych <= ' ') goto yy451; - if (yych != ')') goto yy194; + if (yych <= ' ') goto yy398; + if (yych != ')') goto yy157; } - YYDEBUG(453, *YYCURSOR); + YYDEBUG(400, *YYCURSOR); ++YYCURSOR; - YYDEBUG(454, *YYCURSOR); + YYDEBUG(401, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1237 "Zend/zend_language_scanner.l" +#line 1241 "Zend/zend_language_scanner.l" { return T_BOOL_CAST; } -#line 4919 "Zend/zend_language_scanner.c" -yy455: - YYDEBUG(455, *YYCURSOR); +#line 4497 "Zend/zend_language_scanner.c" +yy402: + YYDEBUG(402, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'A') goto yy456; - if (yych != 'a') goto yy194; -yy456: - YYDEBUG(456, *YYCURSOR); + if (yych == 'A') goto yy403; + if (yych != 'a') goto yy157; +yy403: + YYDEBUG(403, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'N') goto yy451; - if (yych == 'n') goto yy451; - goto yy194; -yy457: - YYDEBUG(457, *YYCURSOR); + if (yych == 'N') goto yy398; + if (yych == 'n') goto yy398; + goto yy157; +yy404: + YYDEBUG(404, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'A') goto yy458; - if (yych != 'a') goto yy194; -yy458: - YYDEBUG(458, *YYCURSOR); + if (yych == 'A') goto yy405; + if (yych != 'a') goto yy157; +yy405: + YYDEBUG(405, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'R') goto yy459; - if (yych != 'r') goto yy194; -yy459: - YYDEBUG(459, *YYCURSOR); + if (yych == 'R') goto yy406; + if (yych != 'r') goto yy157; +yy406: + YYDEBUG(406, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'Y') goto yy428; - if (yych == 'y') goto yy428; - goto yy194; -yy460: - YYDEBUG(460, *YYCURSOR); + if (yych == 'Y') goto yy375; + if (yych == 'y') goto yy375; + goto yy157; +yy407: + YYDEBUG(407, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'S') goto yy461; - if (yych != 's') goto yy194; -yy461: - YYDEBUG(461, *YYCURSOR); + if (yych == 'S') goto yy408; + if (yych != 's') goto yy157; +yy408: + YYDEBUG(408, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy462; - if (yych != 'e') goto yy194; -yy462: - YYDEBUG(462, *YYCURSOR); + if (yych == 'E') goto yy409; + if (yych != 'e') goto yy157; +yy409: + YYDEBUG(409, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy463; - if (yych != 't') goto yy194; -yy463: - YYDEBUG(463, *YYCURSOR); + if (yych == 'T') goto yy410; + if (yych != 't') goto yy157; +yy410: + YYDEBUG(410, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; - YYDEBUG(464, *YYCURSOR); + YYDEBUG(411, *YYCURSOR); if (yych <= 0x1F) { - if (yych == '\t') goto yy463; - goto yy194; + if (yych == '\t') goto yy410; + goto yy157; } else { - if (yych <= ' ') goto yy463; - if (yych != ')') goto yy194; + if (yych <= ' ') goto yy410; + if (yych != ')') goto yy157; } - YYDEBUG(465, *YYCURSOR); + YYDEBUG(412, *YYCURSOR); ++YYCURSOR; - YYDEBUG(466, *YYCURSOR); + YYDEBUG(413, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1241 "Zend/zend_language_scanner.l" +#line 1245 "Zend/zend_language_scanner.l" { return T_UNSET_CAST; } -#line 4983 "Zend/zend_language_scanner.c" -yy467: - YYDEBUG(467, *YYCURSOR); +#line 4561 "Zend/zend_language_scanner.c" +yy414: + YYDEBUG(414, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'R') goto yy468; - if (yych != 'r') goto yy187; -yy468: - YYDEBUG(468, *YYCURSOR); + if (yych == 'R') goto yy415; + if (yych != 'r') goto yy150; +yy415: + YYDEBUG(415, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(469, *YYCURSOR); + YYDEBUG(416, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1213 "Zend/zend_language_scanner.l" +#line 1217 "Zend/zend_language_scanner.l" { return T_VAR; } -#line 5001 "Zend/zend_language_scanner.c" -yy470: - YYDEBUG(470, *YYCURSOR); +#line 4579 "Zend/zend_language_scanner.c" +yy417: + YYDEBUG(417, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'M') goto yy474; - if (yych == 'm') goto yy474; - goto yy187; -yy471: - YYDEBUG(471, *YYCURSOR); + if (yych == 'M') goto yy421; + if (yych == 'm') goto yy421; + goto yy150; +yy418: + YYDEBUG(418, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'W') goto yy472; - if (yych != 'w') goto yy187; -yy472: - YYDEBUG(472, *YYCURSOR); + if (yych == 'W') goto yy419; + if (yych != 'w') goto yy150; +yy419: + YYDEBUG(419, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(473, *YYCURSOR); + YYDEBUG(420, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1205 "Zend/zend_language_scanner.l" +#line 1209 "Zend/zend_language_scanner.l" { return T_NEW; } -#line 5025 "Zend/zend_language_scanner.c" -yy474: - YYDEBUG(474, *YYCURSOR); +#line 4603 "Zend/zend_language_scanner.c" +yy421: + YYDEBUG(421, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy475; - if (yych != 'e') goto yy187; -yy475: - YYDEBUG(475, *YYCURSOR); + if (yych == 'E') goto yy422; + if (yych != 'e') goto yy150; +yy422: + YYDEBUG(422, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'S') goto yy476; - if (yych != 's') goto yy187; -yy476: - YYDEBUG(476, *YYCURSOR); + if (yych == 'S') goto yy423; + if (yych != 's') goto yy150; +yy423: + YYDEBUG(423, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'P') goto yy477; - if (yych != 'p') goto yy187; -yy477: - YYDEBUG(477, *YYCURSOR); + if (yych == 'P') goto yy424; + if (yych != 'p') goto yy150; +yy424: + YYDEBUG(424, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'A') goto yy478; - if (yych != 'a') goto yy187; -yy478: - YYDEBUG(478, *YYCURSOR); + if (yych == 'A') goto yy425; + if (yych != 'a') goto yy150; +yy425: + YYDEBUG(425, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'C') goto yy479; - if (yych != 'c') goto yy187; -yy479: - YYDEBUG(479, *YYCURSOR); + if (yych == 'C') goto yy426; + if (yych != 'c') goto yy150; +yy426: + YYDEBUG(426, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy480; - if (yych != 'e') goto yy187; -yy480: - YYDEBUG(480, *YYCURSOR); + if (yych == 'E') goto yy427; + if (yych != 'e') goto yy150; +yy427: + YYDEBUG(427, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(481, *YYCURSOR); + YYDEBUG(428, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1265 "Zend/zend_language_scanner.l" +#line 1269 "Zend/zend_language_scanner.l" { return T_NAMESPACE; } -#line 5068 "Zend/zend_language_scanner.c" -yy482: - YYDEBUG(482, *YYCURSOR); +#line 4646 "Zend/zend_language_scanner.c" +yy429: + YYDEBUG(429, *YYCURSOR); + ++YYCURSOR; + if ((yych = *YYCURSOR) == '\n') goto yy433; + if (yych == '\r') goto yy434; +yy430: + YYDEBUG(430, *YYCURSOR); + yyleng = YYCURSOR - SCNG(yy_text); +#line 1789 "Zend/zend_language_scanner.l" + { + BEGIN(INITIAL); + return T_CLOSE_TAG; /* implicit ';' at php-end tag */ +} +#line 4660 "Zend/zend_language_scanner.c" +yy431: + YYDEBUG(431, *YYCURSOR); + ++YYCURSOR; + YYDEBUG(432, *YYCURSOR); + yyleng = YYCURSOR - SCNG(yy_text); +#line 1205 "Zend/zend_language_scanner.l" + { + return T_COALESCE; +} +#line 4670 "Zend/zend_language_scanner.c" +yy433: + YYDEBUG(433, *YYCURSOR); + yych = *++YYCURSOR; + goto yy430; +yy434: + YYDEBUG(434, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == '\n') goto yy433; + goto yy430; +yy435: + YYDEBUG(435, *YYCURSOR); yyaccept = 3; YYMARKER = ++YYCURSOR; YYFILL(3); yych = *YYCURSOR; - YYDEBUG(483, *YYCURSOR); + YYDEBUG(436, *YYCURSOR); if (yych <= 'D') { - if (yych <= '/') goto yy190; - if (yych <= '9') goto yy482; - goto yy190; + if (yych <= '/') goto yy153; + if (yych <= '9') goto yy435; + goto yy153; } else { - if (yych <= 'E') goto yy193; - if (yych == 'e') goto yy193; - goto yy190; + if (yych <= 'E') goto yy156; + if (yych == 'e') goto yy156; + goto yy153; } -yy484: - YYDEBUG(484, *YYCURSOR); +yy437: + YYDEBUG(437, *YYCURSOR); ++YYCURSOR; - YYDEBUG(485, *YYCURSOR); + YYDEBUG(438, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1393 "Zend/zend_language_scanner.l" +#line 1397 "Zend/zend_language_scanner.l" { return T_CONCAT_EQUAL; } -#line 5094 "Zend/zend_language_scanner.c" -yy486: - YYDEBUG(486, *YYCURSOR); +#line 4705 "Zend/zend_language_scanner.c" +yy439: + YYDEBUG(439, *YYCURSOR); yych = *++YYCURSOR; - if (yych != '.') goto yy194; - YYDEBUG(487, *YYCURSOR); + if (yych != '.') goto yy157; + YYDEBUG(440, *YYCURSOR); ++YYCURSOR; - YYDEBUG(488, *YYCURSOR); + YYDEBUG(441, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1201 "Zend/zend_language_scanner.l" { return T_ELLIPSIS; } -#line 5107 "Zend/zend_language_scanner.c" -yy489: - YYDEBUG(489, *YYCURSOR); +#line 4718 "Zend/zend_language_scanner.c" +yy442: + YYDEBUG(442, *YYCURSOR); ++YYCURSOR; - YYDEBUG(490, *YYCURSOR); + YYDEBUG(443, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1193 "Zend/zend_language_scanner.l" { return T_PAAMAYIM_NEKUDOTAYIM; } -#line 5117 "Zend/zend_language_scanner.c" -yy491: - YYDEBUG(491, *YYCURSOR); +#line 4728 "Zend/zend_language_scanner.c" +yy444: + YYDEBUG(444, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; -yy492: - YYDEBUG(492, *YYCURSOR); +yy445: + YYDEBUG(445, *YYCURSOR); if (yych <= '\f') { - if (yych <= 0x08) goto yy141; - if (yych <= '\n') goto yy491; - goto yy141; + if (yych <= 0x08) goto yy104; + if (yych <= '\n') goto yy444; + goto yy104; } else { - if (yych <= '\r') goto yy491; - if (yych == ' ') goto yy491; - goto yy141; + if (yych <= '\r') goto yy444; + if (yych == ' ') goto yy444; + goto yy104; } -yy493: - YYDEBUG(493, *YYCURSOR); +yy446: + YYDEBUG(446, *YYCURSOR); ++YYCURSOR; - YYDEBUG(494, *YYCURSOR); + YYDEBUG(447, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1373 "Zend/zend_language_scanner.l" +#line 1377 "Zend/zend_language_scanner.l" { return T_MINUS_EQUAL; } -#line 5143 "Zend/zend_language_scanner.c" -yy495: - YYDEBUG(495, *YYCURSOR); +#line 4754 "Zend/zend_language_scanner.c" +yy448: + YYDEBUG(448, *YYCURSOR); ++YYCURSOR; - YYDEBUG(496, *YYCURSOR); + YYDEBUG(449, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1341 "Zend/zend_language_scanner.l" +#line 1345 "Zend/zend_language_scanner.l" { return T_DEC; } -#line 5153 "Zend/zend_language_scanner.c" -yy497: - YYDEBUG(497, *YYCURSOR); +#line 4764 "Zend/zend_language_scanner.c" +yy450: + YYDEBUG(450, *YYCURSOR); ++YYCURSOR; - YYDEBUG(498, *YYCURSOR); + YYDEBUG(451, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1167 "Zend/zend_language_scanner.l" { yy_push_state(ST_LOOKING_FOR_PROPERTY TSRMLS_CC); return T_OBJECT_OPERATOR; } -#line 5164 "Zend/zend_language_scanner.c" -yy499: - YYDEBUG(499, *YYCURSOR); +#line 4775 "Zend/zend_language_scanner.c" +yy452: + YYDEBUG(452, *YYCURSOR); yych = *++YYCURSOR; if (yych <= 'O') { - if (yych == 'I') goto yy506; - if (yych <= 'N') goto yy187; - goto yy507; + if (yych == 'I') goto yy459; + if (yych <= 'N') goto yy150; + goto yy460; } else { if (yych <= 'i') { - if (yych <= 'h') goto yy187; - goto yy506; + if (yych <= 'h') goto yy150; + goto yy459; } else { - if (yych == 'o') goto yy507; - goto yy187; + if (yych == 'o') goto yy460; + goto yy150; } } -yy500: - YYDEBUG(500, *YYCURSOR); +yy453: + YYDEBUG(453, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'B') goto yy501; - if (yych != 'b') goto yy187; -yy501: - YYDEBUG(501, *YYCURSOR); + if (yych == 'B') goto yy454; + if (yych != 'b') goto yy150; +yy454: + YYDEBUG(454, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'L') goto yy502; - if (yych != 'l') goto yy187; -yy502: - YYDEBUG(502, *YYCURSOR); + if (yych == 'L') goto yy455; + if (yych != 'l') goto yy150; +yy455: + YYDEBUG(455, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'I') goto yy503; - if (yych != 'i') goto yy187; -yy503: - YYDEBUG(503, *YYCURSOR); + if (yych == 'I') goto yy456; + if (yych != 'i') goto yy150; +yy456: + YYDEBUG(456, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'C') goto yy504; - if (yych != 'c') goto yy187; -yy504: - YYDEBUG(504, *YYCURSOR); + if (yych == 'C') goto yy457; + if (yych != 'c') goto yy150; +yy457: + YYDEBUG(457, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(505, *YYCURSOR); + YYDEBUG(458, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1313 "Zend/zend_language_scanner.l" +#line 1317 "Zend/zend_language_scanner.l" { return T_PUBLIC; } -#line 5213 "Zend/zend_language_scanner.c" -yy506: - YYDEBUG(506, *YYCURSOR); +#line 4824 "Zend/zend_language_scanner.c" +yy459: + YYDEBUG(459, *YYCURSOR); yych = *++YYCURSOR; if (yych <= 'V') { - if (yych == 'N') goto yy515; - if (yych <= 'U') goto yy187; - goto yy516; + if (yych == 'N') goto yy468; + if (yych <= 'U') goto yy150; + goto yy469; } else { if (yych <= 'n') { - if (yych <= 'm') goto yy187; - goto yy515; + if (yych <= 'm') goto yy150; + goto yy468; } else { - if (yych == 'v') goto yy516; - goto yy187; + if (yych == 'v') goto yy469; + goto yy150; } } -yy507: - YYDEBUG(507, *YYCURSOR); +yy460: + YYDEBUG(460, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy508; - if (yych != 't') goto yy187; -yy508: - YYDEBUG(508, *YYCURSOR); + if (yych == 'T') goto yy461; + if (yych != 't') goto yy150; +yy461: + YYDEBUG(461, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy509; - if (yych != 'e') goto yy187; -yy509: - YYDEBUG(509, *YYCURSOR); + if (yych == 'E') goto yy462; + if (yych != 'e') goto yy150; +yy462: + YYDEBUG(462, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'C') goto yy510; - if (yych != 'c') goto yy187; -yy510: - YYDEBUG(510, *YYCURSOR); + if (yych == 'C') goto yy463; + if (yych != 'c') goto yy150; +yy463: + YYDEBUG(463, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy511; - if (yych != 't') goto yy187; -yy511: - YYDEBUG(511, *YYCURSOR); + if (yych == 'T') goto yy464; + if (yych != 't') goto yy150; +yy464: + YYDEBUG(464, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy512; - if (yych != 'e') goto yy187; -yy512: - YYDEBUG(512, *YYCURSOR); + if (yych == 'E') goto yy465; + if (yych != 'e') goto yy150; +yy465: + YYDEBUG(465, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'D') goto yy513; - if (yych != 'd') goto yy187; -yy513: - YYDEBUG(513, *YYCURSOR); + if (yych == 'D') goto yy466; + if (yych != 'd') goto yy150; +yy466: + YYDEBUG(466, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(514, *YYCURSOR); + YYDEBUG(467, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1309 "Zend/zend_language_scanner.l" +#line 1313 "Zend/zend_language_scanner.l" { return T_PROTECTED; } -#line 5272 "Zend/zend_language_scanner.c" -yy515: - YYDEBUG(515, *YYCURSOR); +#line 4883 "Zend/zend_language_scanner.c" +yy468: + YYDEBUG(468, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy521; - if (yych == 't') goto yy521; - goto yy187; -yy516: - YYDEBUG(516, *YYCURSOR); + if (yych == 'T') goto yy474; + if (yych == 't') goto yy474; + goto yy150; +yy469: + YYDEBUG(469, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'A') goto yy517; - if (yych != 'a') goto yy187; -yy517: - YYDEBUG(517, *YYCURSOR); + if (yych == 'A') goto yy470; + if (yych != 'a') goto yy150; +yy470: + YYDEBUG(470, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy518; - if (yych != 't') goto yy187; -yy518: - YYDEBUG(518, *YYCURSOR); + if (yych == 'T') goto yy471; + if (yych != 't') goto yy150; +yy471: + YYDEBUG(471, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy519; - if (yych != 'e') goto yy187; -yy519: - YYDEBUG(519, *YYCURSOR); + if (yych == 'E') goto yy472; + if (yych != 'e') goto yy150; +yy472: + YYDEBUG(472, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(520, *YYCURSOR); + YYDEBUG(473, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1305 "Zend/zend_language_scanner.l" +#line 1309 "Zend/zend_language_scanner.l" { return T_PRIVATE; } -#line 5306 "Zend/zend_language_scanner.c" -yy521: - YYDEBUG(521, *YYCURSOR); +#line 4917 "Zend/zend_language_scanner.c" +yy474: + YYDEBUG(474, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(522, *YYCURSOR); + YYDEBUG(475, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1143 "Zend/zend_language_scanner.l" { return T_PRINT; } -#line 5319 "Zend/zend_language_scanner.c" -yy523: - YYDEBUG(523, *YYCURSOR); +#line 4930 "Zend/zend_language_scanner.c" +yy476: + YYDEBUG(476, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'O') goto yy528; - if (yych == 'o') goto yy528; - goto yy187; -yy524: - YYDEBUG(524, *YYCURSOR); + if (yych == 'O') goto yy481; + if (yych == 'o') goto yy481; + goto yy150; +yy477: + YYDEBUG(477, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy525; - if (yych != 't') goto yy187; -yy525: - YYDEBUG(525, *YYCURSOR); + if (yych == 'T') goto yy478; + if (yych != 't') goto yy150; +yy478: + YYDEBUG(478, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'O') goto yy526; - if (yych != 'o') goto yy187; -yy526: - YYDEBUG(526, *YYCURSOR); + if (yych == 'O') goto yy479; + if (yych != 'o') goto yy150; +yy479: + YYDEBUG(479, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(527, *YYCURSOR); + YYDEBUG(480, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1135 "Zend/zend_language_scanner.l" { return T_GOTO; } -#line 5348 "Zend/zend_language_scanner.c" -yy528: - YYDEBUG(528, *YYCURSOR); +#line 4959 "Zend/zend_language_scanner.c" +yy481: + YYDEBUG(481, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'B') goto yy529; - if (yych != 'b') goto yy187; -yy529: - YYDEBUG(529, *YYCURSOR); + if (yych == 'B') goto yy482; + if (yych != 'b') goto yy150; +yy482: + YYDEBUG(482, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'A') goto yy530; - if (yych != 'a') goto yy187; -yy530: - YYDEBUG(530, *YYCURSOR); + if (yych == 'A') goto yy483; + if (yych != 'a') goto yy150; +yy483: + YYDEBUG(483, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'L') goto yy531; - if (yych != 'l') goto yy187; -yy531: - YYDEBUG(531, *YYCURSOR); + if (yych == 'L') goto yy484; + if (yych != 'l') goto yy150; +yy484: + YYDEBUG(484, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(532, *YYCURSOR); + YYDEBUG(485, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1277 "Zend/zend_language_scanner.l" +#line 1281 "Zend/zend_language_scanner.l" { return T_GLOBAL; } -#line 5376 "Zend/zend_language_scanner.c" -yy533: - YYDEBUG(533, *YYCURSOR); +#line 4987 "Zend/zend_language_scanner.c" +yy486: + YYDEBUG(486, *YYCURSOR); yych = *++YYCURSOR; - if (yych == '<') goto yy541; - goto yy194; -yy534: - YYDEBUG(534, *YYCURSOR); + if (yych == '<') goto yy494; + goto yy157; +yy487: + YYDEBUG(487, *YYCURSOR); yych = *++YYCURSOR; - goto yy181; -yy535: - YYDEBUG(535, *YYCURSOR); + goto yy144; +yy488: + YYDEBUG(488, *YYCURSOR); yych = *++YYCURSOR; - goto yy179; -yy536: - YYDEBUG(536, *YYCURSOR); + goto yy142; +yy489: + YYDEBUG(489, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy537; - if (yych != 'e') goto yy187; -yy537: - YYDEBUG(537, *YYCURSOR); + if (yych == 'E') goto yy490; + if (yych != 'e') goto yy150; +yy490: + YYDEBUG(490, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'A') goto yy538; - if (yych != 'a') goto yy187; -yy538: - YYDEBUG(538, *YYCURSOR); + if (yych == 'A') goto yy491; + if (yych != 'a') goto yy150; +yy491: + YYDEBUG(491, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'K') goto yy539; - if (yych != 'k') goto yy187; -yy539: - YYDEBUG(539, *YYCURSOR); + if (yych == 'K') goto yy492; + if (yych != 'k') goto yy150; +yy492: + YYDEBUG(492, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(540, *YYCURSOR); + YYDEBUG(493, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1127 "Zend/zend_language_scanner.l" { return T_BREAK; } -#line 5417 "Zend/zend_language_scanner.c" -yy541: - YYDEBUG(541, *YYCURSOR); +#line 5028 "Zend/zend_language_scanner.c" +yy494: + YYDEBUG(494, *YYCURSOR); yych = *++YYCURSOR; - if (yych == '<') goto yy270; - goto yy194; -yy542: - YYDEBUG(542, *YYCURSOR); + if (yych == '<') goto yy217; + goto yy157; +yy495: + YYDEBUG(495, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'A') goto yy549; - if (yych == 'a') goto yy549; - goto yy187; -yy543: - YYDEBUG(543, *YYCURSOR); + if (yych == 'A') goto yy502; + if (yych == 'a') goto yy502; + goto yy150; +yy496: + YYDEBUG(496, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'I') goto yy544; - if (yych != 'i') goto yy187; -yy544: - YYDEBUG(544, *YYCURSOR); + if (yych == 'I') goto yy497; + if (yych != 'i') goto yy150; +yy497: + YYDEBUG(497, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy545; - if (yych != 't') goto yy187; -yy545: - YYDEBUG(545, *YYCURSOR); + if (yych == 'T') goto yy498; + if (yych != 't') goto yy150; +yy498: + YYDEBUG(498, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'C') goto yy546; - if (yych != 'c') goto yy187; -yy546: - YYDEBUG(546, *YYCURSOR); + if (yych == 'C') goto yy499; + if (yych != 'c') goto yy150; +yy499: + YYDEBUG(499, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'H') goto yy547; - if (yych != 'h') goto yy187; -yy547: - YYDEBUG(547, *YYCURSOR); + if (yych == 'H') goto yy500; + if (yych != 'h') goto yy150; +yy500: + YYDEBUG(500, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(548, *YYCURSOR); + YYDEBUG(501, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1111 "Zend/zend_language_scanner.l" { return T_SWITCH; } -#line 5461 "Zend/zend_language_scanner.c" -yy549: - YYDEBUG(549, *YYCURSOR); +#line 5072 "Zend/zend_language_scanner.c" +yy502: + YYDEBUG(502, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy550; - if (yych != 't') goto yy187; -yy550: - YYDEBUG(550, *YYCURSOR); + if (yych == 'T') goto yy503; + if (yych != 't') goto yy150; +yy503: + YYDEBUG(503, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'I') goto yy551; - if (yych != 'i') goto yy187; -yy551: - YYDEBUG(551, *YYCURSOR); + if (yych == 'I') goto yy504; + if (yych != 'i') goto yy150; +yy504: + YYDEBUG(504, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'C') goto yy552; - if (yych != 'c') goto yy187; -yy552: - YYDEBUG(552, *YYCURSOR); + if (yych == 'C') goto yy505; + if (yych != 'c') goto yy150; +yy505: + YYDEBUG(505, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(553, *YYCURSOR); + YYDEBUG(506, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1293 "Zend/zend_language_scanner.l" +#line 1297 "Zend/zend_language_scanner.l" { return T_STATIC; } -#line 5489 "Zend/zend_language_scanner.c" -yy554: - YYDEBUG(554, *YYCURSOR); +#line 5100 "Zend/zend_language_scanner.c" +yy507: + YYDEBUG(507, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'S') goto yy565; - if (yych == 's') goto yy565; - goto yy187; -yy555: - YYDEBUG(555, *YYCURSOR); + if (yych == 'S') goto yy518; + if (yych == 's') goto yy518; + goto yy150; +yy508: + YYDEBUG(508, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'D') goto yy563; - if (yych == 'd') goto yy563; - goto yy187; -yy556: - YYDEBUG(556, *YYCURSOR); + if (yych == 'D') goto yy516; + if (yych == 'd') goto yy516; + goto yy150; +yy509: + YYDEBUG(509, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'R') goto yy559; - if (yych == 'r') goto yy559; - goto yy187; -yy557: - YYDEBUG(557, *YYCURSOR); + if (yych == 'R') goto yy512; + if (yych == 'r') goto yy512; + goto yy150; +yy510: + YYDEBUG(510, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(558, *YYCURSOR); + YYDEBUG(511, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1107 "Zend/zend_language_scanner.l" { return T_AS; } -#line 5520 "Zend/zend_language_scanner.c" -yy559: - YYDEBUG(559, *YYCURSOR); +#line 5131 "Zend/zend_language_scanner.c" +yy512: + YYDEBUG(512, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'A') goto yy560; - if (yych != 'a') goto yy187; -yy560: - YYDEBUG(560, *YYCURSOR); + if (yych == 'A') goto yy513; + if (yych != 'a') goto yy150; +yy513: + YYDEBUG(513, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'Y') goto yy561; - if (yych != 'y') goto yy187; -yy561: - YYDEBUG(561, *YYCURSOR); + if (yych == 'Y') goto yy514; + if (yych != 'y') goto yy150; +yy514: + YYDEBUG(514, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(562, *YYCURSOR); + YYDEBUG(515, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1329 "Zend/zend_language_scanner.l" +#line 1333 "Zend/zend_language_scanner.l" { return T_ARRAY; } -#line 5543 "Zend/zend_language_scanner.c" -yy563: - YYDEBUG(563, *YYCURSOR); +#line 5154 "Zend/zend_language_scanner.c" +yy516: + YYDEBUG(516, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(564, *YYCURSOR); + YYDEBUG(517, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1433 "Zend/zend_language_scanner.l" +#line 1437 "Zend/zend_language_scanner.l" { return T_LOGICAL_AND; } -#line 5556 "Zend/zend_language_scanner.c" -yy565: - YYDEBUG(565, *YYCURSOR); +#line 5167 "Zend/zend_language_scanner.c" +yy518: + YYDEBUG(518, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy566; - if (yych != 't') goto yy187; -yy566: - YYDEBUG(566, *YYCURSOR); + if (yych == 'T') goto yy519; + if (yych != 't') goto yy150; +yy519: + YYDEBUG(519, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'R') goto yy567; - if (yych != 'r') goto yy187; -yy567: - YYDEBUG(567, *YYCURSOR); + if (yych == 'R') goto yy520; + if (yych != 'r') goto yy150; +yy520: + YYDEBUG(520, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'A') goto yy568; - if (yych != 'a') goto yy187; -yy568: - YYDEBUG(568, *YYCURSOR); + if (yych == 'A') goto yy521; + if (yych != 'a') goto yy150; +yy521: + YYDEBUG(521, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'C') goto yy569; - if (yych != 'c') goto yy187; -yy569: - YYDEBUG(569, *YYCURSOR); + if (yych == 'C') goto yy522; + if (yych != 'c') goto yy150; +yy522: + YYDEBUG(522, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy570; - if (yych != 't') goto yy187; -yy570: - YYDEBUG(570, *YYCURSOR); + if (yych == 'T') goto yy523; + if (yych != 't') goto yy150; +yy523: + YYDEBUG(523, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(571, *YYCURSOR); + YYDEBUG(524, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1297 "Zend/zend_language_scanner.l" +#line 1301 "Zend/zend_language_scanner.l" { return T_ABSTRACT; } -#line 5594 "Zend/zend_language_scanner.c" -yy572: - YYDEBUG(572, *YYCURSOR); +#line 5205 "Zend/zend_language_scanner.c" +yy525: + YYDEBUG(525, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'I') goto yy573; - if (yych != 'i') goto yy187; -yy573: - YYDEBUG(573, *YYCURSOR); + if (yych == 'I') goto yy526; + if (yych != 'i') goto yy150; +yy526: + YYDEBUG(526, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'L') goto yy574; - if (yych != 'l') goto yy187; -yy574: - YYDEBUG(574, *YYCURSOR); + if (yych == 'L') goto yy527; + if (yych != 'l') goto yy150; +yy527: + YYDEBUG(527, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy575; - if (yych != 'e') goto yy187; -yy575: - YYDEBUG(575, *YYCURSOR); + if (yych == 'E') goto yy528; + if (yych != 'e') goto yy150; +yy528: + YYDEBUG(528, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(576, *YYCURSOR); + YYDEBUG(529, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1067 "Zend/zend_language_scanner.l" { return T_WHILE; } -#line 5622 "Zend/zend_language_scanner.c" -yy577: - YYDEBUG(577, *YYCURSOR); +#line 5233 "Zend/zend_language_scanner.c" +yy530: + YYDEBUG(530, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(578, *YYCURSOR); + YYDEBUG(531, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1051 "Zend/zend_language_scanner.l" { return T_IF; } -#line 5635 "Zend/zend_language_scanner.c" -yy579: - YYDEBUG(579, *YYCURSOR); +#line 5246 "Zend/zend_language_scanner.c" +yy532: + YYDEBUG(532, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'P') goto yy621; - if (yych == 'p') goto yy621; - goto yy187; -yy580: - YYDEBUG(580, *YYCURSOR); + if (yych == 'P') goto yy574; + if (yych == 'p') goto yy574; + goto yy150; +yy533: + YYDEBUG(533, *YYCURSOR); yych = *++YYCURSOR; if (yych <= 'T') { if (yych <= 'C') { - if (yych <= 'B') goto yy187; - goto yy588; + if (yych <= 'B') goto yy150; + goto yy541; } else { - if (yych <= 'R') goto yy187; - if (yych <= 'S') goto yy586; - goto yy587; + if (yych <= 'R') goto yy150; + if (yych <= 'S') goto yy539; + goto yy540; } } else { if (yych <= 'r') { - if (yych == 'c') goto yy588; - goto yy187; + if (yych == 'c') goto yy541; + goto yy150; } else { - if (yych <= 's') goto yy586; - if (yych <= 't') goto yy587; - goto yy187; + if (yych <= 's') goto yy539; + if (yych <= 't') goto yy540; + goto yy150; } } -yy581: - YYDEBUG(581, *YYCURSOR); +yy534: + YYDEBUG(534, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'S') goto yy582; - if (yych != 's') goto yy187; -yy582: - YYDEBUG(582, *YYCURSOR); + if (yych == 'S') goto yy535; + if (yych != 's') goto yy150; +yy535: + YYDEBUG(535, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy583; - if (yych != 'e') goto yy187; -yy583: - YYDEBUG(583, *YYCURSOR); + if (yych == 'E') goto yy536; + if (yych != 'e') goto yy150; +yy536: + YYDEBUG(536, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy584; - if (yych != 't') goto yy187; -yy584: - YYDEBUG(584, *YYCURSOR); + if (yych == 'T') goto yy537; + if (yych != 't') goto yy150; +yy537: + YYDEBUG(537, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(585, *YYCURSOR); + YYDEBUG(538, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1281 "Zend/zend_language_scanner.l" +#line 1285 "Zend/zend_language_scanner.l" { return T_ISSET; } -#line 5691 "Zend/zend_language_scanner.c" -yy586: - YYDEBUG(586, *YYCURSOR); +#line 5302 "Zend/zend_language_scanner.c" +yy539: + YYDEBUG(539, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy607; - if (yych == 't') goto yy607; - goto yy187; -yy587: - YYDEBUG(587, *YYCURSOR); + if (yych == 'T') goto yy560; + if (yych == 't') goto yy560; + goto yy150; +yy540: + YYDEBUG(540, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy600; - if (yych == 'e') goto yy600; - goto yy187; -yy588: - YYDEBUG(588, *YYCURSOR); + if (yych == 'E') goto yy553; + if (yych == 'e') goto yy553; + goto yy150; +yy541: + YYDEBUG(541, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'L') goto yy589; - if (yych != 'l') goto yy187; -yy589: - YYDEBUG(589, *YYCURSOR); + if (yych == 'L') goto yy542; + if (yych != 'l') goto yy150; +yy542: + YYDEBUG(542, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'U') goto yy590; - if (yych != 'u') goto yy187; -yy590: - YYDEBUG(590, *YYCURSOR); + if (yych == 'U') goto yy543; + if (yych != 'u') goto yy150; +yy543: + YYDEBUG(543, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'D') goto yy591; - if (yych != 'd') goto yy187; -yy591: - YYDEBUG(591, *YYCURSOR); + if (yych == 'D') goto yy544; + if (yych != 'd') goto yy150; +yy544: + YYDEBUG(544, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy592; - if (yych != 'e') goto yy187; -yy592: - YYDEBUG(592, *YYCURSOR); + if (yych == 'E') goto yy545; + if (yych != 'e') goto yy150; +yy545: + YYDEBUG(545, *YYCURSOR); ++YYCURSOR; if ((yych = *YYCURSOR) <= '^') { if (yych <= '9') { - if (yych >= '0') goto yy186; + if (yych >= '0') goto yy149; } else { - if (yych <= '@') goto yy593; - if (yych <= 'Z') goto yy186; + if (yych <= '@') goto yy546; + if (yych <= 'Z') goto yy149; } } else { if (yych <= '`') { - if (yych <= '_') goto yy594; + if (yych <= '_') goto yy547; } else { - if (yych <= 'z') goto yy186; - if (yych >= 0x7F) goto yy186; + if (yych <= 'z') goto yy149; + if (yych >= 0x7F) goto yy149; } } -yy593: - YYDEBUG(593, *YYCURSOR); +yy546: + YYDEBUG(546, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1249 "Zend/zend_language_scanner.l" +#line 1253 "Zend/zend_language_scanner.l" { return T_INCLUDE; } -#line 5749 "Zend/zend_language_scanner.c" -yy594: - YYDEBUG(594, *YYCURSOR); +#line 5360 "Zend/zend_language_scanner.c" +yy547: + YYDEBUG(547, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'O') goto yy595; - if (yych != 'o') goto yy187; -yy595: - YYDEBUG(595, *YYCURSOR); + if (yych == 'O') goto yy548; + if (yych != 'o') goto yy150; +yy548: + YYDEBUG(548, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'N') goto yy596; - if (yych != 'n') goto yy187; -yy596: - YYDEBUG(596, *YYCURSOR); + if (yych == 'N') goto yy549; + if (yych != 'n') goto yy150; +yy549: + YYDEBUG(549, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'C') goto yy597; - if (yych != 'c') goto yy187; -yy597: - YYDEBUG(597, *YYCURSOR); + if (yych == 'C') goto yy550; + if (yych != 'c') goto yy150; +yy550: + YYDEBUG(550, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy598; - if (yych != 'e') goto yy187; -yy598: - YYDEBUG(598, *YYCURSOR); + if (yych == 'E') goto yy551; + if (yych != 'e') goto yy150; +yy551: + YYDEBUG(551, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(599, *YYCURSOR); + YYDEBUG(552, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1253 "Zend/zend_language_scanner.l" +#line 1257 "Zend/zend_language_scanner.l" { return T_INCLUDE_ONCE; } -#line 5782 "Zend/zend_language_scanner.c" -yy600: - YYDEBUG(600, *YYCURSOR); +#line 5393 "Zend/zend_language_scanner.c" +yy553: + YYDEBUG(553, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'R') goto yy601; - if (yych != 'r') goto yy187; -yy601: - YYDEBUG(601, *YYCURSOR); + if (yych == 'R') goto yy554; + if (yych != 'r') goto yy150; +yy554: + YYDEBUG(554, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'F') goto yy602; - if (yych != 'f') goto yy187; -yy602: - YYDEBUG(602, *YYCURSOR); + if (yych == 'F') goto yy555; + if (yych != 'f') goto yy150; +yy555: + YYDEBUG(555, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'A') goto yy603; - if (yych != 'a') goto yy187; -yy603: - YYDEBUG(603, *YYCURSOR); + if (yych == 'A') goto yy556; + if (yych != 'a') goto yy150; +yy556: + YYDEBUG(556, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'C') goto yy604; - if (yych != 'c') goto yy187; -yy604: - YYDEBUG(604, *YYCURSOR); + if (yych == 'C') goto yy557; + if (yych != 'c') goto yy150; +yy557: + YYDEBUG(557, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy605; - if (yych != 'e') goto yy187; -yy605: - YYDEBUG(605, *YYCURSOR); + if (yych == 'E') goto yy558; + if (yych != 'e') goto yy150; +yy558: + YYDEBUG(558, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(606, *YYCURSOR); + YYDEBUG(559, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1151 "Zend/zend_language_scanner.l" { return T_INTERFACE; } -#line 5820 "Zend/zend_language_scanner.c" -yy607: - YYDEBUG(607, *YYCURSOR); +#line 5431 "Zend/zend_language_scanner.c" +yy560: + YYDEBUG(560, *YYCURSOR); yych = *++YYCURSOR; if (yych <= 'E') { - if (yych == 'A') goto yy608; - if (yych <= 'D') goto yy187; - goto yy609; + if (yych == 'A') goto yy561; + if (yych <= 'D') goto yy150; + goto yy562; } else { if (yych <= 'a') { - if (yych <= '`') goto yy187; + if (yych <= '`') goto yy150; } else { - if (yych == 'e') goto yy609; - goto yy187; + if (yych == 'e') goto yy562; + goto yy150; } } -yy608: - YYDEBUG(608, *YYCURSOR); +yy561: + YYDEBUG(561, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'N') goto yy615; - if (yych == 'n') goto yy615; - goto yy187; -yy609: - YYDEBUG(609, *YYCURSOR); + if (yych == 'N') goto yy568; + if (yych == 'n') goto yy568; + goto yy150; +yy562: + YYDEBUG(562, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'A') goto yy610; - if (yych != 'a') goto yy187; -yy610: - YYDEBUG(610, *YYCURSOR); + if (yych == 'A') goto yy563; + if (yych != 'a') goto yy150; +yy563: + YYDEBUG(563, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'D') goto yy611; - if (yych != 'd') goto yy187; -yy611: - YYDEBUG(611, *YYCURSOR); + if (yych == 'D') goto yy564; + if (yych != 'd') goto yy150; +yy564: + YYDEBUG(564, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'O') goto yy612; - if (yych != 'o') goto yy187; -yy612: - YYDEBUG(612, *YYCURSOR); + if (yych == 'O') goto yy565; + if (yych != 'o') goto yy150; +yy565: + YYDEBUG(565, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'F') goto yy613; - if (yych != 'f') goto yy187; -yy613: - YYDEBUG(613, *YYCURSOR); + if (yych == 'F') goto yy566; + if (yych != 'f') goto yy150; +yy566: + YYDEBUG(566, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(614, *YYCURSOR); + YYDEBUG(567, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1273 "Zend/zend_language_scanner.l" +#line 1277 "Zend/zend_language_scanner.l" { return T_INSTEADOF; } -#line 5874 "Zend/zend_language_scanner.c" -yy615: - YYDEBUG(615, *YYCURSOR); +#line 5485 "Zend/zend_language_scanner.c" +yy568: + YYDEBUG(568, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'C') goto yy616; - if (yych != 'c') goto yy187; -yy616: - YYDEBUG(616, *YYCURSOR); + if (yych == 'C') goto yy569; + if (yych != 'c') goto yy150; +yy569: + YYDEBUG(569, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy617; - if (yych != 'e') goto yy187; -yy617: - YYDEBUG(617, *YYCURSOR); + if (yych == 'E') goto yy570; + if (yych != 'e') goto yy150; +yy570: + YYDEBUG(570, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'O') goto yy618; - if (yych != 'o') goto yy187; -yy618: - YYDEBUG(618, *YYCURSOR); + if (yych == 'O') goto yy571; + if (yych != 'o') goto yy150; +yy571: + YYDEBUG(571, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'F') goto yy619; - if (yych != 'f') goto yy187; -yy619: - YYDEBUG(619, *YYCURSOR); + if (yych == 'F') goto yy572; + if (yych != 'f') goto yy150; +yy572: + YYDEBUG(572, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(620, *YYCURSOR); + YYDEBUG(573, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1103 "Zend/zend_language_scanner.l" { return T_INSTANCEOF; } -#line 5907 "Zend/zend_language_scanner.c" -yy621: - YYDEBUG(621, *YYCURSOR); +#line 5518 "Zend/zend_language_scanner.c" +yy574: + YYDEBUG(574, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'L') goto yy622; - if (yych != 'l') goto yy187; -yy622: - YYDEBUG(622, *YYCURSOR); + if (yych == 'L') goto yy575; + if (yych != 'l') goto yy150; +yy575: + YYDEBUG(575, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy623; - if (yych != 'e') goto yy187; -yy623: - YYDEBUG(623, *YYCURSOR); + if (yych == 'E') goto yy576; + if (yych != 'e') goto yy150; +yy576: + YYDEBUG(576, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'M') goto yy624; - if (yych != 'm') goto yy187; -yy624: - YYDEBUG(624, *YYCURSOR); + if (yych == 'M') goto yy577; + if (yych != 'm') goto yy150; +yy577: + YYDEBUG(577, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy625; - if (yych != 'e') goto yy187; -yy625: - YYDEBUG(625, *YYCURSOR); + if (yych == 'E') goto yy578; + if (yych != 'e') goto yy150; +yy578: + YYDEBUG(578, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'N') goto yy626; - if (yych != 'n') goto yy187; -yy626: - YYDEBUG(626, *YYCURSOR); + if (yych == 'N') goto yy579; + if (yych != 'n') goto yy150; +yy579: + YYDEBUG(579, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy627; - if (yych != 't') goto yy187; -yy627: - YYDEBUG(627, *YYCURSOR); + if (yych == 'T') goto yy580; + if (yych != 't') goto yy150; +yy580: + YYDEBUG(580, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'S') goto yy628; - if (yych != 's') goto yy187; -yy628: - YYDEBUG(628, *YYCURSOR); + if (yych == 'S') goto yy581; + if (yych != 's') goto yy150; +yy581: + YYDEBUG(581, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(629, *YYCURSOR); + YYDEBUG(582, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1163 "Zend/zend_language_scanner.l" { return T_IMPLEMENTS; } -#line 5955 "Zend/zend_language_scanner.c" -yy630: - YYDEBUG(630, *YYCURSOR); +#line 5566 "Zend/zend_language_scanner.c" +yy583: + YYDEBUG(583, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'R') goto yy638; - if (yych == 'r') goto yy638; - goto yy187; -yy631: - YYDEBUG(631, *YYCURSOR); + if (yych == 'R') goto yy591; + if (yych == 'r') goto yy591; + goto yy150; +yy584: + YYDEBUG(584, *YYCURSOR); yych = *++YYCURSOR; if (yych <= 'Y') { - if (yych == 'A') goto yy634; - if (yych <= 'X') goto yy187; + if (yych == 'A') goto yy587; + if (yych <= 'X') goto yy150; } else { if (yych <= 'a') { - if (yych <= '`') goto yy187; - goto yy634; + if (yych <= '`') goto yy150; + goto yy587; } else { - if (yych != 'y') goto yy187; + if (yych != 'y') goto yy150; } } - YYDEBUG(632, *YYCURSOR); + YYDEBUG(585, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(633, *YYCURSOR); + YYDEBUG(586, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1035 "Zend/zend_language_scanner.l" { return T_TRY; } -#line 5987 "Zend/zend_language_scanner.c" -yy634: - YYDEBUG(634, *YYCURSOR); +#line 5598 "Zend/zend_language_scanner.c" +yy587: + YYDEBUG(587, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'I') goto yy635; - if (yych != 'i') goto yy187; -yy635: - YYDEBUG(635, *YYCURSOR); + if (yych == 'I') goto yy588; + if (yych != 'i') goto yy150; +yy588: + YYDEBUG(588, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy636; - if (yych != 't') goto yy187; -yy636: - YYDEBUG(636, *YYCURSOR); + if (yych == 'T') goto yy589; + if (yych != 't') goto yy150; +yy589: + YYDEBUG(589, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(637, *YYCURSOR); + YYDEBUG(590, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1155 "Zend/zend_language_scanner.l" { return T_TRAIT; } -#line 6010 "Zend/zend_language_scanner.c" -yy638: - YYDEBUG(638, *YYCURSOR); +#line 5621 "Zend/zend_language_scanner.c" +yy591: + YYDEBUG(591, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'O') goto yy639; - if (yych != 'o') goto yy187; -yy639: - YYDEBUG(639, *YYCURSOR); + if (yych == 'O') goto yy592; + if (yych != 'o') goto yy150; +yy592: + YYDEBUG(592, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'W') goto yy640; - if (yych != 'w') goto yy187; -yy640: - YYDEBUG(640, *YYCURSOR); + if (yych == 'W') goto yy593; + if (yych != 'w') goto yy150; +yy593: + YYDEBUG(593, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(641, *YYCURSOR); + YYDEBUG(594, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1047 "Zend/zend_language_scanner.l" { return T_THROW; } -#line 6033 "Zend/zend_language_scanner.c" -yy642: - YYDEBUG(642, *YYCURSOR); +#line 5644 "Zend/zend_language_scanner.c" +yy595: + YYDEBUG(595, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy643; - if (yych != 'e') goto yy187; -yy643: - YYDEBUG(643, *YYCURSOR); + if (yych == 'E') goto yy596; + if (yych != 'e') goto yy150; +yy596: + YYDEBUG(596, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'L') goto yy644; - if (yych != 'l') goto yy187; -yy644: - YYDEBUG(644, *YYCURSOR); + if (yych == 'L') goto yy597; + if (yych != 'l') goto yy150; +yy597: + YYDEBUG(597, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'D') goto yy645; - if (yych != 'd') goto yy187; -yy645: - YYDEBUG(645, *YYCURSOR); + if (yych == 'D') goto yy598; + if (yych != 'd') goto yy150; +yy598: + YYDEBUG(598, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(646, *YYCURSOR); + YYDEBUG(599, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1031 "Zend/zend_language_scanner.l" { return T_YIELD; } -#line 6061 "Zend/zend_language_scanner.c" -yy647: - YYDEBUG(647, *YYCURSOR); +#line 5672 "Zend/zend_language_scanner.c" +yy600: + YYDEBUG(600, *YYCURSOR); yych = *++YYCURSOR; if (yych <= 'T') { - if (yych == 'Q') goto yy649; - if (yych <= 'S') goto yy187; + if (yych == 'Q') goto yy602; + if (yych <= 'S') goto yy150; } else { if (yych <= 'q') { - if (yych <= 'p') goto yy187; - goto yy649; + if (yych <= 'p') goto yy150; + goto yy602; } else { - if (yych != 't') goto yy187; + if (yych != 't') goto yy150; } } - YYDEBUG(648, *YYCURSOR); + YYDEBUG(601, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'U') goto yy661; - if (yych == 'u') goto yy661; - goto yy187; -yy649: - YYDEBUG(649, *YYCURSOR); + if (yych == 'U') goto yy614; + if (yych == 'u') goto yy614; + goto yy150; +yy602: + YYDEBUG(602, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'U') goto yy650; - if (yych != 'u') goto yy187; -yy650: - YYDEBUG(650, *YYCURSOR); + if (yych == 'U') goto yy603; + if (yych != 'u') goto yy150; +yy603: + YYDEBUG(603, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'I') goto yy651; - if (yych != 'i') goto yy187; -yy651: - YYDEBUG(651, *YYCURSOR); + if (yych == 'I') goto yy604; + if (yych != 'i') goto yy150; +yy604: + YYDEBUG(604, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'R') goto yy652; - if (yych != 'r') goto yy187; -yy652: - YYDEBUG(652, *YYCURSOR); + if (yych == 'R') goto yy605; + if (yych != 'r') goto yy150; +yy605: + YYDEBUG(605, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy653; - if (yych != 'e') goto yy187; -yy653: - YYDEBUG(653, *YYCURSOR); + if (yych == 'E') goto yy606; + if (yych != 'e') goto yy150; +yy606: + YYDEBUG(606, *YYCURSOR); ++YYCURSOR; if ((yych = *YYCURSOR) <= '^') { if (yych <= '9') { - if (yych >= '0') goto yy186; + if (yych >= '0') goto yy149; } else { - if (yych <= '@') goto yy654; - if (yych <= 'Z') goto yy186; + if (yych <= '@') goto yy607; + if (yych <= 'Z') goto yy149; } } else { if (yych <= '`') { - if (yych <= '_') goto yy655; + if (yych <= '_') goto yy608; } else { - if (yych <= 'z') goto yy186; - if (yych >= 0x7F) goto yy186; + if (yych <= 'z') goto yy149; + if (yych >= 0x7F) goto yy149; } } -yy654: - YYDEBUG(654, *YYCURSOR); +yy607: + YYDEBUG(607, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1257 "Zend/zend_language_scanner.l" +#line 1261 "Zend/zend_language_scanner.l" { return T_REQUIRE; } -#line 6126 "Zend/zend_language_scanner.c" -yy655: - YYDEBUG(655, *YYCURSOR); +#line 5737 "Zend/zend_language_scanner.c" +yy608: + YYDEBUG(608, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'O') goto yy656; - if (yych != 'o') goto yy187; -yy656: - YYDEBUG(656, *YYCURSOR); + if (yych == 'O') goto yy609; + if (yych != 'o') goto yy150; +yy609: + YYDEBUG(609, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'N') goto yy657; - if (yych != 'n') goto yy187; -yy657: - YYDEBUG(657, *YYCURSOR); + if (yych == 'N') goto yy610; + if (yych != 'n') goto yy150; +yy610: + YYDEBUG(610, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'C') goto yy658; - if (yych != 'c') goto yy187; -yy658: - YYDEBUG(658, *YYCURSOR); + if (yych == 'C') goto yy611; + if (yych != 'c') goto yy150; +yy611: + YYDEBUG(611, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy659; - if (yych != 'e') goto yy187; -yy659: - YYDEBUG(659, *YYCURSOR); + if (yych == 'E') goto yy612; + if (yych != 'e') goto yy150; +yy612: + YYDEBUG(612, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(660, *YYCURSOR); + YYDEBUG(613, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1261 "Zend/zend_language_scanner.l" +#line 1265 "Zend/zend_language_scanner.l" { return T_REQUIRE_ONCE; } -#line 6159 "Zend/zend_language_scanner.c" -yy661: - YYDEBUG(661, *YYCURSOR); +#line 5770 "Zend/zend_language_scanner.c" +yy614: + YYDEBUG(614, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'R') goto yy662; - if (yych != 'r') goto yy187; -yy662: - YYDEBUG(662, *YYCURSOR); + if (yych == 'R') goto yy615; + if (yych != 'r') goto yy150; +yy615: + YYDEBUG(615, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'N') goto yy663; - if (yych != 'n') goto yy187; -yy663: - YYDEBUG(663, *YYCURSOR); + if (yych == 'N') goto yy616; + if (yych != 'n') goto yy150; +yy616: + YYDEBUG(616, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(664, *YYCURSOR); + YYDEBUG(617, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1027 "Zend/zend_language_scanner.l" { return T_RETURN; } -#line 6182 "Zend/zend_language_scanner.c" -yy665: - YYDEBUG(665, *YYCURSOR); +#line 5793 "Zend/zend_language_scanner.c" +yy618: + YYDEBUG(618, *YYCURSOR); yych = *++YYCURSOR; if (yych <= 'T') { if (yych <= 'L') { - if (yych <= 'K') goto yy187; - goto yy688; + if (yych <= 'K') goto yy150; + goto yy641; } else { - if (yych <= 'R') goto yy187; - if (yych <= 'S') goto yy687; - goto yy686; + if (yych <= 'R') goto yy150; + if (yych <= 'S') goto yy640; + goto yy639; } } else { if (yych <= 'r') { - if (yych == 'l') goto yy688; - goto yy187; + if (yych == 'l') goto yy641; + goto yy150; } else { - if (yych <= 's') goto yy687; - if (yych <= 't') goto yy686; - goto yy187; + if (yych <= 's') goto yy640; + if (yych <= 't') goto yy639; + goto yy150; } } -yy666: - YYDEBUG(666, *YYCURSOR); +yy619: + YYDEBUG(619, *YYCURSOR); yych = *++YYCURSOR; if (yych <= 'O') { - if (yych == 'A') goto yy678; - if (yych <= 'N') goto yy187; - goto yy679; + if (yych == 'A') goto yy631; + if (yych <= 'N') goto yy150; + goto yy632; } else { if (yych <= 'a') { - if (yych <= '`') goto yy187; - goto yy678; + if (yych <= '`') goto yy150; + goto yy631; } else { - if (yych == 'o') goto yy679; - goto yy187; + if (yych == 'o') goto yy632; + goto yy150; } } -yy667: - YYDEBUG(667, *YYCURSOR); +yy620: + YYDEBUG(620, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'N') goto yy668; - if (yych != 'n') goto yy187; -yy668: - YYDEBUG(668, *YYCURSOR); + if (yych == 'N') goto yy621; + if (yych != 'n') goto yy150; +yy621: + YYDEBUG(621, *YYCURSOR); yych = *++YYCURSOR; if (yych <= 'T') { - if (yych <= 'R') goto yy187; - if (yych >= 'T') goto yy670; + if (yych <= 'R') goto yy150; + if (yych >= 'T') goto yy623; } else { - if (yych <= 'r') goto yy187; - if (yych <= 's') goto yy669; - if (yych <= 't') goto yy670; - goto yy187; + if (yych <= 'r') goto yy150; + if (yych <= 's') goto yy622; + if (yych <= 't') goto yy623; + goto yy150; } -yy669: - YYDEBUG(669, *YYCURSOR); +yy622: + YYDEBUG(622, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy676; - if (yych == 't') goto yy676; - goto yy187; -yy670: - YYDEBUG(670, *YYCURSOR); + if (yych == 'T') goto yy629; + if (yych == 't') goto yy629; + goto yy150; +yy623: + YYDEBUG(623, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'I') goto yy671; - if (yych != 'i') goto yy187; -yy671: - YYDEBUG(671, *YYCURSOR); + if (yych == 'I') goto yy624; + if (yych != 'i') goto yy150; +yy624: + YYDEBUG(624, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'N') goto yy672; - if (yych != 'n') goto yy187; -yy672: - YYDEBUG(672, *YYCURSOR); + if (yych == 'N') goto yy625; + if (yych != 'n') goto yy150; +yy625: + YYDEBUG(625, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'U') goto yy673; - if (yych != 'u') goto yy187; -yy673: - YYDEBUG(673, *YYCURSOR); + if (yych == 'U') goto yy626; + if (yych != 'u') goto yy150; +yy626: + YYDEBUG(626, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy674; - if (yych != 'e') goto yy187; -yy674: - YYDEBUG(674, *YYCURSOR); + if (yych == 'E') goto yy627; + if (yych != 'e') goto yy150; +yy627: + YYDEBUG(627, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(675, *YYCURSOR); + YYDEBUG(628, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1131 "Zend/zend_language_scanner.l" { return T_CONTINUE; } -#line 6276 "Zend/zend_language_scanner.c" -yy676: - YYDEBUG(676, *YYCURSOR); +#line 5887 "Zend/zend_language_scanner.c" +yy629: + YYDEBUG(629, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(677, *YYCURSOR); + YYDEBUG(630, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1023 "Zend/zend_language_scanner.l" { return T_CONST; } -#line 6289 "Zend/zend_language_scanner.c" -yy678: - YYDEBUG(678, *YYCURSOR); +#line 5900 "Zend/zend_language_scanner.c" +yy631: + YYDEBUG(631, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'S') goto yy683; - if (yych == 's') goto yy683; - goto yy187; -yy679: - YYDEBUG(679, *YYCURSOR); + if (yych == 'S') goto yy636; + if (yych == 's') goto yy636; + goto yy150; +yy632: + YYDEBUG(632, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'N') goto yy680; - if (yych != 'n') goto yy187; -yy680: - YYDEBUG(680, *YYCURSOR); + if (yych == 'N') goto yy633; + if (yych != 'n') goto yy150; +yy633: + YYDEBUG(633, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy681; - if (yych != 'e') goto yy187; -yy681: - YYDEBUG(681, *YYCURSOR); + if (yych == 'E') goto yy634; + if (yych != 'e') goto yy150; +yy634: + YYDEBUG(634, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(682, *YYCURSOR); + YYDEBUG(635, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1209 "Zend/zend_language_scanner.l" +#line 1213 "Zend/zend_language_scanner.l" { return T_CLONE; } -#line 6318 "Zend/zend_language_scanner.c" -yy683: - YYDEBUG(683, *YYCURSOR); +#line 5929 "Zend/zend_language_scanner.c" +yy636: + YYDEBUG(636, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'S') goto yy684; - if (yych != 's') goto yy187; -yy684: - YYDEBUG(684, *YYCURSOR); + if (yych == 'S') goto yy637; + if (yych != 's') goto yy150; +yy637: + YYDEBUG(637, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(685, *YYCURSOR); + YYDEBUG(638, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1147 "Zend/zend_language_scanner.l" { return T_CLASS; } -#line 6336 "Zend/zend_language_scanner.c" -yy686: - YYDEBUG(686, *YYCURSOR); +#line 5947 "Zend/zend_language_scanner.c" +yy639: + YYDEBUG(639, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'C') goto yy697; - if (yych == 'c') goto yy697; - goto yy187; -yy687: - YYDEBUG(687, *YYCURSOR); + if (yych == 'C') goto yy650; + if (yych == 'c') goto yy650; + goto yy150; +yy640: + YYDEBUG(640, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy695; - if (yych == 'e') goto yy695; - goto yy187; -yy688: - YYDEBUG(688, *YYCURSOR); + if (yych == 'E') goto yy648; + if (yych == 'e') goto yy648; + goto yy150; +yy641: + YYDEBUG(641, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'L') goto yy689; - if (yych != 'l') goto yy187; -yy689: - YYDEBUG(689, *YYCURSOR); + if (yych == 'L') goto yy642; + if (yych != 'l') goto yy150; +yy642: + YYDEBUG(642, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'A') goto yy690; - if (yych != 'a') goto yy187; -yy690: - YYDEBUG(690, *YYCURSOR); + if (yych == 'A') goto yy643; + if (yych != 'a') goto yy150; +yy643: + YYDEBUG(643, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'B') goto yy691; - if (yych != 'b') goto yy187; -yy691: - YYDEBUG(691, *YYCURSOR); + if (yych == 'B') goto yy644; + if (yych != 'b') goto yy150; +yy644: + YYDEBUG(644, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'L') goto yy692; - if (yych != 'l') goto yy187; -yy692: - YYDEBUG(692, *YYCURSOR); + if (yych == 'L') goto yy645; + if (yych != 'l') goto yy150; +yy645: + YYDEBUG(645, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy693; - if (yych != 'e') goto yy187; -yy693: - YYDEBUG(693, *YYCURSOR); + if (yych == 'E') goto yy646; + if (yych != 'e') goto yy150; +yy646: + YYDEBUG(646, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(694, *YYCURSOR); + YYDEBUG(647, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1333 "Zend/zend_language_scanner.l" +#line 1337 "Zend/zend_language_scanner.l" { return T_CALLABLE; } -#line 6386 "Zend/zend_language_scanner.c" -yy695: - YYDEBUG(695, *YYCURSOR); +#line 5997 "Zend/zend_language_scanner.c" +yy648: + YYDEBUG(648, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(696, *YYCURSOR); + YYDEBUG(649, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1119 "Zend/zend_language_scanner.l" { return T_CASE; } -#line 6399 "Zend/zend_language_scanner.c" -yy697: - YYDEBUG(697, *YYCURSOR); +#line 6010 "Zend/zend_language_scanner.c" +yy650: + YYDEBUG(650, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'H') goto yy698; - if (yych != 'h') goto yy187; -yy698: - YYDEBUG(698, *YYCURSOR); + if (yych == 'H') goto yy651; + if (yych != 'h') goto yy150; +yy651: + YYDEBUG(651, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(699, *YYCURSOR); + YYDEBUG(652, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1039 "Zend/zend_language_scanner.l" { return T_CATCH; } -#line 6417 "Zend/zend_language_scanner.c" -yy700: - YYDEBUG(700, *YYCURSOR); +#line 6028 "Zend/zend_language_scanner.c" +yy653: + YYDEBUG(653, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'N') goto yy717; - if (yych == 'n') goto yy717; - goto yy187; -yy701: - YYDEBUG(701, *YYCURSOR); + if (yych == 'N') goto yy670; + if (yych == 'n') goto yy670; + goto yy150; +yy654: + YYDEBUG(654, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'R') goto yy710; - if (yych == 'r') goto yy710; - goto yy187; -yy702: - YYDEBUG(702, *YYCURSOR); + if (yych == 'R') goto yy663; + if (yych == 'r') goto yy663; + goto yy150; +yy655: + YYDEBUG(655, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'N') goto yy703; - if (yych != 'n') goto yy187; -yy703: - YYDEBUG(703, *YYCURSOR); + if (yych == 'N') goto yy656; + if (yych != 'n') goto yy150; +yy656: + YYDEBUG(656, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'C') goto yy704; - if (yych != 'c') goto yy187; -yy704: - YYDEBUG(704, *YYCURSOR); + if (yych == 'C') goto yy657; + if (yych != 'c') goto yy150; +yy657: + YYDEBUG(657, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy705; - if (yych != 't') goto yy187; -yy705: - YYDEBUG(705, *YYCURSOR); + if (yych == 'T') goto yy658; + if (yych != 't') goto yy150; +yy658: + YYDEBUG(658, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'I') goto yy706; - if (yych != 'i') goto yy187; -yy706: - YYDEBUG(706, *YYCURSOR); + if (yych == 'I') goto yy659; + if (yych != 'i') goto yy150; +yy659: + YYDEBUG(659, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'O') goto yy707; - if (yych != 'o') goto yy187; -yy707: - YYDEBUG(707, *YYCURSOR); + if (yych == 'O') goto yy660; + if (yych != 'o') goto yy150; +yy660: + YYDEBUG(660, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'N') goto yy708; - if (yych != 'n') goto yy187; -yy708: - YYDEBUG(708, *YYCURSOR); + if (yych == 'N') goto yy661; + if (yych != 'n') goto yy150; +yy661: + YYDEBUG(661, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(709, *YYCURSOR); + YYDEBUG(662, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1019 "Zend/zend_language_scanner.l" { return T_FUNCTION; } -#line 6472 "Zend/zend_language_scanner.c" -yy710: - YYDEBUG(710, *YYCURSOR); +#line 6083 "Zend/zend_language_scanner.c" +yy663: + YYDEBUG(663, *YYCURSOR); ++YYCURSOR; if ((yych = *YYCURSOR) <= '^') { if (yych <= '@') { - if (yych <= '/') goto yy711; - if (yych <= '9') goto yy186; + if (yych <= '/') goto yy664; + if (yych <= '9') goto yy149; } else { - if (yych == 'E') goto yy712; - if (yych <= 'Z') goto yy186; + if (yych == 'E') goto yy665; + if (yych <= 'Z') goto yy149; } } else { if (yych <= 'd') { - if (yych != '`') goto yy186; + if (yych != '`') goto yy149; } else { - if (yych <= 'e') goto yy712; - if (yych <= 'z') goto yy186; - if (yych >= 0x7F) goto yy186; + if (yych <= 'e') goto yy665; + if (yych <= 'z') goto yy149; + if (yych >= 0x7F) goto yy149; } } -yy711: - YYDEBUG(711, *YYCURSOR); +yy664: + YYDEBUG(664, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1079 "Zend/zend_language_scanner.l" { return T_FOR; } -#line 6500 "Zend/zend_language_scanner.c" -yy712: - YYDEBUG(712, *YYCURSOR); +#line 6111 "Zend/zend_language_scanner.c" +yy665: + YYDEBUG(665, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'A') goto yy713; - if (yych != 'a') goto yy187; -yy713: - YYDEBUG(713, *YYCURSOR); + if (yych == 'A') goto yy666; + if (yych != 'a') goto yy150; +yy666: + YYDEBUG(666, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'C') goto yy714; - if (yych != 'c') goto yy187; -yy714: - YYDEBUG(714, *YYCURSOR); + if (yych == 'C') goto yy667; + if (yych != 'c') goto yy150; +yy667: + YYDEBUG(667, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'H') goto yy715; - if (yych != 'h') goto yy187; -yy715: - YYDEBUG(715, *YYCURSOR); + if (yych == 'H') goto yy668; + if (yych != 'h') goto yy150; +yy668: + YYDEBUG(668, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(716, *YYCURSOR); + YYDEBUG(669, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1087 "Zend/zend_language_scanner.l" { return T_FOREACH; } -#line 6528 "Zend/zend_language_scanner.c" -yy717: - YYDEBUG(717, *YYCURSOR); +#line 6139 "Zend/zend_language_scanner.c" +yy670: + YYDEBUG(670, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'A') goto yy718; - if (yych != 'a') goto yy187; -yy718: - YYDEBUG(718, *YYCURSOR); + if (yych == 'A') goto yy671; + if (yych != 'a') goto yy150; +yy671: + YYDEBUG(671, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'L') goto yy719; - if (yych != 'l') goto yy187; -yy719: - YYDEBUG(719, *YYCURSOR); + if (yych == 'L') goto yy672; + if (yych != 'l') goto yy150; +yy672: + YYDEBUG(672, *YYCURSOR); ++YYCURSOR; if ((yych = *YYCURSOR) <= '^') { if (yych <= '@') { - if (yych <= '/') goto yy720; - if (yych <= '9') goto yy186; + if (yych <= '/') goto yy673; + if (yych <= '9') goto yy149; } else { - if (yych == 'L') goto yy721; - if (yych <= 'Z') goto yy186; + if (yych == 'L') goto yy674; + if (yych <= 'Z') goto yy149; } } else { if (yych <= 'k') { - if (yych != '`') goto yy186; + if (yych != '`') goto yy149; } else { - if (yych <= 'l') goto yy721; - if (yych <= 'z') goto yy186; - if (yych >= 0x7F) goto yy186; + if (yych <= 'l') goto yy674; + if (yych <= 'z') goto yy149; + if (yych >= 0x7F) goto yy149; } } -yy720: - YYDEBUG(720, *YYCURSOR); +yy673: + YYDEBUG(673, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1301 "Zend/zend_language_scanner.l" +#line 1305 "Zend/zend_language_scanner.l" { return T_FINAL; } -#line 6566 "Zend/zend_language_scanner.c" -yy721: - YYDEBUG(721, *YYCURSOR); +#line 6177 "Zend/zend_language_scanner.c" +yy674: + YYDEBUG(674, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'Y') goto yy722; - if (yych != 'y') goto yy187; -yy722: - YYDEBUG(722, *YYCURSOR); + if (yych == 'Y') goto yy675; + if (yych != 'y') goto yy150; +yy675: + YYDEBUG(675, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(723, *YYCURSOR); + YYDEBUG(676, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1043 "Zend/zend_language_scanner.l" { return T_FINALLY; } -#line 6584 "Zend/zend_language_scanner.c" -yy724: - YYDEBUG(724, *YYCURSOR); +#line 6195 "Zend/zend_language_scanner.c" +yy677: + YYDEBUG(677, *YYCURSOR); yych = *++YYCURSOR; if (yych <= 'F') { - if (yych == 'C') goto yy730; - if (yych <= 'E') goto yy187; - goto yy731; + if (yych == 'C') goto yy683; + if (yych <= 'E') goto yy150; + goto yy684; } else { if (yych <= 'c') { - if (yych <= 'b') goto yy187; - goto yy730; + if (yych <= 'b') goto yy150; + goto yy683; } else { - if (yych == 'f') goto yy731; - goto yy187; + if (yych == 'f') goto yy684; + goto yy150; } } -yy725: - YYDEBUG(725, *YYCURSOR); +yy678: + YYDEBUG(678, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy728; - if (yych == 'e') goto yy728; - goto yy187; -yy726: - YYDEBUG(726, *YYCURSOR); + if (yych == 'E') goto yy681; + if (yych == 'e') goto yy681; + goto yy150; +yy679: + YYDEBUG(679, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(727, *YYCURSOR); + YYDEBUG(680, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1075 "Zend/zend_language_scanner.l" { return T_DO; } -#line 6619 "Zend/zend_language_scanner.c" -yy728: - YYDEBUG(728, *YYCURSOR); +#line 6230 "Zend/zend_language_scanner.c" +yy681: + YYDEBUG(681, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(729, *YYCURSOR); + YYDEBUG(682, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1015 "Zend/zend_language_scanner.l" { return T_EXIT; } -#line 6632 "Zend/zend_language_scanner.c" -yy730: - YYDEBUG(730, *YYCURSOR); +#line 6243 "Zend/zend_language_scanner.c" +yy683: + YYDEBUG(683, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'L') goto yy737; - if (yych == 'l') goto yy737; - goto yy187; -yy731: - YYDEBUG(731, *YYCURSOR); + if (yych == 'L') goto yy690; + if (yych == 'l') goto yy690; + goto yy150; +yy684: + YYDEBUG(684, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'A') goto yy732; - if (yych != 'a') goto yy187; -yy732: - YYDEBUG(732, *YYCURSOR); + if (yych == 'A') goto yy685; + if (yych != 'a') goto yy150; +yy685: + YYDEBUG(685, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'U') goto yy733; - if (yych != 'u') goto yy187; -yy733: - YYDEBUG(733, *YYCURSOR); + if (yych == 'U') goto yy686; + if (yych != 'u') goto yy150; +yy686: + YYDEBUG(686, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'L') goto yy734; - if (yych != 'l') goto yy187; -yy734: - YYDEBUG(734, *YYCURSOR); + if (yych == 'L') goto yy687; + if (yych != 'l') goto yy150; +yy687: + YYDEBUG(687, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy735; - if (yych != 't') goto yy187; -yy735: - YYDEBUG(735, *YYCURSOR); + if (yych == 'T') goto yy688; + if (yych != 't') goto yy150; +yy688: + YYDEBUG(688, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(736, *YYCURSOR); + YYDEBUG(689, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1123 "Zend/zend_language_scanner.l" { return T_DEFAULT; } -#line 6671 "Zend/zend_language_scanner.c" -yy737: - YYDEBUG(737, *YYCURSOR); +#line 6282 "Zend/zend_language_scanner.c" +yy690: + YYDEBUG(690, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'A') goto yy738; - if (yych != 'a') goto yy187; -yy738: - YYDEBUG(738, *YYCURSOR); + if (yych == 'A') goto yy691; + if (yych != 'a') goto yy150; +yy691: + YYDEBUG(691, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'R') goto yy739; - if (yych != 'r') goto yy187; -yy739: - YYDEBUG(739, *YYCURSOR); + if (yych == 'R') goto yy692; + if (yych != 'r') goto yy150; +yy692: + YYDEBUG(692, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy740; - if (yych != 'e') goto yy187; -yy740: - YYDEBUG(740, *YYCURSOR); + if (yych == 'E') goto yy693; + if (yych != 'e') goto yy150; +yy693: + YYDEBUG(693, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(741, *YYCURSOR); + YYDEBUG(694, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1095 "Zend/zend_language_scanner.l" { return T_DECLARE; } -#line 6699 "Zend/zend_language_scanner.c" -yy742: - YYDEBUG(742, *YYCURSOR); +#line 6310 "Zend/zend_language_scanner.c" +yy695: + YYDEBUG(695, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'H') goto yy804; - if (yych == 'h') goto yy804; - goto yy187; -yy743: - YYDEBUG(743, *YYCURSOR); + if (yych == 'H') goto yy757; + if (yych == 'h') goto yy757; + goto yy150; +yy696: + YYDEBUG(696, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'S') goto yy798; - if (yych == 's') goto yy798; - goto yy187; -yy744: - YYDEBUG(744, *YYCURSOR); + if (yych == 'S') goto yy751; + if (yych == 's') goto yy751; + goto yy150; +yy697: + YYDEBUG(697, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'P') goto yy794; - if (yych == 'p') goto yy794; - goto yy187; -yy745: - YYDEBUG(745, *YYCURSOR); + if (yych == 'P') goto yy747; + if (yych == 'p') goto yy747; + goto yy150; +yy698: + YYDEBUG(698, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'D') goto yy760; - if (yych == 'd') goto yy760; - goto yy187; -yy746: - YYDEBUG(746, *YYCURSOR); + if (yych == 'D') goto yy713; + if (yych == 'd') goto yy713; + goto yy150; +yy699: + YYDEBUG(699, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'A') goto yy757; - if (yych == 'a') goto yy757; - goto yy187; -yy747: - YYDEBUG(747, *YYCURSOR); + if (yych == 'A') goto yy710; + if (yych == 'a') goto yy710; + goto yy150; +yy700: + YYDEBUG(700, *YYCURSOR); yych = *++YYCURSOR; if (yych <= 'T') { - if (yych == 'I') goto yy748; - if (yych <= 'S') goto yy187; - goto yy749; + if (yych == 'I') goto yy701; + if (yych <= 'S') goto yy150; + goto yy702; } else { if (yych <= 'i') { - if (yych <= 'h') goto yy187; + if (yych <= 'h') goto yy150; } else { - if (yych == 't') goto yy749; - goto yy187; + if (yych == 't') goto yy702; + goto yy150; } } -yy748: - YYDEBUG(748, *YYCURSOR); +yy701: + YYDEBUG(701, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy755; - if (yych == 't') goto yy755; - goto yy187; -yy749: - YYDEBUG(749, *YYCURSOR); + if (yych == 'T') goto yy708; + if (yych == 't') goto yy708; + goto yy150; +yy702: + YYDEBUG(702, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy750; - if (yych != 'e') goto yy187; -yy750: - YYDEBUG(750, *YYCURSOR); + if (yych == 'E') goto yy703; + if (yych != 'e') goto yy150; +yy703: + YYDEBUG(703, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'N') goto yy751; - if (yych != 'n') goto yy187; -yy751: - YYDEBUG(751, *YYCURSOR); + if (yych == 'N') goto yy704; + if (yych != 'n') goto yy150; +yy704: + YYDEBUG(704, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'D') goto yy752; - if (yych != 'd') goto yy187; -yy752: - YYDEBUG(752, *YYCURSOR); + if (yych == 'D') goto yy705; + if (yych != 'd') goto yy150; +yy705: + YYDEBUG(705, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'S') goto yy753; - if (yych != 's') goto yy187; -yy753: - YYDEBUG(753, *YYCURSOR); + if (yych == 'S') goto yy706; + if (yych != 's') goto yy150; +yy706: + YYDEBUG(706, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(754, *YYCURSOR); + YYDEBUG(707, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1159 "Zend/zend_language_scanner.l" { return T_EXTENDS; } -#line 6783 "Zend/zend_language_scanner.c" -yy755: - YYDEBUG(755, *YYCURSOR); +#line 6394 "Zend/zend_language_scanner.c" +yy708: + YYDEBUG(708, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(756, *YYCURSOR); + YYDEBUG(709, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1011 "Zend/zend_language_scanner.l" { return T_EXIT; } -#line 6796 "Zend/zend_language_scanner.c" -yy757: - YYDEBUG(757, *YYCURSOR); +#line 6407 "Zend/zend_language_scanner.c" +yy710: + YYDEBUG(710, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'L') goto yy758; - if (yych != 'l') goto yy187; -yy758: - YYDEBUG(758, *YYCURSOR); + if (yych == 'L') goto yy711; + if (yych != 'l') goto yy150; +yy711: + YYDEBUG(711, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(759, *YYCURSOR); + YYDEBUG(712, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1245 "Zend/zend_language_scanner.l" +#line 1249 "Zend/zend_language_scanner.l" { return T_EVAL; } -#line 6814 "Zend/zend_language_scanner.c" -yy760: - YYDEBUG(760, *YYCURSOR); +#line 6425 "Zend/zend_language_scanner.c" +yy713: + YYDEBUG(713, *YYCURSOR); yych = *++YYCURSOR; YYDEBUG(-1, yych); switch (yych) { case 'D': - case 'd': goto yy761; + case 'd': goto yy714; case 'F': - case 'f': goto yy762; + case 'f': goto yy715; case 'I': - case 'i': goto yy763; + case 'i': goto yy716; case 'S': - case 's': goto yy764; + case 's': goto yy717; case 'W': - case 'w': goto yy765; - default: goto yy187; + case 'w': goto yy718; + default: goto yy150; } -yy761: - YYDEBUG(761, *YYCURSOR); +yy714: + YYDEBUG(714, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy787; - if (yych == 'e') goto yy787; - goto yy187; -yy762: - YYDEBUG(762, *YYCURSOR); + if (yych == 'E') goto yy740; + if (yych == 'e') goto yy740; + goto yy150; +yy715: + YYDEBUG(715, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'O') goto yy779; - if (yych == 'o') goto yy779; - goto yy187; -yy763: - YYDEBUG(763, *YYCURSOR); + if (yych == 'O') goto yy732; + if (yych == 'o') goto yy732; + goto yy150; +yy716: + YYDEBUG(716, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'F') goto yy777; - if (yych == 'f') goto yy777; - goto yy187; -yy764: - YYDEBUG(764, *YYCURSOR); + if (yych == 'F') goto yy730; + if (yych == 'f') goto yy730; + goto yy150; +yy717: + YYDEBUG(717, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'W') goto yy771; - if (yych == 'w') goto yy771; - goto yy187; -yy765: - YYDEBUG(765, *YYCURSOR); + if (yych == 'W') goto yy724; + if (yych == 'w') goto yy724; + goto yy150; +yy718: + YYDEBUG(718, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'H') goto yy766; - if (yych != 'h') goto yy187; -yy766: - YYDEBUG(766, *YYCURSOR); + if (yych == 'H') goto yy719; + if (yych != 'h') goto yy150; +yy719: + YYDEBUG(719, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'I') goto yy767; - if (yych != 'i') goto yy187; -yy767: - YYDEBUG(767, *YYCURSOR); + if (yych == 'I') goto yy720; + if (yych != 'i') goto yy150; +yy720: + YYDEBUG(720, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'L') goto yy768; - if (yych != 'l') goto yy187; -yy768: - YYDEBUG(768, *YYCURSOR); + if (yych == 'L') goto yy721; + if (yych != 'l') goto yy150; +yy721: + YYDEBUG(721, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy769; - if (yych != 'e') goto yy187; -yy769: - YYDEBUG(769, *YYCURSOR); + if (yych == 'E') goto yy722; + if (yych != 'e') goto yy150; +yy722: + YYDEBUG(722, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(770, *YYCURSOR); + YYDEBUG(723, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1071 "Zend/zend_language_scanner.l" { return T_ENDWHILE; } -#line 6888 "Zend/zend_language_scanner.c" -yy771: - YYDEBUG(771, *YYCURSOR); +#line 6499 "Zend/zend_language_scanner.c" +yy724: + YYDEBUG(724, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'I') goto yy772; - if (yych != 'i') goto yy187; -yy772: - YYDEBUG(772, *YYCURSOR); + if (yych == 'I') goto yy725; + if (yych != 'i') goto yy150; +yy725: + YYDEBUG(725, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy773; - if (yych != 't') goto yy187; -yy773: - YYDEBUG(773, *YYCURSOR); + if (yych == 'T') goto yy726; + if (yych != 't') goto yy150; +yy726: + YYDEBUG(726, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'C') goto yy774; - if (yych != 'c') goto yy187; -yy774: - YYDEBUG(774, *YYCURSOR); + if (yych == 'C') goto yy727; + if (yych != 'c') goto yy150; +yy727: + YYDEBUG(727, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'H') goto yy775; - if (yych != 'h') goto yy187; -yy775: - YYDEBUG(775, *YYCURSOR); + if (yych == 'H') goto yy728; + if (yych != 'h') goto yy150; +yy728: + YYDEBUG(728, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(776, *YYCURSOR); + YYDEBUG(729, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1115 "Zend/zend_language_scanner.l" { return T_ENDSWITCH; } -#line 6921 "Zend/zend_language_scanner.c" -yy777: - YYDEBUG(777, *YYCURSOR); +#line 6532 "Zend/zend_language_scanner.c" +yy730: + YYDEBUG(730, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(778, *YYCURSOR); + YYDEBUG(731, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1059 "Zend/zend_language_scanner.l" { return T_ENDIF; } -#line 6934 "Zend/zend_language_scanner.c" -yy779: - YYDEBUG(779, *YYCURSOR); +#line 6545 "Zend/zend_language_scanner.c" +yy732: + YYDEBUG(732, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'R') goto yy780; - if (yych != 'r') goto yy187; -yy780: - YYDEBUG(780, *YYCURSOR); + if (yych == 'R') goto yy733; + if (yych != 'r') goto yy150; +yy733: + YYDEBUG(733, *YYCURSOR); ++YYCURSOR; if ((yych = *YYCURSOR) <= '^') { if (yych <= '@') { - if (yych <= '/') goto yy781; - if (yych <= '9') goto yy186; + if (yych <= '/') goto yy734; + if (yych <= '9') goto yy149; } else { - if (yych == 'E') goto yy782; - if (yych <= 'Z') goto yy186; + if (yych == 'E') goto yy735; + if (yych <= 'Z') goto yy149; } } else { if (yych <= 'd') { - if (yych != '`') goto yy186; + if (yych != '`') goto yy149; } else { - if (yych <= 'e') goto yy782; - if (yych <= 'z') goto yy186; - if (yych >= 0x7F) goto yy186; + if (yych <= 'e') goto yy735; + if (yych <= 'z') goto yy149; + if (yych >= 0x7F) goto yy149; } } -yy781: - YYDEBUG(781, *YYCURSOR); +yy734: + YYDEBUG(734, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1083 "Zend/zend_language_scanner.l" { return T_ENDFOR; } -#line 6967 "Zend/zend_language_scanner.c" -yy782: - YYDEBUG(782, *YYCURSOR); +#line 6578 "Zend/zend_language_scanner.c" +yy735: + YYDEBUG(735, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'A') goto yy783; - if (yych != 'a') goto yy187; -yy783: - YYDEBUG(783, *YYCURSOR); + if (yych == 'A') goto yy736; + if (yych != 'a') goto yy150; +yy736: + YYDEBUG(736, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'C') goto yy784; - if (yych != 'c') goto yy187; -yy784: - YYDEBUG(784, *YYCURSOR); + if (yych == 'C') goto yy737; + if (yych != 'c') goto yy150; +yy737: + YYDEBUG(737, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'H') goto yy785; - if (yych != 'h') goto yy187; -yy785: - YYDEBUG(785, *YYCURSOR); + if (yych == 'H') goto yy738; + if (yych != 'h') goto yy150; +yy738: + YYDEBUG(738, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(786, *YYCURSOR); + YYDEBUG(739, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1091 "Zend/zend_language_scanner.l" { return T_ENDFOREACH; } -#line 6995 "Zend/zend_language_scanner.c" -yy787: - YYDEBUG(787, *YYCURSOR); +#line 6606 "Zend/zend_language_scanner.c" +yy740: + YYDEBUG(740, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'C') goto yy788; - if (yych != 'c') goto yy187; -yy788: - YYDEBUG(788, *YYCURSOR); + if (yych == 'C') goto yy741; + if (yych != 'c') goto yy150; +yy741: + YYDEBUG(741, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'L') goto yy789; - if (yych != 'l') goto yy187; -yy789: - YYDEBUG(789, *YYCURSOR); + if (yych == 'L') goto yy742; + if (yych != 'l') goto yy150; +yy742: + YYDEBUG(742, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'A') goto yy790; - if (yych != 'a') goto yy187; -yy790: - YYDEBUG(790, *YYCURSOR); + if (yych == 'A') goto yy743; + if (yych != 'a') goto yy150; +yy743: + YYDEBUG(743, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'R') goto yy791; - if (yych != 'r') goto yy187; -yy791: - YYDEBUG(791, *YYCURSOR); + if (yych == 'R') goto yy744; + if (yych != 'r') goto yy150; +yy744: + YYDEBUG(744, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy792; - if (yych != 'e') goto yy187; -yy792: - YYDEBUG(792, *YYCURSOR); + if (yych == 'E') goto yy745; + if (yych != 'e') goto yy150; +yy745: + YYDEBUG(745, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(793, *YYCURSOR); + YYDEBUG(746, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1099 "Zend/zend_language_scanner.l" { return T_ENDDECLARE; } -#line 7033 "Zend/zend_language_scanner.c" -yy794: - YYDEBUG(794, *YYCURSOR); +#line 6644 "Zend/zend_language_scanner.c" +yy747: + YYDEBUG(747, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy795; - if (yych != 't') goto yy187; -yy795: - YYDEBUG(795, *YYCURSOR); + if (yych == 'T') goto yy748; + if (yych != 't') goto yy150; +yy748: + YYDEBUG(748, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'Y') goto yy796; - if (yych != 'y') goto yy187; -yy796: - YYDEBUG(796, *YYCURSOR); + if (yych == 'Y') goto yy749; + if (yych != 'y') goto yy150; +yy749: + YYDEBUG(749, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(797, *YYCURSOR); + YYDEBUG(750, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1285 "Zend/zend_language_scanner.l" +#line 1289 "Zend/zend_language_scanner.l" { return T_EMPTY; } -#line 7056 "Zend/zend_language_scanner.c" -yy798: - YYDEBUG(798, *YYCURSOR); +#line 6667 "Zend/zend_language_scanner.c" +yy751: + YYDEBUG(751, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy799; - if (yych != 'e') goto yy187; -yy799: - YYDEBUG(799, *YYCURSOR); + if (yych == 'E') goto yy752; + if (yych != 'e') goto yy150; +yy752: + YYDEBUG(752, *YYCURSOR); ++YYCURSOR; if ((yych = *YYCURSOR) <= '^') { if (yych <= '@') { - if (yych <= '/') goto yy800; - if (yych <= '9') goto yy186; + if (yych <= '/') goto yy753; + if (yych <= '9') goto yy149; } else { - if (yych == 'I') goto yy801; - if (yych <= 'Z') goto yy186; + if (yych == 'I') goto yy754; + if (yych <= 'Z') goto yy149; } } else { if (yych <= 'h') { - if (yych != '`') goto yy186; + if (yych != '`') goto yy149; } else { - if (yych <= 'i') goto yy801; - if (yych <= 'z') goto yy186; - if (yych >= 0x7F) goto yy186; + if (yych <= 'i') goto yy754; + if (yych <= 'z') goto yy149; + if (yych >= 0x7F) goto yy149; } } -yy800: - YYDEBUG(800, *YYCURSOR); +yy753: + YYDEBUG(753, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1063 "Zend/zend_language_scanner.l" { return T_ELSE; } -#line 7089 "Zend/zend_language_scanner.c" -yy801: - YYDEBUG(801, *YYCURSOR); +#line 6700 "Zend/zend_language_scanner.c" +yy754: + YYDEBUG(754, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'F') goto yy802; - if (yych != 'f') goto yy187; -yy802: - YYDEBUG(802, *YYCURSOR); + if (yych == 'F') goto yy755; + if (yych != 'f') goto yy150; +yy755: + YYDEBUG(755, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(803, *YYCURSOR); + YYDEBUG(756, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1055 "Zend/zend_language_scanner.l" { return T_ELSEIF; } -#line 7107 "Zend/zend_language_scanner.c" -yy804: - YYDEBUG(804, *YYCURSOR); +#line 6718 "Zend/zend_language_scanner.c" +yy757: + YYDEBUG(757, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'O') goto yy805; - if (yych != 'o') goto yy187; -yy805: - YYDEBUG(805, *YYCURSOR); + if (yych == 'O') goto yy758; + if (yych != 'o') goto yy150; +yy758: + YYDEBUG(758, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy186; + goto yy149; } - YYDEBUG(806, *YYCURSOR); + YYDEBUG(759, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1139 "Zend/zend_language_scanner.l" { return T_ECHO; } -#line 7125 "Zend/zend_language_scanner.c" +#line 6736 "Zend/zend_language_scanner.c" } /* *********************************** */ yyc_ST_LOOKING_FOR_PROPERTY: @@ -7160,52 +6771,52 @@ yyc_ST_LOOKING_FOR_PROPERTY: 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, }; - YYDEBUG(807, *YYCURSOR); + YYDEBUG(760, *YYCURSOR); YYFILL(2); yych = *YYCURSOR; if (yych <= '-') { if (yych <= '\r') { - if (yych <= 0x08) goto yy815; - if (yych <= '\n') goto yy809; - if (yych <= '\f') goto yy815; + if (yych <= 0x08) goto yy768; + if (yych <= '\n') goto yy762; + if (yych <= '\f') goto yy768; } else { - if (yych == ' ') goto yy809; - if (yych <= ',') goto yy815; - goto yy811; + if (yych == ' ') goto yy762; + if (yych <= ',') goto yy768; + goto yy764; } } else { if (yych <= '_') { - if (yych <= '@') goto yy815; - if (yych <= 'Z') goto yy813; - if (yych <= '^') goto yy815; - goto yy813; + if (yych <= '@') goto yy768; + if (yych <= 'Z') goto yy766; + if (yych <= '^') goto yy768; + goto yy766; } else { - if (yych <= '`') goto yy815; - if (yych <= 'z') goto yy813; - if (yych <= '~') goto yy815; - goto yy813; + if (yych <= '`') goto yy768; + if (yych <= 'z') goto yy766; + if (yych <= '~') goto yy768; + goto yy766; } } -yy809: - YYDEBUG(809, *YYCURSOR); +yy762: + YYDEBUG(762, *YYCURSOR); ++YYCURSOR; yych = *YYCURSOR; - goto yy821; -yy810: - YYDEBUG(810, *YYCURSOR); + goto yy774; +yy763: + YYDEBUG(763, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1172 "Zend/zend_language_scanner.l" { HANDLE_NEWLINES(yytext, yyleng); return T_WHITESPACE; } -#line 7203 "Zend/zend_language_scanner.c" -yy811: - YYDEBUG(811, *YYCURSOR); +#line 6814 "Zend/zend_language_scanner.c" +yy764: + YYDEBUG(764, *YYCURSOR); ++YYCURSOR; - if ((yych = *YYCURSOR) == '>') goto yy818; -yy812: - YYDEBUG(812, *YYCURSOR); + if ((yych = *YYCURSOR) == '>') goto yy771; +yy765: + YYDEBUG(765, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1187 "Zend/zend_language_scanner.l" { @@ -7213,14 +6824,14 @@ yy812: yy_pop_state(TSRMLS_C); goto restart; } -#line 7217 "Zend/zend_language_scanner.c" -yy813: - YYDEBUG(813, *YYCURSOR); +#line 6828 "Zend/zend_language_scanner.c" +yy766: + YYDEBUG(766, *YYCURSOR); ++YYCURSOR; yych = *YYCURSOR; - goto yy817; -yy814: - YYDEBUG(814, *YYCURSOR); + goto yy770; +yy767: + YYDEBUG(767, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1181 "Zend/zend_language_scanner.l" { @@ -7228,43 +6839,43 @@ yy814: zend_copy_value(zendlval, yytext, yyleng); return T_STRING; } -#line 7232 "Zend/zend_language_scanner.c" -yy815: - YYDEBUG(815, *YYCURSOR); +#line 6843 "Zend/zend_language_scanner.c" +yy768: + YYDEBUG(768, *YYCURSOR); yych = *++YYCURSOR; - goto yy812; -yy816: - YYDEBUG(816, *YYCURSOR); + goto yy765; +yy769: + YYDEBUG(769, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; -yy817: - YYDEBUG(817, *YYCURSOR); +yy770: + YYDEBUG(770, *YYCURSOR); if (yybm[0+yych] & 64) { - goto yy816; + goto yy769; } - goto yy814; -yy818: - YYDEBUG(818, *YYCURSOR); + goto yy767; +yy771: + YYDEBUG(771, *YYCURSOR); ++YYCURSOR; - YYDEBUG(819, *YYCURSOR); + YYDEBUG(772, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); #line 1177 "Zend/zend_language_scanner.l" { return T_OBJECT_OPERATOR; } -#line 7257 "Zend/zend_language_scanner.c" -yy820: - YYDEBUG(820, *YYCURSOR); +#line 6868 "Zend/zend_language_scanner.c" +yy773: + YYDEBUG(773, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; -yy821: - YYDEBUG(821, *YYCURSOR); +yy774: + YYDEBUG(774, *YYCURSOR); if (yybm[0+yych] & 128) { - goto yy820; + goto yy773; } - goto yy810; + goto yy763; } /* *********************************** */ yyc_ST_LOOKING_FOR_VARNAME: @@ -7303,74 +6914,74 @@ yyc_ST_LOOKING_FOR_VARNAME: 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, }; - YYDEBUG(822, *YYCURSOR); + YYDEBUG(775, *YYCURSOR); YYFILL(2); yych = *YYCURSOR; if (yych <= '_') { - if (yych <= '@') goto yy826; - if (yych <= 'Z') goto yy824; - if (yych <= '^') goto yy826; + if (yych <= '@') goto yy779; + if (yych <= 'Z') goto yy777; + if (yych <= '^') goto yy779; } else { - if (yych <= '`') goto yy826; - if (yych <= 'z') goto yy824; - if (yych <= '~') goto yy826; + if (yych <= '`') goto yy779; + if (yych <= 'z') goto yy777; + if (yych <= '~') goto yy779; } -yy824: - YYDEBUG(824, *YYCURSOR); +yy777: + YYDEBUG(777, *YYCURSOR); yyaccept = 0; yych = *(YYMARKER = ++YYCURSOR); if (yych <= '_') { if (yych <= '@') { - if (yych <= '/') goto yy825; - if (yych <= '9') goto yy828; + if (yych <= '/') goto yy778; + if (yych <= '9') goto yy781; } else { - if (yych <= '[') goto yy828; - if (yych >= '_') goto yy828; + if (yych <= '[') goto yy781; + if (yych >= '_') goto yy781; } } else { if (yych <= '|') { - if (yych <= '`') goto yy825; - if (yych <= 'z') goto yy828; + if (yych <= '`') goto yy778; + if (yych <= 'z') goto yy781; } else { - if (yych != '~') goto yy828; + if (yych != '~') goto yy781; } } -yy825: - YYDEBUG(825, *YYCURSOR); +yy778: + YYDEBUG(778, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1484 "Zend/zend_language_scanner.l" +#line 1488 "Zend/zend_language_scanner.l" { yyless(0); yy_pop_state(TSRMLS_C); yy_push_state(ST_IN_SCRIPTING TSRMLS_CC); goto restart; } -#line 7349 "Zend/zend_language_scanner.c" -yy826: - YYDEBUG(826, *YYCURSOR); +#line 6960 "Zend/zend_language_scanner.c" +yy779: + YYDEBUG(779, *YYCURSOR); yych = *++YYCURSOR; - goto yy825; -yy827: - YYDEBUG(827, *YYCURSOR); + goto yy778; +yy780: + YYDEBUG(780, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; -yy828: - YYDEBUG(828, *YYCURSOR); +yy781: + YYDEBUG(781, *YYCURSOR); if (yybm[0+yych] & 128) { - goto yy827; + goto yy780; } - if (yych == '[') goto yy830; - if (yych == '}') goto yy830; - YYDEBUG(829, *YYCURSOR); + if (yych == '[') goto yy783; + if (yych == '}') goto yy783; + YYDEBUG(782, *YYCURSOR); YYCURSOR = YYMARKER; - goto yy825; -yy830: - YYDEBUG(830, *YYCURSOR); + goto yy778; +yy783: + YYDEBUG(783, *YYCURSOR); ++YYCURSOR; - YYDEBUG(831, *YYCURSOR); + YYDEBUG(784, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1475 "Zend/zend_language_scanner.l" +#line 1479 "Zend/zend_language_scanner.l" { yyless(yyleng - 1); zend_copy_value(zendlval, yytext, yyleng); @@ -7378,18 +6989,18 @@ yy830: yy_push_state(ST_IN_SCRIPTING TSRMLS_CC); return T_STRING_VARNAME; } -#line 7382 "Zend/zend_language_scanner.c" +#line 6993 "Zend/zend_language_scanner.c" } /* *********************************** */ yyc_ST_NOWDOC: - YYDEBUG(832, *YYCURSOR); + YYDEBUG(785, *YYCURSOR); YYFILL(1); yych = *YYCURSOR; - YYDEBUG(834, *YYCURSOR); + YYDEBUG(787, *YYCURSOR); ++YYCURSOR; - YYDEBUG(835, *YYCURSOR); + YYDEBUG(788, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2222 "Zend/zend_language_scanner.l" +#line 2160 "Zend/zend_language_scanner.l" { int newline = 0; @@ -7445,7 +7056,7 @@ nowdoc_scan_done: HANDLE_NEWLINES(yytext, yyleng - newline); return T_ENCAPSED_AND_WHITESPACE; } -#line 7449 "Zend/zend_language_scanner.c" +#line 7060 "Zend/zend_language_scanner.c" /* *********************************** */ yyc_ST_VAR_OFFSET: { @@ -7483,76 +7094,76 @@ yyc_ST_VAR_OFFSET: 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, }; - YYDEBUG(836, *YYCURSOR); + YYDEBUG(789, *YYCURSOR); YYFILL(3); yych = *YYCURSOR; if (yych <= '/') { if (yych <= ' ') { if (yych <= '\f') { - if (yych <= 0x08) goto yy850; - if (yych <= '\n') goto yy846; - goto yy850; + if (yych <= 0x08) goto yy803; + if (yych <= '\n') goto yy799; + goto yy803; } else { - if (yych <= '\r') goto yy846; - if (yych <= 0x1F) goto yy850; - goto yy846; + if (yych <= '\r') goto yy799; + if (yych <= 0x1F) goto yy803; + goto yy799; } } else { if (yych <= '$') { - if (yych <= '"') goto yy845; - if (yych <= '#') goto yy846; - goto yy841; + if (yych <= '"') goto yy798; + if (yych <= '#') goto yy799; + goto yy794; } else { - if (yych == '\'') goto yy846; - goto yy845; + if (yych == '\'') goto yy799; + goto yy798; } } } else { if (yych <= '\\') { if (yych <= '@') { - if (yych <= '0') goto yy838; - if (yych <= '9') goto yy840; - goto yy845; + if (yych <= '0') goto yy791; + if (yych <= '9') goto yy793; + goto yy798; } else { - if (yych <= 'Z') goto yy848; - if (yych <= '[') goto yy845; - goto yy846; + if (yych <= 'Z') goto yy801; + if (yych <= '[') goto yy798; + goto yy799; } } else { if (yych <= '_') { - if (yych <= ']') goto yy843; - if (yych <= '^') goto yy845; - goto yy848; + if (yych <= ']') goto yy796; + if (yych <= '^') goto yy798; + goto yy801; } else { - if (yych <= '`') goto yy845; - if (yych <= 'z') goto yy848; - if (yych <= '~') goto yy845; - goto yy848; + if (yych <= '`') goto yy798; + if (yych <= 'z') goto yy801; + if (yych <= '~') goto yy798; + goto yy801; } } } -yy838: - YYDEBUG(838, *YYCURSOR); +yy791: + YYDEBUG(791, *YYCURSOR); yyaccept = 0; yych = *(YYMARKER = ++YYCURSOR); if (yych <= 'W') { if (yych <= '9') { - if (yych >= '0') goto yy862; + if (yych >= '0') goto yy815; } else { - if (yych == 'B') goto yy859; + if (yych == 'B') goto yy812; } } else { if (yych <= 'b') { - if (yych <= 'X') goto yy861; - if (yych >= 'b') goto yy859; + if (yych <= 'X') goto yy814; + if (yych >= 'b') goto yy812; } else { - if (yych == 'x') goto yy861; + if (yych == 'x') goto yy814; } } -yy839: - YYDEBUG(839, *YYCURSOR); +yy792: + YYDEBUG(792, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1555 "Zend/zend_language_scanner.l" +#line 1559 "Zend/zend_language_scanner.l" { /* Offset could be treated as a long */ if (yyleng < MAX_LENGTH_OF_LONG - 1 || (yyleng == MAX_LENGTH_OF_LONG - 1 && strcmp(yytext, long_min_digits) < 0)) { ZVAL_LONG(zendlval, ZEND_STRTOL(yytext, NULL, 10)); @@ -7561,53 +7172,53 @@ yy839: } return T_NUM_STRING; } -#line 7565 "Zend/zend_language_scanner.c" -yy840: - YYDEBUG(840, *YYCURSOR); +#line 7176 "Zend/zend_language_scanner.c" +yy793: + YYDEBUG(793, *YYCURSOR); yych = *++YYCURSOR; - goto yy858; -yy841: - YYDEBUG(841, *YYCURSOR); + goto yy811; +yy794: + YYDEBUG(794, *YYCURSOR); ++YYCURSOR; if ((yych = *YYCURSOR) <= '_') { - if (yych <= '@') goto yy842; - if (yych <= 'Z') goto yy854; - if (yych >= '_') goto yy854; + if (yych <= '@') goto yy795; + if (yych <= 'Z') goto yy807; + if (yych >= '_') goto yy807; } else { - if (yych <= '`') goto yy842; - if (yych <= 'z') goto yy854; - if (yych >= 0x7F) goto yy854; + if (yych <= '`') goto yy795; + if (yych <= 'z') goto yy807; + if (yych >= 0x7F) goto yy807; } -yy842: - YYDEBUG(842, *YYCURSOR); +yy795: + YYDEBUG(795, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1754 "Zend/zend_language_scanner.l" +#line 1708 "Zend/zend_language_scanner.l" { /* Only '[' can be valid, but returning other tokens will allow a more explicit parse error */ return yytext[0]; } -#line 7590 "Zend/zend_language_scanner.c" -yy843: - YYDEBUG(843, *YYCURSOR); +#line 7201 "Zend/zend_language_scanner.c" +yy796: + YYDEBUG(796, *YYCURSOR); ++YYCURSOR; - YYDEBUG(844, *YYCURSOR); + YYDEBUG(797, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1749 "Zend/zend_language_scanner.l" +#line 1703 "Zend/zend_language_scanner.l" { yy_pop_state(TSRMLS_C); return ']'; } -#line 7601 "Zend/zend_language_scanner.c" -yy845: - YYDEBUG(845, *YYCURSOR); +#line 7212 "Zend/zend_language_scanner.c" +yy798: + YYDEBUG(798, *YYCURSOR); yych = *++YYCURSOR; - goto yy842; -yy846: - YYDEBUG(846, *YYCURSOR); + goto yy795; +yy799: + YYDEBUG(799, *YYCURSOR); ++YYCURSOR; - YYDEBUG(847, *YYCURSOR); + YYDEBUG(800, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1759 "Zend/zend_language_scanner.l" +#line 1713 "Zend/zend_language_scanner.l" { /* Invalid rule to return a more explicit parse error with proper line number */ yyless(0); @@ -7615,27 +7226,27 @@ yy846: ZVAL_NULL(zendlval); return T_ENCAPSED_AND_WHITESPACE; } -#line 7619 "Zend/zend_language_scanner.c" -yy848: - YYDEBUG(848, *YYCURSOR); +#line 7230 "Zend/zend_language_scanner.c" +yy801: + YYDEBUG(801, *YYCURSOR); ++YYCURSOR; yych = *YYCURSOR; - goto yy853; -yy849: - YYDEBUG(849, *YYCURSOR); + goto yy806; +yy802: + YYDEBUG(802, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1767 "Zend/zend_language_scanner.l" +#line 1721 "Zend/zend_language_scanner.l" { zend_copy_value(zendlval, yytext, yyleng); return T_STRING; } -#line 7633 "Zend/zend_language_scanner.c" -yy850: - YYDEBUG(850, *YYCURSOR); +#line 7244 "Zend/zend_language_scanner.c" +yy803: + YYDEBUG(803, *YYCURSOR); ++YYCURSOR; - YYDEBUG(851, *YYCURSOR); + YYDEBUG(804, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2279 "Zend/zend_language_scanner.l" +#line 2217 "Zend/zend_language_scanner.l" { if (YYCURSOR > YYLIMIT) { return 0; @@ -7644,115 +7255,115 @@ yy850: zend_error(E_COMPILE_WARNING,"Unexpected character in input: '%c' (ASCII=%d) state=%d", yytext[0], yytext[0], YYSTATE); goto restart; } -#line 7648 "Zend/zend_language_scanner.c" -yy852: - YYDEBUG(852, *YYCURSOR); +#line 7259 "Zend/zend_language_scanner.c" +yy805: + YYDEBUG(805, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; -yy853: - YYDEBUG(853, *YYCURSOR); +yy806: + YYDEBUG(806, *YYCURSOR); if (yybm[0+yych] & 16) { - goto yy852; + goto yy805; } - goto yy849; -yy854: - YYDEBUG(854, *YYCURSOR); + goto yy802; +yy807: + YYDEBUG(807, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; - YYDEBUG(855, *YYCURSOR); + YYDEBUG(808, *YYCURSOR); if (yych <= '^') { if (yych <= '9') { - if (yych >= '0') goto yy854; + if (yych >= '0') goto yy807; } else { - if (yych <= '@') goto yy856; - if (yych <= 'Z') goto yy854; + if (yych <= '@') goto yy809; + if (yych <= 'Z') goto yy807; } } else { if (yych <= '`') { - if (yych <= '_') goto yy854; + if (yych <= '_') goto yy807; } else { - if (yych <= 'z') goto yy854; - if (yych >= 0x7F) goto yy854; + if (yych <= 'z') goto yy807; + if (yych >= 0x7F) goto yy807; } } -yy856: - YYDEBUG(856, *YYCURSOR); +yy809: + YYDEBUG(809, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1744 "Zend/zend_language_scanner.l" +#line 1698 "Zend/zend_language_scanner.l" { zend_copy_value(zendlval, (yytext+1), (yyleng-1)); return T_VARIABLE; } -#line 7689 "Zend/zend_language_scanner.c" -yy857: - YYDEBUG(857, *YYCURSOR); +#line 7300 "Zend/zend_language_scanner.c" +yy810: + YYDEBUG(810, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; -yy858: - YYDEBUG(858, *YYCURSOR); +yy811: + YYDEBUG(811, *YYCURSOR); if (yybm[0+yych] & 32) { - goto yy857; + goto yy810; } - goto yy839; -yy859: - YYDEBUG(859, *YYCURSOR); + goto yy792; +yy812: + YYDEBUG(812, *YYCURSOR); yych = *++YYCURSOR; if (yybm[0+yych] & 128) { - goto yy867; + goto yy820; } -yy860: - YYDEBUG(860, *YYCURSOR); +yy813: + YYDEBUG(813, *YYCURSOR); YYCURSOR = YYMARKER; - goto yy839; -yy861: - YYDEBUG(861, *YYCURSOR); + goto yy792; +yy814: + YYDEBUG(814, *YYCURSOR); yych = *++YYCURSOR; if (yybm[0+yych] & 64) { - goto yy865; + goto yy818; } - goto yy860; -yy862: - YYDEBUG(862, *YYCURSOR); + goto yy813; +yy815: + YYDEBUG(815, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; - YYDEBUG(863, *YYCURSOR); - if (yych <= '/') goto yy864; - if (yych <= '9') goto yy862; -yy864: - YYDEBUG(864, *YYCURSOR); + YYDEBUG(816, *YYCURSOR); + if (yych <= '/') goto yy817; + if (yych <= '9') goto yy815; +yy817: + YYDEBUG(817, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1564 "Zend/zend_language_scanner.l" +#line 1568 "Zend/zend_language_scanner.l" { /* Offset must be treated as a string */ ZVAL_STRINGL(zendlval, yytext, yyleng); return T_NUM_STRING; } -#line 7734 "Zend/zend_language_scanner.c" -yy865: - YYDEBUG(865, *YYCURSOR); +#line 7345 "Zend/zend_language_scanner.c" +yy818: + YYDEBUG(818, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; - YYDEBUG(866, *YYCURSOR); + YYDEBUG(819, *YYCURSOR); if (yybm[0+yych] & 64) { - goto yy865; + goto yy818; } - goto yy864; -yy867: - YYDEBUG(867, *YYCURSOR); + goto yy817; +yy820: + YYDEBUG(820, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; - YYDEBUG(868, *YYCURSOR); + YYDEBUG(821, *YYCURSOR); if (yybm[0+yych] & 128) { - goto yy867; + goto yy820; } - goto yy864; + goto yy817; } } -#line 2288 "Zend/zend_language_scanner.l" +#line 2226 "Zend/zend_language_scanner.l" } diff --git a/Zend/zend_language_scanner.l b/Zend/zend_language_scanner.l index bcc341e8a1..f87d7bada7 100644 --- a/Zend/zend_language_scanner.l +++ b/Zend/zend_language_scanner.l @@ -284,7 +284,8 @@ static const zend_encoding *zend_multibyte_detect_utf_encoding(const unsigned ch /* utf-16 or utf-32? */ p = script; - while ((p-script) < script_size) { + assert(p >= script); + while ((size_t)(p-script) < script_size) { p = memchr(p, 0, script_size-(p-script)-2); if (!p) { break; @@ -300,7 +301,8 @@ static const zend_encoding *zend_multibyte_detect_utf_encoding(const unsigned ch /* BE or LE? */ p = script; - while ((p-script) < script_size) { + assert(p >= script); + while ((size_t)(p-script) < script_size) { if (*p == '\0' && *(p+wchar_size-1) != '\0') { /* BE */ le = 0; @@ -520,7 +522,7 @@ ZEND_API int open_file_for_scanning(zend_file_handle *file_handle TSRMLS_DC) } } SCNG(yy_start) = (unsigned char *)buf - offset; - yy_scan_buffer(buf, size TSRMLS_CC); + yy_scan_buffer(buf, (unsigned int)size TSRMLS_CC); } else { zend_error_noreturn(E_COMPILE_ERROR, "zend_stream_mmap() failed"); } @@ -681,7 +683,7 @@ ZEND_API int zend_prepare_string_for_scanning(zval *str, char *filename TSRMLS_D } } - yy_scan_buffer(buf, size TSRMLS_CC); + yy_scan_buffer(buf, (unsigned int)size TSRMLS_CC); new_compiled_filename = zend_string_init(filename, strlen(filename), 0); zend_set_compiled_filename(new_compiled_filename TSRMLS_CC); @@ -989,8 +991,6 @@ int lex_scan(zval *zendlval TSRMLS_DC) restart: SCNG(yy_text) = YYCURSOR; -yymore_restart: - /*!re2c re2c:yyfill:check = 0; LNUM [0-9]+ @@ -1202,6 +1202,10 @@ NEWLINE ("\r"|"\n"|"\r\n") return T_ELLIPSIS; } +<ST_IN_SCRIPTING>"??" { + return T_COALESCE; +} + <ST_IN_SCRIPTING>"new" { return T_NEW; } @@ -1603,30 +1607,6 @@ NEWLINE ("\r"|"\n"|"\r\n") return T_NS_C; } -<INITIAL>"<script"{WHITESPACE}+"language"{WHITESPACE}*"="{WHITESPACE}*("php"|"\"php\""|"'php'"){WHITESPACE}*">" { - YYCTYPE *bracket = (YYCTYPE*)zend_memrchr(yytext, '<', yyleng - (sizeof("script language=php>") - 1)); - - if (bracket != SCNG(yy_text)) { - /* Handle previously scanned HTML, as possible <script> tags found are assumed to not be PHP's */ - YYCURSOR = bracket; - goto inline_html; - } - - HANDLE_NEWLINES(yytext, yyleng); - BEGIN(ST_IN_SCRIPTING); - return T_OPEN_TAG; -} - - -<INITIAL>"<%=" { - if (CG(asp_tags)) { - BEGIN(ST_IN_SCRIPTING); - return T_OPEN_TAG_WITH_ECHO; - } else { - goto inline_char_handler; - } -} - <INITIAL>"<?=" { BEGIN(ST_IN_SCRIPTING); @@ -1634,16 +1614,6 @@ NEWLINE ("\r"|"\n"|"\r\n") } -<INITIAL>"<%" { - if (CG(asp_tags)) { - BEGIN(ST_IN_SCRIPTING); - return T_OPEN_TAG; - } else { - goto inline_char_handler; - } -} - - <INITIAL>"<?php"([ \t]|{NEWLINE}) { HANDLE_NEWLINE(yytext[yyleng-1]); BEGIN(ST_IN_SCRIPTING); @@ -1672,39 +1642,23 @@ inline_char_handler: YYCURSOR = ptr ? ptr + 1 : YYLIMIT; - if (YYCURSOR < YYLIMIT) { - switch (*YYCURSOR) { - case '?': - if (CG(short_tags) || !strncasecmp((char*)YYCURSOR + 1, "php", 3) || (*(YYCURSOR + 1) == '=')) { /* Assume [ \t\n\r] follows "php" */ - break; - } - continue; - case '%': - if (CG(asp_tags)) { - break; - } - continue; - case 's': - case 'S': - /* Probably NOT an opening PHP <script> tag, so don't end the HTML chunk yet - * If it is, the PHP <script> tag rule checks for any HTML scanned before it */ - YYCURSOR--; - yymore(); - default: - continue; - } - - YYCURSOR--; + if (YYCURSOR >= YYLIMIT) { + break; } - break; + if (*YYCURSOR == '?') { + if (CG(short_tags) || !strncasecmp((char*)YYCURSOR + 1, "php", 3) || (*(YYCURSOR + 1) == '=')) { /* Assume [ \t\n\r] follows "php" */ + + YYCURSOR--; + break; + } + } } -inline_html: yyleng = YYCURSOR - SCNG(yy_text); if (SCNG(output_filter)) { - int readsize; + size_t readsize; char *s = NULL; size_t sz = 0; // TODO: avoid reallocation ??? @@ -1781,11 +1735,6 @@ inline_html: case '\n': CG(zend_lineno)++; break; - case '%': - if (!CG(asp_tags)) { - continue; - } - /* fall through */ case '?': if (*YYCURSOR == '>') { YYCURSOR--; @@ -1837,23 +1786,12 @@ inline_html: return T_COMMENT; } -<ST_IN_SCRIPTING>("?>"|"</script"{WHITESPACE}*">"){NEWLINE}? { +<ST_IN_SCRIPTING>"?>"{NEWLINE}? { BEGIN(INITIAL); return T_CLOSE_TAG; /* implicit ';' at php-end tag */ } -<ST_IN_SCRIPTING>"%>"{NEWLINE}? { - if (CG(asp_tags)) { - BEGIN(INITIAL); - return T_CLOSE_TAG; /* implicit ';' at php-end tag */ - } else { - yyless(1); - return yytext[0]; - } -} - - <ST_IN_SCRIPTING>b?['] { register char *s, *t; char *end; diff --git a/Zend/zend_llist.c b/Zend/zend_llist.c index 0fb49abf5b..0df7e702f1 100644 --- a/Zend/zend_llist.c +++ b/Zend/zend_llist.c @@ -243,7 +243,7 @@ ZEND_API void zend_llist_apply_with_arguments(zend_llist *l, llist_apply_with_ar } -ZEND_API int zend_llist_count(zend_llist *l) +ZEND_API size_t zend_llist_count(zend_llist *l) { return l->count; } diff --git a/Zend/zend_llist.h b/Zend/zend_llist.h index 602884c27d..ffe0c3cf99 100644 --- a/Zend/zend_llist.h +++ b/Zend/zend_llist.h @@ -59,7 +59,7 @@ ZEND_API void zend_llist_apply(zend_llist *l, llist_apply_func_t func TSRMLS_DC) ZEND_API void zend_llist_apply_with_del(zend_llist *l, int (*func)(void *data)); ZEND_API void zend_llist_apply_with_argument(zend_llist *l, llist_apply_with_arg_func_t func, void *arg TSRMLS_DC); ZEND_API void zend_llist_apply_with_arguments(zend_llist *l, llist_apply_with_args_func_t func TSRMLS_DC, int num_args, ...); -ZEND_API int zend_llist_count(zend_llist *l); +ZEND_API size_t zend_llist_count(zend_llist *l); ZEND_API void zend_llist_sort(zend_llist *l, llist_compare_func_t comp_func TSRMLS_DC); /* traversal */ diff --git a/Zend/zend_multiply.h b/Zend/zend_multiply.h index 158be22007..6dce8fb6ac 100644 --- a/Zend/zend_multiply.h +++ b/Zend/zend_multiply.h @@ -84,10 +84,10 @@ } \ } while (0) -#elif SIZEOF_ZEND_LONG == 4 && defined(HAVE_ZEND_LONG64) +#elif SIZEOF_ZEND_LONG == 4 #define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \ - zend_long64 __result = (zend_long64) (a) * (zend_long64) (b); \ + int64_t __result = (int64_t) (a) * (int64_t) (b); \ if (__result > ZEND_LONG_MAX || __result < ZEND_LONG_MIN) { \ (dval) = (double) __result; \ (usedval) = 1; \ @@ -117,7 +117,7 @@ static zend_always_inline size_t zend_safe_address(size_t nmemb, size_t size, size_t offset, int *overflow) { size_t res = nmemb; - zend_ulong m_overflow = 0; + size_t m_overflow = 0; __asm__ ("mull %3\n\taddl %4,%0\n\tadcl $0,%1" : "=&a"(res), "=&d" (m_overflow) @@ -206,13 +206,13 @@ static zend_always_inline size_t zend_safe_address(size_t nmemb, size_t size, si return res; } -#elif SIZEOF_SIZE_T == 4 && defined(HAVE_ZEND_LONG64) +#elif SIZEOF_SIZE_T == 4 static zend_always_inline size_t zend_safe_address(size_t nmemb, size_t size, size_t offset, int *overflow) { - zend_ulong64 res = (zend_ulong64)nmemb * (zend_ulong64)size + (zend_ulong64)offset; + uint64_t res = (uint64_t) nmemb * (uint64_t) size + (uint64_t) offset; - if (UNEXPECTED(res > (zend_ulong64)0xFFFFFFFFL)) { + if (UNEXPECTED(res > UINT64_C(0xFFFFFFFF))) { *overflow = 1; return 0; } diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index f831d2fadd..6b4e8f1a97 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -268,12 +268,7 @@ static zend_always_inline int zend_verify_property_access(zend_property_info *pr case ZEND_ACC_PROTECTED: return zend_check_protected(property_info->ce, EG(scope)); case ZEND_ACC_PRIVATE: - if ((ce==EG(scope) || property_info->ce == EG(scope)) && EG(scope)) { - return 1; - } else { - return 0; - } - break; + return (ce == EG(scope) || property_info->ce == EG(scope)); } return 0; } @@ -293,22 +288,14 @@ static zend_always_inline zend_bool is_derived_class(zend_class_entry *child_cla } /* }}} */ -static zend_always_inline struct _zend_property_info *zend_get_property_info_quick(zend_class_entry *ce, zend_string *member, int silent, void **cache_slot TSRMLS_DC) /* {{{ */ +static zend_always_inline zend_property_info *zend_get_property_info_quick(zend_class_entry *ce, zend_string *member, int silent, void **cache_slot TSRMLS_DC) /* {{{ */ { - zend_property_info *property_info; - zend_property_info *scope_property_info; - zend_bool denied_access = 0; + zval *zv; + zend_property_info *property_info = NULL; + uint32_t flags; if (cache_slot && EXPECTED(ce == CACHED_PTR_EX(cache_slot))) { - property_info = CACHED_PTR_EX(cache_slot + 1); - if (UNEXPECTED(!property_info)) { - EG(std_property_info).flags = ZEND_ACC_PUBLIC; - EG(std_property_info).name = member; - EG(std_property_info).ce = ce; - EG(std_property_info).offset = -1; - property_info = &EG(std_property_info); - } - return property_info; + return CACHED_PTR_EX(cache_slot + 1); } if (UNEXPECTED(member->val[0] == '\0')) { @@ -319,73 +306,69 @@ static zend_always_inline struct _zend_property_info *zend_get_property_info_qui zend_error_noreturn(E_ERROR, "Cannot access property started with '\\0'"); } } - return NULL; + return ZEND_WRONG_PROPERTY_INFO; } - property_info = NULL; - if ((property_info = zend_hash_find_ptr(&ce->properties_info, member)) != NULL) { - if (UNEXPECTED((property_info->flags & ZEND_ACC_SHADOW) != 0)) { + + if (UNEXPECTED(zend_hash_num_elements(&ce->properties_info) == 0)) { + goto exit_dynamic; + } + + zv = zend_hash_find(&ce->properties_info, member); + if (EXPECTED(zv != NULL)) { + property_info = (zend_property_info*)Z_PTR_P(zv); + flags = property_info->flags; + if (UNEXPECTED((flags & ZEND_ACC_SHADOW) != 0)) { /* if it's a shadow - go to access it's private */ property_info = NULL; } else { if (EXPECTED(zend_verify_property_access(property_info, ce TSRMLS_CC) != 0)) { - if (EXPECTED((property_info->flags & ZEND_ACC_CHANGED) != 0) - && EXPECTED(!(property_info->flags & ZEND_ACC_PRIVATE))) { - /* We still need to make sure that we're not in a context - * where the right property is a different 'statically linked' private - * continue checking below... - */ - } else { - if (UNEXPECTED((property_info->flags & ZEND_ACC_STATIC) != 0) && !silent) { + if (UNEXPECTED(!(flags & ZEND_ACC_CHANGED)) + || UNEXPECTED((flags & ZEND_ACC_PRIVATE))) { + if (UNEXPECTED((flags & ZEND_ACC_STATIC) != 0) && !silent) { zend_error(E_STRICT, "Accessing static property %s::$%s as non static", ce->name->val, member->val); } - if (cache_slot) { - CACHE_POLYMORPHIC_PTR_EX(cache_slot, ce, property_info); - } - return property_info; + goto exit; } } else { /* Try to look in the scope instead */ - denied_access = 1; + property_info = ZEND_WRONG_PROPERTY_INFO; } } } + if (EG(scope) != ce && EG(scope) && is_derived_class(ce, EG(scope)) - && (scope_property_info = zend_hash_find_ptr(&EG(scope)->properties_info, member)) != NULL - && scope_property_info->flags & ZEND_ACC_PRIVATE) { + && (zv = zend_hash_find(&EG(scope)->properties_info, member)) != NULL + && ((zend_property_info*)Z_PTR_P(zv))->flags & ZEND_ACC_PRIVATE) { + property_info = (zend_property_info*)Z_PTR_P(zv); + goto exit; + } else if (UNEXPECTED(property_info == NULL)) { +exit_dynamic: if (cache_slot) { - CACHE_POLYMORPHIC_PTR_EX(cache_slot, ce, scope_property_info); + CACHE_POLYMORPHIC_PTR_EX(cache_slot, ce, NULL); } - return scope_property_info; - } else if (property_info) { - if (UNEXPECTED(denied_access != 0)) { - /* Information was available, but we were denied access. Error out. */ - if (!silent) { - zend_error_noreturn(E_ERROR, "Cannot access %s property %s::$%s", zend_visibility_string(property_info->flags), ce->name->val, member->val); - } - return NULL; - } else { - /* fall through, return property_info... */ - if (cache_slot) { - CACHE_POLYMORPHIC_PTR_EX(cache_slot, ce, property_info); - } + return NULL; + } else if (UNEXPECTED(property_info == ZEND_WRONG_PROPERTY_INFO)) { + /* Information was available, but we were denied access. Error out. */ + if (!silent) { + zend_error_noreturn(E_ERROR, "Cannot access %s property %s::$%s", zend_visibility_string(flags), ce->name->val, member->val); } - } else { if (cache_slot) { - CACHE_POLYMORPHIC_PTR_EX(cache_slot, ce, NULL); + CACHE_POLYMORPHIC_PTR_EX(cache_slot, ce, ZEND_WRONG_PROPERTY_INFO); } - EG(std_property_info).flags = ZEND_ACC_PUBLIC; - EG(std_property_info).name = member; - EG(std_property_info).ce = ce; - EG(std_property_info).offset = -1; - property_info = &EG(std_property_info); + return ZEND_WRONG_PROPERTY_INFO; + } + +exit: + if (cache_slot) { + CACHE_POLYMORPHIC_PTR_EX(cache_slot, ce, property_info); } return property_info; } /* }}} */ -ZEND_API struct _zend_property_info *zend_get_property_info(zend_class_entry *ce, zend_string *member, int silent TSRMLS_DC) /* {{{ */ +ZEND_API zend_property_info *zend_get_property_info(zend_class_entry *ce, zend_string *member, int silent TSRMLS_DC) /* {{{ */ { return zend_get_property_info_quick(ce, member, silent, NULL TSRMLS_CC); } @@ -407,7 +390,14 @@ ZEND_API int zend_check_property_access(zend_object *zobj, zend_string *prop_inf } property_info = zend_get_property_info_quick(zobj->ce, member, 1, NULL TSRMLS_CC); zend_string_release(member); - if (!property_info) { + if (property_info == NULL) { + /* undefined public property */ + if (class_name && class_name[0] != '*') { + /* we we're looking for a private prop */ + return FAILURE; + } + return SUCCESS; + } else if (property_info == ZEND_WRONG_PROPERTY_INFO) { return FAILURE; } if (class_name && class_name[0] != '*') { @@ -423,41 +413,19 @@ ZEND_API int zend_check_property_access(zend_object *zobj, zend_string *prop_inf } /* }}} */ -static zend_long *zend_get_property_guard(zend_object *zobj, zend_property_info *property_info, zval *member) /* {{{ */ +static zend_long *zend_get_property_guard(zend_object *zobj, zend_string *member) /* {{{ */ { - zend_property_info info; zval stub, *guard; - zend_string *str = NULL; - - if (!property_info) { - property_info = &info; - info.name = Z_STR_P(member); - } else if(property_info->name->val[0] == '\0'){ - const char *class_name = NULL, *prop_name = NULL; - size_t prop_name_len; - zend_unmangle_property_name_ex(property_info->name, &class_name, - &prop_name, &prop_name_len); - if (class_name) { - /* use unmangled name for protected properties */ - str = info.name = zend_string_init(prop_name, prop_name_len, 0); - property_info = &info; - } - } + if (!zobj->guards) { ALLOC_HASHTABLE(zobj->guards); zend_hash_init(zobj->guards, 8, NULL, NULL, 0); - } else if ((guard = zend_hash_find(zobj->guards, property_info->name)) != NULL) { - if (str) { - zend_string_release(str); - } + } else if ((guard = zend_hash_find(zobj->guards, member)) != NULL) { return &Z_LVAL_P(guard); } ZVAL_LONG(&stub, 0); - guard = zend_hash_add_new(zobj->guards, property_info->name, &stub); - if (str) { - zend_string_release(str); - } + guard = zend_hash_add_new(zobj->guards, member, &stub); return &Z_LVAL_P(guard); } /* }}} */ @@ -468,15 +436,12 @@ zval *zend_std_read_property(zval *object, zval *member, int type, void **cache_ zval tmp_member; zval *retval; zend_property_info *property_info; - int silent; - silent = (type == BP_VAR_IS); zobj = Z_OBJ_P(object); ZVAL_UNDEF(&tmp_member); if (UNEXPECTED(Z_TYPE_P(member) != IS_STRING)) { - ZVAL_DUP(&tmp_member, member); - convert_to_string(&tmp_member); + ZVAL_STR(&tmp_member, zval_get_string(member)); member = &tmp_member; cache_slot = NULL; } @@ -486,24 +451,25 @@ zval *zend_std_read_property(zval *object, zval *member, int type, void **cache_ #endif /* make zend_get_property_info silent if we have getter - we may want to use it */ - property_info = zend_get_property_info_quick(zobj->ce, Z_STR_P(member), silent || (zobj->ce->__get != NULL), cache_slot TSRMLS_CC); + property_info = zend_get_property_info_quick(zobj->ce, Z_STR_P(member), (type == BP_VAR_IS) || (zobj->ce->__get != NULL), cache_slot TSRMLS_CC); + + if (EXPECTED(property_info != ZEND_WRONG_PROPERTY_INFO)) { + if (EXPECTED(property_info != NULL) && + EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0)) { - if (EXPECTED(property_info != NULL)) { - if (EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) && - property_info->offset >= 0) { retval = &zobj->properties_table[property_info->offset]; - if (Z_TYPE_P(retval) != IS_UNDEF) { + if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { goto exit; } - } else if (UNEXPECTED(zobj->properties != NULL)) { - retval = zend_hash_find(zobj->properties, property_info->name); - if (retval) goto exit; + } else if (EXPECTED(zobj->properties != NULL)) { + retval = zend_hash_find(zobj->properties, Z_STR_P(member)); + if (EXPECTED(retval)) goto exit; } } /* magic get */ if (zobj->ce->__get) { - zend_long *guard = zend_get_property_guard(zobj, property_info, member); + zend_long *guard = zend_get_property_guard(zobj, Z_STR_P(member)); if (!((*guard) & IN_GET)) { zval tmp_object; @@ -526,6 +492,7 @@ zval *zend_std_read_property(zval *object, zval *member, int type, void **cache_ retval = &EG(uninitialized_zval); } zval_ptr_dtor(&tmp_object); + goto exit; } else { if (Z_STRVAL_P(member)[0] == '\0') { if (Z_STRLEN_P(member) == 0) { @@ -534,17 +501,12 @@ zval *zend_std_read_property(zval *object, zval *member, int type, void **cache_ zend_error(E_ERROR, "Cannot access property started with '\\0'"); } } - if (!silent) { - zend_error(E_NOTICE,"Undefined property: %s::$%s", zobj->ce->name->val, Z_STRVAL_P(member)); - } - retval = &EG(uninitialized_zval); } - } else { - if (!silent) { - zend_error(E_NOTICE,"Undefined property: %s::$%s", zobj->ce->name->val, Z_STRVAL_P(member)); - } - retval = &EG(uninitialized_zval); } + if ((type != BP_VAR_IS)) { + zend_error(E_NOTICE,"Undefined property: %s::$%s", zobj->ce->name->val, Z_STRVAL_P(member)); + } + retval = &EG(uninitialized_zval); exit: if (UNEXPECTED(Z_TYPE(tmp_member) != IS_UNDEF)) { @@ -567,23 +529,23 @@ ZEND_API void zend_std_write_property(zval *object, zval *member, zval *value, v ZVAL_UNDEF(&tmp_member); if (UNEXPECTED(Z_TYPE_P(member) != IS_STRING)) { - ZVAL_DUP(&tmp_member, member); - convert_to_string(&tmp_member); + ZVAL_STR(&tmp_member, zval_get_string(member)); member = &tmp_member; cache_slot = NULL; } property_info = zend_get_property_info_quick(zobj->ce, Z_STR_P(member), (zobj->ce->__set != NULL), cache_slot TSRMLS_CC); - if (EXPECTED(property_info != NULL)) { - if (EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) && - property_info->offset >= 0) { + if (EXPECTED(property_info != ZEND_WRONG_PROPERTY_INFO)) { + if (EXPECTED(property_info != NULL) && + EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0)) { + variable_ptr = &zobj->properties_table[property_info->offset]; if (Z_TYPE_P(variable_ptr) != IS_UNDEF) { goto found; } } else if (EXPECTED(zobj->properties != NULL)) { - if ((variable_ptr = zend_hash_find(zobj->properties, property_info->name)) != NULL) { + if ((variable_ptr = zend_hash_find(zobj->properties, Z_STR_P(member))) != NULL) { found: /* if we already have this value there, we don't actually need to do anything */ if (EXPECTED(variable_ptr != value)) { @@ -637,7 +599,7 @@ found: /* magic set */ if (zobj->ce->__set) { - zend_long *guard = zend_get_property_guard(zobj, property_info, member); + zend_long *guard = zend_get_property_guard(zobj, Z_STR_P(member)); if (!((*guard) & IN_SET)) { zval tmp_object; @@ -649,7 +611,7 @@ found: } (*guard) &= ~IN_SET; zval_ptr_dtor(&tmp_object); - } else if (EXPECTED(property_info != NULL)) { + } else if (EXPECTED(property_info != ZEND_WRONG_PROPERTY_INFO)) { goto write_std_property; } else { if (Z_STRVAL_P(member)[0] == '\0') { @@ -660,7 +622,7 @@ found: } } } - } else if (EXPECTED(property_info != NULL)) { + } else if (EXPECTED(property_info != ZEND_WRONG_PROPERTY_INFO)) { zval tmp; write_std_property: @@ -673,15 +635,15 @@ write_std_property: Z_ADDREF_P(value); } } - if (EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) && - property_info->offset >= 0) { + if (EXPECTED(property_info != NULL) && + EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0)) { ZVAL_COPY_VALUE(&zobj->properties_table[property_info->offset], value); } else { if (!zobj->properties) { rebuild_object_properties(zobj); } - zend_hash_update(zobj->properties, property_info->name, value); + zend_hash_update(zobj->properties, Z_STR_P(member), value); } } @@ -777,67 +739,63 @@ static int zend_std_has_dimension(zval *object, zval *offset, int check_empty TS static zval *zend_std_get_property_ptr_ptr(zval *object, zval *member, int type, void **cache_slot TSRMLS_DC) /* {{{ */ { zend_object *zobj; - zval tmp_member; - zval *retval, tmp; + zend_string *name; + zval *retval = NULL; zend_property_info *property_info; - zend_long *guard; zobj = Z_OBJ_P(object); - - ZVAL_UNDEF(&tmp_member); - if (UNEXPECTED(Z_TYPE_P(member) != IS_STRING)) { - ZVAL_DUP(&tmp_member, member); - convert_to_string(&tmp_member); - member = &tmp_member; - cache_slot = NULL; + if (EXPECTED(Z_TYPE_P(member) == IS_STRING)) { + name = Z_STR_P(member); + } else { + name = zval_get_string(member); } #if DEBUG_OBJECT_HANDLERS - fprintf(stderr, "Ptr object #%d property: %s\n", Z_OBJ_HANDLE_P(object), Z_STRVAL_P(member)); + fprintf(stderr, "Ptr object #%d property: %s\n", Z_OBJ_HANDLE_P(object), name->val); #endif - property_info = zend_get_property_info_quick(zobj->ce, Z_STR_P(member), (zobj->ce->__get != NULL), cache_slot TSRMLS_CC); - - if (EXPECTED(property_info != NULL)) { - if (EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) && - property_info->offset >= 0) { - retval = &zobj->properties_table[property_info->offset]; - if (Z_TYPE_P(retval) != IS_UNDEF) { - goto exit; - } - } else if (UNEXPECTED(zobj->properties != NULL)) { - retval = zend_hash_find(zobj->properties, property_info->name); - if (retval) goto exit; - } - } + property_info = zend_get_property_info_quick(zobj->ce, name, (zobj->ce->__get != NULL), cache_slot TSRMLS_CC); - if (!zobj->ce->__get || - (guard = zend_get_property_guard(zobj, property_info, member)) == NULL || - (property_info && ((*guard) & IN_GET))) { + if (EXPECTED(property_info != ZEND_WRONG_PROPERTY_INFO)) { + if (EXPECTED(property_info != NULL) && + EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0)) { - /* we don't have access controls - will just add it */ - if(UNEXPECTED(type == BP_VAR_RW || type == BP_VAR_R)) { - zend_error(E_NOTICE, "Undefined property: %s::$%s", zobj->ce->name->val, Z_STRVAL_P(member)); - } - ZVAL_NULL(&tmp); - if (EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) && - property_info->offset >= 0) { retval = &zobj->properties_table[property_info->offset]; - ZVAL_NULL(retval); + if (UNEXPECTED(Z_TYPE_P(retval) == IS_UNDEF)) { + if (EXPECTED(!zobj->ce->__get) || + UNEXPECTED((*zend_get_property_guard(zobj, name)) & IN_GET)) { + ZVAL_NULL(retval); + /* Notice is thrown after creation of the property, to avoid EG(std_property_info) + * being overwritten in an error handler. */ + if (UNEXPECTED(type == BP_VAR_RW || type == BP_VAR_R)) { + zend_error(E_NOTICE, "Undefined property: %s::$%s", zobj->ce->name->val, name->val); + } + } else { + /* we do have getter - fail and let it try again with usual get/set */ + retval = NULL; + } + } } else { - if (!zobj->properties) { - rebuild_object_properties(zobj); + if (UNEXPECTED(!zobj->properties) || + UNEXPECTED((retval = zend_hash_find(zobj->properties, name)) == NULL)) { + if (EXPECTED(!zobj->ce->__get) || + UNEXPECTED((*zend_get_property_guard(zobj, name)) & IN_GET)) { + if (UNEXPECTED(!zobj->properties)) { + rebuild_object_properties(zobj); + } + retval = zend_hash_update(zobj->properties, name, &EG(uninitialized_zval)); + /* Notice is thrown after creation of the property, to avoid EG(std_property_info) + * being overwritten in an error handler. */ + if (UNEXPECTED(type == BP_VAR_RW || type == BP_VAR_R)) { + zend_error(E_NOTICE, "Undefined property: %s::$%s", zobj->ce->name->val, name->val); + } + } } - retval = zend_hash_update(zobj->properties, property_info->name, &tmp); } - } else { - /* we do have getter - fail and let it try again with usual get/set */ - retval = NULL; } -exit: - if (UNEXPECTED(Z_TYPE(tmp_member) != IS_UNDEF)) { - zval_dtor(&tmp_member); + if (UNEXPECTED(Z_TYPE_P(member) != IS_STRING)) { + zend_string_release(name); } return retval; } @@ -853,31 +811,31 @@ static void zend_std_unset_property(zval *object, zval *member, void **cache_slo ZVAL_UNDEF(&tmp_member); if (UNEXPECTED(Z_TYPE_P(member) != IS_STRING)) { - ZVAL_DUP(&tmp_member, member); - convert_to_string(&tmp_member); + ZVAL_STR(&tmp_member, zval_get_string(member)); member = &tmp_member; cache_slot = NULL; } property_info = zend_get_property_info_quick(zobj->ce, Z_STR_P(member), (zobj->ce->__unset != NULL), cache_slot TSRMLS_CC); - if (EXPECTED(property_info != NULL)) { - if (EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) && - property_info->offset >= 0) { + if (EXPECTED(property_info != ZEND_WRONG_PROPERTY_INFO)) { + if (EXPECTED(property_info != NULL) && + EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0)) { + if (Z_TYPE(zobj->properties_table[property_info->offset]) != IS_UNDEF) { zval_ptr_dtor(&zobj->properties_table[property_info->offset]); ZVAL_UNDEF(&zobj->properties_table[property_info->offset]); goto exit; } - } else if (zobj->properties && - UNEXPECTED(zend_hash_del(zobj->properties, property_info->name) != FAILURE)) { + } else if (EXPECTED(zobj->properties != NULL) && + EXPECTED(zend_hash_del(zobj->properties, Z_STR_P(member)) != FAILURE)) { goto exit; } } /* magic unset */ if (zobj->ce->__unset) { - zend_long *guard = zend_get_property_guard(zobj, property_info, member); + zend_long *guard = zend_get_property_guard(zobj, Z_STR_P(member)); if (!((*guard) & IN_UNSET)) { zval tmp_object; @@ -921,7 +879,7 @@ static void zend_std_unset_dimension(zval *object, zval *offset TSRMLS_DC) /* {{ ZEND_API void zend_std_call_user_call(INTERNAL_FUNCTION_PARAMETERS) /* {{{ */ { - zend_internal_function *func = (zend_internal_function *)EG(current_execute_data)->func; + zend_internal_function *func = (zend_internal_function *)EX(func); zval method_name, method_args; zval method_result; zend_class_entry *ce = Z_OBJCE_P(getThis()); @@ -1091,7 +1049,7 @@ static union _zend_function *zend_std_get_method(zend_object **obj_ptr, zend_str /* Ensure that if we're calling a private function, we're allowed to do so. * If we're not and __call() handler exists, invoke it, otherwise error out. */ - updated_fbc = zend_check_private_int(fbc, zobj->handlers->get_class_entry(zobj TSRMLS_CC), lc_method_name TSRMLS_CC); + updated_fbc = zend_check_private_int(fbc, zobj->ce, lc_method_name TSRMLS_CC); if (EXPECTED(updated_fbc != NULL)) { fbc = updated_fbc; } else { @@ -1139,7 +1097,7 @@ static union _zend_function *zend_std_get_method(zend_object **obj_ptr, zend_str ZEND_API void zend_std_callstatic_user_call(INTERNAL_FUNCTION_PARAMETERS) /* {{{ */ { - zend_internal_function *func = (zend_internal_function *)EG(current_execute_data)->func; + zend_internal_function *func = (zend_internal_function *)EX(func); zval method_name, method_args; zval method_result; zend_class_entry *ce = EG(scope); @@ -1231,9 +1189,8 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_st zend_string_free(lc_function_name); } if (ce->__call && - Z_OBJ(EG(This)) && - Z_OBJ_HT(EG(This))->get_class_entry && - instanceof_function(Z_OBJCE(EG(This)), ce TSRMLS_CC)) { + Z_OBJ(EG(current_execute_data)->This) && + instanceof_function(Z_OBJCE(EG(current_execute_data)->This), ce TSRMLS_CC)) { return zend_get_user_call_function(ce, function_name); } else if (ce->__callstatic) { return zend_get_user_callstatic_function(ce, function_name); @@ -1451,23 +1408,23 @@ static int zend_std_has_property(zval *object, zval *member, int has_set_exists, ZVAL_UNDEF(&tmp_member); if (UNEXPECTED(Z_TYPE_P(member) != IS_STRING)) { - ZVAL_DUP(&tmp_member, member); - convert_to_string(&tmp_member); + ZVAL_STR(&tmp_member, zval_get_string(member)); member = &tmp_member; cache_slot = NULL; } property_info = zend_get_property_info_quick(zobj->ce, Z_STR_P(member), 1, cache_slot TSRMLS_CC); - if (EXPECTED(property_info != NULL)) { - if (EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) && - property_info->offset >= 0) { + if (EXPECTED(property_info != ZEND_WRONG_PROPERTY_INFO)) { + if (EXPECTED(property_info != NULL) && + EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0)) { + value = &zobj->properties_table[property_info->offset]; if (Z_TYPE_P(value) != IS_UNDEF) { goto found; } - } else if (UNEXPECTED(zobj->properties != NULL) && - (value = zend_hash_find(zobj->properties, property_info->name)) != NULL) { + } else if (EXPECTED(zobj->properties != NULL) && + (value = zend_hash_find(zobj->properties, Z_STR_P(member))) != NULL) { found: switch (has_set_exists) { case 0: @@ -1487,7 +1444,7 @@ found: result = 0; if ((has_set_exists != 2) && zobj->ce->__isset) { - zend_long *guard = zend_get_property_guard(zobj, property_info, member); + zend_long *guard = zend_get_property_guard(zobj, Z_STR_P(member)); if (!((*guard) & IN_ISSET)) { zval rv; @@ -1529,26 +1486,9 @@ exit: } /* }}} */ -zend_class_entry *zend_std_object_get_class(const zend_object *object TSRMLS_DC) /* {{{ */ -{ - return object->ce; -} -/* }}} */ - -zend_string* zend_std_object_get_class_name(const zend_object *zobj, int parent TSRMLS_DC) /* {{{ */ +zend_string *zend_std_object_get_class_name(const zend_object *zobj TSRMLS_DC) /* {{{ */ { - zend_class_entry *ce; - - if (parent) { - if (!zobj->ce->parent) { - return NULL; - } - ce = zobj->ce->parent; - } else { - ce = zobj->ce; - } - - return zend_string_copy(ce->name); + return zend_string_copy(zobj->ce->name); } /* }}} */ @@ -1664,7 +1604,6 @@ ZEND_API zend_object_handlers std_object_handlers = { zend_std_get_method, /* get_method */ NULL, /* call_method */ zend_std_get_constructor, /* get_constructor */ - zend_std_object_get_class, /* get_class_entry */ zend_std_object_get_class_name, /* get_class_name */ zend_std_compare_objects, /* compare_objects */ zend_std_cast_object_tostring, /* cast_object */ diff --git a/Zend/zend_object_handlers.h b/Zend/zend_object_handlers.h index bc8500c3ec..ac0965ad57 100644 --- a/Zend/zend_object_handlers.h +++ b/Zend/zend_object_handlers.h @@ -25,6 +25,9 @@ union _zend_function; struct _zend_property_info; +#define ZEND_WRONG_PROPERTY_INFO \ + ((struct _zend_property_info*)((zend_intptr_t)-1)) + /* The following rule applies to read_property() and read_dimension() implementations: If you return a zval which is not otherwise referenced by the extension or the engine's symbol table, its reference count should be 0. @@ -95,8 +98,10 @@ typedef void (*zend_object_dtor_obj_t)(zend_object *object TSRMLS_DC); typedef void (*zend_object_free_obj_t)(zend_object *object TSRMLS_DC); typedef zend_object* (*zend_object_clone_obj_t)(zval *object TSRMLS_DC); -typedef zend_class_entry *(*zend_object_get_class_entry_t)(const zend_object *object TSRMLS_DC); -typedef zend_string *(*zend_object_get_class_name_t)(const zend_object *object, int parent TSRMLS_DC); +/* Get class name for display in var_dump and other debugging functions. + * Must be defined and must return a non-NULL value. */ +typedef zend_string *(*zend_object_get_class_name_t)(const zend_object *object TSRMLS_DC); + typedef int (*zend_object_compare_t)(zval *object1, zval *object2 TSRMLS_DC); typedef int (*zend_object_compare_zvals_t)(zval *resul, zval *op1, zval *op2 TSRMLS_DC); @@ -137,7 +142,6 @@ struct _zend_object_handlers { zend_object_get_method_t get_method; zend_object_call_method_t call_method; zend_object_get_constructor_t get_constructor; - zend_object_get_class_entry_t get_class_entry; zend_object_get_class_name_t get_class_name; zend_object_compare_t compare_objects; zend_object_cast_t cast_object; @@ -166,10 +170,6 @@ ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int ty ZEND_API void zend_std_write_property(zval *object, zval *member, zval *value, void **cache_slot TSRMLS_DC); ZEND_API void rebuild_object_properties(zend_object *zobj); - -#define IS_ZEND_STD_OBJECT(z) (Z_TYPE(z) == IS_OBJECT && (Z_OBJ_HT((z))->get_class_entry != NULL)) -#define HAS_CLASS_ENTRY(z) (Z_OBJ_HT(z)->get_class_entry != NULL) - ZEND_API int zend_check_private(union _zend_function *fbc, zend_class_entry *ce, zend_string *function_name TSRMLS_DC); ZEND_API int zend_check_protected(zend_class_entry *ce, zend_class_entry *scope); diff --git a/Zend/zend_objects.c b/Zend/zend_objects.c index 40d37b3d36..58c034163e 100644 --- a/Zend/zend_objects.c +++ b/Zend/zend_objects.c @@ -144,7 +144,8 @@ ZEND_API void zend_objects_clone_members(zend_object *new_object, zend_object *o if (old_object->ce->default_properties_count) { for (i = 0; i < old_object->ce->default_properties_count; i++) { zval_ptr_dtor(&new_object->properties_table[i]); - ZVAL_COPY(&new_object->properties_table[i], &old_object->properties_table[i]); + ZVAL_COPY_VALUE(&new_object->properties_table[i], &old_object->properties_table[i]); + zval_add_ref(&new_object->properties_table[i]); } } if (old_object->properties) { diff --git a/Zend/zend_objects_API.c b/Zend/zend_objects_API.c index 50930df20d..04dd82b6a0 100644 --- a/Zend/zend_objects_API.c +++ b/Zend/zend_objects_API.c @@ -219,107 +219,11 @@ ZEND_API void zend_object_store_ctor_failed(zend_object *obj TSRMLS_DC) GC_FLAGS(obj) |= IS_OBJ_DESTRUCTOR_CALLED; } -/* Proxy objects workings */ -typedef struct _zend_proxy_object { - zend_object std; - zval object; - zval property; -} zend_proxy_object; - -static zend_object_handlers zend_object_proxy_handlers; - -ZEND_API void zend_objects_proxy_destroy(zend_object *object TSRMLS_DC) -{ -} - -ZEND_API void zend_objects_proxy_free_storage(zend_proxy_object *object TSRMLS_DC) -{ - zval_ptr_dtor(&object->object); - zval_ptr_dtor(&object->property); - efree(object); -} - -ZEND_API void zend_objects_proxy_clone(zend_proxy_object *object, zend_proxy_object **object_clone TSRMLS_DC) -{ - *object_clone = emalloc(sizeof(zend_proxy_object)); - (*object_clone)->object = object->object; - (*object_clone)->property = object->property; - Z_ADDREF_P(&(*object_clone)->property); - Z_ADDREF_P(&(*object_clone)->object); -} - -ZEND_API zend_object *zend_object_create_proxy(zval *object, zval *member TSRMLS_DC) -{ - zend_proxy_object *obj = emalloc(sizeof(zend_proxy_object)); - - GC_REFCOUNT(obj) = 1; - GC_TYPE_INFO(obj) = IS_OBJECT; - obj->std.ce = NULL; - obj->std.properties = NULL; - obj->std.guards = NULL; - obj->std.handlers = &zend_object_proxy_handlers; - - ZVAL_COPY(&obj->object, object); - ZVAL_DUP(&obj->property, member); - - return (zend_object*)obj; -} - -ZEND_API void zend_object_proxy_set(zval *property, zval *value TSRMLS_DC) -{ - zend_proxy_object *probj = (zend_proxy_object*)Z_OBJ_P(property); - - if (Z_OBJ_HT(probj->object) && Z_OBJ_HT(probj->object)->write_property) { - Z_OBJ_HT(probj->object)->write_property(&probj->object, &probj->property, value, NULL TSRMLS_CC); - } else { - zend_error(E_WARNING, "Cannot write property of object - no write handler defined"); - } -} - -ZEND_API zval* zend_object_proxy_get(zval *property, zval *rv TSRMLS_DC) -{ - zend_proxy_object *probj = (zend_proxy_object*)Z_OBJ_P(property); - - if (Z_OBJ_HT(probj->object) && Z_OBJ_HT(probj->object)->read_property) { - return Z_OBJ_HT(probj->object)->read_property(&probj->object, &probj->property, BP_VAR_R, NULL, rv TSRMLS_CC); - } else { - zend_error(E_WARNING, "Cannot read property of object - no read handler defined"); - } - - return NULL; -} - ZEND_API zend_object_handlers *zend_get_std_object_handlers(void) { return &std_object_handlers; } -static zend_object_handlers zend_object_proxy_handlers = { - ZEND_OBJECTS_STORE_HANDLERS, - - NULL, /* read_property */ - NULL, /* write_property */ - NULL, /* read dimension */ - NULL, /* write_dimension */ - NULL, /* get_property_ptr_ptr */ - zend_object_proxy_get, /* get */ - zend_object_proxy_set, /* set */ - NULL, /* has_property */ - NULL, /* unset_property */ - NULL, /* has_dimension */ - NULL, /* unset_dimension */ - NULL, /* get_properties */ - NULL, /* get_method */ - NULL, /* call_method */ - NULL, /* get_constructor */ - NULL, /* get_class_entry */ - NULL, /* get_class_name */ - NULL, /* compare_objects */ - NULL, /* cast_object */ - NULL, /* count_elements */ -}; - - /* * Local variables: * tab-width: 4 diff --git a/Zend/zend_objects_API.h b/Zend/zend_objects_API.h index df22a26cc9..362d79a68c 100644 --- a/Zend/zend_objects_API.h +++ b/Zend/zend_objects_API.h @@ -37,14 +37,7 @@ } while (0) -#define OBJ_RELEASE(obj) do { \ - zend_object *_obj = (obj); \ - if (--GC_REFCOUNT(_obj) == 0) { \ - zend_objects_store_del(_obj TSRMLS_CC); \ - } else { \ - gc_possible_root(&_obj->gc TSRMLS_CC); \ - } \ - } while (0) +#define OBJ_RELEASE(obj) zend_object_release(obj TSRMLS_CC) typedef struct _zend_objects_store { zend_object **object_buckets; @@ -78,6 +71,15 @@ ZEND_API zend_object *zend_object_create_proxy(zval *object, zval *member TSRMLS ZEND_API zend_object_handlers *zend_get_std_object_handlers(void); END_EXTERN_C() +static zend_always_inline void zend_object_release(zend_object *obj TSRMLS_DC) +{ + if (--GC_REFCOUNT(obj) == 0) { + zend_objects_store_del(obj TSRMLS_CC); + } else if (UNEXPECTED(!GC_INFO(obj))) { + gc_possible_root(&obj->gc TSRMLS_CC); + } +} + #endif /* ZEND_OBJECTS_H */ /* diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index d57721e58b..5902abd4c5 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -100,16 +100,12 @@ void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_siz ZEND_API void destroy_zend_function(zend_function *function TSRMLS_DC) { - switch (function->type) { - case ZEND_USER_FUNCTION: - destroy_op_array((zend_op_array *) function TSRMLS_CC); - break; - case ZEND_INTERNAL_FUNCTION: - if (function->common.function_name) { - zend_string_release(function->common.function_name); - } - /* do nothing */ - break; + if (function->type == ZEND_USER_FUNCTION) { + destroy_op_array(&function->op_array TSRMLS_CC); + } else { + ZEND_ASSERT(function->type == ZEND_INTERNAL_FUNCTION); + ZEND_ASSERT(function->common.function_name); + zend_string_release(function->common.function_name); } } @@ -118,11 +114,18 @@ ZEND_API void zend_function_dtor(zval *zv) zend_function *function = Z_PTR_P(zv); TSRMLS_FETCH(); - destroy_zend_function(function TSRMLS_CC); - if (function->type == ZEND_INTERNAL_FUNCTION) { - pefree(function, 1); - } else if (!function->common.function_name) { - efree_size(function, sizeof(zend_op_array)); + if (function->type == ZEND_USER_FUNCTION) { + ZEND_ASSERT(function->common.function_name); + destroy_op_array(&function->op_array TSRMLS_CC); + /* op_arrays are allocated on arena, so we don't have to free them */ +//??? efree_size(function, sizeof(zend_op_array)); + } else { + ZEND_ASSERT(function->type == ZEND_INTERNAL_FUNCTION); + ZEND_ASSERT(function->common.function_name); + zend_string_release(function->common.function_name); + if (!(function->common.fn_flags & ZEND_ACC_ARENA_ALLOCATED)) { + pefree(function, 1); + } } } @@ -738,6 +741,7 @@ ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC) case ZEND_JMPZ_EX: case ZEND_JMPNZ_EX: case ZEND_JMP_SET: + case ZEND_COALESCE: case ZEND_NEW: case ZEND_FE_RESET: case ZEND_FE_FETCH: diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index 567d18c4aa..d6a7bf5aa6 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -84,7 +84,7 @@ ZEND_API int zend_atoi(const char *str, int str_len) /* {{{ */ int retval; if (!str_len) { - str_len = strlen(str); + str_len = (int)strlen(str); } retval = ZEND_STRTOL(str, NULL, 0); if (str_len>0) { @@ -112,7 +112,7 @@ ZEND_API zend_long zend_atol(const char *str, int str_len) /* {{{ */ zend_long retval; if (!str_len) { - str_len = strlen(str); + str_len = (int)strlen(str); } retval = ZEND_STRTOL(str, NULL, 0); if (str_len>0) { @@ -827,8 +827,6 @@ try_again: case IS_NULL: case IS_FALSE: return STR_EMPTY_ALLOC(); - case IS_STRING: - return zend_string_copy(Z_STR_P(op)); case IS_TRUE: return zend_string_init("1", 1, 0); case IS_RESOURCE: { @@ -868,6 +866,8 @@ try_again: case IS_REFERENCE: op = Z_REFVAL_P(op); goto try_again; + case IS_STRING: + return zend_string_copy(Z_STR_P(op)); EMPTY_SWITCH_DEFAULT_CASE() } return NULL; @@ -924,7 +924,7 @@ ZEND_API int add_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ * } else if (Z_ISREF_P(op2)) { op2 = Z_REFVAL_P(op2); } else if (!converted) { - ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_ADD); + ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_ADD, add_function); zendi_convert_scalar_to_number(op1, op1_copy, result); zendi_convert_scalar_to_number(op2, op2_copy, result); @@ -977,7 +977,7 @@ ZEND_API int sub_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ * } else if (Z_ISREF_P(op2)) { op2 = Z_REFVAL_P(op2); } else if (!converted) { - ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_SUB); + ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_SUB, sub_function); zendi_convert_scalar_to_number(op1, op1_copy, result); zendi_convert_scalar_to_number(op2, op2_copy, result); @@ -1024,7 +1024,7 @@ ZEND_API int mul_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ * } else if (Z_ISREF_P(op2)) { op2 = Z_REFVAL_P(op2); } else if (!converted) { - ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_MUL); + ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_MUL, mul_function); zendi_convert_scalar_to_number(op1, op1_copy, result); zendi_convert_scalar_to_number(op2, op2_copy, result); @@ -1102,7 +1102,7 @@ ZEND_API int pow_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ * } else if (Z_ISREF_P(op2)) { op2 = Z_REFVAL_P(op2); } else if (!converted) { - ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_POW); + ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_POW, pow_function); if (Z_TYPE_P(op1) == IS_ARRAY) { ZVAL_LONG(result, 0); @@ -1183,7 +1183,7 @@ ZEND_API int div_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ * } else if (Z_ISREF_P(op2)) { op2 = Z_REFVAL_P(op2); } else if (!converted) { - ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_DIV); + ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_DIV, div_function); zendi_convert_scalar_to_number(op1, op1_copy, result); zendi_convert_scalar_to_number(op2, op2_copy, result); @@ -1202,14 +1202,14 @@ ZEND_API int mod_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ * zval op1_copy, op2_copy; zend_long op1_lval; - if (Z_TYPE_P(op1) != IS_LONG || Z_TYPE_P(op2) != IS_LONG) { - ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_MOD); - + if (UNEXPECTED(Z_TYPE_P(op1) != IS_LONG)) { + ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_MOD, mod_function); zendi_convert_to_long(op1, op1_copy, result); - op1_lval = Z_LVAL_P(op1); + } + op1_lval = Z_LVAL_P(op1); + if (UNEXPECTED(Z_TYPE_P(op2) != IS_LONG)) { + ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_MOD); zendi_convert_to_long(op2, op2_copy, result); - } else { - op1_lval = Z_LVAL_P(op1); } if (Z_LVAL_P(op2) == 0) { @@ -1234,15 +1234,14 @@ ZEND_API int boolean_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) zval op1_copy, op2_copy; zend_long op1_lval; - if ((Z_TYPE_P(op1) != IS_FALSE && Z_TYPE_P(op1) != IS_TRUE) || - (Z_TYPE_P(op2) != IS_FALSE && Z_TYPE_P(op2) != IS_TRUE)) { - ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_BOOL_XOR); - + if (UNEXPECTED(Z_TYPE_P(op1) != IS_FALSE && Z_TYPE_P(op1) != IS_TRUE)) { + ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BOOL_XOR, boolean_xor_function); zendi_convert_to_boolean(op1, op1_copy, result); - op1_lval = Z_TYPE_P(op1) == IS_TRUE; + } + op1_lval = Z_TYPE_P(op1) == IS_TRUE; + if (UNEXPECTED(Z_TYPE_P(op2) != IS_FALSE && Z_TYPE_P(op2) != IS_TRUE)) { + ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_BOOL_XOR); zendi_convert_to_boolean(op2, op2_copy, result); - } else { - op1_lval = Z_TYPE_P(op1) == IS_TRUE; } ZVAL_BOOL(result, op1_lval ^ (Z_TYPE_P(op2) == IS_TRUE)); @@ -1281,11 +1280,10 @@ ZEND_API int bitwise_not_function(zval *result, zval *op1 TSRMLS_DC) /* {{{ */ return SUCCESS; case IS_STRING: { size_t i; - zval op1_copy = *op1; - ZVAL_NEW_STR(result, zend_string_alloc(Z_STRLEN(op1_copy), 0)); - for (i = 0; i < Z_STRLEN(op1_copy); i++) { - Z_STRVAL_P(result)[i] = ~Z_STRVAL(op1_copy)[i]; + ZVAL_NEW_STR(result, zend_string_alloc(Z_STRLEN_P(op1), 0)); + for (i = 0; i < Z_STRLEN_P(op1); i++) { + Z_STRVAL_P(result)[i] = ~Z_STRVAL_P(op1)[i]; } Z_STRVAL_P(result)[i] = 0; return SUCCESS; @@ -1329,14 +1327,14 @@ ZEND_API int bitwise_or_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) / return SUCCESS; } - if (Z_TYPE_P(op1) != IS_LONG || Z_TYPE_P(op2) != IS_LONG) { - ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_BW_OR); - + if (UNEXPECTED(Z_TYPE_P(op1) != IS_LONG)) { + ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BW_OR, bitwise_or_function); zendi_convert_to_long(op1, op1_copy, result); - op1_lval = Z_LVAL_P(op1); + } + op1_lval = Z_LVAL_P(op1); + if (UNEXPECTED(Z_TYPE_P(op2) != IS_LONG)) { + ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_BW_OR); zendi_convert_to_long(op2, op2_copy, result); - } else { - op1_lval = Z_LVAL_P(op1); } ZVAL_LONG(result, op1_lval | Z_LVAL_P(op2)); @@ -1374,14 +1372,14 @@ ZEND_API int bitwise_and_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) return SUCCESS; } - if (Z_TYPE_P(op1) != IS_LONG || Z_TYPE_P(op2) != IS_LONG) { - ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_BW_AND); - + if (UNEXPECTED(Z_TYPE_P(op1) != IS_LONG)) { + ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BW_AND, bitwise_and_function); zendi_convert_to_long(op1, op1_copy, result); - op1_lval = Z_LVAL_P(op1); + } + op1_lval = Z_LVAL_P(op1); + if (UNEXPECTED(Z_TYPE_P(op2) != IS_LONG)) { + ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_BW_AND); zendi_convert_to_long(op2, op2_copy, result); - } else { - op1_lval = Z_LVAL_P(op1); } ZVAL_LONG(result, op1_lval & Z_LVAL_P(op2)); @@ -1419,14 +1417,14 @@ ZEND_API int bitwise_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) return SUCCESS; } - if (Z_TYPE_P(op1) != IS_LONG || Z_TYPE_P(op2) != IS_LONG) { - ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_BW_XOR); - + if (UNEXPECTED(Z_TYPE_P(op1) != IS_LONG)) { + ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BW_XOR, bitwise_xor_function); zendi_convert_to_long(op1, op1_copy, result); - op1_lval = Z_LVAL_P(op1); + } + op1_lval = Z_LVAL_P(op1); + if (UNEXPECTED(Z_TYPE_P(op2) != IS_LONG)) { + ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_BW_XOR); zendi_convert_to_long(op2, op2_copy, result); - } else { - op1_lval = Z_LVAL_P(op1); } ZVAL_LONG(result, op1_lval ^ Z_LVAL_P(op2)); @@ -1439,14 +1437,14 @@ ZEND_API int shift_left_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) / zval op1_copy, op2_copy; zend_long op1_lval; - if (Z_TYPE_P(op1) != IS_LONG || Z_TYPE_P(op2) != IS_LONG) { - ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_SL); - + if (UNEXPECTED(Z_TYPE_P(op1) != IS_LONG)) { + ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_SL, shift_left_function); zendi_convert_to_long(op1, op1_copy, result); - op1_lval = Z_LVAL_P(op1); + } + op1_lval = Z_LVAL_P(op1); + if (UNEXPECTED(Z_TYPE_P(op2) != IS_LONG)) { + ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_SL); zendi_convert_to_long(op2, op2_copy, result); - } else { - op1_lval = Z_LVAL_P(op1); } /* prevent wrapping quirkiness on some processors where << 64 + x == << x */ @@ -1471,14 +1469,14 @@ ZEND_API int shift_right_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) zval op1_copy, op2_copy; zend_long op1_lval; - if (Z_TYPE_P(op1) != IS_LONG || Z_TYPE_P(op2) != IS_LONG) { - ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_SR); - + if (UNEXPECTED(Z_TYPE_P(op1) != IS_LONG)) { + ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_SR, shift_right_function); zendi_convert_to_long(op1, op1_copy, result); - op1_lval = Z_LVAL_P(op1); + } + op1_lval = Z_LVAL_P(op1); + if (UNEXPECTED(Z_TYPE_P(op2) != IS_LONG)) { + ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_SR); zendi_convert_to_long(op2, op2_copy, result); - } else { - op1_lval = Z_LVAL_P(op1); } /* prevent wrapping quirkiness on some processors where >> 64 + x == >> x */ @@ -1530,29 +1528,28 @@ ZEND_API int concat_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{ zval op1_copy, op2_copy; int use_copy1 = 0, use_copy2 = 0; - if (UNEXPECTED(Z_TYPE_P(op1) != IS_STRING) || - UNEXPECTED(Z_TYPE_P(op2) != IS_STRING)) { - ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_CONCAT); - - if (Z_TYPE_P(op1) != IS_STRING) { - use_copy1 = zend_make_printable_zval(op1, &op1_copy TSRMLS_CC); - } - if (Z_TYPE_P(op2) != IS_STRING) { - use_copy2 = zend_make_printable_zval(op2, &op2_copy TSRMLS_CC); + if (UNEXPECTED(Z_TYPE_P(op1) != IS_STRING)) { + ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_CONCAT, concat_function); + use_copy1 = zend_make_printable_zval(op1, &op1_copy TSRMLS_CC); + if (use_copy1) { + /* We have created a converted copy of op1. Therefore, op1 won't become the result so + * we have to free it. + */ + if (result == op1) { + zval_dtor(op1); + if (UNEXPECTED(op1 == op2)) { + op2 = &op1_copy; + } + } + op1 = &op1_copy; } } - - if (use_copy1) { - /* We have created a converted copy of op1. Therefore, op1 won't become the result so - * we have to free it. - */ - if (result == op1) { - zval_dtor(op1); + if (UNEXPECTED(Z_TYPE_P(op2) != IS_STRING)) { + ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_CONCAT); + use_copy2 = zend_make_printable_zval(op2, &op2_copy TSRMLS_CC); + if (use_copy2) { + op2 = &op2_copy; } - op1 = &op1_copy; - } - if (use_copy2) { - op2 = &op2_copy; } { @@ -2159,7 +2156,19 @@ try_again: } break; case IS_OBJECT: - if (Z_OBJ_HANDLER_P(op1, do_operation)) { + if (Z_OBJ_HANDLER_P(op1, get) + && Z_OBJ_HANDLER_P(op1, set)) { + /* proxy object */ + zval rv; + zval *val; + TSRMLS_FETCH(); + + val = Z_OBJ_HANDLER_P(op1, get)(op1, &rv TSRMLS_CC); + Z_ADDREF_P(val); + fast_increment_function(val); + Z_OBJ_HANDLER_P(op1, set)(op1, val TSRMLS_CC); + zval_ptr_dtor(val); + } else if (Z_OBJ_HANDLER_P(op1, do_operation)) { zval op2; int res; TSRMLS_FETCH(); @@ -2222,7 +2231,19 @@ try_again: } break; case IS_OBJECT: - if (Z_OBJ_HANDLER_P(op1, do_operation)) { + if (Z_OBJ_HANDLER_P(op1, get) + && Z_OBJ_HANDLER_P(op1, set)) { + /* proxy object */ + zval rv; + zval *val; + TSRMLS_FETCH(); + + val = Z_OBJ_HANDLER_P(op1, get)(op1, &rv TSRMLS_CC); + Z_ADDREF_P(val); + fast_decrement_function(val); + Z_OBJ_HANDLER_P(op1, set)(op1, val TSRMLS_CC); + zval_ptr_dtor(val); + } else if (Z_OBJ_HANDLER_P(op1, do_operation)) { zval op2; int res; TSRMLS_FETCH(); diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h index adb30f603f..f95e856e68 100644 --- a/Zend/zend_operators.h +++ b/Zend/zend_operators.h @@ -69,6 +69,24 @@ ZEND_API int is_smaller_or_equal_function(zval *result, zval *op1, zval *op2 TSR ZEND_API zend_bool instanceof_function_ex(const zend_class_entry *instance_ce, const zend_class_entry *ce, zend_bool interfaces_only TSRMLS_DC); ZEND_API zend_bool instanceof_function(const zend_class_entry *instance_ce, const zend_class_entry *ce TSRMLS_DC); + +/** + * Checks whether the string "str" with length "length" is numeric. The value + * of allow_errors determines whether it's required to be entirely numeric, or + * just its prefix. Leading whitespace is allowed. + * + * The function returns 0 if the string did not contain a valid number; IS_LONG + * if it contained a number that fits within the range of a long; or IS_DOUBLE + * if the number was out of long range or contained a decimal point/exponent. + * The number's value is returned into the respective pointer, *lval or *dval, + * if that pointer is not NULL. + * + * This variant also gives information if a string that represents an integer + * could not be represented as such due to overflow. It writes 1 to oflow_info + * if the integer is larger than ZEND_LONG_MAX and -1 if it's smaller than ZEND_LONG_MIN. + */ +ZEND_API zend_uchar _is_numeric_string_ex(const char *str, size_t length, zend_long *lval, double *dval, int allow_errors, int *oflow_info); + END_EXTERN_C() #if ZEND_DVAL_TO_LVAL_CAST_OK @@ -125,23 +143,6 @@ static zend_always_inline zend_long zend_dval_to_lval(double d) #define ZEND_IS_DIGIT(c) ((c) >= '0' && (c) <= '9') #define ZEND_IS_XDIGIT(c) (((c) >= 'A' && (c) <= 'F') || ((c) >= 'a' && (c) <= 'f')) -/** - * Checks whether the string "str" with length "length" is numeric. The value - * of allow_errors determines whether it's required to be entirely numeric, or - * just its prefix. Leading whitespace is allowed. - * - * The function returns 0 if the string did not contain a valid number; IS_LONG - * if it contained a number that fits within the range of a long; or IS_DOUBLE - * if the number was out of long range or contained a decimal point/exponent. - * The number's value is returned into the respective pointer, *lval or *dval, - * if that pointer is not NULL. - * - * This variant also gives information if a string that represents an integer - * could not be represented as such due to overflow. It writes 1 to oflow_info - * if the integer is larger than ZEND_LONG_MAX and -1 if it's smaller than ZEND_LONG_MIN. - */ -ZEND_API zend_uchar _is_numeric_string_ex(const char *str, size_t length, zend_long *lval, double *dval, int allow_errors, int *oflow_info); - static zend_always_inline zend_uchar is_numeric_string_ex(const char *str, size_t length, zend_long *lval, double *dval, int allow_errors, int *oflow_info) { if (*str > '9') { @@ -285,7 +286,6 @@ ZEND_API int zend_atoi(const char *str, int str_len); ZEND_API zend_long zend_atol(const char *str, int str_len); ZEND_API void zend_locale_sprintf_double(zval *op ZEND_FILE_LINE_DC); -END_EXTERN_C() #define convert_to_ex_master(pzv, lower_type, upper_type) \ if (Z_TYPE_P(pzv)!=upper_type) { \ @@ -887,22 +887,43 @@ static zend_always_inline void fast_is_not_identical_function(zval *result, zval ZVAL_BOOL(result, Z_TYPE_P(result) != IS_TRUE); } -#define ZEND_TRY_BINARY_OBJECT_OPERATION(opcode) \ - if (Z_TYPE_P(op1) == IS_OBJECT && Z_OBJ_HANDLER_P(op1, do_operation)) { \ - if (SUCCESS == Z_OBJ_HANDLER_P(op1, do_operation)(opcode, result, op1, op2 TSRMLS_CC)) { \ - return SUCCESS; \ - } \ - } else if (Z_TYPE_P(op2) == IS_OBJECT && Z_OBJ_HANDLER_P(op2, do_operation)) { \ - if (SUCCESS == Z_OBJ_HANDLER_P(op2, do_operation)(opcode, result, op1, op2 TSRMLS_CC)) { \ - return SUCCESS; \ - } \ +#define ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(opcode, binary_op) \ + if (UNEXPECTED(Z_TYPE_P(op1) == IS_OBJECT) \ + && op1 == result \ + && UNEXPECTED(Z_OBJ_HANDLER_P(op1, get)) \ + && EXPECTED(Z_OBJ_HANDLER_P(op1, set))) { \ + int ret; \ + zval rv; \ + zval *objval = Z_OBJ_HANDLER_P(op1, get)(op1, &rv TSRMLS_CC); \ + Z_ADDREF_P(objval); \ + ret = binary_op(objval, objval, op2 TSRMLS_CC); \ + Z_OBJ_HANDLER_P(op1, set)(op1, objval TSRMLS_CC); \ + zval_ptr_dtor(objval); \ + return ret; \ + } else if (UNEXPECTED(Z_TYPE_P(op1) == IS_OBJECT) \ + && UNEXPECTED(Z_OBJ_HANDLER_P(op1, do_operation))) { \ + if (EXPECTED(SUCCESS == Z_OBJ_HANDLER_P(op1, do_operation)(opcode, result, op1, op2 TSRMLS_CC))) { \ + return SUCCESS; \ + } \ } -#define ZEND_TRY_UNARY_OBJECT_OPERATION(opcode) \ - if (Z_TYPE_P(op1) == IS_OBJECT && Z_OBJ_HANDLER_P(op1, do_operation) \ - && SUCCESS == Z_OBJ_HANDLER_P(op1, do_operation)(opcode, result, op1, NULL TSRMLS_CC) \ - ) { \ - return SUCCESS; \ +#define ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(opcode) \ + if (UNEXPECTED(Z_TYPE_P(op2) == IS_OBJECT) \ + && UNEXPECTED(Z_OBJ_HANDLER_P(op2, do_operation)) \ + && EXPECTED(SUCCESS == Z_OBJ_HANDLER_P(op2, do_operation)(opcode, result, op1, op2 TSRMLS_CC))) { \ + return SUCCESS; \ + } + +#define ZEND_TRY_BINARY_OBJECT_OPERATION(opcode, binary_op) \ + ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(opcode, binary_op) \ + else \ + ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(opcode) + +#define ZEND_TRY_UNARY_OBJECT_OPERATION(opcode) \ + if (UNEXPECTED(Z_TYPE_P(op1) == IS_OBJECT) \ + && UNEXPECTED(Z_OBJ_HANDLER_P(op1, do_operation)) \ + && EXPECTED(SUCCESS == Z_OBJ_HANDLER_P(op1, do_operation)(opcode, result, op1, NULL TSRMLS_CC))) { \ + return SUCCESS; \ } /* buf points to the END of the buffer */ @@ -928,6 +949,8 @@ static zend_always_inline char *zend_print_long_to_buf(char *buf, zend_long num) ZEND_API zend_string *zend_long_to_str(zend_long num); +END_EXTERN_C() + #endif /* diff --git a/Zend/zend_static_allocator.c b/Zend/zend_static_allocator.c deleted file mode 100644 index 049d29f6a2..0000000000 --- a/Zend/zend_static_allocator.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | Zend Engine | - +----------------------------------------------------------------------+ - | Copyright (c) 1998-2014 Zend Technologies Ltd. (http://www.zend.com) | - +----------------------------------------------------------------------+ - | This source file is subject to version 2.00 of the Zend license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.zend.com/license/2_00.txt. | - | If you did not receive a copy of the Zend license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@zend.com so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Authors: Andi Gutmans <andi@zend.com> | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#include "zend_static_allocator.h" - -/* Not checking emalloc() and erealloc() return values as they are supposed to bailout */ - -inline static void block_init(Block *block, uint32_t block_size) -{ - block->pos = block->bp = (char *) emalloc(block_size); - block->end = block->bp + block_size; -} - -inline static char *block_allocate(Block *block, uint32_t size) -{ - char *retval = block->pos; - if ((block->pos += size) >= block->end) { - return (char *)NULL; - } - return retval; -} - -inline static void block_destroy(Block *block) -{ - efree(block->bp); -} - -void static_allocator_init(StaticAllocator *sa) -{ - sa->Blocks = (Block *) emalloc(sizeof(Block)); - block_init(sa->Blocks, ALLOCATOR_BLOCK_SIZE); - sa->num_blocks = 1; - sa->current_block = 0; -} - -char *static_allocator_allocate(StaticAllocator *sa, uint32_t size) -{ - char *retval; - - retval = block_allocate(&sa->Blocks[sa->current_block], size); - if (retval) { - return retval; - } - sa->Blocks = (Block *) erealloc(sa->Blocks, ++sa->num_blocks); - sa->current_block++; - block_init(&sa->Blocks[sa->current_block], (size > ALLOCATOR_BLOCK_SIZE) ? size : ALLOCATOR_BLOCK_SIZE); - retval = block_allocate(&sa->Blocks[sa->current_block], size); - return retval; -} - -void static_allocator_destroy(StaticAllocator *sa) -{ - uint32_t i; - - for (i=0; i<sa->num_blocks; i++) { - block_free(&sa->Blocks[i]); - } - efree(sa->Blocks); -} - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * indent-tabs-mode: t - * End: - */ diff --git a/Zend/zend_static_allocator.h b/Zend/zend_static_allocator.h deleted file mode 100644 index cd9b0ff583..0000000000 --- a/Zend/zend_static_allocator.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | Zend Engine | - +----------------------------------------------------------------------+ - | Copyright (c) 1998-2014 Zend Technologies Ltd. (http://www.zend.com) | - +----------------------------------------------------------------------+ - | This source file is subject to version 2.00 of the Zend license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.zend.com/license/2_00.txt. | - | If you did not receive a copy of the Zend license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@zend.com so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Authors: Andi Gutmans <andi@zend.com> | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#ifndef ZEND_STATIC_ALLOCATOR_H -#define ZEND_STATIC_ALLOCATOR_H - -#define ALLOCATOR_BLOCK_SIZE 400000 - -/* Temporary */ -typedef unsigned int uint32_t; -#define emalloc(s) malloc(s) -#define efree(p) free(p) - -typedef struct _Block { - char *bp; - char *pos; - char *end; -} Block; - -typedef struct _StaticAllocator { - Block *Blocks; - uint32_t num_blocks; - uint32_t current_block; -} StaticAllocator; - -void static_allocator_init(StaticAllocator *sa); -char *static_allocator_allocate(StaticAllocator *sa, uint32_t size); -void static_allocator_destroy(StaticAllocator *sa); - -#endif /* ZEND_STATIC_ALLOCATOR_H */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * indent-tabs-mode: t - * End: - */ diff --git a/Zend/zend_string.c b/Zend/zend_string.c index a4455e8da9..1833bbd241 100644 --- a/Zend/zend_string.c +++ b/Zend/zend_string.c @@ -45,9 +45,9 @@ static void _str_dtor(zval *zv) void zend_interned_strings_init(TSRMLS_D) { +#ifndef ZTS zend_string *str; -#ifndef ZTS zend_hash_init(&CG(interned_strings), 1024, NULL, _str_dtor, 1); CG(interned_strings).nTableMask = CG(interned_strings).nTableSize - 1; @@ -59,12 +59,6 @@ void zend_interned_strings_init(TSRMLS_D) str = zend_string_alloc(sizeof("")-1, 1); str->val[0] = '\000'; CG(empty_string) = zend_new_interned_string_int(str TSRMLS_CC); -#else - str = zend_string_alloc(sizeof("")-1, 1); - str->val[0] = '\000'; - zend_string_hash_val(str); - str->gc.u.v.flags |= IS_STR_INTERNED; - CG(empty_string) = str; #endif /* one char strings (the actual interned strings are going to be created by ext/opcache) */ @@ -79,8 +73,6 @@ void zend_interned_strings_dtor(TSRMLS_D) { #ifndef ZTS zend_hash_destroy(&CG(interned_strings)); -#else - zend_string_release(CG(empty_string)); #endif } diff --git a/Zend/zend_string.h b/Zend/zend_string.h index d30e14b5b3..1da3b511c0 100644 --- a/Zend/zend_string.h +++ b/Zend/zend_string.h @@ -282,6 +282,30 @@ EMPTY_SWITCH_DEFAULT_CASE() return hash; } +static zend_always_inline void zend_interned_empty_string_init(zend_string **s TSRMLS_DC) +{ + zend_string *str; + + str = zend_string_alloc(sizeof("")-1, 1); + str->val[0] = '\000'; + +#ifndef ZTS + *s = zend_new_interned_string(str TSRMLS_CC); +#else + zend_string_hash_val(str); + str->gc.u.v.flags |= IS_STR_INTERNED; + *s = str; +#endif +} + +static zend_always_inline void zend_interned_empty_string_free(zend_string **s TSRMLS_DC) +{ + if (NULL != *s) { + free(*s); + *s = NULL; + } +} + #endif /* ZEND_STRING_H */ /* diff --git a/Zend/zend_ts_hash.c b/Zend/zend_ts_hash.c index 43f02b48f8..dd7aaeb9a7 100644 --- a/Zend/zend_ts_hash.c +++ b/Zend/zend_ts_hash.c @@ -333,7 +333,7 @@ ZEND_API int zend_ts_hash_rehash(TsHashTable *ht) return retval; } -ZEND_API zval *zend_ts_hash_str_find(TsHashTable *ht, const char *key, int len) +ZEND_API zval *zend_ts_hash_str_find(TsHashTable *ht, const char *key, size_t len) { zval *retval; @@ -344,7 +344,7 @@ ZEND_API zval *zend_ts_hash_str_find(TsHashTable *ht, const char *key, int len) return retval; } -ZEND_API zval *_zend_ts_hash_str_update(TsHashTable *ht, const char *key, int len, zval *pData ZEND_FILE_LINE_DC) +ZEND_API zval *_zend_ts_hash_str_update(TsHashTable *ht, const char *key, size_t len, zval *pData ZEND_FILE_LINE_DC) { zval *retval; @@ -355,7 +355,7 @@ ZEND_API zval *_zend_ts_hash_str_update(TsHashTable *ht, const char *key, int le return retval; } -ZEND_API zval *_zend_ts_hash_str_add(TsHashTable *ht, const char *key, int len, zval *pData ZEND_FILE_LINE_DC) +ZEND_API zval *_zend_ts_hash_str_add(TsHashTable *ht, const char *key, size_t len, zval *pData ZEND_FILE_LINE_DC) { zval *retval; diff --git a/Zend/zend_ts_hash.h b/Zend/zend_ts_hash.h index 6cb36410b8..4bac7db205 100644 --- a/Zend/zend_ts_hash.h +++ b/Zend/zend_ts_hash.h @@ -102,16 +102,16 @@ void zend_ts_hash_display_pListTail(TsHashTable *ht); void zend_ts_hash_display(TsHashTable *ht); #endif -ZEND_API zval *zend_ts_hash_str_find(TsHashTable *ht, const char *key, int len); -ZEND_API zval *_zend_ts_hash_str_update(TsHashTable *ht, const char *key, int len, zval *pData ZEND_FILE_LINE_DC); -ZEND_API zval *_zend_ts_hash_str_add(TsHashTable *ht, const char *key, int len, zval *pData ZEND_FILE_LINE_DC); +ZEND_API zval *zend_ts_hash_str_find(TsHashTable *ht, const char *key, size_t len); +ZEND_API zval *_zend_ts_hash_str_update(TsHashTable *ht, const char *key, size_t len, zval *pData ZEND_FILE_LINE_DC); +ZEND_API zval *_zend_ts_hash_str_add(TsHashTable *ht, const char *key, size_t len, zval *pData ZEND_FILE_LINE_DC); #define zend_ts_hash_str_update(ht, key, len, pData) \ _zend_ts_hash_str_update(ht, key, len, pData ZEND_FILE_LINE_CC) #define zend_ts_hash_str_add(ht, key, len, pData) \ _zend_ts_hash_str_add(ht, key, len, pData ZEND_FILE_LINE_CC) -static zend_always_inline void *zend_ts_hash_str_find_ptr(TsHashTable *ht, const char *str, int len) +static zend_always_inline void *zend_ts_hash_str_find_ptr(TsHashTable *ht, const char *str, size_t len) { zval *zv; @@ -119,7 +119,7 @@ static zend_always_inline void *zend_ts_hash_str_find_ptr(TsHashTable *ht, const return zv ? Z_PTR_P(zv) : NULL; } -static zend_always_inline void *zend_ts_hash_str_update_ptr(TsHashTable *ht, const char *str, int len, void *pData) +static zend_always_inline void *zend_ts_hash_str_update_ptr(TsHashTable *ht, const char *str, size_t len, void *pData) { zval tmp, *zv; @@ -128,7 +128,7 @@ static zend_always_inline void *zend_ts_hash_str_update_ptr(TsHashTable *ht, con return zv ? Z_PTR_P(zv) : NULL; } -static zend_always_inline void *zend_ts_hash_str_add_ptr(TsHashTable *ht, const char *str, int len, void *pData) +static zend_always_inline void *zend_ts_hash_str_add_ptr(TsHashTable *ht, const char *str, size_t len, void *pData) { zval tmp, *zv; diff --git a/Zend/zend_types.h b/Zend/zend_types.h index c654106192..383f77caa4 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -64,32 +64,13 @@ typedef enum { # endif #endif -#define HAVE_ZEND_LONG64 -#ifdef ZEND_WIN32 -typedef __int64 zend_long64; -typedef unsigned __int64 zend_ulong64; -#elif SIZEOF_LONG_LONG_INT == 8 -typedef long long int zend_long64; -typedef unsigned long long int zend_ulong64; -#elif SIZEOF_LONG_LONG == 8 -typedef long long zend_long64; -typedef unsigned long long zend_ulong64; -#else -# undef HAVE_ZEND_LONG64 -#endif - -/* XXX this won't work on X32 platform */ -#ifdef ZEND_ENABLE_ZVAL_LONG64 -typedef int64_t zend_intptr_t; -typedef uint64_t zend_uintptr_t; -#else -typedef int32_t zend_intptr_t; -typedef uint32_t zend_uintptr_t; -#endif +typedef intptr_t zend_intptr_t; +typedef uintptr_t zend_uintptr_t; typedef struct _zend_object_handlers zend_object_handlers; typedef struct _zend_class_entry zend_class_entry; typedef union _zend_function zend_function; +typedef struct _zend_execute_data zend_execute_data; typedef struct _zval_struct zval; @@ -140,7 +121,6 @@ struct _zval_struct { uint32_t next; /* hash collision chain */ uint32_t cache_slot; /* literal cache slot */ uint32_t lineno; /* line number (for ast nodes) */ - uint32_t silence_num; /* BEGIN_SILENCE op number */ } u2; }; @@ -438,7 +418,7 @@ static zend_always_inline zend_uchar zval_get_type(const zval* pz) { #define Z_OBJ_HANDLE(zval) (Z_OBJ((zval)))->handle #define Z_OBJ_HANDLE_P(zval_p) Z_OBJ_HANDLE(*(zval_p)) -#define Z_OBJCE(zval) zend_get_class_entry(Z_OBJ(zval) TSRMLS_CC) +#define Z_OBJCE(zval) (Z_OBJ(zval)->ce) #define Z_OBJCE_P(zval_p) Z_OBJCE(*(zval_p)) #define Z_OBJPROP(zval) Z_OBJ_HT((zval))->get_properties(&(zval) TSRMLS_CC) @@ -783,6 +763,7 @@ static zend_always_inline uint32_t zval_delref_p(zval* pz) { #define SEPARATE_ZVAL_NOREF(zv) do { \ zval *_zv = (zv); \ + ZEND_ASSERT(Z_TYPE_P(_zv) != IS_REFERENCE); \ if (Z_COPYABLE_P(_zv) || \ Z_IMMUTABLE_P(_zv)) { \ if (Z_REFCOUNT_P(_zv) > 1) { \ diff --git a/Zend/zend_variables.c b/Zend/zend_variables.c index 3e68a38487..aae8465791 100644 --- a/Zend/zend_variables.c +++ b/Zend/zend_variables.c @@ -221,7 +221,7 @@ ZEND_API void zval_add_ref_unref(zval *p) { if (Z_REFCOUNTED_P(p)) { if (Z_ISREF_P(p)) { - ZVAL_DUP(p, Z_REFVAL_P(p)); + ZVAL_COPY(p, Z_REFVAL_P(p)); } else { Z_ADDREF_P(p); } @@ -266,7 +266,7 @@ ZEND_API void _zval_copy_ctor_func(zval *zvalue ZEND_FILE_LINE_DC) } -ZEND_API int zend_print_variable(zval *var TSRMLS_DC) +ZEND_API size_t zend_print_variable(zval *var TSRMLS_DC) { return zend_print_zval(var, 0 TSRMLS_CC); } diff --git a/Zend/zend_variables.h b/Zend/zend_variables.h index 94ae438e9d..4f840bdd8a 100644 --- a/Zend/zend_variables.h +++ b/Zend/zend_variables.h @@ -93,7 +93,7 @@ static zend_always_inline void _zval_opt_copy_ctor_no_imm(zval *zvalue ZEND_FILE ZEND_API int zval_copy_static_var(zval *p TSRMLS_DC, int num_args, va_list args, zend_hash_key *key); -ZEND_API int zend_print_variable(zval *var TSRMLS_DC); +ZEND_API size_t zend_print_variable(zval *var TSRMLS_DC); ZEND_API void _zval_ptr_dtor(zval *zval_ptr ZEND_FILE_LINE_DC); ZEND_API void _zval_internal_dtor_for_ptr(zval *zvalue ZEND_FILE_LINE_DC); ZEND_API void _zval_internal_dtor(zval *zvalue ZEND_FILE_LINE_DC); diff --git a/Zend/zend_virtual_cwd.c b/Zend/zend_virtual_cwd.c index b061d5a00d..385df393bf 100644 --- a/Zend/zend_virtual_cwd.c +++ b/Zend/zend_virtual_cwd.c @@ -294,7 +294,7 @@ CWD_API int php_sys_readlink(const char *link, char *target, size_t target_len){ CWD_API int php_sys_stat_ex(const char *path, zend_stat_t *buf, int lstat) /* {{{ */ { WIN32_FILE_ATTRIBUTE_DATA data; - __int64 t; + LARGE_INTEGER t; const size_t path_len = strlen(path); ALLOCA_FLAG(use_heap_large); @@ -380,7 +380,7 @@ CWD_API int php_sys_stat_ex(const char *path, zend_stat_t *buf, int lstat) /* {{ } if ((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) { - int len = strlen(path); + size_t len = strlen(path); if (path[len-4] == '.') { if (_memicmp(path+len-3, "exe", 3) == 0 || @@ -393,10 +393,11 @@ CWD_API int php_sys_stat_ex(const char *path, zend_stat_t *buf, int lstat) /* {{ } buf->st_nlink = 1; - t = data.nFileSizeHigh; - t = t << 32; - t |= data.nFileSizeLow; - buf->st_size = t; + t.HighPart = data.nFileSizeHigh; + t.LowPart = data.nFileSizeLow; + /* It's an overflow on 32 bit, however it won't fix as long + as zend_long is 32 bit. */ + buf->st_size = (zend_long)t.QuadPart; buf->st_atime = FileTimeToUnixTime(&data.ftLastAccessTime); buf->st_ctime = FileTimeToUnixTime(&data.ftCreationTime); buf->st_mtime = FileTimeToUnixTime(&data.ftLastWriteTime); @@ -466,7 +467,7 @@ CWD_API void virtual_cwd_startup(void) /* {{{ */ cwd[0] = '\0'; } - main_cwd_state.cwd_length = strlen(cwd); + main_cwd_state.cwd_length = (int)strlen(cwd); #ifdef TSRM_WIN32 if (main_cwd_state.cwd_length >= 2 && cwd[1] == ':') { cwd[0] = toupper(cwd[0]); @@ -1145,7 +1146,7 @@ static int tsrm_realpath_r(char *path, int start, int len, int *ll, time_t *t, i return -1; } if (save) { - i = strlen(data.cFileName); + i = (int)strlen(data.cFileName); memcpy(path+j, data.cFileName, i+1); j += i; } else { @@ -1179,7 +1180,7 @@ static int tsrm_realpath_r(char *path, int start, int len, int *ll, time_t *t, i /* returns 0 for ok, 1 for error */ CWD_API int virtual_file_ex(cwd_state *state, const char *path, verify_path_func verify_path, int use_realpath TSRMLS_DC) /* {{{ */ { - int path_length = strlen(path); + int path_length = (int)strlen(path); char resolved_path[MAXPATHLEN]; int start = 1; int ll = 0; @@ -1393,7 +1394,7 @@ CWD_API int virtual_chdir(const char *path TSRMLS_DC) /* {{{ */ CWD_API int virtual_chdir_file(const char *path, int (*p_chdir)(const char *path TSRMLS_DC) TSRMLS_DC) /* {{{ */ { - int length = strlen(path); + int length = (int)strlen(path); char *temp; int retval; ALLOCA_FLAG(use_heap) @@ -1971,7 +1972,7 @@ CWD_API char *tsrm_realpath(const char *path, char *real_path TSRMLS_DC) /* {{{ } else if (!IS_ABSOLUTE_PATH(path, strlen(path)) && VCWD_GETCWD(cwd, MAXPATHLEN)) { new_state.cwd = estrdup(cwd); - new_state.cwd_length = strlen(cwd); + new_state.cwd_length = (int)strlen(cwd); } else { new_state.cwd = (char*)emalloc(1); if (new_state.cwd == NULL) { diff --git a/Zend/zend_virtual_cwd.h b/Zend/zend_virtual_cwd.h index f40a2deb7e..96ac6faa30 100644 --- a/Zend/zend_virtual_cwd.h +++ b/Zend/zend_virtual_cwd.h @@ -70,7 +70,7 @@ typedef unsigned short mode_t; #define IS_UNC_PATH(path, len) \ (len >= 2 && IS_SLASH(path[0]) && IS_SLASH(path[1])) #define IS_ABSOLUTE_PATH(path, len) \ - (len >= 2 && ((/* is local */isalpha(path[0]) && path[1] == ':') || /* is UNC */IS_SLASH(path[0]) && IS_SLASH(path[1]))) + (len >= 2 && (/* is local */isalpha(path[0]) && path[1] == ':' || /* is UNC */IS_SLASH(path[0]) && IS_SLASH(path[1]))) #elif defined(NETWARE) #ifdef HAVE_DIRENT_H diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index b25ab4e8be..fad38c6428 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -333,17 +333,19 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMP|VAR zval *object = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW); zval *property = GET_OP2_ZVAL_PTR(BP_VAR_R); zval *value; - int have_get_ptr = 0; + zval *zptr; if (OP1_TYPE == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - object = make_real_object(object TSRMLS_CC); + if (OP1_TYPE != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); + } - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to assign property of non-object"); FREE_OP2(); FREE_OP(free_op_data1); @@ -354,20 +356,17 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMP|VAR } else { /* here we are sure we are dealing with an object */ if (opline->extended_value == ZEND_ASSIGN_OBJ - && Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - SEPARATE_ZVAL_IF_NOT_REF(zptr); + && EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - have_get_ptr = 1; - binary_op(zptr, zptr, value TSRMLS_CC); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), zptr); - } - } - } + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + binary_op(zptr, zptr, value TSRMLS_CC); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); + } + } else { zval *z = NULL; zval rv; @@ -424,15 +423,19 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMP|VAR ZEND_VM_HELPER_EX(zend_binary_assign_op_dim_helper, VAR|UNUSED|CV, CONST|TMP|VAR|UNUSED|CV, int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC)) { USE_OPLINE - zend_free_op free_op1, free_op2, free_op_data2, free_op_data1; - zval *var_ptr; + zend_free_op free_op1, free_op2, free_op_data1; + zval *var_ptr, rv; zval *value, *container; SAVE_OPLINE(); container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW); if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } + if (OP1_TYPE != IS_UNUSED) { + ZVAL_DEREF(container); + } + if (OP1_TYPE == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (OP1_TYPE == IS_VAR && !OP1_FREE) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } @@ -440,9 +443,10 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_dim_helper, VAR|UNUSED|CV, CONST|TMP|VAR } else { zval *dim = GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R); - zend_fetch_dimension_address_RW(EX_VAR((opline+1)->op2.var), container, dim, OP2_TYPE TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + zend_fetch_dimension_address_RW(&rv, container, dim, OP2_TYPE TSRMLS_CC); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); } if (UNEXPECTED(var_ptr == NULL)) { @@ -453,33 +457,19 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_dim_helper, VAR|UNUSED|CV, CONST|TMP|VAR if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - ZEND_VM_C_GOTO(assign_op_dim_exit); - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -ZEND_VM_C_LABEL(assign_op_dim_exit): FREE_OP2(); FREE_OP(free_op_data1); - FREE_OP_VAR_PTR(free_op_data2); FREE_OP1_VAR_PTR(); CHECK_EXCEPTION(); ZEND_VM_INC_OPCODE(); @@ -494,7 +484,7 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_helper, VAR|UNUSED|CV, CONST|TMP|VAR|UNU zval *value; SAVE_OPLINE(); - value = GET_OP2_ZVAL_PTR(BP_VAR_R); + value = GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R); var_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW); if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == NULL)) { @@ -505,30 +495,17 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_helper, VAR|UNUSED|CV, CONST|TMP|VAR|UNU if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - ZEND_VM_C_GOTO(assign_op_exit); - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -ZEND_VM_C_LABEL(assign_op_exit): FREE_OP2(); FREE_OP1_VAR_PTR(); CHECK_EXCEPTION(); @@ -685,7 +662,7 @@ ZEND_VM_HELPER_EX(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMP|VAR| zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); object = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW); @@ -696,9 +673,11 @@ ZEND_VM_HELPER_EX(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMP|VAR| zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (OP1_TYPE != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); FREE_OP2(); if (RETURN_VALUE_USED(opline)) { @@ -711,20 +690,17 @@ ZEND_VM_HELPER_EX(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMP|VAR| /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - SEPARATE_ZVAL_IF_NOT_REF(zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - have_get_ptr = 1; - incdec_op(zptr); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(retval, zptr); - } - } - } + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + incdec_op(zptr); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(retval, zptr); + } + } else { zval rv; if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { @@ -777,7 +753,7 @@ ZEND_VM_HELPER_EX(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMP|VAR zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); object = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW); @@ -788,9 +764,11 @@ ZEND_VM_HELPER_EX(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMP|VAR zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (OP1_TYPE != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); FREE_OP2(); ZVAL_NULL(retval); @@ -801,20 +779,15 @@ ZEND_VM_HELPER_EX(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMP|VAR /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - have_get_ptr = 1; - SEPARATE_ZVAL_IF_NOT_REF(zptr); - - ZVAL_DUP(retval, zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - incdec_op(zptr); + ZVAL_DEREF(zptr); + ZVAL_COPY(retval, zptr); - } - } - - if (!have_get_ptr) { + SEPARATE_ZVAL_NOREF(zptr); + incdec_op(zptr); + } else { if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { zval rv; zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); @@ -883,7 +856,6 @@ ZEND_VM_HANDLER(34, ZEND_PRE_INC, VAR|CV, ANY) if (RETURN_VALUE_USED(opline)) { ZVAL_NULL(EX_VAR(opline->result.var)); } - FREE_OP1_VAR_PTR(); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -891,19 +863,7 @@ ZEND_VM_HANDLER(34, ZEND_PRE_INC, VAR|CV, ANY) ZVAL_DEREF(var_ptr); SEPARATE_ZVAL_NOREF(var_ptr); - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) - && Z_OBJ_HANDLER_P(var_ptr, get) - && Z_OBJ_HANDLER_P(var_ptr, set)) { - /* proxy object */ - zval rv; - zval *val = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(val); - fast_increment_function(val); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, val TSRMLS_CC); - zval_ptr_dtor(val); - } else { - increment_function(var_ptr); - } + increment_function(var_ptr); if (RETURN_VALUE_USED(opline)) { ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); @@ -939,7 +899,6 @@ ZEND_VM_HANDLER(35, ZEND_PRE_DEC, VAR|CV, ANY) if (RETURN_VALUE_USED(opline)) { ZVAL_NULL(EX_VAR(opline->result.var)); } - FREE_OP1_VAR_PTR(); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -947,19 +906,7 @@ ZEND_VM_HANDLER(35, ZEND_PRE_DEC, VAR|CV, ANY) ZVAL_DEREF(var_ptr); SEPARATE_ZVAL_NOREF(var_ptr); - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) - && Z_OBJ_HANDLER_P(var_ptr, get) - && Z_OBJ_HANDLER_P(var_ptr, set)) { - /* proxy object */ - zval rv; - zval *val = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(val); - fast_decrement_function(val); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, val TSRMLS_CC); - zval_ptr_dtor(val); - } else { - decrement_function(var_ptr); - } + decrement_function(var_ptr); if (RETURN_VALUE_USED(opline)) { ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); @@ -974,7 +921,7 @@ ZEND_VM_HANDLER(36, ZEND_POST_INC, VAR|CV, ANY) { USE_OPLINE zend_free_op free_op1; - zval *var_ptr, *retval; + zval *var_ptr; SAVE_OPLINE(); var_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW); @@ -991,34 +938,19 @@ ZEND_VM_HANDLER(36, ZEND_POST_INC, VAR|CV, ANY) if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { ZVAL_NULL(EX_VAR(opline->result.var)); - FREE_OP1_VAR_PTR(); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } - retval = EX_VAR(opline->result.var); - if (UNEXPECTED(Z_ISREF_P(var_ptr))) { var_ptr = Z_REFVAL_P(var_ptr); - ZVAL_DUP(retval, var_ptr); + ZVAL_DUP(EX_VAR(opline->result.var), var_ptr); } else { - ZVAL_DUP(retval, var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); + zval_opt_copy_ctor(var_ptr); } - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) - && Z_OBJ_HANDLER_P(var_ptr, get) - && Z_OBJ_HANDLER_P(var_ptr, set)) { - /* proxy object */ - zval rv; - zval *val = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(val); - fast_increment_function(val); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, val TSRMLS_CC); - zval_ptr_dtor(val); - } else { - increment_function(var_ptr); - } + increment_function(var_ptr); FREE_OP1_VAR_PTR(); CHECK_EXCEPTION(); @@ -1029,7 +961,7 @@ ZEND_VM_HANDLER(37, ZEND_POST_DEC, VAR|CV, ANY) { USE_OPLINE zend_free_op free_op1; - zval *var_ptr, *retval; + zval *var_ptr; SAVE_OPLINE(); var_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW); @@ -1046,34 +978,19 @@ ZEND_VM_HANDLER(37, ZEND_POST_DEC, VAR|CV, ANY) if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { ZVAL_NULL(EX_VAR(opline->result.var)); - FREE_OP1_VAR_PTR(); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } - retval = EX_VAR(opline->result.var); - if (UNEXPECTED(Z_ISREF_P(var_ptr))) { var_ptr = Z_REFVAL_P(var_ptr); - ZVAL_DUP(retval, var_ptr); + ZVAL_DUP(EX_VAR(opline->result.var), var_ptr); } else { - ZVAL_DUP(retval, var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); + zval_opt_copy_ctor(var_ptr); } - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) - && Z_OBJ_HANDLER_P(var_ptr, get) - && Z_OBJ_HANDLER_P(var_ptr, set)) { - /* proxy object */ - zval rv; - zval *val = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(val); - fast_decrement_function(val); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, val TSRMLS_CC); - zval_ptr_dtor(val); - } else { - decrement_function(var_ptr); - } + decrement_function(var_ptr); FREE_OP1_VAR_PTR(); CHECK_EXCEPTION(); @@ -1210,9 +1127,6 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMP|VAR|CV, UNUSED|CONST| } ZVAL_COPY(EX_VAR(opline->result.var), retval); } else { - if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) { - ZVAL_MAKE_REF(retval); - } ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); } CHECK_EXCEPTION(); @@ -1265,9 +1179,7 @@ ZEND_VM_HANDLER(81, ZEND_FETCH_DIM_R, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV) container = GET_OP1_ZVAL_PTR(BP_VAR_R); zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R), OP2_TYPE TSRMLS_CC); FREE_OP2(); - if (OP1_TYPE != IS_VAR || !(opline->extended_value & ZEND_FETCH_ADD_LOCK)) { - FREE_OP1(); - } + FREE_OP1(); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -1284,11 +1196,8 @@ ZEND_VM_HANDLER(84, ZEND_FETCH_DIM_W, VAR|CV, CONST|TMP|VAR|UNUSED|CV) if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - if (EXPECTED(opline->extended_value == 0)) { - zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R), OP2_TYPE TSRMLS_CC); - } else { - zend_fetch_dimension_address_W_ref(EX_VAR(opline->result.var), container, GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R), OP2_TYPE TSRMLS_CC); - } + ZVAL_DEREF(container); + zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R), OP2_TYPE TSRMLS_CC); FREE_OP2(); if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -1310,6 +1219,7 @@ ZEND_VM_HANDLER(87, ZEND_FETCH_DIM_RW, VAR|CV, CONST|TMP|VAR|UNUSED|CV) if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R), OP2_TYPE TSRMLS_CC); FREE_OP2(); if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1.var)) { @@ -1351,6 +1261,7 @@ ZEND_VM_HANDLER(93, ZEND_FETCH_DIM_FUNC_ARG, CONST|TMP|VAR|CV, CONST|TMP|VAR|UNU if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R), OP2_TYPE TSRMLS_CC); if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -1382,6 +1293,7 @@ ZEND_VM_HANDLER(96, ZEND_FETCH_DIM_UNSET, VAR|CV, CONST|TMP|VAR|CV) if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R), OP2_TYPE TSRMLS_CC); FREE_OP2(); if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1.var)) { @@ -1392,7 +1304,7 @@ ZEND_VM_HANDLER(96, ZEND_FETCH_DIM_UNSET, VAR|CV, CONST|TMP|VAR|CV) ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HELPER(zend_fetch_property_address_read_helper, CONST|TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV) +ZEND_VM_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV) { USE_OPLINE zend_free_op free_op1; @@ -1404,7 +1316,7 @@ ZEND_VM_HELPER(zend_fetch_property_address_read_helper, CONST|TMP|VAR|UNUSED|CV, container = GET_OP1_OBJ_ZVAL_PTR_DEREF(BP_VAR_R); offset = GET_OP2_ZVAL_PTR(BP_VAR_R); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { zend_error(E_NOTICE, "Trying to get property of non-object"); ZVAL_NULL(EX_VAR(opline->result.var)); @@ -1425,11 +1337,6 @@ ZEND_VM_HELPER(zend_fetch_property_address_read_helper, CONST|TMP|VAR|UNUSED|CV, ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV) -{ - ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_property_address_read_helper); -} - ZEND_VM_HANDLER(85, ZEND_FETCH_OBJ_W, VAR|UNUSED|CV, CONST|TMP|VAR|CV) { USE_OPLINE @@ -1445,7 +1352,7 @@ ZEND_VM_HANDLER(85, ZEND_FETCH_OBJ_W, VAR|UNUSED|CV, CONST|TMP|VAR|CV) zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); FREE_OP2(); if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -1469,7 +1376,7 @@ ZEND_VM_HANDLER(88, ZEND_FETCH_OBJ_RW, VAR|UNUSED|CV, CONST|TMP|VAR|CV) if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC); FREE_OP2(); if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -1491,7 +1398,7 @@ ZEND_VM_HANDLER(91, ZEND_FETCH_OBJ_IS, CONST|TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV container = GET_OP1_OBJ_ZVAL_PTR_DEREF(BP_VAR_IS); offset = GET_OP2_ZVAL_PTR(BP_VAR_R); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -1531,7 +1438,7 @@ ZEND_VM_HANDLER(94, ZEND_FETCH_OBJ_FUNC_ARG, CONST|TMP|VAR|UNUSED|CV, CONST|TMP| if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); FREE_OP2(); if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -1540,7 +1447,7 @@ ZEND_VM_HANDLER(94, ZEND_FETCH_OBJ_FUNC_ARG, CONST|TMP|VAR|UNUSED|CV, CONST|TMP| CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { - ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_property_address_read_helper); + ZEND_VM_DISPATCH_TO_HANDLER(ZEND_FETCH_OBJ_R); } } @@ -1557,7 +1464,7 @@ ZEND_VM_HANDLER(97, ZEND_FETCH_OBJ_UNSET, VAR|UNUSED|CV, CONST|TMP|VAR|CV) if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC); FREE_OP2(); if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -1567,23 +1474,34 @@ ZEND_VM_HANDLER(97, ZEND_FETCH_OBJ_UNSET, VAR|UNUSED|CV, CONST|TMP|VAR|CV) ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(98, ZEND_FETCH_DIM_TMP_VAR, CONST|TMP, CONST) +ZEND_VM_HANDLER(98, ZEND_FETCH_LIST, CONST|TMP|VAR|CV, CONST) { USE_OPLINE zend_free_op free_op1; zval *container; SAVE_OPLINE(); - container = GET_OP1_ZVAL_PTR(BP_VAR_R); + container = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R); - if (UNEXPECTED(Z_TYPE_P(container) != IS_ARRAY)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } else { + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { zend_free_op free_op2; zval *value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R), OP2_TYPE, BP_VAR_R TSRMLS_CC); ZVAL_COPY(EX_VAR(opline->result.var), value); - FREE_OP2(); + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT) && + EXPECTED(Z_OBJ_HT_P(container)->read_dimension)) { + zval *result = EX_VAR(opline->result.var); + zval *retval = Z_OBJ_HT_P(container)->read_dimension(container, GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R), BP_VAR_R, result TSRMLS_CC); + + if (retval) { + if (result != retval) { + ZVAL_COPY(result, retval); + } + } else { + ZVAL_NULL(result); + } + } else { + ZVAL_NULL(EX_VAR(opline->result.var)); } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -1603,7 +1521,7 @@ ZEND_VM_HANDLER(136, ZEND_ASSIGN_OBJ, VAR|UNUSED|CV, CONST|TMP|VAR|CV) if (OP1_TYPE == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, OP1_TYPE, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); FREE_OP2(); FREE_OP1_VAR_PTR(); /* assign_obj has two opcodes! */ @@ -1624,45 +1542,48 @@ ZEND_VM_HANDLER(147, ZEND_ASSIGN_DIM, VAR|CV, CONST|TMP|VAR|UNUSED|CV) if (OP1_TYPE == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - if (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) { - object_ptr = Z_REFVAL_P(object_ptr); - } - if (Z_TYPE_P(object_ptr) == IS_OBJECT) { + ZVAL_DEREF(object_ptr); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { zend_free_op free_op2; zval *property_name = GET_OP2_ZVAL_PTR(BP_VAR_R); - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, OP1_TYPE, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); FREE_OP2(); } else { - zend_free_op free_op2, free_op_data1, free_op_data2; + zend_free_op free_op2, free_op_data1; + zval rv; zval *value; zval *dim = GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R); zval *variable_ptr; - variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, OP2_TYPE TSRMLS_CC); - FREE_OP2(); - value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(variable_ptr != NULL)) { - zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) && + EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + zend_long offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W TSRMLS_CC); + FREE_OP2(); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + zend_assign_to_string_offset(object_ptr, offset, value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); + FREE_OP(free_op_data1); } else { - variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + zend_fetch_dimension_address_W(&rv, object_ptr, dim, OP2_TYPE TSRMLS_CC); + FREE_OP2(); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + variable_ptr = Z_INDIRECT(rv); if (UNEXPECTED(variable_ptr == &EG(error_zval))) { - if (IS_TMP_FREE(free_op_data1)) { - zval_dtor(value); - } + FREE_OP(free_op_data1); if (RETURN_VALUE_USED(opline)) { ZVAL_NULL(EX_VAR(opline->result.var)); } - FREE_OP_VAR_PTR(free_op_data2); } else { value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC); + if ((opline+1)->op1_type == IS_VAR) { + FREE_OP(free_op_data1); + } if (RETURN_VALUE_USED(opline)) { ZVAL_COPY(EX_VAR(opline->result.var), value); } - FREE_OP_VAR_PTR(free_op_data2); } } - FREE_OP_IF_VAR(free_op_data1); } FREE_OP1_VAR_PTR(); /* assign_dim has two opcodes! */ @@ -1684,7 +1605,7 @@ ZEND_VM_HANDLER(38, ZEND_ASSIGN, VAR|CV, CONST|TMP|VAR|CV) if (OP1_TYPE == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) { if (OP2_TYPE == IS_TMP_VAR) { - zval_dtor(value); + FREE_OP2(); } if (RETURN_VALUE_USED(opline)) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -1714,10 +1635,13 @@ ZEND_VM_HANDLER(39, ZEND_ASSIGN_REF, VAR|CV, VAR|CV) SAVE_OPLINE(); value_ptr = GET_OP2_ZVAL_PTR_PTR(BP_VAR_W); + if (OP2_TYPE == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); + } if (OP2_TYPE == IS_VAR && - opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF) && - !Z_ISREF_P(value_ptr)) { + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { if (!OP2_FREE) { PZVAL_LOCK(value_ptr); /* undo the effect of get_zval_ptr_ptr() */ } @@ -1734,15 +1658,14 @@ ZEND_VM_HANDLER(39, ZEND_ASSIGN_REF, VAR|CV, VAR|CV) } variable_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W); + if (OP1_TYPE == IS_VAR && UNEXPECTED(variable_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); + } if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT) && UNEXPECTED(!Z_ISREF_P(variable_ptr))) { zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object"); } - if ((OP2_TYPE == IS_VAR && UNEXPECTED(value_ptr == NULL)) || - (OP1_TYPE == IS_VAR && UNEXPECTED(variable_ptr == NULL))) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); - } if ((OP1_TYPE == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) || (OP2_TYPE == IS_VAR && UNEXPECTED(value_ptr == &EG(error_zval)))) { variable_ptr = &EG(uninitialized_zval); @@ -1769,9 +1692,11 @@ ZEND_VM_HANDLER(39, ZEND_ASSIGN_REF, VAR|CV, VAR|CV) ZEND_VM_HELPER(zend_leave_helper, ANY, ANY) { - vm_frame_kind frame_kind = EX(frame_kind); + vm_frame_kind frame_kind = VM_FRAME_KIND(EX(frame_info)); if (frame_kind == VM_FRAME_NESTED_FUNCTION) { + zend_object *object; + i_free_compiled_variables(execute_data TSRMLS_CC); if (UNEXPECTED(EX(symbol_table) != NULL)) { zend_clean_and_cache_symbol_table(EX(symbol_table) TSRMLS_CC); @@ -1781,26 +1706,22 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY) if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_CLOSURE) != 0) && EX(func)->op_array.prototype) { OBJ_RELEASE((zend_object*)EX(func)->op_array.prototype); } + object = Z_OBJ(EX(This)); zend_vm_stack_free_call_frame(execute_data TSRMLS_CC); execute_data = EG(current_execute_data); - if (Z_OBJ(EG(This))) { + if (object) { if (UNEXPECTED(EG(exception) != NULL) && (EX(opline)->op1.num & ZEND_CALL_CTOR)) { if (!(EX(opline)->op1.num & ZEND_CALL_CTOR_RESULT_UNUSED)) { - Z_DELREF(EG(This)); + GC_REFCOUNT(object)--; } - if (Z_REFCOUNT(EG(This)) == 1) { - zend_object_store_ctor_failed(Z_OBJ(EG(This)) TSRMLS_CC); + if (GC_REFCOUNT(object) == 1) { + zend_object_store_ctor_failed(object TSRMLS_CC); } } - if (!Z_DELREF(EG(This))) { - _zval_dtor_func_for_ptr(Z_COUNTED(EG(This)) ZEND_FILE_LINE_CC); - } else if (UNEXPECTED(!Z_GC_INFO(EG(This)))) { - gc_possible_root(Z_COUNTED(EG(This)) TSRMLS_CC); - } + OBJ_RELEASE(object); } - Z_OBJ(EG(This)) = EX(object); EG(scope) = EX(scope); if (UNEXPECTED(EG(exception) != NULL)) { @@ -1989,13 +1910,14 @@ ZEND_VM_HANDLER(46, ZEND_JMPZ_EX, CONST|TMP|VAR|CV, ANY) } if (i_zend_is_true(val TSRMLS_CC)) { + FREE_OP1(); ZVAL_TRUE(EX_VAR(opline->result.var)); opline++; } else { + FREE_OP1(); ZVAL_FALSE(EX_VAR(opline->result.var)); opline = opline->op2.jmp_addr; } - FREE_OP1(); if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -2041,26 +1963,11 @@ ZEND_VM_HANDLER(70, ZEND_FREE, TMP|VAR, ANY) USE_OPLINE SAVE_OPLINE(); - if (OP1_TYPE == IS_TMP_VAR) { - zval_dtor(EX_VAR(opline->op1.var)); - } else { - zval_ptr_dtor(EX_VAR(opline->op1.var)); - } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(53, ZEND_INIT_STRING, ANY, ANY) -{ - USE_OPLINE - zval *tmp = EX_VAR(opline->result.var); - - SAVE_OPLINE(); - ZVAL_EMPTY_STRING(tmp); - /*CHECK_EXCEPTION();*/ - ZEND_VM_NEXT_OPCODE(); -} - ZEND_VM_HANDLER(54, ZEND_ADD_CHAR, TMP|UNUSED, CONST) { USE_OPLINE @@ -2163,7 +2070,7 @@ ZEND_VM_HANDLER(109, ZEND_FETCH_CLASS, ANY, CONST|TMP|VAR|UNUSED|CV) if (CACHED_PTR(Z_CACHE_SLOT_P(class_name))) { Z_CE_P(EX_VAR(opline->result.var)) = CACHED_PTR(Z_CACHE_SLOT_P(class_name)); } else { - Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class_by_name(Z_STR_P(class_name), opline->op2.zv + 1, opline->extended_value TSRMLS_CC); + Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class_by_name(Z_STR_P(class_name), opline->op2.zv + 1, 0 TSRMLS_CC); CACHE_PTR(Z_CACHE_SLOT_P(class_name), Z_CE_P(EX_VAR(opline->result.var))); } } else if (Z_TYPE_P(class_name) == IS_OBJECT) { @@ -2207,19 +2114,56 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV) object = GET_OP1_OBJ_ZVAL_PTR_DEREF(BP_VAR_R); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + uint32_t nesting = 1; + if (UNEXPECTED(EG(exception) != NULL)) { FREE_OP2(); HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); + + zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); + FREE_OP2(); + FREE_OP1_IF_VAR(); + + if (EG(exception) != NULL) { + HANDLE_EXCEPTION(); + } + + /* No exception raised: Skip over arguments until fcall opcode with correct + * nesting level. Return NULL (except when return value unused) */ + do { + opline++; + if (opline->opcode == ZEND_INIT_FCALL || + opline->opcode == ZEND_INIT_FCALL_BY_NAME || + opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME || + opline->opcode == ZEND_INIT_METHOD_CALL || + opline->opcode == ZEND_INIT_STATIC_METHOD_CALL || + opline->opcode == ZEND_INIT_USER_CALL || + opline->opcode == ZEND_NEW + ) { + nesting++; + } else if (opline->opcode == ZEND_DO_FCALL) { + nesting--; + } + } while (nesting); + + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + /* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */ + if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) { + opline++; + } + ZEND_VM_JMP(++opline); } obj = Z_OBJ_P(object); - called_scope = zend_get_class_entry(obj TSRMLS_CC); + called_scope = obj->ce; if (OP2_TYPE != IS_CONST || - (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) { + EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { zend_object *orig_obj = obj; if (UNEXPECTED(obj->handlers->get_method == NULL)) { @@ -2229,7 +2173,7 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV) /* First, locate the function. */ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((OP2_TYPE == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name)); + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); } if (OP2_TYPE == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -2239,14 +2183,14 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV) } } - if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { obj = NULL; } else { GC_REFCOUNT(obj)++; /* For $this pointer */ } - EX(call) = zend_vm_stack_push_call_frame( - fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_FUNCTION, + fbc, opline->extended_value, called_scope, obj, EX(call) TSRMLS_CC); FREE_OP2(); FREE_OP1_IF_VAR(); @@ -2328,7 +2272,7 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUS if (UNEXPECTED(ce->constructor == NULL)) { zend_error_noreturn(E_ERROR, "Cannot call constructor"); } - if (EX(object) && zend_get_class_entry(EX(object) TSRMLS_CC) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val); } fbc = ce->constructor; @@ -2336,19 +2280,27 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUS object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { - if (EX(object)) { - object = EX(object); + if (Z_OBJ(EX(This))) { + object = Z_OBJ(EX(This)); GC_REFCOUNT(object)++; - if (object->handlers->get_class_entry && - !instanceof_function(zend_get_class_entry(object TSRMLS_CC), ce TSRMLS_CC)) { - /* We are calling method of the other (incompatible) class, - but passing $this. This is done for compatibility with php-4. */ - if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val); - } else { - /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val); - } + } + if (!object || + !instanceof_function(object->ce, ce TSRMLS_CC)) { + /* We are calling method of the other (incompatible) class, + but passing $this. This is done for compatibility with php-4. */ + if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + zend_error( + object ? E_DEPRECATED : E_STRICT, + "Non-static method %s::%s() should not be called statically%s", + fbc->common.scope->name->val, fbc->common.function_name->val, + object ? ", assuming $this from incompatible context" : ""); + } else { + /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ + zend_error_noreturn( + E_ERROR, + "Non-static method %s::%s() cannot be called statically%s", + fbc->common.scope->name->val, fbc->common.function_name->val, + object ? ", assuming $this from incompatible context" : ""); } } } @@ -2360,8 +2312,8 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUS } } - EX(call) = zend_vm_stack_push_call_frame( - fbc, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_FUNCTION, + fbc, opline->extended_value, ce, object, EX(call) TSRMLS_CC); if (OP2_TYPE == IS_UNUSED) { EX(call)->return_value = NULL; @@ -2389,8 +2341,8 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV) CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), fbc); } - EX(call) = zend_vm_stack_push_call_frame( - fbc, opline->extended_value, 0, NULL, NULL, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_FUNCTION, + fbc, opline->extended_value, NULL, NULL, EX(call) TSRMLS_CC); /*CHECK_EXCEPTION();*/ ZEND_VM_NEXT_OPCODE(); @@ -2474,13 +2426,25 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV) if (UNEXPECTED(fbc == NULL)) { zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", called_scope->name->val, Z_STRVAL_P(method)); } + if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { + if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + zend_error(E_STRICT, + "Non-static method %s::%s() should not be called statically", + fbc->common.scope->name->val, fbc->common.function_name->val); + } else { + zend_error_noreturn( + E_ERROR, + "Non-static method %s::%s() cannot be called statically", + fbc->common.scope->name->val, fbc->common.function_name->val); + } + } } else { called_scope = Z_OBJCE_P(obj); object = Z_OBJ_P(obj); fbc = Z_OBJ_HT_P(obj)->get_method(&object, Z_STR_P(method), NULL TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(object), Z_STRVAL_P(method)); + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", object->ce->name->val, Z_STRVAL_P(method)); } if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { @@ -2497,8 +2461,8 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV) zend_error_noreturn(E_ERROR, "Function name must be a string"); ZEND_VM_CONTINUE(); /* Never reached */ } - EX(call) = zend_vm_stack_push_call_frame( - fbc, opline->extended_value, 0, called_scope, object, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_FUNCTION, + fbc, opline->extended_value, called_scope, object, EX(call) TSRMLS_CC); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -2530,6 +2494,18 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMP|VAR|CV) object = fcc.object; if (object) { GC_REFCOUNT(object)++; /* For $this pointer */ + } else if (func->common.scope && + !(func->common.fn_flags & ZEND_ACC_STATIC)) { + if (func->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + zend_error(E_STRICT, + "Non-static method %s::%s() should not be called statically", + func->common.scope->name->val, func->common.function_name->val); + } else { + zend_error_noreturn( + E_ERROR, + "Non-static method %s::%s() cannot be called statically", + func->common.scope->name->val, func->common.function_name->val); + } } } else { zend_error(E_WARNING, "%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(opline->op1.zv), error); @@ -2539,8 +2515,8 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMP|VAR|CV) object = NULL; } - EX(call) = zend_vm_stack_push_call_frame( - func, opline->extended_value, 0, called_scope, object, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_FUNCTION, + func, opline->extended_value, called_scope, object, EX(call) TSRMLS_CC); FREE_OP2(); CHECK_EXCEPTION(); @@ -2571,8 +2547,8 @@ ZEND_VM_HANDLER(69, ZEND_INIT_NS_FCALL_BY_NAME, ANY, CONST) CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), fbc); } - EX(call) = zend_vm_stack_push_call_frame( - fbc, opline->extended_value, 0, NULL, NULL, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_FUNCTION, + fbc, opline->extended_value, NULL, NULL, EX(call) TSRMLS_CC); ZEND_VM_NEXT_OPCODE(); } @@ -2595,8 +2571,8 @@ ZEND_VM_HANDLER(61, ZEND_INIT_FCALL, ANY, CONST) CACHE_PTR(Z_CACHE_SLOT_P(fname), fbc); } - EX(call) = zend_vm_stack_push_call_frame( - fbc, opline->extended_value, 0, NULL, NULL, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_FUNCTION, + fbc, opline->extended_value, NULL, NULL, EX(call) TSRMLS_CC); FREE_OP2(); @@ -2608,9 +2584,10 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY) USE_OPLINE zend_execute_data *call = EX(call); zend_function *fbc = call->func; + zend_object *object = Z_OBJ(call->This); SAVE_OPLINE(); - EX(call) = call->prev_nested_call; + EX(call) = call->prev_execute_data; if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) { if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 0)) { zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", fbc->common.scope->name->val, fbc->common.function_name->val); @@ -2625,22 +2602,6 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY) } } } - if (fbc->common.scope && - !(fbc->common.fn_flags & ZEND_ACC_STATIC) && - !call->object) { - - if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - /* FIXME: output identifiers properly */ - zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically", fbc->common.scope->name->val, fbc->common.function_name->val); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - } else { - /* FIXME: output identifiers properly */ - /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically", fbc->common.scope->name->val, fbc->common.function_name->val); - } - } LOAD_OPLINE(); @@ -2650,16 +2611,16 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY) if (fbc->common.scope) { should_change_scope = 1; - Z_OBJ(EG(This)) = call->object; /* TODO: we don't set scope if we call an object method ??? */ /* See: ext/pdo_sqlite/tests/pdo_fetch_func_001.phpt */ #if 1 - EG(scope) = (call->object) ? NULL : fbc->common.scope; + EG(scope) = object ? NULL : fbc->common.scope; #else EG(scope) = fbc->common.scope; #endif - } else { + } else { call->called_scope = EX(called_scope); + Z_OBJ(call->This) = Z_OBJ(EX(This)); } call->prev_execute_data = execute_data; @@ -2670,7 +2631,7 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY) zval *p = ZEND_CALL_ARG(call, 1); for (i = 0; i < call->num_args; ++i) { - zend_verify_arg_type(fbc, i + 1, p, 0 TSRMLS_CC); + zend_verify_arg_type(fbc, i + 1, p TSRMLS_CC); p++; } if (UNEXPECTED(EG(exception) != NULL)) { @@ -2694,7 +2655,7 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY) if (!zend_execute_internal) { /* saves one function call if zend_execute_internal is not used */ - fbc->internal_function.handler(call->num_args, ret TSRMLS_CC); + fbc->internal_function.handler(call, ret TSRMLS_CC); } else { zend_execute_internal(call, ret TSRMLS_CC); } @@ -2712,18 +2673,7 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY) ZEND_VM_C_GOTO(fcall_end); } } else if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) { - zval *return_value = NULL; - - Z_OBJ(EG(This)) = call->object; - EG(scope) = fbc->common.scope; - call->symbol_table = NULL; - if (RETURN_VALUE_USED(opline)) { - return_value = EX_VAR(opline->result.var); - - ZVAL_NULL(return_value); - Z_VAR_FLAGS_P(return_value) = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0 ? IS_VAR_RET_REF : 0; - } - + call->scope = EG(scope) = fbc->common.scope; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_GENERATOR) != 0)) { if (RETURN_VALUE_USED(opline)) { zend_generator_create_zval(call, &fbc->op_array, EX_VAR(opline->result.var) TSRMLS_CC); @@ -2733,26 +2683,38 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY) zend_vm_stack_free_call_frame(call TSRMLS_CC); } else { + zval *return_value = NULL; + + call->symbol_table = NULL; + if (RETURN_VALUE_USED(opline)) { + return_value = EX_VAR(opline->result.var); + + ZVAL_NULL(return_value); + Z_VAR_FLAGS_P(return_value) = 0; + } + call->prev_execute_data = execute_data; - i_init_func_execute_data(call, &fbc->op_array, return_value, EXPECTED(zend_execute_ex == execute_ex) ? VM_FRAME_NESTED_FUNCTION : VM_FRAME_TOP_FUNCTION TSRMLS_CC); + i_init_func_execute_data(call, &fbc->op_array, return_value TSRMLS_CC); if (EXPECTED(zend_execute_ex == execute_ex)) { ZEND_VM_ENTER(); } else { + call->frame_info = VM_FRAME_INFO( + VM_FRAME_TOP_FUNCTION, + VM_FRAME_FLAGS(call->frame_info)); zend_execute_ex(call TSRMLS_CC); } } } else { /* ZEND_OVERLOADED_FUNCTION */ - Z_OBJ(EG(This)) = call->object; EG(scope) = fbc->common.scope; ZVAL_NULL(EX_VAR(opline->result.var)); /* Not sure what should be done here if it's a static method */ - if (EXPECTED(call->object != NULL)) { + if (EXPECTED(object != NULL)) { call->prev_execute_data = execute_data; EG(current_execute_data) = call; - call->object->handlers->call_method(fbc->common.function_name, call->object, call->num_args, EX_VAR(opline->result.var) TSRMLS_CC); + object->handlers->call_method(fbc->common.function_name, object, call, EX_VAR(opline->result.var) TSRMLS_CC); EG(current_execute_data) = call->prev_execute_data; } else { zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object"); @@ -2777,22 +2739,17 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY) } ZEND_VM_C_LABEL(fcall_end_change_scope): - if (Z_OBJ(EG(This))) { + if (object) { if (UNEXPECTED(EG(exception) != NULL) && (opline->op1.num & ZEND_CALL_CTOR)) { if (!(opline->op1.num & ZEND_CALL_CTOR_RESULT_UNUSED)) { - Z_DELREF(EG(This)); + GC_REFCOUNT(object)--; } - if (Z_REFCOUNT(EG(This)) == 1) { - zend_object_store_ctor_failed(Z_OBJ(EG(This)) TSRMLS_CC); + if (GC_REFCOUNT(object) == 1) { + zend_object_store_ctor_failed(object TSRMLS_CC); } } - if (!Z_DELREF(EG(This))) { - _zval_dtor_func_for_ptr(Z_COUNTED(EG(This)) ZEND_FILE_LINE_CC); - } else if (UNEXPECTED(!Z_GC_INFO(EG(This)))) { - gc_possible_root(Z_COUNTED(EG(This)) TSRMLS_CC); - } + OBJ_RELEASE(object); } - Z_OBJ(EG(This)) = EX(object); EG(scope) = EX(scope); ZEND_VM_C_LABEL(fcall_end): @@ -2860,6 +2817,7 @@ ZEND_VM_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY) } } else { ZVAL_COPY_VALUE(EX(return_value), retval_ptr); + Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; if (OP1_TYPE != IS_TMP_VAR) { zval_opt_copy_ctor_no_imm(EX(return_value)); } @@ -2873,13 +2831,14 @@ ZEND_VM_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY) zend_error_noreturn(E_ERROR, "Cannot return string offsets by reference"); } - if (OP1_TYPE == IS_VAR && !Z_ISREF_P(retval_ptr)) { - if (opline->extended_value == ZEND_RETURNS_FUNCTION && - (Z_VAR_FLAGS_P(retval_ptr) & IS_VAR_RET_REF)) { - } else { + if (OP1_TYPE == IS_VAR) { + if (retval_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(retval_ptr) & IS_VAR_RET_REF))) { zend_error(E_NOTICE, "Only variable references should be returned by reference"); if (EX(return_value)) { ZVAL_NEW_REF(EX(return_value), retval_ptr); + Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; if (Z_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr); } break; @@ -2890,6 +2849,7 @@ ZEND_VM_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY) ZVAL_MAKE_REF(retval_ptr); Z_ADDREF_P(retval_ptr); ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr)); + Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; } } while (0); @@ -2956,7 +2916,7 @@ ZEND_VM_HANDLER(107, ZEND_CATCH, CONST, CV) CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), catch_ce); } - ce = zend_get_class_entry(EG(exception) TSRMLS_CC); + ce = EG(exception)->ce; #ifdef HAVE_DTRACE if (DTRACE_EXCEPTION_CAUGHT_ENABLED()) { @@ -3336,12 +3296,12 @@ ZEND_VM_HANDLER(119, ZEND_SEND_ARRAY, ANY, ANY) if (EX(call)->func->common.fn_flags & ZEND_ACC_CLOSURE) { OBJ_RELEASE((zend_object*)EX(call)->func->common.prototype); } - if (EX(call)->object) { - OBJ_RELEASE(EX(call)->object); + if (Z_OBJ(EX(call)->This)) { + OBJ_RELEASE(Z_OBJ(EX(call)->This)); } EX(call)->func = (zend_function*)&zend_pass_function; EX(call)->called_scope = NULL; - EX(call)->object = NULL; + Z_OBJ(EX(call)->This) = NULL; } else { uint32_t arg_num = 1; @@ -3399,12 +3359,12 @@ ZEND_VM_HANDLER(119, ZEND_SEND_ARRAY, ANY, ANY) if (EX(call)->func->common.fn_flags & ZEND_ACC_CLOSURE) { OBJ_RELEASE((zend_object*)EX(call)->func->common.prototype); } - if (EX(call)->object) { - OBJ_RELEASE(EX(call)->object); + if (Z_OBJ(EX(call)->This)) { + OBJ_RELEASE(Z_OBJ(EX(call)->This)); } EX(call)->func = (zend_function*)&zend_pass_function; EX(call)->called_scope = NULL; - EX(call)->object = NULL; + Z_OBJ(EX(call)->This) = NULL; break; } @@ -3478,12 +3438,12 @@ ZEND_VM_HANDLER(120, ZEND_SEND_USER, VAR|CV, ANY) if (EX(call)->func->common.fn_flags & ZEND_ACC_CLOSURE) { OBJ_RELEASE((zend_object*)EX(call)->func->common.prototype); } - if (EX(call)->object) { - OBJ_RELEASE(EX(call)->object); + if (Z_OBJ(EX(call)->This)) { + OBJ_RELEASE(Z_OBJ(EX(call)->This)); } EX(call)->func = (zend_function*)&zend_pass_function; EX(call)->called_scope = NULL; - EX(call)->object = NULL; + Z_OBJ(EX(call)->This) = NULL; FREE_OP1(); CHECK_EXCEPTION(); @@ -3530,7 +3490,7 @@ ZEND_VM_HANDLER(63, ZEND_RECV, ANY, ANY) } else if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) { zval *param = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC); - zend_verify_arg_type(EX(func), arg_num, param, opline->extended_value TSRMLS_CC); + zend_verify_arg_type(EX(func), arg_num, param TSRMLS_CC); CHECK_EXCEPTION(); } @@ -3558,7 +3518,7 @@ ZEND_VM_HANDLER(64, ZEND_RECV_INIT, ANY, CONST) } if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) { - zend_verify_arg_type(EX(func), arg_num, param, opline->extended_value TSRMLS_CC); + zend_verify_arg_type(EX(func), arg_num, param TSRMLS_CC); } CHECK_EXCEPTION(); @@ -3583,7 +3543,7 @@ ZEND_VM_HANDLER(164, ZEND_RECV_VARIADIC, ANY, ANY) param = EX_VAR_NUM(EX(func)->op_array.last_var + EX(func)->op_array.T); if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) { do { - zend_verify_arg_type(EX(func), arg_num, param, opline->extended_value TSRMLS_CC); + zend_verify_arg_type(EX(func), arg_num, param TSRMLS_CC); zend_hash_next_index_insert_new(Z_ARRVAL_P(params), param); if (Z_REFCOUNTED_P(param)) Z_ADDREF_P(param); param++; @@ -3652,13 +3612,9 @@ ZEND_VM_HANDLER(100, ZEND_GOTO, ANY, CONST) brk_opline = EX(func)->op_array.opcodes + el->brk; - if (brk_opline->opcode == ZEND_SWITCH_FREE) { + if (brk_opline->opcode == ZEND_FREE) { if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) { - zval_ptr_dtor(EX_VAR(brk_opline->op1.var)); - } - } else if (brk_opline->opcode == ZEND_FREE) { - if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) { - zval_dtor(EX_VAR(brk_opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(brk_opline->op1.var)); } } ZEND_VM_JMP(opline->op1.jmp_addr); @@ -3680,33 +3636,38 @@ ZEND_VM_HANDLER(48, ZEND_CASE, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV) ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(49, ZEND_SWITCH_FREE, VAR, ANY) -{ - USE_OPLINE - - SAVE_OPLINE(); - zval_ptr_dtor(EX_VAR(opline->op1.var)); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - -ZEND_VM_HANDLER(68, ZEND_NEW, ANY, ANY) +ZEND_VM_HANDLER(68, ZEND_NEW, CONST|VAR, ANY) { USE_OPLINE zval object_zval; zend_function *constructor; + zend_class_entry *ce; SAVE_OPLINE(); - if (UNEXPECTED((Z_CE_P(EX_VAR(opline->op1.var))->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) != 0)) { - if (Z_CE_P(EX_VAR(opline->op1.var))->ce_flags & ZEND_ACC_INTERFACE) { - zend_error_noreturn(E_ERROR, "Cannot instantiate interface %s", Z_CE_P(EX_VAR(opline->op1.var))->name->val); - } else if ((Z_CE_P(EX_VAR(opline->op1.var))->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) { - zend_error_noreturn(E_ERROR, "Cannot instantiate trait %s", Z_CE_P(EX_VAR(opline->op1.var))->name->val); + if (OP1_TYPE == IS_CONST) { + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv)); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, 0 TSRMLS_CC); + if (UNEXPECTED(ce == NULL)) { + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op1.var)); + } + if (UNEXPECTED((ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) != 0)) { + if (ce->ce_flags & ZEND_ACC_INTERFACE) { + zend_error_noreturn(E_ERROR, "Cannot instantiate interface %s", ce->name->val); + } else if ((ce->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) { + zend_error_noreturn(E_ERROR, "Cannot instantiate trait %s", ce->name->val); } else { - zend_error_noreturn(E_ERROR, "Cannot instantiate abstract class %s", Z_CE_P(EX_VAR(opline->op1.var))->name->val); + zend_error_noreturn(E_ERROR, "Cannot instantiate abstract class %s", ce->name->val); } } - object_init_ex(&object_zval, Z_CE_P(EX_VAR(opline->op1.var))); + object_init_ex(&object_zval, ce); constructor = Z_OBJ_HT(object_zval)->get_constructor(Z_OBJ(object_zval) TSRMLS_CC); if (constructor == NULL) { @@ -3719,10 +3680,13 @@ ZEND_VM_HANDLER(68, ZEND_NEW, ANY, ANY) } else { /* We are not handling overloaded classes right now */ EX(call) = zend_vm_stack_push_call_frame( - constructor, opline->extended_value, - RETURN_VALUE_USED(opline) ? - ZEND_CALL_CTOR : (ZEND_CALL_CTOR | ZEND_CALL_CTOR_RESULT_UNUSED), - Z_CE_P(EX_VAR(opline->op1.var)), + VM_FRAME_INFO( + VM_FRAME_NESTED_FUNCTION, + RETURN_VALUE_USED(opline) ? + ZEND_CALL_CTOR : (ZEND_CALL_CTOR | ZEND_CALL_CTOR_RESULT_UNUSED)), + constructor, + opline->extended_value, + ce, Z_OBJ(object_zval), EX(call) TSRMLS_CC); @@ -3751,7 +3715,7 @@ ZEND_VM_HANDLER(110, ZEND_CLONE, CONST|TMP|VAR|UNUSED|CV, ANY) obj = GET_OP1_OBJ_ZVAL_PTR_DEREF(BP_VAR_R); if (OP1_TYPE == IS_CONST || - UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT)) { + (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT))) { if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -3810,14 +3774,16 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST) } else if ((c = zend_quick_get_constant(opline->op2.zv + 1, opline->extended_value TSRMLS_CC)) == NULL) { if ((opline->extended_value & IS_CONSTANT_UNQUALIFIED) != 0) { char *actual = (char *)zend_memrchr(Z_STRVAL_P(opline->op2.zv), '\\', Z_STRLEN_P(opline->op2.zv)); - if(!actual) { - actual = Z_STRVAL_P(opline->op2.zv); + if (!actual) { + ZVAL_STR(EX_VAR(opline->result.var), zend_string_copy(Z_STR_P(opline->op2.zv))); } else { actual++; + ZVAL_STRINGL(EX_VAR(opline->result.var), + actual, Z_STRLEN_P(opline->op2.zv) - (actual - Z_STRVAL_P(opline->op2.zv))); } /* non-qualified constant - allow text substitution */ - zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", actual, actual); - ZVAL_STRINGL(EX_VAR(opline->result.var), actual, Z_STRLEN_P(opline->op2.zv)-(actual - Z_STRVAL_P(opline->op2.zv))); + zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", + Z_STRVAL_P(EX_VAR(opline->result.var)), Z_STRVAL_P(EX_VAR(opline->result.var))); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { @@ -3849,7 +3815,7 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST) } else if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) { ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv)); } else { - ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, opline->extended_value TSRMLS_CC); + ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, 0 TSRMLS_CC); if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -4063,7 +4029,7 @@ ZEND_VM_HANDLER(21, ZEND_CAST, CONST|TMP|VAR|CV, ANY) if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); } - FREE_OP1(); + FREE_OP1_IF_VAR(); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -4078,15 +4044,13 @@ ZEND_VM_HANDLER(21, ZEND_CAST, CONST|TMP|VAR|CV, ANY) if (UNEXPECTED(Z_OPT_COPYABLE_P(expr))) { zval_copy_ctor_func(expr); } - } else if (OP1_TYPE != IS_TMP_VAR) { + } else { if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); } } } else { ZVAL_COPY_VALUE(result, expr); - if (OP1_TYPE != IS_TMP_VAR) { - zval_opt_copy_ctor(result); - } + Z_ADDREF_P(result); convert_to_array(result); } } else { @@ -4098,23 +4062,18 @@ ZEND_VM_HANDLER(21, ZEND_CAST, CONST|TMP|VAR|CV, ANY) if (UNEXPECTED(Z_OPT_COPYABLE_P(expr))) { zval_copy_ctor_func(expr); } - } else if (OP1_TYPE != IS_TMP_VAR) { + } else { if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); } } } else { ZVAL_COPY_VALUE(result, expr); - if (OP1_TYPE != IS_TMP_VAR) { - zval_opt_copy_ctor(result); - } + zval_opt_copy_ctor(result); convert_to_object(result); } } - - FREE_OP1_IF_VAR(); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); } + FREE_OP1(); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -4134,8 +4093,7 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMP|VAR|CV, ANY) ZVAL_UNDEF(&tmp_inc_filename); if (Z_TYPE_P(inc_filename) != IS_STRING) { - ZVAL_DUP(&tmp_inc_filename, inc_filename); - convert_to_string(&tmp_inc_filename); + ZVAL_STR(&tmp_inc_filename, zval_get_string(inc_filename)); inc_filename = &tmp_inc_filename; } @@ -4214,8 +4172,8 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMP|VAR|CV, ANY) return_value = EX_VAR(opline->result.var); } - call = zend_vm_stack_push_call_frame( - (zend_function*)new_op_array, 0, 0, EX(called_scope), EX(object), NULL TSRMLS_CC); + call = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_CODE, + (zend_function*)new_op_array, 0, EX(called_scope), Z_OBJ(EX(This)), NULL TSRMLS_CC); if (EX(symbol_table)) { call->symbol_table = EX(symbol_table); @@ -4224,10 +4182,11 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMP|VAR|CV, ANY) } call->prev_execute_data = execute_data; - i_init_code_execute_data(call, new_op_array, return_value, EXPECTED(zend_execute_ex == execute_ex) ? VM_FRAME_NESTED_CODE : VM_FRAME_TOP_CODE TSRMLS_CC); + i_init_code_execute_data(call, new_op_array, return_value TSRMLS_CC); if (EXPECTED(zend_execute_ex == execute_ex)) { ZEND_VM_ENTER(); } else { + call->frame_info = VM_FRAME_TOP_CODE; zend_execute_ex(call TSRMLS_CC); } @@ -4278,8 +4237,7 @@ ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMP|VAR|CV, UNUSED|CONST|VAR) ZVAL_UNDEF(&tmp); if (OP1_TYPE != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { - ZVAL_DUP(&tmp, varname); - convert_to_string(&tmp); + ZVAL_STR(&tmp, zval_get_string(varname)); varname = &tmp; } @@ -4339,71 +4297,66 @@ ZEND_VM_HANDLER(75, ZEND_UNSET_DIM, VAR|UNUSED|CV, CONST|TMP|VAR|CV) } offset = GET_OP2_ZVAL_PTR(BP_VAR_R); - switch (Z_TYPE_P(container)) { - case IS_ARRAY: { - HashTable *ht = Z_ARRVAL_P(container); + if (OP1_TYPE != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht = Z_ARRVAL_P(container); ZEND_VM_C_LABEL(offset_again): - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - zend_hash_index_del(ht, hval); - break; - case IS_LONG: - hval = Z_LVAL_P(offset); + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_LONG: + hval = Z_LVAL_P(offset); ZEND_VM_C_LABEL(num_index_dim): - zend_hash_index_del(ht, hval); - break; - case IS_STRING: - if (OP2_TYPE != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { - ZEND_VM_C_GOTO(num_index_dim); - } - } - if (ht == &EG(symbol_table).ht) { - zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); - } else { - zend_hash_del(ht, Z_STR_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_STRING: + if (OP2_TYPE != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { + ZEND_VM_C_GOTO(num_index_dim); } - break; - case IS_NULL: - zend_hash_del(ht, STR_EMPTY_ALLOC()); - break; - case IS_FALSE: - hval = 0; - ZEND_VM_C_GOTO(num_index_dim); - case IS_TRUE: - hval = 1; - ZEND_VM_C_GOTO(num_index_dim); - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - ZEND_VM_C_GOTO(num_index_dim); - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - ZEND_VM_C_GOTO(offset_again); - break; - default: - zend_error(E_WARNING, "Illegal offset type in unset"); - break; - } - FREE_OP2(); - break; + } + if (ht == &EG(symbol_table).ht) { + zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); + } else { + zend_hash_del(ht, Z_STR_P(offset)); + } + break; + case IS_NULL: + zend_hash_del(ht, STR_EMPTY_ALLOC()); + break; + case IS_FALSE: + hval = 0; + ZEND_VM_C_GOTO(num_index_dim); + case IS_TRUE: + hval = 1; + ZEND_VM_C_GOTO(num_index_dim); + case IS_RESOURCE: + hval = Z_RES_HANDLE_P(offset); + ZEND_VM_C_GOTO(num_index_dim); + case IS_REFERENCE: + offset = Z_REFVAL_P(offset); + ZEND_VM_C_GOTO(offset_again); + break; + default: + zend_error(E_WARNING, "Illegal offset type in unset"); + break; } - case IS_OBJECT: - if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use object as array"); - } -//??? if (OP2_TYPE == IS_CONST) { -//??? zval_copy_ctor(offset); -//??? } - Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); - FREE_OP2(); - break; - case IS_STRING: - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - ZEND_VM_CONTINUE(); /* bailed out before */ - default: - FREE_OP2(); - break; + FREE_OP2(); + } else if (OP1_TYPE == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use object as array"); + } +//??? if (OP2_TYPE == IS_CONST) { +//??? zval_copy_ctor(offset); +//??? } + Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); + FREE_OP2(); + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + ZEND_VM_CONTINUE(); /* bailed out before */ + } else { + FREE_OP2(); } FREE_OP1_VAR_PTR(); CHECK_EXCEPTION(); @@ -4425,7 +4378,7 @@ ZEND_VM_HANDLER(76, ZEND_UNSET_OBJ, VAR|UNUSED|CV, CONST|TMP|VAR|CV) offset = GET_OP2_ZVAL_PTR(BP_VAR_R); ZVAL_DEREF(container); - if (Z_TYPE_P(container) == IS_OBJECT) { + if (OP1_TYPE == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->unset_property) { Z_OBJ_HT_P(container)->unset_property(container, offset, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { @@ -4462,13 +4415,8 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET, CONST|TMP|VAR|CV, ANY) } if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref); } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { - if(Z_OBJ_HT_P(array_ptr)->get_class_entry == NULL) { - zend_error(E_WARNING, "foreach() cannot iterate over objects without PHP class"); - ZEND_VM_JMP(opline->op2.jmp_addr); - } - ce = Z_OBJCE_P(array_ptr); - if (!ce || ce->get_iterator == NULL) { + if (ce->get_iterator == NULL) { Z_ADDREF_P(array_ptr); } array_ref = array_ptr; @@ -4480,7 +4428,10 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET, CONST|TMP|VAR|CV, ANY) ZVAL_DEREF(array_ptr); if (OP1_TYPE == IS_TMP_VAR) { ZVAL_COPY_VALUE(&tmp, array_ptr); - array_ptr = &tmp; + if (Z_OPT_IMMUTABLE_P(&tmp)) { + zval_copy_ctor_func(&tmp); + } + array_ref = array_ptr = &tmp; if (Z_TYPE_P(array_ptr) == IS_OBJECT) { ce = Z_OBJCE_P(array_ptr); if (ce && ce->get_iterator) { @@ -4489,17 +4440,18 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET, CONST|TMP|VAR|CV, ANY) } } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { ce = Z_OBJCE_P(array_ptr); - if (!ce || !ce->get_iterator) { + if (!ce->get_iterator) { if (OP1_TYPE == IS_CV) { Z_ADDREF_P(array_ref); } } } else if (Z_IMMUTABLE_P(array_ref)) { if (OP1_TYPE == IS_CV) { - zval_copy_ctor(array_ref); + zval_copy_ctor_func(array_ref); Z_ADDREF_P(array_ref); } else { - ZVAL_DUP(&tmp, array_ref); + ZVAL_COPY_VALUE(&tmp, array_ref); + zval_copy_ctor_func(&tmp); array_ptr = array_ref = &tmp; } } else if (Z_REFCOUNTED_P(array_ref)) { @@ -4520,14 +4472,13 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET, CONST|TMP|VAR|CV, ANY) ZVAL_UNREF(array_ref); array_ptr = array_ref; } - if (Z_IMMUTABLE_P(array_ptr) || - (Z_ISREF_P(array_ref) && - Z_REFCOUNTED_P(array_ptr) && - Z_REFCOUNT_P(array_ptr) > 1)) { - if (!Z_IMMUTABLE_P(array_ptr)) { - Z_DELREF_P(array_ptr); - } - zval_copy_ctor(array_ptr); + if (Z_IMMUTABLE_P(array_ptr)) { + zval_copy_ctor_func(array_ptr); + } else if (Z_ISREF_P(array_ref) && + Z_COPYABLE_P(array_ptr) && + Z_REFCOUNT_P(array_ptr) > 1) { + Z_DELREF_P(array_ptr); + zval_copy_ctor_func(array_ptr); } if (OP1_TYPE == IS_CV) { Z_ADDREF_P(array_ref); @@ -4611,6 +4562,7 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET, CONST|TMP|VAR|CV, ANY) ptr->pos = pos; ptr->ht = fe_ht; ptr->h = fe_ht->arData[pos].h; + ptr->key = fe_ht->arData[pos].key; is_empty = 0; } else { zend_error(E_WARNING, "Invalid argument supplied for foreach()"); @@ -4644,7 +4596,7 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY) array = Z_REFVAL_P(array); // TODO: referenced value might be changed to different array ??? if (Z_IMMUTABLE_P(array)) { - zval_copy_ctor(array); + zval_copy_ctor_func(array); } } @@ -4665,8 +4617,11 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY) pos = ptr->h; } else { pos = fe_ht->arHash[ptr->h & fe_ht->nTableMask]; - while (pos != INVALID_IDX) { - if (fe_ht->arData[pos].h == ptr->h && pos == ptr->pos) { + while (1) { + if (pos == INVALID_IDX) { + pos = fe_ht->nInternalPointer; + break; + } else if (fe_ht->arData[pos].h == ptr->h && fe_ht->arData[pos].key == ptr->key) { break; } pos = Z_NEXT(fe_ht->arData[pos].val); @@ -4719,6 +4674,7 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY) Z_TYPE_P(Z_INDIRECT(p->val)) == IS_UNDEF)); fe_ht->nInternalPointer = ptr->pos = pos; ptr->h = fe_ht->arData[pos].h; + ptr->key = fe_ht->arData[pos].key; ZEND_VM_INC_OPCODE(); ZEND_VM_NEXT_OPCODE(); } else if (EXPECTED(Z_TYPE_P(array) == IS_OBJECT)) { @@ -4742,8 +4698,11 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY) pos = ptr->h; } else { pos = fe_ht->arHash[ptr->h & fe_ht->nTableMask]; - while (pos != INVALID_IDX) { - if (fe_ht->arData[pos].h == ptr->h && pos == ptr->pos) { + while (1) { + if (pos == INVALID_IDX) { + pos = fe_ht->nInternalPointer; + break; + } else if (fe_ht->arData[pos].h == ptr->h && fe_ht->arData[pos].key == ptr->key) { break; } pos = Z_NEXT(fe_ht->arData[pos].val); @@ -4812,6 +4771,7 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY) zend_check_property_access(zobj, p->key TSRMLS_CC) == FAILURE)); fe_ht->nInternalPointer = ptr->pos = pos; ptr->h = fe_ht->arData[pos].h; + ptr->key = fe_ht->arData[pos].key; ZEND_VM_INC_OPCODE(); ZEND_VM_NEXT_OPCODE(); } else { @@ -4874,26 +4834,28 @@ ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMP|VAR|CV, UNUSED|CONST|VAR) { USE_OPLINE zval *value; - zend_bool isset = 1; SAVE_OPLINE(); if (OP1_TYPE == IS_CV && OP2_TYPE == IS_UNUSED && (opline->extended_value & ZEND_QUICK_SET)) { - if (Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_UNDEF) { - value = EX_VAR(opline->op1.var); - ZVAL_DEREF(value); - } else { - isset = 0; + value = EX_VAR(opline->op1.var); + if (opline->extended_value & ZEND_ISSET) { + ZVAL_BOOL(EX_VAR(opline->result.var), + Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + ZVAL_BOOL(EX_VAR(opline->result.var), + !i_zend_is_true(value TSRMLS_CC)); + CHECK_EXCEPTION(); } + ZEND_VM_NEXT_OPCODE(); } else { - HashTable *target_symbol_table; zend_free_op free_op1; zval tmp, *varname = GET_OP1_ZVAL_PTR(BP_VAR_IS); if (OP1_TYPE != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { - ZVAL_DUP(&tmp, varname); - convert_to_string(&tmp); + ZVAL_STR(&tmp, zval_get_string(varname)); varname = &tmp; } @@ -4915,39 +4877,28 @@ ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMP|VAR|CV, UNUSED|CONST|VAR) ce = Z_CE_P(EX_VAR(opline->op2.var)); } value = zend_std_get_static_property(ce, Z_STR_P(varname), 1, ((OP1_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); - if (!value) { - isset = 0; - } } else { - target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); - if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) { - isset = 0; - } + HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname)); } if (OP1_TYPE != IS_CONST && varname == &tmp) { zval_dtor(&tmp); } FREE_OP1(); - } - if (opline->extended_value & ZEND_ISSET) { - if (isset && Z_TYPE_P(value) != IS_NULL && - (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) { - ZVAL_BOOL(EX_VAR(opline->result.var), 1); - } else { - ZVAL_BOOL(EX_VAR(opline->result.var), 0); - } - } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { - if (!isset || !i_zend_is_true(value TSRMLS_CC)) { - ZVAL_BOOL(EX_VAR(opline->result.var), 1); - } else { - ZVAL_BOOL(EX_VAR(opline->result.var), 0); + if (opline->extended_value & ZEND_ISSET) { + ZVAL_BOOL(EX_VAR(opline->result.var), + value && Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + ZVAL_BOOL(EX_VAR(opline->result.var), + !value || !i_zend_is_true(value TSRMLS_CC)); } - } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } } ZEND_VM_HANDLER(115, ZEND_ISSET_ISEMPTY_DIM_OBJ, CONST|TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV) @@ -4963,7 +4914,7 @@ ZEND_VM_HANDLER(115, ZEND_ISSET_ISEMPTY_DIM_OBJ, CONST|TMP|VAR|UNUSED|CV, CONST| container = GET_OP1_OBJ_ZVAL_PTR_DEREF(BP_VAR_IS); offset = GET_OP2_ZVAL_PTR(BP_VAR_R); - if (Z_TYPE_P(container) == IS_ARRAY) { + if (OP1_TYPE != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { HashTable *ht = Z_ARRVAL_P(container); zval *value; zend_string *str; @@ -5016,8 +4967,8 @@ ZEND_VM_C_LABEL(num_index_prop): } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); } - } else if (Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->has_dimension) { + } else if (OP1_TYPE == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to check element of non-array"); @@ -5026,7 +4977,7 @@ ZEND_VM_C_LABEL(num_index_prop): if ((opline->extended_value & ZEND_ISSET) == 0) { result = !result; } - } else if (Z_TYPE_P(container) == IS_STRING) { /* string offsets */ + } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */ zval tmp; result = 0; @@ -5042,7 +4993,7 @@ ZEND_VM_C_LABEL(num_index_prop): offset = &tmp; } } - if (Z_TYPE_P(offset) == IS_LONG) { + if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) { if ((opline->extended_value & ZEND_ISSET) || Z_STRVAL_P(container)[offset->value.lval] != '0') { @@ -5076,8 +5027,8 @@ ZEND_VM_HANDLER(148, ZEND_ISSET_ISEMPTY_PROP_OBJ, CONST|TMP|VAR|UNUSED|CV, CONST container = GET_OP1_OBJ_ZVAL_PTR_DEREF(BP_VAR_IS); offset = GET_OP2_ZVAL_PTR(BP_VAR_R); - if (Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->has_property) { + if (OP1_TYPE == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_property)) { result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to check property of non-object"); @@ -5125,9 +5076,9 @@ ZEND_VM_HANDLER(57, ZEND_BEGIN_SILENCE, ANY, ANY) SAVE_OPLINE(); ZVAL_LONG(EX_VAR(opline->result.var), EG(error_reporting)); - if (Z_TYPE(EX(old_error_reporting)) == IS_UNDEF) { - ZVAL_LONG(&EX(old_error_reporting), EG(error_reporting)); - EX(old_error_reporting).u2.silence_num = opline->op2.num; + if (EX(silence_op_num) == -1) { + EX(silence_op_num) = opline->op2.num; + EX(old_error_reporting) = EG(error_reporting); } if (EG(error_reporting)) { @@ -5158,13 +5109,6 @@ ZEND_VM_HANDLER(57, ZEND_BEGIN_SILENCE, ANY, ANY) ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(142, ZEND_RAISE_ABSTRACT_ERROR, ANY, ANY) -{ - SAVE_OPLINE(); - zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", EX(scope)->name->val, EX(func)->op_array.function_name->val); - ZEND_VM_NEXT_OPCODE(); /* Never reached */ -} - ZEND_VM_HANDLER(58, ZEND_END_SILENCE, TMP, ANY) { USE_OPLINE @@ -5173,9 +5117,8 @@ ZEND_VM_HANDLER(58, ZEND_END_SILENCE, TMP, ANY) if (!EG(error_reporting) && Z_LVAL_P(EX_VAR(opline->op1.var)) != 0) { EG(error_reporting) = Z_LVAL_P(EX_VAR(opline->op1.var)); } - if (Z_TYPE(EX(old_error_reporting)) != IS_UNDEF && - EX(old_error_reporting).u2.silence_num == opline->op2.num) { - ZVAL_UNDEF(&EX(old_error_reporting)); + if (EX(silence_op_num) == opline->op2.num) { + EX(silence_op_num) = -1; } ZEND_VM_NEXT_OPCODE(); } @@ -5214,6 +5157,41 @@ ZEND_VM_HANDLER(152, ZEND_JMP_SET, CONST|TMP|VAR|CV, ANY) ZEND_VM_NEXT_OPCODE(); } +ZEND_VM_HANDLER(169, ZEND_COALESCE, CONST|TMP|VAR|CV, ANY) +{ + USE_OPLINE + zend_free_op free_op1; + zval *value; + int is_ref = 0; + + SAVE_OPLINE(); + value = GET_OP1_ZVAL_PTR(BP_VAR_IS); + + if ((OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) && Z_ISREF_P(value)) { + is_ref = 1; + value = Z_REFVAL_P(value); + } + + if (Z_TYPE_P(value) > IS_NULL) { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value); + if (OP1_TYPE == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + zval_copy_ctor_func(EX_VAR(opline->result.var)); + } + } else if (OP1_TYPE == IS_CV) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } else if (OP1_TYPE == IS_VAR && is_ref) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + FREE_OP1(); + } + ZEND_VM_JMP(opline->op2.jmp_addr); + } + + FREE_OP1(); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + ZEND_VM_HANDLER(22, ZEND_QM_ASSIGN, CONST|TMP|VAR|CV, ANY) { USE_OPLINE @@ -5329,7 +5307,7 @@ ZEND_VM_HANDLER(105, ZEND_TICKS, ANY, ANY) ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(138, ZEND_INSTANCEOF, TMP|VAR|CV, ANY) +ZEND_VM_HANDLER(138, ZEND_INSTANCEOF, TMP|VAR|CV, CONST|VAR) { USE_OPLINE zend_free_op free_op1; @@ -5339,8 +5317,26 @@ ZEND_VM_HANDLER(138, ZEND_INSTANCEOF, TMP|VAR|CV, ANY) SAVE_OPLINE(); expr = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R); - if (Z_TYPE_P(expr) == IS_OBJECT && Z_OBJ_HT_P(expr)->get_class_entry) { - result = instanceof_function(Z_OBJCE_P(expr), Z_CE_P(EX_VAR(opline->op2.var)) TSRMLS_CC); + if (Z_TYPE_P(expr) == IS_OBJECT) { + zend_class_entry *ce; + + if (OP2_TYPE == IS_CONST) { + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC); + if (UNEXPECTED(ce == NULL)) { + ZVAL_FALSE(EX_VAR(opline->result.var)); + FREE_OP1(); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op2.var)); + } + result = instanceof_function(Z_OBJCE_P(expr), ce TSRMLS_CC); } else { result = 0; } @@ -5370,7 +5366,7 @@ ZEND_VM_HANDLER(144, ZEND_ADD_INTERFACE, ANY, CONST) if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { iface = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); } else { - iface = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, opline->extended_value TSRMLS_CC); + iface = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, ZEND_FETCH_CLASS_INTERFACE TSRMLS_CC); if (UNEXPECTED(iface == NULL)) { CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -5399,7 +5395,7 @@ ZEND_VM_HANDLER(154, ZEND_ADD_TRAIT, ANY, ANY) } else { trait = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, - opline->extended_value TSRMLS_CC); + ZEND_FETCH_CLASS_TRAIT TSRMLS_CC); if (UNEXPECTED(trait == NULL)) { CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -5457,18 +5453,18 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY) * arguments pushed to the stack that have to be dtor'ed. */ zend_vm_stack_free_args(EX(call) TSRMLS_CC); - if (call->object) { - if (call->flags & ZEND_CALL_CTOR) { - if (!(call->flags & ZEND_CALL_CTOR_RESULT_UNUSED)) { - GC_REFCOUNT(call->object)--; + if (Z_OBJ(call->This)) { + if (call->frame_info & ZEND_CALL_CTOR) { + if (!(call->frame_info & ZEND_CALL_CTOR_RESULT_UNUSED)) { + GC_REFCOUNT(Z_OBJ(call->This))--; } - if (GC_REFCOUNT(call->object) == 1) { - zend_object_store_ctor_failed(call->object TSRMLS_CC); + if (GC_REFCOUNT(Z_OBJ(call->This)) == 1) { + zend_object_store_ctor_failed(Z_OBJ(call->This) TSRMLS_CC); } } - OBJ_RELEASE(call->object); + OBJ_RELEASE(Z_OBJ(call->This)); } - EX(call) = call->prev_nested_call; + EX(call) = call->prev_execute_data; zend_vm_stack_free_call_frame(call TSRMLS_CC); call = EX(call); } while (call); @@ -5485,13 +5481,9 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY) catch_op_num >= EX(func)->op_array.brk_cont_array[i].brk) { zend_op *brk_opline = &EX(func)->op_array.opcodes[EX(func)->op_array.brk_cont_array[i].brk]; - if (brk_opline->opcode == ZEND_SWITCH_FREE) { + if (brk_opline->opcode == ZEND_FREE) { if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) { - zval_ptr_dtor(EX_VAR(brk_opline->op1.var)); - } - } else if (brk_opline->opcode == ZEND_FREE) { - if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) { - zval_dtor(EX_VAR(brk_opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(brk_opline->op1.var)); } } } @@ -5499,10 +5491,10 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY) } /* restore previous error_reporting value */ - if (!EG(error_reporting) && Z_TYPE(EX(old_error_reporting)) != IS_UNDEF && Z_LVAL(EX(old_error_reporting)) != 0) { - EG(error_reporting) = Z_LVAL(EX(old_error_reporting)); + if (!EG(error_reporting) && EX(silence_op_num) != -1 && EX(old_error_reporting) != 0) { + EG(error_reporting) = EX(old_error_reporting); } - ZVAL_UNDEF(&EX(old_error_reporting)); + EX(silence_op_num) = -1; if (finally_op_num && (!catch_op_num || catch_op_num >= finally_op_num)) { if (EX(delayed_exception)) { @@ -5627,7 +5619,7 @@ ZEND_VM_HANDLER(153, ZEND_DECLARE_LAMBDA_FUNCTION, CONST, UNUSED) if (closure_is_static || closure_is_being_defined_inside_static_context) { zend_create_closure(EX_VAR(opline->result.var), Z_FUNC_P(zfunc), EX(called_scope), NULL TSRMLS_CC); } else { - zend_create_closure(EX_VAR(opline->result.var), Z_FUNC_P(zfunc), EX(scope), Z_OBJ(EG(This)) ? &EG(This) : NULL TSRMLS_CC); + zend_create_closure(EX_VAR(opline->result.var), Z_FUNC_P(zfunc), EX(scope), Z_OBJ(EX(This)) ? &EX(This) : NULL TSRMLS_CC); } CHECK_EXCEPTION(); @@ -5687,7 +5679,7 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE /* Temporary variables don't need ctor copying */ if (OP1_TYPE != IS_TMP_VAR) { - zval_copy_ctor(&generator->value); + zval_opt_copy_ctor(&generator->value); } } else { zval *value_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W); @@ -5698,9 +5690,10 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (OP1_TYPE == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (OP1_TYPE == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -5978,16 +5971,12 @@ ZEND_VM_HANDLER(123, ZEND_TYPE_CHECK, CONST|TMP|VAR|CV, ANY) break; case IS_OBJECT: if (Z_TYPE_P(value) == opline->extended_value) { - if (Z_OBJ_HT_P(value)->get_class_entry == NULL) { - ZVAL_TRUE(EX_VAR(opline->result.var)); + zend_class_entry *ce = Z_OBJCE_P(value); + if (ce->name->len == sizeof("__PHP_Incomplete_Class") - 1 + && !strncmp(ce->name->val, "__PHP_Incomplete_Class", ce->name->len)) { + ZVAL_FALSE(EX_VAR(opline->result.var)); } else { - zend_class_entry *ce = Z_OBJCE_P(value); - if (ce->name->len == sizeof("__PHP_Incomplete_Class") - 1 - && !strncmp(ce->name->val, "__PHP_Incomplete_Class", ce->name->len)) { - ZVAL_FALSE(EX_VAR(opline->result.var)); - } else { - ZVAL_TRUE(EX_VAR(opline->result.var)); - } + ZVAL_TRUE(EX_VAR(opline->result.var)); } } else { ZVAL_FALSE(EX_VAR(opline->result.var)); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 467dd4f168..4f305c2258 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -369,23 +369,25 @@ ZEND_API void zend_execute(zend_op_array *op_array, zval *return_value TSRMLS_DC return; } - execute_data = zend_vm_stack_push_call_frame( - (zend_function*)op_array, 0, 0, EG(current_execute_data) ? EG(current_execute_data)->called_scope : NULL, Z_OBJ(EG(This)), NULL TSRMLS_CC); + execute_data = zend_vm_stack_push_call_frame(VM_FRAME_TOP_CODE, + (zend_function*)op_array, 0, EG(current_execute_data) ? EG(current_execute_data)->called_scope : NULL, EG(current_execute_data) ? Z_OBJ(EG(current_execute_data)->This) : NULL, NULL TSRMLS_CC); if (EG(current_execute_data)) { execute_data->symbol_table = zend_rebuild_symbol_table(TSRMLS_C); } else { execute_data->symbol_table = &EG(symbol_table); } EX(prev_execute_data) = EG(current_execute_data); - i_init_execute_data(execute_data, op_array, return_value, VM_FRAME_TOP_CODE TSRMLS_CC); + i_init_execute_data(execute_data, op_array, return_value TSRMLS_CC); zend_execute_ex(execute_data TSRMLS_CC); } static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) { - vm_frame_kind frame_kind = EX(frame_kind); + vm_frame_kind frame_kind = VM_FRAME_KIND(EX(frame_info)); if (frame_kind == VM_FRAME_NESTED_FUNCTION) { + zend_object *object; + i_free_compiled_variables(execute_data TSRMLS_CC); if (UNEXPECTED(EX(symbol_table) != NULL)) { zend_clean_and_cache_symbol_table(EX(symbol_table) TSRMLS_CC); @@ -395,26 +397,22 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_CLOSURE) != 0) && EX(func)->op_array.prototype) { OBJ_RELEASE((zend_object*)EX(func)->op_array.prototype); } + object = Z_OBJ(EX(This)); zend_vm_stack_free_call_frame(execute_data TSRMLS_CC); execute_data = EG(current_execute_data); - if (Z_OBJ(EG(This))) { + if (object) { if (UNEXPECTED(EG(exception) != NULL) && (EX(opline)->op1.num & ZEND_CALL_CTOR)) { if (!(EX(opline)->op1.num & ZEND_CALL_CTOR_RESULT_UNUSED)) { - Z_DELREF(EG(This)); + GC_REFCOUNT(object)--; } - if (Z_REFCOUNT(EG(This)) == 1) { - zend_object_store_ctor_failed(Z_OBJ(EG(This)) TSRMLS_CC); + if (GC_REFCOUNT(object) == 1) { + zend_object_store_ctor_failed(object TSRMLS_CC); } } - if (!Z_DELREF(EG(This))) { - _zval_dtor_func_for_ptr(Z_COUNTED(EG(This)) ZEND_FILE_LINE_CC); - } else if (UNEXPECTED(!Z_GC_INFO(EG(This)))) { - gc_possible_root(Z_COUNTED(EG(This)) TSRMLS_CC); - } + OBJ_RELEASE(object); } - Z_OBJ(EG(This)) = EX(object); EG(scope) = EX(scope); if (UNEXPECTED(EG(exception) != NULL)) { @@ -488,25 +486,15 @@ static int ZEND_FASTCALL ZEND_JMP_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) ZEND_VM_CONTINUE(); } -static int ZEND_FASTCALL ZEND_INIT_STRING_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *tmp = EX_VAR(opline->result.var); - - SAVE_OPLINE(); - ZVAL_EMPTY_STRING(tmp); - /*CHECK_EXCEPTION();*/ - ZEND_VM_NEXT_OPCODE(); -} - static int ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_execute_data *call = EX(call); zend_function *fbc = call->func; + zend_object *object = Z_OBJ(call->This); SAVE_OPLINE(); - EX(call) = call->prev_nested_call; + EX(call) = call->prev_execute_data; if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) { if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 0)) { zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", fbc->common.scope->name->val, fbc->common.function_name->val); @@ -521,22 +509,6 @@ static int ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } } } - if (fbc->common.scope && - !(fbc->common.fn_flags & ZEND_ACC_STATIC) && - !call->object) { - - if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - /* FIXME: output identifiers properly */ - zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically", fbc->common.scope->name->val, fbc->common.function_name->val); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - } else { - /* FIXME: output identifiers properly */ - /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically", fbc->common.scope->name->val, fbc->common.function_name->val); - } - } LOAD_OPLINE(); @@ -546,16 +518,16 @@ static int ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) if (fbc->common.scope) { should_change_scope = 1; - Z_OBJ(EG(This)) = call->object; /* TODO: we don't set scope if we call an object method ??? */ /* See: ext/pdo_sqlite/tests/pdo_fetch_func_001.phpt */ #if 1 - EG(scope) = (call->object) ? NULL : fbc->common.scope; + EG(scope) = object ? NULL : fbc->common.scope; #else EG(scope) = fbc->common.scope; #endif } else { call->called_scope = EX(called_scope); + Z_OBJ(call->This) = Z_OBJ(EX(This)); } call->prev_execute_data = execute_data; @@ -566,7 +538,7 @@ static int ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zval *p = ZEND_CALL_ARG(call, 1); for (i = 0; i < call->num_args; ++i) { - zend_verify_arg_type(fbc, i + 1, p, 0 TSRMLS_CC); + zend_verify_arg_type(fbc, i + 1, p TSRMLS_CC); p++; } if (UNEXPECTED(EG(exception) != NULL)) { @@ -590,7 +562,7 @@ static int ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) if (!zend_execute_internal) { /* saves one function call if zend_execute_internal is not used */ - fbc->internal_function.handler(call->num_args, ret TSRMLS_CC); + fbc->internal_function.handler(call, ret TSRMLS_CC); } else { zend_execute_internal(call, ret TSRMLS_CC); } @@ -608,18 +580,7 @@ static int ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) goto fcall_end; } } else if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) { - zval *return_value = NULL; - - Z_OBJ(EG(This)) = call->object; - EG(scope) = fbc->common.scope; - call->symbol_table = NULL; - if (RETURN_VALUE_USED(opline)) { - return_value = EX_VAR(opline->result.var); - - ZVAL_NULL(return_value); - Z_VAR_FLAGS_P(return_value) = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0 ? IS_VAR_RET_REF : 0; - } - + call->scope = EG(scope) = fbc->common.scope; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_GENERATOR) != 0)) { if (RETURN_VALUE_USED(opline)) { zend_generator_create_zval(call, &fbc->op_array, EX_VAR(opline->result.var) TSRMLS_CC); @@ -629,26 +590,38 @@ static int ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zend_vm_stack_free_call_frame(call TSRMLS_CC); } else { + zval *return_value = NULL; + + call->symbol_table = NULL; + if (RETURN_VALUE_USED(opline)) { + return_value = EX_VAR(opline->result.var); + + ZVAL_NULL(return_value); + Z_VAR_FLAGS_P(return_value) = 0; + } + call->prev_execute_data = execute_data; - i_init_func_execute_data(call, &fbc->op_array, return_value, EXPECTED(zend_execute_ex == execute_ex) ? VM_FRAME_NESTED_FUNCTION : VM_FRAME_TOP_FUNCTION TSRMLS_CC); + i_init_func_execute_data(call, &fbc->op_array, return_value TSRMLS_CC); if (EXPECTED(zend_execute_ex == execute_ex)) { ZEND_VM_ENTER(); } else { + call->frame_info = VM_FRAME_INFO( + VM_FRAME_TOP_FUNCTION, + VM_FRAME_FLAGS(call->frame_info)); zend_execute_ex(call TSRMLS_CC); } } } else { /* ZEND_OVERLOADED_FUNCTION */ - Z_OBJ(EG(This)) = call->object; EG(scope) = fbc->common.scope; ZVAL_NULL(EX_VAR(opline->result.var)); /* Not sure what should be done here if it's a static method */ - if (EXPECTED(call->object != NULL)) { + if (EXPECTED(object != NULL)) { call->prev_execute_data = execute_data; EG(current_execute_data) = call; - call->object->handlers->call_method(fbc->common.function_name, call->object, call->num_args, EX_VAR(opline->result.var) TSRMLS_CC); + object->handlers->call_method(fbc->common.function_name, object, call, EX_VAR(opline->result.var) TSRMLS_CC); EG(current_execute_data) = call->prev_execute_data; } else { zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object"); @@ -673,22 +646,17 @@ static int ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } fcall_end_change_scope: - if (Z_OBJ(EG(This))) { + if (object) { if (UNEXPECTED(EG(exception) != NULL) && (opline->op1.num & ZEND_CALL_CTOR)) { if (!(opline->op1.num & ZEND_CALL_CTOR_RESULT_UNUSED)) { - Z_DELREF(EG(This)); + GC_REFCOUNT(object)--; } - if (Z_REFCOUNT(EG(This)) == 1) { - zend_object_store_ctor_failed(Z_OBJ(EG(This)) TSRMLS_CC); + if (GC_REFCOUNT(object) == 1) { + zend_object_store_ctor_failed(object TSRMLS_CC); } } - if (!Z_DELREF(EG(This))) { - _zval_dtor_func_for_ptr(Z_COUNTED(EG(This)) ZEND_FILE_LINE_CC); - } else if (UNEXPECTED(!Z_GC_INFO(EG(This)))) { - gc_possible_root(Z_COUNTED(EG(This)) TSRMLS_CC); - } + OBJ_RELEASE(object); } - Z_OBJ(EG(This)) = EX(object); EG(scope) = EX(scope); fcall_end: @@ -895,12 +863,12 @@ static int ZEND_FASTCALL ZEND_SEND_ARRAY_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) if (EX(call)->func->common.fn_flags & ZEND_ACC_CLOSURE) { OBJ_RELEASE((zend_object*)EX(call)->func->common.prototype); } - if (EX(call)->object) { - OBJ_RELEASE(EX(call)->object); + if (Z_OBJ(EX(call)->This)) { + OBJ_RELEASE(Z_OBJ(EX(call)->This)); } EX(call)->func = (zend_function*)&zend_pass_function; EX(call)->called_scope = NULL; - EX(call)->object = NULL; + Z_OBJ(EX(call)->This) = NULL; } else { uint32_t arg_num = 1; @@ -958,12 +926,12 @@ static int ZEND_FASTCALL ZEND_SEND_ARRAY_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) if (EX(call)->func->common.fn_flags & ZEND_ACC_CLOSURE) { OBJ_RELEASE((zend_object*)EX(call)->func->common.prototype); } - if (EX(call)->object) { - OBJ_RELEASE(EX(call)->object); + if (Z_OBJ(EX(call)->This)) { + OBJ_RELEASE(Z_OBJ(EX(call)->This)); } EX(call)->func = (zend_function*)&zend_pass_function; EX(call)->called_scope = NULL; - EX(call)->object = NULL; + Z_OBJ(EX(call)->This) = NULL; break; } @@ -1010,7 +978,7 @@ static int ZEND_FASTCALL ZEND_RECV_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } else if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) { zval *param = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC); - zend_verify_arg_type(EX(func), arg_num, param, opline->extended_value TSRMLS_CC); + zend_verify_arg_type(EX(func), arg_num, param TSRMLS_CC); CHECK_EXCEPTION(); } @@ -1035,7 +1003,7 @@ static int ZEND_FASTCALL ZEND_RECV_VARIADIC_SPEC_HANDLER(ZEND_OPCODE_HANDLER_AR param = EX_VAR_NUM(EX(func)->op_array.last_var + EX(func)->op_array.T); if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) { do { - zend_verify_arg_type(EX(func), arg_num, param, opline->extended_value TSRMLS_CC); + zend_verify_arg_type(EX(func), arg_num, param TSRMLS_CC); zend_hash_next_index_insert_new(Z_ARRVAL_P(params), param); if (Z_REFCOUNTED_P(param)) Z_ADDREF_P(param); param++; @@ -1055,63 +1023,15 @@ static int ZEND_FASTCALL ZEND_RECV_VARIADIC_SPEC_HANDLER(ZEND_OPCODE_HANDLER_AR ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_NEW_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval object_zval; - zend_function *constructor; - - SAVE_OPLINE(); - if (UNEXPECTED((Z_CE_P(EX_VAR(opline->op1.var))->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) != 0)) { - if (Z_CE_P(EX_VAR(opline->op1.var))->ce_flags & ZEND_ACC_INTERFACE) { - zend_error_noreturn(E_ERROR, "Cannot instantiate interface %s", Z_CE_P(EX_VAR(opline->op1.var))->name->val); - } else if ((Z_CE_P(EX_VAR(opline->op1.var))->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) { - zend_error_noreturn(E_ERROR, "Cannot instantiate trait %s", Z_CE_P(EX_VAR(opline->op1.var))->name->val); - } else { - zend_error_noreturn(E_ERROR, "Cannot instantiate abstract class %s", Z_CE_P(EX_VAR(opline->op1.var))->name->val); - } - } - object_init_ex(&object_zval, Z_CE_P(EX_VAR(opline->op1.var))); - constructor = Z_OBJ_HT(object_zval)->get_constructor(Z_OBJ(object_zval) TSRMLS_CC); - - if (constructor == NULL) { - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), &object_zval); - } else { - zval_ptr_dtor(&object_zval); - } - ZEND_VM_JMP(opline->op2.jmp_addr); - } else { - /* We are not handling overloaded classes right now */ - EX(call) = zend_vm_stack_push_call_frame( - constructor, opline->extended_value, - RETURN_VALUE_USED(opline) ? - ZEND_CALL_CTOR : (ZEND_CALL_CTOR | ZEND_CALL_CTOR_RESULT_UNUSED), - Z_CE_P(EX_VAR(opline->op1.var)), - Z_OBJ(object_zval), - EX(call) TSRMLS_CC); - - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), &object_zval); - EX(call)->return_value = EX_VAR(opline->result.var); - } else { - EX(call)->return_value = NULL; - } - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } -} - static int ZEND_FASTCALL ZEND_BEGIN_SILENCE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE SAVE_OPLINE(); ZVAL_LONG(EX_VAR(opline->result.var), EG(error_reporting)); - if (Z_TYPE(EX(old_error_reporting)) == IS_UNDEF) { - ZVAL_LONG(&EX(old_error_reporting), EG(error_reporting)); - EX(old_error_reporting).u2.silence_num = opline->op2.num; + if (EX(silence_op_num) == -1) { + EX(silence_op_num) = opline->op2.num; + EX(old_error_reporting) = EG(error_reporting); } if (EG(error_reporting)) { @@ -1142,13 +1062,6 @@ static int ZEND_FASTCALL ZEND_BEGIN_SILENCE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_AR ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_RAISE_ABSTRACT_ERROR_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - SAVE_OPLINE(); - zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", EX(scope)->name->val, EX(func)->op_array.function_name->val); - ZEND_VM_NEXT_OPCODE(); /* Never reached */ -} - static int ZEND_FASTCALL ZEND_EXT_STMT_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { SAVE_OPLINE(); @@ -1261,7 +1174,7 @@ static int ZEND_FASTCALL ZEND_ADD_TRAIT_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } else { trait = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, - opline->extended_value TSRMLS_CC); + ZEND_FETCH_CLASS_TRAIT TSRMLS_CC); if (UNEXPECTED(trait == NULL)) { CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -1319,18 +1232,18 @@ static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER * arguments pushed to the stack that have to be dtor'ed. */ zend_vm_stack_free_args(EX(call) TSRMLS_CC); - if (call->object) { - if (call->flags & ZEND_CALL_CTOR) { - if (!(call->flags & ZEND_CALL_CTOR_RESULT_UNUSED)) { - GC_REFCOUNT(call->object)--; + if (Z_OBJ(call->This)) { + if (call->frame_info & ZEND_CALL_CTOR) { + if (!(call->frame_info & ZEND_CALL_CTOR_RESULT_UNUSED)) { + GC_REFCOUNT(Z_OBJ(call->This))--; } - if (GC_REFCOUNT(call->object) == 1) { - zend_object_store_ctor_failed(call->object TSRMLS_CC); + if (GC_REFCOUNT(Z_OBJ(call->This)) == 1) { + zend_object_store_ctor_failed(Z_OBJ(call->This) TSRMLS_CC); } } - OBJ_RELEASE(call->object); + OBJ_RELEASE(Z_OBJ(call->This)); } - EX(call) = call->prev_nested_call; + EX(call) = call->prev_execute_data; zend_vm_stack_free_call_frame(call TSRMLS_CC); call = EX(call); } while (call); @@ -1347,13 +1260,9 @@ static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER catch_op_num >= EX(func)->op_array.brk_cont_array[i].brk) { zend_op *brk_opline = &EX(func)->op_array.opcodes[EX(func)->op_array.brk_cont_array[i].brk]; - if (brk_opline->opcode == ZEND_SWITCH_FREE) { + if (brk_opline->opcode == ZEND_FREE) { if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) { - zval_ptr_dtor(EX_VAR(brk_opline->op1.var)); - } - } else if (brk_opline->opcode == ZEND_FREE) { - if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) { - zval_dtor(EX_VAR(brk_opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(brk_opline->op1.var)); } } } @@ -1361,10 +1270,10 @@ static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER } /* restore previous error_reporting value */ - if (!EG(error_reporting) && Z_TYPE(EX(old_error_reporting)) != IS_UNDEF && Z_LVAL(EX(old_error_reporting)) != 0) { - EG(error_reporting) = Z_LVAL(EX(old_error_reporting)); + if (!EG(error_reporting) && EX(silence_op_num) != -1 && EX(old_error_reporting) != 0) { + EG(error_reporting) = EX(old_error_reporting); } - ZVAL_UNDEF(&EX(old_error_reporting)); + EX(silence_op_num) = -1; if (finally_op_num && (!catch_op_num || catch_op_num >= finally_op_num)) { if (EX(delayed_exception)) { @@ -1514,7 +1423,7 @@ static int ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLE if (CACHED_PTR(Z_CACHE_SLOT_P(class_name))) { Z_CE_P(EX_VAR(opline->result.var)) = CACHED_PTR(Z_CACHE_SLOT_P(class_name)); } else { - Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class_by_name(Z_STR_P(class_name), opline->op2.zv + 1, opline->extended_value TSRMLS_CC); + Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class_by_name(Z_STR_P(class_name), opline->op2.zv + 1, 0 TSRMLS_CC); CACHE_PTR(Z_CACHE_SLOT_P(class_name), Z_CE_P(EX_VAR(opline->result.var))); } } else if (Z_TYPE_P(class_name) == IS_OBJECT) { @@ -1551,8 +1460,8 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), fbc); } - EX(call) = zend_vm_stack_push_call_frame( - fbc, opline->extended_value, 0, NULL, NULL, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_FUNCTION, + fbc, opline->extended_value, NULL, NULL, EX(call) TSRMLS_CC); /*CHECK_EXCEPTION();*/ ZEND_VM_NEXT_OPCODE(); @@ -1635,13 +1544,25 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE if (UNEXPECTED(fbc == NULL)) { zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", called_scope->name->val, Z_STRVAL_P(method)); } + if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { + if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + zend_error(E_STRICT, + "Non-static method %s::%s() should not be called statically", + fbc->common.scope->name->val, fbc->common.function_name->val); + } else { + zend_error_noreturn( + E_ERROR, + "Non-static method %s::%s() cannot be called statically", + fbc->common.scope->name->val, fbc->common.function_name->val); + } + } } else { called_scope = Z_OBJCE_P(obj); object = Z_OBJ_P(obj); fbc = Z_OBJ_HT_P(obj)->get_method(&object, Z_STR_P(method), NULL TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(object), Z_STRVAL_P(method)); + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", object->ce->name->val, Z_STRVAL_P(method)); } if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { @@ -1658,8 +1579,8 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE zend_error_noreturn(E_ERROR, "Function name must be a string"); ZEND_VM_CONTINUE(); /* Never reached */ } - EX(call) = zend_vm_stack_push_call_frame( - fbc, opline->extended_value, 0, called_scope, object, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_FUNCTION, + fbc, opline->extended_value, called_scope, object, EX(call) TSRMLS_CC); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -1690,8 +1611,8 @@ static int ZEND_FASTCALL ZEND_INIT_NS_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPC CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), fbc); } - EX(call) = zend_vm_stack_push_call_frame( - fbc, opline->extended_value, 0, NULL, NULL, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_FUNCTION, + fbc, opline->extended_value, NULL, NULL, EX(call) TSRMLS_CC); ZEND_VM_NEXT_OPCODE(); } @@ -1714,8 +1635,8 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER CACHE_PTR(Z_CACHE_SLOT_P(fname), fbc); } - EX(call) = zend_vm_stack_push_call_frame( - fbc, opline->extended_value, 0, NULL, NULL, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_FUNCTION, + fbc, opline->extended_value, NULL, NULL, EX(call) TSRMLS_CC); ZEND_VM_NEXT_OPCODE(); } @@ -1741,7 +1662,7 @@ static int ZEND_FASTCALL ZEND_RECV_INIT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ } if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) { - zend_verify_arg_type(EX(func), arg_num, param, opline->extended_value TSRMLS_CC); + zend_verify_arg_type(EX(func), arg_num, param TSRMLS_CC); } CHECK_EXCEPTION(); @@ -1782,13 +1703,9 @@ static int ZEND_FASTCALL ZEND_GOTO_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) brk_opline = EX(func)->op_array.opcodes + el->brk; - if (brk_opline->opcode == ZEND_SWITCH_FREE) { + if (brk_opline->opcode == ZEND_FREE) { if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) { - zval_ptr_dtor(EX_VAR(brk_opline->op1.var)); - } - } else if (brk_opline->opcode == ZEND_FREE) { - if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) { - zval_dtor(EX_VAR(brk_opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(brk_opline->op1.var)); } } ZEND_VM_JMP(opline->op1.jmp_addr); @@ -1804,7 +1721,7 @@ static int ZEND_FASTCALL ZEND_ADD_INTERFACE_SPEC_CONST_HANDLER(ZEND_OPCODE_HAND if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { iface = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); } else { - iface = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, opline->extended_value TSRMLS_CC); + iface = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, ZEND_FETCH_CLASS_INTERFACE TSRMLS_CC); if (UNEXPECTED(iface == NULL)) { CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -1841,7 +1758,7 @@ static int ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ if (CACHED_PTR(Z_CACHE_SLOT_P(class_name))) { Z_CE_P(EX_VAR(opline->result.var)) = CACHED_PTR(Z_CACHE_SLOT_P(class_name)); } else { - Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class_by_name(Z_STR_P(class_name), opline->op2.zv + 1, opline->extended_value TSRMLS_CC); + Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class_by_name(Z_STR_P(class_name), opline->op2.zv + 1, 0 TSRMLS_CC); CACHE_PTR(Z_CACHE_SLOT_P(class_name), Z_CE_P(EX_VAR(opline->result.var))); } } else if (Z_TYPE_P(class_name) == IS_OBJECT) { @@ -1855,7 +1772,7 @@ static int ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ zend_error_noreturn(E_ERROR, "Class name must be a valid object or a string"); } - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -1879,8 +1796,8 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_H CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), fbc); } - EX(call) = zend_vm_stack_push_call_frame( - fbc, opline->extended_value, 0, NULL, NULL, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_FUNCTION, + fbc, opline->extended_value, NULL, NULL, EX(call) TSRMLS_CC); /*CHECK_EXCEPTION();*/ ZEND_VM_NEXT_OPCODE(); @@ -1907,7 +1824,7 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_H zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(function_name)); } zend_string_free(lcname); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); fbc = Z_FUNC_P(func); called_scope = NULL; @@ -1924,7 +1841,7 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_H /* Delay closure destruction until its invocation */ fbc->common.prototype = (zend_function*)Z_OBJ_P(function_name_ptr); } else if (IS_TMP_VAR == IS_CV) { - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); } } else if (EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) && zend_hash_num_elements(Z_ARRVAL_P(function_name)) == 2) { @@ -1964,13 +1881,25 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_H if (UNEXPECTED(fbc == NULL)) { zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", called_scope->name->val, Z_STRVAL_P(method)); } + if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { + if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + zend_error(E_STRICT, + "Non-static method %s::%s() should not be called statically", + fbc->common.scope->name->val, fbc->common.function_name->val); + } else { + zend_error_noreturn( + E_ERROR, + "Non-static method %s::%s() cannot be called statically", + fbc->common.scope->name->val, fbc->common.function_name->val); + } + } } else { called_scope = Z_OBJCE_P(obj); object = Z_OBJ_P(obj); fbc = Z_OBJ_HT_P(obj)->get_method(&object, Z_STR_P(method), NULL TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(object), Z_STRVAL_P(method)); + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", object->ce->name->val, Z_STRVAL_P(method)); } if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { @@ -1979,7 +1908,7 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_H GC_REFCOUNT(object)++; /* For $this pointer */ } } - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); } else { if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); @@ -1987,8 +1916,8 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_H zend_error_noreturn(E_ERROR, "Function name must be a string"); ZEND_VM_CONTINUE(); /* Never reached */ } - EX(call) = zend_vm_stack_push_call_frame( - fbc, opline->extended_value, 0, called_scope, object, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_FUNCTION, + fbc, opline->extended_value, called_scope, object, EX(call) TSRMLS_CC); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -2015,7 +1944,7 @@ static int ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ if (CACHED_PTR(Z_CACHE_SLOT_P(class_name))) { Z_CE_P(EX_VAR(opline->result.var)) = CACHED_PTR(Z_CACHE_SLOT_P(class_name)); } else { - Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class_by_name(Z_STR_P(class_name), opline->op2.zv + 1, opline->extended_value TSRMLS_CC); + Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class_by_name(Z_STR_P(class_name), opline->op2.zv + 1, 0 TSRMLS_CC); CACHE_PTR(Z_CACHE_SLOT_P(class_name), Z_CE_P(EX_VAR(opline->result.var))); } } else if (Z_TYPE_P(class_name) == IS_OBJECT) { @@ -2053,8 +1982,8 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_H CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), fbc); } - EX(call) = zend_vm_stack_push_call_frame( - fbc, opline->extended_value, 0, NULL, NULL, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_FUNCTION, + fbc, opline->extended_value, NULL, NULL, EX(call) TSRMLS_CC); /*CHECK_EXCEPTION();*/ ZEND_VM_NEXT_OPCODE(); @@ -2138,13 +2067,25 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_H if (UNEXPECTED(fbc == NULL)) { zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", called_scope->name->val, Z_STRVAL_P(method)); } + if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { + if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + zend_error(E_STRICT, + "Non-static method %s::%s() should not be called statically", + fbc->common.scope->name->val, fbc->common.function_name->val); + } else { + zend_error_noreturn( + E_ERROR, + "Non-static method %s::%s() cannot be called statically", + fbc->common.scope->name->val, fbc->common.function_name->val); + } + } } else { called_scope = Z_OBJCE_P(obj); object = Z_OBJ_P(obj); fbc = Z_OBJ_HT_P(obj)->get_method(&object, Z_STR_P(method), NULL TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(object), Z_STRVAL_P(method)); + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", object->ce->name->val, Z_STRVAL_P(method)); } if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { @@ -2161,8 +2102,8 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_H zend_error_noreturn(E_ERROR, "Function name must be a string"); ZEND_VM_CONTINUE(); /* Never reached */ } - EX(call) = zend_vm_stack_push_call_frame( - fbc, opline->extended_value, 0, called_scope, object, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_FUNCTION, + fbc, opline->extended_value, called_scope, object, EX(call) TSRMLS_CC); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -2189,7 +2130,7 @@ static int ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDL if (CACHED_PTR(Z_CACHE_SLOT_P(class_name))) { Z_CE_P(EX_VAR(opline->result.var)) = CACHED_PTR(Z_CACHE_SLOT_P(class_name)); } else { - Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class_by_name(Z_STR_P(class_name), opline->op2.zv + 1, opline->extended_value TSRMLS_CC); + Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class_by_name(Z_STR_P(class_name), opline->op2.zv + 1, 0 TSRMLS_CC); CACHE_PTR(Z_CACHE_SLOT_P(class_name), Z_CE_P(EX_VAR(opline->result.var))); } } else if (Z_TYPE_P(class_name) == IS_OBJECT) { @@ -2228,7 +2169,7 @@ static int ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_A if (CACHED_PTR(Z_CACHE_SLOT_P(class_name))) { Z_CE_P(EX_VAR(opline->result.var)) = CACHED_PTR(Z_CACHE_SLOT_P(class_name)); } else { - Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class_by_name(Z_STR_P(class_name), opline->op2.zv + 1, opline->extended_value TSRMLS_CC); + Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class_by_name(Z_STR_P(class_name), opline->op2.zv + 1, 0 TSRMLS_CC); CACHE_PTR(Z_CACHE_SLOT_P(class_name), Z_CE_P(EX_VAR(opline->result.var))); } } else if (Z_TYPE_P(class_name) == IS_OBJECT) { @@ -2265,8 +2206,8 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HA CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), fbc); } - EX(call) = zend_vm_stack_push_call_frame( - fbc, opline->extended_value, 0, NULL, NULL, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_FUNCTION, + fbc, opline->extended_value, NULL, NULL, EX(call) TSRMLS_CC); /*CHECK_EXCEPTION();*/ ZEND_VM_NEXT_OPCODE(); @@ -2349,13 +2290,25 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HA if (UNEXPECTED(fbc == NULL)) { zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", called_scope->name->val, Z_STRVAL_P(method)); } + if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { + if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + zend_error(E_STRICT, + "Non-static method %s::%s() should not be called statically", + fbc->common.scope->name->val, fbc->common.function_name->val); + } else { + zend_error_noreturn( + E_ERROR, + "Non-static method %s::%s() cannot be called statically", + fbc->common.scope->name->val, fbc->common.function_name->val); + } + } } else { called_scope = Z_OBJCE_P(obj); object = Z_OBJ_P(obj); fbc = Z_OBJ_HT_P(obj)->get_method(&object, Z_STR_P(method), NULL TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(object), Z_STRVAL_P(method)); + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", object->ce->name->val, Z_STRVAL_P(method)); } if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { @@ -2372,8 +2325,8 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HA zend_error_noreturn(E_ERROR, "Function name must be a string"); ZEND_VM_CONTINUE(); /* Never reached */ } - EX(call) = zend_vm_stack_push_call_frame( - fbc, opline->extended_value, 0, called_scope, object, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_FUNCTION, + fbc, opline->extended_value, called_scope, object, EX(call) TSRMLS_CC); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -2544,13 +2497,14 @@ static int ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_AR } if (i_zend_is_true(val TSRMLS_CC)) { + ZVAL_TRUE(EX_VAR(opline->result.var)); opline++; } else { + ZVAL_FALSE(EX_VAR(opline->result.var)); opline = opline->op2.jmp_addr; } - if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -2644,6 +2598,7 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER(ZEND_OPCODE_HAND } } else { ZVAL_COPY_VALUE(EX(return_value), retval_ptr); + Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; if (IS_CONST != IS_TMP_VAR) { zval_opt_copy_ctor_no_imm(EX(return_value)); } @@ -2657,13 +2612,14 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER(ZEND_OPCODE_HAND zend_error_noreturn(E_ERROR, "Cannot return string offsets by reference"); } - if (IS_CONST == IS_VAR && !Z_ISREF_P(retval_ptr)) { - if (opline->extended_value == ZEND_RETURNS_FUNCTION && - (Z_VAR_FLAGS_P(retval_ptr) & IS_VAR_RET_REF)) { - } else { + if (IS_CONST == IS_VAR) { + if (retval_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(retval_ptr) & IS_VAR_RET_REF))) { zend_error(E_NOTICE, "Only variable references should be returned by reference"); if (EX(return_value)) { ZVAL_NEW_REF(EX(return_value), retval_ptr); + Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; if (Z_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr); } break; @@ -2674,6 +2630,7 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER(ZEND_OPCODE_HAND ZVAL_MAKE_REF(retval_ptr); Z_ADDREF_P(retval_ptr); ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr)); + Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; } } while (0); @@ -2762,6 +2719,72 @@ static int ZEND_FASTCALL ZEND_BOOL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_NEW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval object_zval; + zend_function *constructor; + zend_class_entry *ce; + + SAVE_OPLINE(); + if (IS_CONST == IS_CONST) { + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv)); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, 0 TSRMLS_CC); + if (UNEXPECTED(ce == NULL)) { + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op1.var)); + } + if (UNEXPECTED((ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) != 0)) { + if (ce->ce_flags & ZEND_ACC_INTERFACE) { + zend_error_noreturn(E_ERROR, "Cannot instantiate interface %s", ce->name->val); + } else if ((ce->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) { + zend_error_noreturn(E_ERROR, "Cannot instantiate trait %s", ce->name->val); + } else { + zend_error_noreturn(E_ERROR, "Cannot instantiate abstract class %s", ce->name->val); + } + } + object_init_ex(&object_zval, ce); + constructor = Z_OBJ_HT(object_zval)->get_constructor(Z_OBJ(object_zval) TSRMLS_CC); + + if (constructor == NULL) { + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), &object_zval); + } else { + zval_ptr_dtor(&object_zval); + } + ZEND_VM_JMP(opline->op2.jmp_addr); + } else { + /* We are not handling overloaded classes right now */ + EX(call) = zend_vm_stack_push_call_frame( + VM_FRAME_INFO( + VM_FRAME_NESTED_FUNCTION, + RETURN_VALUE_USED(opline) ? + ZEND_CALL_CTOR : (ZEND_CALL_CTOR | ZEND_CALL_CTOR_RESULT_UNUSED)), + constructor, + opline->extended_value, + ce, + Z_OBJ(object_zval), + EX(call) TSRMLS_CC); + + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), &object_zval); + EX(call)->return_value = EX_VAR(opline->result.var); + } else { + EX(call)->return_value = NULL; + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } +} + static int ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -2775,7 +2798,7 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS obj = opline->op1.zv; if (IS_CONST == IS_CONST || - UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT)) { + (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT))) { if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -2886,15 +2909,13 @@ static int ZEND_FASTCALL ZEND_CAST_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) if (UNEXPECTED(Z_OPT_COPYABLE_P(expr))) { zval_copy_ctor_func(expr); } - } else if (IS_CONST != IS_TMP_VAR) { + } else { if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); } } } else { ZVAL_COPY_VALUE(result, expr); - if (IS_CONST != IS_TMP_VAR) { - zval_opt_copy_ctor(result); - } + Z_ADDREF_P(result); convert_to_array(result); } } else { @@ -2906,21 +2927,16 @@ static int ZEND_FASTCALL ZEND_CAST_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) if (UNEXPECTED(Z_OPT_COPYABLE_P(expr))) { zval_copy_ctor_func(expr); } - } else if (IS_CONST != IS_TMP_VAR) { + } else { if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); } } } else { ZVAL_COPY_VALUE(result, expr); - if (IS_CONST != IS_TMP_VAR) { - zval_opt_copy_ctor(result); - } + zval_opt_copy_ctor(result); convert_to_object(result); } } - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); } CHECK_EXCEPTION(); @@ -2941,8 +2957,7 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HA ZVAL_UNDEF(&tmp_inc_filename); if (Z_TYPE_P(inc_filename) != IS_STRING) { - ZVAL_DUP(&tmp_inc_filename, inc_filename); - convert_to_string(&tmp_inc_filename); + ZVAL_STR(&tmp_inc_filename, zval_get_string(inc_filename)); inc_filename = &tmp_inc_filename; } @@ -3021,8 +3036,8 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HA return_value = EX_VAR(opline->result.var); } - call = zend_vm_stack_push_call_frame( - (zend_function*)new_op_array, 0, 0, EX(called_scope), EX(object), NULL TSRMLS_CC); + call = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_CODE, + (zend_function*)new_op_array, 0, EX(called_scope), Z_OBJ(EX(This)), NULL TSRMLS_CC); if (EX(symbol_table)) { call->symbol_table = EX(symbol_table); @@ -3031,10 +3046,11 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HA } call->prev_execute_data = execute_data; - i_init_code_execute_data(call, new_op_array, return_value, EXPECTED(zend_execute_ex == execute_ex) ? VM_FRAME_NESTED_CODE : VM_FRAME_TOP_CODE TSRMLS_CC); + i_init_code_execute_data(call, new_op_array, return_value TSRMLS_CC); if (EXPECTED(zend_execute_ex == execute_ex)) { ZEND_VM_ENTER(); } else { + call->frame_info = VM_FRAME_TOP_CODE; zend_execute_ex(call TSRMLS_CC); } @@ -3075,13 +3091,8 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_A } if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref); } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { - if(Z_OBJ_HT_P(array_ptr)->get_class_entry == NULL) { - zend_error(E_WARNING, "foreach() cannot iterate over objects without PHP class"); - ZEND_VM_JMP(opline->op2.jmp_addr); - } - ce = Z_OBJCE_P(array_ptr); - if (!ce || ce->get_iterator == NULL) { + if (ce->get_iterator == NULL) { Z_ADDREF_P(array_ptr); } array_ref = array_ptr; @@ -3093,7 +3104,10 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_A ZVAL_DEREF(array_ptr); if (IS_CONST == IS_TMP_VAR) { ZVAL_COPY_VALUE(&tmp, array_ptr); - array_ptr = &tmp; + if (Z_OPT_IMMUTABLE_P(&tmp)) { + zval_copy_ctor_func(&tmp); + } + array_ref = array_ptr = &tmp; if (Z_TYPE_P(array_ptr) == IS_OBJECT) { ce = Z_OBJCE_P(array_ptr); if (ce && ce->get_iterator) { @@ -3102,17 +3116,18 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_A } } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { ce = Z_OBJCE_P(array_ptr); - if (!ce || !ce->get_iterator) { + if (!ce->get_iterator) { if (IS_CONST == IS_CV) { Z_ADDREF_P(array_ref); } } } else if (Z_IMMUTABLE_P(array_ref)) { if (IS_CONST == IS_CV) { - zval_copy_ctor(array_ref); + zval_copy_ctor_func(array_ref); Z_ADDREF_P(array_ref); } else { - ZVAL_DUP(&tmp, array_ref); + ZVAL_COPY_VALUE(&tmp, array_ref); + zval_copy_ctor_func(&tmp); array_ptr = array_ref = &tmp; } } else if (Z_REFCOUNTED_P(array_ref)) { @@ -3133,14 +3148,13 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_A ZVAL_UNREF(array_ref); array_ptr = array_ref; } - if (Z_IMMUTABLE_P(array_ptr) || - (Z_ISREF_P(array_ref) && - Z_REFCOUNTED_P(array_ptr) && - Z_REFCOUNT_P(array_ptr) > 1)) { - if (!Z_IMMUTABLE_P(array_ptr)) { - Z_DELREF_P(array_ptr); - } - zval_copy_ctor(array_ptr); + if (Z_IMMUTABLE_P(array_ptr)) { + zval_copy_ctor_func(array_ptr); + } else if (Z_ISREF_P(array_ref) && + Z_COPYABLE_P(array_ptr) && + Z_REFCOUNT_P(array_ptr) > 1) { + Z_DELREF_P(array_ptr); + zval_copy_ctor_func(array_ptr); } if (IS_CONST == IS_CV) { Z_ADDREF_P(array_ref); @@ -3224,6 +3238,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_A ptr->pos = pos; ptr->ht = fe_ht; ptr->h = fe_ht->arData[pos].h; + ptr->key = fe_ht->arData[pos].key; is_empty = 0; } else { zend_error(E_WARNING, "Invalid argument supplied for foreach()"); @@ -3296,6 +3311,40 @@ static int ZEND_FASTCALL ZEND_JMP_SET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_AR ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_COALESCE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *value; + int is_ref = 0; + + SAVE_OPLINE(); + value = opline->op1.zv; + + if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && Z_ISREF_P(value)) { + is_ref = 1; + value = Z_REFVAL_P(value); + } + + if (Z_TYPE_P(value) > IS_NULL) { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value); + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + zval_copy_ctor_func(EX_VAR(opline->result.var)); + } + } else if (IS_CONST == IS_CV) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } else if (IS_CONST == IS_VAR && is_ref) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + + } + ZEND_VM_JMP(opline->op2.jmp_addr); + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -3382,16 +3431,12 @@ static int ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER break; case IS_OBJECT: if (Z_TYPE_P(value) == opline->extended_value) { - if (Z_OBJ_HT_P(value)->get_class_entry == NULL) { - ZVAL_TRUE(EX_VAR(opline->result.var)); + zend_class_entry *ce = Z_OBJCE_P(value); + if (ce->name->len == sizeof("__PHP_Incomplete_Class") - 1 + && !strncmp(ce->name->val, "__PHP_Incomplete_Class", ce->name->len)) { + ZVAL_FALSE(EX_VAR(opline->result.var)); } else { - zend_class_entry *ce = Z_OBJCE_P(value); - if (ce->name->len == sizeof("__PHP_Incomplete_Class") - 1 - && !strncmp(ce->name->val, "__PHP_Incomplete_Class", ce->name->len)) { - ZVAL_FALSE(EX_VAR(opline->result.var)); - } else { - ZVAL_TRUE(EX_VAR(opline->result.var)); - } + ZVAL_TRUE(EX_VAR(opline->result.var)); } } else { ZVAL_FALSE(EX_VAR(opline->result.var)); @@ -3811,9 +3856,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_CONST(int type } ZVAL_COPY(EX_VAR(opline->result.var), retval); } else { - if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) { - ZVAL_MAKE_REF(retval); - } ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); } CHECK_EXCEPTION(); @@ -3866,9 +3908,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_ container = opline->op1.zv; zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); - if (IS_CONST != IS_VAR || !(opline->extended_value & ZEND_FETCH_ADD_LOCK)) { - } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -3904,6 +3944,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_CONST_HANDLER(ZEND_ if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -3923,7 +3964,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_CONST_HANDLER(ZEND_ ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CONST_CONST(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -3935,7 +3976,7 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CONST_CONS container = opline->op1.zv; offset = opline->op2.zv; - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { zend_error(E_NOTICE, "Trying to get property of non-object"); ZVAL_NULL(EX_VAR(opline->result.var)); @@ -3955,11 +3996,6 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CONST_CONS ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_property_address_read_helper_SPEC_CONST_CONST(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -3972,7 +4008,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE container = opline->op1.zv; offset = opline->op2.zv; - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -4011,7 +4047,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_CONST_HANDLER(ZEND_ if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CONST, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -4020,11 +4056,11 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_CONST_HANDLER(ZEND_ CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { - return zend_fetch_property_address_read_helper_SPEC_CONST_CONST(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return ZEND_FETCH_OBJ_R_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -static int ZEND_FASTCALL ZEND_FETCH_DIM_TMP_VAR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_LIST_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -4033,14 +4069,25 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_TMP_VAR_SPEC_CONST_CONST_HANDLER(ZEND_O SAVE_OPLINE(); container = opline->op1.zv; - if (UNEXPECTED(Z_TYPE_P(container) != IS_ARRAY)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } else { + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { zval *value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), opline->op2.zv, IS_CONST, BP_VAR_R TSRMLS_CC); ZVAL_COPY(EX_VAR(opline->result.var), value); + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT) && + EXPECTED(Z_OBJ_HT_P(container)->read_dimension)) { + zval *result = EX_VAR(opline->result.var); + zval *retval = Z_OBJ_HT_P(container)->read_dimension(container, opline->op2.zv, BP_VAR_R, result TSRMLS_CC); + if (retval) { + if (result != retval) { + ZVAL_COPY(result, retval); + } + } else { + ZVAL_NULL(result); + } + } else { + ZVAL_NULL(EX_VAR(opline->result.var)); } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -4119,7 +4166,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER( if (UNEXPECTED(ce->constructor == NULL)) { zend_error_noreturn(E_ERROR, "Cannot call constructor"); } - if (EX(object) && zend_get_class_entry(EX(object) TSRMLS_CC) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val); } fbc = ce->constructor; @@ -4127,19 +4174,27 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER( object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { - if (EX(object)) { - object = EX(object); + if (Z_OBJ(EX(This))) { + object = Z_OBJ(EX(This)); GC_REFCOUNT(object)++; - if (object->handlers->get_class_entry && - !instanceof_function(zend_get_class_entry(object TSRMLS_CC), ce TSRMLS_CC)) { - /* We are calling method of the other (incompatible) class, - but passing $this. This is done for compatibility with php-4. */ - if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val); - } else { - /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val); - } + } + if (!object || + !instanceof_function(object->ce, ce TSRMLS_CC)) { + /* We are calling method of the other (incompatible) class, + but passing $this. This is done for compatibility with php-4. */ + if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + zend_error( + object ? E_DEPRECATED : E_STRICT, + "Non-static method %s::%s() should not be called statically%s", + fbc->common.scope->name->val, fbc->common.function_name->val, + object ? ", assuming $this from incompatible context" : ""); + } else { + /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ + zend_error_noreturn( + E_ERROR, + "Non-static method %s::%s() cannot be called statically%s", + fbc->common.scope->name->val, fbc->common.function_name->val, + object ? ", assuming $this from incompatible context" : ""); } } } @@ -4151,8 +4206,8 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER( } } - EX(call) = zend_vm_stack_push_call_frame( - fbc, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_FUNCTION, + fbc, opline->extended_value, ce, object, EX(call) TSRMLS_CC); if (IS_CONST == IS_UNUSED) { EX(call)->return_value = NULL; @@ -4187,6 +4242,18 @@ static int ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONST_HANDLER(ZEND_OPCO object = fcc.object; if (object) { GC_REFCOUNT(object)++; /* For $this pointer */ + } else if (func->common.scope && + !(func->common.fn_flags & ZEND_ACC_STATIC)) { + if (func->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + zend_error(E_STRICT, + "Non-static method %s::%s() should not be called statically", + func->common.scope->name->val, func->common.function_name->val); + } else { + zend_error_noreturn( + E_ERROR, + "Non-static method %s::%s() cannot be called statically", + func->common.scope->name->val, func->common.function_name->val); + } } } else { zend_error(E_WARNING, "%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(opline->op1.zv), error); @@ -4196,8 +4263,8 @@ static int ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONST_HANDLER(ZEND_OPCO object = NULL; } - EX(call) = zend_vm_stack_push_call_frame( - func, opline->extended_value, 0, called_scope, object, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_FUNCTION, + func, opline->extended_value, called_scope, object, EX(call) TSRMLS_CC); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -4232,14 +4299,16 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCO } else if ((c = zend_quick_get_constant(opline->op2.zv + 1, opline->extended_value TSRMLS_CC)) == NULL) { if ((opline->extended_value & IS_CONSTANT_UNQUALIFIED) != 0) { char *actual = (char *)zend_memrchr(Z_STRVAL_P(opline->op2.zv), '\\', Z_STRLEN_P(opline->op2.zv)); - if(!actual) { - actual = Z_STRVAL_P(opline->op2.zv); + if (!actual) { + ZVAL_STR(EX_VAR(opline->result.var), zend_string_copy(Z_STR_P(opline->op2.zv))); } else { actual++; + ZVAL_STRINGL(EX_VAR(opline->result.var), + actual, Z_STRLEN_P(opline->op2.zv) - (actual - Z_STRVAL_P(opline->op2.zv))); } /* non-qualified constant - allow text substitution */ - zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", actual, actual); - ZVAL_STRINGL(EX_VAR(opline->result.var), actual, Z_STRLEN_P(opline->op2.zv)-(actual - Z_STRVAL_P(opline->op2.zv))); + zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", + Z_STRVAL_P(EX_VAR(opline->result.var)), Z_STRVAL_P(EX_VAR(opline->result.var))); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { @@ -4271,7 +4340,7 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCO } else if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) { ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv)); } else { - ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, opline->extended_value TSRMLS_CC); + ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, 0 TSRMLS_CC); if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -4467,8 +4536,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HA ZVAL_UNDEF(&tmp); if (IS_CONST != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { - ZVAL_DUP(&tmp, varname); - convert_to_string(&tmp); + ZVAL_STR(&tmp, zval_get_string(varname)); varname = &tmp; } @@ -4513,26 +4581,28 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_CONST_HANDLER(ZEND_O { USE_OPLINE zval *value; - zend_bool isset = 1; SAVE_OPLINE(); if (IS_CONST == IS_CV && IS_CONST == IS_UNUSED && (opline->extended_value & ZEND_QUICK_SET)) { - if (Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_UNDEF) { - value = EX_VAR(opline->op1.var); - ZVAL_DEREF(value); - } else { - isset = 0; + value = EX_VAR(opline->op1.var); + if (opline->extended_value & ZEND_ISSET) { + ZVAL_BOOL(EX_VAR(opline->result.var), + Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + ZVAL_BOOL(EX_VAR(opline->result.var), + !i_zend_is_true(value TSRMLS_CC)); + CHECK_EXCEPTION(); } + ZEND_VM_NEXT_OPCODE(); } else { - HashTable *target_symbol_table; zval tmp, *varname = opline->op1.zv; if (IS_CONST != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { - ZVAL_DUP(&tmp, varname); - convert_to_string(&tmp); + ZVAL_STR(&tmp, zval_get_string(varname)); varname = &tmp; } @@ -4554,39 +4624,27 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_CONST_HANDLER(ZEND_O ce = Z_CE_P(EX_VAR(opline->op2.var)); } value = zend_std_get_static_property(ce, Z_STR_P(varname), 1, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); - if (!value) { - isset = 0; - } } else { - target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); - if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) { - isset = 0; - } + HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname)); } if (IS_CONST != IS_CONST && varname == &tmp) { zval_dtor(&tmp); } - } - - if (opline->extended_value & ZEND_ISSET) { - if (isset && Z_TYPE_P(value) != IS_NULL && - (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) { - ZVAL_BOOL(EX_VAR(opline->result.var), 1); - } else { - ZVAL_BOOL(EX_VAR(opline->result.var), 0); - } - } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { - if (!isset || !i_zend_is_true(value TSRMLS_CC)) { - ZVAL_BOOL(EX_VAR(opline->result.var), 1); - } else { - ZVAL_BOOL(EX_VAR(opline->result.var), 0); + if (opline->extended_value & ZEND_ISSET) { + ZVAL_BOOL(EX_VAR(opline->result.var), + value && Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + ZVAL_BOOL(EX_VAR(opline->result.var), + !value || !i_zend_is_true(value TSRMLS_CC)); } - } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } } static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -4602,7 +4660,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_CONST_HANDLER(ZE container = opline->op1.zv; offset = opline->op2.zv; - if (Z_TYPE_P(container) == IS_ARRAY) { + if (IS_CONST != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { HashTable *ht = Z_ARRVAL_P(container); zval *value; zend_string *str; @@ -4655,8 +4713,8 @@ num_index_prop: } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); } - } else if (Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->has_dimension) { + } else if (IS_CONST == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to check element of non-array"); @@ -4665,7 +4723,7 @@ num_index_prop: if ((opline->extended_value & ZEND_ISSET) == 0) { result = !result; } - } else if (Z_TYPE_P(container) == IS_STRING) { /* string offsets */ + } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */ zval tmp; result = 0; @@ -4681,7 +4739,7 @@ num_index_prop: offset = &tmp; } } - if (Z_TYPE_P(offset) == IS_LONG) { + if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) { if ((opline->extended_value & ZEND_ISSET) || Z_STRVAL_P(container)[offset->value.lval] != '0') { @@ -4714,8 +4772,8 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_CONST_HANDLER(Z container = opline->op1.zv; offset = opline->op2.zv; - if (Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->has_property) { + if (IS_CONST == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_property)) { result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to check property of non-object"); @@ -4802,7 +4860,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLE /* Temporary variables don't need ctor copying */ if (IS_CONST != IS_TMP_VAR) { - zval_copy_ctor(&generator->value); + zval_opt_copy_ctor(&generator->value); } } else { zval *value_ptr = NULL; @@ -4813,9 +4871,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLE /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_CONST == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_CONST == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -4922,7 +4981,7 @@ static int ZEND_FASTCALL ZEND_ADD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR opline->op1.zv, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -4937,7 +4996,7 @@ static int ZEND_FASTCALL ZEND_SUB_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR opline->op1.zv, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -4952,7 +5011,7 @@ static int ZEND_FASTCALL ZEND_MUL_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR opline->op1.zv, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -4967,7 +5026,7 @@ static int ZEND_FASTCALL ZEND_DIV_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR opline->op1.zv, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -4982,7 +5041,7 @@ static int ZEND_FASTCALL ZEND_MOD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR opline->op1.zv, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -4997,7 +5056,7 @@ static int ZEND_FASTCALL ZEND_SL_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG opline->op1.zv, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -5012,7 +5071,7 @@ static int ZEND_FASTCALL ZEND_SR_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG opline->op1.zv, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -5027,7 +5086,7 @@ static int ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER opline->op1.zv, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -5042,7 +5101,7 @@ static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_H opline->op1.zv, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -5058,7 +5117,7 @@ static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CONST_TMP_HANDLER(ZEND_OPCO opline->op1.zv, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -5074,7 +5133,7 @@ static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDL opline->op1.zv, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -5090,7 +5149,7 @@ static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_H opline->op1.zv, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -5106,7 +5165,7 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HAN opline->op1.zv, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -5122,7 +5181,7 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_TMP_HANDLER(ZEND_O opline->op1.zv, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -5137,7 +5196,7 @@ static int ZEND_FASTCALL ZEND_BW_OR_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ opline->op1.zv, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -5152,7 +5211,7 @@ static int ZEND_FASTCALL ZEND_BW_AND_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER opline->op1.zv, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -5167,7 +5226,7 @@ static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER opline->op1.zv, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -5182,7 +5241,7 @@ static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDL opline->op1.zv, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -5196,10 +5255,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HA SAVE_OPLINE(); container = opline->op1.zv; zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); - zval_dtor(free_op2.var); - if (IS_CONST != IS_VAR || !(opline->extended_value & ZEND_FETCH_ADD_LOCK)) { + zval_ptr_dtor_nogc(free_op2.var); - } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -5213,7 +5270,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_H SAVE_OPLINE(); container = opline->op1.zv; zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -5235,11 +5292,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_TMP_HANDLER(ZEND_OP if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); } else { if (IS_TMP_VAR == IS_UNUSED) { @@ -5247,14 +5305,14 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_TMP_HANDLER(ZEND_OP } container = opline->op1.zv; zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CONST_TMP(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -5266,7 +5324,7 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CONST_TMP( container = opline->op1.zv; offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { zend_error(E_NOTICE, "Trying to get property of non-object"); ZVAL_NULL(EX_VAR(opline->result.var)); @@ -5281,17 +5339,12 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CONST_TMP( } } - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_property_address_read_helper_SPEC_CONST_TMP(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -5304,7 +5357,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_H container = opline->op1.zv; offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -5318,7 +5371,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_H } } - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -5344,8 +5397,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_TMP_HANDLER(ZEND_OP if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); - zval_dtor(free_op2.var); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CONST, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } @@ -5353,7 +5406,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_TMP_HANDLER(ZEND_OP CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { - return zend_fetch_property_address_read_helper_SPEC_CONST_TMP(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return ZEND_FETCH_OBJ_R_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } @@ -5424,13 +5477,13 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZE } } if (IS_TMP_VAR != IS_CONST) { - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); } } else { if (UNEXPECTED(ce->constructor == NULL)) { zend_error_noreturn(E_ERROR, "Cannot call constructor"); } - if (EX(object) && zend_get_class_entry(EX(object) TSRMLS_CC) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val); } fbc = ce->constructor; @@ -5438,19 +5491,27 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZE object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { - if (EX(object)) { - object = EX(object); + if (Z_OBJ(EX(This))) { + object = Z_OBJ(EX(This)); GC_REFCOUNT(object)++; - if (object->handlers->get_class_entry && - !instanceof_function(zend_get_class_entry(object TSRMLS_CC), ce TSRMLS_CC)) { - /* We are calling method of the other (incompatible) class, - but passing $this. This is done for compatibility with php-4. */ - if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val); - } else { - /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val); - } + } + if (!object || + !instanceof_function(object->ce, ce TSRMLS_CC)) { + /* We are calling method of the other (incompatible) class, + but passing $this. This is done for compatibility with php-4. */ + if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + zend_error( + object ? E_DEPRECATED : E_STRICT, + "Non-static method %s::%s() should not be called statically%s", + fbc->common.scope->name->val, fbc->common.function_name->val, + object ? ", assuming $this from incompatible context" : ""); + } else { + /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ + zend_error_noreturn( + E_ERROR, + "Non-static method %s::%s() cannot be called statically%s", + fbc->common.scope->name->val, fbc->common.function_name->val, + object ? ", assuming $this from incompatible context" : ""); } } } @@ -5462,8 +5523,8 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZE } } - EX(call) = zend_vm_stack_push_call_frame( - fbc, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_FUNCTION, + fbc, opline->extended_value, ce, object, EX(call) TSRMLS_CC); if (IS_TMP_VAR == IS_UNUSED) { EX(call)->return_value = NULL; @@ -5498,6 +5559,18 @@ static int ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE object = fcc.object; if (object) { GC_REFCOUNT(object)++; /* For $this pointer */ + } else if (func->common.scope && + !(func->common.fn_flags & ZEND_ACC_STATIC)) { + if (func->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + zend_error(E_STRICT, + "Non-static method %s::%s() should not be called statically", + func->common.scope->name->val, func->common.function_name->val); + } else { + zend_error_noreturn( + E_ERROR, + "Non-static method %s::%s() cannot be called statically", + func->common.scope->name->val, func->common.function_name->val); + } } } else { zend_error(E_WARNING, "%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(opline->op1.zv), error); @@ -5507,10 +5580,10 @@ static int ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE object = NULL; } - EX(call) = zend_vm_stack_push_call_frame( - func, opline->extended_value, 0, called_scope, object, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_FUNCTION, + func, opline->extended_value, called_scope, object, EX(call) TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -5526,7 +5599,7 @@ static int ZEND_FASTCALL ZEND_CASE_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_A opline->op1.zv, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -5611,7 +5684,7 @@ str_index: /* do nothing */ break; } - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); } else { zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr); } @@ -5663,7 +5736,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_TMP_HANDLER(ZEND container = opline->op1.zv; offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (Z_TYPE_P(container) == IS_ARRAY) { + if (IS_CONST != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { HashTable *ht = Z_ARRVAL_P(container); zval *value; zend_string *str; @@ -5716,8 +5789,8 @@ num_index_prop: } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); } - } else if (Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->has_dimension) { + } else if (IS_CONST == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to check element of non-array"); @@ -5726,7 +5799,7 @@ num_index_prop: if ((opline->extended_value & ZEND_ISSET) == 0) { result = !result; } - } else if (Z_TYPE_P(container) == IS_STRING) { /* string offsets */ + } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */ zval tmp; result = 0; @@ -5742,7 +5815,7 @@ num_index_prop: offset = &tmp; } } - if (Z_TYPE_P(offset) == IS_LONG) { + if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) { if ((opline->extended_value & ZEND_ISSET) || Z_STRVAL_P(container)[offset->value.lval] != '0') { @@ -5757,7 +5830,7 @@ num_index_prop: result = ((opline->extended_value & ZEND_ISSET) == 0); } - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); ZVAL_BOOL(EX_VAR(opline->result.var), result); CHECK_EXCEPTION(); @@ -5776,8 +5849,8 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_TMP_HANDLER(ZEN container = opline->op1.zv; offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->has_property) { + if (IS_CONST == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_property)) { result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to check property of non-object"); @@ -5790,7 +5863,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_TMP_HANDLER(ZEN result = ((opline->extended_value & ZEND_ISSET) == 0); } - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); ZVAL_BOOL(EX_VAR(opline->result.var), result); CHECK_EXCEPTION(); @@ -5832,7 +5905,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ /* Temporary variables don't need ctor copying */ if (IS_CONST != IS_TMP_VAR) { - zval_copy_ctor(&generator->value); + zval_opt_copy_ctor(&generator->value); } } else { zval *value_ptr = NULL; @@ -5843,9 +5916,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_CONST == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_CONST == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -5937,7 +6011,7 @@ static int ZEND_FASTCALL ZEND_POW_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR opline->op1.zv, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -6323,9 +6397,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_VAR(int type, } ZVAL_COPY(EX_VAR(opline->result.var), retval); } else { - if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) { - ZVAL_MAKE_REF(retval); - } ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); } CHECK_EXCEPTION(); @@ -6378,9 +6449,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HA container = opline->op1.zv; zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); - if (IS_CONST != IS_VAR || !(opline->extended_value & ZEND_FETCH_ADD_LOCK)) { - } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -6416,6 +6485,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_VAR_HANDLER(ZEND_OP if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC); if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -6435,7 +6505,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_VAR_HANDLER(ZEND_OP ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CONST_VAR(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -6447,7 +6517,7 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CONST_VAR( container = opline->op1.zv; offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { zend_error(E_NOTICE, "Trying to get property of non-object"); ZVAL_NULL(EX_VAR(opline->result.var)); @@ -6468,11 +6538,6 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CONST_VAR( ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_property_address_read_helper_SPEC_CONST_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -6485,7 +6550,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_H container = opline->op1.zv; offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -6525,7 +6590,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_VAR_HANDLER(ZEND_OP if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CONST, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -6534,7 +6599,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_VAR_HANDLER(ZEND_OP CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { - return zend_fetch_property_address_read_helper_SPEC_CONST_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return ZEND_FETCH_OBJ_R_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } @@ -6611,7 +6676,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZE if (UNEXPECTED(ce->constructor == NULL)) { zend_error_noreturn(E_ERROR, "Cannot call constructor"); } - if (EX(object) && zend_get_class_entry(EX(object) TSRMLS_CC) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val); } fbc = ce->constructor; @@ -6619,19 +6684,27 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZE object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { - if (EX(object)) { - object = EX(object); + if (Z_OBJ(EX(This))) { + object = Z_OBJ(EX(This)); GC_REFCOUNT(object)++; - if (object->handlers->get_class_entry && - !instanceof_function(zend_get_class_entry(object TSRMLS_CC), ce TSRMLS_CC)) { - /* We are calling method of the other (incompatible) class, - but passing $this. This is done for compatibility with php-4. */ - if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val); - } else { - /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val); - } + } + if (!object || + !instanceof_function(object->ce, ce TSRMLS_CC)) { + /* We are calling method of the other (incompatible) class, + but passing $this. This is done for compatibility with php-4. */ + if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + zend_error( + object ? E_DEPRECATED : E_STRICT, + "Non-static method %s::%s() should not be called statically%s", + fbc->common.scope->name->val, fbc->common.function_name->val, + object ? ", assuming $this from incompatible context" : ""); + } else { + /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ + zend_error_noreturn( + E_ERROR, + "Non-static method %s::%s() cannot be called statically%s", + fbc->common.scope->name->val, fbc->common.function_name->val, + object ? ", assuming $this from incompatible context" : ""); } } } @@ -6643,8 +6716,8 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZE } } - EX(call) = zend_vm_stack_push_call_frame( - fbc, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_FUNCTION, + fbc, opline->extended_value, ce, object, EX(call) TSRMLS_CC); if (IS_VAR == IS_UNUSED) { EX(call)->return_value = NULL; @@ -6679,6 +6752,18 @@ static int ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE object = fcc.object; if (object) { GC_REFCOUNT(object)++; /* For $this pointer */ + } else if (func->common.scope && + !(func->common.fn_flags & ZEND_ACC_STATIC)) { + if (func->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + zend_error(E_STRICT, + "Non-static method %s::%s() should not be called statically", + func->common.scope->name->val, func->common.function_name->val); + } else { + zend_error_noreturn( + E_ERROR, + "Non-static method %s::%s() cannot be called statically", + func->common.scope->name->val, func->common.function_name->val); + } } } else { zend_error(E_WARNING, "%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(opline->op1.zv), error); @@ -6688,8 +6773,8 @@ static int ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE object = NULL; } - EX(call) = zend_vm_stack_push_call_frame( - func, opline->extended_value, 0, called_scope, object, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_FUNCTION, + func, opline->extended_value, called_scope, object, EX(call) TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); @@ -6865,8 +6950,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HAND ZVAL_UNDEF(&tmp); if (IS_CONST != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { - ZVAL_DUP(&tmp, varname); - convert_to_string(&tmp); + ZVAL_STR(&tmp, zval_get_string(varname)); varname = &tmp; } @@ -6911,26 +6995,28 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_VAR_HANDLER(ZEND_OPC { USE_OPLINE zval *value; - zend_bool isset = 1; SAVE_OPLINE(); if (IS_CONST == IS_CV && IS_VAR == IS_UNUSED && (opline->extended_value & ZEND_QUICK_SET)) { - if (Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_UNDEF) { - value = EX_VAR(opline->op1.var); - ZVAL_DEREF(value); - } else { - isset = 0; + value = EX_VAR(opline->op1.var); + if (opline->extended_value & ZEND_ISSET) { + ZVAL_BOOL(EX_VAR(opline->result.var), + Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + ZVAL_BOOL(EX_VAR(opline->result.var), + !i_zend_is_true(value TSRMLS_CC)); + CHECK_EXCEPTION(); } + ZEND_VM_NEXT_OPCODE(); } else { - HashTable *target_symbol_table; zval tmp, *varname = opline->op1.zv; if (IS_CONST != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { - ZVAL_DUP(&tmp, varname); - convert_to_string(&tmp); + ZVAL_STR(&tmp, zval_get_string(varname)); varname = &tmp; } @@ -6952,39 +7038,27 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_VAR_HANDLER(ZEND_OPC ce = Z_CE_P(EX_VAR(opline->op2.var)); } value = zend_std_get_static_property(ce, Z_STR_P(varname), 1, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); - if (!value) { - isset = 0; - } } else { - target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); - if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) { - isset = 0; - } + HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname)); } if (IS_CONST != IS_CONST && varname == &tmp) { zval_dtor(&tmp); } - } - - if (opline->extended_value & ZEND_ISSET) { - if (isset && Z_TYPE_P(value) != IS_NULL && - (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) { - ZVAL_BOOL(EX_VAR(opline->result.var), 1); - } else { - ZVAL_BOOL(EX_VAR(opline->result.var), 0); - } - } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { - if (!isset || !i_zend_is_true(value TSRMLS_CC)) { - ZVAL_BOOL(EX_VAR(opline->result.var), 1); - } else { - ZVAL_BOOL(EX_VAR(opline->result.var), 0); + if (opline->extended_value & ZEND_ISSET) { + ZVAL_BOOL(EX_VAR(opline->result.var), + value && Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + ZVAL_BOOL(EX_VAR(opline->result.var), + !value || !i_zend_is_true(value TSRMLS_CC)); } - } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } } static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -7000,7 +7074,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_VAR_HANDLER(ZEND container = opline->op1.zv; offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (Z_TYPE_P(container) == IS_ARRAY) { + if (IS_CONST != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { HashTable *ht = Z_ARRVAL_P(container); zval *value; zend_string *str; @@ -7053,8 +7127,8 @@ num_index_prop: } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); } - } else if (Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->has_dimension) { + } else if (IS_CONST == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to check element of non-array"); @@ -7063,7 +7137,7 @@ num_index_prop: if ((opline->extended_value & ZEND_ISSET) == 0) { result = !result; } - } else if (Z_TYPE_P(container) == IS_STRING) { /* string offsets */ + } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */ zval tmp; result = 0; @@ -7079,7 +7153,7 @@ num_index_prop: offset = &tmp; } } - if (Z_TYPE_P(offset) == IS_LONG) { + if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) { if ((opline->extended_value & ZEND_ISSET) || Z_STRVAL_P(container)[offset->value.lval] != '0') { @@ -7113,8 +7187,8 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_VAR_HANDLER(ZEN container = opline->op1.zv; offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->has_property) { + if (IS_CONST == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_property)) { result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to check property of non-object"); @@ -7169,7 +7243,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ /* Temporary variables don't need ctor copying */ if (IS_CONST != IS_TMP_VAR) { - zval_copy_ctor(&generator->value); + zval_opt_copy_ctor(&generator->value); } } else { zval *value_ptr = NULL; @@ -7180,9 +7254,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_CONST == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_CONST == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -7385,9 +7460,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_UNUSED(int typ } ZVAL_COPY(EX_VAR(opline->result.var), retval); } else { - if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) { - ZVAL_MAKE_REF(retval); - } ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); } CHECK_EXCEPTION(); @@ -7446,6 +7518,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_UNUSED_HANDLER(ZEND if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC); if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -7538,7 +7611,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER if (UNEXPECTED(ce->constructor == NULL)) { zend_error_noreturn(E_ERROR, "Cannot call constructor"); } - if (EX(object) && zend_get_class_entry(EX(object) TSRMLS_CC) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val); } fbc = ce->constructor; @@ -7546,19 +7619,27 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { - if (EX(object)) { - object = EX(object); + if (Z_OBJ(EX(This))) { + object = Z_OBJ(EX(This)); GC_REFCOUNT(object)++; - if (object->handlers->get_class_entry && - !instanceof_function(zend_get_class_entry(object TSRMLS_CC), ce TSRMLS_CC)) { - /* We are calling method of the other (incompatible) class, - but passing $this. This is done for compatibility with php-4. */ - if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val); - } else { - /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val); - } + } + if (!object || + !instanceof_function(object->ce, ce TSRMLS_CC)) { + /* We are calling method of the other (incompatible) class, + but passing $this. This is done for compatibility with php-4. */ + if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + zend_error( + object ? E_DEPRECATED : E_STRICT, + "Non-static method %s::%s() should not be called statically%s", + fbc->common.scope->name->val, fbc->common.function_name->val, + object ? ", assuming $this from incompatible context" : ""); + } else { + /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ + zend_error_noreturn( + E_ERROR, + "Non-static method %s::%s() cannot be called statically%s", + fbc->common.scope->name->val, fbc->common.function_name->val, + object ? ", assuming $this from incompatible context" : ""); } } } @@ -7570,8 +7651,8 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER } } - EX(call) = zend_vm_stack_push_call_frame( - fbc, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_FUNCTION, + fbc, opline->extended_value, ce, object, EX(call) TSRMLS_CC); if (IS_UNUSED == IS_UNUSED) { EX(call)->return_value = NULL; @@ -7734,8 +7815,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_H ZVAL_UNDEF(&tmp); if (IS_CONST != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { - ZVAL_DUP(&tmp, varname); - convert_to_string(&tmp); + ZVAL_STR(&tmp, zval_get_string(varname)); varname = &tmp; } @@ -7780,26 +7860,28 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_UNUSED_HANDLER(ZEND_ { USE_OPLINE zval *value; - zend_bool isset = 1; SAVE_OPLINE(); if (IS_CONST == IS_CV && IS_UNUSED == IS_UNUSED && (opline->extended_value & ZEND_QUICK_SET)) { - if (Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_UNDEF) { - value = EX_VAR(opline->op1.var); - ZVAL_DEREF(value); - } else { - isset = 0; + value = EX_VAR(opline->op1.var); + if (opline->extended_value & ZEND_ISSET) { + ZVAL_BOOL(EX_VAR(opline->result.var), + Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + ZVAL_BOOL(EX_VAR(opline->result.var), + !i_zend_is_true(value TSRMLS_CC)); + CHECK_EXCEPTION(); } + ZEND_VM_NEXT_OPCODE(); } else { - HashTable *target_symbol_table; zval tmp, *varname = opline->op1.zv; if (IS_CONST != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { - ZVAL_DUP(&tmp, varname); - convert_to_string(&tmp); + ZVAL_STR(&tmp, zval_get_string(varname)); varname = &tmp; } @@ -7821,39 +7903,27 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_UNUSED_HANDLER(ZEND_ ce = Z_CE_P(EX_VAR(opline->op2.var)); } value = zend_std_get_static_property(ce, Z_STR_P(varname), 1, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); - if (!value) { - isset = 0; - } } else { - target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); - if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) { - isset = 0; - } + HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname)); } if (IS_CONST != IS_CONST && varname == &tmp) { zval_dtor(&tmp); } - } - - if (opline->extended_value & ZEND_ISSET) { - if (isset && Z_TYPE_P(value) != IS_NULL && - (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) { - ZVAL_BOOL(EX_VAR(opline->result.var), 1); - } else { - ZVAL_BOOL(EX_VAR(opline->result.var), 0); - } - } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { - if (!isset || !i_zend_is_true(value TSRMLS_CC)) { - ZVAL_BOOL(EX_VAR(opline->result.var), 1); - } else { - ZVAL_BOOL(EX_VAR(opline->result.var), 0); + if (opline->extended_value & ZEND_ISSET) { + ZVAL_BOOL(EX_VAR(opline->result.var), + value && Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + ZVAL_BOOL(EX_VAR(opline->result.var), + !value || !i_zend_is_true(value TSRMLS_CC)); } - } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } } static int ZEND_FASTCALL ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -7874,7 +7944,7 @@ static int ZEND_FASTCALL ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_CONST_UNUSED_HANDLER if (closure_is_static || closure_is_being_defined_inside_static_context) { zend_create_closure(EX_VAR(opline->result.var), Z_FUNC_P(zfunc), EX(called_scope), NULL TSRMLS_CC); } else { - zend_create_closure(EX_VAR(opline->result.var), Z_FUNC_P(zfunc), EX(scope), Z_OBJ(EG(This)) ? &EG(This) : NULL TSRMLS_CC); + zend_create_closure(EX_VAR(opline->result.var), Z_FUNC_P(zfunc), EX(scope), Z_OBJ(EX(This)) ? &EX(This) : NULL TSRMLS_CC); } CHECK_EXCEPTION(); @@ -7916,7 +7986,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDL /* Temporary variables don't need ctor copying */ if (IS_CONST != IS_TMP_VAR) { - zval_copy_ctor(&generator->value); + zval_opt_copy_ctor(&generator->value); } } else { zval *value_ptr = NULL; @@ -7927,9 +7997,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDL /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_CONST == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_CONST == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -8296,9 +8367,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HAN container = opline->op1.zv; zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); - if (IS_CONST != IS_VAR || !(opline->extended_value & ZEND_FETCH_ADD_LOCK)) { - } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -8334,6 +8403,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_CV_HANDLER(ZEND_OPC if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -8353,7 +8423,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_CV_HANDLER(ZEND_OPC ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CONST_CV(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -8365,7 +8435,7 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CONST_CV(Z container = opline->op1.zv; offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { zend_error(E_NOTICE, "Trying to get property of non-object"); ZVAL_NULL(EX_VAR(opline->result.var)); @@ -8385,11 +8455,6 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CONST_CV(Z ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_property_address_read_helper_SPEC_CONST_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -8402,7 +8467,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HA container = opline->op1.zv; offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -8441,7 +8506,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_CV_HANDLER(ZEND_OPC if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CONST, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -8450,7 +8515,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_CV_HANDLER(ZEND_OPC CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { - return zend_fetch_property_address_read_helper_SPEC_CONST_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return ZEND_FETCH_OBJ_R_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } @@ -8527,7 +8592,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEN if (UNEXPECTED(ce->constructor == NULL)) { zend_error_noreturn(E_ERROR, "Cannot call constructor"); } - if (EX(object) && zend_get_class_entry(EX(object) TSRMLS_CC) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val); } fbc = ce->constructor; @@ -8535,19 +8600,27 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEN object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { - if (EX(object)) { - object = EX(object); + if (Z_OBJ(EX(This))) { + object = Z_OBJ(EX(This)); GC_REFCOUNT(object)++; - if (object->handlers->get_class_entry && - !instanceof_function(zend_get_class_entry(object TSRMLS_CC), ce TSRMLS_CC)) { - /* We are calling method of the other (incompatible) class, - but passing $this. This is done for compatibility with php-4. */ - if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val); - } else { - /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val); - } + } + if (!object || + !instanceof_function(object->ce, ce TSRMLS_CC)) { + /* We are calling method of the other (incompatible) class, + but passing $this. This is done for compatibility with php-4. */ + if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + zend_error( + object ? E_DEPRECATED : E_STRICT, + "Non-static method %s::%s() should not be called statically%s", + fbc->common.scope->name->val, fbc->common.function_name->val, + object ? ", assuming $this from incompatible context" : ""); + } else { + /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ + zend_error_noreturn( + E_ERROR, + "Non-static method %s::%s() cannot be called statically%s", + fbc->common.scope->name->val, fbc->common.function_name->val, + object ? ", assuming $this from incompatible context" : ""); } } } @@ -8559,8 +8632,8 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEN } } - EX(call) = zend_vm_stack_push_call_frame( - fbc, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_FUNCTION, + fbc, opline->extended_value, ce, object, EX(call) TSRMLS_CC); if (IS_CV == IS_UNUSED) { EX(call)->return_value = NULL; @@ -8595,6 +8668,18 @@ static int ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_ object = fcc.object; if (object) { GC_REFCOUNT(object)++; /* For $this pointer */ + } else if (func->common.scope && + !(func->common.fn_flags & ZEND_ACC_STATIC)) { + if (func->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + zend_error(E_STRICT, + "Non-static method %s::%s() should not be called statically", + func->common.scope->name->val, func->common.function_name->val); + } else { + zend_error_noreturn( + E_ERROR, + "Non-static method %s::%s() cannot be called statically", + func->common.scope->name->val, func->common.function_name->val); + } } } else { zend_error(E_WARNING, "%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(opline->op1.zv), error); @@ -8604,8 +8689,8 @@ static int ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_ object = NULL; } - EX(call) = zend_vm_stack_push_call_frame( - func, opline->extended_value, 0, called_scope, object, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_FUNCTION, + func, opline->extended_value, called_scope, object, EX(call) TSRMLS_CC); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -8631,7 +8716,7 @@ static int ZEND_FASTCALL ZEND_CATCH_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_A CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), catch_ce); } - ce = zend_get_class_entry(EG(exception) TSRMLS_CC); + ce = EG(exception)->ce; #ifdef HAVE_DTRACE if (DTRACE_EXCEPTION_CAUGHT_ENABLED()) { @@ -8811,7 +8896,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_CV_HANDLER(ZEND_ container = opline->op1.zv; offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (Z_TYPE_P(container) == IS_ARRAY) { + if (IS_CONST != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { HashTable *ht = Z_ARRVAL_P(container); zval *value; zend_string *str; @@ -8864,8 +8949,8 @@ num_index_prop: } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); } - } else if (Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->has_dimension) { + } else if (IS_CONST == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to check element of non-array"); @@ -8874,7 +8959,7 @@ num_index_prop: if ((opline->extended_value & ZEND_ISSET) == 0) { result = !result; } - } else if (Z_TYPE_P(container) == IS_STRING) { /* string offsets */ + } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */ zval tmp; result = 0; @@ -8890,7 +8975,7 @@ num_index_prop: offset = &tmp; } } - if (Z_TYPE_P(offset) == IS_LONG) { + if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) { if ((opline->extended_value & ZEND_ISSET) || Z_STRVAL_P(container)[offset->value.lval] != '0') { @@ -8923,8 +9008,8 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_CV_HANDLER(ZEND container = opline->op1.zv; offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->has_property) { + if (IS_CONST == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_property)) { result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to check property of non-object"); @@ -8978,7 +9063,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_A /* Temporary variables don't need ctor copying */ if (IS_CONST != IS_TMP_VAR) { - zval_copy_ctor(&generator->value); + zval_opt_copy_ctor(&generator->value); } } else { zval *value_ptr = NULL; @@ -8989,9 +9074,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_A /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_CONST == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_CONST == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -9096,7 +9182,7 @@ static int ZEND_FASTCALL ZEND_BW_NOT_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); bitwise_not_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -9109,7 +9195,7 @@ static int ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); boolean_not_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -9125,7 +9211,7 @@ static int ZEND_FASTCALL ZEND_ECHO_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zend_print_variable(z TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -9162,7 +9248,7 @@ static int ZEND_FASTCALL ZEND_JMPZ_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } else { opline = opline->op2.jmp_addr; } - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -9193,7 +9279,7 @@ static int ZEND_FASTCALL ZEND_JMPNZ_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } else { opline++; } - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -9224,7 +9310,7 @@ static int ZEND_FASTCALL ZEND_JMPZNZ_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } else { opline = opline->op2.jmp_addr; } - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -9253,13 +9339,14 @@ static int ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS } if (i_zend_is_true(val TSRMLS_CC)) { + zval_ptr_dtor_nogc(free_op1.var); ZVAL_TRUE(EX_VAR(opline->result.var)); opline++; } else { + zval_ptr_dtor_nogc(free_op1.var); ZVAL_FALSE(EX_VAR(opline->result.var)); opline = opline->op2.jmp_addr; } - zval_dtor(free_op1.var); if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -9293,7 +9380,7 @@ static int ZEND_FASTCALL ZEND_JMPNZ_EX_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG ZVAL_FALSE(EX_VAR(opline->result.var)); opline++; } - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -9305,11 +9392,7 @@ static int ZEND_FASTCALL ZEND_FREE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) USE_OPLINE SAVE_OPLINE(); - if (IS_TMP_VAR == IS_TMP_VAR) { - zval_dtor(EX_VAR(opline->op1.var)); - } else { - zval_ptr_dtor(EX_VAR(opline->op1.var)); - } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -9324,7 +9407,7 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) retval_ptr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (!EX(return_value)) { - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); } else { if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { ZVAL_COPY_VALUE(EX(return_value), retval_ptr); @@ -9363,10 +9446,11 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLE retval_ptr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (!EX(return_value)) { if (IS_TMP_VAR == IS_TMP_VAR) { - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); } } else { ZVAL_COPY_VALUE(EX(return_value), retval_ptr); + Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; if (IS_TMP_VAR != IS_TMP_VAR) { zval_opt_copy_ctor_no_imm(EX(return_value)); } @@ -9380,13 +9464,14 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLE zend_error_noreturn(E_ERROR, "Cannot return string offsets by reference"); } - if (IS_TMP_VAR == IS_VAR && !Z_ISREF_P(retval_ptr)) { - if (opline->extended_value == ZEND_RETURNS_FUNCTION && - (Z_VAR_FLAGS_P(retval_ptr) & IS_VAR_RET_REF)) { - } else { + if (IS_TMP_VAR == IS_VAR) { + if (retval_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(retval_ptr) & IS_VAR_RET_REF))) { zend_error(E_NOTICE, "Only variable references should be returned by reference"); if (EX(return_value)) { ZVAL_NEW_REF(EX(return_value), retval_ptr); + Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; if (Z_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr); } break; @@ -9397,6 +9482,7 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLE ZVAL_MAKE_REF(retval_ptr); Z_ADDREF_P(retval_ptr); ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr)); + Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; } } while (0); @@ -9480,7 +9566,7 @@ static int ZEND_FASTCALL ZEND_BOOL_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); /* PHP 3.0 returned "" for false and 1 for true, here we use 0 and 1 for now */ ZVAL_BOOL(retval, i_zend_is_true(_get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC) TSRMLS_CC)); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -9499,7 +9585,7 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) obj = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_TMP_VAR == IS_CONST || - UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT)) { + (IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT))) { if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -9596,7 +9682,6 @@ static int ZEND_FASTCALL ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); } - zval_dtor(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -9611,15 +9696,13 @@ static int ZEND_FASTCALL ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) if (UNEXPECTED(Z_OPT_COPYABLE_P(expr))) { zval_copy_ctor_func(expr); } - } else if (IS_TMP_VAR != IS_TMP_VAR) { + } else { if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); } } } else { ZVAL_COPY_VALUE(result, expr); - if (IS_TMP_VAR != IS_TMP_VAR) { - zval_opt_copy_ctor(result); - } + Z_ADDREF_P(result); convert_to_array(result); } } else { @@ -9631,23 +9714,19 @@ static int ZEND_FASTCALL ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) if (UNEXPECTED(Z_OPT_COPYABLE_P(expr))) { zval_copy_ctor_func(expr); } - } else if (IS_TMP_VAR != IS_TMP_VAR) { + } else { if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); } } } else { ZVAL_COPY_VALUE(result, expr); - if (IS_TMP_VAR != IS_TMP_VAR) { - zval_opt_copy_ctor(result); - } + zval_opt_copy_ctor(result); convert_to_object(result); } } - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); } - zval_dtor(free_op1.var); + + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -9666,8 +9745,7 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HAND ZVAL_UNDEF(&tmp_inc_filename); if (Z_TYPE_P(inc_filename) != IS_STRING) { - ZVAL_DUP(&tmp_inc_filename, inc_filename); - convert_to_string(&tmp_inc_filename); + ZVAL_STR(&tmp_inc_filename, zval_get_string(inc_filename)); inc_filename = &tmp_inc_filename; } @@ -9735,7 +9813,7 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HAND if (Z_TYPE(tmp_inc_filename) != IS_UNDEF) { zval_ptr_dtor(&tmp_inc_filename); } - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } else if (EXPECTED(new_op_array != NULL)) { @@ -9746,8 +9824,8 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HAND return_value = EX_VAR(opline->result.var); } - call = zend_vm_stack_push_call_frame( - (zend_function*)new_op_array, 0, 0, EX(called_scope), EX(object), NULL TSRMLS_CC); + call = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_CODE, + (zend_function*)new_op_array, 0, EX(called_scope), Z_OBJ(EX(This)), NULL TSRMLS_CC); if (EX(symbol_table)) { call->symbol_table = EX(symbol_table); @@ -9756,10 +9834,11 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HAND } call->prev_execute_data = execute_data; - i_init_code_execute_data(call, new_op_array, return_value, EXPECTED(zend_execute_ex == execute_ex) ? VM_FRAME_NESTED_CODE : VM_FRAME_TOP_CODE TSRMLS_CC); + i_init_code_execute_data(call, new_op_array, return_value TSRMLS_CC); if (EXPECTED(zend_execute_ex == execute_ex)) { ZEND_VM_ENTER(); } else { + call->frame_info = VM_FRAME_TOP_CODE; zend_execute_ex(call TSRMLS_CC); } @@ -9800,13 +9879,8 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG } if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref); } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { - if(Z_OBJ_HT_P(array_ptr)->get_class_entry == NULL) { - zend_error(E_WARNING, "foreach() cannot iterate over objects without PHP class"); - ZEND_VM_JMP(opline->op2.jmp_addr); - } - ce = Z_OBJCE_P(array_ptr); - if (!ce || ce->get_iterator == NULL) { + if (ce->get_iterator == NULL) { Z_ADDREF_P(array_ptr); } array_ref = array_ptr; @@ -9818,7 +9892,10 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG ZVAL_DEREF(array_ptr); if (IS_TMP_VAR == IS_TMP_VAR) { ZVAL_COPY_VALUE(&tmp, array_ptr); - array_ptr = &tmp; + if (Z_OPT_IMMUTABLE_P(&tmp)) { + zval_copy_ctor_func(&tmp); + } + array_ref = array_ptr = &tmp; if (Z_TYPE_P(array_ptr) == IS_OBJECT) { ce = Z_OBJCE_P(array_ptr); if (ce && ce->get_iterator) { @@ -9827,17 +9904,18 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG } } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { ce = Z_OBJCE_P(array_ptr); - if (!ce || !ce->get_iterator) { + if (!ce->get_iterator) { if (IS_TMP_VAR == IS_CV) { Z_ADDREF_P(array_ref); } } } else if (Z_IMMUTABLE_P(array_ref)) { if (IS_TMP_VAR == IS_CV) { - zval_copy_ctor(array_ref); + zval_copy_ctor_func(array_ref); Z_ADDREF_P(array_ref); } else { - ZVAL_DUP(&tmp, array_ref); + ZVAL_COPY_VALUE(&tmp, array_ref); + zval_copy_ctor_func(&tmp); array_ptr = array_ref = &tmp; } } else if (Z_REFCOUNTED_P(array_ref)) { @@ -9858,14 +9936,13 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG ZVAL_UNREF(array_ref); array_ptr = array_ref; } - if (Z_IMMUTABLE_P(array_ptr) || - (Z_ISREF_P(array_ref) && - Z_REFCOUNTED_P(array_ptr) && - Z_REFCOUNT_P(array_ptr) > 1)) { - if (!Z_IMMUTABLE_P(array_ptr)) { - Z_DELREF_P(array_ptr); - } - zval_copy_ctor(array_ptr); + if (Z_IMMUTABLE_P(array_ptr)) { + zval_copy_ctor_func(array_ptr); + } else if (Z_ISREF_P(array_ref) && + Z_COPYABLE_P(array_ptr) && + Z_REFCOUNT_P(array_ptr) > 1) { + Z_DELREF_P(array_ptr); + zval_copy_ctor_func(array_ptr); } if (IS_TMP_VAR == IS_CV) { Z_ADDREF_P(array_ref); @@ -9949,6 +10026,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG ptr->pos = pos; ptr->ht = fe_ht; ptr->h = fe_ht->arData[pos].h; + ptr->key = fe_ht->arData[pos].key; is_empty = 0; } else { zend_error(E_WARNING, "Invalid argument supplied for foreach()"); @@ -9981,7 +10059,7 @@ static int ZEND_FASTCALL ZEND_EXIT_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } else { zend_print_variable(ptr TSRMLS_CC); } - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); } #endif zend_bailout(); @@ -9996,9 +10074,8 @@ static int ZEND_FASTCALL ZEND_END_SILENCE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ if (!EG(error_reporting) && Z_LVAL_P(EX_VAR(opline->op1.var)) != 0) { EG(error_reporting) = Z_LVAL_P(EX_VAR(opline->op1.var)); } - if (Z_TYPE(EX(old_error_reporting)) != IS_UNDEF && - EX(old_error_reporting).u2.silence_num == opline->op2.num) { - ZVAL_UNDEF(&EX(old_error_reporting)); + if (EX(silence_op_num) == opline->op2.num) { + EX(silence_op_num) = -1; } ZEND_VM_NEXT_OPCODE(); } @@ -10027,29 +10104,32 @@ static int ZEND_FASTCALL ZEND_JMP_SET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); } else if (IS_TMP_VAR == IS_VAR && is_ref) { if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); } ZEND_VM_JMP(opline->op2.jmp_addr); } - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_COALESCE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; zval *value; + int is_ref = 0; SAVE_OPLINE(); value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && Z_ISREF_P(value)) { - ZVAL_COPY(EX_VAR(opline->result.var), Z_REFVAL_P(value)); - zval_dtor(free_op1.var); - } else { + is_ref = 1; + value = Z_REFVAL_P(value); + } + + if (Z_TYPE_P(value) > IS_NULL) { ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value); if (IS_TMP_VAR == IS_CONST) { if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { @@ -10057,29 +10137,40 @@ static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR } } else if (IS_TMP_VAR == IS_CV) { if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } else if (IS_TMP_VAR == IS_VAR && is_ref) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + zval_ptr_dtor_nogc(free_op1.var); } + ZEND_VM_JMP(opline->op2.jmp_addr); } + + zval_ptr_dtor_nogc(free_op1.var); + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; - zval *expr; - zend_bool result; + zval *value; SAVE_OPLINE(); - expr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (Z_TYPE_P(expr) == IS_OBJECT && Z_OBJ_HT_P(expr)->get_class_entry) { - result = instanceof_function(Z_OBJCE_P(expr), Z_CE_P(EX_VAR(opline->op2.var)) TSRMLS_CC); + if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && Z_ISREF_P(value)) { + ZVAL_COPY(EX_VAR(opline->result.var), Z_REFVAL_P(value)); + zval_ptr_dtor_nogc(free_op1.var); } else { - result = 0; + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value); + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + zval_copy_ctor_func(EX_VAR(opline->result.var)); + } + } else if (IS_TMP_VAR == IS_CV) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } } - ZVAL_BOOL(EX_VAR(opline->result.var), result); - zval_dtor(free_op1.var); - CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -10118,7 +10209,7 @@ strlen_error: ZVAL_NULL(EX_VAR(opline->result.var)); } } - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -10144,16 +10235,12 @@ static int ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_A break; case IS_OBJECT: if (Z_TYPE_P(value) == opline->extended_value) { - if (Z_OBJ_HT_P(value)->get_class_entry == NULL) { - ZVAL_TRUE(EX_VAR(opline->result.var)); + zend_class_entry *ce = Z_OBJCE_P(value); + if (ce->name->len == sizeof("__PHP_Incomplete_Class") - 1 + && !strncmp(ce->name->val, "__PHP_Incomplete_Class", ce->name->len)) { + ZVAL_FALSE(EX_VAR(opline->result.var)); } else { - zend_class_entry *ce = Z_OBJCE_P(value); - if (ce->name->len == sizeof("__PHP_Incomplete_Class") - 1 - && !strncmp(ce->name->val, "__PHP_Incomplete_Class", ce->name->len)) { - ZVAL_FALSE(EX_VAR(opline->result.var)); - } else { - ZVAL_TRUE(EX_VAR(opline->result.var)); - } + ZVAL_TRUE(EX_VAR(opline->result.var)); } } else { ZVAL_FALSE(EX_VAR(opline->result.var)); @@ -10169,7 +10256,7 @@ static int ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_A break; EMPTY_SWITCH_DEFAULT_CASE() } - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -10183,7 +10270,7 @@ static int ZEND_FASTCALL ZEND_ADD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_AR fast_add_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -10198,7 +10285,7 @@ static int ZEND_FASTCALL ZEND_SUB_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_AR fast_sub_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -10213,7 +10300,7 @@ static int ZEND_FASTCALL ZEND_MUL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_AR fast_mul_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -10228,7 +10315,7 @@ static int ZEND_FASTCALL ZEND_DIV_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_AR fast_div_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -10243,7 +10330,7 @@ static int ZEND_FASTCALL ZEND_MOD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_AR fast_mod_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -10258,7 +10345,7 @@ static int ZEND_FASTCALL ZEND_SL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG shift_left_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -10273,7 +10360,7 @@ static int ZEND_FASTCALL ZEND_SR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG shift_right_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -10288,7 +10375,7 @@ static int ZEND_FASTCALL ZEND_CONCAT_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER concat_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -10303,7 +10390,7 @@ static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_H fast_is_identical_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -10319,7 +10406,7 @@ static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCO fast_is_not_identical_function(result, _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -10335,7 +10422,7 @@ static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDL fast_equal_function(result, _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -10351,7 +10438,7 @@ static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_H fast_not_equal_function(result, _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -10367,7 +10454,7 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HAN fast_is_smaller_function(result, _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -10383,7 +10470,7 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMP_CONST_HANDLER(ZEND_O fast_is_smaller_or_equal_function(result, _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -10398,7 +10485,7 @@ static int ZEND_FASTCALL ZEND_BW_OR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ bitwise_or_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -10413,7 +10500,7 @@ static int ZEND_FASTCALL ZEND_BW_AND_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER bitwise_and_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -10428,7 +10515,7 @@ static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER bitwise_xor_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -10443,7 +10530,7 @@ static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDL boolean_xor_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -10482,7 +10569,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_CONST(int type, if (IS_TMP_VAR != IS_CONST) { zend_string_release(name); } - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -10492,7 +10579,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_CONST(int type, ce = Z_CE_P(EX_VAR(opline->op2.var)); } retval = zend_std_get_static_property(ce, name, 0, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); } else { target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); retval = zend_hash_find(target_symbol_table, name); @@ -10540,7 +10627,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_CONST(int type, zval_update_constant(retval, 1 TSRMLS_CC); } } else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) { - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); } } @@ -10555,9 +10642,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_CONST(int type, } ZVAL_COPY(EX_VAR(opline->result.var), retval); } else { - if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) { - ZVAL_MAKE_REF(retval); - } ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); } CHECK_EXCEPTION(); @@ -10610,9 +10694,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HA container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); - if (IS_TMP_VAR != IS_VAR || !(opline->extended_value & ZEND_FETCH_ADD_LOCK)) { - zval_dtor(free_op1.var); - } + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -10627,7 +10709,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_H container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -10648,6 +10730,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CONST_HANDLER(ZEND_OP if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -10661,13 +10744,13 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CONST_HANDLER(ZEND_OP container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_TMP_CONST(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; @@ -10679,7 +10762,7 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_TMP_CONST( container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = opline->op2.zv; - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { zend_error(E_NOTICE, "Trying to get property of non-object"); ZVAL_NULL(EX_VAR(opline->result.var)); @@ -10694,16 +10777,11 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_TMP_CONST( } } - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_property_address_read_helper_SPEC_TMP_CONST(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -10716,7 +10794,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_H container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = opline->op2.zv; - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -10730,7 +10808,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_H } } - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -10755,7 +10833,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CONST_HANDLER(ZEND_OP if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_TMP_VAR, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -10764,11 +10842,11 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CONST_HANDLER(ZEND_OP CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { - return zend_fetch_property_address_read_helper_SPEC_TMP_CONST(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return ZEND_FETCH_OBJ_R_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -static int ZEND_FASTCALL ZEND_FETCH_DIM_TMP_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_LIST_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; @@ -10777,14 +10855,25 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_TMP_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPC SAVE_OPLINE(); container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_ARRAY)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } else { + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { zval *value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), opline->op2.zv, IS_CONST, BP_VAR_R TSRMLS_CC); ZVAL_COPY(EX_VAR(opline->result.var), value); + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT) && + EXPECTED(Z_OBJ_HT_P(container)->read_dimension)) { + zval *result = EX_VAR(opline->result.var); + zval *retval = Z_OBJ_HT_P(container)->read_dimension(container, opline->op2.zv, BP_VAR_R, result TSRMLS_CC); + if (retval) { + if (result != retval) { + ZVAL_COPY(result, retval); + } + } else { + ZVAL_NULL(result); + } + } else { + ZVAL_NULL(EX_VAR(opline->result.var)); } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -10852,19 +10941,55 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_CONST_HANDLER(ZEND_OPCO object = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + uint32_t nesting = 1; + if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); + + zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); + + + if (EG(exception) != NULL) { + HANDLE_EXCEPTION(); + } + + /* No exception raised: Skip over arguments until fcall opcode with correct + * nesting level. Return NULL (except when return value unused) */ + do { + opline++; + if (opline->opcode == ZEND_INIT_FCALL || + opline->opcode == ZEND_INIT_FCALL_BY_NAME || + opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME || + opline->opcode == ZEND_INIT_METHOD_CALL || + opline->opcode == ZEND_INIT_STATIC_METHOD_CALL || + opline->opcode == ZEND_INIT_USER_CALL || + opline->opcode == ZEND_NEW + ) { + nesting++; + } else if (opline->opcode == ZEND_DO_FCALL) { + nesting--; + } + } while (nesting); + + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + /* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */ + if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) { + opline++; + } + ZEND_VM_JMP(++opline); } obj = Z_OBJ_P(object); - called_scope = zend_get_class_entry(obj TSRMLS_CC); + called_scope = obj->ce; if (IS_CONST != IS_CONST || - (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) { + EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { zend_object *orig_obj = obj; if (UNEXPECTED(obj->handlers->get_method == NULL)) { @@ -10874,7 +10999,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_CONST_HANDLER(ZEND_OPCO /* First, locate the function. */ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name)); + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); } if (IS_CONST == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -10884,14 +11009,14 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_CONST_HANDLER(ZEND_OPCO } } - if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { obj = NULL; } else { GC_REFCOUNT(obj)++; /* For $this pointer */ } - EX(call) = zend_vm_stack_push_call_frame( - fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_FUNCTION, + fbc, opline->extended_value, called_scope, obj, EX(call) TSRMLS_CC); CHECK_EXCEPTION(); @@ -11066,8 +11191,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HAND ZVAL_UNDEF(&tmp); if (IS_TMP_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { - ZVAL_DUP(&tmp, varname); - convert_to_string(&tmp); + ZVAL_STR(&tmp, zval_get_string(varname)); varname = &tmp; } @@ -11083,7 +11207,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HAND if (IS_TMP_VAR != IS_CONST) { zval_dtor(&tmp); } - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); HANDLE_EXCEPTION(); } if (UNEXPECTED(ce == NULL)) { @@ -11103,7 +11227,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HAND if (IS_TMP_VAR != IS_CONST) { zval_dtor(&tmp); } - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -11112,26 +11236,28 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPC { USE_OPLINE zval *value; - zend_bool isset = 1; SAVE_OPLINE(); if (IS_TMP_VAR == IS_CV && IS_CONST == IS_UNUSED && (opline->extended_value & ZEND_QUICK_SET)) { - if (Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_UNDEF) { - value = EX_VAR(opline->op1.var); - ZVAL_DEREF(value); - } else { - isset = 0; + value = EX_VAR(opline->op1.var); + if (opline->extended_value & ZEND_ISSET) { + ZVAL_BOOL(EX_VAR(opline->result.var), + Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + ZVAL_BOOL(EX_VAR(opline->result.var), + !i_zend_is_true(value TSRMLS_CC)); + CHECK_EXCEPTION(); } + ZEND_VM_NEXT_OPCODE(); } else { - HashTable *target_symbol_table; zend_free_op free_op1; zval tmp, *varname = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_TMP_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { - ZVAL_DUP(&tmp, varname); - convert_to_string(&tmp); + ZVAL_STR(&tmp, zval_get_string(varname)); varname = &tmp; } @@ -11153,39 +11279,28 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPC ce = Z_CE_P(EX_VAR(opline->op2.var)); } value = zend_std_get_static_property(ce, Z_STR_P(varname), 1, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); - if (!value) { - isset = 0; - } } else { - target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); - if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) { - isset = 0; - } + HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname)); } if (IS_TMP_VAR != IS_CONST && varname == &tmp) { zval_dtor(&tmp); } - zval_dtor(free_op1.var); - } + zval_ptr_dtor_nogc(free_op1.var); - if (opline->extended_value & ZEND_ISSET) { - if (isset && Z_TYPE_P(value) != IS_NULL && - (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) { - ZVAL_BOOL(EX_VAR(opline->result.var), 1); - } else { - ZVAL_BOOL(EX_VAR(opline->result.var), 0); - } - } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { - if (!isset || !i_zend_is_true(value TSRMLS_CC)) { - ZVAL_BOOL(EX_VAR(opline->result.var), 1); - } else { - ZVAL_BOOL(EX_VAR(opline->result.var), 0); + if (opline->extended_value & ZEND_ISSET) { + ZVAL_BOOL(EX_VAR(opline->result.var), + value && Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + ZVAL_BOOL(EX_VAR(opline->result.var), + !value || !i_zend_is_true(value TSRMLS_CC)); } - } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } } static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -11201,7 +11316,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP_CONST_HANDLER(ZEND container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = opline->op2.zv; - if (Z_TYPE_P(container) == IS_ARRAY) { + if (IS_TMP_VAR != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { HashTable *ht = Z_ARRVAL_P(container); zval *value; zend_string *str; @@ -11254,8 +11369,8 @@ num_index_prop: } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); } - } else if (Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->has_dimension) { + } else if (IS_TMP_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to check element of non-array"); @@ -11264,7 +11379,7 @@ num_index_prop: if ((opline->extended_value & ZEND_ISSET) == 0) { result = !result; } - } else if (Z_TYPE_P(container) == IS_STRING) { /* string offsets */ + } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */ zval tmp; result = 0; @@ -11280,7 +11395,7 @@ num_index_prop: offset = &tmp; } } - if (Z_TYPE_P(offset) == IS_LONG) { + if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) { if ((opline->extended_value & ZEND_ISSET) || Z_STRVAL_P(container)[offset->value.lval] != '0') { @@ -11296,7 +11411,7 @@ num_index_prop: } ZVAL_BOOL(EX_VAR(opline->result.var), result); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -11313,8 +11428,8 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMP_CONST_HANDLER(ZEN container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = opline->op2.zv; - if (Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->has_property) { + if (IS_TMP_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_property)) { result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to check property of non-object"); @@ -11328,7 +11443,46 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMP_CONST_HANDLER(ZEN } ZVAL_BOOL(EX_VAR(opline->result.var), result); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *expr; + zend_bool result; + + SAVE_OPLINE(); + expr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + + if (Z_TYPE_P(expr) == IS_OBJECT) { + zend_class_entry *ce; + + if (IS_CONST == IS_CONST) { + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC); + if (UNEXPECTED(ce == NULL)) { + ZVAL_FALSE(EX_VAR(opline->result.var)); + zval_ptr_dtor_nogc(free_op1.var); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op2.var)); + } + result = instanceof_function(Z_OBJCE_P(expr), ce TSRMLS_CC); + } else { + result = 0; + } + ZVAL_BOOL(EX_VAR(opline->result.var), result); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -11368,7 +11522,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ /* Temporary variables don't need ctor copying */ if (IS_TMP_VAR != IS_TMP_VAR) { - zval_copy_ctor(&generator->value); + zval_opt_copy_ctor(&generator->value); } } else { zval *value_ptr = NULL; @@ -11379,9 +11533,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_TMP_VAR == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_TMP_VAR == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -11472,7 +11627,7 @@ static int ZEND_FASTCALL ZEND_POW_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_AR pow_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -11487,8 +11642,8 @@ static int ZEND_FASTCALL ZEND_ADD_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS fast_add_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op1.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -11502,8 +11657,8 @@ static int ZEND_FASTCALL ZEND_SUB_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS fast_sub_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op1.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -11517,8 +11672,8 @@ static int ZEND_FASTCALL ZEND_MUL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS fast_mul_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op1.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -11532,8 +11687,8 @@ static int ZEND_FASTCALL ZEND_DIV_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS fast_div_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op1.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -11547,8 +11702,8 @@ static int ZEND_FASTCALL ZEND_MOD_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS fast_mod_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op1.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -11562,8 +11717,8 @@ static int ZEND_FASTCALL ZEND_SL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) shift_left_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op1.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -11577,8 +11732,8 @@ static int ZEND_FASTCALL ZEND_SR_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) shift_right_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op1.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -11592,8 +11747,8 @@ static int ZEND_FASTCALL ZEND_CONCAT_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_A concat_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op1.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -11607,8 +11762,8 @@ static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HAN fast_is_identical_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op1.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -11623,8 +11778,8 @@ static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE fast_is_not_identical_function(result, _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op1.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -11639,8 +11794,8 @@ static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER fast_equal_function(result, _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op1.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -11655,8 +11810,8 @@ static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HAN fast_not_equal_function(result, _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op1.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -11671,8 +11826,8 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDL fast_is_smaller_function(result, _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op1.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -11687,8 +11842,8 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMP_TMP_HANDLER(ZEND_OPC fast_is_smaller_or_equal_function(result, _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op1.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -11702,8 +11857,8 @@ static int ZEND_FASTCALL ZEND_BW_OR_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR bitwise_or_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op1.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -11717,8 +11872,8 @@ static int ZEND_FASTCALL ZEND_BW_AND_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_A bitwise_and_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op1.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -11732,8 +11887,8 @@ static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_A bitwise_xor_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op1.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -11747,8 +11902,8 @@ static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER boolean_xor_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op1.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -11762,10 +11917,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); - zval_dtor(free_op2.var); - if (IS_TMP_VAR != IS_VAR || !(opline->extended_value & ZEND_FETCH_ADD_LOCK)) { - zval_dtor(free_op1.var); - } + zval_ptr_dtor_nogc(free_op2.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -11779,8 +11932,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HAN SAVE_OPLINE(); container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); - zval_dtor(free_op2.var); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op2.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -11801,11 +11954,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_TMP_HANDLER(ZEND_OPCO if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); } else { if (IS_TMP_VAR == IS_UNUSED) { @@ -11813,14 +11967,14 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_TMP_HANDLER(ZEND_OPCO } container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); - zval_dtor(free_op2.var); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op2.var); + zval_ptr_dtor_nogc(free_op1.var); } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_TMP_TMP(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; @@ -11832,7 +11986,7 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_TMP_TMP(ZE container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { zend_error(E_NOTICE, "Trying to get property of non-object"); ZVAL_NULL(EX_VAR(opline->result.var)); @@ -11847,17 +12001,12 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_TMP_TMP(ZE } } - zval_dtor(free_op2.var); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op2.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_property_address_read_helper_SPEC_TMP_TMP(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -11870,7 +12019,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HAN container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -11884,8 +12033,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HAN } } - zval_dtor(free_op2.var); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op2.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -11910,8 +12059,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TMP_HANDLER(ZEND_OPCO if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); - zval_dtor(free_op2.var); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_TMP_VAR, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } @@ -11919,7 +12068,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TMP_HANDLER(ZEND_OPCO CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { - return zend_fetch_property_address_read_helper_SPEC_TMP_TMP(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return ZEND_FETCH_OBJ_R_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } @@ -11961,7 +12110,7 @@ static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ * which aren't affected by FREE_OP(Ts, )'s anyway, unless they're * string offsets or overloaded objects */ - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -11991,19 +12140,55 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE object = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + uint32_t nesting = 1; + if (UNEXPECTED(EG(exception) != NULL)) { - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); + HANDLE_EXCEPTION(); + } + + zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); + zval_ptr_dtor_nogc(free_op2.var); + + if (EG(exception) != NULL) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); + + /* No exception raised: Skip over arguments until fcall opcode with correct + * nesting level. Return NULL (except when return value unused) */ + do { + opline++; + if (opline->opcode == ZEND_INIT_FCALL || + opline->opcode == ZEND_INIT_FCALL_BY_NAME || + opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME || + opline->opcode == ZEND_INIT_METHOD_CALL || + opline->opcode == ZEND_INIT_STATIC_METHOD_CALL || + opline->opcode == ZEND_INIT_USER_CALL || + opline->opcode == ZEND_NEW + ) { + nesting++; + } else if (opline->opcode == ZEND_DO_FCALL) { + nesting--; + } + } while (nesting); + + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + /* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */ + if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) { + opline++; + } + ZEND_VM_JMP(++opline); } obj = Z_OBJ_P(object); - called_scope = zend_get_class_entry(obj TSRMLS_CC); + called_scope = obj->ce; if (IS_TMP_VAR != IS_CONST || - (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) { + EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { zend_object *orig_obj = obj; if (UNEXPECTED(obj->handlers->get_method == NULL)) { @@ -12013,7 +12198,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE /* First, locate the function. */ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_TMP_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name)); + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); } if (IS_TMP_VAR == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -12023,16 +12208,16 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE } } - if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { obj = NULL; } else { GC_REFCOUNT(obj)++; /* For $this pointer */ } - EX(call) = zend_vm_stack_push_call_frame( - fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_FUNCTION, + fbc, opline->extended_value, called_scope, obj, EX(call) TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -12049,7 +12234,7 @@ static int ZEND_FASTCALL ZEND_CASE_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -12134,7 +12319,7 @@ str_index: /* do nothing */ break; } - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); } else { zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr); } @@ -12186,7 +12371,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP_TMP_HANDLER(ZEND_O container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (Z_TYPE_P(container) == IS_ARRAY) { + if (IS_TMP_VAR != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { HashTable *ht = Z_ARRVAL_P(container); zval *value; zend_string *str; @@ -12239,8 +12424,8 @@ num_index_prop: } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); } - } else if (Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->has_dimension) { + } else if (IS_TMP_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to check element of non-array"); @@ -12249,7 +12434,7 @@ num_index_prop: if ((opline->extended_value & ZEND_ISSET) == 0) { result = !result; } - } else if (Z_TYPE_P(container) == IS_STRING) { /* string offsets */ + } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */ zval tmp; result = 0; @@ -12265,7 +12450,7 @@ num_index_prop: offset = &tmp; } } - if (Z_TYPE_P(offset) == IS_LONG) { + if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) { if ((opline->extended_value & ZEND_ISSET) || Z_STRVAL_P(container)[offset->value.lval] != '0') { @@ -12280,9 +12465,9 @@ num_index_prop: result = ((opline->extended_value & ZEND_ISSET) == 0); } - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); ZVAL_BOOL(EX_VAR(opline->result.var), result); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -12299,8 +12484,8 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMP_TMP_HANDLER(ZEND_ container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->has_property) { + if (IS_TMP_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_property)) { result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to check property of non-object"); @@ -12313,9 +12498,9 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMP_TMP_HANDLER(ZEND_ result = ((opline->extended_value & ZEND_ISSET) == 0); } - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); ZVAL_BOOL(EX_VAR(opline->result.var), result); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -12355,7 +12540,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR /* Temporary variables don't need ctor copying */ if (IS_TMP_VAR != IS_TMP_VAR) { - zval_copy_ctor(&generator->value); + zval_opt_copy_ctor(&generator->value); } } else { zval *value_ptr = NULL; @@ -12366,9 +12551,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_TMP_VAR == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_TMP_VAR == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -12459,8 +12645,8 @@ static int ZEND_FASTCALL ZEND_POW_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS pow_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op1.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -12474,7 +12660,7 @@ static int ZEND_FASTCALL ZEND_ADD_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS fast_add_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -12489,7 +12675,7 @@ static int ZEND_FASTCALL ZEND_SUB_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS fast_sub_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -12504,7 +12690,7 @@ static int ZEND_FASTCALL ZEND_MUL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS fast_mul_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -12519,7 +12705,7 @@ static int ZEND_FASTCALL ZEND_DIV_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS fast_div_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -12534,7 +12720,7 @@ static int ZEND_FASTCALL ZEND_MOD_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS fast_mod_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -12549,7 +12735,7 @@ static int ZEND_FASTCALL ZEND_SL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) shift_left_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -12564,7 +12750,7 @@ static int ZEND_FASTCALL ZEND_SR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) shift_right_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -12579,7 +12765,7 @@ static int ZEND_FASTCALL ZEND_CONCAT_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_A concat_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -12594,7 +12780,7 @@ static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HAN fast_is_identical_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -12610,7 +12796,7 @@ static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE fast_is_not_identical_function(result, _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -12626,7 +12812,7 @@ static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER fast_equal_function(result, _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -12642,7 +12828,7 @@ static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HAN fast_not_equal_function(result, _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -12658,7 +12844,7 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDL fast_is_smaller_function(result, _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -12674,7 +12860,7 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMP_VAR_HANDLER(ZEND_OPC fast_is_smaller_or_equal_function(result, _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -12689,7 +12875,7 @@ static int ZEND_FASTCALL ZEND_BW_OR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR bitwise_or_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -12704,7 +12890,7 @@ static int ZEND_FASTCALL ZEND_BW_AND_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_A bitwise_and_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -12719,7 +12905,7 @@ static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_A bitwise_xor_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -12734,7 +12920,7 @@ static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER boolean_xor_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -12773,7 +12959,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_VAR(int type, ZE if (IS_TMP_VAR != IS_CONST) { zend_string_release(name); } - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -12783,7 +12969,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_VAR(int type, ZE ce = Z_CE_P(EX_VAR(opline->op2.var)); } retval = zend_std_get_static_property(ce, name, 0, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); } else { target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); retval = zend_hash_find(target_symbol_table, name); @@ -12831,7 +13017,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_VAR(int type, ZE zval_update_constant(retval, 1 TSRMLS_CC); } } else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) { - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); } } @@ -12846,9 +13032,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_VAR(int type, ZE } ZVAL_COPY(EX_VAR(opline->result.var), retval); } else { - if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) { - ZVAL_MAKE_REF(retval); - } ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); } CHECK_EXCEPTION(); @@ -12901,9 +13084,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HAND container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); - if (IS_TMP_VAR != IS_VAR || !(opline->extended_value & ZEND_FETCH_ADD_LOCK)) { - zval_dtor(free_op1.var); - } + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -12918,7 +13099,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HAN container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -12939,6 +13120,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_VAR_HANDLER(ZEND_OPCO if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC); if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -12952,13 +13134,13 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_VAR_HANDLER(ZEND_OPCO container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_TMP_VAR(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; @@ -12970,7 +13152,7 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_TMP_VAR(ZE container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { zend_error(E_NOTICE, "Trying to get property of non-object"); ZVAL_NULL(EX_VAR(opline->result.var)); @@ -12986,16 +13168,11 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_TMP_VAR(ZE } zval_ptr_dtor_nogc(free_op2.var); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_property_address_read_helper_SPEC_TMP_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -13008,7 +13185,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HAN container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -13023,7 +13200,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HAN } zval_ptr_dtor_nogc(free_op2.var); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -13048,7 +13225,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_VAR_HANDLER(ZEND_OPCO if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_TMP_VAR, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -13057,7 +13234,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_VAR_HANDLER(ZEND_OPCO CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { - return zend_fetch_property_address_read_helper_SPEC_TMP_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return ZEND_FETCH_OBJ_R_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } @@ -13129,19 +13306,55 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE object = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + uint32_t nesting = 1; + if (UNEXPECTED(EG(exception) != NULL)) { zval_ptr_dtor_nogc(free_op2.var); HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); + + zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); + zval_ptr_dtor_nogc(free_op2.var); + + if (EG(exception) != NULL) { + HANDLE_EXCEPTION(); + } + + /* No exception raised: Skip over arguments until fcall opcode with correct + * nesting level. Return NULL (except when return value unused) */ + do { + opline++; + if (opline->opcode == ZEND_INIT_FCALL || + opline->opcode == ZEND_INIT_FCALL_BY_NAME || + opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME || + opline->opcode == ZEND_INIT_METHOD_CALL || + opline->opcode == ZEND_INIT_STATIC_METHOD_CALL || + opline->opcode == ZEND_INIT_USER_CALL || + opline->opcode == ZEND_NEW + ) { + nesting++; + } else if (opline->opcode == ZEND_DO_FCALL) { + nesting--; + } + } while (nesting); + + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + /* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */ + if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) { + opline++; + } + ZEND_VM_JMP(++opline); } obj = Z_OBJ_P(object); - called_scope = zend_get_class_entry(obj TSRMLS_CC); + called_scope = obj->ce; if (IS_VAR != IS_CONST || - (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) { + EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { zend_object *orig_obj = obj; if (UNEXPECTED(obj->handlers->get_method == NULL)) { @@ -13151,7 +13364,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE /* First, locate the function. */ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name)); + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); } if (IS_VAR == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -13161,14 +13374,14 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE } } - if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { obj = NULL; } else { GC_REFCOUNT(obj)++; /* For $this pointer */ } - EX(call) = zend_vm_stack_push_call_frame( - fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_FUNCTION, + fbc, opline->extended_value, called_scope, obj, EX(call) TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); @@ -13345,8 +13558,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLE ZVAL_UNDEF(&tmp); if (IS_TMP_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { - ZVAL_DUP(&tmp, varname); - convert_to_string(&tmp); + ZVAL_STR(&tmp, zval_get_string(varname)); varname = &tmp; } @@ -13362,7 +13574,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLE if (IS_TMP_VAR != IS_CONST) { zval_dtor(&tmp); } - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); HANDLE_EXCEPTION(); } if (UNEXPECTED(ce == NULL)) { @@ -13382,7 +13594,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLE if (IS_TMP_VAR != IS_CONST) { zval_dtor(&tmp); } - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -13391,26 +13603,28 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCOD { USE_OPLINE zval *value; - zend_bool isset = 1; SAVE_OPLINE(); if (IS_TMP_VAR == IS_CV && IS_VAR == IS_UNUSED && (opline->extended_value & ZEND_QUICK_SET)) { - if (Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_UNDEF) { - value = EX_VAR(opline->op1.var); - ZVAL_DEREF(value); - } else { - isset = 0; + value = EX_VAR(opline->op1.var); + if (opline->extended_value & ZEND_ISSET) { + ZVAL_BOOL(EX_VAR(opline->result.var), + Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + ZVAL_BOOL(EX_VAR(opline->result.var), + !i_zend_is_true(value TSRMLS_CC)); + CHECK_EXCEPTION(); } + ZEND_VM_NEXT_OPCODE(); } else { - HashTable *target_symbol_table; zend_free_op free_op1; zval tmp, *varname = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_TMP_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { - ZVAL_DUP(&tmp, varname); - convert_to_string(&tmp); + ZVAL_STR(&tmp, zval_get_string(varname)); varname = &tmp; } @@ -13432,39 +13646,28 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCOD ce = Z_CE_P(EX_VAR(opline->op2.var)); } value = zend_std_get_static_property(ce, Z_STR_P(varname), 1, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); - if (!value) { - isset = 0; - } } else { - target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); - if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) { - isset = 0; - } + HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname)); } if (IS_TMP_VAR != IS_CONST && varname == &tmp) { zval_dtor(&tmp); } - zval_dtor(free_op1.var); - } + zval_ptr_dtor_nogc(free_op1.var); - if (opline->extended_value & ZEND_ISSET) { - if (isset && Z_TYPE_P(value) != IS_NULL && - (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) { - ZVAL_BOOL(EX_VAR(opline->result.var), 1); - } else { - ZVAL_BOOL(EX_VAR(opline->result.var), 0); - } - } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { - if (!isset || !i_zend_is_true(value TSRMLS_CC)) { - ZVAL_BOOL(EX_VAR(opline->result.var), 1); - } else { - ZVAL_BOOL(EX_VAR(opline->result.var), 0); + if (opline->extended_value & ZEND_ISSET) { + ZVAL_BOOL(EX_VAR(opline->result.var), + value && Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + ZVAL_BOOL(EX_VAR(opline->result.var), + !value || !i_zend_is_true(value TSRMLS_CC)); } - } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } } static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -13480,7 +13683,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP_VAR_HANDLER(ZEND_O container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (Z_TYPE_P(container) == IS_ARRAY) { + if (IS_TMP_VAR != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { HashTable *ht = Z_ARRVAL_P(container); zval *value; zend_string *str; @@ -13533,8 +13736,8 @@ num_index_prop: } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); } - } else if (Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->has_dimension) { + } else if (IS_TMP_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to check element of non-array"); @@ -13543,7 +13746,7 @@ num_index_prop: if ((opline->extended_value & ZEND_ISSET) == 0) { result = !result; } - } else if (Z_TYPE_P(container) == IS_STRING) { /* string offsets */ + } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */ zval tmp; result = 0; @@ -13559,7 +13762,7 @@ num_index_prop: offset = &tmp; } } - if (Z_TYPE_P(offset) == IS_LONG) { + if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) { if ((opline->extended_value & ZEND_ISSET) || Z_STRVAL_P(container)[offset->value.lval] != '0') { @@ -13576,7 +13779,7 @@ num_index_prop: zval_ptr_dtor_nogc(free_op2.var); ZVAL_BOOL(EX_VAR(opline->result.var), result); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -13593,8 +13796,8 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMP_VAR_HANDLER(ZEND_ container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->has_property) { + if (IS_TMP_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_property)) { result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to check property of non-object"); @@ -13609,7 +13812,46 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMP_VAR_HANDLER(ZEND_ zval_ptr_dtor_nogc(free_op2.var); ZVAL_BOOL(EX_VAR(opline->result.var), result); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *expr; + zend_bool result; + + SAVE_OPLINE(); + expr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + + if (Z_TYPE_P(expr) == IS_OBJECT) { + zend_class_entry *ce; + + if (IS_VAR == IS_CONST) { + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC); + if (UNEXPECTED(ce == NULL)) { + ZVAL_FALSE(EX_VAR(opline->result.var)); + zval_ptr_dtor_nogc(free_op1.var); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op2.var)); + } + result = instanceof_function(Z_OBJCE_P(expr), ce TSRMLS_CC); + } else { + result = 0; + } + ZVAL_BOOL(EX_VAR(opline->result.var), result); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -13649,7 +13891,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR /* Temporary variables don't need ctor copying */ if (IS_TMP_VAR != IS_TMP_VAR) { - zval_copy_ctor(&generator->value); + zval_opt_copy_ctor(&generator->value); } } else { zval *value_ptr = NULL; @@ -13660,9 +13902,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_TMP_VAR == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_TMP_VAR == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -13753,7 +13996,7 @@ static int ZEND_FASTCALL ZEND_POW_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS pow_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -13792,7 +14035,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_UNUSED(int type, if (IS_TMP_VAR != IS_CONST) { zend_string_release(name); } - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -13802,7 +14045,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_UNUSED(int type, ce = Z_CE_P(EX_VAR(opline->op2.var)); } retval = zend_std_get_static_property(ce, name, 0, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); } else { target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); retval = zend_hash_find(target_symbol_table, name); @@ -13850,7 +14093,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_UNUSED(int type, zval_update_constant(retval, 1 TSRMLS_CC); } } else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) { - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); } } @@ -13865,9 +14108,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_UNUSED(int type, } ZVAL_COPY(EX_VAR(opline->result.var), retval); } else { - if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) { - ZVAL_MAKE_REF(retval); - } ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); } CHECK_EXCEPTION(); @@ -13926,6 +14166,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_UNUSED_HANDLER(ZEND_O if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC); if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -13939,7 +14180,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_UNUSED_HANDLER(ZEND_O container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -14098,8 +14339,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HAN ZVAL_UNDEF(&tmp); if (IS_TMP_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { - ZVAL_DUP(&tmp, varname); - convert_to_string(&tmp); + ZVAL_STR(&tmp, zval_get_string(varname)); varname = &tmp; } @@ -14115,7 +14355,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HAN if (IS_TMP_VAR != IS_CONST) { zval_dtor(&tmp); } - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); HANDLE_EXCEPTION(); } if (UNEXPECTED(ce == NULL)) { @@ -14135,7 +14375,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HAN if (IS_TMP_VAR != IS_CONST) { zval_dtor(&tmp); } - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -14144,26 +14384,28 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_UNUSED_HANDLER(ZEND_OP { USE_OPLINE zval *value; - zend_bool isset = 1; SAVE_OPLINE(); if (IS_TMP_VAR == IS_CV && IS_UNUSED == IS_UNUSED && (opline->extended_value & ZEND_QUICK_SET)) { - if (Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_UNDEF) { - value = EX_VAR(opline->op1.var); - ZVAL_DEREF(value); - } else { - isset = 0; + value = EX_VAR(opline->op1.var); + if (opline->extended_value & ZEND_ISSET) { + ZVAL_BOOL(EX_VAR(opline->result.var), + Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + ZVAL_BOOL(EX_VAR(opline->result.var), + !i_zend_is_true(value TSRMLS_CC)); + CHECK_EXCEPTION(); } + ZEND_VM_NEXT_OPCODE(); } else { - HashTable *target_symbol_table; zend_free_op free_op1; zval tmp, *varname = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_TMP_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { - ZVAL_DUP(&tmp, varname); - convert_to_string(&tmp); + ZVAL_STR(&tmp, zval_get_string(varname)); varname = &tmp; } @@ -14185,39 +14427,28 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_UNUSED_HANDLER(ZEND_OP ce = Z_CE_P(EX_VAR(opline->op2.var)); } value = zend_std_get_static_property(ce, Z_STR_P(varname), 1, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); - if (!value) { - isset = 0; - } } else { - target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); - if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) { - isset = 0; - } + HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname)); } if (IS_TMP_VAR != IS_CONST && varname == &tmp) { zval_dtor(&tmp); } - zval_dtor(free_op1.var); - } + zval_ptr_dtor_nogc(free_op1.var); - if (opline->extended_value & ZEND_ISSET) { - if (isset && Z_TYPE_P(value) != IS_NULL && - (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) { - ZVAL_BOOL(EX_VAR(opline->result.var), 1); - } else { - ZVAL_BOOL(EX_VAR(opline->result.var), 0); - } - } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { - if (!isset || !i_zend_is_true(value TSRMLS_CC)) { - ZVAL_BOOL(EX_VAR(opline->result.var), 1); - } else { - ZVAL_BOOL(EX_VAR(opline->result.var), 0); + if (opline->extended_value & ZEND_ISSET) { + ZVAL_BOOL(EX_VAR(opline->result.var), + value && Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + ZVAL_BOOL(EX_VAR(opline->result.var), + !value || !i_zend_is_true(value TSRMLS_CC)); } - } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } } static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -14255,7 +14486,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER /* Temporary variables don't need ctor copying */ if (IS_TMP_VAR != IS_TMP_VAR) { - zval_copy_ctor(&generator->value); + zval_opt_copy_ctor(&generator->value); } } else { zval *value_ptr = NULL; @@ -14266,9 +14497,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_TMP_VAR == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_TMP_VAR == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -14359,7 +14591,7 @@ static int ZEND_FASTCALL ZEND_ADD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) fast_add_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -14374,7 +14606,7 @@ static int ZEND_FASTCALL ZEND_SUB_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) fast_sub_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -14389,7 +14621,7 @@ static int ZEND_FASTCALL ZEND_MUL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) fast_mul_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -14404,7 +14636,7 @@ static int ZEND_FASTCALL ZEND_DIV_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) fast_div_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -14419,7 +14651,7 @@ static int ZEND_FASTCALL ZEND_MOD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) fast_mod_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -14434,7 +14666,7 @@ static int ZEND_FASTCALL ZEND_SL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) shift_left_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -14449,7 +14681,7 @@ static int ZEND_FASTCALL ZEND_SR_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) shift_right_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -14464,7 +14696,7 @@ static int ZEND_FASTCALL ZEND_CONCAT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_AR concat_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -14479,7 +14711,7 @@ static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HAND fast_is_identical_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -14495,7 +14727,7 @@ static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_ fast_is_not_identical_function(result, _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -14511,7 +14743,7 @@ static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ fast_equal_function(result, _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -14527,7 +14759,7 @@ static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HAND fast_not_equal_function(result, _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -14543,7 +14775,7 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLE fast_is_smaller_function(result, _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -14559,7 +14791,7 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMP_CV_HANDLER(ZEND_OPCO fast_is_smaller_or_equal_function(result, _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -14574,7 +14806,7 @@ static int ZEND_FASTCALL ZEND_BW_OR_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG bitwise_or_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -14589,7 +14821,7 @@ static int ZEND_FASTCALL ZEND_BW_AND_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_AR bitwise_and_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -14604,7 +14836,7 @@ static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_AR bitwise_xor_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -14619,7 +14851,7 @@ static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ boolean_xor_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -14635,9 +14867,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDL container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); - if (IS_TMP_VAR != IS_VAR || !(opline->extended_value & ZEND_FETCH_ADD_LOCK)) { - zval_dtor(free_op1.var); - } + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -14652,7 +14882,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HAND container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -14673,6 +14903,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV_HANDLER(ZEND_OPCOD if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -14686,13 +14917,13 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV_HANDLER(ZEND_OPCOD container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_TMP_CV(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; @@ -14704,7 +14935,7 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_TMP_CV(ZEN container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { zend_error(E_NOTICE, "Trying to get property of non-object"); ZVAL_NULL(EX_VAR(opline->result.var)); @@ -14719,16 +14950,11 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_TMP_CV(ZEN } } - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_property_address_read_helper_SPEC_TMP_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -14741,7 +14967,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HAND container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -14755,7 +14981,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HAND } } - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -14780,7 +15006,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CV_HANDLER(ZEND_OPCOD if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_TMP_VAR, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -14789,7 +15015,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CV_HANDLER(ZEND_OPCOD CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { - return zend_fetch_property_address_read_helper_SPEC_TMP_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return ZEND_FETCH_OBJ_R_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } @@ -14860,19 +15086,55 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_ object = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + uint32_t nesting = 1; + if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); + + zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); + + + if (EG(exception) != NULL) { + HANDLE_EXCEPTION(); + } + + /* No exception raised: Skip over arguments until fcall opcode with correct + * nesting level. Return NULL (except when return value unused) */ + do { + opline++; + if (opline->opcode == ZEND_INIT_FCALL || + opline->opcode == ZEND_INIT_FCALL_BY_NAME || + opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME || + opline->opcode == ZEND_INIT_METHOD_CALL || + opline->opcode == ZEND_INIT_STATIC_METHOD_CALL || + opline->opcode == ZEND_INIT_USER_CALL || + opline->opcode == ZEND_NEW + ) { + nesting++; + } else if (opline->opcode == ZEND_DO_FCALL) { + nesting--; + } + } while (nesting); + + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + /* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */ + if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) { + opline++; + } + ZEND_VM_JMP(++opline); } obj = Z_OBJ_P(object); - called_scope = zend_get_class_entry(obj TSRMLS_CC); + called_scope = obj->ce; if (IS_CV != IS_CONST || - (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) { + EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { zend_object *orig_obj = obj; if (UNEXPECTED(obj->handlers->get_method == NULL)) { @@ -14882,7 +15144,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_ /* First, locate the function. */ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name)); + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); } if (IS_CV == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -14892,14 +15154,14 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_ } } - if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { obj = NULL; } else { GC_REFCOUNT(obj)++; /* For $this pointer */ } - EX(call) = zend_vm_stack_push_call_frame( - fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_FUNCTION, + fbc, opline->extended_value, called_scope, obj, EX(call) TSRMLS_CC); CHECK_EXCEPTION(); @@ -15053,7 +15315,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP_CV_HANDLER(ZEND_OP container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (Z_TYPE_P(container) == IS_ARRAY) { + if (IS_TMP_VAR != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { HashTable *ht = Z_ARRVAL_P(container); zval *value; zend_string *str; @@ -15106,8 +15368,8 @@ num_index_prop: } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); } - } else if (Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->has_dimension) { + } else if (IS_TMP_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to check element of non-array"); @@ -15116,7 +15378,7 @@ num_index_prop: if ((opline->extended_value & ZEND_ISSET) == 0) { result = !result; } - } else if (Z_TYPE_P(container) == IS_STRING) { /* string offsets */ + } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */ zval tmp; result = 0; @@ -15132,7 +15394,7 @@ num_index_prop: offset = &tmp; } } - if (Z_TYPE_P(offset) == IS_LONG) { + if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) { if ((opline->extended_value & ZEND_ISSET) || Z_STRVAL_P(container)[offset->value.lval] != '0') { @@ -15148,7 +15410,7 @@ num_index_prop: } ZVAL_BOOL(EX_VAR(opline->result.var), result); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -15165,8 +15427,8 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMP_CV_HANDLER(ZEND_O container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->has_property) { + if (IS_TMP_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_property)) { result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to check property of non-object"); @@ -15180,7 +15442,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMP_CV_HANDLER(ZEND_O } ZVAL_BOOL(EX_VAR(opline->result.var), result); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -15220,7 +15482,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG /* Temporary variables don't need ctor copying */ if (IS_TMP_VAR != IS_TMP_VAR) { - zval_copy_ctor(&generator->value); + zval_opt_copy_ctor(&generator->value); } } else { zval *value_ptr = NULL; @@ -15231,9 +15493,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_TMP_VAR == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_TMP_VAR == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -15324,7 +15587,7 @@ static int ZEND_FASTCALL ZEND_POW_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) pow_function(EX_VAR(opline->result.var), _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op1.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -15381,7 +15644,6 @@ static int ZEND_FASTCALL ZEND_PRE_INC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS if (RETURN_VALUE_USED(opline)) { ZVAL_NULL(EX_VAR(opline->result.var)); } - if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -15389,19 +15651,7 @@ static int ZEND_FASTCALL ZEND_PRE_INC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS ZVAL_DEREF(var_ptr); SEPARATE_ZVAL_NOREF(var_ptr); - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) - && Z_OBJ_HANDLER_P(var_ptr, get) - && Z_OBJ_HANDLER_P(var_ptr, set)) { - /* proxy object */ - zval rv; - zval *val = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(val); - fast_increment_function(val); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, val TSRMLS_CC); - zval_ptr_dtor(val); - } else { - increment_function(var_ptr); - } + increment_function(var_ptr); if (RETURN_VALUE_USED(opline)) { ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); @@ -15437,7 +15687,6 @@ static int ZEND_FASTCALL ZEND_PRE_DEC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS if (RETURN_VALUE_USED(opline)) { ZVAL_NULL(EX_VAR(opline->result.var)); } - if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -15445,19 +15694,7 @@ static int ZEND_FASTCALL ZEND_PRE_DEC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS ZVAL_DEREF(var_ptr); SEPARATE_ZVAL_NOREF(var_ptr); - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) - && Z_OBJ_HANDLER_P(var_ptr, get) - && Z_OBJ_HANDLER_P(var_ptr, set)) { - /* proxy object */ - zval rv; - zval *val = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(val); - fast_decrement_function(val); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, val TSRMLS_CC); - zval_ptr_dtor(val); - } else { - decrement_function(var_ptr); - } + decrement_function(var_ptr); if (RETURN_VALUE_USED(opline)) { ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); @@ -15472,7 +15709,7 @@ static int ZEND_FASTCALL ZEND_POST_INC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG { USE_OPLINE zend_free_op free_op1; - zval *var_ptr, *retval; + zval *var_ptr; SAVE_OPLINE(); var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); @@ -15489,34 +15726,19 @@ static int ZEND_FASTCALL ZEND_POST_INC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { ZVAL_NULL(EX_VAR(opline->result.var)); - if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } - retval = EX_VAR(opline->result.var); - if (UNEXPECTED(Z_ISREF_P(var_ptr))) { var_ptr = Z_REFVAL_P(var_ptr); - ZVAL_DUP(retval, var_ptr); + ZVAL_DUP(EX_VAR(opline->result.var), var_ptr); } else { - ZVAL_DUP(retval, var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); + zval_opt_copy_ctor(var_ptr); } - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) - && Z_OBJ_HANDLER_P(var_ptr, get) - && Z_OBJ_HANDLER_P(var_ptr, set)) { - /* proxy object */ - zval rv; - zval *val = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(val); - fast_increment_function(val); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, val TSRMLS_CC); - zval_ptr_dtor(val); - } else { - increment_function(var_ptr); - } + increment_function(var_ptr); if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; CHECK_EXCEPTION(); @@ -15527,7 +15749,7 @@ static int ZEND_FASTCALL ZEND_POST_DEC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG { USE_OPLINE zend_free_op free_op1; - zval *var_ptr, *retval; + zval *var_ptr; SAVE_OPLINE(); var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); @@ -15544,34 +15766,19 @@ static int ZEND_FASTCALL ZEND_POST_DEC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { ZVAL_NULL(EX_VAR(opline->result.var)); - if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } - retval = EX_VAR(opline->result.var); - if (UNEXPECTED(Z_ISREF_P(var_ptr))) { var_ptr = Z_REFVAL_P(var_ptr); - ZVAL_DUP(retval, var_ptr); + ZVAL_DUP(EX_VAR(opline->result.var), var_ptr); } else { - ZVAL_DUP(retval, var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); + zval_opt_copy_ctor(var_ptr); } - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) - && Z_OBJ_HANDLER_P(var_ptr, get) - && Z_OBJ_HANDLER_P(var_ptr, set)) { - /* proxy object */ - zval rv; - zval *val = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(val); - fast_decrement_function(val); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, val TSRMLS_CC); - zval_ptr_dtor(val); - } else { - decrement_function(var_ptr); - } + decrement_function(var_ptr); if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; CHECK_EXCEPTION(); @@ -15717,13 +15924,14 @@ static int ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS } if (i_zend_is_true(val TSRMLS_CC)) { + zval_ptr_dtor_nogc(free_op1.var); ZVAL_TRUE(EX_VAR(opline->result.var)); opline++; } else { + zval_ptr_dtor_nogc(free_op1.var); ZVAL_FALSE(EX_VAR(opline->result.var)); opline = opline->op2.jmp_addr; } - zval_ptr_dtor_nogc(free_op1.var); if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -15769,11 +15977,7 @@ static int ZEND_FASTCALL ZEND_FREE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) USE_OPLINE SAVE_OPLINE(); - if (IS_VAR == IS_TMP_VAR) { - zval_dtor(EX_VAR(opline->op1.var)); - } else { - zval_ptr_dtor(EX_VAR(opline->op1.var)); - } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -15831,6 +16035,7 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLE } } else { ZVAL_COPY_VALUE(EX(return_value), retval_ptr); + Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; if (IS_VAR != IS_TMP_VAR) { zval_opt_copy_ctor_no_imm(EX(return_value)); } @@ -15844,13 +16049,14 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLE zend_error_noreturn(E_ERROR, "Cannot return string offsets by reference"); } - if (IS_VAR == IS_VAR && !Z_ISREF_P(retval_ptr)) { - if (opline->extended_value == ZEND_RETURNS_FUNCTION && - (Z_VAR_FLAGS_P(retval_ptr) & IS_VAR_RET_REF)) { - } else { + if (IS_VAR == IS_VAR) { + if (retval_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(retval_ptr) & IS_VAR_RET_REF))) { zend_error(E_NOTICE, "Only variable references should be returned by reference"); if (EX(return_value)) { ZVAL_NEW_REF(EX(return_value), retval_ptr); + Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; if (Z_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr); } break; @@ -15861,6 +16067,7 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLE ZVAL_MAKE_REF(retval_ptr); Z_ADDREF_P(retval_ptr); ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr)); + Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; } } while (0); @@ -16060,12 +16267,12 @@ static int ZEND_FASTCALL ZEND_SEND_USER_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR if (EX(call)->func->common.fn_flags & ZEND_ACC_CLOSURE) { OBJ_RELEASE((zend_object*)EX(call)->func->common.prototype); } - if (EX(call)->object) { - OBJ_RELEASE(EX(call)->object); + if (Z_OBJ(EX(call)->This)) { + OBJ_RELEASE(Z_OBJ(EX(call)->This)); } EX(call)->func = (zend_function*)&zend_pass_function; EX(call)->called_scope = NULL; - EX(call)->object = NULL; + Z_OBJ(EX(call)->This) = NULL; zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); @@ -16115,14 +16322,70 @@ static int ZEND_FASTCALL ZEND_BOOL_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_SWITCH_FREE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_NEW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval object_zval; + zend_function *constructor; + zend_class_entry *ce; SAVE_OPLINE(); - zval_ptr_dtor(EX_VAR(opline->op1.var)); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + if (IS_VAR == IS_CONST) { + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv)); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, 0 TSRMLS_CC); + if (UNEXPECTED(ce == NULL)) { + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op1.var)); + } + if (UNEXPECTED((ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) != 0)) { + if (ce->ce_flags & ZEND_ACC_INTERFACE) { + zend_error_noreturn(E_ERROR, "Cannot instantiate interface %s", ce->name->val); + } else if ((ce->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) { + zend_error_noreturn(E_ERROR, "Cannot instantiate trait %s", ce->name->val); + } else { + zend_error_noreturn(E_ERROR, "Cannot instantiate abstract class %s", ce->name->val); + } + } + object_init_ex(&object_zval, ce); + constructor = Z_OBJ_HT(object_zval)->get_constructor(Z_OBJ(object_zval) TSRMLS_CC); + + if (constructor == NULL) { + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), &object_zval); + } else { + zval_ptr_dtor(&object_zval); + } + ZEND_VM_JMP(opline->op2.jmp_addr); + } else { + /* We are not handling overloaded classes right now */ + EX(call) = zend_vm_stack_push_call_frame( + VM_FRAME_INFO( + VM_FRAME_NESTED_FUNCTION, + RETURN_VALUE_USED(opline) ? + ZEND_CALL_CTOR : (ZEND_CALL_CTOR | ZEND_CALL_CTOR_RESULT_UNUSED)), + constructor, + opline->extended_value, + ce, + Z_OBJ(object_zval), + EX(call) TSRMLS_CC); + + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), &object_zval); + EX(call)->return_value = EX_VAR(opline->result.var); + } else { + EX(call)->return_value = NULL; + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } } static int ZEND_FASTCALL ZEND_CLONE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -16138,7 +16401,7 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) obj = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_CONST || - UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT)) { + (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT))) { if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -16250,15 +16513,13 @@ static int ZEND_FASTCALL ZEND_CAST_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) if (UNEXPECTED(Z_OPT_COPYABLE_P(expr))) { zval_copy_ctor_func(expr); } - } else if (IS_VAR != IS_TMP_VAR) { + } else { if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); } } } else { ZVAL_COPY_VALUE(result, expr); - if (IS_VAR != IS_TMP_VAR) { - zval_opt_copy_ctor(result); - } + Z_ADDREF_P(result); convert_to_array(result); } } else { @@ -16270,23 +16531,18 @@ static int ZEND_FASTCALL ZEND_CAST_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) if (UNEXPECTED(Z_OPT_COPYABLE_P(expr))) { zval_copy_ctor_func(expr); } - } else if (IS_VAR != IS_TMP_VAR) { + } else { if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); } } } else { ZVAL_COPY_VALUE(result, expr); - if (IS_VAR != IS_TMP_VAR) { - zval_opt_copy_ctor(result); - } + zval_opt_copy_ctor(result); convert_to_object(result); } } - - zval_ptr_dtor_nogc(free_op1.var); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); } + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -16306,8 +16562,7 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND ZVAL_UNDEF(&tmp_inc_filename); if (Z_TYPE_P(inc_filename) != IS_STRING) { - ZVAL_DUP(&tmp_inc_filename, inc_filename); - convert_to_string(&tmp_inc_filename); + ZVAL_STR(&tmp_inc_filename, zval_get_string(inc_filename)); inc_filename = &tmp_inc_filename; } @@ -16386,8 +16641,8 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND return_value = EX_VAR(opline->result.var); } - call = zend_vm_stack_push_call_frame( - (zend_function*)new_op_array, 0, 0, EX(called_scope), EX(object), NULL TSRMLS_CC); + call = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_CODE, + (zend_function*)new_op_array, 0, EX(called_scope), Z_OBJ(EX(This)), NULL TSRMLS_CC); if (EX(symbol_table)) { call->symbol_table = EX(symbol_table); @@ -16396,10 +16651,11 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND } call->prev_execute_data = execute_data; - i_init_code_execute_data(call, new_op_array, return_value, EXPECTED(zend_execute_ex == execute_ex) ? VM_FRAME_NESTED_CODE : VM_FRAME_TOP_CODE TSRMLS_CC); + i_init_code_execute_data(call, new_op_array, return_value TSRMLS_CC); if (EXPECTED(zend_execute_ex == execute_ex)) { ZEND_VM_ENTER(); } else { + call->frame_info = VM_FRAME_TOP_CODE; zend_execute_ex(call TSRMLS_CC); } @@ -16440,13 +16696,8 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG } if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref); } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { - if(Z_OBJ_HT_P(array_ptr)->get_class_entry == NULL) { - zend_error(E_WARNING, "foreach() cannot iterate over objects without PHP class"); - ZEND_VM_JMP(opline->op2.jmp_addr); - } - ce = Z_OBJCE_P(array_ptr); - if (!ce || ce->get_iterator == NULL) { + if (ce->get_iterator == NULL) { Z_ADDREF_P(array_ptr); } array_ref = array_ptr; @@ -16458,7 +16709,10 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG ZVAL_DEREF(array_ptr); if (IS_VAR == IS_TMP_VAR) { ZVAL_COPY_VALUE(&tmp, array_ptr); - array_ptr = &tmp; + if (Z_OPT_IMMUTABLE_P(&tmp)) { + zval_copy_ctor_func(&tmp); + } + array_ref = array_ptr = &tmp; if (Z_TYPE_P(array_ptr) == IS_OBJECT) { ce = Z_OBJCE_P(array_ptr); if (ce && ce->get_iterator) { @@ -16467,17 +16721,18 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG } } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { ce = Z_OBJCE_P(array_ptr); - if (!ce || !ce->get_iterator) { + if (!ce->get_iterator) { if (IS_VAR == IS_CV) { Z_ADDREF_P(array_ref); } } } else if (Z_IMMUTABLE_P(array_ref)) { if (IS_VAR == IS_CV) { - zval_copy_ctor(array_ref); + zval_copy_ctor_func(array_ref); Z_ADDREF_P(array_ref); } else { - ZVAL_DUP(&tmp, array_ref); + ZVAL_COPY_VALUE(&tmp, array_ref); + zval_copy_ctor_func(&tmp); array_ptr = array_ref = &tmp; } } else if (Z_REFCOUNTED_P(array_ref)) { @@ -16498,14 +16753,13 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG ZVAL_UNREF(array_ref); array_ptr = array_ref; } - if (Z_IMMUTABLE_P(array_ptr) || - (Z_ISREF_P(array_ref) && - Z_REFCOUNTED_P(array_ptr) && - Z_REFCOUNT_P(array_ptr) > 1)) { - if (!Z_IMMUTABLE_P(array_ptr)) { - Z_DELREF_P(array_ptr); - } - zval_copy_ctor(array_ptr); + if (Z_IMMUTABLE_P(array_ptr)) { + zval_copy_ctor_func(array_ptr); + } else if (Z_ISREF_P(array_ref) && + Z_COPYABLE_P(array_ptr) && + Z_REFCOUNT_P(array_ptr) > 1) { + Z_DELREF_P(array_ptr); + zval_copy_ctor_func(array_ptr); } if (IS_VAR == IS_CV) { Z_ADDREF_P(array_ref); @@ -16589,6 +16843,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG ptr->pos = pos; ptr->ht = fe_ht; ptr->h = fe_ht->arData[pos].h; + ptr->key = fe_ht->arData[pos].key; is_empty = 0; } else { zend_error(E_WARNING, "Invalid argument supplied for foreach()"); @@ -16622,7 +16877,7 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG array = Z_REFVAL_P(array); // TODO: referenced value might be changed to different array ??? if (Z_IMMUTABLE_P(array)) { - zval_copy_ctor(array); + zval_copy_ctor_func(array); } } @@ -16643,8 +16898,11 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG pos = ptr->h; } else { pos = fe_ht->arHash[ptr->h & fe_ht->nTableMask]; - while (pos != INVALID_IDX) { - if (fe_ht->arData[pos].h == ptr->h && pos == ptr->pos) { + while (1) { + if (pos == INVALID_IDX) { + pos = fe_ht->nInternalPointer; + break; + } else if (fe_ht->arData[pos].h == ptr->h && fe_ht->arData[pos].key == ptr->key) { break; } pos = Z_NEXT(fe_ht->arData[pos].val); @@ -16697,6 +16955,7 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG Z_TYPE_P(Z_INDIRECT(p->val)) == IS_UNDEF)); fe_ht->nInternalPointer = ptr->pos = pos; ptr->h = fe_ht->arData[pos].h; + ptr->key = fe_ht->arData[pos].key; ZEND_VM_INC_OPCODE(); ZEND_VM_NEXT_OPCODE(); } else if (EXPECTED(Z_TYPE_P(array) == IS_OBJECT)) { @@ -16720,8 +16979,11 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG pos = ptr->h; } else { pos = fe_ht->arHash[ptr->h & fe_ht->nTableMask]; - while (pos != INVALID_IDX) { - if (fe_ht->arData[pos].h == ptr->h && pos == ptr->pos) { + while (1) { + if (pos == INVALID_IDX) { + pos = fe_ht->nInternalPointer; + break; + } else if (fe_ht->arData[pos].h == ptr->h && fe_ht->arData[pos].key == ptr->key) { break; } pos = Z_NEXT(fe_ht->arData[pos].val); @@ -16790,6 +17052,7 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG zend_check_property_access(zobj, p->key TSRMLS_CC) == FAILURE)); fe_ht->nInternalPointer = ptr->pos = pos; ptr->h = fe_ht->arData[pos].h; + ptr->key = fe_ht->arData[pos].key; ZEND_VM_INC_OPCODE(); ZEND_VM_NEXT_OPCODE(); } else { @@ -16904,19 +17167,22 @@ static int ZEND_FASTCALL ZEND_JMP_SET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_COALESCE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; zval *value; + int is_ref = 0; SAVE_OPLINE(); value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && Z_ISREF_P(value)) { - ZVAL_COPY(EX_VAR(opline->result.var), Z_REFVAL_P(value)); - zval_ptr_dtor_nogc(free_op1.var); - } else { + is_ref = 1; + value = Z_REFVAL_P(value); + } + + if (Z_TYPE_P(value) > IS_NULL) { ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value); if (IS_VAR == IS_CONST) { if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { @@ -16924,29 +17190,40 @@ static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR } } else if (IS_VAR == IS_CV) { if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } else if (IS_VAR == IS_VAR && is_ref) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + zval_ptr_dtor_nogc(free_op1.var); } + ZEND_VM_JMP(opline->op2.jmp_addr); } + + zval_ptr_dtor_nogc(free_op1.var); + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; - zval *expr; - zend_bool result; + zval *value; SAVE_OPLINE(); - expr = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (Z_TYPE_P(expr) == IS_OBJECT && Z_OBJ_HT_P(expr)->get_class_entry) { - result = instanceof_function(Z_OBJCE_P(expr), Z_CE_P(EX_VAR(opline->op2.var)) TSRMLS_CC); + if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && Z_ISREF_P(value)) { + ZVAL_COPY(EX_VAR(opline->result.var), Z_REFVAL_P(value)); + zval_ptr_dtor_nogc(free_op1.var); } else { - result = 0; + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value); + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + zval_copy_ctor_func(EX_VAR(opline->result.var)); + } + } else if (IS_VAR == IS_CV) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } } - ZVAL_BOOL(EX_VAR(opline->result.var), result); - zval_ptr_dtor_nogc(free_op1.var); - CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -17011,16 +17288,12 @@ static int ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_A break; case IS_OBJECT: if (Z_TYPE_P(value) == opline->extended_value) { - if (Z_OBJ_HT_P(value)->get_class_entry == NULL) { - ZVAL_TRUE(EX_VAR(opline->result.var)); + zend_class_entry *ce = Z_OBJCE_P(value); + if (ce->name->len == sizeof("__PHP_Incomplete_Class") - 1 + && !strncmp(ce->name->val, "__PHP_Incomplete_Class", ce->name->len)) { + ZVAL_FALSE(EX_VAR(opline->result.var)); } else { - zend_class_entry *ce = Z_OBJCE_P(value); - if (ce->name->len == sizeof("__PHP_Incomplete_Class") - 1 - && !strncmp(ce->name->val, "__PHP_Incomplete_Class", ce->name->len)) { - ZVAL_FALSE(EX_VAR(opline->result.var)); - } else { - ZVAL_TRUE(EX_VAR(opline->result.var)); - } + ZVAL_TRUE(EX_VAR(opline->result.var)); } } else { ZVAL_FALSE(EX_VAR(opline->result.var)); @@ -17323,17 +17596,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(int (*b zval *object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); zval *property = opline->op2.zv; zval *value; - int have_get_ptr = 0; + zval *zptr; if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - object = make_real_object(object TSRMLS_CC); + if (IS_VAR != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); + } - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to assign property of non-object"); FREE_OP(free_op_data1); @@ -17344,20 +17619,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(int (*b } else { /* here we are sure we are dealing with an object */ if (opline->extended_value == ZEND_ASSIGN_OBJ - && Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - SEPARATE_ZVAL_IF_NOT_REF(zptr); + && EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - have_get_ptr = 1; - binary_op(zptr, zptr, value TSRMLS_CC); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), zptr); - } - } - } + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + binary_op(zptr, zptr, value TSRMLS_CC); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); + } + } else { zval *z = NULL; zval rv; @@ -17413,15 +17685,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(int (*b static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op_data2, free_op_data1; - zval *var_ptr; + zend_free_op free_op1, free_op_data1; + zval *var_ptr, rv; zval *value, *container; SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } + if (IS_VAR != IS_UNUSED) { + ZVAL_DEREF(container); + } + if (IS_VAR == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_VAR == IS_VAR && !(free_op1.var != NULL)) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } @@ -17429,9 +17705,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(int (*b } else { zval *dim = opline->op2.zv; - zend_fetch_dimension_address_RW(EX_VAR((opline+1)->op2.var), container, dim, IS_CONST TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + zend_fetch_dimension_address_RW(&rv, container, dim, IS_CONST TSRMLS_CC); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); } if (UNEXPECTED(var_ptr == NULL)) { @@ -17442,33 +17719,18 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(int (*b if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_dim_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_dim_exit: - FREE_OP(free_op_data1); - FREE_OP_VAR_PTR(free_op_data2); if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; CHECK_EXCEPTION(); ZEND_VM_INC_OPCODE(); @@ -17494,31 +17756,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_CONST(int (*binar if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_exit: - if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -17674,7 +17922,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_CONST(incdec_t zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); @@ -17685,9 +17933,11 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_CONST(incdec_t zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_VAR != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); if (RETURN_VALUE_USED(opline)) { @@ -17700,20 +17950,17 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_CONST(incdec_t /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - SEPARATE_ZVAL_IF_NOT_REF(zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - have_get_ptr = 1; - incdec_op(zptr); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(retval, zptr); - } - } - } + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + incdec_op(zptr); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(retval, zptr); + } + } else { zval rv; if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { @@ -17765,7 +18012,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_CONST(incdec_ zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); @@ -17776,9 +18023,11 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_CONST(incdec_ zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_VAR != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); ZVAL_NULL(retval); @@ -17789,20 +18038,15 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_CONST(incdec_ /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - have_get_ptr = 1; - SEPARATE_ZVAL_IF_NOT_REF(zptr); - - ZVAL_DUP(retval, zptr); - - incdec_op(zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - } - } + ZVAL_DEREF(zptr); + ZVAL_COPY(retval, zptr); - if (!have_get_ptr) { + SEPARATE_ZVAL_NOREF(zptr); + incdec_op(zptr); + } else { if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { zval rv; zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); @@ -17951,9 +18195,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_CONST(int type, } ZVAL_COPY(EX_VAR(opline->result.var), retval); } else { - if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) { - ZVAL_MAKE_REF(retval); - } ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); } CHECK_EXCEPTION(); @@ -18006,9 +18247,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HA container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); - if (IS_VAR != IS_VAR || !(opline->extended_value & ZEND_FETCH_ADD_LOCK)) { - zval_ptr_dtor_nogc(free_op1.var); - } + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -18025,11 +18264,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HA if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - if (EXPECTED(opline->extended_value == 0)) { - zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); - } else { - zend_fetch_dimension_address_W_ref(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); - } + ZVAL_DEREF(container); + zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -18051,6 +18287,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_H if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { @@ -18092,6 +18329,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OP if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -18123,6 +18361,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCOD if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { @@ -18133,7 +18372,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCOD ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_VAR_CONST(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; @@ -18145,7 +18384,7 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_VAR_CONST( container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = opline->op2.zv; - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { zend_error(E_NOTICE, "Trying to get property of non-object"); ZVAL_NULL(EX_VAR(opline->result.var)); @@ -18165,11 +18404,6 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_VAR_CONST( ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_property_address_read_helper_SPEC_VAR_CONST(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -18185,7 +18419,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HA zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -18209,7 +18443,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_H if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -18231,7 +18465,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_H container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = opline->op2.zv; - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -18270,7 +18504,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OP if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -18279,7 +18513,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OP CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { - return zend_fetch_property_address_read_helper_SPEC_VAR_CONST(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return ZEND_FETCH_OBJ_R_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } @@ -18296,7 +18530,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCOD if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -18306,6 +18540,39 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCOD ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_FETCH_LIST_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *container; + + SAVE_OPLINE(); + container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + + zval *value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), opline->op2.zv, IS_CONST, BP_VAR_R TSRMLS_CC); + + ZVAL_COPY(EX_VAR(opline->result.var), value); + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT) && + EXPECTED(Z_OBJ_HT_P(container)->read_dimension)) { + zval *result = EX_VAR(opline->result.var); + zval *retval = Z_OBJ_HT_P(container)->read_dimension(container, opline->op2.zv, BP_VAR_R, result TSRMLS_CC); + + if (retval) { + if (result != retval) { + ZVAL_COPY(result, retval); + } + } else { + ZVAL_NULL(result); + } + } else { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -18320,7 +18587,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAN if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, IS_VAR, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; /* assign_obj has two opcodes! */ @@ -18341,45 +18608,48 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAN if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - if (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) { - object_ptr = Z_REFVAL_P(object_ptr); - } - if (Z_TYPE_P(object_ptr) == IS_OBJECT) { + ZVAL_DEREF(object_ptr); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { zval *property_name = opline->op2.zv; - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_VAR, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); } else { - zend_free_op free_op_data1, free_op_data2; + zend_free_op free_op_data1; + zval rv; zval *value; zval *dim = opline->op2.zv; zval *variable_ptr; - variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_CONST TSRMLS_CC); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) && + EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + zend_long offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W TSRMLS_CC); - value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(variable_ptr != NULL)) { - zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + zend_assign_to_string_offset(object_ptr, offset, value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); + FREE_OP(free_op_data1); } else { - variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_CONST TSRMLS_CC); + + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + variable_ptr = Z_INDIRECT(rv); if (UNEXPECTED(variable_ptr == &EG(error_zval))) { - if (IS_TMP_FREE(free_op_data1)) { - zval_dtor(value); - } + FREE_OP(free_op_data1); if (RETURN_VALUE_USED(opline)) { ZVAL_NULL(EX_VAR(opline->result.var)); } - FREE_OP_VAR_PTR(free_op_data2); } else { value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC); + if ((opline+1)->op1_type == IS_VAR) { + FREE_OP(free_op_data1); + } if (RETURN_VALUE_USED(opline)) { ZVAL_COPY(EX_VAR(opline->result.var), value); } - FREE_OP_VAR_PTR(free_op_data2); } } - FREE_OP_IF_VAR(free_op_data1); } if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; /* assign_dim has two opcodes! */ @@ -18401,7 +18671,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) { if (IS_CONST == IS_TMP_VAR) { - zval_dtor(value); + } if (RETURN_VALUE_USED(opline)) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -18444,19 +18714,56 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCO object = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + uint32_t nesting = 1; + if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); + + zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); + + zval_ptr_dtor_nogc(free_op1.var); + + if (EG(exception) != NULL) { + HANDLE_EXCEPTION(); + } + + /* No exception raised: Skip over arguments until fcall opcode with correct + * nesting level. Return NULL (except when return value unused) */ + do { + opline++; + if (opline->opcode == ZEND_INIT_FCALL || + opline->opcode == ZEND_INIT_FCALL_BY_NAME || + opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME || + opline->opcode == ZEND_INIT_METHOD_CALL || + opline->opcode == ZEND_INIT_STATIC_METHOD_CALL || + opline->opcode == ZEND_INIT_USER_CALL || + opline->opcode == ZEND_NEW + ) { + nesting++; + } else if (opline->opcode == ZEND_DO_FCALL) { + nesting--; + } + } while (nesting); + + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + /* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */ + if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) { + opline++; + } + ZEND_VM_JMP(++opline); } obj = Z_OBJ_P(object); - called_scope = zend_get_class_entry(obj TSRMLS_CC); + called_scope = obj->ce; if (IS_CONST != IS_CONST || - (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) { + EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { zend_object *orig_obj = obj; if (UNEXPECTED(obj->handlers->get_method == NULL)) { @@ -18466,7 +18773,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCO /* First, locate the function. */ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name)); + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); } if (IS_CONST == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -18476,14 +18783,14 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCO } } - if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { obj = NULL; } else { GC_REFCOUNT(obj)++; /* For $this pointer */ } - EX(call) = zend_vm_stack_push_call_frame( - fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_FUNCTION, + fbc, opline->extended_value, called_scope, obj, EX(call) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1.var); @@ -18564,7 +18871,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZE if (UNEXPECTED(ce->constructor == NULL)) { zend_error_noreturn(E_ERROR, "Cannot call constructor"); } - if (EX(object) && zend_get_class_entry(EX(object) TSRMLS_CC) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val); } fbc = ce->constructor; @@ -18572,19 +18879,27 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZE object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { - if (EX(object)) { - object = EX(object); + if (Z_OBJ(EX(This))) { + object = Z_OBJ(EX(This)); GC_REFCOUNT(object)++; - if (object->handlers->get_class_entry && - !instanceof_function(zend_get_class_entry(object TSRMLS_CC), ce TSRMLS_CC)) { - /* We are calling method of the other (incompatible) class, - but passing $this. This is done for compatibility with php-4. */ - if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val); - } else { - /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val); - } + } + if (!object || + !instanceof_function(object->ce, ce TSRMLS_CC)) { + /* We are calling method of the other (incompatible) class, + but passing $this. This is done for compatibility with php-4. */ + if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + zend_error( + object ? E_DEPRECATED : E_STRICT, + "Non-static method %s::%s() should not be called statically%s", + fbc->common.scope->name->val, fbc->common.function_name->val, + object ? ", assuming $this from incompatible context" : ""); + } else { + /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ + zend_error_noreturn( + E_ERROR, + "Non-static method %s::%s() cannot be called statically%s", + fbc->common.scope->name->val, fbc->common.function_name->val, + object ? ", assuming $this from incompatible context" : ""); } } } @@ -18596,8 +18911,8 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZE } } - EX(call) = zend_vm_stack_push_call_frame( - fbc, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_FUNCTION, + fbc, opline->extended_value, ce, object, EX(call) TSRMLS_CC); if (IS_CONST == IS_UNUSED) { EX(call)->return_value = NULL; @@ -18636,14 +18951,16 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE } else if ((c = zend_quick_get_constant(opline->op2.zv + 1, opline->extended_value TSRMLS_CC)) == NULL) { if ((opline->extended_value & IS_CONSTANT_UNQUALIFIED) != 0) { char *actual = (char *)zend_memrchr(Z_STRVAL_P(opline->op2.zv), '\\', Z_STRLEN_P(opline->op2.zv)); - if(!actual) { - actual = Z_STRVAL_P(opline->op2.zv); + if (!actual) { + ZVAL_STR(EX_VAR(opline->result.var), zend_string_copy(Z_STR_P(opline->op2.zv))); } else { actual++; + ZVAL_STRINGL(EX_VAR(opline->result.var), + actual, Z_STRLEN_P(opline->op2.zv) - (actual - Z_STRVAL_P(opline->op2.zv))); } /* non-qualified constant - allow text substitution */ - zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", actual, actual); - ZVAL_STRINGL(EX_VAR(opline->result.var), actual, Z_STRLEN_P(opline->op2.zv)-(actual - Z_STRVAL_P(opline->op2.zv))); + zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", + Z_STRVAL_P(EX_VAR(opline->result.var)), Z_STRVAL_P(EX_VAR(opline->result.var))); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { @@ -18675,7 +18992,7 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE } else if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) { ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv)); } else { - ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, opline->extended_value TSRMLS_CC); + ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, 0 TSRMLS_CC); if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -18871,8 +19188,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAND ZVAL_UNDEF(&tmp); if (IS_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { - ZVAL_DUP(&tmp, varname); - convert_to_string(&tmp); + ZVAL_STR(&tmp, zval_get_string(varname)); varname = &tmp; } @@ -18932,71 +19248,66 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAND } offset = opline->op2.zv; - switch (Z_TYPE_P(container)) { - case IS_ARRAY: { - HashTable *ht = Z_ARRVAL_P(container); + if (IS_VAR != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht = Z_ARRVAL_P(container); offset_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - zend_hash_index_del(ht, hval); - break; - case IS_LONG: - hval = Z_LVAL_P(offset); + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_LONG: + hval = Z_LVAL_P(offset); num_index_dim: - zend_hash_index_del(ht, hval); - break; - case IS_STRING: - if (IS_CONST != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { - goto num_index_dim; - } - } - if (ht == &EG(symbol_table).ht) { - zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); - } else { - zend_hash_del(ht, Z_STR_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_STRING: + if (IS_CONST != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { + goto num_index_dim; } - break; - case IS_NULL: - zend_hash_del(ht, STR_EMPTY_ALLOC()); - break; - case IS_FALSE: - hval = 0; - goto num_index_dim; - case IS_TRUE: - hval = 1; - goto num_index_dim; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_dim; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto offset_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type in unset"); - break; - } + } + if (ht == &EG(symbol_table).ht) { + zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); + } else { + zend_hash_del(ht, Z_STR_P(offset)); + } + break; + case IS_NULL: + zend_hash_del(ht, STR_EMPTY_ALLOC()); + break; + case IS_FALSE: + hval = 0; + goto num_index_dim; + case IS_TRUE: + hval = 1; + goto num_index_dim; + case IS_RESOURCE: + hval = Z_RES_HANDLE_P(offset); + goto num_index_dim; + case IS_REFERENCE: + offset = Z_REFVAL_P(offset); + goto offset_again; + break; + default: + zend_error(E_WARNING, "Illegal offset type in unset"); + break; + } - break; + } else if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use object as array"); } - case IS_OBJECT: - if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use object as array"); - } -//??? if (IS_CONST == IS_CONST) { -//??? zval_copy_ctor(offset); -//??? } - Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); +//??? if (IS_CONST == IS_CONST) { +//??? zval_copy_ctor(offset); +//??? } + Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); - break; - case IS_STRING: - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - ZEND_VM_CONTINUE(); /* bailed out before */ - default: + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + ZEND_VM_CONTINUE(); /* bailed out before */ + } else { - break; } if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; CHECK_EXCEPTION(); @@ -19018,7 +19329,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAND offset = opline->op2.zv; ZVAL_DEREF(container); - if (Z_TYPE_P(container) == IS_OBJECT) { + if (IS_VAR == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->unset_property) { Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { @@ -19035,26 +19346,28 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_CONST_HANDLER(ZEND_OPC { USE_OPLINE zval *value; - zend_bool isset = 1; SAVE_OPLINE(); if (IS_VAR == IS_CV && IS_CONST == IS_UNUSED && (opline->extended_value & ZEND_QUICK_SET)) { - if (Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_UNDEF) { - value = EX_VAR(opline->op1.var); - ZVAL_DEREF(value); - } else { - isset = 0; + value = EX_VAR(opline->op1.var); + if (opline->extended_value & ZEND_ISSET) { + ZVAL_BOOL(EX_VAR(opline->result.var), + Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + ZVAL_BOOL(EX_VAR(opline->result.var), + !i_zend_is_true(value TSRMLS_CC)); + CHECK_EXCEPTION(); } + ZEND_VM_NEXT_OPCODE(); } else { - HashTable *target_symbol_table; zend_free_op free_op1; zval tmp, *varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { - ZVAL_DUP(&tmp, varname); - convert_to_string(&tmp); + ZVAL_STR(&tmp, zval_get_string(varname)); varname = &tmp; } @@ -19076,39 +19389,28 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_CONST_HANDLER(ZEND_OPC ce = Z_CE_P(EX_VAR(opline->op2.var)); } value = zend_std_get_static_property(ce, Z_STR_P(varname), 1, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); - if (!value) { - isset = 0; - } } else { - target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); - if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) { - isset = 0; - } + HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname)); } if (IS_VAR != IS_CONST && varname == &tmp) { zval_dtor(&tmp); } zval_ptr_dtor_nogc(free_op1.var); - } - if (opline->extended_value & ZEND_ISSET) { - if (isset && Z_TYPE_P(value) != IS_NULL && - (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) { - ZVAL_BOOL(EX_VAR(opline->result.var), 1); - } else { - ZVAL_BOOL(EX_VAR(opline->result.var), 0); - } - } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { - if (!isset || !i_zend_is_true(value TSRMLS_CC)) { - ZVAL_BOOL(EX_VAR(opline->result.var), 1); - } else { - ZVAL_BOOL(EX_VAR(opline->result.var), 0); + if (opline->extended_value & ZEND_ISSET) { + ZVAL_BOOL(EX_VAR(opline->result.var), + value && Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + ZVAL_BOOL(EX_VAR(opline->result.var), + !value || !i_zend_is_true(value TSRMLS_CC)); } - } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } } static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -19124,7 +19426,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_VAR_CONST_HANDLER(ZEND container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = opline->op2.zv; - if (Z_TYPE_P(container) == IS_ARRAY) { + if (IS_VAR != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { HashTable *ht = Z_ARRVAL_P(container); zval *value; zend_string *str; @@ -19177,8 +19479,8 @@ num_index_prop: } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); } - } else if (Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->has_dimension) { + } else if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to check element of non-array"); @@ -19187,7 +19489,7 @@ num_index_prop: if ((opline->extended_value & ZEND_ISSET) == 0) { result = !result; } - } else if (Z_TYPE_P(container) == IS_STRING) { /* string offsets */ + } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */ zval tmp; result = 0; @@ -19203,7 +19505,7 @@ num_index_prop: offset = &tmp; } } - if (Z_TYPE_P(offset) == IS_LONG) { + if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) { if ((opline->extended_value & ZEND_ISSET) || Z_STRVAL_P(container)[offset->value.lval] != '0') { @@ -19236,8 +19538,8 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_CONST_HANDLER(ZEN container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = opline->op2.zv; - if (Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->has_property) { + if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_property)) { result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to check property of non-object"); @@ -19256,6 +19558,45 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_CONST_HANDLER(ZEN ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *expr; + zend_bool result; + + SAVE_OPLINE(); + expr = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + + if (Z_TYPE_P(expr) == IS_OBJECT) { + zend_class_entry *ce; + + if (IS_CONST == IS_CONST) { + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC); + if (UNEXPECTED(ce == NULL)) { + ZVAL_FALSE(EX_VAR(opline->result.var)); + zval_ptr_dtor_nogc(free_op1.var); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op2.var)); + } + result = instanceof_function(Z_OBJCE_P(expr), ce TSRMLS_CC); + } else { + result = 0; + } + ZVAL_BOOL(EX_VAR(opline->result.var), result); + zval_ptr_dtor_nogc(free_op1.var); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -19291,7 +19632,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ /* Temporary variables don't need ctor copying */ if (IS_VAR != IS_TMP_VAR) { - zval_copy_ctor(&generator->value); + zval_opt_copy_ctor(&generator->value); } } else { zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); @@ -19302,9 +19643,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_VAR == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_VAR == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -19417,7 +19759,7 @@ static int ZEND_FASTCALL ZEND_ADD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1.var); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -19432,7 +19774,7 @@ static int ZEND_FASTCALL ZEND_SUB_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1.var); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -19447,7 +19789,7 @@ static int ZEND_FASTCALL ZEND_MUL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1.var); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -19462,7 +19804,7 @@ static int ZEND_FASTCALL ZEND_DIV_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1.var); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -19477,7 +19819,7 @@ static int ZEND_FASTCALL ZEND_MOD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1.var); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -19492,7 +19834,7 @@ static int ZEND_FASTCALL ZEND_SL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1.var); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -19507,7 +19849,7 @@ static int ZEND_FASTCALL ZEND_SR_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1.var); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -19522,7 +19864,7 @@ static int ZEND_FASTCALL ZEND_CONCAT_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_A _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1.var); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -19537,7 +19879,7 @@ static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAN _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1.var); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -19553,7 +19895,7 @@ static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1.var); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -19569,7 +19911,7 @@ static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1.var); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -19585,7 +19927,7 @@ static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAN _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1.var); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -19601,7 +19943,7 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDL _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1.var); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -19617,7 +19959,7 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_VAR_TMP_HANDLER(ZEND_OPC _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1.var); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -19632,7 +19974,7 @@ static int ZEND_FASTCALL ZEND_BW_OR_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1.var); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -19647,7 +19989,7 @@ static int ZEND_FASTCALL ZEND_BW_AND_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_A _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1.var); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -19662,7 +20004,7 @@ static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_A _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1.var); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -19677,7 +20019,7 @@ static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1.var); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -19689,19 +20031,21 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(int (*bin zval *object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); zval *property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); zval *value; - int have_get_ptr = 0; + zval *zptr; if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - object = make_real_object(object TSRMLS_CC); + if (IS_VAR != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); + } - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to assign property of non-object"); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); FREE_OP(free_op_data1); if (RETURN_VALUE_USED(opline)) { @@ -19710,20 +20054,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(int (*bin } else { /* here we are sure we are dealing with an object */ if (opline->extended_value == ZEND_ASSIGN_OBJ - && Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - SEPARATE_ZVAL_IF_NOT_REF(zptr); + && EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - have_get_ptr = 1; - binary_op(zptr, zptr, value TSRMLS_CC); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), zptr); - } - } - } + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + binary_op(zptr, zptr, value TSRMLS_CC); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); + } + } else { zval *z = NULL; zval rv; @@ -19766,7 +20107,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(int (*bin } } - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); FREE_OP(free_op_data1); } @@ -19780,15 +20121,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(int (*bin static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_TMP(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2, free_op_data2, free_op_data1; - zval *var_ptr; + zend_free_op free_op1, free_op2, free_op_data1; + zval *var_ptr, rv; zval *value, *container; SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } + if (IS_VAR != IS_UNUSED) { + ZVAL_DEREF(container); + } + if (IS_VAR == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_VAR == IS_VAR && !(free_op1.var != NULL)) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } @@ -19796,9 +20141,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_TMP(int (*bin } else { zval *dim = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - zend_fetch_dimension_address_RW(EX_VAR((opline+1)->op2.var), container, dim, IS_TMP_VAR TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + zend_fetch_dimension_address_RW(&rv, container, dim, IS_TMP_VAR TSRMLS_CC); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); } if (UNEXPECTED(var_ptr == NULL)) { @@ -19809,33 +20155,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_TMP(int (*bin if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_dim_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_dim_exit: - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); FREE_OP(free_op_data1); - FREE_OP_VAR_PTR(free_op_data2); if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; CHECK_EXCEPTION(); ZEND_VM_INC_OPCODE(); @@ -19861,31 +20193,18 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_TMP(int (*binary_ if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_exit: - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -20041,7 +20360,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_TMP(incdec_t i zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); @@ -20052,11 +20371,13 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_TMP(incdec_t i zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_VAR != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); if (RETURN_VALUE_USED(opline)) { ZVAL_NULL(retval); } @@ -20067,20 +20388,17 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_TMP(incdec_t i /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - SEPARATE_ZVAL_IF_NOT_REF(zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - have_get_ptr = 1; - incdec_op(zptr); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(retval, zptr); - } - } - } + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + incdec_op(zptr); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(retval, zptr); + } + } else { zval rv; if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { @@ -20110,7 +20428,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_TMP(incdec_t i } } - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -20133,7 +20451,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_TMP(incdec_t zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); @@ -20144,11 +20462,13 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_TMP(incdec_t zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_VAR != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); ZVAL_NULL(retval); if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; CHECK_EXCEPTION(); @@ -20157,20 +20477,15 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_TMP(incdec_t /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - have_get_ptr = 1; - SEPARATE_ZVAL_IF_NOT_REF(zptr); - - ZVAL_DUP(retval, zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - incdec_op(zptr); - - } - } + ZVAL_DEREF(zptr); + ZVAL_COPY(retval, zptr); - if (!have_get_ptr) { + SEPARATE_ZVAL_NOREF(zptr); + incdec_op(zptr); + } else { if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { zval rv; zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); @@ -20198,7 +20513,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_TMP(incdec_t } } - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -20223,10 +20538,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); - zval_dtor(free_op2.var); - if (IS_VAR != IS_VAR || !(opline->extended_value & ZEND_FETCH_ADD_LOCK)) { - zval_ptr_dtor_nogc(free_op1.var); - } + zval_ptr_dtor_nogc(free_op2.var); + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -20243,12 +20556,9 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAND if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - if (EXPECTED(opline->extended_value == 0)) { - zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); - } else { - zend_fetch_dimension_address_W_ref(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); - } - zval_dtor(free_op2.var); + ZVAL_DEREF(container); + zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } @@ -20269,8 +20579,9 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAN if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } @@ -20288,7 +20599,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAN SAVE_OPLINE(); container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -20310,11 +20621,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_TMP_HANDLER(ZEND_OPCO if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; } else { if (IS_TMP_VAR == IS_UNUSED) { @@ -20322,7 +20634,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_TMP_HANDLER(ZEND_OPCO } container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); zval_ptr_dtor_nogc(free_op1.var); } CHECK_EXCEPTION(); @@ -20341,8 +20653,9 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } @@ -20351,7 +20664,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_ ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_VAR_TMP(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; @@ -20363,7 +20676,7 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_VAR_TMP(ZE container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { zend_error(E_NOTICE, "Trying to get property of non-object"); ZVAL_NULL(EX_VAR(opline->result.var)); @@ -20378,17 +20691,12 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_VAR_TMP(ZE } } - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_property_address_read_helper_SPEC_VAR_TMP(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -20404,8 +20712,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAND zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); - zval_dtor(free_op2.var); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } @@ -20428,8 +20736,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAN if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); - zval_dtor(free_op2.var); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } @@ -20450,7 +20758,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAN container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -20464,7 +20772,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAN } } - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -20490,8 +20798,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TMP_HANDLER(ZEND_OPCO if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); - zval_dtor(free_op2.var); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } @@ -20499,7 +20807,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TMP_HANDLER(ZEND_OPCO CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { - return zend_fetch_property_address_read_helper_SPEC_VAR_TMP(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return ZEND_FETCH_OBJ_R_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } @@ -20516,8 +20824,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); - zval_dtor(free_op2.var); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } @@ -20540,8 +20848,8 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDL if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); - zval_dtor(free_op2.var); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, IS_VAR, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; /* assign_obj has two opcodes! */ CHECK_EXCEPTION(); @@ -20561,45 +20869,48 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDL if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - if (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) { - object_ptr = Z_REFVAL_P(object_ptr); - } - if (Z_TYPE_P(object_ptr) == IS_OBJECT) { + ZVAL_DEREF(object_ptr); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { zend_free_op free_op2; zval *property_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); - zval_dtor(free_op2.var); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_VAR, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); } else { - zend_free_op free_op2, free_op_data1, free_op_data2; + zend_free_op free_op2, free_op_data1; + zval rv; zval *value; zval *dim = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); zval *variable_ptr; - variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_TMP_VAR TSRMLS_CC); - zval_dtor(free_op2.var); - value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(variable_ptr != NULL)) { - zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) && + EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + zend_long offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + zend_assign_to_string_offset(object_ptr, offset, value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); + FREE_OP(free_op_data1); } else { - variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_TMP_VAR TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + variable_ptr = Z_INDIRECT(rv); if (UNEXPECTED(variable_ptr == &EG(error_zval))) { - if (IS_TMP_FREE(free_op_data1)) { - zval_dtor(value); - } + FREE_OP(free_op_data1); if (RETURN_VALUE_USED(opline)) { ZVAL_NULL(EX_VAR(opline->result.var)); } - FREE_OP_VAR_PTR(free_op_data2); } else { value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC); + if ((opline+1)->op1_type == IS_VAR) { + FREE_OP(free_op_data1); + } if (RETURN_VALUE_USED(opline)) { ZVAL_COPY(EX_VAR(opline->result.var), value); } - FREE_OP_VAR_PTR(free_op_data2); } } - FREE_OP_IF_VAR(free_op_data1); } if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; /* assign_dim has two opcodes! */ @@ -20621,7 +20932,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_A if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) { if (IS_TMP_VAR == IS_TMP_VAR) { - zval_dtor(value); + zval_ptr_dtor_nogc(free_op2.var); } if (RETURN_VALUE_USED(opline)) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -20664,19 +20975,56 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE object = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + uint32_t nesting = 1; + if (UNEXPECTED(EG(exception) != NULL)) { - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); + + zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); + zval_ptr_dtor_nogc(free_op2.var); + zval_ptr_dtor_nogc(free_op1.var); + + if (EG(exception) != NULL) { + HANDLE_EXCEPTION(); + } + + /* No exception raised: Skip over arguments until fcall opcode with correct + * nesting level. Return NULL (except when return value unused) */ + do { + opline++; + if (opline->opcode == ZEND_INIT_FCALL || + opline->opcode == ZEND_INIT_FCALL_BY_NAME || + opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME || + opline->opcode == ZEND_INIT_METHOD_CALL || + opline->opcode == ZEND_INIT_STATIC_METHOD_CALL || + opline->opcode == ZEND_INIT_USER_CALL || + opline->opcode == ZEND_NEW + ) { + nesting++; + } else if (opline->opcode == ZEND_DO_FCALL) { + nesting--; + } + } while (nesting); + + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + /* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */ + if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) { + opline++; + } + ZEND_VM_JMP(++opline); } obj = Z_OBJ_P(object); - called_scope = zend_get_class_entry(obj TSRMLS_CC); + called_scope = obj->ce; if (IS_TMP_VAR != IS_CONST || - (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) { + EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { zend_object *orig_obj = obj; if (UNEXPECTED(obj->handlers->get_method == NULL)) { @@ -20686,7 +21034,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE /* First, locate the function. */ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_TMP_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name)); + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); } if (IS_TMP_VAR == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -20696,16 +21044,16 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE } } - if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { obj = NULL; } else { GC_REFCOUNT(obj)++; /* For $this pointer */ } - EX(call) = zend_vm_stack_push_call_frame( - fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_FUNCTION, + fbc, opline->extended_value, called_scope, obj, EX(call) TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); @@ -20779,13 +21127,13 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND } } if (IS_TMP_VAR != IS_CONST) { - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); } } else { if (UNEXPECTED(ce->constructor == NULL)) { zend_error_noreturn(E_ERROR, "Cannot call constructor"); } - if (EX(object) && zend_get_class_entry(EX(object) TSRMLS_CC) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val); } fbc = ce->constructor; @@ -20793,19 +21141,27 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { - if (EX(object)) { - object = EX(object); + if (Z_OBJ(EX(This))) { + object = Z_OBJ(EX(This)); GC_REFCOUNT(object)++; - if (object->handlers->get_class_entry && - !instanceof_function(zend_get_class_entry(object TSRMLS_CC), ce TSRMLS_CC)) { - /* We are calling method of the other (incompatible) class, - but passing $this. This is done for compatibility with php-4. */ - if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val); - } else { - /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val); - } + } + if (!object || + !instanceof_function(object->ce, ce TSRMLS_CC)) { + /* We are calling method of the other (incompatible) class, + but passing $this. This is done for compatibility with php-4. */ + if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + zend_error( + object ? E_DEPRECATED : E_STRICT, + "Non-static method %s::%s() should not be called statically%s", + fbc->common.scope->name->val, fbc->common.function_name->val, + object ? ", assuming $this from incompatible context" : ""); + } else { + /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ + zend_error_noreturn( + E_ERROR, + "Non-static method %s::%s() cannot be called statically%s", + fbc->common.scope->name->val, fbc->common.function_name->val, + object ? ", assuming $this from incompatible context" : ""); } } } @@ -20817,8 +21173,8 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND } } - EX(call) = zend_vm_stack_push_call_frame( - fbc, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_FUNCTION, + fbc, opline->extended_value, ce, object, EX(call) TSRMLS_CC); if (IS_TMP_VAR == IS_UNUSED) { EX(call)->return_value = NULL; @@ -20839,7 +21195,7 @@ static int ZEND_FASTCALL ZEND_CASE_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -20924,7 +21280,7 @@ str_index: /* do nothing */ break; } - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); } else { zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr); } @@ -20982,71 +21338,66 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLE } offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - switch (Z_TYPE_P(container)) { - case IS_ARRAY: { - HashTable *ht = Z_ARRVAL_P(container); + if (IS_VAR != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht = Z_ARRVAL_P(container); offset_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - zend_hash_index_del(ht, hval); - break; - case IS_LONG: - hval = Z_LVAL_P(offset); + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_LONG: + hval = Z_LVAL_P(offset); num_index_dim: - zend_hash_index_del(ht, hval); - break; - case IS_STRING: - if (IS_TMP_VAR != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { - goto num_index_dim; - } - } - if (ht == &EG(symbol_table).ht) { - zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); - } else { - zend_hash_del(ht, Z_STR_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_STRING: + if (IS_TMP_VAR != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { + goto num_index_dim; } - break; - case IS_NULL: - zend_hash_del(ht, STR_EMPTY_ALLOC()); - break; - case IS_FALSE: - hval = 0; - goto num_index_dim; - case IS_TRUE: - hval = 1; - goto num_index_dim; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_dim; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto offset_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type in unset"); - break; - } - zval_dtor(free_op2.var); - break; + } + if (ht == &EG(symbol_table).ht) { + zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); + } else { + zend_hash_del(ht, Z_STR_P(offset)); + } + break; + case IS_NULL: + zend_hash_del(ht, STR_EMPTY_ALLOC()); + break; + case IS_FALSE: + hval = 0; + goto num_index_dim; + case IS_TRUE: + hval = 1; + goto num_index_dim; + case IS_RESOURCE: + hval = Z_RES_HANDLE_P(offset); + goto num_index_dim; + case IS_REFERENCE: + offset = Z_REFVAL_P(offset); + goto offset_again; + break; + default: + zend_error(E_WARNING, "Illegal offset type in unset"); + break; } - case IS_OBJECT: - if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use object as array"); - } -//??? if (IS_TMP_VAR == IS_CONST) { -//??? zval_copy_ctor(offset); -//??? } - Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); - zval_dtor(free_op2.var); - break; - case IS_STRING: - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - ZEND_VM_CONTINUE(); /* bailed out before */ - default: - zval_dtor(free_op2.var); - break; + zval_ptr_dtor_nogc(free_op2.var); + } else if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use object as array"); + } +//??? if (IS_TMP_VAR == IS_CONST) { +//??? zval_copy_ctor(offset); +//??? } + Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + ZEND_VM_CONTINUE(); /* bailed out before */ + } else { + zval_ptr_dtor_nogc(free_op2.var); } if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; CHECK_EXCEPTION(); @@ -21068,14 +21419,14 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLE offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); ZVAL_DEREF(container); - if (Z_TYPE_P(container) == IS_OBJECT) { + if (IS_VAR == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->unset_property) { Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to unset property of non-object"); } } - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -21094,7 +21445,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_VAR_TMP_HANDLER(ZEND_O container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (Z_TYPE_P(container) == IS_ARRAY) { + if (IS_VAR != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { HashTable *ht = Z_ARRVAL_P(container); zval *value; zend_string *str; @@ -21147,8 +21498,8 @@ num_index_prop: } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); } - } else if (Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->has_dimension) { + } else if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to check element of non-array"); @@ -21157,7 +21508,7 @@ num_index_prop: if ((opline->extended_value & ZEND_ISSET) == 0) { result = !result; } - } else if (Z_TYPE_P(container) == IS_STRING) { /* string offsets */ + } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */ zval tmp; result = 0; @@ -21173,7 +21524,7 @@ num_index_prop: offset = &tmp; } } - if (Z_TYPE_P(offset) == IS_LONG) { + if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) { if ((opline->extended_value & ZEND_ISSET) || Z_STRVAL_P(container)[offset->value.lval] != '0') { @@ -21188,7 +21539,7 @@ num_index_prop: result = ((opline->extended_value & ZEND_ISSET) == 0); } - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); ZVAL_BOOL(EX_VAR(opline->result.var), result); zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); @@ -21207,8 +21558,8 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_TMP_HANDLER(ZEND_ container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->has_property) { + if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_property)) { result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to check property of non-object"); @@ -21221,7 +21572,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_TMP_HANDLER(ZEND_ result = ((opline->extended_value & ZEND_ISSET) == 0); } - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); ZVAL_BOOL(EX_VAR(opline->result.var), result); zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); @@ -21263,7 +21614,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR /* Temporary variables don't need ctor copying */ if (IS_VAR != IS_TMP_VAR) { - zval_copy_ctor(&generator->value); + zval_opt_copy_ctor(&generator->value); } } else { zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); @@ -21274,9 +21625,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_VAR == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_VAR == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -21369,7 +21721,7 @@ static int ZEND_FASTCALL ZEND_POW_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1.var); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -21661,17 +22013,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(int (*bin zval *object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); zval *property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); zval *value; - int have_get_ptr = 0; + zval *zptr; if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - object = make_real_object(object TSRMLS_CC); + if (IS_VAR != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); + } - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to assign property of non-object"); zval_ptr_dtor_nogc(free_op2.var); FREE_OP(free_op_data1); @@ -21682,20 +22036,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(int (*bin } else { /* here we are sure we are dealing with an object */ if (opline->extended_value == ZEND_ASSIGN_OBJ - && Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - SEPARATE_ZVAL_IF_NOT_REF(zptr); + && EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - have_get_ptr = 1; - binary_op(zptr, zptr, value TSRMLS_CC); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), zptr); - } - } - } + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + binary_op(zptr, zptr, value TSRMLS_CC); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); + } + } else { zval *z = NULL; zval rv; @@ -21752,15 +22103,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(int (*bin static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_VAR(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2, free_op_data2, free_op_data1; - zval *var_ptr; + zend_free_op free_op1, free_op2, free_op_data1; + zval *var_ptr, rv; zval *value, *container; SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } + if (IS_VAR != IS_UNUSED) { + ZVAL_DEREF(container); + } + if (IS_VAR == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_VAR == IS_VAR && !(free_op1.var != NULL)) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } @@ -21768,9 +22123,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_VAR(int (*bin } else { zval *dim = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - zend_fetch_dimension_address_RW(EX_VAR((opline+1)->op2.var), container, dim, IS_VAR TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + zend_fetch_dimension_address_RW(&rv, container, dim, IS_VAR TSRMLS_CC); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); } if (UNEXPECTED(var_ptr == NULL)) { @@ -21781,33 +22137,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_VAR(int (*bin if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_dim_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_dim_exit: zval_ptr_dtor_nogc(free_op2.var); FREE_OP(free_op_data1); - FREE_OP_VAR_PTR(free_op_data2); if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; CHECK_EXCEPTION(); ZEND_VM_INC_OPCODE(); @@ -21822,7 +22164,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_VAR(int (*binary_ zval *value; SAVE_OPLINE(); - value = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + value = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) { @@ -21833,30 +22175,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_VAR(int (*binary_ if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_exit: zval_ptr_dtor_nogc(free_op2.var); if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; CHECK_EXCEPTION(); @@ -22013,7 +22342,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_VAR(incdec_t i zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); @@ -22024,9 +22353,11 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_VAR(incdec_t i zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_VAR != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); zval_ptr_dtor_nogc(free_op2.var); if (RETURN_VALUE_USED(opline)) { @@ -22039,20 +22370,17 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_VAR(incdec_t i /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - SEPARATE_ZVAL_IF_NOT_REF(zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - have_get_ptr = 1; - incdec_op(zptr); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(retval, zptr); - } - } - } + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + incdec_op(zptr); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(retval, zptr); + } + } else { zval rv; if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { @@ -22105,7 +22433,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_VAR(incdec_t zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); @@ -22116,9 +22444,11 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_VAR(incdec_t zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_VAR != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); zval_ptr_dtor_nogc(free_op2.var); ZVAL_NULL(retval); @@ -22129,20 +22459,15 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_VAR(incdec_t /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - have_get_ptr = 1; - SEPARATE_ZVAL_IF_NOT_REF(zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - ZVAL_DUP(retval, zptr); + ZVAL_DEREF(zptr); + ZVAL_COPY(retval, zptr); - incdec_op(zptr); - - } - } - - if (!have_get_ptr) { + SEPARATE_ZVAL_NOREF(zptr); + incdec_op(zptr); + } else { if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { zval rv; zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); @@ -22292,9 +22617,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_VAR(int type, ZE } ZVAL_COPY(EX_VAR(opline->result.var), retval); } else { - if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) { - ZVAL_MAKE_REF(retval); - } ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); } CHECK_EXCEPTION(); @@ -22347,9 +22669,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAND container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); - if (IS_VAR != IS_VAR || !(opline->extended_value & ZEND_FETCH_ADD_LOCK)) { - zval_ptr_dtor_nogc(free_op1.var); - } + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -22366,11 +22686,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAND if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - if (EXPECTED(opline->extended_value == 0)) { - zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC); - } else { - zend_fetch_dimension_address_W_ref(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC); - } + ZVAL_DEREF(container); + zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -22392,6 +22709,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAN if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { @@ -22433,6 +22751,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_VAR_HANDLER(ZEND_OPCO if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -22464,6 +22783,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { @@ -22474,7 +22794,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_ ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_VAR_VAR(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; @@ -22486,7 +22806,7 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_VAR_VAR(ZE container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { zend_error(E_NOTICE, "Trying to get property of non-object"); ZVAL_NULL(EX_VAR(opline->result.var)); @@ -22507,11 +22827,6 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_VAR_VAR(ZE ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_property_address_read_helper_SPEC_VAR_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -22527,7 +22842,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAND zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -22551,7 +22866,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAN if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -22573,7 +22888,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAN container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -22613,7 +22928,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_VAR_HANDLER(ZEND_OPCO if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -22622,7 +22937,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_VAR_HANDLER(ZEND_OPCO CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { - return zend_fetch_property_address_read_helper_SPEC_VAR_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return ZEND_FETCH_OBJ_R_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } @@ -22639,7 +22954,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -22663,7 +22978,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, IS_VAR, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; /* assign_obj has two opcodes! */ @@ -22684,45 +22999,48 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - if (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) { - object_ptr = Z_REFVAL_P(object_ptr); - } - if (Z_TYPE_P(object_ptr) == IS_OBJECT) { + ZVAL_DEREF(object_ptr); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { zend_free_op free_op2; zval *property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_VAR, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); } else { - zend_free_op free_op2, free_op_data1, free_op_data2; + zend_free_op free_op2, free_op_data1; + zval rv; zval *value; zval *dim = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); zval *variable_ptr; - variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_VAR TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2.var); - value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(variable_ptr != NULL)) { - zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) && + EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + zend_long offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + zend_assign_to_string_offset(object_ptr, offset, value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); + FREE_OP(free_op_data1); } else { - variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_VAR TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + variable_ptr = Z_INDIRECT(rv); if (UNEXPECTED(variable_ptr == &EG(error_zval))) { - if (IS_TMP_FREE(free_op_data1)) { - zval_dtor(value); - } + FREE_OP(free_op_data1); if (RETURN_VALUE_USED(opline)) { ZVAL_NULL(EX_VAR(opline->result.var)); } - FREE_OP_VAR_PTR(free_op_data2); } else { value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC); + if ((opline+1)->op1_type == IS_VAR) { + FREE_OP(free_op_data1); + } if (RETURN_VALUE_USED(opline)) { ZVAL_COPY(EX_VAR(opline->result.var), value); } - FREE_OP_VAR_PTR(free_op_data2); } } - FREE_OP_IF_VAR(free_op_data1); } if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; /* assign_dim has two opcodes! */ @@ -22744,7 +23062,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_A if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) { if (IS_VAR == IS_TMP_VAR) { - zval_dtor(value); + zval_ptr_dtor_nogc(free_op2.var); } if (RETURN_VALUE_USED(opline)) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -22774,10 +23092,13 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL SAVE_OPLINE(); value_ptr = _get_zval_ptr_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); + } if (IS_VAR == IS_VAR && - opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF) && - !Z_ISREF_P(value_ptr)) { + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { if (!(free_op2.var != NULL)) { PZVAL_LOCK(value_ptr); /* undo the effect of get_zval_ptr_ptr() */ } @@ -22794,15 +23115,14 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL } variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); + } if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT) && UNEXPECTED(!Z_ISREF_P(variable_ptr))) { zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object"); } - if ((IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) || - (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == NULL))) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); - } if ((IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) || (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == &EG(error_zval)))) { variable_ptr = &EG(uninitialized_zval); @@ -22851,19 +23171,56 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE object = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + uint32_t nesting = 1; + if (UNEXPECTED(EG(exception) != NULL)) { zval_ptr_dtor_nogc(free_op2.var); HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); + + zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); + zval_ptr_dtor_nogc(free_op2.var); + zval_ptr_dtor_nogc(free_op1.var); + + if (EG(exception) != NULL) { + HANDLE_EXCEPTION(); + } + + /* No exception raised: Skip over arguments until fcall opcode with correct + * nesting level. Return NULL (except when return value unused) */ + do { + opline++; + if (opline->opcode == ZEND_INIT_FCALL || + opline->opcode == ZEND_INIT_FCALL_BY_NAME || + opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME || + opline->opcode == ZEND_INIT_METHOD_CALL || + opline->opcode == ZEND_INIT_STATIC_METHOD_CALL || + opline->opcode == ZEND_INIT_USER_CALL || + opline->opcode == ZEND_NEW + ) { + nesting++; + } else if (opline->opcode == ZEND_DO_FCALL) { + nesting--; + } + } while (nesting); + + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + /* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */ + if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) { + opline++; + } + ZEND_VM_JMP(++opline); } obj = Z_OBJ_P(object); - called_scope = zend_get_class_entry(obj TSRMLS_CC); + called_scope = obj->ce; if (IS_VAR != IS_CONST || - (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) { + EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { zend_object *orig_obj = obj; if (UNEXPECTED(obj->handlers->get_method == NULL)) { @@ -22873,7 +23230,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE /* First, locate the function. */ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name)); + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); } if (IS_VAR == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -22883,14 +23240,14 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE } } - if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { obj = NULL; } else { GC_REFCOUNT(obj)++; /* For $this pointer */ } - EX(call) = zend_vm_stack_push_call_frame( - fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_FUNCTION, + fbc, opline->extended_value, called_scope, obj, EX(call) TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); zval_ptr_dtor_nogc(free_op1.var); @@ -22972,7 +23329,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND if (UNEXPECTED(ce->constructor == NULL)) { zend_error_noreturn(E_ERROR, "Cannot call constructor"); } - if (EX(object) && zend_get_class_entry(EX(object) TSRMLS_CC) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val); } fbc = ce->constructor; @@ -22980,19 +23337,27 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { - if (EX(object)) { - object = EX(object); + if (Z_OBJ(EX(This))) { + object = Z_OBJ(EX(This)); GC_REFCOUNT(object)++; - if (object->handlers->get_class_entry && - !instanceof_function(zend_get_class_entry(object TSRMLS_CC), ce TSRMLS_CC)) { - /* We are calling method of the other (incompatible) class, - but passing $this. This is done for compatibility with php-4. */ - if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val); - } else { - /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val); - } + } + if (!object || + !instanceof_function(object->ce, ce TSRMLS_CC)) { + /* We are calling method of the other (incompatible) class, + but passing $this. This is done for compatibility with php-4. */ + if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + zend_error( + object ? E_DEPRECATED : E_STRICT, + "Non-static method %s::%s() should not be called statically%s", + fbc->common.scope->name->val, fbc->common.function_name->val, + object ? ", assuming $this from incompatible context" : ""); + } else { + /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ + zend_error_noreturn( + E_ERROR, + "Non-static method %s::%s() cannot be called statically%s", + fbc->common.scope->name->val, fbc->common.function_name->val, + object ? ", assuming $this from incompatible context" : ""); } } } @@ -23004,8 +23369,8 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND } } - EX(call) = zend_vm_stack_push_call_frame( - fbc, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_FUNCTION, + fbc, opline->extended_value, ce, object, EX(call) TSRMLS_CC); if (IS_VAR == IS_UNUSED) { EX(call)->return_value = NULL; @@ -23184,8 +23549,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLE ZVAL_UNDEF(&tmp); if (IS_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { - ZVAL_DUP(&tmp, varname); - convert_to_string(&tmp); + ZVAL_STR(&tmp, zval_get_string(varname)); varname = &tmp; } @@ -23245,71 +23609,66 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLE } offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - switch (Z_TYPE_P(container)) { - case IS_ARRAY: { - HashTable *ht = Z_ARRVAL_P(container); + if (IS_VAR != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht = Z_ARRVAL_P(container); offset_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - zend_hash_index_del(ht, hval); - break; - case IS_LONG: - hval = Z_LVAL_P(offset); + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_LONG: + hval = Z_LVAL_P(offset); num_index_dim: - zend_hash_index_del(ht, hval); - break; - case IS_STRING: - if (IS_VAR != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { - goto num_index_dim; - } - } - if (ht == &EG(symbol_table).ht) { - zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); - } else { - zend_hash_del(ht, Z_STR_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_STRING: + if (IS_VAR != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { + goto num_index_dim; } - break; - case IS_NULL: - zend_hash_del(ht, STR_EMPTY_ALLOC()); - break; - case IS_FALSE: - hval = 0; - goto num_index_dim; - case IS_TRUE: - hval = 1; - goto num_index_dim; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_dim; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto offset_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type in unset"); - break; - } - zval_ptr_dtor_nogc(free_op2.var); - break; + } + if (ht == &EG(symbol_table).ht) { + zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); + } else { + zend_hash_del(ht, Z_STR_P(offset)); + } + break; + case IS_NULL: + zend_hash_del(ht, STR_EMPTY_ALLOC()); + break; + case IS_FALSE: + hval = 0; + goto num_index_dim; + case IS_TRUE: + hval = 1; + goto num_index_dim; + case IS_RESOURCE: + hval = Z_RES_HANDLE_P(offset); + goto num_index_dim; + case IS_REFERENCE: + offset = Z_REFVAL_P(offset); + goto offset_again; + break; + default: + zend_error(E_WARNING, "Illegal offset type in unset"); + break; } - case IS_OBJECT: - if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use object as array"); - } -//??? if (IS_VAR == IS_CONST) { -//??? zval_copy_ctor(offset); -//??? } - Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2.var); - break; - case IS_STRING: - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - ZEND_VM_CONTINUE(); /* bailed out before */ - default: - zval_ptr_dtor_nogc(free_op2.var); - break; + zval_ptr_dtor_nogc(free_op2.var); + } else if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use object as array"); + } +//??? if (IS_VAR == IS_CONST) { +//??? zval_copy_ctor(offset); +//??? } + Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + ZEND_VM_CONTINUE(); /* bailed out before */ + } else { + zval_ptr_dtor_nogc(free_op2.var); } if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; CHECK_EXCEPTION(); @@ -23331,7 +23690,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLE offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); ZVAL_DEREF(container); - if (Z_TYPE_P(container) == IS_OBJECT) { + if (IS_VAR == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->unset_property) { Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { @@ -23348,26 +23707,28 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_VAR_HANDLER(ZEND_OPCOD { USE_OPLINE zval *value; - zend_bool isset = 1; SAVE_OPLINE(); if (IS_VAR == IS_CV && IS_VAR == IS_UNUSED && (opline->extended_value & ZEND_QUICK_SET)) { - if (Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_UNDEF) { - value = EX_VAR(opline->op1.var); - ZVAL_DEREF(value); - } else { - isset = 0; + value = EX_VAR(opline->op1.var); + if (opline->extended_value & ZEND_ISSET) { + ZVAL_BOOL(EX_VAR(opline->result.var), + Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + ZVAL_BOOL(EX_VAR(opline->result.var), + !i_zend_is_true(value TSRMLS_CC)); + CHECK_EXCEPTION(); } + ZEND_VM_NEXT_OPCODE(); } else { - HashTable *target_symbol_table; zend_free_op free_op1; zval tmp, *varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { - ZVAL_DUP(&tmp, varname); - convert_to_string(&tmp); + ZVAL_STR(&tmp, zval_get_string(varname)); varname = &tmp; } @@ -23389,39 +23750,28 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_VAR_HANDLER(ZEND_OPCOD ce = Z_CE_P(EX_VAR(opline->op2.var)); } value = zend_std_get_static_property(ce, Z_STR_P(varname), 1, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); - if (!value) { - isset = 0; - } } else { - target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); - if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) { - isset = 0; - } + HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname)); } if (IS_VAR != IS_CONST && varname == &tmp) { zval_dtor(&tmp); } zval_ptr_dtor_nogc(free_op1.var); - } - if (opline->extended_value & ZEND_ISSET) { - if (isset && Z_TYPE_P(value) != IS_NULL && - (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) { - ZVAL_BOOL(EX_VAR(opline->result.var), 1); - } else { - ZVAL_BOOL(EX_VAR(opline->result.var), 0); - } - } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { - if (!isset || !i_zend_is_true(value TSRMLS_CC)) { - ZVAL_BOOL(EX_VAR(opline->result.var), 1); - } else { - ZVAL_BOOL(EX_VAR(opline->result.var), 0); + if (opline->extended_value & ZEND_ISSET) { + ZVAL_BOOL(EX_VAR(opline->result.var), + value && Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + ZVAL_BOOL(EX_VAR(opline->result.var), + !value || !i_zend_is_true(value TSRMLS_CC)); } - } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } } static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -23437,7 +23787,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_VAR_VAR_HANDLER(ZEND_O container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (Z_TYPE_P(container) == IS_ARRAY) { + if (IS_VAR != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { HashTable *ht = Z_ARRVAL_P(container); zval *value; zend_string *str; @@ -23490,8 +23840,8 @@ num_index_prop: } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); } - } else if (Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->has_dimension) { + } else if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to check element of non-array"); @@ -23500,7 +23850,7 @@ num_index_prop: if ((opline->extended_value & ZEND_ISSET) == 0) { result = !result; } - } else if (Z_TYPE_P(container) == IS_STRING) { /* string offsets */ + } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */ zval tmp; result = 0; @@ -23516,7 +23866,7 @@ num_index_prop: offset = &tmp; } } - if (Z_TYPE_P(offset) == IS_LONG) { + if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) { if ((opline->extended_value & ZEND_ISSET) || Z_STRVAL_P(container)[offset->value.lval] != '0') { @@ -23550,8 +23900,8 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_VAR_HANDLER(ZEND_ container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->has_property) { + if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_property)) { result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to check property of non-object"); @@ -23571,6 +23921,45 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_VAR_HANDLER(ZEND_ ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *expr; + zend_bool result; + + SAVE_OPLINE(); + expr = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + + if (Z_TYPE_P(expr) == IS_OBJECT) { + zend_class_entry *ce; + + if (IS_VAR == IS_CONST) { + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC); + if (UNEXPECTED(ce == NULL)) { + ZVAL_FALSE(EX_VAR(opline->result.var)); + zval_ptr_dtor_nogc(free_op1.var); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op2.var)); + } + result = instanceof_function(Z_OBJCE_P(expr), ce TSRMLS_CC); + } else { + result = 0; + } + ZVAL_BOOL(EX_VAR(opline->result.var), result); + zval_ptr_dtor_nogc(free_op1.var); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -23606,7 +23995,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR /* Temporary variables don't need ctor copying */ if (IS_VAR != IS_TMP_VAR) { - zval_copy_ctor(&generator->value); + zval_opt_copy_ctor(&generator->value); } } else { zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); @@ -23617,9 +24006,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_VAR == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_VAR == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -23729,17 +24119,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(int (* zval *object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); zval *property = NULL; zval *value; - int have_get_ptr = 0; + zval *zptr; if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - object = make_real_object(object TSRMLS_CC); + if (IS_VAR != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); + } - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to assign property of non-object"); FREE_OP(free_op_data1); @@ -23750,20 +24142,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(int (* } else { /* here we are sure we are dealing with an object */ if (opline->extended_value == ZEND_ASSIGN_OBJ - && Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_UNUSED == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - SEPARATE_ZVAL_IF_NOT_REF(zptr); + && EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_UNUSED == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - have_get_ptr = 1; - binary_op(zptr, zptr, value TSRMLS_CC); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), zptr); - } - } - } + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + binary_op(zptr, zptr, value TSRMLS_CC); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); + } + } else { zval *z = NULL; zval rv; @@ -23819,15 +24208,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(int (* static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_UNUSED(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op_data2, free_op_data1; - zval *var_ptr; + zend_free_op free_op1, free_op_data1; + zval *var_ptr, rv; zval *value, *container; SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } + if (IS_VAR != IS_UNUSED) { + ZVAL_DEREF(container); + } + if (IS_VAR == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_VAR == IS_VAR && !(free_op1.var != NULL)) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } @@ -23835,9 +24228,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_UNUSED(int (* } else { zval *dim = NULL; - zend_fetch_dimension_address_RW(EX_VAR((opline+1)->op2.var), container, dim, IS_UNUSED TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + zend_fetch_dimension_address_RW(&rv, container, dim, IS_UNUSED TSRMLS_CC); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); } if (UNEXPECTED(var_ptr == NULL)) { @@ -23848,33 +24242,18 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_UNUSED(int (* if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_dim_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_dim_exit: - FREE_OP(free_op_data1); - FREE_OP_VAR_PTR(free_op_data2); if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; CHECK_EXCEPTION(); ZEND_VM_INC_OPCODE(); @@ -23900,31 +24279,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_UNUSED(int (*bina if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_exit: - if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -24179,9 +24544,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_UNUSED(int type, } ZVAL_COPY(EX_VAR(opline->result.var), retval); } else { - if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) { - ZVAL_MAKE_REF(retval); - } ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); } CHECK_EXCEPTION(); @@ -24236,11 +24598,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_H if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - if (EXPECTED(opline->extended_value == 0)) { - zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC); - } else { - zend_fetch_dimension_address_W_ref(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC); - } + ZVAL_DEREF(container); + zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -24262,6 +24621,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { @@ -24288,6 +24648,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_UNUSED_HANDLER(ZEND_O if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -24319,45 +24680,48 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HA if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - if (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) { - object_ptr = Z_REFVAL_P(object_ptr); - } - if (Z_TYPE_P(object_ptr) == IS_OBJECT) { + ZVAL_DEREF(object_ptr); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { zval *property_name = NULL; - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_UNUSED == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_VAR, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_UNUSED == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); } else { - zend_free_op free_op_data1, free_op_data2; + zend_free_op free_op_data1; + zval rv; zval *value; zval *dim = NULL; zval *variable_ptr; - variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_UNUSED TSRMLS_CC); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) && + EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + zend_long offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W TSRMLS_CC); - value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(variable_ptr != NULL)) { - zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + zend_assign_to_string_offset(object_ptr, offset, value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); + FREE_OP(free_op_data1); } else { - variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_UNUSED TSRMLS_CC); + + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + variable_ptr = Z_INDIRECT(rv); if (UNEXPECTED(variable_ptr == &EG(error_zval))) { - if (IS_TMP_FREE(free_op_data1)) { - zval_dtor(value); - } + FREE_OP(free_op_data1); if (RETURN_VALUE_USED(opline)) { ZVAL_NULL(EX_VAR(opline->result.var)); } - FREE_OP_VAR_PTR(free_op_data2); } else { value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC); + if ((opline+1)->op1_type == IS_VAR) { + FREE_OP(free_op_data1); + } if (RETURN_VALUE_USED(opline)) { ZVAL_COPY(EX_VAR(opline->result.var), value); } - FREE_OP_VAR_PTR(free_op_data2); } } - FREE_OP_IF_VAR(free_op_data1); } if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; /* assign_dim has two opcodes! */ @@ -24439,7 +24803,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(Z if (UNEXPECTED(ce->constructor == NULL)) { zend_error_noreturn(E_ERROR, "Cannot call constructor"); } - if (EX(object) && zend_get_class_entry(EX(object) TSRMLS_CC) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val); } fbc = ce->constructor; @@ -24447,19 +24811,27 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(Z object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { - if (EX(object)) { - object = EX(object); + if (Z_OBJ(EX(This))) { + object = Z_OBJ(EX(This)); GC_REFCOUNT(object)++; - if (object->handlers->get_class_entry && - !instanceof_function(zend_get_class_entry(object TSRMLS_CC), ce TSRMLS_CC)) { - /* We are calling method of the other (incompatible) class, - but passing $this. This is done for compatibility with php-4. */ - if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val); - } else { - /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val); - } + } + if (!object || + !instanceof_function(object->ce, ce TSRMLS_CC)) { + /* We are calling method of the other (incompatible) class, + but passing $this. This is done for compatibility with php-4. */ + if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + zend_error( + object ? E_DEPRECATED : E_STRICT, + "Non-static method %s::%s() should not be called statically%s", + fbc->common.scope->name->val, fbc->common.function_name->val, + object ? ", assuming $this from incompatible context" : ""); + } else { + /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ + zend_error_noreturn( + E_ERROR, + "Non-static method %s::%s() cannot be called statically%s", + fbc->common.scope->name->val, fbc->common.function_name->val, + object ? ", assuming $this from incompatible context" : ""); } } } @@ -24471,8 +24843,8 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(Z } } - EX(call) = zend_vm_stack_push_call_frame( - fbc, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_FUNCTION, + fbc, opline->extended_value, ce, object, EX(call) TSRMLS_CC); if (IS_UNUSED == IS_UNUSED) { EX(call)->return_value = NULL; @@ -24635,8 +25007,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HAN ZVAL_UNDEF(&tmp); if (IS_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { - ZVAL_DUP(&tmp, varname); - convert_to_string(&tmp); + ZVAL_STR(&tmp, zval_get_string(varname)); varname = &tmp; } @@ -24681,26 +25052,28 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_UNUSED_HANDLER(ZEND_OP { USE_OPLINE zval *value; - zend_bool isset = 1; SAVE_OPLINE(); if (IS_VAR == IS_CV && IS_UNUSED == IS_UNUSED && (opline->extended_value & ZEND_QUICK_SET)) { - if (Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_UNDEF) { - value = EX_VAR(opline->op1.var); - ZVAL_DEREF(value); - } else { - isset = 0; + value = EX_VAR(opline->op1.var); + if (opline->extended_value & ZEND_ISSET) { + ZVAL_BOOL(EX_VAR(opline->result.var), + Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + ZVAL_BOOL(EX_VAR(opline->result.var), + !i_zend_is_true(value TSRMLS_CC)); + CHECK_EXCEPTION(); } + ZEND_VM_NEXT_OPCODE(); } else { - HashTable *target_symbol_table; zend_free_op free_op1; zval tmp, *varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { - ZVAL_DUP(&tmp, varname); - convert_to_string(&tmp); + ZVAL_STR(&tmp, zval_get_string(varname)); varname = &tmp; } @@ -24722,39 +25095,28 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_UNUSED_HANDLER(ZEND_OP ce = Z_CE_P(EX_VAR(opline->op2.var)); } value = zend_std_get_static_property(ce, Z_STR_P(varname), 1, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); - if (!value) { - isset = 0; - } } else { - target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); - if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) { - isset = 0; - } + HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname)); } if (IS_VAR != IS_CONST && varname == &tmp) { zval_dtor(&tmp); } zval_ptr_dtor_nogc(free_op1.var); - } - if (opline->extended_value & ZEND_ISSET) { - if (isset && Z_TYPE_P(value) != IS_NULL && - (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) { - ZVAL_BOOL(EX_VAR(opline->result.var), 1); - } else { - ZVAL_BOOL(EX_VAR(opline->result.var), 0); - } - } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { - if (!isset || !i_zend_is_true(value TSRMLS_CC)) { - ZVAL_BOOL(EX_VAR(opline->result.var), 1); - } else { - ZVAL_BOOL(EX_VAR(opline->result.var), 0); + if (opline->extended_value & ZEND_ISSET) { + ZVAL_BOOL(EX_VAR(opline->result.var), + value && Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + ZVAL_BOOL(EX_VAR(opline->result.var), + !value || !i_zend_is_true(value TSRMLS_CC)); } - } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } } static int ZEND_FASTCALL ZEND_SEPARATE_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -24810,7 +25172,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER /* Temporary variables don't need ctor copying */ if (IS_VAR != IS_TMP_VAR) { - zval_copy_ctor(&generator->value); + zval_opt_copy_ctor(&generator->value); } } else { zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); @@ -24821,9 +25183,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_VAR == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_VAR == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -25193,17 +25556,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CV(int (*bina zval *object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); zval *property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); zval *value; - int have_get_ptr = 0; + zval *zptr; if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - object = make_real_object(object TSRMLS_CC); + if (IS_VAR != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); + } - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to assign property of non-object"); FREE_OP(free_op_data1); @@ -25214,20 +25579,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CV(int (*bina } else { /* here we are sure we are dealing with an object */ if (opline->extended_value == ZEND_ASSIGN_OBJ - && Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - SEPARATE_ZVAL_IF_NOT_REF(zptr); + && EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - have_get_ptr = 1; - binary_op(zptr, zptr, value TSRMLS_CC); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), zptr); - } - } - } + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + binary_op(zptr, zptr, value TSRMLS_CC); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); + } + } else { zval *z = NULL; zval rv; @@ -25283,15 +25645,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CV(int (*bina static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_CV(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op_data2, free_op_data1; - zval *var_ptr; + zend_free_op free_op1, free_op_data1; + zval *var_ptr, rv; zval *value, *container; SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } + if (IS_VAR != IS_UNUSED) { + ZVAL_DEREF(container); + } + if (IS_VAR == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_VAR == IS_VAR && !(free_op1.var != NULL)) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } @@ -25299,9 +25665,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_CV(int (*bina } else { zval *dim = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - zend_fetch_dimension_address_RW(EX_VAR((opline+1)->op2.var), container, dim, IS_CV TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + zend_fetch_dimension_address_RW(&rv, container, dim, IS_CV TSRMLS_CC); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); } if (UNEXPECTED(var_ptr == NULL)) { @@ -25312,33 +25679,18 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_CV(int (*bina if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_dim_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_dim_exit: - FREE_OP(free_op_data1); - FREE_OP_VAR_PTR(free_op_data2); if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; CHECK_EXCEPTION(); ZEND_VM_INC_OPCODE(); @@ -25353,7 +25705,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_CV(int (*binary_o zval *value; SAVE_OPLINE(); - value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + value = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) { @@ -25364,31 +25716,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_CV(int (*binary_o if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_exit: - if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -25544,7 +25882,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_CV(incdec_t in zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); @@ -25555,9 +25893,11 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_CV(incdec_t in zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_VAR != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); if (RETURN_VALUE_USED(opline)) { @@ -25570,20 +25910,17 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_CV(incdec_t in /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - SEPARATE_ZVAL_IF_NOT_REF(zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - have_get_ptr = 1; - incdec_op(zptr); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(retval, zptr); - } - } - } + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + incdec_op(zptr); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(retval, zptr); + } + } else { zval rv; if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { @@ -25635,7 +25972,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_CV(incdec_t i zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); @@ -25646,9 +25983,11 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_CV(incdec_t i zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_VAR != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); ZVAL_NULL(retval); @@ -25659,20 +25998,15 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_CV(incdec_t i /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - have_get_ptr = 1; - SEPARATE_ZVAL_IF_NOT_REF(zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - ZVAL_DUP(retval, zptr); - - incdec_op(zptr); - - } - } + ZVAL_DEREF(zptr); + ZVAL_COPY(retval, zptr); - if (!have_get_ptr) { + SEPARATE_ZVAL_NOREF(zptr); + incdec_op(zptr); + } else { if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { zval rv; zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); @@ -25725,9 +26059,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDL container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); - if (IS_VAR != IS_VAR || !(opline->extended_value & ZEND_FETCH_ADD_LOCK)) { - zval_ptr_dtor_nogc(free_op1.var); - } + zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -25744,11 +26076,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDL if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - if (EXPECTED(opline->extended_value == 0)) { - zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); - } else { - zend_fetch_dimension_address_W_ref(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); - } + ZVAL_DEREF(container); + zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -25770,6 +26099,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HAND if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { @@ -25811,6 +26141,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CV_HANDLER(ZEND_OPCOD if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -25842,6 +26173,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_H if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { @@ -25852,7 +26184,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_H ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_VAR_CV(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; @@ -25864,7 +26196,7 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_VAR_CV(ZEN container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { zend_error(E_NOTICE, "Trying to get property of non-object"); ZVAL_NULL(EX_VAR(opline->result.var)); @@ -25884,11 +26216,6 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_VAR_CV(ZEN ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_property_address_read_helper_SPEC_VAR_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -25904,7 +26231,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDL zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -25928,7 +26255,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HAND if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -25950,7 +26277,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HAND container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -25989,7 +26316,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CV_HANDLER(ZEND_OPCOD if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -25998,7 +26325,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CV_HANDLER(ZEND_OPCOD CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { - return zend_fetch_property_address_read_helper_SPEC_VAR_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return ZEND_FETCH_OBJ_R_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } @@ -26015,7 +26342,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_H if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -26039,7 +26366,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, IS_VAR, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; /* assign_obj has two opcodes! */ @@ -26060,45 +26387,48 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - if (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) { - object_ptr = Z_REFVAL_P(object_ptr); - } - if (Z_TYPE_P(object_ptr) == IS_OBJECT) { + ZVAL_DEREF(object_ptr); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { zval *property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_VAR, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); } else { - zend_free_op free_op_data1, free_op_data2; + zend_free_op free_op_data1; + zval rv; zval *value; zval *dim = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); zval *variable_ptr; - variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_CV TSRMLS_CC); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) && + EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + zend_long offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W TSRMLS_CC); - value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(variable_ptr != NULL)) { - zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + zend_assign_to_string_offset(object_ptr, offset, value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); + FREE_OP(free_op_data1); } else { - variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_CV TSRMLS_CC); + + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + variable_ptr = Z_INDIRECT(rv); if (UNEXPECTED(variable_ptr == &EG(error_zval))) { - if (IS_TMP_FREE(free_op_data1)) { - zval_dtor(value); - } + FREE_OP(free_op_data1); if (RETURN_VALUE_USED(opline)) { ZVAL_NULL(EX_VAR(opline->result.var)); } - FREE_OP_VAR_PTR(free_op_data2); } else { value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC); + if ((opline+1)->op1_type == IS_VAR) { + FREE_OP(free_op_data1); + } if (RETURN_VALUE_USED(opline)) { ZVAL_COPY(EX_VAR(opline->result.var), value); } - FREE_OP_VAR_PTR(free_op_data2); } } - FREE_OP_IF_VAR(free_op_data1); } if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; /* assign_dim has two opcodes! */ @@ -26120,7 +26450,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_AR if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) { if (IS_CV == IS_TMP_VAR) { - zval_dtor(value); + } if (RETURN_VALUE_USED(opline)) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -26149,10 +26479,13 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE SAVE_OPLINE(); value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op2.var TSRMLS_CC); + if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); + } if (IS_CV == IS_VAR && - opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF) && - !Z_ISREF_P(value_ptr)) { + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { if (!0) { PZVAL_LOCK(value_ptr); /* undo the effect of get_zval_ptr_ptr() */ } @@ -26169,15 +26502,14 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE } variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); + } if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT) && UNEXPECTED(!Z_ISREF_P(variable_ptr))) { zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object"); } - if ((IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) || - (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == NULL))) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); - } if ((IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) || (IS_CV == IS_VAR && UNEXPECTED(value_ptr == &EG(error_zval)))) { variable_ptr = &EG(uninitialized_zval); @@ -26225,19 +26557,56 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_ object = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + uint32_t nesting = 1; + if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); + + zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); + + zval_ptr_dtor_nogc(free_op1.var); + + if (EG(exception) != NULL) { + HANDLE_EXCEPTION(); + } + + /* No exception raised: Skip over arguments until fcall opcode with correct + * nesting level. Return NULL (except when return value unused) */ + do { + opline++; + if (opline->opcode == ZEND_INIT_FCALL || + opline->opcode == ZEND_INIT_FCALL_BY_NAME || + opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME || + opline->opcode == ZEND_INIT_METHOD_CALL || + opline->opcode == ZEND_INIT_STATIC_METHOD_CALL || + opline->opcode == ZEND_INIT_USER_CALL || + opline->opcode == ZEND_NEW + ) { + nesting++; + } else if (opline->opcode == ZEND_DO_FCALL) { + nesting--; + } + } while (nesting); + + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + /* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */ + if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) { + opline++; + } + ZEND_VM_JMP(++opline); } obj = Z_OBJ_P(object); - called_scope = zend_get_class_entry(obj TSRMLS_CC); + called_scope = obj->ce; if (IS_CV != IS_CONST || - (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) { + EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { zend_object *orig_obj = obj; if (UNEXPECTED(obj->handlers->get_method == NULL)) { @@ -26247,7 +26616,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_ /* First, locate the function. */ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name)); + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); } if (IS_CV == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -26257,14 +26626,14 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_ } } - if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { obj = NULL; } else { GC_REFCOUNT(obj)++; /* For $this pointer */ } - EX(call) = zend_vm_stack_push_call_frame( - fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_FUNCTION, + fbc, opline->extended_value, called_scope, obj, EX(call) TSRMLS_CC); zval_ptr_dtor_nogc(free_op1.var); @@ -26345,7 +26714,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_ if (UNEXPECTED(ce->constructor == NULL)) { zend_error_noreturn(E_ERROR, "Cannot call constructor"); } - if (EX(object) && zend_get_class_entry(EX(object) TSRMLS_CC) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val); } fbc = ce->constructor; @@ -26353,19 +26722,27 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_ object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { - if (EX(object)) { - object = EX(object); + if (Z_OBJ(EX(This))) { + object = Z_OBJ(EX(This)); GC_REFCOUNT(object)++; - if (object->handlers->get_class_entry && - !instanceof_function(zend_get_class_entry(object TSRMLS_CC), ce TSRMLS_CC)) { - /* We are calling method of the other (incompatible) class, - but passing $this. This is done for compatibility with php-4. */ - if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val); - } else { - /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val); - } + } + if (!object || + !instanceof_function(object->ce, ce TSRMLS_CC)) { + /* We are calling method of the other (incompatible) class, + but passing $this. This is done for compatibility with php-4. */ + if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + zend_error( + object ? E_DEPRECATED : E_STRICT, + "Non-static method %s::%s() should not be called statically%s", + fbc->common.scope->name->val, fbc->common.function_name->val, + object ? ", assuming $this from incompatible context" : ""); + } else { + /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ + zend_error_noreturn( + E_ERROR, + "Non-static method %s::%s() cannot be called statically%s", + fbc->common.scope->name->val, fbc->common.function_name->val, + object ? ", assuming $this from incompatible context" : ""); } } } @@ -26377,8 +26754,8 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_ } } - EX(call) = zend_vm_stack_push_call_frame( - fbc, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_FUNCTION, + fbc, opline->extended_value, ce, object, EX(call) TSRMLS_CC); if (IS_CV == IS_UNUSED) { EX(call)->return_value = NULL; @@ -26541,71 +26918,66 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER } offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - switch (Z_TYPE_P(container)) { - case IS_ARRAY: { - HashTable *ht = Z_ARRVAL_P(container); + if (IS_VAR != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht = Z_ARRVAL_P(container); offset_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - zend_hash_index_del(ht, hval); - break; - case IS_LONG: - hval = Z_LVAL_P(offset); + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_LONG: + hval = Z_LVAL_P(offset); num_index_dim: - zend_hash_index_del(ht, hval); - break; - case IS_STRING: - if (IS_CV != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { - goto num_index_dim; - } - } - if (ht == &EG(symbol_table).ht) { - zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); - } else { - zend_hash_del(ht, Z_STR_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_STRING: + if (IS_CV != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { + goto num_index_dim; } - break; - case IS_NULL: - zend_hash_del(ht, STR_EMPTY_ALLOC()); - break; - case IS_FALSE: - hval = 0; - goto num_index_dim; - case IS_TRUE: - hval = 1; - goto num_index_dim; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_dim; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto offset_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type in unset"); - break; - } + } + if (ht == &EG(symbol_table).ht) { + zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); + } else { + zend_hash_del(ht, Z_STR_P(offset)); + } + break; + case IS_NULL: + zend_hash_del(ht, STR_EMPTY_ALLOC()); + break; + case IS_FALSE: + hval = 0; + goto num_index_dim; + case IS_TRUE: + hval = 1; + goto num_index_dim; + case IS_RESOURCE: + hval = Z_RES_HANDLE_P(offset); + goto num_index_dim; + case IS_REFERENCE: + offset = Z_REFVAL_P(offset); + goto offset_again; + break; + default: + zend_error(E_WARNING, "Illegal offset type in unset"); + break; + } - break; + } else if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use object as array"); } - case IS_OBJECT: - if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use object as array"); - } -//??? if (IS_CV == IS_CONST) { -//??? zval_copy_ctor(offset); -//??? } - Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); +//??? if (IS_CV == IS_CONST) { +//??? zval_copy_ctor(offset); +//??? } + Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); - break; - case IS_STRING: - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - ZEND_VM_CONTINUE(); /* bailed out before */ - default: + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + ZEND_VM_CONTINUE(); /* bailed out before */ + } else { - break; } if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; CHECK_EXCEPTION(); @@ -26627,7 +26999,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); ZVAL_DEREF(container); - if (Z_TYPE_P(container) == IS_OBJECT) { + if (IS_VAR == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->unset_property) { Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { @@ -26653,7 +27025,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OP container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (Z_TYPE_P(container) == IS_ARRAY) { + if (IS_VAR != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { HashTable *ht = Z_ARRVAL_P(container); zval *value; zend_string *str; @@ -26706,8 +27078,8 @@ num_index_prop: } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); } - } else if (Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->has_dimension) { + } else if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to check element of non-array"); @@ -26716,7 +27088,7 @@ num_index_prop: if ((opline->extended_value & ZEND_ISSET) == 0) { result = !result; } - } else if (Z_TYPE_P(container) == IS_STRING) { /* string offsets */ + } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */ zval tmp; result = 0; @@ -26732,7 +27104,7 @@ num_index_prop: offset = &tmp; } } - if (Z_TYPE_P(offset) == IS_LONG) { + if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) { if ((opline->extended_value & ZEND_ISSET) || Z_STRVAL_P(container)[offset->value.lval] != '0') { @@ -26765,8 +27137,8 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_CV_HANDLER(ZEND_O container = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->has_property) { + if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_property)) { result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to check property of non-object"); @@ -26820,7 +27192,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG /* Temporary variables don't need ctor copying */ if (IS_VAR != IS_TMP_VAR) { - zval_copy_ctor(&generator->value); + zval_opt_copy_ctor(&generator->value); } } else { zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); @@ -26831,9 +27203,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_VAR == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_VAR == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -26946,10 +27319,10 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARG zend_object_clone_obj_t clone_call; SAVE_OPLINE(); - obj = _get_obj_zval_ptr_unused(TSRMLS_C); + obj = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); if (IS_UNUSED == IS_CONST || - UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT)) { + (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT))) { if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -27020,20 +27393,22 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(int { USE_OPLINE zend_free_op free_op_data1; - zval *object = _get_obj_zval_ptr_unused(TSRMLS_C); + zval *object = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); zval *property = opline->op2.zv; zval *value; - int have_get_ptr = 0; + zval *zptr; if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - object = make_real_object(object TSRMLS_CC); + if (IS_UNUSED != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); + } - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to assign property of non-object"); FREE_OP(free_op_data1); @@ -27044,20 +27419,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(int } else { /* here we are sure we are dealing with an object */ if (opline->extended_value == ZEND_ASSIGN_OBJ - && Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - SEPARATE_ZVAL_IF_NOT_REF(zptr); + && EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - have_get_ptr = 1; - binary_op(zptr, zptr, value TSRMLS_CC); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), zptr); - } - } - } + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + binary_op(zptr, zptr, value TSRMLS_CC); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); + } + } else { zval *z = NULL; zval rv; @@ -27112,15 +27484,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(int static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data2, free_op_data1; - zval *var_ptr; + zend_free_op free_op_data1; + zval *var_ptr, rv; zval *value, *container; SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(TSRMLS_C); + container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } + if (IS_UNUSED != IS_UNUSED) { + ZVAL_DEREF(container); + } + if (IS_UNUSED == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_UNUSED == IS_VAR && !0) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } @@ -27128,9 +27504,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(int } else { zval *dim = opline->op2.zv; - zend_fetch_dimension_address_RW(EX_VAR((opline+1)->op2.var), container, dim, IS_CONST TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + zend_fetch_dimension_address_RW(&rv, container, dim, IS_CONST TSRMLS_CC); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); } if (UNEXPECTED(var_ptr == NULL)) { @@ -27141,33 +27518,18 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(int if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_dim_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_dim_exit: - FREE_OP(free_op_data1); - FREE_OP_VAR_PTR(free_op_data2); CHECK_EXCEPTION(); ZEND_VM_INC_OPCODE(); @@ -27193,31 +27555,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_CONST(int (*bi if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_exit: - CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -27373,10 +27721,10 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CONST(incde zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); - object = _get_obj_zval_ptr_unused(TSRMLS_C); + object = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); property = opline->op2.zv; retval = EX_VAR(opline->result.var); @@ -27384,9 +27732,11 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CONST(incde zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_UNUSED != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); if (RETURN_VALUE_USED(opline)) { @@ -27399,20 +27749,17 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CONST(incde /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - SEPARATE_ZVAL_IF_NOT_REF(zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - have_get_ptr = 1; - incdec_op(zptr); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(retval, zptr); - } - } - } + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + incdec_op(zptr); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(retval, zptr); + } + } else { zval rv; if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { @@ -27464,10 +27811,10 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CONST(incd zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); - object = _get_obj_zval_ptr_unused(TSRMLS_C); + object = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); property = opline->op2.zv; retval = EX_VAR(opline->result.var); @@ -27475,9 +27822,11 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CONST(incd zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_UNUSED != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); ZVAL_NULL(retval); @@ -27488,20 +27837,15 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CONST(incd /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - have_get_ptr = 1; - SEPARATE_ZVAL_IF_NOT_REF(zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - ZVAL_DUP(retval, zptr); + ZVAL_DEREF(zptr); + ZVAL_COPY(retval, zptr); - incdec_op(zptr); - - } - } - - if (!have_get_ptr) { + SEPARATE_ZVAL_NOREF(zptr); + incdec_op(zptr); + } else { if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { zval rv; zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); @@ -27544,7 +27888,7 @@ static int ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCOD return zend_post_incdec_property_helper_SPEC_UNUSED_CONST(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } -static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_UNUSED_CONST(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -27553,10 +27897,10 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_UNUSED_CON zval *offset; SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(TSRMLS_C); + container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); offset = opline->op2.zv; - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { zend_error(E_NOTICE, "Trying to get property of non-object"); ZVAL_NULL(EX_VAR(opline->result.var)); @@ -27576,11 +27920,6 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_UNUSED_CON ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_property_address_read_helper_SPEC_UNUSED_CONST(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -27591,12 +27930,12 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE SAVE_OPLINE(); property = opline->op2.zv; - container = _get_obj_zval_ptr_unused(TSRMLS_C); + container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -27615,12 +27954,12 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCOD SAVE_OPLINE(); property = opline->op2.zv; - container = _get_obj_zval_ptr_unused(TSRMLS_C); + container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -27639,10 +27978,10 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCOD zval *offset; SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(TSRMLS_C); + container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); offset = opline->op2.zv; - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -27673,7 +28012,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CONST_HANDLER(ZEND SAVE_OPLINE(); property = opline->op2.zv; - container = _get_obj_zval_ptr_unused(TSRMLS_C); + container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) { zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); @@ -27681,7 +28020,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CONST_HANDLER(ZEND if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -27690,7 +28029,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CONST_HANDLER(ZEND CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { - return zend_fetch_property_address_read_helper_SPEC_UNUSED_CONST(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return ZEND_FETCH_OBJ_R_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } @@ -27701,13 +28040,13 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CONST_HANDLER(ZEND_OP zval *container, *property; SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(TSRMLS_C); + container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); property = opline->op2.zv; if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -27725,13 +28064,13 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_ zval *property_name; SAVE_OPLINE(); - object = _get_obj_zval_ptr_unused(TSRMLS_C); + object = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); property_name = opline->op2.zv; if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, IS_UNUSED, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); /* assign_obj has two opcodes! */ @@ -27800,21 +28139,57 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_O zend_error_noreturn(E_ERROR, "Method name must be a string"); } - object = _get_obj_zval_ptr_unused(TSRMLS_C); + object = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); + + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + uint32_t nesting = 1; - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); + + zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); + + + if (EG(exception) != NULL) { + HANDLE_EXCEPTION(); + } + + /* No exception raised: Skip over arguments until fcall opcode with correct + * nesting level. Return NULL (except when return value unused) */ + do { + opline++; + if (opline->opcode == ZEND_INIT_FCALL || + opline->opcode == ZEND_INIT_FCALL_BY_NAME || + opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME || + opline->opcode == ZEND_INIT_METHOD_CALL || + opline->opcode == ZEND_INIT_STATIC_METHOD_CALL || + opline->opcode == ZEND_INIT_USER_CALL || + opline->opcode == ZEND_NEW + ) { + nesting++; + } else if (opline->opcode == ZEND_DO_FCALL) { + nesting--; + } + } while (nesting); + + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + /* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */ + if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) { + opline++; + } + ZEND_VM_JMP(++opline); } obj = Z_OBJ_P(object); - called_scope = zend_get_class_entry(obj TSRMLS_CC); + called_scope = obj->ce; if (IS_CONST != IS_CONST || - (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) { + EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { zend_object *orig_obj = obj; if (UNEXPECTED(obj->handlers->get_method == NULL)) { @@ -27824,7 +28199,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_O /* First, locate the function. */ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name)); + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); } if (IS_CONST == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -27834,14 +28209,14 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_O } } - if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { obj = NULL; } else { GC_REFCOUNT(obj)++; /* For $this pointer */ } - EX(call) = zend_vm_stack_push_call_frame( - fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_FUNCTION, + fbc, opline->extended_value, called_scope, obj, EX(call) TSRMLS_CC); CHECK_EXCEPTION(); @@ -27862,14 +28237,16 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPC } else if ((c = zend_quick_get_constant(opline->op2.zv + 1, opline->extended_value TSRMLS_CC)) == NULL) { if ((opline->extended_value & IS_CONSTANT_UNQUALIFIED) != 0) { char *actual = (char *)zend_memrchr(Z_STRVAL_P(opline->op2.zv), '\\', Z_STRLEN_P(opline->op2.zv)); - if(!actual) { - actual = Z_STRVAL_P(opline->op2.zv); + if (!actual) { + ZVAL_STR(EX_VAR(opline->result.var), zend_string_copy(Z_STR_P(opline->op2.zv))); } else { actual++; + ZVAL_STRINGL(EX_VAR(opline->result.var), + actual, Z_STRLEN_P(opline->op2.zv) - (actual - Z_STRVAL_P(opline->op2.zv))); } /* non-qualified constant - allow text substitution */ - zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", actual, actual); - ZVAL_STRINGL(EX_VAR(opline->result.var), actual, Z_STRLEN_P(opline->op2.zv)-(actual - Z_STRVAL_P(opline->op2.zv))); + zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", + Z_STRVAL_P(EX_VAR(opline->result.var)), Z_STRVAL_P(EX_VAR(opline->result.var))); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { @@ -27901,7 +28278,7 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPC } else if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) { ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv)); } else { - ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, opline->extended_value TSRMLS_CC); + ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, 0 TSRMLS_CC); if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -27984,7 +28361,7 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_H zend_ulong hval; SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(TSRMLS_C); + container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); } @@ -27994,71 +28371,66 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_H } offset = opline->op2.zv; - switch (Z_TYPE_P(container)) { - case IS_ARRAY: { - HashTable *ht = Z_ARRVAL_P(container); + if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht = Z_ARRVAL_P(container); offset_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - zend_hash_index_del(ht, hval); - break; - case IS_LONG: - hval = Z_LVAL_P(offset); + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_LONG: + hval = Z_LVAL_P(offset); num_index_dim: - zend_hash_index_del(ht, hval); - break; - case IS_STRING: - if (IS_CONST != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { - goto num_index_dim; - } - } - if (ht == &EG(symbol_table).ht) { - zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); - } else { - zend_hash_del(ht, Z_STR_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_STRING: + if (IS_CONST != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { + goto num_index_dim; } - break; - case IS_NULL: - zend_hash_del(ht, STR_EMPTY_ALLOC()); - break; - case IS_FALSE: - hval = 0; - goto num_index_dim; - case IS_TRUE: - hval = 1; - goto num_index_dim; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_dim; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto offset_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type in unset"); - break; - } + } + if (ht == &EG(symbol_table).ht) { + zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); + } else { + zend_hash_del(ht, Z_STR_P(offset)); + } + break; + case IS_NULL: + zend_hash_del(ht, STR_EMPTY_ALLOC()); + break; + case IS_FALSE: + hval = 0; + goto num_index_dim; + case IS_TRUE: + hval = 1; + goto num_index_dim; + case IS_RESOURCE: + hval = Z_RES_HANDLE_P(offset); + goto num_index_dim; + case IS_REFERENCE: + offset = Z_REFVAL_P(offset); + goto offset_again; + break; + default: + zend_error(E_WARNING, "Illegal offset type in unset"); + break; + } - break; + } else if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use object as array"); } - case IS_OBJECT: - if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use object as array"); - } -//??? if (IS_CONST == IS_CONST) { -//??? zval_copy_ctor(offset); -//??? } - Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); +//??? if (IS_CONST == IS_CONST) { +//??? zval_copy_ctor(offset); +//??? } + Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); - break; - case IS_STRING: - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - ZEND_VM_CONTINUE(); /* bailed out before */ - default: + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + ZEND_VM_CONTINUE(); /* bailed out before */ + } else { - break; } CHECK_EXCEPTION(); @@ -28073,14 +28445,14 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_H zval *offset; SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(TSRMLS_C); + container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); } offset = opline->op2.zv; ZVAL_DEREF(container); - if (Z_TYPE_P(container) == IS_OBJECT) { + if (IS_UNUSED == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->unset_property) { Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { @@ -28103,10 +28475,10 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_UNUSED_CONST_HANDLER(Z zval *offset; SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(TSRMLS_C); + container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); offset = opline->op2.zv; - if (Z_TYPE_P(container) == IS_ARRAY) { + if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { HashTable *ht = Z_ARRVAL_P(container); zval *value; zend_string *str; @@ -28159,8 +28531,8 @@ num_index_prop: } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); } - } else if (Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->has_dimension) { + } else if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to check element of non-array"); @@ -28169,7 +28541,7 @@ num_index_prop: if ((opline->extended_value & ZEND_ISSET) == 0) { result = !result; } - } else if (Z_TYPE_P(container) == IS_STRING) { /* string offsets */ + } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */ zval tmp; result = 0; @@ -28185,7 +28557,7 @@ num_index_prop: offset = &tmp; } } - if (Z_TYPE_P(offset) == IS_LONG) { + if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) { if ((opline->extended_value & ZEND_ISSET) || Z_STRVAL_P(container)[offset->value.lval] != '0') { @@ -28215,11 +28587,11 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_CONST_HANDLER( zval *offset; SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(TSRMLS_C); + container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); offset = opline->op2.zv; - if (Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->has_property) { + if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_property)) { result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to check property of non-object"); @@ -28273,7 +28645,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDL /* Temporary variables don't need ctor copying */ if (IS_UNUSED != IS_TMP_VAR) { - zval_copy_ctor(&generator->value); + zval_opt_copy_ctor(&generator->value); } } else { zval *value_ptr = NULL; @@ -28284,9 +28656,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDL /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_UNUSED == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_UNUSED == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -28377,22 +28750,24 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(int (* { USE_OPLINE zend_free_op free_op2, free_op_data1; - zval *object = _get_obj_zval_ptr_unused(TSRMLS_C); + zval *object = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); zval *property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); zval *value; - int have_get_ptr = 0; + zval *zptr; if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - object = make_real_object(object TSRMLS_CC); + if (IS_UNUSED != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); + } - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to assign property of non-object"); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); FREE_OP(free_op_data1); if (RETURN_VALUE_USED(opline)) { @@ -28401,20 +28776,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(int (* } else { /* here we are sure we are dealing with an object */ if (opline->extended_value == ZEND_ASSIGN_OBJ - && Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - SEPARATE_ZVAL_IF_NOT_REF(zptr); + && EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - have_get_ptr = 1; - binary_op(zptr, zptr, value TSRMLS_CC); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), zptr); - } - } - } + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + binary_op(zptr, zptr, value TSRMLS_CC); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); + } + } else { zval *z = NULL; zval rv; @@ -28457,7 +28829,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(int (* } } - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); FREE_OP(free_op_data1); } @@ -28470,15 +28842,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(int (* static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMP(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2, free_op_data2, free_op_data1; - zval *var_ptr; + zend_free_op free_op2, free_op_data1; + zval *var_ptr, rv; zval *value, *container; SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(TSRMLS_C); + container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } + if (IS_UNUSED != IS_UNUSED) { + ZVAL_DEREF(container); + } + if (IS_UNUSED == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_UNUSED == IS_VAR && !0) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } @@ -28486,9 +28862,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMP(int (* } else { zval *dim = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - zend_fetch_dimension_address_RW(EX_VAR((opline+1)->op2.var), container, dim, IS_TMP_VAR TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + zend_fetch_dimension_address_RW(&rv, container, dim, IS_TMP_VAR TSRMLS_CC); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); } if (UNEXPECTED(var_ptr == NULL)) { @@ -28499,33 +28876,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMP(int (* if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_dim_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_dim_exit: - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); FREE_OP(free_op_data1); - FREE_OP_VAR_PTR(free_op_data2); CHECK_EXCEPTION(); ZEND_VM_INC_OPCODE(); @@ -28551,31 +28914,18 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_TMP(int (*bina if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_exit: - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -28731,10 +29081,10 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_TMP(incdec_ zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); - object = _get_obj_zval_ptr_unused(TSRMLS_C); + object = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); retval = EX_VAR(opline->result.var); @@ -28742,11 +29092,13 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_TMP(incdec_ zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_UNUSED != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); if (RETURN_VALUE_USED(opline)) { ZVAL_NULL(retval); } @@ -28757,20 +29109,17 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_TMP(incdec_ /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - SEPARATE_ZVAL_IF_NOT_REF(zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - have_get_ptr = 1; - incdec_op(zptr); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(retval, zptr); - } - } - } + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + incdec_op(zptr); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(retval, zptr); + } + } else { zval rv; if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { @@ -28800,7 +29149,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_TMP(incdec_ } } - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -28823,10 +29172,10 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_TMP(incdec zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); - object = _get_obj_zval_ptr_unused(TSRMLS_C); + object = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); retval = EX_VAR(opline->result.var); @@ -28834,11 +29183,13 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_TMP(incdec zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_UNUSED != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); ZVAL_NULL(retval); CHECK_EXCEPTION(); @@ -28847,20 +29198,15 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_TMP(incdec /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - have_get_ptr = 1; - SEPARATE_ZVAL_IF_NOT_REF(zptr); - - ZVAL_DUP(retval, zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - incdec_op(zptr); + ZVAL_DEREF(zptr); + ZVAL_COPY(retval, zptr); - } - } - - if (!have_get_ptr) { + SEPARATE_ZVAL_NOREF(zptr); + incdec_op(zptr); + } else { if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { zval rv; zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); @@ -28888,7 +29234,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_TMP(incdec } } - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -28904,7 +29250,7 @@ static int ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_ return zend_post_incdec_property_helper_SPEC_UNUSED_TMP(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } -static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_UNUSED_TMP(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -28913,10 +29259,10 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_UNUSED_TMP zval *offset; SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(TSRMLS_C); + container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { zend_error(E_NOTICE, "Trying to get property of non-object"); ZVAL_NULL(EX_VAR(opline->result.var)); @@ -28931,17 +29277,12 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_UNUSED_TMP } } - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_property_address_read_helper_SPEC_UNUSED_TMP(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -28952,13 +29293,13 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_H SAVE_OPLINE(); property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - container = _get_obj_zval_ptr_unused(TSRMLS_C); + container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); - zval_dtor(free_op2.var); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } @@ -28976,13 +29317,13 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_ SAVE_OPLINE(); property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - container = _get_obj_zval_ptr_unused(TSRMLS_C); + container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); - zval_dtor(free_op2.var); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } @@ -29000,10 +29341,10 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_ zval *offset; SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(TSRMLS_C); + container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -29017,7 +29358,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_ } } - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -29035,7 +29376,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_TMP_HANDLER(ZEND_O SAVE_OPLINE(); property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - container = _get_obj_zval_ptr_unused(TSRMLS_C); + container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) { zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); @@ -29043,8 +29384,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_TMP_HANDLER(ZEND_O if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); - zval_dtor(free_op2.var); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } @@ -29052,7 +29393,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_TMP_HANDLER(ZEND_O CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { - return zend_fetch_property_address_read_helper_SPEC_UNUSED_TMP(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } @@ -29063,14 +29404,14 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCO zval *container, *property; SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(TSRMLS_C); + container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); - zval_dtor(free_op2.var); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } @@ -29087,14 +29428,14 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HA zval *property_name; SAVE_OPLINE(); - object = _get_obj_zval_ptr_unused(TSRMLS_C); + object = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); property_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); - zval_dtor(free_op2.var); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, IS_UNUSED, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); /* assign_obj has two opcodes! */ CHECK_EXCEPTION(); @@ -29140,7 +29481,7 @@ static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDL * which aren't affected by FREE_OP(Ts, )'s anyway, unless they're * string offsets or overloaded objects */ - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -29168,21 +29509,57 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMP_HANDLER(ZEND_OPC zend_error_noreturn(E_ERROR, "Method name must be a string"); } - object = _get_obj_zval_ptr_unused(TSRMLS_C); + object = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); + + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + uint32_t nesting = 1; - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (UNEXPECTED(EG(exception) != NULL)) { - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); + HANDLE_EXCEPTION(); + } + + zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); + zval_ptr_dtor_nogc(free_op2.var); + + if (EG(exception) != NULL) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); + + /* No exception raised: Skip over arguments until fcall opcode with correct + * nesting level. Return NULL (except when return value unused) */ + do { + opline++; + if (opline->opcode == ZEND_INIT_FCALL || + opline->opcode == ZEND_INIT_FCALL_BY_NAME || + opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME || + opline->opcode == ZEND_INIT_METHOD_CALL || + opline->opcode == ZEND_INIT_STATIC_METHOD_CALL || + opline->opcode == ZEND_INIT_USER_CALL || + opline->opcode == ZEND_NEW + ) { + nesting++; + } else if (opline->opcode == ZEND_DO_FCALL) { + nesting--; + } + } while (nesting); + + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + /* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */ + if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) { + opline++; + } + ZEND_VM_JMP(++opline); } obj = Z_OBJ_P(object); - called_scope = zend_get_class_entry(obj TSRMLS_CC); + called_scope = obj->ce; if (IS_TMP_VAR != IS_CONST || - (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) { + EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { zend_object *orig_obj = obj; if (UNEXPECTED(obj->handlers->get_method == NULL)) { @@ -29192,7 +29569,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMP_HANDLER(ZEND_OPC /* First, locate the function. */ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_TMP_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name)); + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); } if (IS_TMP_VAR == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -29202,16 +29579,16 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMP_HANDLER(ZEND_OPC } } - if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { obj = NULL; } else { GC_REFCOUNT(obj)++; /* For $this pointer */ } - EX(call) = zend_vm_stack_push_call_frame( - fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_FUNCTION, + fbc, opline->extended_value, called_scope, obj, EX(call) TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -29257,7 +29634,7 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HAN zend_ulong hval; SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(TSRMLS_C); + container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); } @@ -29267,71 +29644,66 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HAN } offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - switch (Z_TYPE_P(container)) { - case IS_ARRAY: { - HashTable *ht = Z_ARRVAL_P(container); + if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht = Z_ARRVAL_P(container); offset_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - zend_hash_index_del(ht, hval); - break; - case IS_LONG: - hval = Z_LVAL_P(offset); + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_LONG: + hval = Z_LVAL_P(offset); num_index_dim: - zend_hash_index_del(ht, hval); - break; - case IS_STRING: - if (IS_TMP_VAR != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { - goto num_index_dim; - } - } - if (ht == &EG(symbol_table).ht) { - zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); - } else { - zend_hash_del(ht, Z_STR_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_STRING: + if (IS_TMP_VAR != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { + goto num_index_dim; } - break; - case IS_NULL: - zend_hash_del(ht, STR_EMPTY_ALLOC()); - break; - case IS_FALSE: - hval = 0; - goto num_index_dim; - case IS_TRUE: - hval = 1; - goto num_index_dim; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_dim; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto offset_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type in unset"); - break; - } - zval_dtor(free_op2.var); - break; + } + if (ht == &EG(symbol_table).ht) { + zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); + } else { + zend_hash_del(ht, Z_STR_P(offset)); + } + break; + case IS_NULL: + zend_hash_del(ht, STR_EMPTY_ALLOC()); + break; + case IS_FALSE: + hval = 0; + goto num_index_dim; + case IS_TRUE: + hval = 1; + goto num_index_dim; + case IS_RESOURCE: + hval = Z_RES_HANDLE_P(offset); + goto num_index_dim; + case IS_REFERENCE: + offset = Z_REFVAL_P(offset); + goto offset_again; + break; + default: + zend_error(E_WARNING, "Illegal offset type in unset"); + break; } - case IS_OBJECT: - if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use object as array"); - } -//??? if (IS_TMP_VAR == IS_CONST) { -//??? zval_copy_ctor(offset); -//??? } - Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); - zval_dtor(free_op2.var); - break; - case IS_STRING: - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - ZEND_VM_CONTINUE(); /* bailed out before */ - default: - zval_dtor(free_op2.var); - break; + zval_ptr_dtor_nogc(free_op2.var); + } else if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use object as array"); + } +//??? if (IS_TMP_VAR == IS_CONST) { +//??? zval_copy_ctor(offset); +//??? } + Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + ZEND_VM_CONTINUE(); /* bailed out before */ + } else { + zval_ptr_dtor_nogc(free_op2.var); } CHECK_EXCEPTION(); @@ -29346,21 +29718,21 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HAN zval *offset; SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(TSRMLS_C); + container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); } offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); ZVAL_DEREF(container); - if (Z_TYPE_P(container) == IS_OBJECT) { + if (IS_UNUSED == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->unset_property) { Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to unset property of non-object"); } } - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -29376,10 +29748,10 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_UNUSED_TMP_HANDLER(ZEN zval *offset; SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(TSRMLS_C); + container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (Z_TYPE_P(container) == IS_ARRAY) { + if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { HashTable *ht = Z_ARRVAL_P(container); zval *value; zend_string *str; @@ -29432,8 +29804,8 @@ num_index_prop: } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); } - } else if (Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->has_dimension) { + } else if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to check element of non-array"); @@ -29442,7 +29814,7 @@ num_index_prop: if ((opline->extended_value & ZEND_ISSET) == 0) { result = !result; } - } else if (Z_TYPE_P(container) == IS_STRING) { /* string offsets */ + } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */ zval tmp; result = 0; @@ -29458,7 +29830,7 @@ num_index_prop: offset = &tmp; } } - if (Z_TYPE_P(offset) == IS_LONG) { + if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) { if ((opline->extended_value & ZEND_ISSET) || Z_STRVAL_P(container)[offset->value.lval] != '0') { @@ -29473,7 +29845,7 @@ num_index_prop: result = ((opline->extended_value & ZEND_ISSET) == 0); } - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); ZVAL_BOOL(EX_VAR(opline->result.var), result); CHECK_EXCEPTION(); @@ -29489,11 +29861,11 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_TMP_HANDLER(ZE zval *offset; SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(TSRMLS_C); + container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->has_property) { + if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_property)) { result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to check property of non-object"); @@ -29506,7 +29878,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_TMP_HANDLER(ZE result = ((opline->extended_value & ZEND_ISSET) == 0); } - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); ZVAL_BOOL(EX_VAR(opline->result.var), result); CHECK_EXCEPTION(); @@ -29548,7 +29920,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER /* Temporary variables don't need ctor copying */ if (IS_UNUSED != IS_TMP_VAR) { - zval_copy_ctor(&generator->value); + zval_opt_copy_ctor(&generator->value); } } else { zval *value_ptr = NULL; @@ -29559,9 +29931,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_UNUSED == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_UNUSED == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -29652,20 +30025,22 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(int (* { USE_OPLINE zend_free_op free_op2, free_op_data1; - zval *object = _get_obj_zval_ptr_unused(TSRMLS_C); + zval *object = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); zval *property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); zval *value; - int have_get_ptr = 0; + zval *zptr; if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - object = make_real_object(object TSRMLS_CC); + if (IS_UNUSED != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); + } - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to assign property of non-object"); zval_ptr_dtor_nogc(free_op2.var); FREE_OP(free_op_data1); @@ -29676,20 +30051,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(int (* } else { /* here we are sure we are dealing with an object */ if (opline->extended_value == ZEND_ASSIGN_OBJ - && Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - SEPARATE_ZVAL_IF_NOT_REF(zptr); + && EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - have_get_ptr = 1; - binary_op(zptr, zptr, value TSRMLS_CC); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), zptr); - } - } - } + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + binary_op(zptr, zptr, value TSRMLS_CC); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); + } + } else { zval *z = NULL; zval rv; @@ -29745,15 +30117,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(int (* static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_VAR(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2, free_op_data2, free_op_data1; - zval *var_ptr; + zend_free_op free_op2, free_op_data1; + zval *var_ptr, rv; zval *value, *container; SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(TSRMLS_C); + container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } + if (IS_UNUSED != IS_UNUSED) { + ZVAL_DEREF(container); + } + if (IS_UNUSED == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_UNUSED == IS_VAR && !0) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } @@ -29761,9 +30137,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_VAR(int (* } else { zval *dim = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - zend_fetch_dimension_address_RW(EX_VAR((opline+1)->op2.var), container, dim, IS_VAR TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + zend_fetch_dimension_address_RW(&rv, container, dim, IS_VAR TSRMLS_CC); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); } if (UNEXPECTED(var_ptr == NULL)) { @@ -29774,33 +30151,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_VAR(int (* if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_dim_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_dim_exit: zval_ptr_dtor_nogc(free_op2.var); FREE_OP(free_op_data1); - FREE_OP_VAR_PTR(free_op_data2); CHECK_EXCEPTION(); ZEND_VM_INC_OPCODE(); @@ -29815,7 +30178,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_VAR(int (*bina zval *value; SAVE_OPLINE(); - value = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + value = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); var_ptr = NULL; if (IS_UNUSED == IS_VAR && UNEXPECTED(var_ptr == NULL)) { @@ -29826,30 +30189,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_VAR(int (*bina if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_exit: zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); @@ -30006,10 +30356,10 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_VAR(incdec_ zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); - object = _get_obj_zval_ptr_unused(TSRMLS_C); + object = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); retval = EX_VAR(opline->result.var); @@ -30017,9 +30367,11 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_VAR(incdec_ zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_UNUSED != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); zval_ptr_dtor_nogc(free_op2.var); if (RETURN_VALUE_USED(opline)) { @@ -30032,20 +30384,17 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_VAR(incdec_ /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - SEPARATE_ZVAL_IF_NOT_REF(zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - have_get_ptr = 1; - incdec_op(zptr); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(retval, zptr); - } - } - } + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + incdec_op(zptr); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(retval, zptr); + } + } else { zval rv; if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { @@ -30098,10 +30447,10 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_VAR(incdec zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); - object = _get_obj_zval_ptr_unused(TSRMLS_C); + object = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); retval = EX_VAR(opline->result.var); @@ -30109,9 +30458,11 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_VAR(incdec zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_UNUSED != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); zval_ptr_dtor_nogc(free_op2.var); ZVAL_NULL(retval); @@ -30122,20 +30473,15 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_VAR(incdec /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - have_get_ptr = 1; - SEPARATE_ZVAL_IF_NOT_REF(zptr); - - ZVAL_DUP(retval, zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - incdec_op(zptr); + ZVAL_DEREF(zptr); + ZVAL_COPY(retval, zptr); - } - } - - if (!have_get_ptr) { + SEPARATE_ZVAL_NOREF(zptr); + incdec_op(zptr); + } else { if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { zval rv; zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); @@ -30179,7 +30525,7 @@ static int ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_ return zend_post_incdec_property_helper_SPEC_UNUSED_VAR(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } -static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_UNUSED_VAR(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -30188,10 +30534,10 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_UNUSED_VAR zval *offset; SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(TSRMLS_C); + container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { zend_error(E_NOTICE, "Trying to get property of non-object"); ZVAL_NULL(EX_VAR(opline->result.var)); @@ -30212,11 +30558,6 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_UNUSED_VAR ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_property_address_read_helper_SPEC_UNUSED_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -30227,12 +30568,12 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_H SAVE_OPLINE(); property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - container = _get_obj_zval_ptr_unused(TSRMLS_C); + container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -30251,12 +30592,12 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_ SAVE_OPLINE(); property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - container = _get_obj_zval_ptr_unused(TSRMLS_C); + container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -30275,10 +30616,10 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_ zval *offset; SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(TSRMLS_C); + container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -30310,7 +30651,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_VAR_HANDLER(ZEND_O SAVE_OPLINE(); property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - container = _get_obj_zval_ptr_unused(TSRMLS_C); + container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) { zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); @@ -30318,7 +30659,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_VAR_HANDLER(ZEND_O if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -30327,7 +30668,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_VAR_HANDLER(ZEND_O CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { - return zend_fetch_property_address_read_helper_SPEC_UNUSED_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return ZEND_FETCH_OBJ_R_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } @@ -30338,13 +30679,13 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCO zval *container, *property; SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(TSRMLS_C); + container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -30362,13 +30703,13 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HA zval *property_name; SAVE_OPLINE(); - object = _get_obj_zval_ptr_unused(TSRMLS_C); + object = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, IS_UNUSED, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); /* assign_obj has two opcodes! */ @@ -30443,21 +30784,57 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_VAR_HANDLER(ZEND_OPC zend_error_noreturn(E_ERROR, "Method name must be a string"); } - object = _get_obj_zval_ptr_unused(TSRMLS_C); + object = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); + + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + uint32_t nesting = 1; - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (UNEXPECTED(EG(exception) != NULL)) { zval_ptr_dtor_nogc(free_op2.var); HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); + + zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); + zval_ptr_dtor_nogc(free_op2.var); + + if (EG(exception) != NULL) { + HANDLE_EXCEPTION(); + } + + /* No exception raised: Skip over arguments until fcall opcode with correct + * nesting level. Return NULL (except when return value unused) */ + do { + opline++; + if (opline->opcode == ZEND_INIT_FCALL || + opline->opcode == ZEND_INIT_FCALL_BY_NAME || + opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME || + opline->opcode == ZEND_INIT_METHOD_CALL || + opline->opcode == ZEND_INIT_STATIC_METHOD_CALL || + opline->opcode == ZEND_INIT_USER_CALL || + opline->opcode == ZEND_NEW + ) { + nesting++; + } else if (opline->opcode == ZEND_DO_FCALL) { + nesting--; + } + } while (nesting); + + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + /* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */ + if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) { + opline++; + } + ZEND_VM_JMP(++opline); } obj = Z_OBJ_P(object); - called_scope = zend_get_class_entry(obj TSRMLS_CC); + called_scope = obj->ce; if (IS_VAR != IS_CONST || - (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) { + EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { zend_object *orig_obj = obj; if (UNEXPECTED(obj->handlers->get_method == NULL)) { @@ -30467,7 +30844,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_VAR_HANDLER(ZEND_OPC /* First, locate the function. */ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name)); + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); } if (IS_VAR == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -30477,14 +30854,14 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_VAR_HANDLER(ZEND_OPC } } - if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { obj = NULL; } else { GC_REFCOUNT(obj)++; /* For $this pointer */ } - EX(call) = zend_vm_stack_push_call_frame( - fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_FUNCTION, + fbc, opline->extended_value, called_scope, obj, EX(call) TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); @@ -30532,7 +30909,7 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HAN zend_ulong hval; SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(TSRMLS_C); + container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); } @@ -30542,71 +30919,66 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HAN } offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - switch (Z_TYPE_P(container)) { - case IS_ARRAY: { - HashTable *ht = Z_ARRVAL_P(container); + if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht = Z_ARRVAL_P(container); offset_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - zend_hash_index_del(ht, hval); - break; - case IS_LONG: - hval = Z_LVAL_P(offset); + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_LONG: + hval = Z_LVAL_P(offset); num_index_dim: - zend_hash_index_del(ht, hval); - break; - case IS_STRING: - if (IS_VAR != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { - goto num_index_dim; - } - } - if (ht == &EG(symbol_table).ht) { - zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); - } else { - zend_hash_del(ht, Z_STR_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_STRING: + if (IS_VAR != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { + goto num_index_dim; } - break; - case IS_NULL: - zend_hash_del(ht, STR_EMPTY_ALLOC()); - break; - case IS_FALSE: - hval = 0; - goto num_index_dim; - case IS_TRUE: - hval = 1; - goto num_index_dim; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_dim; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto offset_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type in unset"); - break; - } - zval_ptr_dtor_nogc(free_op2.var); - break; + } + if (ht == &EG(symbol_table).ht) { + zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); + } else { + zend_hash_del(ht, Z_STR_P(offset)); + } + break; + case IS_NULL: + zend_hash_del(ht, STR_EMPTY_ALLOC()); + break; + case IS_FALSE: + hval = 0; + goto num_index_dim; + case IS_TRUE: + hval = 1; + goto num_index_dim; + case IS_RESOURCE: + hval = Z_RES_HANDLE_P(offset); + goto num_index_dim; + case IS_REFERENCE: + offset = Z_REFVAL_P(offset); + goto offset_again; + break; + default: + zend_error(E_WARNING, "Illegal offset type in unset"); + break; } - case IS_OBJECT: - if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use object as array"); - } -//??? if (IS_VAR == IS_CONST) { -//??? zval_copy_ctor(offset); -//??? } - Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2.var); - break; - case IS_STRING: - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - ZEND_VM_CONTINUE(); /* bailed out before */ - default: - zval_ptr_dtor_nogc(free_op2.var); - break; + zval_ptr_dtor_nogc(free_op2.var); + } else if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use object as array"); + } +//??? if (IS_VAR == IS_CONST) { +//??? zval_copy_ctor(offset); +//??? } + Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + ZEND_VM_CONTINUE(); /* bailed out before */ + } else { + zval_ptr_dtor_nogc(free_op2.var); } CHECK_EXCEPTION(); @@ -30621,14 +30993,14 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HAN zval *offset; SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(TSRMLS_C); + container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); } offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); ZVAL_DEREF(container); - if (Z_TYPE_P(container) == IS_OBJECT) { + if (IS_UNUSED == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->unset_property) { Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { @@ -30651,10 +31023,10 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_UNUSED_VAR_HANDLER(ZEN zval *offset; SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(TSRMLS_C); + container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (Z_TYPE_P(container) == IS_ARRAY) { + if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { HashTable *ht = Z_ARRVAL_P(container); zval *value; zend_string *str; @@ -30707,8 +31079,8 @@ num_index_prop: } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); } - } else if (Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->has_dimension) { + } else if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to check element of non-array"); @@ -30717,7 +31089,7 @@ num_index_prop: if ((opline->extended_value & ZEND_ISSET) == 0) { result = !result; } - } else if (Z_TYPE_P(container) == IS_STRING) { /* string offsets */ + } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */ zval tmp; result = 0; @@ -30733,7 +31105,7 @@ num_index_prop: offset = &tmp; } } - if (Z_TYPE_P(offset) == IS_LONG) { + if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) { if ((opline->extended_value & ZEND_ISSET) || Z_STRVAL_P(container)[offset->value.lval] != '0') { @@ -30764,11 +31136,11 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_VAR_HANDLER(ZE zval *offset; SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(TSRMLS_C); + container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->has_property) { + if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_property)) { result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to check property of non-object"); @@ -30823,7 +31195,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER /* Temporary variables don't need ctor copying */ if (IS_UNUSED != IS_TMP_VAR) { - zval_copy_ctor(&generator->value); + zval_opt_copy_ctor(&generator->value); } } else { zval *value_ptr = NULL; @@ -30834,9 +31206,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_UNUSED == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_UNUSED == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -30927,20 +31300,22 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(int { USE_OPLINE zend_free_op free_op_data1; - zval *object = _get_obj_zval_ptr_unused(TSRMLS_C); + zval *object = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); zval *property = NULL; zval *value; - int have_get_ptr = 0; + zval *zptr; if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - object = make_real_object(object TSRMLS_CC); + if (IS_UNUSED != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); + } - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to assign property of non-object"); FREE_OP(free_op_data1); @@ -30951,20 +31326,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(int } else { /* here we are sure we are dealing with an object */ if (opline->extended_value == ZEND_ASSIGN_OBJ - && Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_UNUSED == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - SEPARATE_ZVAL_IF_NOT_REF(zptr); + && EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_UNUSED == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - have_get_ptr = 1; - binary_op(zptr, zptr, value TSRMLS_CC); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), zptr); - } - } - } + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + binary_op(zptr, zptr, value TSRMLS_CC); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); + } + } else { zval *z = NULL; zval rv; @@ -31019,15 +31391,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(int static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_UNUSED(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data2, free_op_data1; - zval *var_ptr; + zend_free_op free_op_data1; + zval *var_ptr, rv; zval *value, *container; SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(TSRMLS_C); + container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } + if (IS_UNUSED != IS_UNUSED) { + ZVAL_DEREF(container); + } + if (IS_UNUSED == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_UNUSED == IS_VAR && !0) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } @@ -31035,9 +31411,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_UNUSED(int } else { zval *dim = NULL; - zend_fetch_dimension_address_RW(EX_VAR((opline+1)->op2.var), container, dim, IS_UNUSED TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + zend_fetch_dimension_address_RW(&rv, container, dim, IS_UNUSED TSRMLS_CC); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); } if (UNEXPECTED(var_ptr == NULL)) { @@ -31048,33 +31425,18 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_UNUSED(int if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_dim_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_dim_exit: - FREE_OP(free_op_data1); - FREE_OP_VAR_PTR(free_op_data2); CHECK_EXCEPTION(); ZEND_VM_INC_OPCODE(); @@ -31100,31 +31462,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_UNUSED(int (*b if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_exit: - CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -31339,7 +31687,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HAND /* Temporary variables don't need ctor copying */ if (IS_UNUSED != IS_TMP_VAR) { - zval_copy_ctor(&generator->value); + zval_opt_copy_ctor(&generator->value); } } else { zval *value_ptr = NULL; @@ -31350,9 +31698,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HAND /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_UNUSED == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_UNUSED == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -31443,20 +31792,22 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(int (*b { USE_OPLINE zend_free_op free_op_data1; - zval *object = _get_obj_zval_ptr_unused(TSRMLS_C); + zval *object = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); zval *property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); zval *value; - int have_get_ptr = 0; + zval *zptr; if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - object = make_real_object(object TSRMLS_CC); + if (IS_UNUSED != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); + } - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to assign property of non-object"); FREE_OP(free_op_data1); @@ -31467,20 +31818,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(int (*b } else { /* here we are sure we are dealing with an object */ if (opline->extended_value == ZEND_ASSIGN_OBJ - && Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - SEPARATE_ZVAL_IF_NOT_REF(zptr); + && EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - have_get_ptr = 1; - binary_op(zptr, zptr, value TSRMLS_CC); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), zptr); - } - } - } + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + binary_op(zptr, zptr, value TSRMLS_CC); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); + } + } else { zval *z = NULL; zval rv; @@ -31535,15 +31883,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(int (*b static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_CV(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data2, free_op_data1; - zval *var_ptr; + zend_free_op free_op_data1; + zval *var_ptr, rv; zval *value, *container; SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(TSRMLS_C); + container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } + if (IS_UNUSED != IS_UNUSED) { + ZVAL_DEREF(container); + } + if (IS_UNUSED == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_UNUSED == IS_VAR && !0) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } @@ -31551,9 +31903,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_CV(int (*b } else { zval *dim = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - zend_fetch_dimension_address_RW(EX_VAR((opline+1)->op2.var), container, dim, IS_CV TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + zend_fetch_dimension_address_RW(&rv, container, dim, IS_CV TSRMLS_CC); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); } if (UNEXPECTED(var_ptr == NULL)) { @@ -31564,33 +31917,18 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_CV(int (*b if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_dim_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_dim_exit: - FREE_OP(free_op_data1); - FREE_OP_VAR_PTR(free_op_data2); CHECK_EXCEPTION(); ZEND_VM_INC_OPCODE(); @@ -31605,7 +31943,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_CV(int (*binar zval *value; SAVE_OPLINE(); - value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + value = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); var_ptr = NULL; if (IS_UNUSED == IS_VAR && UNEXPECTED(var_ptr == NULL)) { @@ -31616,31 +31954,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_CV(int (*binar if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_exit: - CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -31796,10 +32120,10 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CV(incdec_t zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); - object = _get_obj_zval_ptr_unused(TSRMLS_C); + object = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); retval = EX_VAR(opline->result.var); @@ -31807,9 +32131,11 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CV(incdec_t zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_UNUSED != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); if (RETURN_VALUE_USED(opline)) { @@ -31822,20 +32148,17 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CV(incdec_t /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - SEPARATE_ZVAL_IF_NOT_REF(zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - have_get_ptr = 1; - incdec_op(zptr); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(retval, zptr); - } - } - } + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + incdec_op(zptr); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(retval, zptr); + } + } else { zval rv; if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { @@ -31887,10 +32210,10 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CV(incdec_ zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); - object = _get_obj_zval_ptr_unused(TSRMLS_C); + object = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); retval = EX_VAR(opline->result.var); @@ -31898,9 +32221,11 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CV(incdec_ zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_UNUSED != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); ZVAL_NULL(retval); @@ -31911,20 +32236,15 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CV(incdec_ /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - have_get_ptr = 1; - SEPARATE_ZVAL_IF_NOT_REF(zptr); - - ZVAL_DUP(retval, zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - incdec_op(zptr); - - } - } + ZVAL_DEREF(zptr); + ZVAL_COPY(retval, zptr); - if (!have_get_ptr) { + SEPARATE_ZVAL_NOREF(zptr); + incdec_op(zptr); + } else { if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { zval rv; zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); @@ -31967,7 +32287,7 @@ static int ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_H return zend_post_incdec_property_helper_SPEC_UNUSED_CV(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } -static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_UNUSED_CV(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -31976,10 +32296,10 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_UNUSED_CV( zval *offset; SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(TSRMLS_C); + container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { zend_error(E_NOTICE, "Trying to get property of non-object"); ZVAL_NULL(EX_VAR(opline->result.var)); @@ -31999,11 +32319,6 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_UNUSED_CV( ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_property_address_read_helper_SPEC_UNUSED_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -32014,12 +32329,12 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HA SAVE_OPLINE(); property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - container = _get_obj_zval_ptr_unused(TSRMLS_C); + container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -32038,12 +32353,12 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_H SAVE_OPLINE(); property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - container = _get_obj_zval_ptr_unused(TSRMLS_C); + container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -32062,10 +32377,10 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_H zval *offset; SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(TSRMLS_C); + container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -32096,7 +32411,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CV_HANDLER(ZEND_OP SAVE_OPLINE(); property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - container = _get_obj_zval_ptr_unused(TSRMLS_C); + container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) { zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); @@ -32104,7 +32419,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CV_HANDLER(ZEND_OP if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -32113,7 +32428,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CV_HANDLER(ZEND_OP CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { - return zend_fetch_property_address_read_helper_SPEC_UNUSED_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return ZEND_FETCH_OBJ_R_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } @@ -32124,13 +32439,13 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CV_HANDLER(ZEND_OPCOD zval *container, *property; SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(TSRMLS_C); + container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -32148,13 +32463,13 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HAN zval *property_name; SAVE_OPLINE(); - object = _get_obj_zval_ptr_unused(TSRMLS_C); + object = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, IS_UNUSED, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); /* assign_obj has two opcodes! */ @@ -32228,21 +32543,57 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CV_HANDLER(ZEND_OPCO zend_error_noreturn(E_ERROR, "Method name must be a string"); } - object = _get_obj_zval_ptr_unused(TSRMLS_C); + object = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); + + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + uint32_t nesting = 1; - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); + + zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); + + + if (EG(exception) != NULL) { + HANDLE_EXCEPTION(); + } + + /* No exception raised: Skip over arguments until fcall opcode with correct + * nesting level. Return NULL (except when return value unused) */ + do { + opline++; + if (opline->opcode == ZEND_INIT_FCALL || + opline->opcode == ZEND_INIT_FCALL_BY_NAME || + opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME || + opline->opcode == ZEND_INIT_METHOD_CALL || + opline->opcode == ZEND_INIT_STATIC_METHOD_CALL || + opline->opcode == ZEND_INIT_USER_CALL || + opline->opcode == ZEND_NEW + ) { + nesting++; + } else if (opline->opcode == ZEND_DO_FCALL) { + nesting--; + } + } while (nesting); + + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + /* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */ + if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) { + opline++; + } + ZEND_VM_JMP(++opline); } obj = Z_OBJ_P(object); - called_scope = zend_get_class_entry(obj TSRMLS_CC); + called_scope = obj->ce; if (IS_CV != IS_CONST || - (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) { + EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { zend_object *orig_obj = obj; if (UNEXPECTED(obj->handlers->get_method == NULL)) { @@ -32252,7 +32603,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CV_HANDLER(ZEND_OPCO /* First, locate the function. */ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name)); + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); } if (IS_CV == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -32262,14 +32613,14 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CV_HANDLER(ZEND_OPCO } } - if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { obj = NULL; } else { GC_REFCOUNT(obj)++; /* For $this pointer */ } - EX(call) = zend_vm_stack_push_call_frame( - fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_FUNCTION, + fbc, opline->extended_value, called_scope, obj, EX(call) TSRMLS_CC); CHECK_EXCEPTION(); @@ -32316,7 +32667,7 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HAND zend_ulong hval; SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(TSRMLS_C); + container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); } @@ -32326,71 +32677,66 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HAND } offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - switch (Z_TYPE_P(container)) { - case IS_ARRAY: { - HashTable *ht = Z_ARRVAL_P(container); + if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht = Z_ARRVAL_P(container); offset_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - zend_hash_index_del(ht, hval); - break; - case IS_LONG: - hval = Z_LVAL_P(offset); + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_LONG: + hval = Z_LVAL_P(offset); num_index_dim: - zend_hash_index_del(ht, hval); - break; - case IS_STRING: - if (IS_CV != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { - goto num_index_dim; - } - } - if (ht == &EG(symbol_table).ht) { - zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); - } else { - zend_hash_del(ht, Z_STR_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_STRING: + if (IS_CV != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { + goto num_index_dim; } - break; - case IS_NULL: - zend_hash_del(ht, STR_EMPTY_ALLOC()); - break; - case IS_FALSE: - hval = 0; - goto num_index_dim; - case IS_TRUE: - hval = 1; - goto num_index_dim; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_dim; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto offset_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type in unset"); - break; - } + } + if (ht == &EG(symbol_table).ht) { + zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); + } else { + zend_hash_del(ht, Z_STR_P(offset)); + } + break; + case IS_NULL: + zend_hash_del(ht, STR_EMPTY_ALLOC()); + break; + case IS_FALSE: + hval = 0; + goto num_index_dim; + case IS_TRUE: + hval = 1; + goto num_index_dim; + case IS_RESOURCE: + hval = Z_RES_HANDLE_P(offset); + goto num_index_dim; + case IS_REFERENCE: + offset = Z_REFVAL_P(offset); + goto offset_again; + break; + default: + zend_error(E_WARNING, "Illegal offset type in unset"); + break; + } - break; + } else if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use object as array"); } - case IS_OBJECT: - if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use object as array"); - } -//??? if (IS_CV == IS_CONST) { -//??? zval_copy_ctor(offset); -//??? } - Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); +//??? if (IS_CV == IS_CONST) { +//??? zval_copy_ctor(offset); +//??? } + Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); - break; - case IS_STRING: - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - ZEND_VM_CONTINUE(); /* bailed out before */ - default: + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + ZEND_VM_CONTINUE(); /* bailed out before */ + } else { - break; } CHECK_EXCEPTION(); @@ -32405,14 +32751,14 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HAND zval *offset; SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(TSRMLS_C); + container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); } offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); ZVAL_DEREF(container); - if (Z_TYPE_P(container) == IS_OBJECT) { + if (IS_UNUSED == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->unset_property) { Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { @@ -32435,10 +32781,10 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND zval *offset; SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(TSRMLS_C); + container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (Z_TYPE_P(container) == IS_ARRAY) { + if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { HashTable *ht = Z_ARRVAL_P(container); zval *value; zend_string *str; @@ -32491,8 +32837,8 @@ num_index_prop: } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); } - } else if (Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->has_dimension) { + } else if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to check element of non-array"); @@ -32501,7 +32847,7 @@ num_index_prop: if ((opline->extended_value & ZEND_ISSET) == 0) { result = !result; } - } else if (Z_TYPE_P(container) == IS_STRING) { /* string offsets */ + } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */ zval tmp; result = 0; @@ -32517,7 +32863,7 @@ num_index_prop: offset = &tmp; } } - if (Z_TYPE_P(offset) == IS_LONG) { + if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) { if ((opline->extended_value & ZEND_ISSET) || Z_STRVAL_P(container)[offset->value.lval] != '0') { @@ -32547,11 +32893,11 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_CV_HANDLER(ZEN zval *offset; SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(TSRMLS_C); + container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->has_property) { + if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_property)) { result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to check property of non-object"); @@ -32605,7 +32951,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ /* Temporary variables don't need ctor copying */ if (IS_UNUSED != IS_TMP_VAR) { - zval_copy_ctor(&generator->value); + zval_opt_copy_ctor(&generator->value); } } else { zval *value_ptr = NULL; @@ -32616,9 +32962,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_UNUSED == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_UNUSED == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -32756,7 +33103,6 @@ static int ZEND_FASTCALL ZEND_PRE_INC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) if (RETURN_VALUE_USED(opline)) { ZVAL_NULL(EX_VAR(opline->result.var)); } - CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -32764,19 +33110,7 @@ static int ZEND_FASTCALL ZEND_PRE_INC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) ZVAL_DEREF(var_ptr); SEPARATE_ZVAL_NOREF(var_ptr); - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) - && Z_OBJ_HANDLER_P(var_ptr, get) - && Z_OBJ_HANDLER_P(var_ptr, set)) { - /* proxy object */ - zval rv; - zval *val = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(val); - fast_increment_function(val); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, val TSRMLS_CC); - zval_ptr_dtor(val); - } else { - increment_function(var_ptr); - } + increment_function(var_ptr); if (RETURN_VALUE_USED(opline)) { ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); @@ -32811,7 +33145,6 @@ static int ZEND_FASTCALL ZEND_PRE_DEC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) if (RETURN_VALUE_USED(opline)) { ZVAL_NULL(EX_VAR(opline->result.var)); } - CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -32819,19 +33152,7 @@ static int ZEND_FASTCALL ZEND_PRE_DEC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) ZVAL_DEREF(var_ptr); SEPARATE_ZVAL_NOREF(var_ptr); - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) - && Z_OBJ_HANDLER_P(var_ptr, get) - && Z_OBJ_HANDLER_P(var_ptr, set)) { - /* proxy object */ - zval rv; - zval *val = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(val); - fast_decrement_function(val); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, val TSRMLS_CC); - zval_ptr_dtor(val); - } else { - decrement_function(var_ptr); - } + decrement_function(var_ptr); if (RETURN_VALUE_USED(opline)) { ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); @@ -32845,7 +33166,7 @@ static int ZEND_FASTCALL ZEND_POST_INC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS { USE_OPLINE - zval *var_ptr, *retval; + zval *var_ptr; SAVE_OPLINE(); var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); @@ -32862,34 +33183,19 @@ static int ZEND_FASTCALL ZEND_POST_INC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { ZVAL_NULL(EX_VAR(opline->result.var)); - CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } - retval = EX_VAR(opline->result.var); - if (UNEXPECTED(Z_ISREF_P(var_ptr))) { var_ptr = Z_REFVAL_P(var_ptr); - ZVAL_DUP(retval, var_ptr); + ZVAL_DUP(EX_VAR(opline->result.var), var_ptr); } else { - ZVAL_DUP(retval, var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); + zval_opt_copy_ctor(var_ptr); } - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) - && Z_OBJ_HANDLER_P(var_ptr, get) - && Z_OBJ_HANDLER_P(var_ptr, set)) { - /* proxy object */ - zval rv; - zval *val = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(val); - fast_increment_function(val); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, val TSRMLS_CC); - zval_ptr_dtor(val); - } else { - increment_function(var_ptr); - } + increment_function(var_ptr); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -32899,7 +33205,7 @@ static int ZEND_FASTCALL ZEND_POST_DEC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS { USE_OPLINE - zval *var_ptr, *retval; + zval *var_ptr; SAVE_OPLINE(); var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); @@ -32916,34 +33222,19 @@ static int ZEND_FASTCALL ZEND_POST_DEC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { ZVAL_NULL(EX_VAR(opline->result.var)); - CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } - retval = EX_VAR(opline->result.var); - if (UNEXPECTED(Z_ISREF_P(var_ptr))) { var_ptr = Z_REFVAL_P(var_ptr); - ZVAL_DUP(retval, var_ptr); + ZVAL_DUP(EX_VAR(opline->result.var), var_ptr); } else { - ZVAL_DUP(retval, var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); + zval_opt_copy_ctor(var_ptr); } - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) - && Z_OBJ_HANDLER_P(var_ptr, get) - && Z_OBJ_HANDLER_P(var_ptr, set)) { - /* proxy object */ - zval rv; - zval *val = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(val); - fast_decrement_function(val); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, val TSRMLS_CC); - zval_ptr_dtor(val); - } else { - decrement_function(var_ptr); - } + decrement_function(var_ptr); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -33087,13 +33378,14 @@ static int ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } if (i_zend_is_true(val TSRMLS_CC)) { + ZVAL_TRUE(EX_VAR(opline->result.var)); opline++; } else { + ZVAL_FALSE(EX_VAR(opline->result.var)); opline = opline->op2.jmp_addr; } - if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -33187,6 +33479,7 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER } } else { ZVAL_COPY_VALUE(EX(return_value), retval_ptr); + Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; if (IS_CV != IS_TMP_VAR) { zval_opt_copy_ctor_no_imm(EX(return_value)); } @@ -33200,13 +33493,14 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER zend_error_noreturn(E_ERROR, "Cannot return string offsets by reference"); } - if (IS_CV == IS_VAR && !Z_ISREF_P(retval_ptr)) { - if (opline->extended_value == ZEND_RETURNS_FUNCTION && - (Z_VAR_FLAGS_P(retval_ptr) & IS_VAR_RET_REF)) { - } else { + if (IS_CV == IS_VAR) { + if (retval_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(retval_ptr) & IS_VAR_RET_REF))) { zend_error(E_NOTICE, "Only variable references should be returned by reference"); if (EX(return_value)) { ZVAL_NEW_REF(EX(return_value), retval_ptr); + Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; if (Z_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr); } break; @@ -33217,6 +33511,7 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER ZVAL_MAKE_REF(retval_ptr); Z_ADDREF_P(retval_ptr); ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr)); + Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; } } while (0); @@ -33414,12 +33709,12 @@ static int ZEND_FASTCALL ZEND_SEND_USER_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG if (EX(call)->func->common.fn_flags & ZEND_ACC_CLOSURE) { OBJ_RELEASE((zend_object*)EX(call)->func->common.prototype); } - if (EX(call)->object) { - OBJ_RELEASE(EX(call)->object); + if (Z_OBJ(EX(call)->This)) { + OBJ_RELEASE(Z_OBJ(EX(call)->This)); } EX(call)->func = (zend_function*)&zend_pass_function; EX(call)->called_scope = NULL; - EX(call)->object = NULL; + Z_OBJ(EX(call)->This) = NULL; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -33479,7 +33774,7 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) obj = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_CONST || - UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT)) { + (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT))) { if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -33590,15 +33885,13 @@ static int ZEND_FASTCALL ZEND_CAST_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) if (UNEXPECTED(Z_OPT_COPYABLE_P(expr))) { zval_copy_ctor_func(expr); } - } else if (IS_CV != IS_TMP_VAR) { + } else { if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); } } } else { ZVAL_COPY_VALUE(result, expr); - if (IS_CV != IS_TMP_VAR) { - zval_opt_copy_ctor(result); - } + Z_ADDREF_P(result); convert_to_array(result); } } else { @@ -33610,21 +33903,16 @@ static int ZEND_FASTCALL ZEND_CAST_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) if (UNEXPECTED(Z_OPT_COPYABLE_P(expr))) { zval_copy_ctor_func(expr); } - } else if (IS_CV != IS_TMP_VAR) { + } else { if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr); } } } else { ZVAL_COPY_VALUE(result, expr); - if (IS_CV != IS_TMP_VAR) { - zval_opt_copy_ctor(result); - } + zval_opt_copy_ctor(result); convert_to_object(result); } } - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); } CHECK_EXCEPTION(); @@ -33645,8 +33933,7 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL ZVAL_UNDEF(&tmp_inc_filename); if (Z_TYPE_P(inc_filename) != IS_STRING) { - ZVAL_DUP(&tmp_inc_filename, inc_filename); - convert_to_string(&tmp_inc_filename); + ZVAL_STR(&tmp_inc_filename, zval_get_string(inc_filename)); inc_filename = &tmp_inc_filename; } @@ -33725,8 +34012,8 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL return_value = EX_VAR(opline->result.var); } - call = zend_vm_stack_push_call_frame( - (zend_function*)new_op_array, 0, 0, EX(called_scope), EX(object), NULL TSRMLS_CC); + call = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_CODE, + (zend_function*)new_op_array, 0, EX(called_scope), Z_OBJ(EX(This)), NULL TSRMLS_CC); if (EX(symbol_table)) { call->symbol_table = EX(symbol_table); @@ -33735,10 +34022,11 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL } call->prev_execute_data = execute_data; - i_init_code_execute_data(call, new_op_array, return_value, EXPECTED(zend_execute_ex == execute_ex) ? VM_FRAME_NESTED_CODE : VM_FRAME_TOP_CODE TSRMLS_CC); + i_init_code_execute_data(call, new_op_array, return_value TSRMLS_CC); if (EXPECTED(zend_execute_ex == execute_ex)) { ZEND_VM_ENTER(); } else { + call->frame_info = VM_FRAME_TOP_CODE; zend_execute_ex(call TSRMLS_CC); } @@ -33779,13 +34067,8 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS } if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref); } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { - if(Z_OBJ_HT_P(array_ptr)->get_class_entry == NULL) { - zend_error(E_WARNING, "foreach() cannot iterate over objects without PHP class"); - ZEND_VM_JMP(opline->op2.jmp_addr); - } - ce = Z_OBJCE_P(array_ptr); - if (!ce || ce->get_iterator == NULL) { + if (ce->get_iterator == NULL) { Z_ADDREF_P(array_ptr); } array_ref = array_ptr; @@ -33797,7 +34080,10 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS ZVAL_DEREF(array_ptr); if (IS_CV == IS_TMP_VAR) { ZVAL_COPY_VALUE(&tmp, array_ptr); - array_ptr = &tmp; + if (Z_OPT_IMMUTABLE_P(&tmp)) { + zval_copy_ctor_func(&tmp); + } + array_ref = array_ptr = &tmp; if (Z_TYPE_P(array_ptr) == IS_OBJECT) { ce = Z_OBJCE_P(array_ptr); if (ce && ce->get_iterator) { @@ -33806,17 +34092,18 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS } } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { ce = Z_OBJCE_P(array_ptr); - if (!ce || !ce->get_iterator) { + if (!ce->get_iterator) { if (IS_CV == IS_CV) { Z_ADDREF_P(array_ref); } } } else if (Z_IMMUTABLE_P(array_ref)) { if (IS_CV == IS_CV) { - zval_copy_ctor(array_ref); + zval_copy_ctor_func(array_ref); Z_ADDREF_P(array_ref); } else { - ZVAL_DUP(&tmp, array_ref); + ZVAL_COPY_VALUE(&tmp, array_ref); + zval_copy_ctor_func(&tmp); array_ptr = array_ref = &tmp; } } else if (Z_REFCOUNTED_P(array_ref)) { @@ -33837,14 +34124,13 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS ZVAL_UNREF(array_ref); array_ptr = array_ref; } - if (Z_IMMUTABLE_P(array_ptr) || - (Z_ISREF_P(array_ref) && - Z_REFCOUNTED_P(array_ptr) && - Z_REFCOUNT_P(array_ptr) > 1)) { - if (!Z_IMMUTABLE_P(array_ptr)) { - Z_DELREF_P(array_ptr); - } - zval_copy_ctor(array_ptr); + if (Z_IMMUTABLE_P(array_ptr)) { + zval_copy_ctor_func(array_ptr); + } else if (Z_ISREF_P(array_ref) && + Z_COPYABLE_P(array_ptr) && + Z_REFCOUNT_P(array_ptr) > 1) { + Z_DELREF_P(array_ptr); + zval_copy_ctor_func(array_ptr); } if (IS_CV == IS_CV) { Z_ADDREF_P(array_ref); @@ -33928,6 +34214,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS ptr->pos = pos; ptr->ht = fe_ht; ptr->h = fe_ht->arData[pos].h; + ptr->key = fe_ht->arData[pos].key; is_empty = 0; } else { zend_error(E_WARNING, "Invalid argument supplied for foreach()"); @@ -34000,19 +34287,22 @@ static int ZEND_FASTCALL ZEND_JMP_SET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_COALESCE_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; + int is_ref = 0; SAVE_OPLINE(); - value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + value = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); if ((IS_CV == IS_VAR || IS_CV == IS_CV) && Z_ISREF_P(value)) { - ZVAL_COPY(EX_VAR(opline->result.var), Z_REFVAL_P(value)); + is_ref = 1; + value = Z_REFVAL_P(value); + } - } else { + if (Z_TYPE_P(value) > IS_NULL) { ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value); if (IS_CV == IS_CONST) { if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { @@ -34020,29 +34310,39 @@ static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG } } else if (IS_CV == IS_CV) { if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } else if (IS_CV == IS_VAR && is_ref) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } + ZEND_VM_JMP(opline->op2.jmp_addr); } + + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *expr; - zend_bool result; + zval *value; SAVE_OPLINE(); - expr = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + + if ((IS_CV == IS_VAR || IS_CV == IS_CV) && Z_ISREF_P(value)) { + ZVAL_COPY(EX_VAR(opline->result.var), Z_REFVAL_P(value)); - if (Z_TYPE_P(expr) == IS_OBJECT && Z_OBJ_HT_P(expr)->get_class_entry) { - result = instanceof_function(Z_OBJCE_P(expr), Z_CE_P(EX_VAR(opline->op2.var)) TSRMLS_CC); } else { - result = 0; + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value); + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + zval_copy_ctor_func(EX_VAR(opline->result.var)); + } + } else if (IS_CV == IS_CV) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } } - ZVAL_BOOL(EX_VAR(opline->result.var), result); - - CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -34107,16 +34407,12 @@ static int ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_AR break; case IS_OBJECT: if (Z_TYPE_P(value) == opline->extended_value) { - if (Z_OBJ_HT_P(value)->get_class_entry == NULL) { - ZVAL_TRUE(EX_VAR(opline->result.var)); + zend_class_entry *ce = Z_OBJCE_P(value); + if (ce->name->len == sizeof("__PHP_Incomplete_Class") - 1 + && !strncmp(ce->name->val, "__PHP_Incomplete_Class", ce->name->len)) { + ZVAL_FALSE(EX_VAR(opline->result.var)); } else { - zend_class_entry *ce = Z_OBJCE_P(value); - if (ce->name->len == sizeof("__PHP_Incomplete_Class") - 1 - && !strncmp(ce->name->val, "__PHP_Incomplete_Class", ce->name->len)) { - ZVAL_FALSE(EX_VAR(opline->result.var)); - } else { - ZVAL_TRUE(EX_VAR(opline->result.var)); - } + ZVAL_TRUE(EX_VAR(opline->result.var)); } } else { ZVAL_FALSE(EX_VAR(opline->result.var)); @@ -34419,17 +34715,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CONST(int (*bi zval *object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); zval *property = opline->op2.zv; zval *value; - int have_get_ptr = 0; + zval *zptr; if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - object = make_real_object(object TSRMLS_CC); + if (IS_CV != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); + } - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to assign property of non-object"); FREE_OP(free_op_data1); @@ -34440,20 +34738,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CONST(int (*bi } else { /* here we are sure we are dealing with an object */ if (opline->extended_value == ZEND_ASSIGN_OBJ - && Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - SEPARATE_ZVAL_IF_NOT_REF(zptr); + && EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - have_get_ptr = 1; - binary_op(zptr, zptr, value TSRMLS_CC); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), zptr); - } - } - } + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + binary_op(zptr, zptr, value TSRMLS_CC); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); + } + } else { zval *z = NULL; zval rv; @@ -34508,15 +34803,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CONST(int (*bi static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_CONST(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data2, free_op_data1; - zval *var_ptr; + zend_free_op free_op_data1; + zval *var_ptr, rv; zval *value, *container; SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } + if (IS_CV != IS_UNUSED) { + ZVAL_DEREF(container); + } + if (IS_CV == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_CV == IS_VAR && !0) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } @@ -34524,9 +34823,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_CONST(int (*bi } else { zval *dim = opline->op2.zv; - zend_fetch_dimension_address_RW(EX_VAR((opline+1)->op2.var), container, dim, IS_CONST TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + zend_fetch_dimension_address_RW(&rv, container, dim, IS_CONST TSRMLS_CC); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); } if (UNEXPECTED(var_ptr == NULL)) { @@ -34537,33 +34837,18 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_CONST(int (*bi if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_dim_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_dim_exit: - FREE_OP(free_op_data1); - FREE_OP_VAR_PTR(free_op_data2); CHECK_EXCEPTION(); ZEND_VM_INC_OPCODE(); @@ -34589,31 +34874,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_CONST(int (*binary if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_exit: - CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -34769,7 +35040,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CONST(incdec_t zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); @@ -34780,9 +35051,11 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CONST(incdec_t zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_CV != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); if (RETURN_VALUE_USED(opline)) { @@ -34795,20 +35068,17 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CONST(incdec_t /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - SEPARATE_ZVAL_IF_NOT_REF(zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - have_get_ptr = 1; - incdec_op(zptr); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(retval, zptr); - } - } - } + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + incdec_op(zptr); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(retval, zptr); + } + } else { zval rv; if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { @@ -34860,7 +35130,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CONST(incdec_t zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); @@ -34871,9 +35141,11 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CONST(incdec_t zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_CV != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); ZVAL_NULL(retval); @@ -34884,20 +35156,15 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CONST(incdec_t /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - have_get_ptr = 1; - SEPARATE_ZVAL_IF_NOT_REF(zptr); - - ZVAL_DUP(retval, zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - incdec_op(zptr); + ZVAL_DEREF(zptr); + ZVAL_COPY(retval, zptr); - } - } - - if (!have_get_ptr) { + SEPARATE_ZVAL_NOREF(zptr); + incdec_op(zptr); + } else { if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { zval rv; zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); @@ -35046,9 +35313,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_CONST(int type, Z } ZVAL_COPY(EX_VAR(opline->result.var), retval); } else { - if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) { - ZVAL_MAKE_REF(retval); - } ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); } CHECK_EXCEPTION(); @@ -35101,9 +35365,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAN container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); - if (IS_CV != IS_VAR || !(opline->extended_value & ZEND_FETCH_ADD_LOCK)) { - } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -35120,11 +35382,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAN if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - if (EXPECTED(opline->extended_value == 0)) { - zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); - } else { - zend_fetch_dimension_address_W_ref(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); - } + ZVAL_DEREF(container); + zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -35146,6 +35405,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HA if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { @@ -35187,6 +35447,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CONST_HANDLER(ZEND_OPC if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -35218,6 +35479,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CONST_HANDLER(ZEND_OPCODE if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { @@ -35228,7 +35490,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CONST_HANDLER(ZEND_OPCODE ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CV_CONST(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -35240,7 +35502,7 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CV_CONST(Z container = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); offset = opline->op2.zv; - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { zend_error(E_NOTICE, "Trying to get property of non-object"); ZVAL_NULL(EX_VAR(opline->result.var)); @@ -35260,11 +35522,6 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CV_CONST(Z ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_property_address_read_helper_SPEC_CV_CONST(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -35280,7 +35537,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAN zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -35304,7 +35561,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HA if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -35326,7 +35583,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HA container = _get_zval_ptr_cv_deref_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); offset = opline->op2.zv; - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -35365,7 +35622,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CONST_HANDLER(ZEND_OPC if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -35374,7 +35631,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CONST_HANDLER(ZEND_OPC CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { - return zend_fetch_property_address_read_helper_SPEC_CV_CONST(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return ZEND_FETCH_OBJ_R_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } @@ -35391,7 +35648,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_CONST_HANDLER(ZEND_OPCODE if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -35401,6 +35658,39 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_CONST_HANDLER(ZEND_OPCODE ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_FETCH_LIST_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *container; + + SAVE_OPLINE(); + container = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + + zval *value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), opline->op2.zv, IS_CONST, BP_VAR_R TSRMLS_CC); + + ZVAL_COPY(EX_VAR(opline->result.var), value); + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT) && + EXPECTED(Z_OBJ_HT_P(container)->read_dimension)) { + zval *result = EX_VAR(opline->result.var); + zval *retval = Z_OBJ_HT_P(container)->read_dimension(container, opline->op2.zv, BP_VAR_R, result TSRMLS_CC); + + if (retval) { + if (result != retval) { + ZVAL_COPY(result, retval); + } + } else { + ZVAL_NULL(result); + } + } else { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -35415,7 +35705,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAND if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, IS_CV, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); /* assign_obj has two opcodes! */ @@ -35436,45 +35726,48 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAND if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - if (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) { - object_ptr = Z_REFVAL_P(object_ptr); - } - if (Z_TYPE_P(object_ptr) == IS_OBJECT) { + ZVAL_DEREF(object_ptr); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { zval *property_name = opline->op2.zv; - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_CV, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); } else { - zend_free_op free_op_data1, free_op_data2; + zend_free_op free_op_data1; + zval rv; zval *value; zval *dim = opline->op2.zv; zval *variable_ptr; - variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_CONST TSRMLS_CC); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) && + EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + zend_long offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W TSRMLS_CC); - value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(variable_ptr != NULL)) { - zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + zend_assign_to_string_offset(object_ptr, offset, value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); + FREE_OP(free_op_data1); } else { - variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_CONST TSRMLS_CC); + + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + variable_ptr = Z_INDIRECT(rv); if (UNEXPECTED(variable_ptr == &EG(error_zval))) { - if (IS_TMP_FREE(free_op_data1)) { - zval_dtor(value); - } + FREE_OP(free_op_data1); if (RETURN_VALUE_USED(opline)) { ZVAL_NULL(EX_VAR(opline->result.var)); } - FREE_OP_VAR_PTR(free_op_data2); } else { value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC); + if ((opline+1)->op1_type == IS_VAR) { + FREE_OP(free_op_data1); + } if (RETURN_VALUE_USED(opline)) { ZVAL_COPY(EX_VAR(opline->result.var), value); } - FREE_OP_VAR_PTR(free_op_data2); } } - FREE_OP_IF_VAR(free_op_data1); } /* assign_dim has two opcodes! */ @@ -35496,7 +35789,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) { if (IS_CONST == IS_TMP_VAR) { - zval_dtor(value); + } if (RETURN_VALUE_USED(opline)) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -35539,19 +35832,55 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CONST_HANDLER(ZEND_OPCOD object = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + uint32_t nesting = 1; + if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); + + zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); + + + if (EG(exception) != NULL) { + HANDLE_EXCEPTION(); + } + + /* No exception raised: Skip over arguments until fcall opcode with correct + * nesting level. Return NULL (except when return value unused) */ + do { + opline++; + if (opline->opcode == ZEND_INIT_FCALL || + opline->opcode == ZEND_INIT_FCALL_BY_NAME || + opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME || + opline->opcode == ZEND_INIT_METHOD_CALL || + opline->opcode == ZEND_INIT_STATIC_METHOD_CALL || + opline->opcode == ZEND_INIT_USER_CALL || + opline->opcode == ZEND_NEW + ) { + nesting++; + } else if (opline->opcode == ZEND_DO_FCALL) { + nesting--; + } + } while (nesting); + + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + /* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */ + if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) { + opline++; + } + ZEND_VM_JMP(++opline); } obj = Z_OBJ_P(object); - called_scope = zend_get_class_entry(obj TSRMLS_CC); + called_scope = obj->ce; if (IS_CONST != IS_CONST || - (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) { + EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { zend_object *orig_obj = obj; if (UNEXPECTED(obj->handlers->get_method == NULL)) { @@ -35561,7 +35890,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CONST_HANDLER(ZEND_OPCOD /* First, locate the function. */ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name)); + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); } if (IS_CONST == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -35571,14 +35900,14 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CONST_HANDLER(ZEND_OPCOD } } - if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { obj = NULL; } else { GC_REFCOUNT(obj)++; /* For $this pointer */ } - EX(call) = zend_vm_stack_push_call_frame( - fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_FUNCTION, + fbc, opline->extended_value, called_scope, obj, EX(call) TSRMLS_CC); CHECK_EXCEPTION(); @@ -35753,8 +36082,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDL ZVAL_UNDEF(&tmp); if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { - ZVAL_DUP(&tmp, varname); - convert_to_string(&tmp); + ZVAL_STR(&tmp, zval_get_string(varname)); varname = &tmp; } @@ -35814,71 +36142,66 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDL } offset = opline->op2.zv; - switch (Z_TYPE_P(container)) { - case IS_ARRAY: { - HashTable *ht = Z_ARRVAL_P(container); + if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht = Z_ARRVAL_P(container); offset_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - zend_hash_index_del(ht, hval); - break; - case IS_LONG: - hval = Z_LVAL_P(offset); + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_LONG: + hval = Z_LVAL_P(offset); num_index_dim: - zend_hash_index_del(ht, hval); - break; - case IS_STRING: - if (IS_CONST != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { - goto num_index_dim; - } - } - if (ht == &EG(symbol_table).ht) { - zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); - } else { - zend_hash_del(ht, Z_STR_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_STRING: + if (IS_CONST != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { + goto num_index_dim; } - break; - case IS_NULL: - zend_hash_del(ht, STR_EMPTY_ALLOC()); - break; - case IS_FALSE: - hval = 0; - goto num_index_dim; - case IS_TRUE: - hval = 1; - goto num_index_dim; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_dim; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto offset_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type in unset"); - break; - } + } + if (ht == &EG(symbol_table).ht) { + zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); + } else { + zend_hash_del(ht, Z_STR_P(offset)); + } + break; + case IS_NULL: + zend_hash_del(ht, STR_EMPTY_ALLOC()); + break; + case IS_FALSE: + hval = 0; + goto num_index_dim; + case IS_TRUE: + hval = 1; + goto num_index_dim; + case IS_RESOURCE: + hval = Z_RES_HANDLE_P(offset); + goto num_index_dim; + case IS_REFERENCE: + offset = Z_REFVAL_P(offset); + goto offset_again; + break; + default: + zend_error(E_WARNING, "Illegal offset type in unset"); + break; + } - break; + } else if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use object as array"); } - case IS_OBJECT: - if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use object as array"); - } -//??? if (IS_CONST == IS_CONST) { -//??? zval_copy_ctor(offset); -//??? } - Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); +//??? if (IS_CONST == IS_CONST) { +//??? zval_copy_ctor(offset); +//??? } + Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); - break; - case IS_STRING: - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - ZEND_VM_CONTINUE(); /* bailed out before */ - default: + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + ZEND_VM_CONTINUE(); /* bailed out before */ + } else { - break; } CHECK_EXCEPTION(); @@ -35900,7 +36223,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDL offset = opline->op2.zv; ZVAL_DEREF(container); - if (Z_TYPE_P(container) == IS_OBJECT) { + if (IS_CV == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->unset_property) { Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { @@ -35917,26 +36240,28 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_CONST_HANDLER(ZEND_OPCO { USE_OPLINE zval *value; - zend_bool isset = 1; SAVE_OPLINE(); if (IS_CV == IS_CV && IS_CONST == IS_UNUSED && (opline->extended_value & ZEND_QUICK_SET)) { - if (Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_UNDEF) { - value = EX_VAR(opline->op1.var); - ZVAL_DEREF(value); - } else { - isset = 0; + value = EX_VAR(opline->op1.var); + if (opline->extended_value & ZEND_ISSET) { + ZVAL_BOOL(EX_VAR(opline->result.var), + Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + ZVAL_BOOL(EX_VAR(opline->result.var), + !i_zend_is_true(value TSRMLS_CC)); + CHECK_EXCEPTION(); } + ZEND_VM_NEXT_OPCODE(); } else { - HashTable *target_symbol_table; zval tmp, *varname = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { - ZVAL_DUP(&tmp, varname); - convert_to_string(&tmp); + ZVAL_STR(&tmp, zval_get_string(varname)); varname = &tmp; } @@ -35958,39 +36283,27 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_CONST_HANDLER(ZEND_OPCO ce = Z_CE_P(EX_VAR(opline->op2.var)); } value = zend_std_get_static_property(ce, Z_STR_P(varname), 1, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); - if (!value) { - isset = 0; - } } else { - target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); - if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) { - isset = 0; - } + HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname)); } if (IS_CV != IS_CONST && varname == &tmp) { zval_dtor(&tmp); } - } - - if (opline->extended_value & ZEND_ISSET) { - if (isset && Z_TYPE_P(value) != IS_NULL && - (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) { - ZVAL_BOOL(EX_VAR(opline->result.var), 1); - } else { - ZVAL_BOOL(EX_VAR(opline->result.var), 0); - } - } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { - if (!isset || !i_zend_is_true(value TSRMLS_CC)) { - ZVAL_BOOL(EX_VAR(opline->result.var), 1); - } else { - ZVAL_BOOL(EX_VAR(opline->result.var), 0); + if (opline->extended_value & ZEND_ISSET) { + ZVAL_BOOL(EX_VAR(opline->result.var), + value && Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + ZVAL_BOOL(EX_VAR(opline->result.var), + !value || !i_zend_is_true(value TSRMLS_CC)); } - } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } } static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -36006,7 +36319,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_CONST_HANDLER(ZEND_ container = _get_zval_ptr_cv_deref_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); offset = opline->op2.zv; - if (Z_TYPE_P(container) == IS_ARRAY) { + if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { HashTable *ht = Z_ARRVAL_P(container); zval *value; zend_string *str; @@ -36059,8 +36372,8 @@ num_index_prop: } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); } - } else if (Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->has_dimension) { + } else if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to check element of non-array"); @@ -36069,7 +36382,7 @@ num_index_prop: if ((opline->extended_value & ZEND_ISSET) == 0) { result = !result; } - } else if (Z_TYPE_P(container) == IS_STRING) { /* string offsets */ + } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */ zval tmp; result = 0; @@ -36085,7 +36398,7 @@ num_index_prop: offset = &tmp; } } - if (Z_TYPE_P(offset) == IS_LONG) { + if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) { if ((opline->extended_value & ZEND_ISSET) || Z_STRVAL_P(container)[offset->value.lval] != '0') { @@ -36118,8 +36431,8 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_CONST_HANDLER(ZEND container = _get_zval_ptr_cv_deref_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); offset = opline->op2.zv; - if (Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->has_property) { + if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_property)) { result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to check property of non-object"); @@ -36138,6 +36451,45 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_CONST_HANDLER(ZEND ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *expr; + zend_bool result; + + SAVE_OPLINE(); + expr = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + + if (Z_TYPE_P(expr) == IS_OBJECT) { + zend_class_entry *ce; + + if (IS_CONST == IS_CONST) { + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC); + if (UNEXPECTED(ce == NULL)) { + ZVAL_FALSE(EX_VAR(opline->result.var)); + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op2.var)); + } + result = instanceof_function(Z_OBJCE_P(expr), ce TSRMLS_CC); + } else { + result = 0; + } + ZVAL_BOOL(EX_VAR(opline->result.var), result); + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -36173,7 +36525,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_A /* Temporary variables don't need ctor copying */ if (IS_CV != IS_TMP_VAR) { - zval_copy_ctor(&generator->value); + zval_opt_copy_ctor(&generator->value); } } else { zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); @@ -36184,9 +36536,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_A /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_CV == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_CV == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -36355,7 +36708,7 @@ static int ZEND_FASTCALL ZEND_ADD_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -36370,7 +36723,7 @@ static int ZEND_FASTCALL ZEND_SUB_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -36385,7 +36738,7 @@ static int ZEND_FASTCALL ZEND_MUL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -36400,7 +36753,7 @@ static int ZEND_FASTCALL ZEND_DIV_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -36415,7 +36768,7 @@ static int ZEND_FASTCALL ZEND_MOD_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -36430,7 +36783,7 @@ static int ZEND_FASTCALL ZEND_SL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -36445,7 +36798,7 @@ static int ZEND_FASTCALL ZEND_SR_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -36460,7 +36813,7 @@ static int ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -36475,7 +36828,7 @@ static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HAND _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -36491,7 +36844,7 @@ static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_ _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -36507,7 +36860,7 @@ static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -36523,7 +36876,7 @@ static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HAND _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -36539,7 +36892,7 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLE _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -36555,7 +36908,7 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CV_TMP_HANDLER(ZEND_OPCO _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -36570,7 +36923,7 @@ static int ZEND_FASTCALL ZEND_BW_OR_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -36585,7 +36938,7 @@ static int ZEND_FASTCALL ZEND_BW_AND_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -36600,7 +36953,7 @@ static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -36615,7 +36968,7 @@ static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -36627,19 +36980,21 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_TMP(int (*bina zval *object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); zval *property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); zval *value; - int have_get_ptr = 0; + zval *zptr; if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - object = make_real_object(object TSRMLS_CC); + if (IS_CV != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); + } - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to assign property of non-object"); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); FREE_OP(free_op_data1); if (RETURN_VALUE_USED(opline)) { @@ -36648,20 +37003,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_TMP(int (*bina } else { /* here we are sure we are dealing with an object */ if (opline->extended_value == ZEND_ASSIGN_OBJ - && Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - SEPARATE_ZVAL_IF_NOT_REF(zptr); + && EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - have_get_ptr = 1; - binary_op(zptr, zptr, value TSRMLS_CC); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), zptr); - } - } - } + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + binary_op(zptr, zptr, value TSRMLS_CC); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); + } + } else { zval *z = NULL; zval rv; @@ -36704,7 +37056,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_TMP(int (*bina } } - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); FREE_OP(free_op_data1); } @@ -36717,15 +37069,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_TMP(int (*bina static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_TMP(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2, free_op_data2, free_op_data1; - zval *var_ptr; + zend_free_op free_op2, free_op_data1; + zval *var_ptr, rv; zval *value, *container; SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } + if (IS_CV != IS_UNUSED) { + ZVAL_DEREF(container); + } + if (IS_CV == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_CV == IS_VAR && !0) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } @@ -36733,9 +37089,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_TMP(int (*bina } else { zval *dim = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - zend_fetch_dimension_address_RW(EX_VAR((opline+1)->op2.var), container, dim, IS_TMP_VAR TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + zend_fetch_dimension_address_RW(&rv, container, dim, IS_TMP_VAR TSRMLS_CC); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); } if (UNEXPECTED(var_ptr == NULL)) { @@ -36746,33 +37103,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_TMP(int (*bina if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_dim_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_dim_exit: - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); FREE_OP(free_op_data1); - FREE_OP_VAR_PTR(free_op_data2); CHECK_EXCEPTION(); ZEND_VM_INC_OPCODE(); @@ -36798,31 +37141,18 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_TMP(int (*binary_o if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_exit: - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -36978,7 +37308,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_TMP(incdec_t in zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); @@ -36989,11 +37319,13 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_TMP(incdec_t in zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_CV != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); if (RETURN_VALUE_USED(opline)) { ZVAL_NULL(retval); } @@ -37004,20 +37336,17 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_TMP(incdec_t in /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - SEPARATE_ZVAL_IF_NOT_REF(zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - have_get_ptr = 1; - incdec_op(zptr); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(retval, zptr); - } - } - } + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + incdec_op(zptr); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(retval, zptr); + } + } else { zval rv; if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { @@ -37047,7 +37376,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_TMP(incdec_t in } } - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -37070,7 +37399,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_TMP(incdec_t i zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); @@ -37081,11 +37410,13 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_TMP(incdec_t i zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_CV != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); ZVAL_NULL(retval); CHECK_EXCEPTION(); @@ -37094,20 +37425,15 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_TMP(incdec_t i /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - have_get_ptr = 1; - SEPARATE_ZVAL_IF_NOT_REF(zptr); - - ZVAL_DUP(retval, zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - incdec_op(zptr); + ZVAL_DEREF(zptr); + ZVAL_COPY(retval, zptr); - } - } - - if (!have_get_ptr) { + SEPARATE_ZVAL_NOREF(zptr); + incdec_op(zptr); + } else { if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { zval rv; zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); @@ -37135,7 +37461,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_TMP(incdec_t i } } - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -37160,10 +37486,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDL SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); - zval_dtor(free_op2.var); - if (IS_CV != IS_VAR || !(opline->extended_value & ZEND_FETCH_ADD_LOCK)) { + zval_ptr_dtor_nogc(free_op2.var); - } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -37180,12 +37504,9 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDL if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - if (EXPECTED(opline->extended_value == 0)) { - zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); - } else { - zend_fetch_dimension_address_W_ref(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); - } - zval_dtor(free_op2.var); + ZVAL_DEREF(container); + zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } @@ -37206,8 +37527,9 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HAND if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } @@ -37225,7 +37547,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -37247,11 +37569,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_TMP_HANDLER(ZEND_OPCOD if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); } else { if (IS_TMP_VAR == IS_UNUSED) { @@ -37259,7 +37582,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_TMP_HANDLER(ZEND_OPCOD } container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); } CHECK_EXCEPTION(); @@ -37278,8 +37601,9 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_H if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } @@ -37288,7 +37612,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_H ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CV_TMP(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -37300,7 +37624,7 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CV_TMP(ZEN container = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { zend_error(E_NOTICE, "Trying to get property of non-object"); ZVAL_NULL(EX_VAR(opline->result.var)); @@ -37315,17 +37639,12 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CV_TMP(ZEN } } - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_property_address_read_helper_SPEC_CV_TMP(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -37341,8 +37660,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDL zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); - zval_dtor(free_op2.var); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } @@ -37365,8 +37684,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HAND if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); - zval_dtor(free_op2.var); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } @@ -37387,7 +37706,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HAND container = _get_zval_ptr_cv_deref_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -37401,7 +37720,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HAND } } - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -37427,8 +37746,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_TMP_HANDLER(ZEND_OPCOD if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); - zval_dtor(free_op2.var); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } @@ -37436,7 +37755,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_TMP_HANDLER(ZEND_OPCOD CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { - return zend_fetch_property_address_read_helper_SPEC_CV_TMP(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return ZEND_FETCH_OBJ_R_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } @@ -37453,8 +37772,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_H if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); - zval_dtor(free_op2.var); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); } @@ -37477,8 +37796,8 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLE if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); - zval_dtor(free_op2.var); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, IS_CV, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); /* assign_obj has two opcodes! */ CHECK_EXCEPTION(); @@ -37498,45 +37817,48 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLE if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - if (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) { - object_ptr = Z_REFVAL_P(object_ptr); - } - if (Z_TYPE_P(object_ptr) == IS_OBJECT) { + ZVAL_DEREF(object_ptr); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { zend_free_op free_op2; zval *property_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); - zval_dtor(free_op2.var); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_CV, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); } else { - zend_free_op free_op2, free_op_data1, free_op_data2; + zend_free_op free_op2, free_op_data1; + zval rv; zval *value; zval *dim = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); zval *variable_ptr; - variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_TMP_VAR TSRMLS_CC); - zval_dtor(free_op2.var); - value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(variable_ptr != NULL)) { - zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) && + EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + zend_long offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + zend_assign_to_string_offset(object_ptr, offset, value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); + FREE_OP(free_op_data1); } else { - variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_TMP_VAR TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + variable_ptr = Z_INDIRECT(rv); if (UNEXPECTED(variable_ptr == &EG(error_zval))) { - if (IS_TMP_FREE(free_op_data1)) { - zval_dtor(value); - } + FREE_OP(free_op_data1); if (RETURN_VALUE_USED(opline)) { ZVAL_NULL(EX_VAR(opline->result.var)); } - FREE_OP_VAR_PTR(free_op_data2); } else { value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC); + if ((opline+1)->op1_type == IS_VAR) { + FREE_OP(free_op_data1); + } if (RETURN_VALUE_USED(opline)) { ZVAL_COPY(EX_VAR(opline->result.var), value); } - FREE_OP_VAR_PTR(free_op_data2); } } - FREE_OP_IF_VAR(free_op_data1); } /* assign_dim has two opcodes! */ @@ -37558,7 +37880,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) { if (IS_TMP_VAR == IS_TMP_VAR) { - zval_dtor(value); + zval_ptr_dtor_nogc(free_op2.var); } if (RETURN_VALUE_USED(opline)) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -37601,19 +37923,55 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_ object = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + uint32_t nesting = 1; + if (UNEXPECTED(EG(exception) != NULL)) { - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); + + zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); + zval_ptr_dtor_nogc(free_op2.var); + + if (EG(exception) != NULL) { + HANDLE_EXCEPTION(); + } + + /* No exception raised: Skip over arguments until fcall opcode with correct + * nesting level. Return NULL (except when return value unused) */ + do { + opline++; + if (opline->opcode == ZEND_INIT_FCALL || + opline->opcode == ZEND_INIT_FCALL_BY_NAME || + opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME || + opline->opcode == ZEND_INIT_METHOD_CALL || + opline->opcode == ZEND_INIT_STATIC_METHOD_CALL || + opline->opcode == ZEND_INIT_USER_CALL || + opline->opcode == ZEND_NEW + ) { + nesting++; + } else if (opline->opcode == ZEND_DO_FCALL) { + nesting--; + } + } while (nesting); + + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + /* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */ + if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) { + opline++; + } + ZEND_VM_JMP(++opline); } obj = Z_OBJ_P(object); - called_scope = zend_get_class_entry(obj TSRMLS_CC); + called_scope = obj->ce; if (IS_TMP_VAR != IS_CONST || - (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) { + EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { zend_object *orig_obj = obj; if (UNEXPECTED(obj->handlers->get_method == NULL)) { @@ -37623,7 +37981,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_ /* First, locate the function. */ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_TMP_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name)); + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); } if (IS_TMP_VAR == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -37633,16 +37991,16 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_ } } - if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { obj = NULL; } else { GC_REFCOUNT(obj)++; /* For $this pointer */ } - EX(call) = zend_vm_stack_push_call_frame( - fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_FUNCTION, + fbc, opline->extended_value, called_scope, obj, EX(call) TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -37659,7 +38017,7 @@ static int ZEND_FASTCALL ZEND_CASE_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -37744,7 +38102,7 @@ str_index: /* do nothing */ break; } - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); } else { zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr); } @@ -37802,71 +38160,66 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER } offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - switch (Z_TYPE_P(container)) { - case IS_ARRAY: { - HashTable *ht = Z_ARRVAL_P(container); + if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht = Z_ARRVAL_P(container); offset_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - zend_hash_index_del(ht, hval); - break; - case IS_LONG: - hval = Z_LVAL_P(offset); + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_LONG: + hval = Z_LVAL_P(offset); num_index_dim: - zend_hash_index_del(ht, hval); - break; - case IS_STRING: - if (IS_TMP_VAR != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { - goto num_index_dim; - } - } - if (ht == &EG(symbol_table).ht) { - zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); - } else { - zend_hash_del(ht, Z_STR_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_STRING: + if (IS_TMP_VAR != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { + goto num_index_dim; } - break; - case IS_NULL: - zend_hash_del(ht, STR_EMPTY_ALLOC()); - break; - case IS_FALSE: - hval = 0; - goto num_index_dim; - case IS_TRUE: - hval = 1; - goto num_index_dim; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_dim; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto offset_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type in unset"); - break; - } - zval_dtor(free_op2.var); - break; + } + if (ht == &EG(symbol_table).ht) { + zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); + } else { + zend_hash_del(ht, Z_STR_P(offset)); + } + break; + case IS_NULL: + zend_hash_del(ht, STR_EMPTY_ALLOC()); + break; + case IS_FALSE: + hval = 0; + goto num_index_dim; + case IS_TRUE: + hval = 1; + goto num_index_dim; + case IS_RESOURCE: + hval = Z_RES_HANDLE_P(offset); + goto num_index_dim; + case IS_REFERENCE: + offset = Z_REFVAL_P(offset); + goto offset_again; + break; + default: + zend_error(E_WARNING, "Illegal offset type in unset"); + break; } - case IS_OBJECT: - if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use object as array"); - } -//??? if (IS_TMP_VAR == IS_CONST) { -//??? zval_copy_ctor(offset); -//??? } - Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); - zval_dtor(free_op2.var); - break; - case IS_STRING: - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - ZEND_VM_CONTINUE(); /* bailed out before */ - default: - zval_dtor(free_op2.var); - break; + zval_ptr_dtor_nogc(free_op2.var); + } else if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use object as array"); + } +//??? if (IS_TMP_VAR == IS_CONST) { +//??? zval_copy_ctor(offset); +//??? } + Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + ZEND_VM_CONTINUE(); /* bailed out before */ + } else { + zval_ptr_dtor_nogc(free_op2.var); } CHECK_EXCEPTION(); @@ -37888,14 +38241,14 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); ZVAL_DEREF(container); - if (Z_TYPE_P(container) == IS_OBJECT) { + if (IS_CV == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->unset_property) { Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to unset property of non-object"); } } - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -37914,7 +38267,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_TMP_HANDLER(ZEND_OP container = _get_zval_ptr_cv_deref_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (Z_TYPE_P(container) == IS_ARRAY) { + if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { HashTable *ht = Z_ARRVAL_P(container); zval *value; zend_string *str; @@ -37967,8 +38320,8 @@ num_index_prop: } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); } - } else if (Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->has_dimension) { + } else if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to check element of non-array"); @@ -37977,7 +38330,7 @@ num_index_prop: if ((opline->extended_value & ZEND_ISSET) == 0) { result = !result; } - } else if (Z_TYPE_P(container) == IS_STRING) { /* string offsets */ + } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */ zval tmp; result = 0; @@ -37993,7 +38346,7 @@ num_index_prop: offset = &tmp; } } - if (Z_TYPE_P(offset) == IS_LONG) { + if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) { if ((opline->extended_value & ZEND_ISSET) || Z_STRVAL_P(container)[offset->value.lval] != '0') { @@ -38008,7 +38361,7 @@ num_index_prop: result = ((opline->extended_value & ZEND_ISSET) == 0); } - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); ZVAL_BOOL(EX_VAR(opline->result.var), result); CHECK_EXCEPTION(); @@ -38027,8 +38380,8 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_TMP_HANDLER(ZEND_O container = _get_zval_ptr_cv_deref_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->has_property) { + if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_property)) { result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to check property of non-object"); @@ -38041,7 +38394,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_TMP_HANDLER(ZEND_O result = ((opline->extended_value & ZEND_ISSET) == 0); } - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); ZVAL_BOOL(EX_VAR(opline->result.var), result); CHECK_EXCEPTION(); @@ -38083,7 +38436,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG /* Temporary variables don't need ctor copying */ if (IS_CV != IS_TMP_VAR) { - zval_copy_ctor(&generator->value); + zval_opt_copy_ctor(&generator->value); } } else { zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); @@ -38094,9 +38447,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_CV == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_CV == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -38188,7 +38542,7 @@ static int ZEND_FASTCALL ZEND_POW_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); - zval_dtor(free_op2.var); + zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -38480,17 +38834,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_VAR(int (*bina zval *object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); zval *property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); zval *value; - int have_get_ptr = 0; + zval *zptr; if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - object = make_real_object(object TSRMLS_CC); + if (IS_CV != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); + } - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to assign property of non-object"); zval_ptr_dtor_nogc(free_op2.var); FREE_OP(free_op_data1); @@ -38501,20 +38857,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_VAR(int (*bina } else { /* here we are sure we are dealing with an object */ if (opline->extended_value == ZEND_ASSIGN_OBJ - && Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - SEPARATE_ZVAL_IF_NOT_REF(zptr); + && EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - have_get_ptr = 1; - binary_op(zptr, zptr, value TSRMLS_CC); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), zptr); - } - } - } + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + binary_op(zptr, zptr, value TSRMLS_CC); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); + } + } else { zval *z = NULL; zval rv; @@ -38570,15 +38923,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_VAR(int (*bina static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_VAR(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2, free_op_data2, free_op_data1; - zval *var_ptr; + zend_free_op free_op2, free_op_data1; + zval *var_ptr, rv; zval *value, *container; SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } + if (IS_CV != IS_UNUSED) { + ZVAL_DEREF(container); + } + if (IS_CV == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_CV == IS_VAR && !0) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } @@ -38586,9 +38943,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_VAR(int (*bina } else { zval *dim = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - zend_fetch_dimension_address_RW(EX_VAR((opline+1)->op2.var), container, dim, IS_VAR TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + zend_fetch_dimension_address_RW(&rv, container, dim, IS_VAR TSRMLS_CC); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); } if (UNEXPECTED(var_ptr == NULL)) { @@ -38599,33 +38957,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_VAR(int (*bina if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_dim_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_dim_exit: zval_ptr_dtor_nogc(free_op2.var); FREE_OP(free_op_data1); - FREE_OP_VAR_PTR(free_op_data2); CHECK_EXCEPTION(); ZEND_VM_INC_OPCODE(); @@ -38640,7 +38984,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_VAR(int (*binary_o zval *value; SAVE_OPLINE(); - value = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + value = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) { @@ -38651,30 +38995,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_VAR(int (*binary_o if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_exit: zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); @@ -38831,7 +39162,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_VAR(incdec_t in zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); @@ -38842,9 +39173,11 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_VAR(incdec_t in zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_CV != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); zval_ptr_dtor_nogc(free_op2.var); if (RETURN_VALUE_USED(opline)) { @@ -38857,20 +39190,17 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_VAR(incdec_t in /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - SEPARATE_ZVAL_IF_NOT_REF(zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - have_get_ptr = 1; - incdec_op(zptr); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(retval, zptr); - } - } - } + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + incdec_op(zptr); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(retval, zptr); + } + } else { zval rv; if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { @@ -38923,7 +39253,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_VAR(incdec_t i zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); @@ -38934,9 +39264,11 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_VAR(incdec_t i zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_CV != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); zval_ptr_dtor_nogc(free_op2.var); ZVAL_NULL(retval); @@ -38947,20 +39279,15 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_VAR(incdec_t i /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - have_get_ptr = 1; - SEPARATE_ZVAL_IF_NOT_REF(zptr); - - ZVAL_DUP(retval, zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - incdec_op(zptr); - - } - } + ZVAL_DEREF(zptr); + ZVAL_COPY(retval, zptr); - if (!have_get_ptr) { + SEPARATE_ZVAL_NOREF(zptr); + incdec_op(zptr); + } else { if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { zval rv; zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); @@ -39110,9 +39437,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_VAR(int type, ZEN } ZVAL_COPY(EX_VAR(opline->result.var), retval); } else { - if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) { - ZVAL_MAKE_REF(retval); - } ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); } CHECK_EXCEPTION(); @@ -39165,9 +39489,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDL container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); - if (IS_CV != IS_VAR || !(opline->extended_value & ZEND_FETCH_ADD_LOCK)) { - } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -39184,11 +39506,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDL if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - if (EXPECTED(opline->extended_value == 0)) { - zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC); - } else { - zend_fetch_dimension_address_W_ref(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC); - } + ZVAL_DEREF(container); + zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -39210,6 +39529,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HAND if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { @@ -39251,6 +39571,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_VAR_HANDLER(ZEND_OPCOD if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -39282,6 +39603,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_H if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { @@ -39292,7 +39614,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_H ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CV_VAR(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -39304,7 +39626,7 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CV_VAR(ZEN container = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { zend_error(E_NOTICE, "Trying to get property of non-object"); ZVAL_NULL(EX_VAR(opline->result.var)); @@ -39325,11 +39647,6 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CV_VAR(ZEN ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_property_address_read_helper_SPEC_CV_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -39345,7 +39662,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDL zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -39369,7 +39686,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HAND if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -39391,7 +39708,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HAND container = _get_zval_ptr_cv_deref_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -39431,7 +39748,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_VAR_HANDLER(ZEND_OPCOD if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -39440,7 +39757,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_VAR_HANDLER(ZEND_OPCOD CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { - return zend_fetch_property_address_read_helper_SPEC_CV_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return ZEND_FETCH_OBJ_R_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } @@ -39457,7 +39774,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_H if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -39481,7 +39798,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, IS_CV, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); /* assign_obj has two opcodes! */ @@ -39502,45 +39819,48 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - if (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) { - object_ptr = Z_REFVAL_P(object_ptr); - } - if (Z_TYPE_P(object_ptr) == IS_OBJECT) { + ZVAL_DEREF(object_ptr); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { zend_free_op free_op2; zval *property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_CV, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); } else { - zend_free_op free_op2, free_op_data1, free_op_data2; + zend_free_op free_op2, free_op_data1; + zval rv; zval *value; zval *dim = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); zval *variable_ptr; - variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_VAR TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2.var); - value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(variable_ptr != NULL)) { - zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) && + EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + zend_long offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + zend_assign_to_string_offset(object_ptr, offset, value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); + FREE_OP(free_op_data1); } else { - variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_VAR TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + variable_ptr = Z_INDIRECT(rv); if (UNEXPECTED(variable_ptr == &EG(error_zval))) { - if (IS_TMP_FREE(free_op_data1)) { - zval_dtor(value); - } + FREE_OP(free_op_data1); if (RETURN_VALUE_USED(opline)) { ZVAL_NULL(EX_VAR(opline->result.var)); } - FREE_OP_VAR_PTR(free_op_data2); } else { value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC); + if ((opline+1)->op1_type == IS_VAR) { + FREE_OP(free_op_data1); + } if (RETURN_VALUE_USED(opline)) { ZVAL_COPY(EX_VAR(opline->result.var), value); } - FREE_OP_VAR_PTR(free_op_data2); } } - FREE_OP_IF_VAR(free_op_data1); } /* assign_dim has two opcodes! */ @@ -39562,7 +39882,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) { if (IS_VAR == IS_TMP_VAR) { - zval_dtor(value); + zval_ptr_dtor_nogc(free_op2.var); } if (RETURN_VALUE_USED(opline)) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -39592,10 +39912,13 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE SAVE_OPLINE(); value_ptr = _get_zval_ptr_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); + } if (IS_VAR == IS_VAR && - opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF) && - !Z_ISREF_P(value_ptr)) { + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { if (!(free_op2.var != NULL)) { PZVAL_LOCK(value_ptr); /* undo the effect of get_zval_ptr_ptr() */ } @@ -39612,15 +39935,14 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE } variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); + } if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT) && UNEXPECTED(!Z_ISREF_P(variable_ptr))) { zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object"); } - if ((IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) || - (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == NULL))) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); - } if ((IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) || (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == &EG(error_zval)))) { variable_ptr = &EG(uninitialized_zval); @@ -39668,19 +39990,55 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_ object = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + uint32_t nesting = 1; + if (UNEXPECTED(EG(exception) != NULL)) { zval_ptr_dtor_nogc(free_op2.var); HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); + + zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); + zval_ptr_dtor_nogc(free_op2.var); + + if (EG(exception) != NULL) { + HANDLE_EXCEPTION(); + } + + /* No exception raised: Skip over arguments until fcall opcode with correct + * nesting level. Return NULL (except when return value unused) */ + do { + opline++; + if (opline->opcode == ZEND_INIT_FCALL || + opline->opcode == ZEND_INIT_FCALL_BY_NAME || + opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME || + opline->opcode == ZEND_INIT_METHOD_CALL || + opline->opcode == ZEND_INIT_STATIC_METHOD_CALL || + opline->opcode == ZEND_INIT_USER_CALL || + opline->opcode == ZEND_NEW + ) { + nesting++; + } else if (opline->opcode == ZEND_DO_FCALL) { + nesting--; + } + } while (nesting); + + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + /* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */ + if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) { + opline++; + } + ZEND_VM_JMP(++opline); } obj = Z_OBJ_P(object); - called_scope = zend_get_class_entry(obj TSRMLS_CC); + called_scope = obj->ce; if (IS_VAR != IS_CONST || - (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) { + EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { zend_object *orig_obj = obj; if (UNEXPECTED(obj->handlers->get_method == NULL)) { @@ -39690,7 +40048,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_ /* First, locate the function. */ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name)); + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); } if (IS_VAR == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -39700,14 +40058,14 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_ } } - if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { obj = NULL; } else { GC_REFCOUNT(obj)++; /* For $this pointer */ } - EX(call) = zend_vm_stack_push_call_frame( - fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_FUNCTION, + fbc, opline->extended_value, called_scope, obj, EX(call) TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); @@ -39884,8 +40242,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER ZVAL_UNDEF(&tmp); if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { - ZVAL_DUP(&tmp, varname); - convert_to_string(&tmp); + ZVAL_STR(&tmp, zval_get_string(varname)); varname = &tmp; } @@ -39945,71 +40302,66 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER } offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - switch (Z_TYPE_P(container)) { - case IS_ARRAY: { - HashTable *ht = Z_ARRVAL_P(container); + if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht = Z_ARRVAL_P(container); offset_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - zend_hash_index_del(ht, hval); - break; - case IS_LONG: - hval = Z_LVAL_P(offset); + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_LONG: + hval = Z_LVAL_P(offset); num_index_dim: - zend_hash_index_del(ht, hval); - break; - case IS_STRING: - if (IS_VAR != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { - goto num_index_dim; - } - } - if (ht == &EG(symbol_table).ht) { - zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); - } else { - zend_hash_del(ht, Z_STR_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_STRING: + if (IS_VAR != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { + goto num_index_dim; } - break; - case IS_NULL: - zend_hash_del(ht, STR_EMPTY_ALLOC()); - break; - case IS_FALSE: - hval = 0; - goto num_index_dim; - case IS_TRUE: - hval = 1; - goto num_index_dim; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_dim; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto offset_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type in unset"); - break; - } - zval_ptr_dtor_nogc(free_op2.var); - break; + } + if (ht == &EG(symbol_table).ht) { + zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); + } else { + zend_hash_del(ht, Z_STR_P(offset)); + } + break; + case IS_NULL: + zend_hash_del(ht, STR_EMPTY_ALLOC()); + break; + case IS_FALSE: + hval = 0; + goto num_index_dim; + case IS_TRUE: + hval = 1; + goto num_index_dim; + case IS_RESOURCE: + hval = Z_RES_HANDLE_P(offset); + goto num_index_dim; + case IS_REFERENCE: + offset = Z_REFVAL_P(offset); + goto offset_again; + break; + default: + zend_error(E_WARNING, "Illegal offset type in unset"); + break; } - case IS_OBJECT: - if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use object as array"); - } -//??? if (IS_VAR == IS_CONST) { -//??? zval_copy_ctor(offset); -//??? } - Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2.var); - break; - case IS_STRING: - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - ZEND_VM_CONTINUE(); /* bailed out before */ - default: - zval_ptr_dtor_nogc(free_op2.var); - break; + zval_ptr_dtor_nogc(free_op2.var); + } else if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use object as array"); + } +//??? if (IS_VAR == IS_CONST) { +//??? zval_copy_ctor(offset); +//??? } + Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + ZEND_VM_CONTINUE(); /* bailed out before */ + } else { + zval_ptr_dtor_nogc(free_op2.var); } CHECK_EXCEPTION(); @@ -40031,7 +40383,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); ZVAL_DEREF(container); - if (Z_TYPE_P(container) == IS_OBJECT) { + if (IS_CV == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->unset_property) { Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { @@ -40048,26 +40400,28 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE { USE_OPLINE zval *value; - zend_bool isset = 1; SAVE_OPLINE(); if (IS_CV == IS_CV && IS_VAR == IS_UNUSED && (opline->extended_value & ZEND_QUICK_SET)) { - if (Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_UNDEF) { - value = EX_VAR(opline->op1.var); - ZVAL_DEREF(value); - } else { - isset = 0; + value = EX_VAR(opline->op1.var); + if (opline->extended_value & ZEND_ISSET) { + ZVAL_BOOL(EX_VAR(opline->result.var), + Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + ZVAL_BOOL(EX_VAR(opline->result.var), + !i_zend_is_true(value TSRMLS_CC)); + CHECK_EXCEPTION(); } + ZEND_VM_NEXT_OPCODE(); } else { - HashTable *target_symbol_table; zval tmp, *varname = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { - ZVAL_DUP(&tmp, varname); - convert_to_string(&tmp); + ZVAL_STR(&tmp, zval_get_string(varname)); varname = &tmp; } @@ -40089,39 +40443,27 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE ce = Z_CE_P(EX_VAR(opline->op2.var)); } value = zend_std_get_static_property(ce, Z_STR_P(varname), 1, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); - if (!value) { - isset = 0; - } } else { - target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); - if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) { - isset = 0; - } + HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname)); } if (IS_CV != IS_CONST && varname == &tmp) { zval_dtor(&tmp); } - } - - if (opline->extended_value & ZEND_ISSET) { - if (isset && Z_TYPE_P(value) != IS_NULL && - (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) { - ZVAL_BOOL(EX_VAR(opline->result.var), 1); - } else { - ZVAL_BOOL(EX_VAR(opline->result.var), 0); - } - } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { - if (!isset || !i_zend_is_true(value TSRMLS_CC)) { - ZVAL_BOOL(EX_VAR(opline->result.var), 1); - } else { - ZVAL_BOOL(EX_VAR(opline->result.var), 0); + if (opline->extended_value & ZEND_ISSET) { + ZVAL_BOOL(EX_VAR(opline->result.var), + value && Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + ZVAL_BOOL(EX_VAR(opline->result.var), + !value || !i_zend_is_true(value TSRMLS_CC)); } - } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } } static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -40137,7 +40479,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_VAR_HANDLER(ZEND_OP container = _get_zval_ptr_cv_deref_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (Z_TYPE_P(container) == IS_ARRAY) { + if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { HashTable *ht = Z_ARRVAL_P(container); zval *value; zend_string *str; @@ -40190,8 +40532,8 @@ num_index_prop: } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); } - } else if (Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->has_dimension) { + } else if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to check element of non-array"); @@ -40200,7 +40542,7 @@ num_index_prop: if ((opline->extended_value & ZEND_ISSET) == 0) { result = !result; } - } else if (Z_TYPE_P(container) == IS_STRING) { /* string offsets */ + } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */ zval tmp; result = 0; @@ -40216,7 +40558,7 @@ num_index_prop: offset = &tmp; } } - if (Z_TYPE_P(offset) == IS_LONG) { + if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) { if ((opline->extended_value & ZEND_ISSET) || Z_STRVAL_P(container)[offset->value.lval] != '0') { @@ -40250,8 +40592,8 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_VAR_HANDLER(ZEND_O container = _get_zval_ptr_cv_deref_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->has_property) { + if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_property)) { result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to check property of non-object"); @@ -40271,6 +40613,45 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_VAR_HANDLER(ZEND_O ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *expr; + zend_bool result; + + SAVE_OPLINE(); + expr = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + + if (Z_TYPE_P(expr) == IS_OBJECT) { + zend_class_entry *ce; + + if (IS_VAR == IS_CONST) { + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC); + if (UNEXPECTED(ce == NULL)) { + ZVAL_FALSE(EX_VAR(opline->result.var)); + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op2.var)); + } + result = instanceof_function(Z_OBJCE_P(expr), ce TSRMLS_CC); + } else { + result = 0; + } + ZVAL_BOOL(EX_VAR(opline->result.var), result); + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -40306,7 +40687,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG /* Temporary variables don't need ctor copying */ if (IS_CV != IS_TMP_VAR) { - zval_copy_ctor(&generator->value); + zval_opt_copy_ctor(&generator->value); } } else { zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); @@ -40317,9 +40698,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_CV == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_CV == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -40428,17 +40810,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(int (*b zval *object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); zval *property = NULL; zval *value; - int have_get_ptr = 0; + zval *zptr; if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - object = make_real_object(object TSRMLS_CC); + if (IS_CV != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); + } - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to assign property of non-object"); FREE_OP(free_op_data1); @@ -40449,20 +40833,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(int (*b } else { /* here we are sure we are dealing with an object */ if (opline->extended_value == ZEND_ASSIGN_OBJ - && Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_UNUSED == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - SEPARATE_ZVAL_IF_NOT_REF(zptr); + && EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_UNUSED == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - have_get_ptr = 1; - binary_op(zptr, zptr, value TSRMLS_CC); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), zptr); - } - } - } + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + binary_op(zptr, zptr, value TSRMLS_CC); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); + } + } else { zval *z = NULL; zval rv; @@ -40517,15 +40898,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(int (*b static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data2, free_op_data1; - zval *var_ptr; + zend_free_op free_op_data1; + zval *var_ptr, rv; zval *value, *container; SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } + if (IS_CV != IS_UNUSED) { + ZVAL_DEREF(container); + } + if (IS_CV == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_CV == IS_VAR && !0) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } @@ -40533,9 +40918,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(int (*b } else { zval *dim = NULL; - zend_fetch_dimension_address_RW(EX_VAR((opline+1)->op2.var), container, dim, IS_UNUSED TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + zend_fetch_dimension_address_RW(&rv, container, dim, IS_UNUSED TSRMLS_CC); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); } if (UNEXPECTED(var_ptr == NULL)) { @@ -40546,33 +40932,18 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(int (*b if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_dim_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_dim_exit: - FREE_OP(free_op_data1); - FREE_OP_VAR_PTR(free_op_data2); CHECK_EXCEPTION(); ZEND_VM_INC_OPCODE(); @@ -40598,31 +40969,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_UNUSED(int (*binar if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_exit: - CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -40877,9 +41234,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_UNUSED(int type, } ZVAL_COPY(EX_VAR(opline->result.var), retval); } else { - if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) { - ZVAL_MAKE_REF(retval); - } ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); } CHECK_EXCEPTION(); @@ -40934,11 +41288,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HA if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - if (EXPECTED(opline->extended_value == 0)) { - zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC); - } else { - zend_fetch_dimension_address_W_ref(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC); - } + ZVAL_DEREF(container); + zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -40960,6 +41311,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_H if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { @@ -40986,6 +41338,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_UNUSED_HANDLER(ZEND_OP if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -41017,45 +41370,48 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HAN if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - if (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) { - object_ptr = Z_REFVAL_P(object_ptr); - } - if (Z_TYPE_P(object_ptr) == IS_OBJECT) { + ZVAL_DEREF(object_ptr); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { zval *property_name = NULL; - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_UNUSED == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_CV, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_UNUSED == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); } else { - zend_free_op free_op_data1, free_op_data2; + zend_free_op free_op_data1; + zval rv; zval *value; zval *dim = NULL; zval *variable_ptr; - variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_UNUSED TSRMLS_CC); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) && + EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + zend_long offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W TSRMLS_CC); - value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(variable_ptr != NULL)) { - zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + zend_assign_to_string_offset(object_ptr, offset, value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); + FREE_OP(free_op_data1); } else { - variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_UNUSED TSRMLS_CC); + + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + variable_ptr = Z_INDIRECT(rv); if (UNEXPECTED(variable_ptr == &EG(error_zval))) { - if (IS_TMP_FREE(free_op_data1)) { - zval_dtor(value); - } + FREE_OP(free_op_data1); if (RETURN_VALUE_USED(opline)) { ZVAL_NULL(EX_VAR(opline->result.var)); } - FREE_OP_VAR_PTR(free_op_data2); } else { value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC); + if ((opline+1)->op1_type == IS_VAR) { + FREE_OP(free_op_data1); + } if (RETURN_VALUE_USED(opline)) { ZVAL_COPY(EX_VAR(opline->result.var), value); } - FREE_OP_VAR_PTR(free_op_data2); } } - FREE_OP_IF_VAR(free_op_data1); } /* assign_dim has two opcodes! */ @@ -41217,8 +41573,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HAND ZVAL_UNDEF(&tmp); if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { - ZVAL_DUP(&tmp, varname); - convert_to_string(&tmp); + ZVAL_STR(&tmp, zval_get_string(varname)); varname = &tmp; } @@ -41263,26 +41618,28 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPC { USE_OPLINE zval *value; - zend_bool isset = 1; SAVE_OPLINE(); if (IS_CV == IS_CV && IS_UNUSED == IS_UNUSED && (opline->extended_value & ZEND_QUICK_SET)) { - if (Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_UNDEF) { - value = EX_VAR(opline->op1.var); - ZVAL_DEREF(value); - } else { - isset = 0; + value = EX_VAR(opline->op1.var); + if (opline->extended_value & ZEND_ISSET) { + ZVAL_BOOL(EX_VAR(opline->result.var), + Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + ZVAL_BOOL(EX_VAR(opline->result.var), + !i_zend_is_true(value TSRMLS_CC)); + CHECK_EXCEPTION(); } + ZEND_VM_NEXT_OPCODE(); } else { - HashTable *target_symbol_table; zval tmp, *varname = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { - ZVAL_DUP(&tmp, varname); - convert_to_string(&tmp); + ZVAL_STR(&tmp, zval_get_string(varname)); varname = &tmp; } @@ -41304,39 +41661,27 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPC ce = Z_CE_P(EX_VAR(opline->op2.var)); } value = zend_std_get_static_property(ce, Z_STR_P(varname), 1, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(varname)) : NULL) TSRMLS_CC); - if (!value) { - isset = 0; - } } else { - target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); - if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) { - isset = 0; - } + HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); + value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname)); } if (IS_CV != IS_CONST && varname == &tmp) { zval_dtor(&tmp); } - } - - if (opline->extended_value & ZEND_ISSET) { - if (isset && Z_TYPE_P(value) != IS_NULL && - (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) { - ZVAL_BOOL(EX_VAR(opline->result.var), 1); - } else { - ZVAL_BOOL(EX_VAR(opline->result.var), 0); - } - } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { - if (!isset || !i_zend_is_true(value TSRMLS_CC)) { - ZVAL_BOOL(EX_VAR(opline->result.var), 1); - } else { - ZVAL_BOOL(EX_VAR(opline->result.var), 0); + if (opline->extended_value & ZEND_ISSET) { + ZVAL_BOOL(EX_VAR(opline->result.var), + value && Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + ZVAL_BOOL(EX_VAR(opline->result.var), + !value || !i_zend_is_true(value TSRMLS_CC)); } - } - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } } static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -41374,7 +41719,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ /* Temporary variables don't need ctor copying */ if (IS_CV != IS_TMP_VAR) { - zval_copy_ctor(&generator->value); + zval_opt_copy_ctor(&generator->value); } } else { zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); @@ -41385,9 +41730,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_CV == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_CV == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -41756,17 +42102,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CV(int (*binar zval *object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); zval *property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); zval *value; - int have_get_ptr = 0; + zval *zptr; if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - object = make_real_object(object TSRMLS_CC); + if (IS_CV != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); + } - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to assign property of non-object"); FREE_OP(free_op_data1); @@ -41777,20 +42125,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CV(int (*binar } else { /* here we are sure we are dealing with an object */ if (opline->extended_value == ZEND_ASSIGN_OBJ - && Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - SEPARATE_ZVAL_IF_NOT_REF(zptr); + && EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - have_get_ptr = 1; - binary_op(zptr, zptr, value TSRMLS_CC); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), zptr); - } - } - } + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + binary_op(zptr, zptr, value TSRMLS_CC); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); + } + } else { zval *z = NULL; zval rv; @@ -41845,15 +42190,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CV(int (*binar static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_CV(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data2, free_op_data1; - zval *var_ptr; + zend_free_op free_op_data1; + zval *var_ptr, rv; zval *value, *container; SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } + if (IS_CV != IS_UNUSED) { + ZVAL_DEREF(container); + } + if (IS_CV == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_CV == IS_VAR && !0) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } @@ -41861,9 +42210,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_CV(int (*binar } else { zval *dim = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - zend_fetch_dimension_address_RW(EX_VAR((opline+1)->op2.var), container, dim, IS_CV TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + zend_fetch_dimension_address_RW(&rv, container, dim, IS_CV TSRMLS_CC); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); } if (UNEXPECTED(var_ptr == NULL)) { @@ -41874,33 +42224,18 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_CV(int (*binar if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_dim_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_dim_exit: - FREE_OP(free_op_data1); - FREE_OP_VAR_PTR(free_op_data2); CHECK_EXCEPTION(); ZEND_VM_INC_OPCODE(); @@ -41915,7 +42250,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_CV(int (*binary_op zval *value; SAVE_OPLINE(); - value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + value = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) { @@ -41926,31 +42261,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_CV(int (*binary_op if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_exit: - CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -42106,7 +42427,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CV(incdec_t inc zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); @@ -42117,9 +42438,11 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CV(incdec_t inc zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_CV != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); if (RETURN_VALUE_USED(opline)) { @@ -42132,20 +42455,17 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CV(incdec_t inc /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - SEPARATE_ZVAL_IF_NOT_REF(zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - have_get_ptr = 1; - incdec_op(zptr); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(retval, zptr); - } - } - } + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + incdec_op(zptr); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(retval, zptr); + } + } else { zval rv; if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { @@ -42197,7 +42517,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CV(incdec_t in zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); @@ -42208,9 +42528,11 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CV(incdec_t in zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + if (IS_CV != IS_UNUSED) { + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); ZVAL_NULL(retval); @@ -42221,20 +42543,15 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CV(incdec_t in /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - have_get_ptr = 1; - SEPARATE_ZVAL_IF_NOT_REF(zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - ZVAL_DUP(retval, zptr); - - incdec_op(zptr); - - } - } + ZVAL_DEREF(zptr); + ZVAL_COPY(retval, zptr); - if (!have_get_ptr) { + SEPARATE_ZVAL_NOREF(zptr); + incdec_op(zptr); + } else { if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { zval rv; zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); @@ -42287,9 +42604,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLE container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); - if (IS_CV != IS_VAR || !(opline->extended_value & ZEND_FETCH_ADD_LOCK)) { - } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -42306,11 +42621,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLE if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - if (EXPECTED(opline->extended_value == 0)) { - zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); - } else { - zend_fetch_dimension_address_W_ref(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); - } + ZVAL_DEREF(container); + zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -42332,6 +42644,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDL if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { @@ -42373,6 +42686,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CV_HANDLER(ZEND_OPCODE if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -42404,6 +42718,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HA if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { @@ -42414,7 +42729,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HA ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CV_CV(ZEND_OPCODE_HANDLER_ARGS) +static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -42426,7 +42741,7 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CV_CV(ZEND container = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { zend_error(E_NOTICE, "Trying to get property of non-object"); ZVAL_NULL(EX_VAR(opline->result.var)); @@ -42446,11 +42761,6 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CV_CV(ZEND ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - return zend_fetch_property_address_read_helper_SPEC_CV_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -42466,7 +42776,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLE zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -42490,7 +42800,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDL if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -42512,7 +42822,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDL container = _get_zval_ptr_cv_deref_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + if ((IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -42551,7 +42861,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CV_HANDLER(ZEND_OPCODE if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -42560,7 +42870,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CV_HANDLER(ZEND_OPCODE CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { - return zend_fetch_property_address_read_helper_SPEC_CV_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return ZEND_FETCH_OBJ_R_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } @@ -42577,7 +42887,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HA if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -42601,7 +42911,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, IS_CV, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); /* assign_obj has two opcodes! */ @@ -42622,45 +42932,48 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - if (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) { - object_ptr = Z_REFVAL_P(object_ptr); - } - if (Z_TYPE_P(object_ptr) == IS_OBJECT) { + ZVAL_DEREF(object_ptr); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { zval *property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_CV, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); } else { - zend_free_op free_op_data1, free_op_data2; + zend_free_op free_op_data1; + zval rv; zval *value; zval *dim = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); zval *variable_ptr; - variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_CV TSRMLS_CC); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) && + EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + zend_long offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W TSRMLS_CC); - value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(variable_ptr != NULL)) { - zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + zend_assign_to_string_offset(object_ptr, offset, value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); + FREE_OP(free_op_data1); } else { - variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_CV TSRMLS_CC); + + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + variable_ptr = Z_INDIRECT(rv); if (UNEXPECTED(variable_ptr == &EG(error_zval))) { - if (IS_TMP_FREE(free_op_data1)) { - zval_dtor(value); - } + FREE_OP(free_op_data1); if (RETURN_VALUE_USED(opline)) { ZVAL_NULL(EX_VAR(opline->result.var)); } - FREE_OP_VAR_PTR(free_op_data2); } else { value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC); + if ((opline+1)->op1_type == IS_VAR) { + FREE_OP(free_op_data1); + } if (RETURN_VALUE_USED(opline)) { ZVAL_COPY(EX_VAR(opline->result.var), value); } - FREE_OP_VAR_PTR(free_op_data2); } } - FREE_OP_IF_VAR(free_op_data1); } /* assign_dim has two opcodes! */ @@ -42682,7 +42995,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) { if (IS_CV == IS_TMP_VAR) { - zval_dtor(value); + } if (RETURN_VALUE_USED(opline)) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -42711,10 +43024,13 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op2.var TSRMLS_CC); + if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); + } if (IS_CV == IS_VAR && - opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF) && - !Z_ISREF_P(value_ptr)) { + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { if (!0) { PZVAL_LOCK(value_ptr); /* undo the effect of get_zval_ptr_ptr() */ } @@ -42731,15 +43047,14 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER } variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); + } if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT) && UNEXPECTED(!Z_ISREF_P(variable_ptr))) { zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object"); } - if ((IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) || - (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == NULL))) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); - } if ((IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) || (IS_CV == IS_VAR && UNEXPECTED(value_ptr == &EG(error_zval)))) { variable_ptr = &EG(uninitialized_zval); @@ -42786,19 +43101,55 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_H object = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + uint32_t nesting = 1; + if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); + + zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); + + + if (EG(exception) != NULL) { + HANDLE_EXCEPTION(); + } + + /* No exception raised: Skip over arguments until fcall opcode with correct + * nesting level. Return NULL (except when return value unused) */ + do { + opline++; + if (opline->opcode == ZEND_INIT_FCALL || + opline->opcode == ZEND_INIT_FCALL_BY_NAME || + opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME || + opline->opcode == ZEND_INIT_METHOD_CALL || + opline->opcode == ZEND_INIT_STATIC_METHOD_CALL || + opline->opcode == ZEND_INIT_USER_CALL || + opline->opcode == ZEND_NEW + ) { + nesting++; + } else if (opline->opcode == ZEND_DO_FCALL) { + nesting--; + } + } while (nesting); + + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + /* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */ + if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) { + opline++; + } + ZEND_VM_JMP(++opline); } obj = Z_OBJ_P(object); - called_scope = zend_get_class_entry(obj TSRMLS_CC); + called_scope = obj->ce; if (IS_CV != IS_CONST || - (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) { + EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) { zend_object *orig_obj = obj; if (UNEXPECTED(obj->handlers->get_method == NULL)) { @@ -42808,7 +43159,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_H /* First, locate the function. */ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name)); + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); } if (IS_CV == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -42818,14 +43169,14 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_H } } - if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { obj = NULL; } else { GC_REFCOUNT(obj)++; /* For $this pointer */ } - EX(call) = zend_vm_stack_push_call_frame( - fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame(VM_FRAME_NESTED_FUNCTION, + fbc, opline->extended_value, called_scope, obj, EX(call) TSRMLS_CC); CHECK_EXCEPTION(); @@ -42985,71 +43336,66 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ } offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - switch (Z_TYPE_P(container)) { - case IS_ARRAY: { - HashTable *ht = Z_ARRVAL_P(container); + if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht = Z_ARRVAL_P(container); offset_again: - switch (Z_TYPE_P(offset)) { - case IS_DOUBLE: - hval = zend_dval_to_lval(Z_DVAL_P(offset)); - zend_hash_index_del(ht, hval); - break; - case IS_LONG: - hval = Z_LVAL_P(offset); + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_LONG: + hval = Z_LVAL_P(offset); num_index_dim: - zend_hash_index_del(ht, hval); - break; - case IS_STRING: - if (IS_CV != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { - goto num_index_dim; - } - } - if (ht == &EG(symbol_table).ht) { - zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); - } else { - zend_hash_del(ht, Z_STR_P(offset)); + zend_hash_index_del(ht, hval); + break; + case IS_STRING: + if (IS_CV != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) { + goto num_index_dim; } - break; - case IS_NULL: - zend_hash_del(ht, STR_EMPTY_ALLOC()); - break; - case IS_FALSE: - hval = 0; - goto num_index_dim; - case IS_TRUE: - hval = 1; - goto num_index_dim; - case IS_RESOURCE: - hval = Z_RES_HANDLE_P(offset); - goto num_index_dim; - case IS_REFERENCE: - offset = Z_REFVAL_P(offset); - goto offset_again; - break; - default: - zend_error(E_WARNING, "Illegal offset type in unset"); - break; - } + } + if (ht == &EG(symbol_table).ht) { + zend_delete_global_variable(Z_STR_P(offset) TSRMLS_CC); + } else { + zend_hash_del(ht, Z_STR_P(offset)); + } + break; + case IS_NULL: + zend_hash_del(ht, STR_EMPTY_ALLOC()); + break; + case IS_FALSE: + hval = 0; + goto num_index_dim; + case IS_TRUE: + hval = 1; + goto num_index_dim; + case IS_RESOURCE: + hval = Z_RES_HANDLE_P(offset); + goto num_index_dim; + case IS_REFERENCE: + offset = Z_REFVAL_P(offset); + goto offset_again; + break; + default: + zend_error(E_WARNING, "Illegal offset type in unset"); + break; + } - break; + } else if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot use object as array"); } - case IS_OBJECT: - if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use object as array"); - } -//??? if (IS_CV == IS_CONST) { -//??? zval_copy_ctor(offset); -//??? } - Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); +//??? if (IS_CV == IS_CONST) { +//??? zval_copy_ctor(offset); +//??? } + Z_OBJ_HT_P(container)->unset_dimension(container, offset TSRMLS_CC); - break; - case IS_STRING: - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - ZEND_VM_CONTINUE(); /* bailed out before */ - default: + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + ZEND_VM_CONTINUE(); /* bailed out before */ + } else { - break; } CHECK_EXCEPTION(); @@ -43071,7 +43417,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); ZVAL_DEREF(container); - if (Z_TYPE_P(container) == IS_OBJECT) { + if (IS_CV == IS_UNUSED || Z_TYPE_P(container) == IS_OBJECT) { if (Z_OBJ_HT_P(container)->unset_property) { Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { @@ -43097,7 +43443,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPC container = _get_zval_ptr_cv_deref_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (Z_TYPE_P(container) == IS_ARRAY) { + if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { HashTable *ht = Z_ARRVAL_P(container); zval *value; zend_string *str; @@ -43150,8 +43496,8 @@ num_index_prop: } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); } - } else if (Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->has_dimension) { + } else if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) { result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to check element of non-array"); @@ -43160,7 +43506,7 @@ num_index_prop: if ((opline->extended_value & ZEND_ISSET) == 0) { result = !result; } - } else if (Z_TYPE_P(container) == IS_STRING) { /* string offsets */ + } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */ zval tmp; result = 0; @@ -43176,7 +43522,7 @@ num_index_prop: offset = &tmp; } } - if (Z_TYPE_P(offset) == IS_LONG) { + if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) { if ((opline->extended_value & ZEND_ISSET) || Z_STRVAL_P(container)[offset->value.lval] != '0') { @@ -43209,8 +43555,8 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_CV_HANDLER(ZEND_OP container = _get_zval_ptr_cv_deref_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (Z_TYPE_P(container) == IS_OBJECT) { - if (Z_OBJ_HT_P(container)->has_property) { + if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (EXPECTED(Z_OBJ_HT_P(container)->has_property)) { result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC); } else { zend_error(E_NOTICE, "Trying to check property of non-object"); @@ -43264,7 +43610,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS /* Temporary variables don't need ctor copying */ if (IS_CV != IS_TMP_VAR) { - zval_copy_ctor(&generator->value); + zval_opt_copy_ctor(&generator->value); } } else { zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); @@ -43275,9 +43621,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_CV == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_CV == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -44624,11 +44971,11 @@ void zend_init_opcodes_handlers(void) ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, - ZEND_SWITCH_FREE_SPEC_VAR_HANDLER, - ZEND_SWITCH_FREE_SPEC_VAR_HANDLER, - ZEND_SWITCH_FREE_SPEC_VAR_HANDLER, - ZEND_SWITCH_FREE_SPEC_VAR_HANDLER, - ZEND_SWITCH_FREE_SPEC_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, @@ -44714,31 +45061,31 @@ void zend_init_opcodes_handlers(void) ZEND_BOOL_SPEC_CV_HANDLER, ZEND_BOOL_SPEC_CV_HANDLER, ZEND_BOOL_SPEC_CV_HANDLER, - ZEND_INIT_STRING_SPEC_HANDLER, - ZEND_INIT_STRING_SPEC_HANDLER, - ZEND_INIT_STRING_SPEC_HANDLER, - ZEND_INIT_STRING_SPEC_HANDLER, - ZEND_INIT_STRING_SPEC_HANDLER, - ZEND_INIT_STRING_SPEC_HANDLER, - ZEND_INIT_STRING_SPEC_HANDLER, - ZEND_INIT_STRING_SPEC_HANDLER, - ZEND_INIT_STRING_SPEC_HANDLER, - ZEND_INIT_STRING_SPEC_HANDLER, - ZEND_INIT_STRING_SPEC_HANDLER, - ZEND_INIT_STRING_SPEC_HANDLER, - ZEND_INIT_STRING_SPEC_HANDLER, - ZEND_INIT_STRING_SPEC_HANDLER, - ZEND_INIT_STRING_SPEC_HANDLER, - ZEND_INIT_STRING_SPEC_HANDLER, - ZEND_INIT_STRING_SPEC_HANDLER, - ZEND_INIT_STRING_SPEC_HANDLER, - ZEND_INIT_STRING_SPEC_HANDLER, - ZEND_INIT_STRING_SPEC_HANDLER, - ZEND_INIT_STRING_SPEC_HANDLER, - ZEND_INIT_STRING_SPEC_HANDLER, - ZEND_INIT_STRING_SPEC_HANDLER, - ZEND_INIT_STRING_SPEC_HANDLER, - ZEND_INIT_STRING_SPEC_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, @@ -45089,31 +45436,31 @@ void zend_init_opcodes_handlers(void) ZEND_SEND_REF_SPEC_CV_HANDLER, ZEND_SEND_REF_SPEC_CV_HANDLER, ZEND_SEND_REF_SPEC_CV_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, + ZEND_NEW_SPEC_CONST_HANDLER, + ZEND_NEW_SPEC_CONST_HANDLER, + ZEND_NEW_SPEC_CONST_HANDLER, + ZEND_NEW_SPEC_CONST_HANDLER, + ZEND_NEW_SPEC_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NEW_SPEC_VAR_HANDLER, + ZEND_NEW_SPEC_VAR_HANDLER, + ZEND_NEW_SPEC_VAR_HANDLER, + ZEND_NEW_SPEC_VAR_HANDLER, + ZEND_NEW_SPEC_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, ZEND_INIT_NS_FCALL_BY_NAME_SPEC_CONST_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, @@ -45839,18 +46186,17 @@ void zend_init_opcodes_handlers(void) ZEND_FETCH_OBJ_UNSET_SPEC_CV_VAR_HANDLER, ZEND_NULL_HANDLER, ZEND_FETCH_OBJ_UNSET_SPEC_CV_CV_HANDLER, - ZEND_FETCH_DIM_TMP_VAR_SPEC_CONST_CONST_HANDLER, - ZEND_NULL_HANDLER, + ZEND_FETCH_LIST_SPEC_CONST_CONST_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, - ZEND_FETCH_DIM_TMP_VAR_SPEC_TMP_CONST_HANDLER, - ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, + ZEND_FETCH_LIST_SPEC_TMP_CONST_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, + ZEND_FETCH_LIST_SPEC_VAR_CONST_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, @@ -45860,6 +46206,7 @@ void zend_init_opcodes_handlers(void) ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, + ZEND_FETCH_LIST_SPEC_CV_CONST_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, @@ -46844,26 +47191,26 @@ void zend_init_opcodes_handlers(void) ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, - ZEND_INSTANCEOF_SPEC_TMP_HANDLER, - ZEND_INSTANCEOF_SPEC_TMP_HANDLER, - ZEND_INSTANCEOF_SPEC_TMP_HANDLER, - ZEND_INSTANCEOF_SPEC_TMP_HANDLER, - ZEND_INSTANCEOF_SPEC_TMP_HANDLER, - ZEND_INSTANCEOF_SPEC_VAR_HANDLER, - ZEND_INSTANCEOF_SPEC_VAR_HANDLER, - ZEND_INSTANCEOF_SPEC_VAR_HANDLER, - ZEND_INSTANCEOF_SPEC_VAR_HANDLER, - ZEND_INSTANCEOF_SPEC_VAR_HANDLER, + ZEND_INSTANCEOF_SPEC_TMP_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_INSTANCEOF_SPEC_TMP_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_INSTANCEOF_SPEC_VAR_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_INSTANCEOF_SPEC_VAR_VAR_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, - ZEND_INSTANCEOF_SPEC_CV_HANDLER, - ZEND_INSTANCEOF_SPEC_CV_HANDLER, - ZEND_INSTANCEOF_SPEC_CV_HANDLER, - ZEND_INSTANCEOF_SPEC_CV_HANDLER, - ZEND_INSTANCEOF_SPEC_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_INSTANCEOF_SPEC_CV_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_INSTANCEOF_SPEC_CV_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, ZEND_DECLARE_CLASS_SPEC_HANDLER, ZEND_DECLARE_CLASS_SPEC_HANDLER, ZEND_DECLARE_CLASS_SPEC_HANDLER, @@ -46939,31 +47286,31 @@ void zend_init_opcodes_handlers(void) ZEND_DECLARE_FUNCTION_SPEC_HANDLER, ZEND_DECLARE_FUNCTION_SPEC_HANDLER, ZEND_DECLARE_FUNCTION_SPEC_HANDLER, - ZEND_RAISE_ABSTRACT_ERROR_SPEC_HANDLER, - ZEND_RAISE_ABSTRACT_ERROR_SPEC_HANDLER, - ZEND_RAISE_ABSTRACT_ERROR_SPEC_HANDLER, - ZEND_RAISE_ABSTRACT_ERROR_SPEC_HANDLER, - ZEND_RAISE_ABSTRACT_ERROR_SPEC_HANDLER, - ZEND_RAISE_ABSTRACT_ERROR_SPEC_HANDLER, - ZEND_RAISE_ABSTRACT_ERROR_SPEC_HANDLER, - ZEND_RAISE_ABSTRACT_ERROR_SPEC_HANDLER, - ZEND_RAISE_ABSTRACT_ERROR_SPEC_HANDLER, - ZEND_RAISE_ABSTRACT_ERROR_SPEC_HANDLER, - ZEND_RAISE_ABSTRACT_ERROR_SPEC_HANDLER, - ZEND_RAISE_ABSTRACT_ERROR_SPEC_HANDLER, - ZEND_RAISE_ABSTRACT_ERROR_SPEC_HANDLER, - ZEND_RAISE_ABSTRACT_ERROR_SPEC_HANDLER, - ZEND_RAISE_ABSTRACT_ERROR_SPEC_HANDLER, - ZEND_RAISE_ABSTRACT_ERROR_SPEC_HANDLER, - ZEND_RAISE_ABSTRACT_ERROR_SPEC_HANDLER, - ZEND_RAISE_ABSTRACT_ERROR_SPEC_HANDLER, - ZEND_RAISE_ABSTRACT_ERROR_SPEC_HANDLER, - ZEND_RAISE_ABSTRACT_ERROR_SPEC_HANDLER, - ZEND_RAISE_ABSTRACT_ERROR_SPEC_HANDLER, - ZEND_RAISE_ABSTRACT_ERROR_SPEC_HANDLER, - ZEND_RAISE_ABSTRACT_ERROR_SPEC_HANDLER, - ZEND_RAISE_ABSTRACT_ERROR_SPEC_HANDLER, - ZEND_RAISE_ABSTRACT_ERROR_SPEC_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, @@ -47614,6 +47961,31 @@ void zend_init_opcodes_handlers(void) ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, + ZEND_COALESCE_SPEC_CONST_HANDLER, + ZEND_COALESCE_SPEC_CONST_HANDLER, + ZEND_COALESCE_SPEC_CONST_HANDLER, + ZEND_COALESCE_SPEC_CONST_HANDLER, + ZEND_COALESCE_SPEC_CONST_HANDLER, + ZEND_COALESCE_SPEC_TMP_HANDLER, + ZEND_COALESCE_SPEC_TMP_HANDLER, + ZEND_COALESCE_SPEC_TMP_HANDLER, + ZEND_COALESCE_SPEC_TMP_HANDLER, + ZEND_COALESCE_SPEC_TMP_HANDLER, + ZEND_COALESCE_SPEC_VAR_HANDLER, + ZEND_COALESCE_SPEC_VAR_HANDLER, + ZEND_COALESCE_SPEC_VAR_HANDLER, + ZEND_COALESCE_SPEC_VAR_HANDLER, + ZEND_COALESCE_SPEC_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_COALESCE_SPEC_CV_HANDLER, + ZEND_COALESCE_SPEC_CV_HANDLER, + ZEND_COALESCE_SPEC_CV_HANDLER, + ZEND_COALESCE_SPEC_CV_HANDLER, + ZEND_COALESCE_SPEC_CV_HANDLER, ZEND_NULL_HANDLER }; zend_opcode_handlers = (opcode_handler_t*)labels; diff --git a/Zend/zend_vm_execute.skl b/Zend/zend_vm_execute.skl index 58cbe09787..03ed7ca65e 100644 --- a/Zend/zend_vm_execute.skl +++ b/Zend/zend_vm_execute.skl @@ -34,15 +34,15 @@ ZEND_API void zend_{%EXECUTOR_NAME%}(zend_op_array *op_array, zval *return_value return; } - execute_data = zend_vm_stack_push_call_frame( - (zend_function*)op_array, 0, 0, EG(current_execute_data) ? EG(current_execute_data)->called_scope : NULL, Z_OBJ(EG(This)), NULL TSRMLS_CC); + execute_data = zend_vm_stack_push_call_frame(VM_FRAME_TOP_CODE, + (zend_function*)op_array, 0, EG(current_execute_data) ? EG(current_execute_data)->called_scope : NULL, EG(current_execute_data) ? Z_OBJ(EG(current_execute_data)->This) : NULL, NULL TSRMLS_CC); if (EG(current_execute_data)) { execute_data->symbol_table = zend_rebuild_symbol_table(TSRMLS_C); } else { execute_data->symbol_table = &EG(symbol_table); } EX(prev_execute_data) = EG(current_execute_data); - i_init_execute_data(execute_data, op_array, return_value, VM_FRAME_TOP_CODE TSRMLS_CC); + i_init_execute_data(execute_data, op_array, return_value TSRMLS_CC); zend_{%EXECUTOR_NAME%}_ex(execute_data TSRMLS_CC); } diff --git a/Zend/zend_vm_gen.php b/Zend/zend_vm_gen.php index ac7a96ce61..69c25085aa 100644 --- a/Zend/zend_vm_gen.php +++ b/Zend/zend_vm_gen.php @@ -212,7 +212,7 @@ $op1_get_obj_zval_ptr_deref = array( "TMP" => "_get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC)", "VAR" => "_get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC)", "CONST" => "opline->op1.zv", - "UNUSED" => "_get_obj_zval_ptr_unused(TSRMLS_C)", + "UNUSED" => "_get_obj_zval_ptr_unused(execute_data TSRMLS_CC)", "CV" => "_get_zval_ptr_cv_deref_\\1(execute_data, opline->op1.var TSRMLS_CC)", ); @@ -221,7 +221,7 @@ $op2_get_obj_zval_ptr_deref = array( "TMP" => "_get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC)", "VAR" => "_get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC)", "CONST" => "opline->op2.zv", - "UNUSED" => "_get_obj_zval_ptr_unused(TSRMLS_C)", + "UNUSED" => "_get_obj_zval_ptr_unused(execute_data TSRMLS_CC)", "CV" => "_get_zval_ptr_cv_deref_\\1(execute_data, opline->op2.var TSRMLS_CC)", ); @@ -230,7 +230,7 @@ $op1_get_obj_zval_ptr_ptr = array( "TMP" => "NULL", "VAR" => "_get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC)", "CONST" => "NULL", - "UNUSED" => "_get_obj_zval_ptr_unused(TSRMLS_C)", + "UNUSED" => "_get_obj_zval_ptr_unused(execute_data TSRMLS_CC)", "CV" => "_get_zval_ptr_cv_\\1(execute_data, opline->op1.var TSRMLS_CC)", ); @@ -239,13 +239,13 @@ $op2_get_obj_zval_ptr_ptr = array( "TMP" => "NULL", "VAR" => "_get_zval_ptr_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC)", "CONST" => "NULL", - "UNUSED" => "_get_obj_zval_ptr_unused(TSRMLS_C)", + "UNUSED" => "_get_obj_zval_ptr_unused(execute_data TSRMLS_CC)", "CV" => "_get_zval_ptr_cv_\\1(execute_data, opline->op2.var TSRMLS_CC)", ); $op1_free_op = array( "ANY" => "FREE_OP(free_op1)", - "TMP" => "zval_dtor(free_op1.var)", + "TMP" => "zval_ptr_dtor_nogc(free_op1.var)", "VAR" => "zval_ptr_dtor_nogc(free_op1.var)", "CONST" => "", "UNUSED" => "", @@ -254,7 +254,7 @@ $op1_free_op = array( $op2_free_op = array( "ANY" => "FREE_OP(free_op2)", - "TMP" => "zval_dtor(free_op2.var)", + "TMP" => "zval_ptr_dtor_nogc(free_op2.var)", "VAR" => "zval_ptr_dtor_nogc(free_op2.var)", "CONST" => "", "UNUSED" => "", @@ -262,7 +262,7 @@ $op2_free_op = array( ); $op1_free_op_if_var = array( - "ANY" => "FREE_OP_IF_VAR(free_op1)", + "ANY" => "if (opline->op1_type == IS_VAR) {zval_ptr_dtor_nogc(free_op1.var);}", "TMP" => "", "VAR" => "zval_ptr_dtor_nogc(free_op1.var)", "CONST" => "", @@ -271,7 +271,7 @@ $op1_free_op_if_var = array( ); $op2_free_op_if_var = array( - "ANY" => "FREE_OP_IF_VAR(free_op2)", + "ANY" => "if (opline->op1_type == IS_VAR) {zval_ptr_dtor_nogc(free_op1.var);}", "TMP" => "", "VAR" => "zval_ptr_dtor_nogc(free_op2.var)", "CONST" => "", diff --git a/Zend/zend_vm_opcodes.c b/Zend/zend_vm_opcodes.c index 8d86ce23f1..067fd362e6 100644 --- a/Zend/zend_vm_opcodes.c +++ b/Zend/zend_vm_opcodes.c @@ -21,7 +21,7 @@ #include <stdio.h> #include <zend.h> -const char *zend_vm_opcodes_map[169] = { +const char *zend_vm_opcodes_map[170] = { "ZEND_NOP", "ZEND_ADD", "ZEND_SUB", @@ -71,11 +71,11 @@ const char *zend_vm_opcodes_map[169] = { "ZEND_JMPZ_EX", "ZEND_JMPNZ_EX", "ZEND_CASE", - "ZEND_SWITCH_FREE", + NULL, "ZEND_BRK", "ZEND_CONT", "ZEND_BOOL", - "ZEND_INIT_STRING", + NULL, "ZEND_ADD_CHAR", "ZEND_ADD_STRING", "ZEND_ADD_VAR", @@ -120,7 +120,7 @@ const char *zend_vm_opcodes_map[169] = { "ZEND_FETCH_UNSET", "ZEND_FETCH_DIM_UNSET", "ZEND_FETCH_OBJ_UNSET", - "ZEND_FETCH_DIM_TMP_VAR", + "ZEND_FETCH_LIST", "ZEND_FETCH_CONSTANT", "ZEND_GOTO", "ZEND_EXT_STMT", @@ -164,7 +164,7 @@ const char *zend_vm_opcodes_map[169] = { "ZEND_DECLARE_CLASS", "ZEND_DECLARE_INHERITED_CLASS", "ZEND_DECLARE_FUNCTION", - "ZEND_RAISE_ABSTRACT_ERROR", + NULL, "ZEND_DECLARE_CONST", "ZEND_ADD_INTERFACE", "ZEND_DECLARE_INHERITED_CLASS_DELAYED", @@ -191,6 +191,7 @@ const char *zend_vm_opcodes_map[169] = { "ZEND_POW", "ZEND_ASSIGN_POW", "ZEND_BIND_GLOBAL", + "ZEND_COALESCE", }; ZEND_API const char* zend_get_opcode_name(zend_uchar opcode) { diff --git a/Zend/zend_vm_opcodes.h b/Zend/zend_vm_opcodes.h index 70721b874b..c06fd84ff4 100644 --- a/Zend/zend_vm_opcodes.h +++ b/Zend/zend_vm_opcodes.h @@ -72,11 +72,9 @@ ZEND_API const char *zend_get_opcode_name(zend_uchar opcode); #define ZEND_JMPZ_EX 46 #define ZEND_JMPNZ_EX 47 #define ZEND_CASE 48 -#define ZEND_SWITCH_FREE 49 #define ZEND_BRK 50 #define ZEND_CONT 51 #define ZEND_BOOL 52 -#define ZEND_INIT_STRING 53 #define ZEND_ADD_CHAR 54 #define ZEND_ADD_STRING 55 #define ZEND_ADD_VAR 56 @@ -121,7 +119,7 @@ ZEND_API const char *zend_get_opcode_name(zend_uchar opcode); #define ZEND_FETCH_UNSET 95 #define ZEND_FETCH_DIM_UNSET 96 #define ZEND_FETCH_OBJ_UNSET 97 -#define ZEND_FETCH_DIM_TMP_VAR 98 +#define ZEND_FETCH_LIST 98 #define ZEND_FETCH_CONSTANT 99 #define ZEND_GOTO 100 #define ZEND_EXT_STMT 101 @@ -156,7 +154,6 @@ ZEND_API const char *zend_get_opcode_name(zend_uchar opcode); #define ZEND_DECLARE_CLASS 139 #define ZEND_DECLARE_INHERITED_CLASS 140 #define ZEND_DECLARE_FUNCTION 141 -#define ZEND_RAISE_ABSTRACT_ERROR 142 #define ZEND_DECLARE_CONST 143 #define ZEND_ADD_INTERFACE 144 #define ZEND_DECLARE_INHERITED_CLASS_DELAYED 145 @@ -180,5 +177,6 @@ ZEND_API const char *zend_get_opcode_name(zend_uchar opcode); #define ZEND_POW 166 #define ZEND_ASSIGN_POW 167 #define ZEND_BIND_GLOBAL 168 +#define ZEND_COALESCE 169 #endif |
