29 Commits

Autor SHA1 Mensagem Data
ptarjan e8141ac49d Revert "Update folly"
This reverts commit 4cf537888b.
2014-01-14 14:50:32 -08:00
Sara Golemon 4cf537888b Update folly
Conflicts:
	CMake/HPHPSetup.cmake
2014-01-14 14:35:31 -08:00
ptarjan 2752b5bbb1 bump version to 2.3.3 2014-01-14 14:21:24 -08:00
Paul Tarjan cc6cbf3852 fix fastcgi segfaults a better way
I think this is what julk originally wanted. He has a `m_keepConn` boolean that is set by `ConnectionFlags::KEEP_CONN` and if that is false, he calls this callback in both the error and the success case.

This doesn't segfault when the connection is abruptly closed by the requestor.

Closes #1522

Reviewed By: @scannell

Differential Revision: D1124995
2014-01-14 14:17:54 -08:00
Antony Puckey 1a4fac8a25 add getRemoteAddr to transport which defaults to empty string. add getRemoteAddr to fastcgi transport to return the proper header. fi no remoteAddr set it to the remoteHost ( libevent ) only set REMOTE_HOST if there is something in it as per php-src
Differential Revision: D1126545
2014-01-14 14:14:39 -08:00
Antony Puckey ae6443500e Set HTTPS header appropriately in fastcgi
Check passed header values for HTTPS.

IIS sets this header to "off" so check for that and empty value before
using transport->setSSL().

Only change to lower case if the value is not empty for performance.

Closes #1546

Reviewed By: @ptarjan

Differential Revision: D1125440

Pulled By: @scannell
2014-01-13 18:37:49 -08:00
Antony Puckey e42452e4f2 Allow transport to override SERVER_ headers
Uses the following headers from the transport (for fastcgi)
instead of the local config if they exist:

SERVER_NAME
SERVER_ADDR
SERVER_PORT

Closes #1445

Reviewed By: @ptarjan

Differential Revision: D1114969

Pulled By: @scannell
2014-01-13 18:37:16 -08:00
Antony Puckey 1dd7e6165e Populate fastcgi (transport-specific) headers
Added new function CopyServerParams in http-protocol which uses the new transport function getServerParams that adds any transport specific SERVER variables ie: FASTCGI_PARAMS to the _SERVER array

Closes #1437
Closes #1511

Reviewed By: @sgolemon

Differential Revision: D1120838

Pulled By: @scannell
2014-01-13 18:36:41 -08:00
Paul Tarjan 01ef59346e Support mod_fastcgi
when using mod_fastcgi SCRIPT_NAME is the Action instead of the actual document you want
this commit uses PATH_TRANSLATED - DOCUMENT_ROOT

tested with:
apache+mod_fastcgi
apache+mod_proxy_fcgi
nginx with no PATH_TRANSLATED header
nginx with this as PATH_TRANSLATED: fastcgi_param PATH_TRANSLATED $document_root$fastcgi_script_name;

Reviewed By: @scannell

Differential Revision: D1114124
2014-01-13 18:36:22 -08:00
Paul Tarjan 9380a44469 delete FastCGIConnection object
This was a leak appearing in @apuckey's valgrind dump. @simpkins said the object should delete itself since either the success or error callbacks will for sure be called for each connection.

Closes #1252

Reviewed By: @scannell

Differential Revision: D1115399
2014-01-13 13:32:58 -08:00
Paul Tarjan 3f859af167 stop emitting regex debugging message
This message is breaking composer installing things with enormous regexes. I tried to change the default error level but @markw65 didn't like that and we need to do something, so I guess lets not emit this if EHHS is off.

Closes #1347

Reviewed By: @markw65

Differential Revision: D1118365
2014-01-13 13:27:01 -08:00
Scott MacVicar 55ecfbdbb6 Fix libxml_disable_entity_loader()
This wasn't calling requestInit and setting the libxml handler no null.
So the first time an error came along it would reset the handler from
no-op to reading again.

This is a much better fix, we set our custom handler in requestInit and
when libxml_disable_entity_loader we store that state as a member bool
ensuring requestInit is always called to set our own handler.

If the handler isn't inserted then the behavious is as before. The only
time this could go pear shaped is say we wanted to make the default be
off. In that case we'd need a global requestInit that is always called
since there are libxml references everywhere.

Reviewed By: @jdelong

Differential Revision: D1116686
2014-01-13 13:20:25 -08:00
ptarjan f951cb8d88 bump version to 2.3.2 2013-12-23 12:51:42 -08:00
Paul Tarjan 2a3225ecd0 fix DOCUMENT_ROOT for fastcgi
We shouldn't have spcialized code in here for fastcgi, and it didn't even work.

Reviewed By: @markw65

Differential Revision: D1109072
2013-12-21 15:36:40 -08:00
Paul Tarjan 65cfdabb76 Allow fastcgi to use the DOCUMENT_ROOT from the web server
: We shouldn't use the current directory or the configured `SourceRoot` since the webserver could have many virtual hosts and always will send us a DOCUMENT_ROOT header.

The only scary part of the change is checking for `sourceRoot` instead of `getDocumentRoot` but I think it is right.

Differential Revision: D1108017
2013-12-21 15:36:27 -08:00
Paul Tarjan 25a26c6bd7 Fix Phar's directory detection
I screwed up the prefix check. Something that is a directory has to have a `/` between the prefix and the file, not just any character.

Closes #1334

Reviewed By: @JoelMarcey

Differential Revision: D1104260
2013-12-20 18:11:39 -08:00
Daniel Sloof 3effbfe5d1 Close pdo connection after request ends
When a request finishes and the PDO connection is not closed in
userland, we need to explictly close it to prevent excessive amount of
connections (and eventually causing MySQL to reject them).

This can obviously be solved in userland by closing the connection in a
register_shutdown_function, but we need to be consistent with PHP.

Closes #1345

Reviewed By: @markw65

Differential Revision: D1098327

Pulled By: @scannell
2013-12-20 11:44:02 -08:00
ptarjan 3a708166b8 bump version to 2.3.1 2013-12-17 13:48:38 -08:00
Paul Tarjan 3c17422435 Make FastCGI less magical for headers
When I changed `getHeaders()` to be the same for fastcgi as all the other transports I didn't notice julk has put in special rules to deal with the fact they weren't the same. Rip that out.

This makes `$_SERVER` contain `HTTP_HOST` instead of just `HOST`.

Reviewed By: @sgolemon

Differential Revision: D1100779
2013-12-17 13:48:08 -08:00
Paul Tarjan d3f23f393f fastcgi headers need unmangling
Headers as mangled in the FastCGI protocol, but the `getHeader()` method on `Transport` assumed the header was the original value.

Closes #1359

Reviewed By: @alexmalyshev

Differential Revision: D1098954
2013-12-17 13:48:07 -08:00
ptarjan 3fa32fab6e bump version for release 2013-12-12 15:23:59 -08:00
mwilliams 075cb79c9f Generate a pid.map file when we unmap parts of the text section
The perf tool won't lookup symbols for parts of the binary
that aren't file mapped, so provide a perf-pid.map file when we
do that.

Reviewed By: @bertmaher

Differential Revision: D1091918
2013-12-12 15:11:25 -08:00
bsimmers a1f2c80031 Don't arena allocate IRTrace
It has a std::list member so we need to run its destructor. I also
cleaned up some type stuff I ran into along the way.

Reviewed By: @jdelong
2013-12-12 15:11:24 -08:00
mwilliams 4e791cc4b6 Fix cpu identification
I broke this when cleaning up some -fstrict-alias warnings.

Reviewed By: @jdelong

Differential Revision: D1087374
2013-12-12 15:11:24 -08:00
mwilliams e62e500a84 Revert "Allow generation of hack types in hhvm thrift extension"
: This reverts commit 6792a3a1a02048f866eeb78937b4c6d5e3b29074.

Reviewed By: @ckwalsh
2013-12-12 15:11:23 -08:00
mwilliams bab7343e83 Fix crash trying to inline after a bad method call
In some cases, we can statically prove that an FCall will
go to a particular method. But that might depend on the fact that
the FPush* would fatal. eg we know that an object is of class Foo,
or is null. The FPushObjMethodD will fatal if its null, so the
FCall is known to call Foo::method (or an override).

But if we try to inline the FCall bad things will happen if the
FPush* was interped. So don't do that.

Reviewed By: @swtaarrs

Differential Revision: D1078789
2013-12-12 15:11:23 -08:00
mwilliams ef3d8e9fc5 Fix crash trying to inline after a bad method call
In some cases, we can statically prove that an FCall will
go to a particular method. But that might depend on the fact that
the FPush* would fatal. eg we know that an object is of class Foo,
or is null. The FPushObjMethodD will fatal if its null, so the
FCall is known to call Foo::method (or an override).

But if we try to inline the FCall bad things will happen if the
FPush* was interped. So don't do that.

Reviewed By: @ottoni
2013-12-12 15:11:22 -08:00
mwilliams 9401291363 Don't translate idx when JitEnableRenameFunctions is set
Users are supposed to be able to override idx with
their own version - but that doesn't work if we translate it
during bytecode emission.

We don't really have a good way of knowing whether its been
overridden, however, so use JitEnableRenameFunctions as we
have for other, similar cases.

Reviewed By: @dariorussi

Differential Revision: D1078332
2013-12-12 15:11:22 -08:00
mwilliams f0665f2e92 Fix race in pmethodCacheMissPath
pmethodCacheMissPath smashes code under the write lease,
but there's nothing to prevent two threads going through it in
sequence - resulting in a double free of the pdata.

Check to see if the code has already been smashed, and bail out if
it has.

Reviewed By: @edwinsmith

Differential Revision: D1078180
2013-12-12 15:10:56 -08:00
12607 arquivos alterados com 97823 adições e 352894 exclusões
+12 -2
Ver Arquivo
@@ -32,8 +32,18 @@ hphp.log
/hphp/hhvm/gen
/hphp/hhvm/hhvm
*.ext_hhvm.cpp
*.ext_hhvm.h
/hphp/runtime/ext/*.ext_hhvm.cpp
/hphp/runtime/ext/*.ext_hhvm.h
/hphp/runtime/ext/*/*.ext_hhvm.cpp
/hphp/runtime/ext/*/*.ext_hhvm.h
/hphp/runtime/ext/*/*/*.ext_hhvm.h
/hphp/runtime/ext/*/*/*.ext_hhvm.cpp
/hphp/runtime/ext_zend_compat/*/*.ext_hhvm.cpp
/hphp/runtime/ext_zend_compat/*/*.ext_hhvm.h
/hphp/runtime/ext_zend_compat/*/*/*.ext_hhvm.cpp
/hphp/runtime/ext_zend_compat/*/*/*.ext_hhvm.h
/hphp/runtime/base/builtin-functions.cpp.ext_hhvm.cpp
/hphp/runtime/base/builtin-functions.cpp.ext_hhvm.h
/hphp/runtime/ext_hhvm/ext_hhvm_infotabs.cpp
/hphp/runtime/ext_hhvm/ext_hhvm_infotabs.h
+8 -19
Ver Arquivo
@@ -4,34 +4,23 @@ compiler:
- gcc
before_script:
- time TRAVIS=1 ./configure_ubuntu_12.04.sh
- TRAVIS=1 ./configure_ubuntu_12.04.sh
# for some tests
- time sudo locale-gen de_DE && sudo locale-gen zh_CN.utf8 && sudo locale-gen fr_FR
- time HPHP_HOME=`pwd` make -j 6
# mysql configuration for unit-tests
- mysql -e 'CREATE DATABASE IF NOT EXISTS hhvm;'
- export PDO_MYSQL_TEST_DSN="mysql:host=127.0.0.1;dbname=hhvm"
- export PDO_MYSQL_TEST_USER="travis"
- export PDO_MYSQL_TEST_PASS=""
- sudo locale-gen de_DE && sudo locale-gen zh_CN.utf8 && sudo locale-gen fr_FR
- HPHP_HOME=`pwd` make -j 6
# Test suites take longer to run in RepoAuthoritative mode (-r) than normal so
# split out the -r from normal runs and further split the -r runs by suite to
# avoid the possibility of slower machines exceeding the 50 minute test timeout
env:
- TEST_RUN_MODE="-m jit quick"
- TEST_RUN_MODE="-m jit slow"
- TEST_RUN_MODE="-m jit zend"
- TEST_RUN_MODE="-m jit -r quick"
- TEST_RUN_MODE="-m jit -r slow"
- TEST_RUN_MODE="-m jit all"
- TEST_RUN_MODE="-m interp all"
- TEST_RUN_MODE="-m jit -r quick slow"
- TEST_RUN_MODE="-m interp -r quick slow"
- TEST_RUN_MODE="-m jit -r zend"
- TEST_RUN_MODE="-m interp quick"
- TEST_RUN_MODE="-m interp slow"
- TEST_RUN_MODE="-m interp zend"
- TEST_RUN_MODE="-m interp -r quick"
- TEST_RUN_MODE="-m interp -r slow"
- TEST_RUN_MODE="-m interp -r zend"
script: time hphp/hhvm/hhvm hphp/test/run $TEST_RUN_MODE
script: hphp/hhvm/hhvm hphp/test/run $TEST_RUN_MODE
notifications:
email: false
-61
Ver Arquivo
@@ -1,61 +0,0 @@
option(ENABLE_ZEND_COMPAT "Enable Zend source compatibility (beta)" OFF)
set(ZEND_COMPAT_PROJECTS)
set(ZEND_COMPAT_BUILD_DIRS)
set(ZEND_COMPAT_EXCLUDE_IDLS)
set(ZEND_COMPAT_LINK_LIBRARIES)
# Look for projects
set(EZC_DIR "${HPHP_HOME}/hphp/runtime/ext_zend_compat/")
file(GLOB ezc_projects RELATIVE ${EZC_DIR} "${EZC_DIR}/*")
foreach(ezc_project ${ezc_projects})
get_filename_component(ezc_name ${ezc_project} NAME)
if ((NOT ${ezc_name} STREQUAL "php-src") AND (IS_DIRECTORY "${EZC_DIR}/${ezc_name}"))
list(APPEND ZEND_COMPAT_PROJECTS ${ezc_name})
endif()
endforeach()
if (ENABLE_ZEND_COMPAT)
foreach(ezc_project ${ZEND_COMPAT_PROJECTS})
if (${ezc_project} STREQUAL "yaml")
find_package(LibYaml)
if (LibYaml_INCLUDE_DIRS)
list(APPEND ZEND_COMPAT_BUILD_DIRS "${EZC_DIR}/yaml")
include_directories(${LibYaml_INCLUDE_DIRS})
list(APPEND ZEND_COMPAT_LINK_LIBRARIES ${LibYaml_LIBRARIES})
else()
list(APPEND ZEND_COMPAT_EXCLUDE_IDLS "yaml.idl.json")
endif()
elseif (${ezc_project} STREQUAL "mongo")
include_directories("${EZC_DIR}/mongo/mcon")
list(APPEND ZEND_COMPAT_BUILD_DIRS "${EZC_DIR}/mongo")
else()
list(APPEND ZEND_COMPAT_BUILD_DIRS "${EZC_DIR}/${ezc_project}")
endif()
endforeach()
if (ZEND_COMPAT_BUILD_DIRS)
list(APPEND ZEND_COMPAT_BUILD_DIRS "${EZC_DIR}/php-src")
include_directories("${EZC_DIR}/php-src")
include_directories("${EZC_DIR}/php-src/main")
include_directories("${EZC_DIR}/php-src/Zend")
include_directories("${EZC_DIR}/php-src/TSRM")
endif()
else()
foreach(ezc_project ${ZEND_COMPAT_PROJECTS})
list(APPEND ZEND_COMPAT_EXCLUDE_IDLS "${ezc_project}.idl.json")
endforeach()
endif()
# This is really ugly, but cmake's list(FIND)
# doesn't entirely work the way it should
macro(ZEND_COMPAT_STRIP_IDLS IDLS)
foreach(idl ${${IDLS}})
get_filename_component(idl_name ${idl} NAME)
foreach(f ${ARGV})
if (${idl_name} STREQUAL ${f})
list(REMOVE_ITEM ${IDLS} ${idl})
endif()
endforeach()
endforeach()
endmacro()
-16
Ver Arquivo
@@ -1,16 +0,0 @@
find_package(PkgConfig)
pkg_check_modules(PC_FREETYPE QUIET freetype2)
find_path(FREETYPE_INCLUDE_DIRS NAMES freetype/config/ftheader.h
HINTS ${PC_FREETYPE_INCLUDEDIR} ${PC_FREETYPE_INCLUDE_DIRS}
PATH_SUFFIXES freetype2)
find_library(FREETYPE_LIBRARIES NAMES freetype)
include (FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Freetype DEFAULT_MSG
FREETYPE_LIBRARIES
FREETYPE_INCLUDE_DIRS)
mark_as_advanced(FREETYPE_INCLUDE_DIRS FREETYPE_LIBRARIES)
+121
Ver Arquivo
@@ -0,0 +1,121 @@
# - Find GD
# Find the native GD includes and library
# This module defines
# GD_INCLUDE_DIR, where to find gd.h, etc.
# GD_LIBRARIES, the libraries needed to use GD.
# GD_FOUND, If false, do not try to use GD.
# also defined, but not for general use are
# GD_LIBRARY, where to find the GD library.
# GD_SUPPORTS_PNG, GD_SUPPORTS_JPEG, GD_SUPPORTS_GIF, test
# support for image formats in GD.
FIND_PATH(GD_INCLUDE_DIR gd.h
/usr/local/include
/usr/include
)
if(WIN32 AND NOT CYGWIN)
SET(GD_NAMES ${GD_NAMES} bgd)
else(WIN32)
SET(GD_NAMES ${GD_NAMES} gd)
endif(WIN32 AND NOT CYGWIN)
FIND_LIBRARY(GD_LIBRARY
NAMES ${GD_NAMES}
PATHS /usr/lib64 /usr/lib /usr/local/lib
)
IF (GD_LIBRARY AND GD_INCLUDE_DIR)
SET(GD_LIBRARIES ${GD_LIBRARY})
SET(GD_FOUND "YES")
ELSE (GD_LIBRARY AND GD_INCLUDE_DIR)
SET(GD_FOUND "NO")
ENDIF (GD_LIBRARY AND GD_INCLUDE_DIR)
IF (GD_FOUND)
IF (WIN32 AND NOT CYGWIN)
SET(GD_SUPPORTS_PNG ON)
SET(GD_SUPPORTS_JPEG ON)
SET(GD_SUPPORTS_GIF ON)
get_filename_component(GD_LIBRARY_DIR ${GD_LIBRARY} PATH)
ELSE (WIN32 AND NOT CYGWIN)
INCLUDE(CheckLibraryExists)
GET_FILENAME_COMPONENT(GD_LIB_PATH ${GD_LIBRARY} PATH)
GET_FILENAME_COMPONENT(GD_LIB ${GD_LIBRARY} NAME)
CHECK_LIBRARY_EXISTS("${GD_LIBRARY}" "gdImagePng" "${GD_LIB_PATH}" GD_SUPPORTS_PNG)
IF (GD_SUPPORTS_PNG)
find_package(PNG)
IF (PNG_FOUND)
SET(GD_LIBRARIES ${GD_LIBRARIES} ${PNG_LIBRARIES})
SET(GD_INCLUDE_DIR ${GD_INCLUDE_DIR} ${PNG_INCLUDE_DIR})
ELSE (PNG_FOUND)
SET(GD_SUPPORTS_PNG "NO")
ENDIF (PNG_FOUND)
ENDIF (GD_SUPPORTS_PNG)
CHECK_LIBRARY_EXISTS("${GD_LIBRARY}" "gdImageJpeg" "${GD_LIB_PATH}" GD_SUPPORTS_JPEG)
IF (GD_SUPPORTS_JPEG)
find_package(JPEG)
IF (JPEG_FOUND)
SET(GD_LIBRARIES ${GD_LIBRARIES} ${JPEG_LIBRARIES})
SET(GD_INCLUDE_DIR ${GD_INCLUDE_DIR} ${JPEG_INCLUDE_DIR})
ELSE (JPEG_FOUND)
SET(GD_SUPPORTS_JPEG "NO")
ENDIF (JPEG_FOUND)
ENDIF (GD_SUPPORTS_JPEG)
CHECK_LIBRARY_EXISTS("${GD_LIBRARY}" "gdImageGif" "${GD_LIB_PATH}" GD_SUPPORTS_GIF)
# Trim the list of include directories
SET(GDINCTRIM)
FOREACH(GD_DIR ${GD_INCLUDE_DIR})
SET(GD_TMP_FOUND OFF)
FOREACH(GD_TRIMMED ${GDINCTRIM})
IF ("${GD_DIR}" STREQUAL "${GD_TRIMMED}")
SET(GD_TMP_FOUND ON)
ENDIF ("${GD_DIR}" STREQUAL "${GD_TRIMMED}")
ENDFOREACH(GD_TRIMMED ${GDINCTRIM})
IF (NOT GD_TMP_FOUND)
SET(GDINCTRIM "${GDINCTRIM}" "${GD_DIR}")
ENDIF (NOT GD_TMP_FOUND)
ENDFOREACH(GD_DIR ${GD_INCLUDE_DIR})
SET(GD_INCLUDE_DIR ${GDINCTRIM})
SET(GD_LIBRARY_DIR)
# Generate trimmed list of library directories and list of libraries
FOREACH(GD_LIB ${GD_LIBRARIES})
GET_FILENAME_COMPONENT(GD_NEXTLIBDIR ${GD_LIB} PATH)
SET(GD_TMP_FOUND OFF)
FOREACH(GD_LIBDIR ${GD_LIBRARY_DIR})
IF ("${GD_NEXTLIBDIR}" STREQUAL "${GD_LIBDIR}")
SET(GD_TMP_FOUND ON)
ENDIF ("${GD_NEXTLIBDIR}" STREQUAL "${GD_LIBDIR}")
ENDFOREACH(GD_LIBDIR ${GD_LIBRARIES})
IF (NOT GD_TMP_FOUND)
SET(GD_LIBRARY_DIR "${GD_LIBRARY_DIR}" "${GD_NEXTLIBDIR}")
ENDIF (NOT GD_TMP_FOUND)
ENDFOREACH(GD_LIB ${GD_LIBRARIES})
ENDIF (WIN32 AND NOT CYGWIN)
ENDIF (GD_FOUND)
IF (GD_FOUND)
IF (NOT GD_FIND_QUIETLY)
MESSAGE(STATUS "Found GD: ${GD_LIBRARY}")
ENDIF (NOT GD_FIND_QUIETLY)
ELSE (GD_FOUND)
IF (GD_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find GD library")
ENDIF (GD_FIND_REQUIRED)
ENDIF (GD_FOUND)
MARK_AS_ADVANCED(
GD_LIBRARY
GD_LIBRARIES
GD_INCLUDE_DIR
GD_LIBRARY_DIR
GD_SUPPORTS_PNG
GD_SUPPORTS_JPEG
GD_SUPPORTS_GIF
)
+1 -9
Ver Arquivo
@@ -18,7 +18,7 @@ endif (LIBDWARF_LIBRARIES AND LIBDWARF_INCLUDE_DIRS)
find_path (DWARF_INCLUDE_DIR
NAMES
libdwarf.h dwarf.h
dwarf.h
PATHS
/usr/include
/usr/include/libdwarf
@@ -50,13 +50,5 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibDwarf DEFAULT_MSG
LIBDWARF_LIBRARIES
LIBDWARF_INCLUDE_DIRS)
if (LIBDWARF_LIBRARIES AND LIBDWARF_INCLUDE_DIRS)
set(CMAKE_REQUIRED_INCLUDES ${LIBDWARF_INCLUDE_DIRS})
set(CMAKE_REQUIRED_LIBRARIES ${LIBDWARF_LIBRARIES})
include(CheckSymbolExists)
CHECK_SYMBOL_EXISTS(dwarf_encode_leb128 "libdwarf.h" LIBDWARF_HAVE_ENCODE_LEB128)
endif()
mark_as_advanced(LIBDW_INCLUDE_DIR DWARF_INCLUDE_DIR)
mark_as_advanced(LIBDWARF_INCLUDE_DIRS LIBDWARF_LIBRARIES)
mark_as_advanced(LIBDWARF_HAVE_ENCODE_LEB128)
-14
Ver Arquivo
@@ -1,14 +0,0 @@
if (LIBJPEG_LIBRARIES AND LIBJPEG_INCLUDE_DIRS)
set (LibJpeg_FIND_QUIETLY TRUE)
endif (LIBJPEG_LIBRARIES AND LIBJPEG_INCLUDE_DIRS)
find_path(LIBJPEG_INCLUDE_DIRS NAMES jpeglib.h)
find_library(LIBJPEG_LIBRARIES NAMES jpeg)
include (FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibJpeg DEFAULT_MSG
LIBJPEG_LIBRARIES
LIBJPEG_INCLUDE_DIRS)
mark_as_advanced(LIBJPEG_INCLUDE_DIRS LIBJPEG_LIBRARIES)
-14
Ver Arquivo
@@ -1,14 +0,0 @@
if (LIBPNG_LIBRARIES AND LIBPNG_INCLUDE_DIRS)
set (LibPng_FIND_QUIETLY TRUE)
endif (LIBPNG_LIBRARIES AND LIBPNG_INCLUDE_DIRS)
find_path(LIBPNG_INCLUDE_DIRS NAMES png.h)
find_library(LIBPNG_LIBRARIES NAMES png)
include (FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibPng DEFAULT_MSG
LIBPNG_LIBRARIES
LIBPNG_INCLUDE_DIRS)
mark_as_advanced(LIBPNG_INCLUDE_DIRS LIBPNG_LIBRARIES)
-12
Ver Arquivo
@@ -1,12 +0,0 @@
if (LIBODBC_LIBRARIES AND LIBODBC_INCLUDE_DIRS)
set (LibUODBC_FIND_QUIETLY TRUE)
endif (LIBODBC_LIBRARIES AND LIBODBC_INCLUDE_DIRS)
find_path (LIBODBC_INCLUDE_DIRS NAMES sqlext.h)
find_library (LIBODBC_LIBRARIES NAMES odbc)
include (FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibUODBC DEFAULT_MSG
LIBODBC_LIBRARIES
LIBODBC_INCLUDE_DIRS)
mark_as_advanced(LIBODBC_INCLUDE_DIRS LIBODBC_LIBRARIES)
-14
Ver Arquivo
@@ -1,14 +0,0 @@
if (LIBVPX_LIBRARIES AND LIBVPX_INCLUDE_DIRS)
set (LibVpx_FIND_QUIETLY TRUE)
endif (LIBVPX_LIBRARIES AND LIBVPX_INCLUDE_DIRS)
find_path(LIBVPX_INCLUDE_DIRS NAMES vpx_codec.h)
find_library(LIBVPX_LIBRARIES NAMES vpx)
include (FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibVpx DEFAULT_MSG
LIBVPX_LIBRARIES
LIBVPX_INCLUDE_DIRS)
mark_as_advanced(LIBVPX_INCLUDE_DIRS LIBVPX_LIBRARIES)
-13
Ver Arquivo
@@ -1,13 +0,0 @@
if (LibYaml_LIBRARIES AND LibYaml_INCLUDE_DIRS)
set (LibYaml_FIND_QUIETLY TRUE)
endif (LibYaml_LIBRARIES AND LibYaml_INCLUDE_DIRS)
find_path (LibYaml_INCLUDE_DIRS NAMES yaml.h)
find_library (LibYaml_LIBRARIES NAMES yaml)
include (FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibYaml DEFAULT_MSG
LibYaml_LIBRARIES
LibYaml_INCLUDE_DIRS)
mark_as_advanced(LibYaml_INCLUDE_DIRS LibYaml_LIBRARIES)
+5 -2
Ver Arquivo
@@ -13,8 +13,11 @@ if (FOLLY_IFUNC)
endif()
set(CMAKE_REQUIRED_LIBRARIES rt)
include(CheckFunctionExists)
CHECK_FUNCTION_EXISTS("clock_gettime" HAVE_CLOCK_GETTIME)
CHECK_CXX_SOURCE_COMPILES("#include <time.h>
int main() {
clock_gettime((clockid_t)0, NULL);
return 0;
}" HAVE_CLOCK_GETTIME)
if (HAVE_CLOCK_GETTIME)
add_definitions("-DFOLLY_HAVE_CLOCK_GETTIME=1")
+1 -5
Ver Arquivo
@@ -39,11 +39,7 @@ else()
set(GNUCC_48_OPT "-Wno-unused-local-typedefs -fno-canonical-system-headers -Wno-deprecated-declarations")
endif()
set(CMAKE_C_FLAGS "-w")
set(CMAKE_CXX_FLAGS "-fno-gcse -fno-omit-frame-pointer -ftemplate-depth-180 -Wall -Woverloaded-virtual -Wno-deprecated -Wno-strict-aliasing -Wno-write-strings -Wno-invalid-offsetof -fno-operator-names -Wno-error=array-bounds -Wno-error=switch -std=gnu++11 -Werror=format-security -Wno-unused-result -Wno-sign-compare -Wno-attributes -Wno-maybe-uninitialized -mcrc32 ${GNUCC_48_OPT}")
endif()
if(${CMAKE_CXX_COMPILER} MATCHES ".*clang.*")
set(CMAKE_CXX_FLAGS "-fno-gcse -fno-omit-frame-pointer -ftemplate-depth-180 -Wall -Woverloaded-virtual -Wno-deprecated -Wno-strict-aliasing -Wno-write-strings -Wno-invalid-offsetof -fno-operator-names -Wno-error=array-bounds -Wno-error=switch -std=gnu++11 -Werror=format-security -Wno-unused-result -Wno-sign-compare -Wno-attributes -Wno-maybe-uninitialized -Wno-mismatched-tags -Wno-unknown-warning-option -Wno-return-type-c-linkage -Qunused-arguments")
set(CMAKE_CXX_FLAGS "-fno-gcse -fno-omit-frame-pointer -ftemplate-depth-180 -Wall -Woverloaded-virtual -Wno-deprecated -Wno-strict-aliasing -Wno-write-strings -Wno-invalid-offsetof -fno-operator-names -Wno-error=array-bounds -Wno-error=switch -std=gnu++11 -Werror=format-security -Wno-unused-result -Wno-sign-compare -Wno-attributes -Wno-maybe-uninitialized ${GNUCC_48_OPT}")
endif()
if(CMAKE_COMPILER_IS_GNUCC)
+4 -59
Ver Arquivo
@@ -96,40 +96,13 @@ if(HAVE_CUSTOM_LIBEVENT)
endif()
set(CMAKE_REQUIRED_LIBRARIES)
find_package(LibUODBC)
if (LIBUODBC_INCLUDE_DIRS)
include_directories(${LIBUODBC_INCLUDE_DIRS})
add_definitions("-DHAVE_UODBC")
endif ()
# GD checks
add_definitions(-DPNG_SKIP_SETJMP_CHECK)
find_package(LibVpx)
if (LIBVPX_INCLUDE_DIRS)
include_directories(${LIBVPX_INCLUDE_DIRS})
add_definitions("-DHAVE_GD_WEBP")
endif()
find_package(LibJpeg)
if (LIBJPEG_INCLUDE_DIRS)
include_directories(${LIBJPEG_INCLUDE_DIRS})
add_definitions("-DHAVE_GD_JPG")
endif()
find_package(LibPng)
if (LIBPNG_INCLUDE_DIRS)
include_directories(${LIBPNG_INCLUDE_DIRS})
add_definitions("-DHAVE_GD_PNG")
endif()
find_package(Freetype)
if (FREETYPE_INCLUDE_DIRS)
include_directories(${FREETYPE_INCLUDE_DIRS})
add_definitions("-DHAVE_LIBFREETYPE -DHAVE_GD_FREETYPE -DENABLE_GD_TTF")
endif()
find_package(GD REQUIRED)
# libXed
find_package(LibXed)
if (LibXed_INCLUDE_DIR AND LibXed_LIBRARY)
include_directories(${LibXed_INCLUDE_DIR})
add_definitions("-DHAVE_LIBXED")
add_definitions(-DHAVE_LIBXED)
endif()
# CURL checks
@@ -319,9 +292,6 @@ include_directories(${CCLIENT_INCLUDE_PATH})
find_package(LibDwarf REQUIRED)
include_directories(${LIBDWARF_INCLUDE_DIRS})
if (LIBDWARF_HAVE_ENCODE_LEB128)
add_definitions("-DHAVE_LIBDWARF_20130729")
endif()
find_package(LibElf REQUIRED)
include_directories(${LIBELF_INCLUDE_DIRS})
@@ -335,26 +305,15 @@ if (NOT RECENT_CCLIENT)
message(FATAL_ERROR "Your version of c-client is too old, you need 2007")
endif()
if (EXISTS "${CCLIENT_INCLUDE_PATH}/linkage.c")
CONTAINS_STRING("${CCLIENT_INCLUDE_PATH}/linkage.c" auth_gss CCLIENT_HAS_GSS)
elseif (EXISTS "${CCLIENT_INCLUDE_PATH}/linkage.h")
CONTAINS_STRING("${CCLIENT_INCLUDE_PATH}/linkage.h" auth_gss CCLIENT_HAS_GSS)
endif()
find_package(Libpam)
if (PAM_INCLUDE_PATH)
include_directories(${PAM_INCLUDE_PATH})
endif()
if (NOT CCLIENT_HAS_GSS)
else()
add_definitions(-DSKIP_IMAP_GSS=1)
endif()
if (EXISTS "${CCLIENT_INCLUDE_PATH}/linkage.c")
CONTAINS_STRING("${CCLIENT_INCLUDE_PATH}/linkage.c" ssl_onceonlyinit CCLIENT_HAS_SSL)
elseif (EXISTS "${CCLIENT_INCLUDE_PATH}/linkage.h")
CONTAINS_STRING("${CCLIENT_INCLUDE_PATH}/linkage.h" ssl_onceonlyinit CCLIENT_HAS_SSL)
endif()
if (NOT CCLIENT_HAS_SSL)
@@ -488,21 +447,7 @@ endif()
target_link_libraries(${target} ${ONIGURUMA_LIBRARIES})
target_link_libraries(${target} ${Mcrypt_LIB})
target_link_libraries(${target} ${GD_LIBRARY})
if (FREETYPE_LIBRARIES)
target_link_libraries(${target} ${FREETYPE_LIBRARIES})
endif()
if (LIBJPEG_LIBRARIES)
target_link_libraries(${target} ${LIBJPEG_LIBRARIES})
endif()
if (LIBPNG_LIBRARIES)
target_link_libraries(${target} ${LIBPNG_LIBRARIES})
endif()
if (LIBVPX_LIBRARIES)
target_link_libraries(${target} ${LIBVPX_LIBRARIES})
endif()
if (LIBUODBC_LIBRARIES)
target_link_libraries(${target} ${LIBUODBC_LIBRARIES})
endif()
target_link_libraries(${target} ${LDAP_LIBRARIES})
target_link_libraries(${target} ${LBER_LIBRARIES})
-21
Ver Arquivo
@@ -38,27 +38,6 @@ function(auto_sources RETURN_VALUE PATTERN SOURCE_SUBDIRS)
set(${RETURN_VALUE} ${${RETURN_VALUE}} PARENT_SCOPE)
endfunction(auto_sources)
macro(HHVM_SELECT_SOURCES DIR)
auto_sources(files "*.cpp" "RECURSE" "${DIR}")
foreach(f ${files})
if (NOT (${f} MATCHES "(ext_hhvm|/(old-)?tests?/)"))
list(APPEND CXX_SOURCES ${f})
endif()
endforeach()
auto_sources(files "*.c" "RECURSE" "${DIR}")
foreach(f ${files})
if (NOT (${f} MATCHES "(ext_hhvm|/(old-)?tests?/)"))
list(APPEND C_SOURCES ${f})
endif()
endforeach()
auto_sources(files "*.S" "RECURSE" "${DIR}")
foreach(f ${files})
if (NOT (${f} MATCHES "(ext_hhvm|/(old-)?tests?/)"))
list(APPEND ASM_SOURCES ${f})
endif()
endforeach()
endmacro(HHVM_SELECT_SOURCES)
function(CONTAINS_STRING FILE SEARCH RETURN_VALUE)
file(STRINGS ${FILE} FILE_CONTENTS REGEX ".*${SEARCH}.*")
if (FILE_CONTENTS)
+2 -5
Ver Arquivo
@@ -62,7 +62,8 @@ include(HPHPCompiler)
include(HPHPFunctions)
include(HPHPFindLibs)
add_definitions(-D_REENTRANT=1 -D_PTHREADS=1 -D__STDC_FORMAT_MACROS -DFOLLY_HAVE_WEAK_SYMBOLS=1)
add_definitions(-D_REENTRANT=1 -D_PTHREADS=1 -D__STDC_FORMAT_MACROS)
add_definitions(-DHHVM_LIB_PATH_DEFAULT="${HPHP_HOME}/bin")
if (LINUX)
add_definitions(-D_GNU_SOURCE)
@@ -123,10 +124,6 @@ if(ENABLE_FASTCGI)
add_definitions(-DENABLE_FASTCGI=1)
endif ()
if(DISABLE_HARDWARE_COUNTERS)
add_definitions(-DNO_HARDWARE_COUNTERS=1)
endif ()
# enable the OSS options if we have any
add_definitions(-DHPHP_OSS=1)
-3
Ver Arquivo
@@ -13,6 +13,3 @@ option(USE_JEMALLOC "Use jemalloc" ON)
option(USE_TCMALLOC "Use tcmalloc (if jemalloc is not used)" ON)
option(USE_GOOGLE_HEAP_PROFILER "Use Google heap profiler" OFF)
option(USE_GOOGLE_CPU_PROFILER "Use Google cpu profiler" OFF)
option(DISABLE_HARDWARE_COUNTERS "Disable hardware counters (for XenU systems)" OFF)
+21 -11
Ver Arquivo
@@ -1,18 +1,18 @@
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.7 FATAL_ERROR)
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.5 FATAL_ERROR)
PROJECT(hphp C CXX ASM)
IF(NOT CMAKE_SIZEOF_VOID_P EQUAL 8)
message(FATAL_ERROR "HHVM requires a 64bit OS")
IF("$ENV{HPHP_HOME}" STREQUAL "")
message(FATAL_ERROR "You should set the HPHP_HOME environmental")
ENDIF()
set(HPHP_HOME "$ENV{HPHP_HOME}")
if (NOT HPHP_HOME)
set(HPHP_HOME "${CMAKE_CURRENT_SOURCE_DIR}")
endif()
message("Using HPHP_HOME == ${HPHP_HOME}")
file(TO_CMAKE_PATH "$ENV{HPHP_HOME}" HPHP_HOME)
IF(NOT EXISTS "${HPHP_HOME}/CMake/HPHPSetup.cmake")
message(FATAL_ERROR "Invalid HPHP_HOME. Set it to the root of your hhvm tree, or run `cmake .` from there.")
IF(NOT IS_DIRECTORY ${HPHP_HOME})
message(FATAL_ERROR "The value of HPHP_HOME does not exist")
ENDIF()
IF(NOT EXISTS "${HPHP_HOME}/LICENSE.PHP")
message(FATAL_ERROR "The value of HPHP_HOME in incorrect")
ENDIF()
SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake" ${CMAKE_MODULE_PATH})
@@ -20,5 +20,15 @@ SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake" ${CMAKE_MODULE_PATH})
include("${CMAKE_CURRENT_SOURCE_DIR}/CMake/HPHPFunctions.cmake")
include(CheckFunctionExists)
add_subdirectory(hphp)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/hphp)
IF(CMAKE_SIZEOF_VOID_P EQUAL 4)
message(FATAL_ERROR "32-bit support is currently unsupported, check back with a later version of HipHop")
ENDIF()
if ("$ENV{USE_HHVM}" STREQUAL "1")
message("Building for HHVM")
endif()
if ("$ENV{USE_HPHPC}" STREQUAL "1")
message(FATAL_ERROR "Building HPHPc is no longer supported")
endif()
+1 -1
Ver Arquivo
@@ -1,6 +1,6 @@
# HHVM [![Build Status](https://travis-ci.org/facebook/hhvm.png?branch=master)](https://travis-ci.org/facebook/hhvm)
HHVM (aka the HipHop Virtual Machine) is a new open-source virtual machine designed for executing programs written in PHP. HHVM uses a just-in-time compilation approach to achieve superior performance while maintaining the flexibility that PHP developers are accustomed to. To date, HHVM (and its predecessor HPHPc before it) has realized over a 9x increase in web request throughput and over a 5x reduction in memory consumption for Facebook compared with the Zend PHP 5.2 engine + APC.
HHVM (aka the HipHop Virtual Machine) is a new open-source virtual machine designed for executing programs written in PHP. HHVM uses a just-in-time compilation approach to achieve superior performance while maintaining the flexibility that PHP developers are accustomed to. To date, HHVM (and its precedessor HPHPc before it) has realized over a 9x increase in web request throughput and over a 5x reduction in memory consumption for Facebook compared with the Zend PHP 5.2 engine + APC.
HHVM can be run as a standalone webserver (i.e. without the Apache webserver and the "modphp" extension). HHVM can also be used together with a FastCGI-based webserver, and work is in progress to make HHVM work smoothly with Apache.
externo
+1 -1
Ver Arquivo
@@ -3,7 +3,7 @@
if [ "$1" = '--help' ] || [ "$1" = '-h' ]; then
echo 'usage: ./configure -Dvariable=argument ...\n'
echo 'Variables: '
echo ' CMAKE_BUILD_TYPE=Debug|Release Sets build type (default Release).'
echo ' CMAKE_BUILD_TYPE=Debug|Release Sets build type (default Relase).'
exit 2
fi
+5 -4
Ver Arquivo
@@ -1,6 +1,6 @@
#########################################
#
# Install all the dependencies for HipHop
# Install all the dependancies for HipHop
#
#########################################
@@ -20,12 +20,13 @@ if [ "x${TRAVIS}" != "x" ]; then
fi
export CMAKE_PREFIX_PATH=`/bin/pwd`/..
export HPHP_HOME=`/bin/pwd`
# install python-software-properties before trying to add a PPA
# install python-software-properties before trying to add a PPA
sudo apt-get -y update
sudo apt-get install -y python-software-properties
# install apt-fast to speed up later dependency installation
# install apt-fast to speedup later dependency installation
sudo add-apt-repository -y ppa:apt-fast/stable
sudo apt-get -y update
sudo apt-get -y install apt-fast
@@ -123,4 +124,4 @@ cmake .
echo "-------------------------------------------------------------------------"
echo "Done. Now run:"
echo " CMAKE_PREFIX_PATH=\`pwd\`/.. make"
echo " CMAKE_PREFIX_PATH=\`pwd\`/.. HPHP_HOME=\`pwd\` make"
+4 -2
Ver Arquivo
@@ -17,9 +17,11 @@
include(HPHPSetup)
include(FollySetup)
include(ExtZendCompat)
add_definitions("-DHHVM")
# HHVM Build
SET(USE_HHVM TRUE)
SET(ENV{HHVM} 1)
ADD_DEFINITIONS("-DHHVM -DHHVM_BINARY=1 -DHHVM_PATH=\\\"${HPHP_HOME}/hphp/hhvm/hhvm\\\"")
add_subdirectory(tools/bootstrap)
+5 -99
Ver Arquivo
@@ -1,104 +1,10 @@
Next release
- FrozenMap collection
- Deprecated Vector|Set|Map::put() method removed
- == between Frozen{Vector|Set|Map} and {Vector|Set|Map} now can return true
- Map collections learned the in-place retain() and retainWithKey()
- 'num' scalar typehint that accepts both ints and floats
"Beastie Boys" 6-Jan-2014
- Support lex-time binary constants (eg. 0b10111)
- StreamWrappers now support rmdir, mkdir, rename and unlink
- Miscellaneous Zend PHP compatibility fixes
- Default StatCache to off
- Miscellaneous FastCGI fixes
- Miscellaneous region compiler fixes
- Map and StableMap collections use the same underlying implementation
- Trait requirements enforced
- hhprof performance improvements
- Add array to string conversion notice
- Add RaiseNotice IR opcode
- Fix VirtualHost.<name>.Pattern matching
- Fix various memory leaks (pdo_parse_params, Gen*WaitHandle)
- Import a lot more Zend tests that used to crash or hang
- Clean up base.h
- XLS register allocation cleanup
- Enable region compiler by default for JIT functions in ahot
- Fatal on eval() in RepoAuthoritative mode
- Enable LTO for HHVM
- Fix a few SPL compatibility issues
"Appleseed" 23-Dec-2013
- Fix issues with DOCUMENT_ROOT in fastcgi
- Better type inference for collections and builtins in repo mode
- Shorter syntax for lambda expressions w/ automatic captures
- Parser support for trait require clauses
- Move FrozenVector and Set to the HH namespace
- Fix resource to array conversion
- Fix a request local memory leak in foreach of apc arrays
- Initial php_odbc API implementation
- Implement PHP's hash_copy() function
- Experimental tool: Memoization Opportunity Profiler
- Various small parity/behavior fixes (in phar, proc_open, filter_var)
- A Eval.DumpHhas=1 option to dump hhas for a php file
- Better warnings in Set::toArray
- Fix the behavior of foreach loops in finally blocks
- chmod -x runtime/vm/jit/*.{cpp,h}
- Changes to make hhvm build clean with clang-3.4
- Fix array_product to not be bug-compatible with PHP 5.2
- Change the Map datastructure---preserves order and does faster foreach
- FrozenSet collection
- Generate pid.map when we unmap text section, for the perf tool
- Implemented GlobIterator
- Implemented Reflection::export and Reflection::getModifierNames
"Tom Yum" 9-Dec-2013
- support date.timezone in ini files
- implement fileinfo
- special comparisons for DateTime
- delete unimplemented functions
- support for the finally clause in try blocks
"Huarache" 26-Nov-2013
- Linker re-ordering of hot functions
- Huge pages for hot functions
- Implement ZipArchive
- preg_replace /e support
- get_mem_usage() no longer can be negative
- Userland file system support
- Implement fileinfo extension
- wordwrap() fixes
- PDO::sqliteCreateFunction()
- Implement NumberFormatter
- Implement Locale
- Implement DatePeriod
- Many reflection fixes
- Stub out PharData
- A ton of performance fixes
- A ton of open source framework fixes
- FastCGI Server Support
"Garlic Alfredo" 11-Nov-2013
- teach implode() about collections
- fix ini parsing leak
- Make array not an instanceof Traversable
"Burrito" 28-Oct-2013
- Initial support for using FastCGI
- Initial support for php.ini configuration files
- Log when a nullable (e.g. ?int) is incorrect
- Add support for collections to array_diff, array_diff_key, array_intersect,
array_intersect_key
- tc-print improvements and fixes
- Several debugger fixes
- More improvements to the experimental PHP extension compat layer
- Fixed how parse errors are handled by eval()
- Support custom reason for status header
- Emit better error message when hhvm's systemlib doesn't load properly
- Fixes / clarifications added to the bytecode specification
- Lots of other bug fixes, clean up, PHP compat fixes, and JIT improvements
"Sausage" 14-Oct-2013
- Direct invocation of callable arrays: $f = [$cls_or_obj, 'method']; $f()
- Direct invocation of callable arrays: $f = [$cls_or_instance, 'method']; $f()
- ASAN clean
- Support dynamically loadable extensions
- Support loading mini-systemlibs from extensions
@@ -120,7 +26,7 @@ Next release
- Support arbitrary expressions inside empty()
"Bobotie" 16-Sep-2013
- HNI (HipHop Native Interface) for calling C++ functions from PHP
- HNI (HipHop Native Interface) for calling C++ functions from Php
- Fix PropertyAccessorMap::isset
- Expose more POSIX constants
- Fixed behavior of stream_get_contents when default args are used.
@@ -134,14 +40,14 @@ Next release
- Import ftp extension
"Kimchi" 2-Sep-2013
- Fix order of custom attributes and visibility in ctor arg promotion
- Fix order of custom attributes and visibility in ctor arg promotion
- Implement CachingIterator
- Implement RecursiveCachingIterator
- Generalized heuristic for choosing when to inline in the jit
- Introduced a Zend compatibility layer to compile extensions
- Imported calendar extension
- Use gcc-4.8.1 by default
- Improve hhvm command line parsing logic
- Improve hhvm commandline parsing logic
- Fix register_shutdown in session_set_save_handler to match PHP 5.4
- Add "native" functions for use in Systemlib
- PHP extension source-compatitblility layer
@@ -199,7 +105,7 @@ Next release
"Wasabi Peas" 08-Jul-2013
- always_assert when we run out of TC space
- Initial changes to get HHVM compiling on OSX
- Consolidate ObjectData and Instance
- Consolodate ObjectData and Instance
- Prototype heap tracing framework & Heap profiler
- Better JIT code generation for Mod and Div
- Fixes to enable compilation with clang
+1 -8
Ver Arquivo
@@ -1927,7 +1927,6 @@ StatementPtr AliasManager::canonicalizeRecur(StatementPtr s, int &ret) {
switch (stype) {
case Statement::KindOfUseTraitStatement:
case Statement::KindOfTraitRequireStatement:
case Statement::KindOfTraitPrecStatement:
case Statement::KindOfTraitAliasStatement:
return StatementPtr();
@@ -1969,7 +1968,7 @@ StatementPtr AliasManager::canonicalizeRecur(StatementPtr s, int &ret) {
}
case Statement::KindOfIfBranchStatement:
always_assert(false);
always_assert(0);
break;
case Statement::KindOfForStatement: {
@@ -3304,12 +3303,6 @@ private:
static bool isNewResult(ExpressionPtr e) {
if (!e) return false;
if (e->is(Expression::KindOfNewObjectExpression)) return true;
if (e->is(Expression::KindOfBinaryOpExpression)) {
auto b = spc(BinaryOpExpression, e);
if (b->getOp() == T_COLLECTION) {
return true;
}
}
if (e->is(Expression::KindOfAssignmentExpression)) {
return isNewResult(spc(AssignmentExpression, e)->getValue());
}
+48 -52
Ver Arquivo
@@ -32,7 +32,6 @@
#include "hphp/compiler/statement/loop_statement.h"
#include "hphp/compiler/statement/class_variable.h"
#include "hphp/compiler/statement/use_trait_statement.h"
#include "hphp/compiler/statement/trait_require_statement.h"
#include "hphp/compiler/analysis/symbol_table.h"
#include "hphp/compiler/package.h"
#include "hphp/compiler/parser/parser.h"
@@ -489,7 +488,8 @@ void AnalysisResult::link(FileScopePtr user, FileScopePtr provider) {
bool AnalysisResult::addClassDependency(FileScopePtr usingFile,
const std::string &className) {
if (m_systemClasses.find(className) != m_systemClasses.end())
if (BuiltinSymbols::s_classes.find(className) !=
BuiltinSymbols::s_classes.end())
return true;
StringToClassScopePtrVecMap::const_iterator iter =
@@ -507,7 +507,8 @@ bool AnalysisResult::addClassDependency(FileScopePtr usingFile,
bool AnalysisResult::addFunctionDependency(FileScopePtr usingFile,
const std::string &functionName) {
if (m_functions.find(functionName) != m_functions.end())
if (BuiltinSymbols::s_functions.find(functionName) !=
BuiltinSymbols::s_functions.end())
return true;
StringToFunctionScopePtrMap::const_iterator iter =
m_functionDecs.find(functionName);
@@ -569,16 +570,12 @@ bool AnalysisResult::isSystemConstant(const std::string &constName) const {
///////////////////////////////////////////////////////////////////////////////
// Program
void AnalysisResult::addSystemFunction(FunctionScopeRawPtr fs) {
FunctionScopePtr& entry = m_functions[fs->getName()];
assert(!entry);
entry = fs;
}
void AnalysisResult::addSystemClass(ClassScopeRawPtr cs) {
ClassScopePtr& entry = m_systemClasses[cs->getName()];
assert(!entry);
entry = cs;
void AnalysisResult::loadBuiltins() {
AnalysisResultPtr ar = shared_from_this();
BuiltinSymbols::LoadFunctions(ar, m_functions);
BuiltinSymbols::LoadClasses(ar, m_systemClasses);
BuiltinSymbols::LoadVariables(ar, m_variables);
BuiltinSymbols::LoadConstants(ar, m_constants);
}
void AnalysisResult::checkClassDerivations() {
@@ -590,11 +587,7 @@ void AnalysisResult::checkClassDerivations() {
hphp_string_iset seen;
cls->checkDerivation(ar, seen);
if (Option::WholeProgram) {
try {
cls->importUsedTraits(ar);
} catch (const AnalysisTimeFatalException& e) {
cls->setFatal(e);
}
cls->importUsedTraits(ar);
}
}
}
@@ -612,26 +605,22 @@ void AnalysisResult::resolveNSFallbackFuncs() {
}
void AnalysisResult::collectFunctionsAndClasses(FileScopePtr fs) {
for (const auto& iter : fs->getFunctions()) {
FunctionScopePtr func = iter.second;
const StringToFunctionScopePtrMap &funcs = fs->getFunctions();
for (StringToFunctionScopePtrMap::const_iterator iter = funcs.begin();
iter != funcs.end(); ++iter) {
FunctionScopePtr func = iter->second;
if (!func->inPseudoMain()) {
FunctionScopePtr &funcDec = m_functionDecs[iter.first];
FunctionScopePtr &funcDec = m_functionDecs[iter->first];
if (funcDec) {
if (funcDec->isSystem()) {
assert(funcDec->allowOverride());
funcDec = func;
} else if (func->isSystem()) {
assert(func->allowOverride());
} else {
FunctionScopePtrVec &funcVec = m_functionReDecs[iter.first];
int sz = funcVec.size();
if (!sz) {
funcDec->setRedeclaring(sz++);
funcVec.push_back(funcDec);
}
func->setRedeclaring(sz++);
funcVec.push_back(func);
FunctionScopePtrVec &funcVec = m_functionReDecs[iter->first];
int sz = funcVec.size();
if (!sz) {
funcDec->setRedeclaring(sz++);
funcVec.push_back(funcDec);
}
func->setRedeclaring(sz++);
funcVec.push_back(func);
} else {
funcDec = func;
}
@@ -639,12 +628,13 @@ void AnalysisResult::collectFunctionsAndClasses(FileScopePtr fs) {
}
if (const StringToFunctionScopePtrVecMap *redec = fs->getRedecFunctions()) {
for (const auto &iter : *redec) {
FunctionScopePtrVec::const_iterator i = iter.second.begin();
FunctionScopePtrVec::const_iterator e = iter.second.end();
FunctionScopePtr &funcDec = m_functionDecs[iter.first];
for (StringToFunctionScopePtrVecMap::const_iterator iter = redec->begin();
iter != redec->end(); ++iter) {
FunctionScopePtrVec::const_iterator i = iter->second.begin();
FunctionScopePtrVec::const_iterator e = iter->second.end();
FunctionScopePtr &funcDec = m_functionDecs[iter->first];
assert(funcDec); // because the first one was in funcs above
FunctionScopePtrVec &funcVec = m_functionReDecs[iter.first];
FunctionScopePtrVec &funcVec = m_functionReDecs[iter->first];
int sz = funcVec.size();
if (!sz) {
funcDec->setRedeclaring(sz++);
@@ -657,9 +647,11 @@ void AnalysisResult::collectFunctionsAndClasses(FileScopePtr fs) {
}
}
for (const auto& iter : fs->getClasses()) {
ClassScopePtrVec &clsVec = m_classDecs[iter.first];
clsVec.insert(clsVec.end(), iter.second.begin(), iter.second.end());
const StringToClassScopePtrVecMap &classes = fs->getClasses();
for (StringToClassScopePtrVecMap::const_iterator iter = classes.begin();
iter != classes.end(); ++iter) {
ClassScopePtrVec &clsVec = m_classDecs[iter->first];
clsVec.insert(clsVec.end(), iter->second.begin(), iter->second.end());
}
m_classAliases.insert(fs->getClassAliases().begin(),
@@ -1616,10 +1608,12 @@ void AnalysisResult::inferTypes() {
BlockScopeRawPtrQueue scopes;
getScopesSet(scopes);
for (auto scope : scopes) {
scope->setInTypeInference(true);
scope->clearUpdated();
assert(scope->getNumDepsToWaitFor() == 0);
for (BlockScopeRawPtrQueue::iterator
it = scopes.begin(), end = scopes.end();
it != end; ++it) {
(*it)->setInTypeInference(true);
(*it)->clearUpdated();
assert((*it)->getNumDepsToWaitFor() == 0);
}
#ifdef HPHP_INSTRUMENT_TYPE_INF
@@ -1630,11 +1624,13 @@ void AnalysisResult::inferTypes() {
processScopesParallel<InferTypes>("InferTypes");
for (auto scope : scopes) {
scope->setInTypeInference(false);
scope->clearUpdated();
assert(scope->getMark() == BlockScope::MarkProcessed);
assert(scope->getNumDepsToWaitFor() == 0);
for (BlockScopeRawPtrQueue::iterator
it = scopes.begin(), end = scopes.end();
it != end; ++it) {
(*it)->setInTypeInference(false);
(*it)->clearUpdated();
assert((*it)->getMark() == BlockScope::MarkProcessed);
assert((*it)->getNumDepsToWaitFor() == 0);
}
}
+2 -4
Ver Arquivo
@@ -24,7 +24,6 @@
#include "hphp/compiler/analysis/symbol_table.h"
#include "hphp/compiler/analysis/function_container.h"
#include "hphp/compiler/package.h"
#include "hphp/compiler/hphp.h"
#include "hphp/util/string-bag.h"
#include "hphp/util/thread-local.h"
@@ -37,7 +36,7 @@ namespace HPHP {
DECLARE_BOOST_TYPES(ClassScope);
DECLARE_EXTENDED_BOOST_TYPES(FileScope);
DECLARE_BOOST_TYPES(FileScope);
DECLARE_BOOST_TYPES(FunctionScope);
DECLARE_BOOST_TYPES(Location);
DECLARE_BOOST_TYPES(AnalysisResult);
@@ -151,8 +150,7 @@ public:
void addNSFallbackFunc(ConstructPtr c, FileScopePtr fs);
void addSystemFunction(FunctionScopeRawPtr fs);
void addSystemClass(ClassScopeRawPtr cs);
void loadBuiltins();
void analyzeProgram(bool system = false);
void analyzeIncludes();
void analyzeProgramFinal();
+3 -1
Ver Arquivo
@@ -155,7 +155,9 @@ bool BlockScope::hasUser(BlockScopeRawPtr user, int useKinds) const {
}
void BlockScope::addUse(BlockScopeRawPtr user, int useKinds) {
if ((is(ClassScope) || is(FunctionScope)) && getStmt()) {
if (is(ClassScope) ? static_cast<HPHP::ClassScope*>(this)->isUserClass() :
is(FunctionScope) &&
static_cast<HPHP::FunctionScope*>(this)->isUserFunction()) {
if (user.get() == this) {
m_selfUser |= useKinds;
-391
Ver Arquivo
@@ -1,391 +0,0 @@
/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP 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.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#include "hphp/compiler/analysis/capture_extractor.h"
#include "hphp/compiler/expression/join_clause.h"
#include "hphp/compiler/expression/scalar_expression.h"
#include "hphp/parser/hphp.tab.hpp"
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
/**
* Rewrites the construct rooted in cp so that it is in a form
* that a query processor can evaluate while referencing only
* state that is contained in the query processor or supplied
* to the query processor in the form of arguments to the query.
* For instance, a reference to a local variable in the scope
* containing the query expression will be rewritten into a
* reference to a (synthetic) parameter of the query expression.
* This is similar to the way lambda expressions capture variables
* from their enclosing environment.
* Note that rewriting implies allocating new objects.
* The original construct is not mutated in any way.
* If the original construct is already in the right form, it is
* returned as is.
*/
ExpressionPtr CaptureExtractor::rewrite(ExpressionPtr ep) {
assert(ep != nullptr);
switch (ep->getKindOf()) {
case Expression::KindOfQueryExpression: {
return rewriteQuery(static_pointer_cast<QueryExpression>(ep));
}
case Expression::KindOfSelectClause: {
// leave select clauses alone, another visitor deals with them.
return ep;
}
case Expression::KindOfFromClause:
case Expression::KindOfLetClause:
case Expression::KindOfIntoClause:
case Expression::KindOfWhereClause: {
return rewriteSimpleClause(static_pointer_cast<SimpleQueryClause>(ep));
}
case Expression::KindOfGroupClause:
case Expression::KindOfJoinClause:
case Expression::KindOfOrderbyClause:
case Expression::KindOfOrdering: {
// leave these alone. they are query specific and not parameterizable.
return ep;
}
case Expression::KindOfObjectPropertyExpression: {
return rewriteObjectProperty(
static_pointer_cast<ObjectPropertyExpression>(ep));
}
case Expression::KindOfSimpleFunctionCall: {
return rewriteCall(static_pointer_cast<SimpleFunctionCall>(ep));
}
case Expression::KindOfScalarExpression: {
// Leave scalars alone. If the query processor can't handle them
// rewriting won't help.
return ep;
}
case Expression::KindOfUnaryOpExpression: {
return rewriteUnary(static_pointer_cast<UnaryOpExpression>(ep));
}
case Expression::KindOfBinaryOpExpression: {
return rewriteBinary(static_pointer_cast<BinaryOpExpression>(ep));
}
case Expression::KindOfSimpleVariable: {
return rewriteSimpleVariable(static_pointer_cast<SimpleVariable>(ep));
}
case Expression::KindOfExpressionList: {
return rewriteExpressionList(static_pointer_cast<ExpressionList>(ep));
}
default: {
// If we get here, the expression is not a candidate for evaluation
// by the query processor, so just turn it into a query parameter.
return newQueryParamRef(ep);
}
}
}
/**
* Appends the given expression to end of the m_capturedExpressions list
* and creates a new expression with the same scope and source location
* that represents a reference to a query parameter. Query parameters do
* not have a source code equivalent, but inform the query processor that
* this expression represents the ith argument value, where i is zero based
* and forms the last character of the special string @query_param_i.
*/
SimpleVariablePtr CaptureExtractor::newQueryParamRef(ExpressionPtr ae) {
assert(ae != nullptr);
char count = '0' + m_capturedExpressions.size();
std::string pname = "@query_param_";
pname.push_back(count);
SimpleVariablePtr param(
new SimpleVariable(ae->getScope(), ae->getLocation(), pname)
);
m_capturedExpressions.push_back(ae);
return param;
}
/**
* If one or more of the arguments of the function call depend on query only
* state (query local but not a query parameter reference), then rewrite
* all of the arguments to be query local and return the rewritten
* function call (the query processor has to either figure out a way to call
* the function or must cause a runtime error when faced with the call).
* Otherwise, rewrite the call as a query parameter reference.
*/
ExpressionPtr CaptureExtractor::rewriteCall(SimpleFunctionCallPtr sfc) {
assert(sfc != nullptr);
if (sfc->hadBackslash() ||
(sfc->getClass() != nullptr && !sfc->getClassName().empty())) {
return newQueryParamRef(sfc);
}
auto args = sfc->getParams();
auto pc = args == nullptr ? 0 : args->getCount();
bool isQueryCall = false;
for (int i = 0; i < pc; i++) {
auto arg = (*args)[i];
assert(arg != nullptr);
isQueryCall |= this->dependsOnQueryOnlyState(arg);
}
if (!isQueryCall) return newQueryParamRef(sfc);
ExpressionListPtr newArgs(
new ExpressionList(args->getScope(), args->getLocation())
);
bool noRewrites = true;
for (int i = 0; i < pc; i++) {
auto arg = (*args)[i];
auto newArg = rewrite(arg);
if (arg != newArg) noRewrites = false;
newArgs->addElement(newArg);
}
if (noRewrites) return sfc;
SimpleFunctionCallPtr result(
new SimpleFunctionCall(sfc->getScope(), sfc->getLocation(),
sfc->getName(), false, newArgs, ExpressionPtr())
);
return result;
}
/**
* Traverses the expression tree rooted at e and returns true if
* any node in the tree is a simple variable that references a
* name in m_boundVars.
*/
bool CaptureExtractor::dependsOnQueryOnlyState(ExpressionPtr e) {
assert(e != nullptr);
if (e->getKindOf() == Expression::KindOfSimpleVariable) {
auto sv = static_pointer_cast<SimpleVariable>(e);
auto varName = sv->getName();
for (auto &boundVar : m_boundVars) {
if (varName == boundVar) return true;
}
return false;
}
auto numKids = e->getKidCount();
for (int i = 0; i < numKids; i++) {
auto ei = e->getNthExpr(i);
if (ei == nullptr) return false; //Default param
if (dependsOnQueryOnlyState(ei)) return true;
}
return false;
}
/**
* If a simple variable refers to a name bound inside the query
* then leave it alone. If not, rewrite it to be reference to
* a query parameter.
*/
SimpleVariablePtr CaptureExtractor::rewriteSimpleVariable(
SimpleVariablePtr sv) {
assert(sv != nullptr);
auto varName = sv->getName();
for (auto &boundVar : m_boundVars) {
if (varName == boundVar) return sv;
}
return newQueryParamRef(sv);
}
/**
* Query expressions introduce a local scope with names introduced
* by some of the clauses of the query expression. This needs
* special handling so that we can track variables local to the query.
*/
QueryExpressionPtr CaptureExtractor::rewriteQuery(QueryExpressionPtr qe) {
assert(qe != nullptr);
auto clauses = qe->getClauses();
auto newClauses = rewriteExpressionList(clauses);
if (clauses == newClauses) return qe;
QueryExpressionPtr result(
new QueryExpression(qe->getScope(), qe->getLocation(), newClauses)
);
return result;
}
/**
* Rewrites any expression query clauses in this list of clauses, taking care
* to track variables local to the query.
*/
ExpressionListPtr CaptureExtractor::rewriteExpressionList(ExpressionListPtr l) {
int np = 0;
int nc = l->getCount();
ExpressionListPtr newList(
new ExpressionList(l->getScope(), l->getLocation())
);
bool noRewrites = true;
for (int i = 0; i < nc; i++) {
auto e = (*l)[i];
assert(e != nullptr);
auto kind = e->getKindOf();
switch (kind) {
case Expression::KindOfIntoClause: {
// The into expression is in the scope of the into clause
SimpleQueryClausePtr qcp(static_pointer_cast<SimpleQueryClause>(e));
m_boundVars.push_back(qcp->getIdentifier());
np++;
break;
}
case Expression::KindOfJoinClause: {
JoinClausePtr jcp(static_pointer_cast<JoinClause>(e));
m_boundVars.push_back(jcp->getVar());
np++;
break;
}
default:
break;
}
auto ne = rewrite(e);
if (ne != e) noRewrites = false;
newList->addElement(ne);
// deal with clauses that introduce names for subsequent clauses
switch (kind) {
case Expression::KindOfFromClause:
case Expression::KindOfLetClause: {
SimpleQueryClausePtr qcp(static_pointer_cast<SimpleQueryClause>(e));
m_boundVars.push_back(qcp->getIdentifier());
np++;
break;
}
case Expression::KindOfJoinClause: {
JoinClausePtr jcp(static_pointer_cast<JoinClause>(e));
auto groupId = jcp->getGroup();
if (!groupId.empty()) {
m_boundVars.push_back(groupId);
np++;
}
break;
}
default:
break;
}
}
while (np-- > 0) m_boundVars.pop_back();
if (noRewrites) return l;
return newList;
}
/*
* If the expression of a simple query clause is query local, then
* return the clause as is. Otherwise return a clone of the clause
* with the expression rewritten to reference a query parameter.
*/
SimpleQueryClausePtr CaptureExtractor::rewriteSimpleClause(
SimpleQueryClausePtr sc) {
assert (sc != nullptr);
auto expr = sc->getExpression();
auto newExpr = rewrite(expr);
if (expr == newExpr) return sc;
auto rsc = static_pointer_cast<SimpleQueryClause>(sc->clone());
rsc->setExpression(newExpr);
return rsc;
}
/*
* If the object expression is query local, that is, if it is a simple variable
* referring to a name declared in a query clause, or itself a query local
* object expression, then if keep this expression as is. If not, then
* rewrite this expression into a query parameter reference.
*/
ExpressionPtr CaptureExtractor::rewriteObjectProperty(
ObjectPropertyExpressionPtr ope) {
assert(ope != nullptr);
auto obj = ope->getObject();
if (this->dependsOnQueryOnlyState(obj)) {
auto prop = ope->getProperty();
if (prop->getKindOf() == Expression::KindOfScalarExpression) {
auto scalar = static_pointer_cast<ScalarExpression>(prop);
const string &propName = scalar->getLiteralString();
if (!propName.empty()) {
return ope;
}
}
}
return newQueryParamRef(ope);
}
/**
* If the unary operation is not PHP specific, but something a query
* processor can handle (+ - ! ~), then rewrite the operand to something
* the query processor can evaluate (such as a query parameter reference)
* and rewrite the entire expression to use the rewritten operand.
* If the rewritten operand is the same as the original operand, just
* return the expression as is.
*/
ExpressionPtr CaptureExtractor::rewriteUnary(UnaryOpExpressionPtr ue) {
assert (ue != nullptr);
if (!ue->getFront()) return nullptr;
switch (ue->getOp()) {
case '+':
case '-':
case '!':
case '~':
break; // Could be something the query processor can handle
default:
return newQueryParamRef(ue);
}
auto expr = ue->getExpression();
auto newExpr = rewrite(expr);
if (expr == newExpr) return ue;
UnaryOpExpressionPtr result(
new UnaryOpExpression(ue->getScope(), ue->getLocation(),
newExpr, ue->getOp(), true)
);
return result;
}
/**
* If the binary operation is not PHP specific, but something a query
* processor can handle (+ - * and so on), then rewrite the operands to
* something the query processor can evaluate (such as a query parameter
* references) and rewrite the entire expression to use the rewritten operands.
* If the rewritten operands are the same as the original operands, just
* return the expression as is.
*/
ExpressionPtr CaptureExtractor::rewriteBinary(BinaryOpExpressionPtr be) {
assert(be != nullptr);
switch (be->getOp()) {
case '+':
case '-':
case '*':
case '/':
case '%':
case '&':
case '|':
case '^':
case T_IS_IDENTICAL:
case T_IS_EQUAL:
case '>':
case '<':
case T_IS_GREATER_OR_EQUAL:
case T_IS_SMALLER_OR_EQUAL:
case T_IS_NOT_IDENTICAL:
case T_IS_NOT_EQUAL:
case T_BOOLEAN_OR:
case T_BOOLEAN_AND:
case T_LOGICAL_OR:
case T_LOGICAL_AND:
case '.':
break; // Could be something the query processor can handle
default:
return newQueryParamRef(be);
}
auto expr1 = be->getExp1();
auto expr2 = be->getExp2();
auto newExpr1 = rewrite(expr1);
auto newExpr2 = rewrite(expr2);
if (expr1 == newExpr1 && expr2 == newExpr2) return be;
BinaryOpExpressionPtr result(
new BinaryOpExpression(be->getScope(), be->getLocation(),
newExpr1, newExpr2, be->getOp())
);
return result;
}
}
-66
Ver Arquivo
@@ -1,66 +0,0 @@
/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP 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.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#ifndef incl_HPHP_CAPTURE_EXTRACTOR_H_
#define incl_HPHP_CAPTURE_EXTRACTOR_H_
#include "hphp/compiler/expression/binary_op_expression.h"
#include "hphp/compiler/expression/expression.h"
#include "hphp/compiler/expression/object_property_expression.h"
#include "hphp/compiler/expression/query_expression.h"
#include "hphp/compiler/expression/simple_function_call.h"
#include "hphp/compiler/expression/simple_query_clause.h"
#include "hphp/compiler/expression/simple_variable.h"
#include "hphp/compiler/expression/unary_op_expression.h"
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
/** A rewriter for query expressions that capture variables that lie
* outside of the scope of the query expression. Subexpressions that
* contain such references are turned into references to query parameter
* variables. The original expressions are collected into the list
* returned by getCapturedEpressions. Their runtime values are obtained
* before the query is evaluated and are passed as arguments to the query
* processor.
*/
class CaptureExtractor {
public:
ExpressionPtr rewrite(ExpressionPtr ep);
std::vector<ExpressionPtr> getCapturedExpressions() {
return m_capturedExpressions;
}
private:
bool dependsOnQueryOnlyState(ExpressionPtr e);
SimpleVariablePtr newQueryParamRef(ExpressionPtr ae);
ExpressionPtr rewriteBinary(BinaryOpExpressionPtr be);
ExpressionPtr rewriteCall(SimpleFunctionCallPtr sfc);
ExpressionListPtr rewriteExpressionList(ExpressionListPtr l);
ExpressionPtr rewriteObjectProperty(ObjectPropertyExpressionPtr ope);
QueryExpressionPtr rewriteQuery(QueryExpressionPtr qe);
SimpleQueryClausePtr rewriteSimpleClause(SimpleQueryClausePtr sc);
SimpleVariablePtr rewriteSimpleVariable(SimpleVariablePtr sv);
ExpressionPtr rewriteUnary(UnaryOpExpressionPtr ue);
std::vector<ExpressionPtr> m_capturedExpressions;
std::vector<std::string> m_boundVars;
};
}
#endif // incl_HPHP_CAPTURE_EXTRACTOR_H_
+21 -129
Ver Arquivo
@@ -39,7 +39,6 @@
#include "hphp/compiler/statement/class_variable.h"
#include "hphp/compiler/statement/class_constant.h"
#include "hphp/compiler/statement/use_trait_statement.h"
#include "hphp/compiler/statement/trait_require_statement.h"
#include "hphp/compiler/statement/trait_prec_statement.h"
#include "hphp/compiler/statement/trait_alias_statement.h"
#include "hphp/runtime/base/zend-string.h"
@@ -474,17 +473,6 @@ void ClassScope::addImportTraitMethod(const TraitMethod &traitMethod,
m_importMethToTraitMap[methName].push_back(traitMethod);
}
void ClassScope::addTraitRequirement(const string &requiredName,
bool isExtends) {
assert(isTrait());
if (isExtends) {
m_traitRequiredExtends.insert(requiredName);
} else {
m_traitRequiredImplements.insert(requiredName);
}
}
void
ClassScope::setImportTraitMethodModifiers(const string &methName,
ClassScopePtr traitCls,
@@ -545,7 +533,6 @@ ClassScope::findTraitMethod(AnalysisResultPtr ar,
void ClassScope::findTraitMethodsToImport(AnalysisResultPtr ar,
ClassScopePtr trait) {
assert(Option::WholeProgram);
ClassStatementPtr tStmt =
dynamic_pointer_cast<ClassStatement>(trait->getStmt());
StatementListPtr tStmts = tStmt->getStmts();
@@ -562,45 +549,7 @@ void ClassScope::findTraitMethodsToImport(AnalysisResultPtr ar,
}
}
void ClassScope::importTraitRequirements(AnalysisResultPtr ar,
ClassScopePtr trait) {
if (isTrait()) {
for (auto const& req : trait->getTraitRequiredExtends()) {
addTraitRequirement(req, true);
}
for (auto const& req : trait->getTraitRequiredImplements()) {
addTraitRequirement(req, false);
}
} else {
for (auto const& req : trait->getTraitRequiredExtends()) {
if (!derivesFrom(ar, req, true, false)) {
getStmt()->analysisTimeFatal(
Compiler::InvalidDerivation,
Strings::TRAIT_REQ_EXTENDS,
m_originalName.c_str(),
req.c_str(),
trait->getOriginalName().c_str(),
"use"
);
}
}
for (auto const& req : trait->getTraitRequiredImplements()) {
if (!derivesFrom(ar, req, true, false)) {
getStmt()->analysisTimeFatal(
Compiler::InvalidDerivation,
Strings::TRAIT_REQ_IMPLEMENTS,
m_originalName.c_str(),
req.c_str(),
trait->getOriginalName().c_str(),
"use"
);
}
}
}
}
void ClassScope::applyTraitPrecRule(TraitPrecStatementPtr stmt) {
assert(Option::WholeProgram);
const string methodName = Util::toLower(stmt->getMethodName());
const string selectedTraitName = Util::toLower(stmt->getTraitName());
std::set<string> otherTraitNames;
@@ -631,20 +580,12 @@ void ClassScope::applyTraitPrecRule(TraitPrecStatementPtr stmt) {
// Report error if didn't find the selected trait
if (!foundSelectedTrait) {
stmt->analysisTimeFatal(
Compiler::UnknownTrait,
Strings::TRAITS_UNKNOWN_TRAIT,
selectedTraitName.c_str()
);
Compiler::Error(Compiler::UnknownTrait, stmt);
}
// Sanity checking: otherTraitNames should be empty now
if (otherTraitNames.size()) {
stmt->analysisTimeFatal(
Compiler::UnknownTrait,
Strings::TRAITS_UNKNOWN_TRAIT,
selectedTraitName.c_str()
);
Compiler::Error(Compiler::UnknownTrait, stmt);
}
}
@@ -655,7 +596,6 @@ bool ClassScope::hasMethod(const string &methodName) const {
ClassScopePtr
ClassScope::findSingleTraitWithMethod(AnalysisResultPtr ar,
const string &methodName) const {
assert(Option::WholeProgram);
ClassScopePtr trait = ClassScopePtr();
for (unsigned i = 0; i < m_usedTraitNames.size(); i++) {
@@ -673,7 +613,6 @@ ClassScope::findSingleTraitWithMethod(AnalysisResultPtr ar,
}
void ClassScope::addTraitAlias(TraitAliasStatementPtr aliasStmt) {
assert(Option::WholeProgram);
const string &traitName = aliasStmt->getTraitName();
const string &origMethName = aliasStmt->getMethodName();
const string &newMethName = aliasStmt->getNewMethodName();
@@ -684,7 +623,6 @@ void ClassScope::addTraitAlias(TraitAliasStatementPtr aliasStmt) {
void ClassScope::applyTraitAliasRule(AnalysisResultPtr ar,
TraitAliasStatementPtr stmt) {
assert(Option::WholeProgram);
const string traitName = Util::toLower(stmt->getTraitName());
const string origMethName = Util::toLower(stmt->getMethodName());
const string newMethName = Util::toLower(stmt->getNewMethodName());
@@ -697,11 +635,8 @@ void ClassScope::applyTraitAliasRule(AnalysisResultPtr ar,
traitCls = ar->findClass(traitName);
}
if (!traitCls || !(traitCls->isTrait())) {
stmt->analysisTimeFatal(
Compiler::UnknownTrait,
Strings::TRAITS_UNKNOWN_TRAIT,
traitName.empty() ? origMethName.c_str() : traitName.c_str()
);
Compiler::Error(Compiler::UnknownTrait, stmt);
return;
}
// Keep record of alias rule
@@ -712,10 +647,8 @@ void ClassScope::applyTraitAliasRule(AnalysisResultPtr ar,
MethodStatementPtr methStmt = findTraitMethod(ar, traitCls, origMethName,
visitedTraits);
if (!methStmt) {
stmt->analysisTimeFatal(
Compiler::UnknownTraitMethod,
Strings::TRAITS_UNKNOWN_TRAIT_METHOD, origMethName.c_str()
);
Compiler::Error(Compiler::UnknownTraitMethod, stmt);
return;
}
if (origMethName == newMethName) {
@@ -730,7 +663,6 @@ void ClassScope::applyTraitAliasRule(AnalysisResultPtr ar,
}
void ClassScope::applyTraitRules(AnalysisResultPtr ar) {
assert(Option::WholeProgram);
ClassStatementPtr classStmt = dynamic_pointer_cast<ClassStatement>(getStmt());
assert(classStmt);
StatementListPtr stmts = classStmt->getStmts();
@@ -763,7 +695,6 @@ void ClassScope::applyTraitRules(AnalysisResultPtr ar) {
// 1) implemented by other traits
// 2) duplicate
void ClassScope::removeSpareTraitAbstractMethods(AnalysisResultPtr ar) {
assert(Option::WholeProgram);
for (MethodToTraitListMap::iterator iter = m_importMethToTraitMap.begin();
iter != m_importMethToTraitMap.end(); iter++) {
@@ -801,17 +732,9 @@ void ClassScope::removeSpareTraitAbstractMethods(AnalysisResultPtr ar) {
}
void ClassScope::importUsedTraits(AnalysisResultPtr ar) {
// Trait flattening is supposed to happen only when we have awareness of
// the whole program.
assert(Option::WholeProgram);
if (m_traitStatus == FLATTENED) return;
if (m_traitStatus == BEING_FLATTENED) {
getStmt()->analysisTimeFatal(
Compiler::CyclicDependentTraits,
"Cyclic dependency between traits involving %s",
getOriginalName().c_str()
);
Compiler::Error(Compiler::CyclicDependentTraits, getStmt());
return;
}
if (m_usedTraitNames.size() == 0) {
@@ -828,53 +751,18 @@ void ClassScope::importUsedTraits(AnalysisResultPtr ar) {
}
}
if (isTrait()) {
for (auto const& req : getTraitRequiredExtends()) {
ClassScopePtr rCls = ar->findClass(req);
if (!rCls || rCls->isFinal() || rCls->isInterface()) {
getStmt()->analysisTimeFatal(
Compiler::InvalidDerivation,
Strings::TRAIT_BAD_REQ_EXTENDS,
m_originalName.c_str(),
req.c_str(),
req.c_str()
);
}
}
for (auto const& req : getTraitRequiredImplements()) {
ClassScopePtr rCls = ar->findClass(req);
if (!rCls || !(rCls->isInterface())) {
getStmt()->analysisTimeFatal(
Compiler::InvalidDerivation,
Strings::TRAIT_BAD_REQ_IMPLEMENTS,
m_originalName.c_str(),
req.c_str(),
req.c_str()
);
}
}
}
// Find trait methods to be imported
for (unsigned i = 0; i < m_usedTraitNames.size(); i++) {
ClassScopePtr tCls = ar->findClass(m_usedTraitNames[i]);
if (!tCls || !(tCls->isTrait())) {
setAttribute(UsesUnknownTrait); // XXX: is this useful ... for anything?
getStmt()->analysisTimeFatal(
Compiler::UnknownTrait,
Strings::TRAITS_UNKNOWN_TRAIT,
m_usedTraitNames[i].c_str()
);
setAttribute(UsesUnknownTrait);
Compiler::Error(Compiler::UnknownTrait, getStmt());
continue;
}
// First, make sure the used trait is flattened
tCls->importUsedTraits(ar);
findTraitMethodsToImport(ar, tCls);
// Import any interfaces implemented
tCls->getInterfaces(ar, m_bases, false);
importTraitRequirements(ar, tCls);
}
// Apply rules
@@ -894,7 +782,7 @@ void ClassScope::importUsedTraits(AnalysisResultPtr ar) {
}
std::map<string, MethodStatementPtr> importedTraitMethods;
std::vector<std::pair<string,const TraitMethod*>> importedTraitsWithOrigName;
std::vector<std::pair<string,const TraitMethod*> > importedTraitsWithOrigName;
// Actually import the methods
for (MethodToTraitListMap::const_iterator
@@ -908,11 +796,7 @@ void ClassScope::importUsedTraits(AnalysisResultPtr ar) {
}
// Consistency checking: each name must only refer to one imported method
if (iter->second.size() > 1) {
getStmt()->analysisTimeFatal(
Compiler::MethodInMultipleTraits,
Strings::METHOD_IN_MULTIPLE_TRAITS,
iter->first.c_str()
);
Compiler::Error(Compiler::MethodInMultipleTraits, getStmt());
} else {
TraitMethodList::const_iterator traitMethIter = iter->second.begin();
if ((traitMethIter->m_modifiers ? traitMethIter->m_modifiers :
@@ -923,6 +807,13 @@ void ClassScope::importUsedTraits(AnalysisResultPtr ar) {
continue;
}
}
if (traitMethIter->m_modifiers &&
traitMethIter->m_modifiers->isStatic()) {
Compiler::Error(Compiler::InvalidAccessModifier,
traitMethIter->m_modifiers);
continue;
}
string sourceName = traitMethIter->m_ruleStmt ?
Util::toLower(((TraitAliasStatement*)traitMethIter->m_ruleStmt.get())->
getMethodName()) : iter->first;
@@ -1243,7 +1134,8 @@ void ClassScope::getInterfaces(AnalysisResultConstPtr ar,
if (cls && cls->isRedeclaring()) {
cls = self->findExactClass(cls);
}
names.push_back(cls ? cls->getDocName() : *it);
if (cls) names.push_back(cls->getDocName());
else names.push_back(*it);
if (cls && recursive) {
cls->getInterfaces(ar, names, true);
}
+3 -34
Ver Arquivo
@@ -24,9 +24,8 @@
#include "hphp/compiler/statement/trait_prec_statement.h"
#include "hphp/compiler/statement/trait_alias_statement.h"
#include "hphp/compiler/expression/user_attribute.h"
#include "hphp/compiler/json.h"
#include "hphp/util/functional.h"
#include "hphp/util/hash-map-typedefs.h"
#include "hphp/util/json.h"
#include "hphp/util/case-insensitive.h"
#include "hphp/compiler/option.h"
namespace HPHP {
@@ -174,7 +173,6 @@ public:
* Get/set attributes.
*/
void setSystem();
bool isSystem() const { return m_attribute & System; }
void setAttribute(Attribute attr) { m_attribute |= attr;}
void clearAttribute(Attribute attr) { m_attribute &= ~attr;}
bool getAttribute(Attribute attr) const {
@@ -303,29 +301,17 @@ public:
}
}
const boost::container::flat_set<std::string>& getTraitRequiredExtends()
const {
return m_traitRequiredExtends;
}
const boost::container::flat_set<std::string>& getTraitRequiredImplements()
const {
return m_traitRequiredImplements;
}
const std::vector<std::string> &getUsedTraitNames() const {
return m_usedTraitNames;
}
const std::vector<std::pair<std::string, std::string>>& getTraitAliases()
const std::vector<std::pair<std::string, std::string> > &getTraitAliases()
const {
return m_traitAliases;
}
void addTraitAlias(TraitAliasStatementPtr aliasStmt);
void addTraitRequirement(const std::string &requiredName, bool isExtends);
void importUsedTraits(AnalysisResultPtr ar);
/**
@@ -383,16 +369,6 @@ public:
bool canSkipCreateMethod(AnalysisResultConstPtr ar) const;
bool checkHasPropTable(AnalysisResultConstPtr ar);
const StringData* getFatalMessage() const {
return m_fatal_error_msg;
}
void setFatal(const AnalysisTimeFatalException& fatal) {
assert(m_fatal_error_msg == nullptr);
m_fatal_error_msg = makeStaticString(fatal.getMessage());
assert(m_fatal_error_msg != nullptr);
}
private:
// need to maintain declaration order for ClassInfo map
FunctionScopePtrVec m_functionsVec;
@@ -402,8 +378,6 @@ private:
UserAttributeMap m_userAttributes;
std::vector<std::string> m_usedTraitNames;
boost::container::flat_set<std::string> m_traitRequiredExtends;
boost::container::flat_set<std::string> m_traitRequiredImplements;
// m_traitAliases is used to support ReflectionClass::getTraitAliases
std::vector<std::pair<std::string, std::string> > m_traitAliases;
@@ -453,9 +427,6 @@ private:
// bases 32 through n are all known.
unsigned m_knownBases;
// holds the fact that accessing this class declaration is a fatal error
const StringData* m_fatal_error_msg = nullptr;
void addImportTraitMethod(const TraitMethod &traitMethod,
const std::string &methName);
void informClosuresAboutScopeClone(ConstructPtr root,
@@ -476,8 +447,6 @@ private:
void findTraitMethodsToImport(AnalysisResultPtr ar, ClassScopePtr trait);
void importTraitRequirements(AnalysisResultPtr ar, ClassScopePtr trait);
MethodStatementPtr findTraitMethod(AnalysisResultPtr ar,
ClassScopePtr trait,
const std::string &methodName,
+1 -1
Ver Arquivo
@@ -18,7 +18,7 @@
#define incl_HPHP_COMPILER_ERROR_H_
#include "hphp/compiler/analysis/type.h"
#include "hphp/compiler/json.h"
#include "hphp/util/json.h"
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
-1
Ver Arquivo
@@ -245,7 +245,6 @@ int ControlFlowBuilder::before(ConstructRawPtr cp) {
Statement::KindOf stype = s->getKindOf();
switch (stype) {
case Statement::KindOfUseTraitStatement:
case Statement::KindOfTraitRequireStatement:
case Statement::KindOfTraitPrecStatement:
case Statement::KindOfTraitAliasStatement:
not_reached();
+1 -1
Ver Arquivo
@@ -37,6 +37,7 @@ CODE_ERROR_ENTRY(InvalidAttribute)
CODE_ERROR_ENTRY(UnknownTrait)
CODE_ERROR_ENTRY(MethodInMultipleTraits)
CODE_ERROR_ENTRY(UnknownTraitMethod)
CODE_ERROR_ENTRY(InvalidAccessModifier)
CODE_ERROR_ENTRY(CyclicDependentTraits)
CODE_ERROR_ENTRY(InvalidTraitStatement)
CODE_ERROR_ENTRY(RedeclaredTrait)
@@ -44,4 +45,3 @@ CODE_ERROR_ENTRY(InvalidInstantiation)
CODE_ERROR_ENTRY(InvalidYield)
CODE_ERROR_ENTRY(InvalidAwait)
CODE_ERROR_ENTRY(BadDefaultValueType)
CODE_ERROR_ENTRY(InvalidMethodDefinition)
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+206 -161
Ver Arquivo
@@ -20,7 +20,6 @@
#include "hphp/compiler/expression/expression.h"
#include "hphp/compiler/statement/statement.h"
#include "hphp/compiler/statement/use_trait_statement.h"
#include "hphp/compiler/statement/trait_require_statement.h"
#include "hphp/compiler/statement/trait_prec_statement.h"
#include "hphp/compiler/statement/trait_alias_statement.h"
#include "hphp/compiler/statement/typedef_statement.h"
@@ -111,7 +110,7 @@ public:
typ1 a1, typ2 a2, typ3 a3
#define FOUR(typ1, typ2, typ3, typ4) \
typ1 a1, typ2 a2, typ3 a3, typ4 a4
#define MA std::vector<unsigned char>
#define MA std::vector<uchar>
#define BLA std::vector<Label*>&
#define SLA std::vector<StrOff>&
#define ILA std::vector<IterPair>&
@@ -123,7 +122,7 @@ public:
#define SA const StringData*
#define AA ArrayData*
#define BA Label&
#define OA(type) type
#define OA unsigned char
#define VSA std::vector<std::string>&
OPCODES
#undef O
@@ -330,130 +329,240 @@ public:
Label m_entry;
};
DECLARE_BOOST_TYPES(ControlTarget);
/*
* The structure represents a code path that potentially requires
* running finally blocks. A code path has an assigned state ID that
* is used inside switch statements emitted at the end of finally
* blocks. It also has an optional label (the destination to jump
* to after all the required finally blocks are run).
*/
struct ControlTarget {
static const int k_unsetState;
explicit ControlTarget(EmitterVisitor* router);
~ControlTarget();
// Manage state ID reuse.
bool isRegistered();
EmitterVisitor* m_visitor;
// The target to jump to once all the necessary finally blocks are run.
Label m_label;
// The state ID that identifies this control target inside finally
// epilogues. This ID assigned to the "state" unnamed local variable.
int m_state;
};
struct ControlTargetInfo {
ControlTargetInfo() : used(false) {}
ControlTargetInfo(ControlTargetPtr t, bool b) : target(t), used(b) {}
ControlTargetPtr target;
bool used;
};
class FinallyRouter;
DECLARE_BOOST_TYPES(Region);
DECLARE_BOOST_TYPES(FinallyRouterEntry);
/*
* Region represents a single level of the unified stack
* FinallyRouterEntry represents a single level of the unified stack
* of constructs that are meaningful from the point of view of finally
* implementation. The levels are used to keep track of the information
* such as the control targets that can be taken inside a block.
* such as the actions that can be taken inside a block.
*/
class Region {
class FinallyRouterEntry {
public:
enum Kind {
enum EntryKind {
// Top-level (global) context.
Global,
GlobalEntry,
// Function body / method body entry.
FuncBody,
FuncBodyEntry,
// Entry for finally fault funclets emitted after the body of
// a function
FaultFunclet,
// Region by a finally clause
TryFinally,
FuncFaultEntry,
// Try block entry (begins with try ends after catches).
TryFinallyEntry,
// Finally block entry (begins after catches ends after finally)
Finally,
// Loop or switch statement.
LoopOrSwitch,
FinallyEntry,
// Loop OR a break statement.
LoopEntry,
};
typedef Emitter::IterPair IterPair;
typedef std::vector<IterPair> IterVec;
Region(Region::Kind kind, RegionPtr parent);
DECLARE_BOOST_TYPES(Action);
/*
* The structure represents a code path that potentially requires
* running finally blocks. A code path has an assigned state ID that
* is used inside switch statements emitted at the end of finally
* blocks. It also has an optional label (the destination to jump
* to after all the required finally blocks are run).
*/
struct Action {
static const int k_unsetState;
explicit Action(FinallyRouter* router);
~Action();
// Manage state ID reuse.
bool isAllocated();
void allocate();
void release();
FinallyRouter* m_router;
// The target to jump to once all the necessary finally blocks
// are run.
Label m_label;
// The state ID that identifies this action inside finally switch
// statements. This is the id assigned to the "state" unnamed
// local variable.
int m_state;
};
FinallyRouterEntry(FinallyRouter* router,
EntryKind kind,
FinallyRouterEntryPtr parent);
~FinallyRouterEntry();
// Helpers used for freeing iterators when appropriate actions
// require that.
void emitIterBreak(Emitter& e,
IterVec& iters,
Label& target);
void emitIterFree(Emitter& e, IterVec& iters);
void emitIterFree(Emitter& e);
// Emission of code snippets commencing actions. Method
// emitXYZ(e, ...) should be used instead of e.XYZ(...) in
// EmitterVisitor.
void emitReturn(Emitter& e, char sym);
void emitReturnImpl(Emitter& e,
char sym,
IterVec& iters);
void emitGoto(Emitter& e, StringData* name);
void emitGotoImpl(Emitter& e,
StringData* name,
IterVec& iters);
void emitBreak(Emitter& e, int depth);
void emitBreakImpl(Emitter& e,
int depth,
IterVec& iters);
void emitContinue(Emitter& e, int depth);
void emitContinueImpl(Emitter& e,
int depth,
IterVec& iters);
// Emit the switch statement in the finally epilogue. Optimizes
// cases where there is either just a fall-through case, or where
// there is a single case other than fall-through.
void emitFinallySwitch(Emitter& e);
// Helper for emitting beginning of single case from the finally
// epilogue.
void emitCase(Emitter& e, std::vector<Label*>& cases, ActionPtr action);
void emitReturnCase(Emitter& e, std::vector<Label*>& cases, char sym);
void emitReturnCaseImpl(Emitter& e, char sym, IterVec& iters);
void emitBreakCase(Emitter& e, std::vector<Label*>& cases, int depth);
void emitBreakCaseImpl(Emitter& e, int depth, IterVec& iters);
void emitContinueCase(Emitter& e, std::vector<Label*>& cases, int depth);
void emitContinueCaseImpl(Emitter& e, int depth, IterVec& iters);
// Helper for establishing the maximal depth of break / continue
// control targets that are allocated.
// actions that are allocated.
int getBreakContinueDepth();
// Returns the maximal break / continue depth admissable (aka the
// number of nested loops).
int getMaxBreakContinueDepth();
int getMaxState();
// Methods used for emitting different cases for the finally
// epilogue switch.
void emitGotoCase(Emitter& e, std::vector<Label*>& cases, StringData* name);
void emitGotoCaseImpl(Emitter& e, StringData* name, IterVec& iters);
void emitReturnCases(Emitter& e, std::vector<Label*>& cases);
void emitGotoCases(Emitter& e, std::vector<Label*>& cases);
void emitBreakContinueCases(Emitter& e, std::vector<Label*>& cases);
void emitAllCases(Emitter& e, std::vector<Label*>& cases);
// Methods used for collecting labels corresponding to the cases
// from the finally epilogue. All the labels are accumulated
// inside the cases array. The array is eventually passed to
// e.Switch as the immediate argument.
void collectReturnCases(std::vector<Label*>& cases);
void collectGotoCases(std::vector<Label*>& cases);
void collectBreakContinueCases(std::vector<Label*>& cases);
void collectCase(std::vector<Label*>& cases,
ActionPtr action);
void collectAllCases(std::vector<Label*>& cases);
// The number of cases to be emitted. This is a helper used in
// establishing whether one of the optimized cases can be used.
int getCaseCount();
bool isForeach() { return m_iterId != -1; }
bool isTryFinally() { return m_kind == Region::Kind::TryFinally; }
bool isFinally() { return m_kind == Region::Kind::Finally; }
// Methods used for allocating new finally-aware code-paths.
// When alloc is set to false, the action is merely allocated in
// memory and shared among different entries. When alloc is set to
// true, the action is additionally assigned a state ID.
ActionPtr registerReturn(StatementPtr s, char sym);
ActionPtr registerGoto(StatementPtr s, StringData* name, bool alloc);
ActionPtr registerBreak(StatementPtr s, int depth, bool alloc);
ActionPtr registerContinue(StatementPtr s, int depth, bool alloc);
// Used to indicate that a particular label is present inside
// an entry. Labels don't have corresponding actions, however
// they need to be tracked in order to handle gotos appropriately.
void registerLabel(StatementPtr s, StringData* name);
// Yield / await is not supported inside a finally block for now.
// This method throws a parse time fatal whenever appropriate.
void registerYieldAwait(ExpressionPtr e);
bool isBreakUsed(int i) {
auto it = m_breakTargets.find(i);
if (it == m_breakTargets.end()) return false;
return it->second.used;
}
bool isContinueUsed(int i) {
auto it = m_continueTargets.find(i);
if (it == m_continueTargets.end()) return false;
return it->second.used;
}
Region::Kind m_kind;
FinallyRouter* m_router;
EntryKind m_kind;
// Only used for loop / break kind of entries.
Id m_iterId;
IterKind m_iterKind;
bool m_iterRef;
// Because of a bug in code emission, functions sometimes have
// inconsistent return flavors. Therefore instead of a single
// return control target, there need to be one return control
// target per flavor used. Once the bug is removed, this code
// can be simplified.
std::map<char, ControlTargetInfo> m_returnTargets;
// Break and continue control targets identified by their depth.
std::map<int, ControlTargetInfo> m_breakTargets;
std::map<int, ControlTargetInfo> m_continueTargets;
// Goto control targets. Each goto control target is identified
// by the name of the destination label.
std::map<StringData*, ControlTargetInfo, string_data_lt> m_gotoTargets;
// A set of goto labels occurrning inside the statement represented
// inconsistent return flavours. Therefore instead of a single
// return action, there need to be one return action per flavor
// used. Once the bug is removed, this code can be simplified.
std::map<char, ActionPtr> m_returnActions;
// A map of goto actions. Each goto action is identified by the
// name of the destination label.
std::map<StringData*, ActionPtr, string_data_lt> m_gotoActions;
// A map of goto labels occurrning inside the statement represented
// by this entry. This value is used for establishing whether
// a finally block needs to be executed when performing gotos.
std::set<StringData*, string_data_lt> m_gotoLabels;
// Continue actions identified by their depth.
std::map<int, ActionPtr> m_continueActions;
// Break actions identified by their depth.
std::map<int, ActionPtr> m_breakActions;
// The label denoting the beginning of a finally block inside the
// current try. Only used when the entry kind is a try statement.
Label m_finallyLabel;
// The cases that need to be included in the switch statement. Only
// used when kind is set to try statement.
// These are the actions that are invoked inside the protected region
// protected by the try represented by this entry.
std::set<ActionPtr> m_finallyCases;
// The parent entry.
RegionPtr m_parent;
FinallyRouterEntryPtr m_parent;
};
class FinallyRouter {
public:
typedef FinallyRouterEntry::EntryKind EntryKind;
FinallyRouter();
~FinallyRouter();
// The top entry on the unified stack.
FinallyRouterEntryPtr top();
// Create an entry corresponding to the passed in statement s.
// If the statement is insignificant (e.g. is an if statement),
// nullptr is returned.
FinallyRouterEntryPtr createForStatement(StatementPtr s);
// Create a global (top-level) entry.
FinallyRouterEntryPtr createGlobal(StatementPtr s);
// Create an entry for a functiob body.
FinallyRouterEntryPtr createFuncBody(StatementPtr s);
// Create an entry for a fault funclet inside a function body
FinallyRouterEntryPtr createFuncFault(StatementPtr s);
// Helper function for creating entries.
FinallyRouterEntryPtr create(StatementPtr s, EntryKind kind);
// Enter/leave the passed in entry. Note that entries sometimes need be
// to be constructed before they are entered, or need to be accessed
// after they are left. This especially applies to constructs such
// as loops and try blocks.
void enter(FinallyRouterEntryPtr);
void leave(FinallyRouterEntryPtr);
// Functions used for handling state IDs allocation.
// FIXME (#3275259): This should be moved into global / func
// body / fault funclet entries in order to optimize state
// allocation. See the task description for more details.
int allocateState();
void releaseState(int state);
// The stack of all the entered entries.
std::vector<FinallyRouterEntryPtr> m_entries;
// The state IDs currently allocated. See FIXME above.
std::set<int> m_states;
};
class EmitterVisitor {
friend class UnsetUnnamedLocalThunklet;
friend class FuncFinisher;
public:
typedef std::vector<int> IndexChain;
typedef Emitter::IterPair IterPair;
typedef std::vector<IterPair> IterVec;
explicit EmitterVisitor(UnitEmitter& ue);
~EmitterVisitor();
@@ -465,7 +574,7 @@ public:
void assignFinallyVariableIds();
void fixReturnType(Emitter& e, FunctionCallPtr fn,
Func* builtinFunc = nullptr);
typedef std::vector<int> IndexChain;
void visitListAssignmentLHS(Emitter& e, ExpressionPtr exp,
IndexChain& indexChain,
std::vector<IndexChain*>& chainList);
@@ -501,13 +610,13 @@ public:
|| isJumpTarget(m_ue.bcPos())
|| (instrFlags(getPrevOpcode()) & TF) == 0);
}
FuncEmitter* getFuncEmitter() { return m_curFunc; }
FinallyRouter& getFinallyRouter() { return m_finallyRouter; }
Id getStateLocal() {
assert(m_stateLocal >= 0);
DCHECK(m_stateLocal >= 0);
return m_stateLocal;
}
Id getRetLocal() {
assert(m_retLocal >= 0);
DCHECK(m_retLocal >= 0);
return m_retLocal;
}
@@ -579,11 +688,11 @@ private:
FuncEmitter* m_fe;
};
class CatchRegion {
class ExnHandlerRegion {
public:
CatchRegion(Offset start, Offset end) : m_start(start),
ExnHandlerRegion(Offset start, Offset end) : m_start(start),
m_end(end) {}
~CatchRegion() {
~ExnHandlerRegion() {
for (std::vector<std::pair<StringData*, Label*> >::const_iterator it =
m_catchLabels.begin(); it != m_catchLabels.end(); it++) {
delete it->second;
@@ -662,31 +771,24 @@ private:
static EmittedClosures s_emittedClosures;
std::deque<Funclet*> m_funclets;
std::map<StatementPtr, Funclet*> m_memoizedFunclets;
std::deque<CatchRegion*> m_catchRegions;
std::deque<ExnHandlerRegion*> m_exnHandlers;
std::deque<FaultRegion*> m_faultRegions;
std::deque<FPIRegion*> m_fpiRegions;
std::vector<Array> m_staticArrays;
std::set<std::string,stdltistr> m_hoistables;
LocationPtr m_tempLoc;
std::vector<Label> m_yieldLabels;
// The stack of all Regions that this EmitterVisitor is currently inside
std::vector<RegionPtr> m_regions;
// The state IDs currently allocated for the "finally router" logic.
// See FIXME above the registerControlTarget() method.
std::set<int> m_states;
// Unnamed local variables used by the "finally router" logic
FinallyRouter m_finallyRouter;
Id m_stateLocal;
Id m_retLocal;
MetaInfoBuilder m_metaInfo;
public:
bool checkIfStackEmpty(const char* forInstruction) const;
void unexpectedStackSym(char sym, const char* where) const;
int scanStackForLocation(int iLast);
void buildVectorImm(std::vector<unsigned char>& vectorImm,
void buildVectorImm(std::vector<uchar>& vectorImm,
int iFirst, int iLast, bool allowW,
Emitter& e);
enum class PassByRefKind {
@@ -709,7 +811,7 @@ public:
void emitSet(Emitter& e);
void emitSetOp(Emitter& e, int op);
void emitBind(Emitter& e);
void emitIncDec(Emitter& e, IncDecOp cop);
void emitIncDec(Emitter& e, unsigned char cop);
void emitPop(Emitter& e);
void emitConvertToCell(Emitter& e);
void emitConvertToCellIfVar(Emitter& e);
@@ -809,44 +911,14 @@ public:
void emitForeachListAssignment(Emitter& e,
ListAssignmentPtr la,
int vLocalId);
void emitForeach(Emitter& e, ForEachStatementPtr fe);
void emitForeach(Emitter& e,
ForEachStatementPtr fe,
FinallyRouterEntryPtr entry);
void emitRestoreErrorReporting(Emitter& e, Id oldLevelLoc);
void emitMakeUnitFatal(Emitter& e,
const char* msg,
FatalOp k = FatalOp::Runtime);
// Emits a Jmp or IterBreak instruction to the specified target, freeing
// the specified iterator variables. emitJump() cannot be used to leave a
// try region, except if it jumps to the m_finallyLabel of the try region.
void emitJump(Emitter& e, IterVec& iters, Label& target);
// These methods handle the return, break, continue, and goto operations.
// These methods are aware of try/finally blocks and foreach blocks and
// will free iterators and jump to finally epilogues as appropriate.
void emitReturn(Emitter& e, char sym, StatementPtr s);
void emitBreak(Emitter& e, int depth, StatementPtr s);
void emitContinue(Emitter& e, int depth, StatementPtr s);
void emitGoto(Emitter& e, StringData* name, StatementPtr s);
// Helper methods for emitting IterFree instructions
void emitIterFree(Emitter& e, IterVec& iters);
void emitIterFreeForReturn(Emitter& e);
// A "finally epilogue" is a blob of bytecode that comes after an inline
// copy of a "finally" clause body. Finally epilogues are used to ensure
// that that the bodies of finally clauses are executed whenever a return,
// break, continue, or goto operation jumps out of their corresponding
// "try" blocks.
void emitFinallyEpilogue(Emitter& e, Region* entry);
void emitReturnTrampoline(Emitter& e, Region* entry,
std::vector<Label*>& cases, char sym);
void emitBreakTrampoline(Emitter& e, Region* entry,
std::vector<Label*>& cases, int depth);
void emitContinueTrampoline(Emitter& e, Region* entry,
std::vector<Label*>& cases, int depth);
void emitGotoTrampoline(Emitter& e, Region* entry,
std::vector<Label*>& cases, StringData* name);
Funclet* addFunclet(Thunklet* body);
Funclet* addFunclet(StatementPtr stmt,
Thunklet* body);
@@ -867,20 +939,18 @@ public:
Offset end,
Label* entry,
FaultIterInfo = FaultIterInfo { -1, KindOfIter });
void
newFaultRegionAndFunclet(Offset start,
void newFuncletAndRegion(Offset start,
Offset end,
Thunklet* t,
FaultIterInfo = FaultIterInfo { -1, KindOfIter });
void
newFaultRegionAndFunclet(StatementPtr stmt,
void newFuncletAndRegion(StatementPtr stmt,
Offset start,
Offset end,
Thunklet* t,
FaultIterInfo = FaultIterInfo { -1, KindOfIter });
void newFPIRegion(Offset start, Offset end, Offset fpOff);
void copyOverCatchAndFaultRegions(FuncEmitter* fe);
void copyOverExnHandlers(FuncEmitter* fe);
void copyOverFPIRegions(FuncEmitter* fe);
void saveMaxStackCells(FuncEmitter* fe);
void finishFunc(Emitter& e, FuncEmitter* fe);
@@ -892,31 +962,6 @@ public:
void emitClassTraitAliasRule(PreClassEmitter* pce,
TraitAliasStatementPtr rule);
void emitClassUseTrait(PreClassEmitter* pce, UseTraitStatementPtr useStmt);
// Helper function for creating entries.
RegionPtr createRegion(StatementPtr s, Region::Kind kind);
// Enter/leave the passed in entry. Note that entries sometimes need be
// to be constructed before they are entered, or need to be accessed
// after they are left. This especially applies to constructs such
// as loops and try blocks.
void enterRegion(RegionPtr);
void leaveRegion(RegionPtr);
// Functions used for handling state IDs allocation.
// FIXME (#3275259): This should be moved into global / func
// body / fault funclet entries in order to optimize state
// allocation. See the task description for more details.
void registerControlTarget(ControlTarget* t);
void unregisterControlTarget(ControlTarget* t);
void registerReturn(StatementPtr s, Region* entry, char sym);
void registerYieldAwait(ExpressionPtr e);
ControlTargetPtr registerBreak(StatementPtr s, Region* entry, int depth,
bool alloc);
ControlTargetPtr registerContinue(StatementPtr s, Region* entry, int depth,
bool alloc);
ControlTargetPtr registerGoto(StatementPtr s, Region* entry,
StringData* name, bool alloc);
};
void emitAllHHBC(AnalysisResultPtr ar);
+34 -27
Ver Arquivo
@@ -19,7 +19,6 @@
#include "folly/ScopeGuard.h"
#include "hphp/compiler/analysis/code_error.h"
#include "hphp/compiler/analysis/lambda_names.h"
#include "hphp/compiler/analysis/analysis_result.h"
#include "hphp/compiler/analysis/class_scope.h"
#include "hphp/compiler/statement/statement_list.h"
@@ -30,7 +29,7 @@
#include "hphp/compiler/parser/parser.h"
#include "hphp/util/logger.h"
#include "hphp/util/util.h"
#include "hphp/util/deprecated/base.h"
#include "hphp/util/base.h"
#include "hphp/compiler/expression/expression_list.h"
#include "hphp/compiler/statement/function_statement.h"
#include "hphp/compiler/analysis/variable_table.h"
@@ -39,14 +38,15 @@
#include "hphp/compiler/expression/user_attribute.h"
#include "hphp/runtime/base/complex-types.h"
namespace HPHP {
using namespace HPHP;
///////////////////////////////////////////////////////////////////////////////
FileScope::FileScope(const string &fileName, int fileSize, const MD5 &md5)
: BlockScope("", "", StatementPtr(), BlockScope::FileScope),
m_size(fileSize), m_md5(md5), m_includeState(0), m_system(false),
m_fileName(fileName), m_redeclaredFunctions(0) {
m_size(fileSize), m_md5(md5), m_module(false), m_privateInclude(false),
m_externInclude(false),
m_includeState(0), m_fileName(fileName), m_redeclaredFunctions(0) {
pushAttribute(); // for global scope
}
@@ -68,11 +68,6 @@ void FileScope::setFileLevel(StatementListPtr stmtList) {
}
}
void FileScope::setSystem() {
m_fileName = "/:" + m_fileName;
m_system = true;
}
FunctionScopePtr FileScope::setTree(AnalysisResultConstPtr ar,
StatementListPtr tree) {
m_tree = tree;
@@ -262,10 +257,9 @@ void FileScope::addConstantDependency(AnalysisResultPtr ar,
}
void FileScope::analyzeProgram(AnalysisResultPtr ar) {
if (!m_pseudoMain) return;
m_pseudoMain->getStmt()->analyzeProgram(ar);
resolve_lambda_names(ar, shared_from_this());
if (m_pseudoMain) {
m_pseudoMain->getStmt()->analyzeProgram(ar);
}
}
ClassScopeRawPtr FileScope::resolveClass(ClassScopeRawPtr cls) {
@@ -379,6 +373,11 @@ void FileScope::analyzeIncludesHelper(AnalysisResultPtr ar) {
static_pointer_cast<IncludeExpression>(exp)->getIncludedFile(ar));
if (fs && fs->m_includeState != 1) {
if (!fs->m_includeState) {
if (m_module && fs->m_privateInclude) {
BOOST_FOREACH(BlockScopeRawPtr bs, m_providedDefs) {
fs->m_providedDefs.insert(bs);
}
}
fs->analyzeIncludesHelper(ar);
}
BOOST_FOREACH(BlockScopeRawPtr bs, fs->m_providedDefs) {
@@ -396,7 +395,7 @@ void FileScope::analyzeIncludesHelper(AnalysisResultPtr ar) {
}
void FileScope::analyzeIncludes(AnalysisResultPtr ar) {
if (!m_includeState) {
if (!m_privateInclude && !m_includeState) {
analyzeIncludesHelper(ar);
}
}
@@ -458,18 +457,24 @@ string FileScope::outputFilebase() const {
static void getFuncScopesSet(BlockScopeRawPtrQueue &v,
const StringToFunctionScopePtrMap &funcMap) {
for (const auto& iter : funcMap) {
FunctionScopePtr f = iter.second;
if (f->getStmt()) {
for (StringToFunctionScopePtrMap::const_iterator
iter = funcMap.begin(), end = funcMap.end();
iter != end; ++iter) {
FunctionScopePtr f = iter->second;
if (f->isUserFunction()) {
v.push_back(f);
}
}
}
void FileScope::getScopesSet(BlockScopeRawPtrQueue &v) {
for (const auto& clsVec : getClasses()) {
for (const auto cls : clsVec.second) {
if (cls->getStmt()) {
const StringToClassScopePtrVecMap &classes = getClasses();
for (StringToClassScopePtrVecMap::const_iterator iter = classes.begin(),
end = classes.end(); iter != end; ++iter) {
for (ClassScopePtrVec::const_iterator it = iter->second.begin(),
e = iter->second.end(); it != e; ++it) {
ClassScopePtr cls = *it;
if (cls->isUserClass()) {
v.push_back(cls);
getFuncScopesSet(v, cls->getFunctions());
}
@@ -477,17 +482,20 @@ void FileScope::getScopesSet(BlockScopeRawPtrQueue &v) {
}
getFuncScopesSet(v, getFunctions());
if (const auto redec = m_redeclaredFunctions) {
for (const auto& funcVec : *redec) {
auto i = funcVec.second.begin(), e = funcVec.second.end();
if (const StringToFunctionScopePtrVecMap *redec = m_redeclaredFunctions) {
for (StringToFunctionScopePtrVecMap::const_iterator iter = redec->begin(),
end = redec->end(); iter != end; ++iter) {
FunctionScopePtrVec::const_iterator i = iter->second.begin(),
e = iter->second.end();
v.insert(v.end(), ++i, e);
}
}
}
void FileScope::getClassesFlattened(ClassScopePtrVec &classes) const {
for (const auto& clsVec : m_classes) {
for (auto cls : clsVec.second) {
for (StringToClassScopePtrVecMap::const_iterator it = m_classes.begin();
it != m_classes.end(); ++it) {
BOOST_FOREACH(ClassScopePtr cls, it->second) {
classes.push_back(cls);
}
}
@@ -510,4 +518,3 @@ void FileScope::serialize(JSON::DocTarget::OutputStream &out) const {
ms.done();
}
}
+11 -14
Ver Arquivo
@@ -17,16 +17,14 @@
#ifndef incl_HPHP_FILE_SCOPE_H_
#define incl_HPHP_FILE_SCOPE_H_
#include <string>
#include <map>
#include <boost/algorithm/string.hpp>
#include "hphp/compiler/analysis/block_scope.h"
#include "hphp/compiler/analysis/function_container.h"
#include "hphp/compiler/analysis/code_error.h"
#include "hphp/compiler/code_generator.h"
#include <boost/graph/adjacency_list.hpp>
#include "hphp/compiler/json.h"
#include "hphp/util/json.h"
#include "hphp/util/md5.h"
namespace HPHP {
@@ -80,7 +78,6 @@ public:
const std::string &getName() const { return m_fileName;}
const MD5& getMd5() const { return m_md5; }
void setMd5(const MD5& md5) { m_md5 = md5; }
StatementListPtr getStmt() const { return m_tree;}
const StringToClassScopePtrVecMap &getClasses() const {
return m_classes;
@@ -145,12 +142,8 @@ public:
const std::string &decname);
void addClassAlias(const std::string& target, const std::string& alias) {
m_classAliasMap.insert(
std::make_pair(
boost::to_lower_copy(target),
boost::to_lower_copy(alias)
)
);
m_classAliasMap.insert(std::make_pair(Util::toLower(target),
Util::toLower(alias)));
}
std::multimap<std::string,std::string> const& getClassAliases() const {
@@ -158,7 +151,7 @@ public:
}
void addTypeAliasName(const std::string& name) {
m_typeAliasNames.insert(boost::to_lower_copy(name));
m_typeAliasNames.insert(Util::toLower(name));
}
std::set<std::string> const& getTypeAliasNames() const {
@@ -173,8 +166,10 @@ public:
m_vertex = vertex;
}
void setSystem();
bool isSystem() const { return m_system; }
void setModule() { m_module = true; }
void setPrivateInclude() { m_privateInclude = true; }
bool isPrivateInclude() const { return m_privateInclude && !m_externInclude; }
void setExternInclude() { m_externInclude = true; }
void analyzeProgram(AnalysisResultPtr ar);
void analyzeIncludes(AnalysisResultPtr ar);
@@ -204,8 +199,10 @@ public:
private:
int m_size;
MD5 m_md5;
unsigned m_module : 1;
unsigned m_privateInclude : 1;
unsigned m_externInclude : 1;
unsigned m_includeState : 2;
unsigned m_system : 1;
std::vector<int> m_attributes;
std::string m_fileName;
+1 -1
Ver Arquivo
@@ -24,7 +24,7 @@ namespace HPHP {
class CodeGenerator;
DECLARE_BOOST_TYPES(AnalysisResult);
DECLARE_EXTENDED_BOOST_TYPES(FunctionScope);
DECLARE_BOOST_TYPES(FunctionScope);
DECLARE_BOOST_TYPES(ClassScope);
DECLARE_BOOST_TYPES(FunctionContainer);
+6 -10
Ver Arquivo
@@ -292,8 +292,7 @@ bool FunctionScope::hasUserAttr(const char *attr) const {
}
bool FunctionScope::isZendParamMode() const {
return m_attributeClassInfo &
(ClassInfo::ZendParamModeNull | ClassInfo::ZendParamModeFalse);
return m_attributeClassInfo & ClassInfo::ZendParamMode;
}
bool FunctionScope::isPublic() const {
@@ -848,14 +847,11 @@ bool FunctionScope::popReturnType() {
m_prevReturn.reset();
return false;
}
Logger::Verbose("Corrected %s's return type %s -> %s",
getFullName().c_str(),
m_prevReturn->toString().c_str(),
m_returnType->toString().c_str());
} else {
Logger::Verbose("Set %s's return type %s",
getFullName().c_str(),
m_returnType->toString().c_str());
if (!isFirstPass()) {
Logger::Verbose("Corrected function return type %s -> %s",
m_prevReturn->toString().c_str(),
m_returnType->toString().c_str());
}
}
} else if (!m_prevReturn) {
return false;
+2 -4
Ver Arquivo
@@ -20,9 +20,8 @@
#include "hphp/compiler/expression/user_attribute.h"
#include "hphp/compiler/analysis/block_scope.h"
#include "hphp/compiler/option.h"
#include "hphp/compiler/json.h"
#include "hphp/util/hash-map-typedefs.h"
#include "hphp/util/json.h"
#include "hphp/parser/parser.h"
namespace HPHP {
@@ -96,7 +95,6 @@ public:
* What kind of function this is.
*/
bool isUserFunction() const { return !m_system && !isNative(); }
bool isSystem() const { return m_system; }
bool isDynamic() const { return m_dynamic; }
bool isPublic() const;
bool isProtected() const;
@@ -389,7 +387,7 @@ public:
ReadWriteMutex &getInlineMutex() { return m_inlineMutex; }
DECLARE_EXTENDED_BOOST_TYPES(FunctionInfo);
DECLARE_BOOST_TYPES(FunctionInfo);
static void RecordFunctionInfo(std::string fname, FunctionScopePtr func);
+1 -1
Ver Arquivo
@@ -18,7 +18,7 @@
#define incl_HPHP_LABEL_SCOPE_H_
#include "hphp/compiler/hphp.h"
#include "hphp/util/deprecated/base.h"
#include "hphp/util/base.h"
#include <vector>
#include <string>
-156
Ver Arquivo
@@ -1,156 +0,0 @@
/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP 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.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#include "hphp/compiler/analysis/lambda_names.h"
#include <set>
#include "folly/ScopeGuard.h"
#include "hphp/compiler/analysis/variable_table.h"
#include "hphp/compiler/analysis/function_scope.h"
#include "hphp/compiler/statement/method_statement.h"
#include "hphp/compiler/statement/function_statement.h"
#include "hphp/compiler/expression/closure_expression.h"
namespace HPHP {
//////////////////////////////////////////////////////////////////////
namespace {
struct NameScope {
NameScope* const prev;
VariableTablePtr const vars;
};
struct Walker {
explicit Walker(AnalysisResultPtr ar)
: m_curScope{nullptr}
, m_ar{ar}
{}
void walk_functions(const FunctionContainer& funcCont) {
for (auto& kv : funcCont.getFunctions()) {
walk_function(kv.second);
}
}
private:
void visit_closure(ClosureExpressionPtr ce) {
auto const cfunc = ce->getClosureFunction();
with_scope(
cfunc->getScope()->getVariables(),
[&] {
walk_ast(cfunc->getStmts());
}
);
if (ce->type() != ClosureType::Short) return;
if (ce->captureState() == ClosureExpression::CaptureState::Known) {
return;
}
auto const paramNames = ce->collectParamNames();
std::set<std::string> mentioned;
cfunc->getScope()->getVariables()->getNames(mentioned);
std::set<std::string> toCapture;
for (auto& m : mentioned) {
if (paramNames.count(m)) continue;
if (m == "this") {
toCapture.insert("this");
continue;
}
for (auto scope = m_curScope; scope; scope = scope->prev) {
if (scope->vars->getSymbol(m)) {
toCapture.insert(m);
break;
}
}
}
if (cfunc->getFunctionScope()->containsThis()) {
toCapture.insert("this");
}
ce->setCaptureList(m_ar, toCapture);
}
void walk_ast(ConstructPtr node) {
if (!node) return;
if (dynamic_pointer_cast<MethodStatement>(node)) {
// Don't descend into nested non-closure functions, or functions
// in the psuedo-main.
return;
}
if (auto ce = dynamic_pointer_cast<ClosureExpression>(node)) {
visit_closure(ce);
return;
}
for (int i = 0; i < node->getKidCount(); ++i) {
walk_ast(node->getNthKid(i));
}
}
void walk_function(const FunctionScopePtr& fscope) {
if (fscope->isClosure()) return;
auto ms = dynamic_pointer_cast<MethodStatement>(fscope->getStmt());
ConstructPtr node(ms->getStmts());
with_scope(
fscope->getVariables(),
[&] {
walk_ast(node);
}
);
}
template<class Func>
void with_scope(const VariableTablePtr& scopeVars, Func func) {
auto newScope = NameScope { m_curScope, scopeVars };
m_curScope = &newScope;
SCOPE_EXIT { m_curScope = m_curScope->prev; };
func();
}
private:
NameScope* m_curScope;
AnalysisResultPtr m_ar;
};
}
//////////////////////////////////////////////////////////////////////
void resolve_lambda_names(AnalysisResultPtr ar, const FileScopePtr& fscope) {
Walker walker(ar);
ClassScopePtrVec classScopes;
fscope->getClassesFlattened(classScopes);
for (auto& cls : classScopes) {
walker.walk_functions(*cls);
}
walker.walk_functions(*fscope);
}
//////////////////////////////////////////////////////////////////////
}
-39
Ver Arquivo
@@ -1,39 +0,0 @@
/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP 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.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#ifndef incl_HPHP_COMPILER_ANALYSIS_LAMBDA_NAMES_H_
#define incl_HPHP_COMPILER_ANALYSIS_LAMBDA_NAMES_H_
#include "hphp/compiler/statement/statement_list.h"
#include "hphp/compiler/analysis/file_scope.h"
#include "hphp/compiler/analysis/analysis_result.h"
namespace HPHP {
//////////////////////////////////////////////////////////////////////
/*
* After the first analysis pass over a file, this pass must run to
* resolve names for lambda expressions and determine their automatic
* capture lists.
*/
void resolve_lambda_names(AnalysisResultPtr ar, const FileScopePtr&);
//////////////////////////////////////////////////////////////////////
}
#endif
+5 -5
Ver Arquivo
@@ -24,7 +24,7 @@ namespace HPHP { namespace Compiler {
static void collapseJmp(Offset* offsetPtr, Op* instr, Op* start) {
if (offsetPtr) {
Op* dest = instr + *offsetPtr;
while (isUnconditionalJmp(*dest) && dest != instr) {
while (*dest == OpJmp && dest != instr) {
dest = start + instrJumpTarget(start, dest - start);
}
*offsetPtr = dest - instr;
@@ -91,10 +91,10 @@ Peephole::Peephole(UnitEmitter &ue, MetaInfoBuilder& metaInfo)
// fallthrough
incDecOp:
if (static_cast<IncDecOp>(imm->u_OA) == IncDecOp::PostInc) {
imm->u_OA = static_cast<unsigned char>(IncDecOp::PreInc);
} else if (static_cast<IncDecOp>(imm->u_OA) == IncDecOp::PostDec) {
imm->u_OA = static_cast<unsigned char>(IncDecOp::PreDec);
if (imm->u_OA == PostInc) {
imm->u_OA = PreInc;
} else if (imm->u_OA == PostDec) {
imm->u_OA = PreDec;
}
break;
default:
+2 -3
Ver Arquivo
@@ -18,10 +18,9 @@
#define incl_HPHP_SYMBOL_TABLE_H_
#include "hphp/compiler/hphp.h"
#include "hphp/compiler/json.h"
#include "hphp/util/json.h"
#include "hphp/util/util.h"
#include "hphp/util/lock.h"
#include "hphp/util/hash-map-typedefs.h"
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
@@ -30,7 +29,7 @@ class BlockScope;
class CodeGenerator;
class Variant;
DECLARE_BOOST_TYPES(Construct);
DECLARE_EXTENDED_BOOST_TYPES(Type);
DECLARE_BOOST_TYPES(Type);
DECLARE_BOOST_TYPES(AnalysisResult);
DECLARE_BOOST_TYPES(SymbolTable);
DECLARE_BOOST_TYPES(FunctionScope);
-2
Ver Arquivo
@@ -71,8 +71,6 @@ void Type::InitTypeHintMap() {
s_HHTypeHintTypes["double"] = Type::Double;
s_HHTypeHintTypes["float"] = Type::Double;
s_HHTypeHintTypes["string"] = Type::String;
// Type::Numeric doesn't include numeric strings; this is intentional
s_HHTypeHintTypes["num"] = Type::Numeric;
s_HHTypeHintTypes["resource"] = Type::Resource;
s_HHTypeHintTypes["callable"] = Type::Variant;
}
+2 -2
Ver Arquivo
@@ -18,8 +18,8 @@
#define incl_HPHP_TYPE_H_
#include "hphp/compiler/hphp.h"
#include "hphp/compiler/json.h"
#include "hphp/util/functional.h"
#include "hphp/util/json.h"
#include "hphp/util/case-insensitive.h"
#include "hphp/runtime/base/types.h"
+1 -3
Ver Arquivo
@@ -428,9 +428,7 @@ TypePtr VariableTable::add(Symbol *sym, TypePtr type,
type = setType(ar, sym, type, true);
if (sym->isParameter()) {
auto p = dynamic_pointer_cast<ParameterExpression>(construct);
if (p) {
sym->setDeclaration(construct);
}
if (p) sym->setDeclaration(construct);
} else {
sym->setDeclaration(construct);
}
+1 -2
Ver Arquivo
@@ -20,7 +20,6 @@
#include "hphp/compiler/analysis/symbol_table.h"
#include "hphp/compiler/statement/statement.h"
#include "hphp/compiler/analysis/class_scope.h"
#include "hphp/util/hash-map-typedefs.h"
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
@@ -297,7 +296,7 @@ public:
* GlobalVariables class to make ThreadLocal<GlobalVaribles> work.
* This data structure is only needed by global scope.
*/
DECLARE_EXTENDED_BOOST_TYPES(StaticGlobalInfo);
DECLARE_BOOST_TYPES(StaticGlobalInfo);
struct StaticGlobalInfo {
Symbol *sym;
VariableTable *variables; // where this variable was from
+124 -38
Ver Arquivo
@@ -50,7 +50,8 @@ using namespace HPHP;
bool BuiltinSymbols::Loaded = false;
StringBag BuiltinSymbols::s_strings;
AnalysisResultPtr BuiltinSymbols::s_systemAr;
StringToFunctionScopePtrMap BuiltinSymbols::s_functions;
const char *const BuiltinSymbols::GlobalNames[] = {
"HTTP_RAW_POST_DATA",
@@ -85,7 +86,12 @@ const char *BuiltinSymbols::SystemClasses[] = {
nullptr
};
StringToClassScopePtrMap BuiltinSymbols::s_classes;
VariableTablePtr BuiltinSymbols::s_variables;
ConstantTablePtr BuiltinSymbols::s_constants;
StringToTypePtrMap BuiltinSymbols::s_superGlobals;
AnalysisResultPtr BuiltinSymbols::s_systemAr;
void *BuiltinSymbols::s_handle_main = nullptr;
///////////////////////////////////////////////////////////////////////////////
@@ -212,6 +218,7 @@ FunctionScopePtr BuiltinSymbols::ImportFunctionScopePtr(AnalysisResultPtr ar,
}
void BuiltinSymbols::ImportExtFunctions(AnalysisResultPtr ar,
StringToFunctionScopePtrMap &map,
ClassInfo *cls) {
const ClassInfo::MethodVec &methods = cls->getMethodsVec();
for (auto it = methods.begin(); it != methods.end(); ++it) {
@@ -221,13 +228,14 @@ void BuiltinSymbols::ImportExtFunctions(AnalysisResultPtr ar,
}
FunctionScopePtr f = ImportFunctionScopePtr(ar, cls, *it);
ar->addSystemFunction(f);
assert(!map[f->getName()]);
map[f->getName()] = f;
}
}
void BuiltinSymbols::ImportExtMethods(AnalysisResultPtr ar,
FunctionScopePtrVec &vec,
ClassInfo *cls) {
void BuiltinSymbols::ImportExtFunctions(AnalysisResultPtr ar,
FunctionScopePtrVec &vec,
ClassInfo *cls) {
const ClassInfo::MethodVec &methods = cls->getMethodsVec();
for (auto it = methods.begin(); it != methods.end(); ++it) {
FunctionScopePtr f = ImportFunctionScopePtr(ar, cls, *it);
@@ -279,7 +287,7 @@ void BuiltinSymbols::ImportExtConstants(AnalysisResultPtr ar,
ClassScopePtr BuiltinSymbols::ImportClassScopePtr(AnalysisResultPtr ar,
ClassInfo *cls) {
FunctionScopePtrVec methods;
ImportExtMethods(ar, methods, cls);
ImportExtFunctions(ar, methods, cls);
ClassInfo::InterfaceVec ifaces = cls->getInterfacesVec();
String parent = cls->getParentClass();
@@ -317,7 +325,8 @@ void BuiltinSymbols::ImportExtClasses(AnalysisResultPtr ar) {
}
ClassScopePtr cl = ImportClassScopePtr(ar, it->second);
ar->addSystemClass(cl);
assert(!s_classes[cl->getName()]);
s_classes[cl->getName()] = cl;
}
}
@@ -329,11 +338,13 @@ bool BuiltinSymbols::Load(AnalysisResultPtr ar) {
ClassInfo::Load();
// load extension functions first, so system/php may call them
ImportExtFunctions(ar, ClassInfo::GetSystem());
ImportExtFunctions(ar, s_functions, ClassInfo::GetSystem());
AnalysisResultPtr ar2 = AnalysisResultPtr(new AnalysisResult());
s_variables = VariableTablePtr(new VariableTable(*ar2.get()));
s_constants = ConstantTablePtr(new ConstantTable(*ar2.get()));
ConstantTablePtr cns = ar->getConstants();
// load extension constants, classes and dynamics
ImportExtConstants(ar, cns, ClassInfo::GetSystem());
ImportExtConstants(ar, s_constants, ClassInfo::GetSystem());
ImportExtClasses(ar);
Array constants = ClassInfo::GetSystemConstants();
@@ -342,11 +353,11 @@ bool BuiltinSymbols::Load(AnalysisResultPtr ar) {
CVarRef key = it.first();
if (!key.isString()) continue;
std::string name = key.toCStrRef().data();
if (cns->getSymbol(name)) continue;
if (s_constants->getSymbol(name)) continue;
if (name == "true" || name == "false" || name == "null") continue;
CVarRef value = it.secondRef();
if (!value.isInitialized() || value.isObject()) continue;
ExpressionPtr e = Expression::MakeScalarExpression(ar, ar, loc, value);
ExpressionPtr e = Expression::MakeScalarExpression(ar2, ar2, loc, value);
TypePtr t =
value.isNull() ? Type::Null :
value.isBoolean() ? Type::Boolean :
@@ -354,47 +365,122 @@ bool BuiltinSymbols::Load(AnalysisResultPtr ar) {
value.isDouble() ? Type::Double :
value.isArray() ? Type::Array : Type::Variant;
cns->add(key.toCStrRef().data(), t, e, ar, e);
s_constants->add(key.toCStrRef().data(), t, e, ar2, e);
}
s_variables = ar2->getVariables();
for (int i = 0, n = NumGlobalNames(); i < n; ++i) {
ar->getVariables()->add(GlobalNames[i], Type::Variant, false, ar,
ConstructPtr(), ModifierExpressionPtr());
s_variables->add(GlobalNames[i], Type::Variant, false, ar,
ConstructPtr(), ModifierExpressionPtr());
}
cns->setDynamic(ar, "PHP_BINARY", true);
cns->setDynamic(ar, "PHP_BINDIR", true);
cns->setDynamic(ar, "PHP_OS", true);
cns->setDynamic(ar, "PHP_SAPI", true);
cns->setDynamic(ar, "SID", true);
s_constants->setDynamic(ar, "PHP_BINARY", true);
s_constants->setDynamic(ar, "PHP_BINDIR", true);
s_constants->setDynamic(ar, "PHP_OS", true);
s_constants->setDynamic(ar, "PHP_SAPI", true);
s_constants->setDynamic(ar, "SID", true);
// Systemlib files were all parsed by hphp_process_init
// parse all PHP files under system/php
s_systemAr = ar = AnalysisResultPtr(new AnalysisResult());
ar->loadBuiltins();
string slib = get_systemlib();
Scanner scanner(slib.c_str(), slib.size(),
Option::GetScannerType(), "systemlib.php");
Compiler::Parser parser(scanner, "systemlib.php", ar);
if (!parser.parse()) {
Logger::Error("Unable to parse systemlib.php: %s",
parser.getMessage().c_str());
assert(false);
}
ar->analyzeProgram(true);
ar->inferTypes();
const StringToFileScopePtrMap &files = ar->getAllFiles();
for (const auto& file : files) {
file.second->setSystem();
const auto& classes = file.second->getClasses();
for (const auto& clsVec : classes) {
assert(clsVec.second.size() == 1);
auto cls = clsVec.second[0];
cls->setSystem();
ar->addSystemClass(cls);
for (const auto& func : cls->getFunctions()) {
FunctionScope::RecordFunctionInfo(func.first, func.second);
}
for (StringToFileScopePtrMap::const_iterator iterFile = files.begin();
iterFile != files.end(); iterFile++) {
const StringToClassScopePtrVecMap &classes =
iterFile->second->getClasses();
for (StringToClassScopePtrVecMap::const_iterator iter = classes.begin();
iter != classes.end(); ++iter) {
assert(iter->second.size() == 1);
iter->second[0]->setSystem();
assert(!s_classes[iter->first]);
s_classes[iter->first] = iter->second[0];
}
const auto& functions = file.second->getFunctions();
for (const auto& func : functions) {
func.second->setSystem();
ar->addSystemFunction(func.second);
FunctionScope::RecordFunctionInfo(func.first, func.second);
const StringToFunctionScopePtrMap &functions =
iterFile->second->getFunctions();
for (StringToFunctionScopePtrMap::const_iterator iter = functions.begin();
iter != functions.end(); ++iter) {
iter->second->setSystem();
s_functions[iter->first] = iter->second;
}
}
return true;
}
AnalysisResultPtr BuiltinSymbols::LoadGlobalSymbols(const char *fileName) {
AnalysisResultPtr ar(new AnalysisResult());
string phpBaseName = "/system/globals/";
phpBaseName += fileName;
string phpFileName = Option::GetSystemRoot() + phpBaseName;
const char *baseName = s_strings.add(phpBaseName.c_str());
fileName = s_strings.add(phpFileName.c_str());
try {
Scanner scanner(fileName, Option::GetScannerType());
Compiler::Parser parser(scanner, baseName, ar);
if (!parser.parse()) {
assert(false);
Logger::Error("Unable to parse file %s: %s", fileName,
parser.getMessage().c_str());
}
} catch (FileOpenException &e) {
Logger::Error("%s", e.getMessage().c_str());
}
ar->analyzeProgram(true);
ar->inferTypes();
return ar;
}
void BuiltinSymbols::LoadFunctions(AnalysisResultPtr ar,
StringToFunctionScopePtrMap &functions) {
assert(Loaded);
functions.insert(s_functions.begin(), s_functions.end());
}
void BuiltinSymbols::LoadClasses(AnalysisResultPtr ar,
StringToClassScopePtrMap &classes) {
assert(Loaded);
classes.insert(s_classes.begin(), s_classes.end());
}
void BuiltinSymbols::LoadVariables(AnalysisResultPtr ar,
VariableTablePtr variables) {
assert(Loaded);
if (s_variables) {
variables->import(s_variables);
}
}
void BuiltinSymbols::LoadConstants(AnalysisResultPtr ar,
ConstantTablePtr constants) {
assert(Loaded);
if (s_constants) {
constants->import(s_constants);
}
}
ConstantTablePtr BuiltinSymbols::LoadSystemConstants() {
AnalysisResultPtr ar = LoadGlobalSymbols("constants.php");
const auto &fileScopes = ar->getAllFilesVector();
if (!fileScopes.empty()) {
return fileScopes[0]->getConstants();
}
throw std::runtime_error("LoadSystemConstants failed");
}
void BuiltinSymbols::LoadSuperGlobals() {
if (s_superGlobals.empty()) {
s_superGlobals["_SERVER"] = Type::Variant;
+22 -7
Ver Arquivo
@@ -24,17 +24,16 @@
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
DECLARE_EXTENDED_BOOST_TYPES(Type);
DECLARE_BOOST_TYPES(Type);
DECLARE_BOOST_TYPES(AnalysisResult);
DECLARE_EXTENDED_BOOST_TYPES(FunctionScope);
DECLARE_EXTENDED_BOOST_TYPES(ClassScope);
DECLARE_BOOST_TYPES(FunctionScope);
DECLARE_BOOST_TYPES(ClassScope);
DECLARE_BOOST_TYPES(VariableTable);
DECLARE_BOOST_TYPES(ConstantTable);
class BuiltinSymbols {
public:
static bool Loaded;
static AnalysisResultPtr s_systemAr;
static bool Load(AnalysisResultPtr ar);
@@ -47,6 +46,11 @@ public:
static void LoadConstants(AnalysisResultPtr ar,
ConstantTablePtr constants);
/*
* Load system/globals/constants.php.
*/
static ConstantTablePtr LoadSystemConstants();
/**
* Testing whether a variable is a PHP superglobal.
*/
@@ -56,24 +60,35 @@ public:
static bool IsDeclaredDynamic(const std::string& name);
static void LoadSuperGlobals();
static StringToFunctionScopePtrMap s_functions;
static StringToClassScopePtrMap s_classes;
static VariableTablePtr s_variables;
static ConstantTablePtr s_constants;
static AnalysisResultPtr s_systemAr;
static const char *const GlobalNames[];
static int NumGlobalNames();
private:
static StringBag s_strings;
static const char *SystemClasses[];
static AnalysisResultPtr LoadGlobalSymbols(const char *fileName);
static StringToTypePtrMap s_superGlobals;
static std::set<std::string> s_declaredDynamic;
static void *s_handle_main;
static FunctionScopePtr ImportFunctionScopePtr(AnalysisResultPtr ar,
ClassInfo *cls,
ClassInfo::MethodInfo *method);
static void ImportExtFunctions(AnalysisResultPtr ar,
StringToFunctionScopePtrMap &map,
ClassInfo *cls);
static void ImportExtFunctions(AnalysisResultPtr ar,
FunctionScopePtrVec &vec,
ClassInfo *cls);
static void ImportExtMethods(AnalysisResultPtr ar,
FunctionScopePtrVec &vec,
ClassInfo *cls);
static void ImportExtProperties(AnalysisResultPtr ar,
VariableTablePtr dest,
ClassInfo *cls);
+21 -44
Ver Arquivo
@@ -451,14 +451,6 @@ void CodeGenerator::printPropertyHeader(const std::string propertyName) {
printf("%s\";", propertyName.c_str());
}
void CodeGenerator::printNull() {
printf("N;");
}
void CodeGenerator::printBool(bool value) {
printf("b:%d;", value ? 1 : 0);
}
void CodeGenerator::printValue(double v) {
*m_out << "d:";
if (std::isnan(v)) {
@@ -481,7 +473,7 @@ void CodeGenerator::printValue(int32_t value) {
}
void CodeGenerator::printValue(int64_t value) {
printf("i:%" PRId64 ";", value);
printf("i:%ld;", value);
}
void CodeGenerator::printValue(std::string value) {
@@ -491,7 +483,7 @@ void CodeGenerator::printValue(std::string value) {
}
void CodeGenerator::printModifierVector(std::string value) {
printf("V:9:\"HH\\Vector\":1:{");
printf("V:6:\"Vector\":1:{");
printObjectHeader("Modifier", 1);
printPropertyHeader("name");
printValue(value);
@@ -508,12 +500,12 @@ void CodeGenerator::printTypeExpression(std::string value) {
void CodeGenerator::printExpression(ExpressionPtr expression, bool isRef) {
if (isRef) {
printObjectHeader("UnaryOpExpression", 3);
printObjectHeader("UnaryOpExpression", 4);
printPropertyHeader("expression");
expression->outputCodeModel(*this);
printPropertyHeader("operation");
printValue(PHP_REFERENCE_OP);
printPropertyHeader("sourceLocation");
printPropertyHeader("location");
printLocation(expression->getLocation());
printObjectFooter();
} else {
@@ -522,62 +514,47 @@ void CodeGenerator::printExpression(ExpressionPtr expression, bool isRef) {
}
void CodeGenerator::printExpressionVector(ExpressionListPtr el) {
auto count = el == nullptr ? 0 : el->getCount();
printf("V:9:\"HH\\Vector\":%d:{", count);
if (count > 0) {
printf("V:6:\"Vector\":%d:{", el->getCount());
if (el->getCount() > 0) {
el->outputCodeModel(*this);
}
printf("}");
}
void CodeGenerator::printExpressionVector(ExpressionPtr e) {
if (e->is(Expression::KindOfExpressionList)) {
auto sl = static_pointer_cast<ExpressionList>(e);
printExpressionVector(sl);
} else {
printf("V:9:\"HH\\Vector\":1:{");
e->outputCodeModel(*this);
printf("}");
}
printf("V:6:\"Vector\":1:{");
e->outputCodeModel(*this);
printf("}");
}
void CodeGenerator::printAsBlock(StatementPtr s) {
if (s != nullptr && s->is(Statement::KindOfBlockStatement)) {
if (s->is(Statement::KindOfBlockStatement)) {
s->outputCodeModel(*this);
} else {
auto numProps = s == nullptr ? 1 : 2;
printObjectHeader("BlockStatement", numProps);
printObjectHeader("BlockStatement", 2);
printPropertyHeader("statements");
printStatementVector(s);
if (s != nullptr) {
printPropertyHeader("sourceLocation");
printLocation(s->getLocation());
if (s->is(Statement::KindOfStatementList)) {
auto sl = static_pointer_cast<StatementList>(s);
printStatementVector(sl);
} else {
printf("V:6:\"Vector\":1:{");
s->outputCodeModel(*this);
printf("}");
}
printPropertyHeader("location");
printLocation(s->getLocation());
printObjectFooter();
}
}
void CodeGenerator::printStatementVector(StatementListPtr sl) {
printf("V:9:\"HH\\Vector\":%d:{", sl->getCount());
printf("V:6:\"Vector\":%d:{", sl->getCount());
if (sl->getCount() > 0) {
sl->outputCodeModel(*this);
}
printf("}");
}
void CodeGenerator::printStatementVector(StatementPtr s) {
if (s == nullptr) {
printf("V:9:\"HH\\Vector\":0:{}");
} else if (s->is(Statement::KindOfStatementList)) {
auto sl = static_pointer_cast<StatementList>(s);
printStatementVector(sl);
} else {
printf("V:9:\"HH\\Vector\":1:{");
s->outputCodeModel(*this);
printf("}");
}
}
void CodeGenerator::printLocation(LocationPtr location) {
if (location == nullptr) return;
printObjectHeader("SourceLocation", 4);
+1 -4
Ver Arquivo
@@ -27,7 +27,7 @@ DECLARE_BOOST_TYPES(Statement);
DECLARE_BOOST_TYPES(StatementList);
DECLARE_BOOST_TYPES(Construct);
DECLARE_BOOST_TYPES(BlockScope);
DECLARE_EXTENDED_BOOST_TYPES(ClassScope);
DECLARE_BOOST_TYPES(ClassScope);
DECLARE_BOOST_TYPES(FunctionScope);
DECLARE_BOOST_TYPES(FileScope);
DECLARE_BOOST_TYPES(LoopStatement);
@@ -277,8 +277,6 @@ public:
void printObjectHeader(const std::string className, int numProperties);
void printPropertyHeader(const std::string propertyName);
void printObjectFooter();
void printNull();
void printBool(bool value);
void printValue(double value);
void printValue(int32_t value);
void printValue(int64_t value);
@@ -290,7 +288,6 @@ public:
void printExpressionVector(ExpressionPtr e);
void printAsBlock(StatementPtr s);
void printStatementVector(StatementListPtr sl);
void printStatementVector(StatementPtr s);
void printLocation(LocationPtr location);
void setAstClassPrefix(const std::string &prefix) { m_astPrefix = prefix; }
private:
+5 -19
Ver Arquivo
@@ -85,18 +85,11 @@ namespace HPHP {
PHP_POST_INCREMENT_OP = 18,
PHP_PRE_DECREMENT_OP = 19,
PHP_PRE_INCREMENT_OP = 20,
PHP_PRINT_OP = 21,
PHP_REFERENCE_OP = 22,
PHP_REQUIRE_OP = 23,
PHP_REQUIRE_ONCE_OP = 24,
PHP_STRING_CAST_OP = 25,
PHP_UNSET_CAST_OP = 26,
};
/** Enumerates the kinds of trait require statements. */
enum CodeModelRequireKind {
PHP_EXTENDS = 1,
PHP_IMPLEMENTS = 2,
PHP_REFERENCE_OP = 21,
PHP_REQUIRE_OP = 22,
PHP_REQUIRE_ONCE_OP = 23,
PHP_STRING_CAST_OP = 24,
PHP_UNSET_CAST_OP = 25,
};
/** Enumerates the kinds of type declaration statements. */
@@ -106,12 +99,5 @@ namespace HPHP {
PHP_TRAIT = 3,
};
/** The sort order to use when grouping query results */
enum CodeModelOrder {
PHP_NOT_SPECIFIED = 1,
PHP_ASCENDING = 2,
PHP_DESCENDING = 3,
};
}
#endif // incl_HPHP_CODE_MODEL_ENUMS_H_
+3 -12
Ver Arquivo
@@ -25,7 +25,7 @@
#include "hphp/compiler/option.h"
#include "hphp/compiler/parser/parser.h"
#include "hphp/compiler/builtin_symbols.h"
#include "hphp/compiler/json.h"
#include "hphp/util/json.h"
#include "hphp/util/logger.h"
#include "hphp/util/db-conn.h"
#include "hphp/util/exception.h"
@@ -484,8 +484,6 @@ int prepareOptions(CompilerOptions &po, int argc, char **argv) {
Option::ParseTimeOpts = false;
}
initialize_hhbbc_options();
return 0;
}
@@ -542,12 +540,6 @@ int process(const CompilerOptions &po) {
bool isPickledPHP = (po.target == "php" && po.format == "pickled");
if (!isPickledPHP) {
bool wp = Option::WholeProgram;
Option::WholeProgram = false;
BuiltinSymbols::s_systemAr = ar;
hphp_process_init();
BuiltinSymbols::s_systemAr.reset();
Option::WholeProgram = wp;
if (po.target == "hhbc" && !Option::WholeProgram) {
// We're trying to produce the same bytecode as runtime parsing.
// There's nothing to do.
@@ -555,7 +547,9 @@ int process(const CompilerOptions &po) {
if (!BuiltinSymbols::Load(ar)) {
return false;
}
ar->loadBuiltins();
}
hphp_process_init();
}
{
@@ -807,7 +801,6 @@ void hhbcTargetInit(const CompilerOptions &po, AnalysisResultPtr ar) {
if (po.format.find("exe") != string::npos) {
RuntimeOption::RepoCentralPath += ".hhbc";
}
unlink(RuntimeOption::RepoCentralPath.c_str());
RuntimeOption::RepoLocalMode = "--";
RuntimeOption::RepoDebugInfo = Option::RepoDebugInfo;
RuntimeOption::RepoJournal = "memory";
@@ -923,8 +916,6 @@ int runTarget(const CompilerOptions &po) {
cmd += buf;
cmd += " -vRepo.Authoritative=true";
if (getenv("HPHP_DUMP_BYTECODE")) cmd += " -vEval.DumpBytecode=1";
if (getenv("HPHP_INTERP")) cmd += " -vEval.Jit=0";
cmd += " -vRepo.Local.Mode=r- -vRepo.Local.Path=";
}
cmd += po.outputDir + '/' + po.program;
+1 -15
Ver Arquivo
@@ -469,23 +469,9 @@ void Construct::parseTimeFatal(Compiler::ErrorType err, const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
string msg;
string_vsnprintf(msg, fmt, ap);
Util::string_vsnprintf(msg, fmt, ap);
va_end(ap);
if (err != Compiler::NoError) Compiler::Error(err, shared_from_this());
throw ParseTimeFatalException(m_loc->file, m_loc->line0, "%s", msg.c_str());
}
void Construct::analysisTimeFatal(Compiler::ErrorType err,
const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
string msg;
string_vsnprintf(msg, fmt, ap);
va_end(ap);
assert(err != Compiler::NoError);
Compiler::Error(err, shared_from_this());
throw AnalysisTimeFatalException(m_loc->file, m_loc->line0,
"%s [analysis]", msg.c_str());
}
+1 -3
Ver Arquivo
@@ -17,7 +17,7 @@
#ifndef incl_HPHP_CONSTRUCT_H_
#define incl_HPHP_CONSTRUCT_H_
#include "hphp/compiler/json.h"
#include "hphp/util/json.h"
#include "hphp/compiler/code_generator.h"
#include "hphp/compiler/analysis/code_error.h"
#include "hphp/compiler/analysis/block_scope.h"
@@ -180,8 +180,6 @@ public:
void resetScope(BlockScopeRawPtr scope, bool resetOrigScope=false);
void parseTimeFatal(Compiler::ErrorType error, const char *fmt, ...)
ATTRIBUTE_PRINTF(3,4);
void analysisTimeFatal(Compiler::ErrorType error, const char *fmt, ...)
ATTRIBUTE_PRINTF(3,4);
virtual int getLocalEffects() const { return UnknownEffect;}
int getChildrenEffects() const;
int getContainedEffects() const;
@@ -399,7 +399,7 @@ void ArrayElementExpression::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("SimpleVariableExpression", 2);
cg.printPropertyHeader("name");
cg.printValue(m_globalName);
cg.printPropertyHeader("sourceLocation");
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
} else if (m_offset) {
@@ -410,16 +410,16 @@ void ArrayElementExpression::outputCodeModel(CodeGenerator &cg) {
cg.printExpression(m_offset, false);
cg.printPropertyHeader("operation");
cg.printValue(PHP_ARRAY_ELEMENT);
cg.printPropertyHeader("sourceLocation");
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
} else {
cg.printObjectHeader("UnaryOpExpression", 3);
cg.printObjectHeader("UnaryOpExpression", 4);
cg.printPropertyHeader("expression");
m_variable->outputCodeModel(cg);
cg.printPropertyHeader("operation");
cg.printValue(PHP_ARRAY_APPEND_POINT_OP);
cg.printPropertyHeader("sourceLocation");
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
@@ -134,7 +134,7 @@ void ArrayPairExpression::outputCodeModel(CodeGenerator &cg) {
cg.printExpression(m_value, m_ref);
cg.printPropertyHeader("operation");
cg.printValue(PHP_ARRAY_PAIR);
cg.printPropertyHeader("sourceLocation");
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
} else {
@@ -317,7 +317,7 @@ void AssignmentExpression::outputCodeModel(CodeGenerator &cg) {
cg.printExpression(m_value, m_ref);
cg.printPropertyHeader("operation");
cg.printValue(PHP_ASSIGNMENT);
cg.printPropertyHeader("sourceLocation");
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
+2 -2
Ver Arquivo
@@ -86,12 +86,12 @@ TypePtr AwaitExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
///////////////////////////////////////////////////////////////////////////////
void AwaitExpression::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("UnaryOpExpression", 3);
cg.printObjectHeader("UnaryOpExpression", 2);
cg.printPropertyHeader("expression");
m_exp->outputCodeModel(cg);
cg.printPropertyHeader("operation");
cg.printValue(PHP_AWAIT_OP);
cg.printPropertyHeader("sourceLocation");
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
@@ -67,7 +67,7 @@ BinaryOpExpression::BinaryOpExpression
break;
case T_COLLECTION: {
std::string s = m_exp1->getLiteralString();
Collection::Type cType = Collection::InvalidType;
int cType = 0;
if (strcasecmp(s.c_str(), "vector") == 0) {
cType = Collection::VectorType;
} else if (strcasecmp(s.c_str(), "map") == 0) {
@@ -78,12 +78,6 @@ BinaryOpExpression::BinaryOpExpression
cType = Collection::SetType;
} else if (strcasecmp(s.c_str(), "pair") == 0) {
cType = Collection::PairType;
} else if (strcasecmp(s.c_str(), "frozenvector") == 0) {
cType = Collection::FrozenVectorType;
} else if (strcasecmp(s.c_str(), "frozenmap") == 0) {
cType = Collection::FrozenMapType;
} else if (strcasecmp(s.c_str(), "frozenset") == 0) {
cType = Collection::FrozenSetType;
}
ExpressionListPtr el = static_pointer_cast<ExpressionList>(m_exp2);
el->setCollectionType(cType);
@@ -484,9 +478,6 @@ ExpressionPtr BinaryOpExpression::foldConst(AnalysisResultConstPtr ar) {
ExpressionPtr aExp = m_exp1;
ExpressionPtr bExp = binOpExp->m_exp1;
ExpressionPtr cExp = binOpExp->m_exp2;
if (aExp->isArray() || bExp->isArray() || cExp->isArray()) {
break;
}
m_exp1 = binOpExp = Clone(binOpExp);
m_exp2 = cExp;
binOpExp->m_exp1 = aExp;
@@ -547,9 +538,6 @@ ExpressionPtr BinaryOpExpression::foldConst(AnalysisResultConstPtr ar) {
*result.asCell() = cellBitXor(*v1.asCell(), *v2.asCell());
break;
case '.':
if (v1.isArray() || v2.isArray()) {
return ExpressionPtr();
}
result = concat(v1.toString(), v2.toString());
break;
case T_IS_IDENTICAL:
@@ -816,7 +804,7 @@ TypePtr BinaryOpExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
case T_COLLECTION:
et1 = Type::Any;
et2 = Type::Any;
rt = Type::CreateObjectType(m_exp1->getLiteralString());
rt = Type::Object;
break;
default:
assert(false);
@@ -934,7 +922,7 @@ void BinaryOpExpression::outputCodeModel(CodeGenerator &cg) {
m_exp1->outputCodeModel(cg);
cg.printPropertyHeader("arguments");
cg.printExpressionVector(static_pointer_cast<ExpressionList>(m_exp2));
cg.printPropertyHeader("sourceLocation");
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
return;
@@ -990,7 +978,7 @@ void BinaryOpExpression::outputCodeModel(CodeGenerator &cg) {
}
cg.printValue(op);
cg.printPropertyHeader("sourceLocation");
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
@@ -1075,3 +1063,4 @@ bool BinaryOpExpression::isOpEqual() {
}
return false;
}
@@ -224,12 +224,12 @@ bool ClassConstantExpression::canonCompare(ExpressionPtr e) const {
///////////////////////////////////////////////////////////////////////////////
void ClassConstantExpression::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("ClassPropertyExpression", 3);
cg.printObjectHeader("ClassPropertyExpression", 2);
cg.printPropertyHeader("className");
StaticClassName::outputCodeModel(cg);
cg.printPropertyHeader("propertyName");
cg.printValue(m_varName);
cg.printPropertyHeader("sourceLocation");
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
@@ -46,7 +46,6 @@ public:
bool isValid() const { return m_valid; }
bool isDynamic() const;
bool hasClass() const { return m_defScope != 0; }
bool isColonColonClass() const { return m_varName == "class"; }
private:
std::string m_varName;
BlockScope *m_defScope;
+107 -195
Ver Arquivo
@@ -13,11 +13,8 @@
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#include "hphp/compiler/expression/closure_expression.h"
#include <boost/make_shared.hpp>
#include "folly/ScopeGuard.h"
#include "hphp/compiler/expression/parameter_expression.h"
#include "hphp/compiler/expression/expression_list.h"
#include "hphp/compiler/expression/simple_variable.h"
@@ -27,79 +24,68 @@
#include "hphp/compiler/analysis/function_scope.h"
#include "hphp/compiler/analysis/file_scope.h"
namespace HPHP {
//////////////////////////////////////////////////////////////////////
using namespace HPHP;
TypePtr ClosureExpression::s_ClosureType =
Type::CreateObjectType("closure"); // needs lower case
ClosureExpression::ClosureExpression(
EXPRESSION_CONSTRUCTOR_PARAMETERS,
ClosureType type,
FunctionStatementPtr func,
ExpressionListPtr vars)
: Expression(EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES(ClosureExpression))
, m_type(type)
, m_func(func)
, m_captureState(m_type == ClosureType::Short ? CaptureState::Unknown
: CaptureState::Known)
{
switch (m_type) {
case ClosureType::Short:
break;
case ClosureType::Long:
if (vars) initializeFromUseList(vars);
break;
}
}
///////////////////////////////////////////////////////////////////////////////
// constructors/destructors
void ClosureExpression::initializeFromUseList(ExpressionListPtr vars) {
m_vars = ExpressionListPtr(
new ExpressionList(vars->getScope(), vars->getLocation()));
ClosureExpression::ClosureExpression
(EXPRESSION_CONSTRUCTOR_PARAMETERS, FunctionStatementPtr func,
ExpressionListPtr vars)
: Expression(EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES(ClosureExpression)),
m_func(func) {
// Because PHP is insane you can have a use variable with the same
// name as a param name.
// In that case, params win (which is different than zend but much easier)
auto seenBefore = collectParamNames();
if (vars) {
m_vars = ExpressionListPtr
(new ExpressionList(vars->getScope(), vars->getLocation()));
// push the vars in reverse order, not retaining duplicates
std::set<string> seenBefore;
for (int i = vars->getCount() - 1; i >= 0; i--) {
ParameterExpressionPtr param(
dynamic_pointer_cast<ParameterExpression>((*vars)[i]));
assert(param);
if (param->getName() == "this") {
// "this" is automatically included.
// Once we get rid of all the callsites, make this an error
continue;
// Because PHP is insane you can have a use variable with the same
// name as a param name.
// In that case, params win (which is different than zend but much easier)
ExpressionListPtr bodyParams = m_func->getParams();
if (bodyParams) {
int nParams = bodyParams->getCount();
for (int i = 0; i < nParams; i++) {
ParameterExpressionPtr par(
static_pointer_cast<ParameterExpression>((*bodyParams)[i]));
seenBefore.insert(par->getName());
}
}
if (seenBefore.find(param->getName().c_str()) == seenBefore.end()) {
seenBefore.insert(param->getName().c_str());
m_vars->insertElement(param);
for (int i = vars->getCount() - 1; i >= 0; i--) {
ParameterExpressionPtr param(
dynamic_pointer_cast<ParameterExpression>((*vars)[i]));
assert(param);
if (seenBefore.find(param->getName().c_str()) == seenBefore.end()) {
seenBefore.insert(param->getName().c_str());
m_vars->insertElement(param);
}
}
if (m_vars) {
m_values = ExpressionListPtr
(new ExpressionList(m_vars->getScope(), m_vars->getLocation()));
for (int i = 0; i < m_vars->getCount(); i++) {
ParameterExpressionPtr param =
dynamic_pointer_cast<ParameterExpression>((*m_vars)[i]);
const string &name = param->getName();
SimpleVariablePtr var(new SimpleVariable(param->getScope(),
param->getLocation(),
name));
if (param->isRef()) {
var->setContext(RefValue);
}
m_values->addElement(var);
}
assert(m_vars->getCount() == m_values->getCount());
}
}
initializeValuesFromVars();
}
void ClosureExpression::initializeValuesFromVars() {
if (!m_vars) return;
m_values = ExpressionListPtr
(new ExpressionList(m_vars->getScope(), m_vars->getLocation()));
for (int i = 0; i < m_vars->getCount(); i++) {
ParameterExpressionPtr param =
dynamic_pointer_cast<ParameterExpression>((*m_vars)[i]);
const string &name = param->getName();
SimpleVariablePtr var(new SimpleVariable(param->getScope(),
param->getLocation(),
name));
if (param->isRef()) {
var->setContext(RefValue);
}
m_values->addElement(var);
}
assert(m_vars->getCount() == m_values->getCount());
}
ExpressionPtr ClosureExpression::clone() {
@@ -146,65 +132,62 @@ void ClosureExpression::setNthKid(int n, ConstructPtr cp) {
void ClosureExpression::analyzeProgram(AnalysisResultPtr ar) {
m_func->analyzeProgram(ar);
if (m_vars) {
m_values->analyzeProgram(ar);
if (m_vars) analyzeVars(ar);
if (ar->getPhase() == AnalysisResult::AnalyzeAll) {
getFunctionScope()->addUse(m_func->getFunctionScope(),
BlockScope::UseKindClosure);
m_func->getFunctionScope()->setClosureVars(m_vars);
FunctionScopeRawPtr container =
// closure function's variable table (not containing function's)
VariableTablePtr variables = m_func->getFunctionScope()->getVariables();
VariableTablePtr containing = getFunctionScope()->getVariables();
for (int i = 0; i < m_vars->getCount(); i++) {
ParameterExpressionPtr param =
dynamic_pointer_cast<ParameterExpression>((*m_vars)[i]);
const string &name = param->getName();
{
Symbol *containingSym = containing->addDeclaredSymbol(name, param);
containingSym->setPassClosureVar();
Symbol *sym = variables->addDeclaredSymbol(name, param);
sym->setClosureVar();
sym->setDeclaration(ConstructPtr());
if (param->isRef()) {
sym->setRefClosureVar();
sym->setUsed();
} else {
sym->clearRefClosureVar();
sym->clearUsed();
}
}
}
return;
}
if (ar->getPhase() == AnalysisResult::AnalyzeFinal) {
// closure function's variable table (not containing function's)
VariableTablePtr variables = m_func->getFunctionScope()->getVariables();
for (int i = 0; i < m_vars->getCount(); i++) {
ParameterExpressionPtr param =
dynamic_pointer_cast<ParameterExpression>((*m_vars)[i]);
const string &name = param->getName();
// so we can assign values to them, instead of seeing CVarRef
Symbol *sym = variables->getSymbol(name);
if (sym && sym->isParameter()) {
sym->setLvalParam();
}
}
}
}
FunctionScopeRawPtr container =
getFunctionScope()->getContainingNonClosureFunction();
if (container && container->isStatic()) {
m_func->getModifiers()->add(T_STATIC);
}
}
void ClosureExpression::analyzeVars(AnalysisResultPtr ar) {
m_values->analyzeProgram(ar);
if (ar->getPhase() == AnalysisResult::AnalyzeAll) {
getFunctionScope()->addUse(m_func->getFunctionScope(),
BlockScope::UseKindClosure);
m_func->getFunctionScope()->setClosureVars(m_vars);
// closure function's variable table (not containing function's)
VariableTablePtr variables = m_func->getFunctionScope()->getVariables();
VariableTablePtr containing = getFunctionScope()->getVariables();
for (int i = 0; i < m_vars->getCount(); i++) {
ParameterExpressionPtr param =
dynamic_pointer_cast<ParameterExpression>((*m_vars)[i]);
const string &name = param->getName();
{
Symbol *containingSym = containing->addDeclaredSymbol(name, param);
containingSym->setPassClosureVar();
Symbol *sym = variables->addDeclaredSymbol(name, param);
sym->setClosureVar();
sym->setDeclaration(ConstructPtr());
if (param->isRef()) {
sym->setRefClosureVar();
sym->setUsed();
} else {
sym->clearRefClosureVar();
sym->clearUsed();
}
}
}
return;
}
if (ar->getPhase() == AnalysisResult::AnalyzeFinal) {
// closure function's variable table (not containing function's)
VariableTablePtr variables = m_func->getFunctionScope()->getVariables();
for (int i = 0; i < m_vars->getCount(); i++) {
ParameterExpressionPtr param =
dynamic_pointer_cast<ParameterExpression>((*m_vars)[i]);
const string &name = param->getName();
// so we can assign values to them, instead of seeing CVarRef
Symbol *sym = variables->getSymbol(name);
if (sym && sym->isParameter()) {
sym->setLvalParam();
}
}
}
}
TypePtr ClosureExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
@@ -268,72 +251,6 @@ TypePtr ClosureExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
return s_ClosureType;
}
void ClosureExpression::setCaptureList(
AnalysisResultPtr ar,
const std::set<std::string>& captureNames) {
assert(m_captureState == CaptureState::Unknown);
m_captureState = CaptureState::Known;
bool usedThis = false;
SCOPE_EXIT {
/*
* TODO: closures in a non-class scope should be neither static
* nor non-static, but right now we don't really have this idea.
*
* This would allow not having to check for a $this or late bound
* class in the closure object or on the ActRec when returning
* from those closures.
*
* (We could also mark closures that don't use late static binding
* with this flag to avoid checks on closures in member functions
* when they use neither $this nor static::)
*/
if (!usedThis) m_func->getModifiers()->add(T_STATIC);
};
if (captureNames.empty()) return;
m_vars = ExpressionListPtr(
new ExpressionList(getOriginalScope(), getLocation()));
for (auto const& name : captureNames) {
if (name == "this") {
usedThis = true;
continue;
}
auto expr = ParameterExpressionPtr(new ParameterExpression(
BlockScopePtr(getOriginalScope()),
getLocation(),
TypeAnnotationPtr(),
true /* hhType */,
name,
false /* ref */,
0 /* token modifier thing */,
ExpressionPtr(),
ExpressionPtr()
));
m_vars->insertElement(expr);
}
initializeValuesFromVars();
analyzeVars(ar);
}
std::set<std::string> ClosureExpression::collectParamNames() const {
std::set<std::string> ret;
auto bodyParams = m_func->getParams();
if (!bodyParams) return ret;
int nParams = bodyParams->getCount();
for (int i = 0; i < nParams; i++) {
auto par = static_pointer_cast<ParameterExpression>((*bodyParams)[i]);
ret.insert(par->getName());
}
return ret;
}
bool ClosureExpression::hasStaticLocals() {
ConstructPtr cons(m_func);
return hasStaticLocalsImpl(cons);
@@ -365,15 +282,12 @@ bool ClosureExpression::hasStaticLocalsImpl(ConstructPtr root) {
///////////////////////////////////////////////////////////////////////////////
void ClosureExpression::outputCodeModel(CodeGenerator &cg) {
auto numProps = m_vars != nullptr && m_vars->getCount() > 0 ? 3 : 2;
cg.printObjectHeader("ClosureExpression", numProps);
cg.printPropertyHeader("ffunction");
cg.printObjectHeader("ClosureExpression", 3);
cg.printPropertyHeader("function");
m_func->outputCodeModel(cg);
if (m_vars != nullptr && m_vars->getCount() > 0) {
cg.printPropertyHeader("capturedVariables");
cg.printExpressionVector(m_vars);
}
cg.printPropertyHeader("sourceLocation");
cg.printPropertyHeader("capturedVariables");
cg.printExpressionVector(m_vars);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
@@ -390,5 +304,3 @@ void ClosureExpression::outputPHP(CodeGenerator &cg, AnalysisResultPtr ar) {
}
m_func->outputPHPBody(cg, ar);
}
}
+5 -34
Ver Arquivo
@@ -18,7 +18,6 @@
#define incl_HPHP_CLOSURE_EXPRESSION_H_
#include "hphp/compiler/expression/expression.h"
#include "hphp/parser/parser.h"
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
@@ -30,20 +29,10 @@ DECLARE_BOOST_TYPES(ExpressionList);
class ClosureExpression : public Expression {
public:
ClosureExpression(EXPRESSION_CONSTRUCTOR_PARAMETERS,
ClosureType type,
FunctionStatementPtr func,
ExpressionListPtr vars);
FunctionStatementPtr func, ExpressionListPtr vars);
DECLARE_BASE_EXPRESSION_VIRTUAL_FUNCTIONS;
// Flag for whether we have already determined the capture list for
// this lambda.
enum class CaptureState {
Unknown,
Known,
};
CaptureState captureState() const { return m_captureState; }
virtual ConstructPtr getNthKid(int n) const;
virtual void setNthKid(int n, ConstructPtr cp);
virtual int getKidCount() const;
@@ -54,35 +43,17 @@ public:
StringData* getClosureClassName() { return m_closureClassName; }
void setClosureClassName(StringData* value) { m_closureClassName = value; }
bool hasStaticLocals();
ClosureType type() const { return m_type; }
std::set<std::string> collectParamNames() const;
/*
* Initialize the capture list for a closure that uses automatic
* captures.
*
* Pre: captureState() == CaptureState::Unknown.
*/
void setCaptureList(AnalysisResultPtr ar,
const std::set<std::string>&);
private:
static TypePtr s_ClosureType;
private:
void initializeFromUseList(ExpressionListPtr vars);
void initializeValuesFromVars();
void analyzeVars(AnalysisResultPtr);
bool hasStaticLocalsImpl(ConstructPtr root);
private:
ClosureType m_type;
FunctionStatementPtr m_func;
ExpressionListPtr m_vars;
ExpressionListPtr m_values;
StringData* m_closureClassName;
std::set<std::string> m_unboundNames;
CaptureState m_captureState;
static TypePtr s_ClosureType;
bool hasStaticLocalsImpl(ConstructPtr root);
};
///////////////////////////////////////////////////////////////////////////////
@@ -277,9 +277,9 @@ TypePtr ConstantExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
void ConstantExpression::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("SimpleVariableExpression", 2);
cg.printPropertyHeader("variableName");
cg.printValue(m_origName);
cg.printPropertyHeader("sourceLocation");
cg.printPropertyHeader("name");
cg.printValue(getNonNSOriginalName());
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
@@ -128,7 +128,7 @@ void DynamicFunctionCall::outputCodeModel(CodeGenerator &cg) {
m_nameExp->outputCodeModel(cg);
cg.printPropertyHeader("arguments");
cg.printExpressionVector(m_params);
cg.printPropertyHeader("sourceLocation");
cg.printPropertyHeader("location");
cg.printLocation(m_nameExp->getLocation());
cg.printObjectFooter();
}
+1 -1
Ver Arquivo
@@ -96,7 +96,7 @@ void DynamicVariable::outputCodeModel(CodeGenerator &cg) {
m_exp->outputCodeModel(cg);
cg.printPropertyHeader("operation");
cg.printValue(PHP_DYNAMIC_VARIABLE_OP) ;
cg.printPropertyHeader("sourceLocation");
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
@@ -122,12 +122,14 @@ bool EncapsListExpression::canonCompare(ExpressionPtr e) const {
///////////////////////////////////////////////////////////////////////////////
void EncapsListExpression::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("EncapsListExpression", 3);
cg.printObjectHeader("EncapsListExpression", 2);
cg.printPropertyHeader("delimiter");
cg.printValue(m_type);
cg.printPropertyHeader("expressions");
cg.printExpressionVector(m_exps);
cg.printPropertyHeader("sourceLocation");
if (m_exps) {
cg.printPropertyHeader("expressions");
cg.printExpressionVector(m_exps);
}
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
+2 -15
Ver Arquivo
@@ -17,12 +17,9 @@
#ifndef incl_HPHP_EXPRESSION_H_
#define incl_HPHP_EXPRESSION_H_
#include "hphp/util/deprecated/declare-boost-types.h"
#include "hphp/util/hash-map-typedefs.h"
#include "hphp/compiler/construct.h"
#include "hphp/compiler/analysis/type.h"
#include "hphp/compiler/analysis/analysis_result.h"
#include "hphp/util/hash-map-typedefs.h"
#define EXPRESSION_CONSTRUCTOR_BASE_PARAMETERS \
BlockScopePtr scope, LocationPtr loc, Expression::KindOf kindOf
@@ -51,7 +48,7 @@ namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
DECLARE_BOOST_TYPES(Statement);
DECLARE_EXTENDED_BOOST_TYPES(Expression);
DECLARE_BOOST_TYPES(Expression);
class Variant;
#define DECLARE_EXPRESSION_TYPES(x) \
@@ -81,17 +78,7 @@ class Variant;
x(ClosureExpression, None), \
x(YieldExpression, None), \
x(AwaitExpression, None), \
x(UserAttribute, None), \
x(QueryExpression, None), \
x(FromClause, None), \
x(LetClause, None), \
x(WhereClause, None), \
x(SelectClause, None), \
x(IntoClause, None), \
x(JoinClause, None), \
x(GroupClause, None), \
x(OrderbyClause, None), \
x(Ordering, None)
x(UserAttribute, None)
class Expression : public Construct {
public:
+6 -11
Ver Arquivo
@@ -239,11 +239,9 @@ void ExpressionList::stripConcat() {
BinaryOpExpressionPtr b
(static_pointer_cast<BinaryOpExpression>(e));
if (b->getOp() == '.') {
if(!b->getExp1()->isArray() && !b->getExp2()->isArray()) {
e = b->getExp1();
el.insertElement(b->getExp2(), i + 1);
continue;
}
e = b->getExp1();
el.insertElement(b->getExp2(), i + 1);
continue;
}
}
i++;
@@ -274,7 +272,7 @@ void ExpressionList::markParams(bool noRefWrapper) {
}
}
void ExpressionList::setCollectionType(Collection::Type cType) {
void ExpressionList::setCollectionType(int cType) {
m_arrayElements = true;
m_collectionType = cType;
}
@@ -471,11 +469,7 @@ bool ExpressionList::canonCompare(ExpressionPtr e) const {
void ExpressionList::outputCodeModel(CodeGenerator &cg) {
for (unsigned int i = 0; i < m_exps.size(); i++) {
ExpressionPtr exp = m_exps[i];
if (exp) {
cg.printExpression(exp, exp->hasContext(RefParameter));
} else {
cg.printNull();
}
cg.printExpression(exp, exp?exp->hasContext(RefParameter):false);
}
}
@@ -514,3 +508,4 @@ unsigned int ExpressionList::checkLitstrKeys() const {
}
return keys.size();
}
+1 -1
Ver Arquivo
@@ -73,7 +73,7 @@ public:
void markParam(int p, bool noRefWrapper);
void markParams(bool noRefWrapper);
void setCollectionType(Collection::Type cType);
void setCollectionType(int cType);
virtual bool canonCompare(ExpressionPtr e) const;
-111
Ver Arquivo
@@ -1,111 +0,0 @@
/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP 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.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#include "hphp/compiler/expression/group_clause.h"
#include "hphp/compiler/analysis/code_error.h"
#include "hphp/runtime/base/complex-types.h"
using namespace HPHP;
///////////////////////////////////////////////////////////////////////////////
// constructors/destructors
GroupClause::GroupClause
(EXPRESSION_CONSTRUCTOR_PARAMETERS,
ExpressionPtr coll, ExpressionPtr key)
: Expression(EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES(GroupClause)),
m_coll(coll), m_key(key) {
}
ExpressionPtr GroupClause::clone() {
GroupClausePtr exp(new GroupClause(*this));
Expression::deepCopy(exp);
exp->m_coll = Clone(m_coll);
exp->m_key = Clone(m_key);
return exp;
}
///////////////////////////////////////////////////////////////////////////////
// parser functions
///////////////////////////////////////////////////////////////////////////////
// static analysis functions
void GroupClause::analyzeProgram(AnalysisResultPtr ar) {
m_coll->analyzeProgram(ar);
m_key->analyzeProgram(ar);
}
ConstructPtr GroupClause::getNthKid(int n) const {
switch (n) {
case 0:
return m_coll;
case 1:
return m_key;
default:
assert(false);
break;
}
return ConstructPtr();
}
int GroupClause::getKidCount() const {
return 2;
}
void GroupClause::setNthKid(int n, ConstructPtr cp) {
switch (n) {
case 0:
m_coll = dynamic_pointer_cast<Expression>(cp);
break;
case 1:
m_key = dynamic_pointer_cast<Expression>(cp);
break;
default:
break;
}
}
TypePtr GroupClause::inferTypes(AnalysisResultPtr ar, TypePtr type,
bool coerce) {
m_coll->inferAndCheck(ar, Type::Some, false);
m_key->inferAndCheck(ar, Type::Some, false);
return Type::Object;
}
///////////////////////////////////////////////////////////////////////////////
void GroupClause::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("GroupClause", 3);
cg.printPropertyHeader("collection");
m_coll->outputCodeModel(cg);
cg.printPropertyHeader("key");
m_key->outputCodeModel(cg);
cg.printPropertyHeader("sourceLocation");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
void GroupClause::outputPHP(CodeGenerator &cg, AnalysisResultPtr ar) {
cg_printf("group ");
m_coll->outputPHP(cg, ar);
cg_printf(" by ");
m_key->outputPHP(cg, ar);
}
-138
Ver Arquivo
@@ -1,138 +0,0 @@
/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP 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.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#include "hphp/compiler/expression/join_clause.h"
#include "hphp/compiler/analysis/code_error.h"
#include "hphp/runtime/base/complex-types.h"
using namespace HPHP;
///////////////////////////////////////////////////////////////////////////////
// constructors/destructors
JoinClause::JoinClause
(EXPRESSION_CONSTRUCTOR_PARAMETERS,
const std::string &var, ExpressionPtr coll, ExpressionPtr left,
ExpressionPtr right, const std::string &group)
: Expression(EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES(JoinClause)),
m_var(var), m_coll(coll), m_left(left),
m_right(right), m_group(group) {
}
ExpressionPtr JoinClause::clone() {
JoinClausePtr exp(new JoinClause(*this));
Expression::deepCopy(exp);
exp->m_var = m_var;
exp->m_coll = Clone(m_coll);
exp->m_left = Clone(m_left);
exp->m_right = Clone(m_right);
exp->m_group = m_group;
return exp;
}
///////////////////////////////////////////////////////////////////////////////
// parser functions
///////////////////////////////////////////////////////////////////////////////
// static analysis functions
void JoinClause::analyzeProgram(AnalysisResultPtr ar) {
m_coll->analyzeProgram(ar);
m_left->analyzeProgram(ar);
m_right->analyzeProgram(ar);
}
ConstructPtr JoinClause::getNthKid(int n) const {
switch (n) {
case 0:
return m_coll;
case 1:
return m_left;
case 2:
return m_right;
default:
assert(false);
break;
}
return ConstructPtr();
}
int JoinClause::getKidCount() const {
return 3;
}
void JoinClause::setNthKid(int n, ConstructPtr cp) {
switch (n) {
case 0:
m_coll = dynamic_pointer_cast<Expression>(cp);
break;
case 1:
m_left = dynamic_pointer_cast<Expression>(cp);
break;
case 2:
m_right = dynamic_pointer_cast<Expression>(cp);
break;
default:
break;
}
}
TypePtr JoinClause::inferTypes(AnalysisResultPtr ar, TypePtr type,
bool coerce) {
m_coll->inferAndCheck(ar, Type::Some, false);
m_left->inferAndCheck(ar, Type::Some, false);
m_right->inferAndCheck(ar, Type::Some, false);
return Type::Object;
}
///////////////////////////////////////////////////////////////////////////////
void JoinClause::outputCodeModel(CodeGenerator &cg) {
auto numProps = 5;
if (!m_group.empty()) numProps++;
cg.printObjectHeader("JoinClause", numProps);
cg.printPropertyHeader("variable");
cg.printValue(m_var);
cg.printPropertyHeader("collection");
m_coll->outputCodeModel(cg);
cg.printPropertyHeader("left");
m_left->outputCodeModel(cg);
cg.printPropertyHeader("right");
m_right->outputCodeModel(cg);
if (!m_group.empty()) {
cg.printPropertyHeader("group");
cg.printValue(m_group);
}
cg.printPropertyHeader("sourceLocation");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
void JoinClause::outputPHP(CodeGenerator &cg, AnalysisResultPtr ar) {
cg_printf("join %s in ", m_var.c_str());
m_coll->outputPHP(cg, ar);
cg_printf(" on ");
m_left->outputPHP(cg, ar);
cg_printf(" equals ");
m_right->outputPHP(cg, ar);
if (!m_group.empty()) {
cg_printf(" into %s", m_group.c_str());
}
}
-52
Ver Arquivo
@@ -1,52 +0,0 @@
/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP 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.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#ifndef incl_HPHP_JOIN_CLAUSE_H_
#define incl_HPHP_JOIN_CLAUSE_H_
#include "hphp/compiler/expression/expression.h"
#include "hphp/compiler/expression/expression_list.h"
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
DECLARE_BOOST_TYPES(JoinClause);
class JoinClause : public Expression {
public:
JoinClause(EXPRESSION_CONSTRUCTOR_PARAMETERS,
const std::string &var, ExpressionPtr coll, ExpressionPtr left,
ExpressionPtr right, const std::string &group);
DECLARE_EXPRESSION_VIRTUAL_FUNCTIONS;
std::string getVar() const { return m_var; }
ExpressionPtr getColl() { return m_coll; }
ExpressionPtr getLeft() { return m_left; }
ExpressionPtr getRight() { return m_right; }
std::string getGroup() { return m_group; }
private:
std::string m_var;
ExpressionPtr m_coll;
ExpressionPtr m_left;
ExpressionPtr m_right;
std::string m_group;
};
///////////////////////////////////////////////////////////////////////////////
}
#endif // incl_HPHP_JOIN_CLAUSE_H_
+5 -18
Ver Arquivo
@@ -31,7 +31,7 @@ using namespace HPHP;
// constructors/destructors
/*
Determine whether the rhs behaves normally, or abnormally.
Determine whether the rhs behaves normall, or abnormally.
1) If the expression is the silence operator, recurse on the inner expression.
2) If the expression is a list assignment expression, recurse on the
@@ -77,7 +77,6 @@ static ListAssignment::RHSKind GetRHSKind(ExpressionPtr rhs) {
case Expression::KindOfIncludeExpression:
case Expression::KindOfYieldExpression:
case Expression::KindOfAwaitExpression:
case Expression::KindOfQueryExpression:
return ListAssignment::Regular;
case Expression::KindOfListAssignment:
@@ -119,15 +118,6 @@ static ListAssignment::RHSKind GetRHSKind(ExpressionPtr rhs) {
case Expression::KindOfParameterExpression:
case Expression::KindOfModifierExpression:
case Expression::KindOfUserAttribute:
case Expression::KindOfFromClause:
case Expression::KindOfLetClause:
case Expression::KindOfWhereClause:
case Expression::KindOfSelectClause:
case Expression::KindOfIntoClause:
case Expression::KindOfJoinClause:
case Expression::KindOfGroupClause:
case Expression::KindOfOrderbyClause:
case Expression::KindOfOrdering:
always_assert(false);
// non-arrays
@@ -286,15 +276,12 @@ TypePtr ListAssignment::inferTypes(AnalysisResultPtr ar, TypePtr type,
///////////////////////////////////////////////////////////////////////////////
void ListAssignment::outputCodeModel(CodeGenerator &cg) {
auto numProps = m_array != nullptr ? 3 : 2;
cg.printObjectHeader("ListAssignmentExpression", numProps);
cg.printObjectHeader("ListAssignmentExpression", 3);
cg.printPropertyHeader("variables");
cg.printExpressionVector(m_variables);
if (m_array != nullptr) {
cg.printPropertyHeader("expression");
m_array->outputCodeModel(cg);
}
cg.printPropertyHeader("sourceLocation");
cg.printPropertyHeader("expression");
m_array->outputCodeModel(cg);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
+1 -15
Ver Arquivo
@@ -118,20 +118,6 @@ bool ModifierExpression::validForClosure() const {
return true;
}
/**
* In the context of a trait alias rule, only method access and visibility
* modifiers are allowed
*/
bool ModifierExpression::validForTraitAliasRule() const {
for (auto const& mod: m_modifiers) {
if (mod != T_PUBLIC && mod != T_PRIVATE && mod != T_PROTECTED
&& mod != T_FINAL) {
return false;
}
}
return true;
}
///////////////////////////////////////////////////////////////////////////////
// static analysis functions
@@ -148,7 +134,7 @@ TypePtr ModifierExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
///////////////////////////////////////////////////////////////////////////////
void ModifierExpression::outputCodeModel(CodeGenerator &cg) {
cg.printf("V:9:\"HH\\Vector\":%d:{", (int)m_modifiers.size());
cg.printf("V:6:\"Vector\":%d:{", (int)m_modifiers.size());
for (unsigned int i = 0; i < m_modifiers.size(); i++) {
cg.printObjectHeader("Modifier", 1);
cg.printPropertyHeader("name");
@@ -56,7 +56,6 @@ public:
bool validForFunction() const;
bool validForClosure() const;
bool validForTraitAliasRule() const;
void setHasPrivacy(bool f) { m_hasPrivacy = f; }
@@ -166,7 +166,7 @@ void NewObjectExpression::outputCodeModel(CodeGenerator &cg) {
cg.printPropertyHeader("arguments");
cg.printExpressionVector(m_params);
}
cg.printPropertyHeader("sourceLocation");
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
@@ -280,7 +280,7 @@ TypePtr ObjectMethodExpression::inferAndCheck(AnalysisResultPtr ar,
///////////////////////////////////////////////////////////////////////////////
void ObjectMethodExpression::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("ObjectMethodCallExpression",
cg.printObjectHeader("ObjectMethodCallExpression(",
m_params == nullptr ? 3 : 4);
cg.printPropertyHeader("object");
m_object->outputCodeModel(cg);
@@ -294,7 +294,7 @@ void ObjectMethodExpression::outputCodeModel(CodeGenerator &cg) {
cg.printPropertyHeader("arguments");
cg.printExpressionVector(m_params);
}
cg.printPropertyHeader("sourceLocation");
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
@@ -335,7 +335,7 @@ ObjectPropertyExpression::postOptimize(AnalysisResultConstPtr ar) {
///////////////////////////////////////////////////////////////////////////////
void ObjectPropertyExpression::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("ObjectPropertyExpression", 3);
cg.printObjectHeader("ObjectPropertyExpression(", 3);
cg.printPropertyHeader("object");
m_object->outputCodeModel(cg);
if (m_property->is(Expression::KindOfScalarExpression)) {
@@ -344,7 +344,7 @@ void ObjectPropertyExpression::outputCodeModel(CodeGenerator &cg) {
cg.printPropertyHeader("propertyExpression");
}
m_property->outputCodeModel(cg);
cg.printPropertyHeader("sourceLocation");
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
-126
Ver Arquivo
@@ -1,126 +0,0 @@
/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP 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.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#include "hphp/compiler/expression/ordering.h"
#include "hphp/compiler/analysis/code_error.h"
#include "hphp/runtime/base/complex-types.h"
using namespace HPHP;
///////////////////////////////////////////////////////////////////////////////
// constructors/destructors
Ordering::Ordering
(EXPRESSION_CONSTRUCTOR_PARAMETERS,
ExpressionPtr key, TokenID direction)
: Expression(EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES(Ordering)),
m_key(key), m_direction(direction){
}
ExpressionPtr Ordering::clone() {
OrderingPtr exp(new Ordering(*this));
Expression::deepCopy(exp);
exp->m_key = Clone(m_key);
exp->m_direction = m_direction;
return exp;
}
///////////////////////////////////////////////////////////////////////////////
// parser functions
///////////////////////////////////////////////////////////////////////////////
// static analysis functions
void Ordering::analyzeProgram(AnalysisResultPtr ar) {
m_key->analyzeProgram(ar);
}
ConstructPtr Ordering::getNthKid(int n) const {
switch (n) {
case 0:
return m_key;
default:
assert(false);
break;
}
return ConstructPtr();
}
int Ordering::getKidCount() const {
return 1;
}
void Ordering::setNthKid(int n, ConstructPtr cp) {
switch (n) {
case 0:
m_key = dynamic_pointer_cast<Expression>(cp);
break;
default:
break;
}
}
TypePtr Ordering::inferTypes(AnalysisResultPtr ar, TypePtr type,
bool coerce) {
m_key->inferAndCheck(ar, Type::Some, false);
return Type::Object;
}
///////////////////////////////////////////////////////////////////////////////
void Ordering::outputCodeModel(CodeGenerator &cg) {
int direction;
switch (m_direction) {
case T_ASCENDING:
direction = 1;
break;
case T_DESCENDING:
direction = 2;
break;
default:
direction = 3;
break;
}
auto propCount = direction > 0 ? 3 : 2;
cg.printObjectHeader("Ordering", propCount);
cg.printPropertyHeader("key");
m_key->outputCodeModel(cg);
if (propCount == 3) {
cg.printPropertyHeader("direction");
cg.printValue(direction);
}
cg.printPropertyHeader("sourceLocation");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
void Ordering::outputPHP(CodeGenerator &cg, AnalysisResultPtr ar) {
m_key->outputPHP(cg, ar);
switch (m_direction) {
case T_ASCENDING:
cg_printf(" ascending");
break;
case T_DESCENDING:
cg_printf(" decending");
break;
default:
break;
}
}
@@ -308,14 +308,14 @@ void ParameterExpression::outputCodeModel(CodeGenerator &cg) {
if (m_modifier != 0) propCount++;
if (m_ref) propCount++;
if (m_defaultValue != nullptr) propCount++;
cg.printObjectHeader("ParameterDeclaration", propCount);
cg.printObjectHeader("ParameterDeclaration(", propCount);
if (m_attributeList) {
cg.printPropertyHeader("isPassedByReference");
cg.printExpressionVector(m_attributeList);
}
if (m_modifier != 0) {
cg.printPropertyHeader("modifiers");
printf("V:9:\"HH\\Vector\":1:{");
printf("V:6:\"Vector\":1:{");
switch (m_modifier) {
case T_PUBLIC: cg.printValue("public"); break;
case T_PROTECTED: cg.printValue("protected"); break;
@@ -334,7 +334,7 @@ void ParameterExpression::outputCodeModel(CodeGenerator &cg) {
cg.printPropertyHeader("expression");
m_defaultValue->outputCodeModel(cg);
}
cg.printPropertyHeader("sourceLocation");
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
+1 -1
Ver Arquivo
@@ -19,7 +19,7 @@
#include "hphp/compiler/expression/expression.h"
#include "hphp/compiler/expression/constant_expression.h"
#include "hphp/compiler/json.h"
#include "hphp/util/json.h"
#include "hphp/parser/scanner.h"
namespace HPHP {
+2 -2
Ver Arquivo
@@ -172,7 +172,7 @@ void QOpExpression::outputCodeModel(CodeGenerator &cg) {
m_condition->outputCodeModel(cg);
cg.printPropertyHeader("valueIfNull");
} else {
cg.printObjectHeader("ConditionalExpression", 4);
cg.printObjectHeader("ConditionalExpression(", 4);
cg.printPropertyHeader("condition");
m_condition->outputCodeModel(cg);
cg.printPropertyHeader("valueIfTrue");
@@ -180,7 +180,7 @@ void QOpExpression::outputCodeModel(CodeGenerator &cg) {
cg.printPropertyHeader("valueIfFalse");
}
m_expNo->outputCodeModel(cg);
cg.printPropertyHeader("sourceLocation");
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
-165
Ver Arquivo
@@ -1,165 +0,0 @@
/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP 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.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#include "hphp/compiler/expression/query_expression.h"
#include "hphp/compiler/expression/simple_query_clause.h"
#include "hphp/compiler/analysis/capture_extractor.h"
#include "hphp/compiler/analysis/code_error.h"
#include "hphp/runtime/base/complex-types.h"
using namespace HPHP;
///////////////////////////////////////////////////////////////////////////////
// constructors/destructors
QueryOrderby::QueryOrderby(EXPRESSION_CONSTRUCTOR_BASE_PARAMETERS)
: Expression(EXPRESSION_CONSTRUCTOR_BASE_PARAMETER_VALUES) {
m_expressions = nullptr;
}
ExpressionPtr QueryOrderby::clone() {
assert(false);
return nullptr;
}
QueryExpression::QueryExpression(EXPRESSION_CONSTRUCTOR_PARAMETERS,
ExpressionPtr head, ExpressionPtr body)
: QueryOrderby(EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES(QueryExpression)) {
m_queryargs = ExpressionListPtr(
new ExpressionList(getScope(), getLocation())
);
m_expressions = ExpressionListPtr(
new ExpressionList(getScope(), getLocation())
);
m_expressions->addElement(head);
assert(body != nullptr && body->is(Expression::KindOfExpressionList));
ExpressionListPtr el(static_pointer_cast<ExpressionList>(body));
for (unsigned int i = 0; i < el->getCount(); i++) {
if ((*el)[i]) m_expressions->addElement((*el)[i]);
}
}
QueryExpression::QueryExpression(EXPRESSION_CONSTRUCTOR_PARAMETERS,
ExpressionListPtr clauses)
: QueryOrderby(EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES(QueryExpression)) {
m_queryargs = ExpressionListPtr(
new ExpressionList(getScope(), getLocation())
);
m_expressions = clauses;
}
///////////////////////////////////////////////////////////////////////////////
// parser functions
///////////////////////////////////////////////////////////////////////////////
// static analysis functions
ExpressionListPtr QueryExpression::getQueryArguments() {
if (m_queryargs->getCount() == 0) serializeQueryExpression();
return m_queryargs;
}
StringData* QueryExpression::getQueryString() {
if (m_querystr == nullptr) serializeQueryExpression();
return m_querystr;
}
void QueryExpression::serializeQueryExpression() {
CaptureExtractor ce;
auto qe = ce.rewrite(static_pointer_cast<Expression>(shared_from_this()));
m_queryargs->clearElements();
for (auto e : ce.getCapturedExpressions()) {
m_queryargs->addElement(e);
}
assert(m_queryargs->getCount() > 0); //syntax requires an initial from clause
std::ostringstream serialized;
CodeGenerator cg(&serialized, CodeGenerator::Output::CodeModel);
cg.setAstClassPrefix("Code"); //TODO: create option for this
qe->outputCodeModel(cg);
std::string s(serialized.str().c_str(), serialized.str().length());
m_querystr = makeStaticString(s);
}
void QueryOrderby::analyzeProgram(AnalysisResultPtr ar) {
for (unsigned int i = 0; i < m_expressions->getCount(); i++) {
(*m_expressions)[i]->analyzeProgram(ar);
}
}
ConstructPtr QueryOrderby::getNthKid(int n) const {
if (n < (int)m_expressions->getCount()) {
return (*m_expressions)[n];
}
return ConstructPtr();
}
int QueryOrderby::getKidCount() const {
return m_expressions->getCount();
}
void QueryOrderby::setNthKid(int n, ConstructPtr cp) {
int m = m_expressions->getCount();
if (n >= m) {
assert(false);
} else {
(*m_expressions)[n] = dynamic_pointer_cast<Expression>(cp);
}
}
TypePtr QueryOrderby::inferTypes(AnalysisResultPtr ar, TypePtr type,
bool coerce) {
for (unsigned int i = 0; i < m_expressions->getCount(); i++) {
if (ExpressionPtr e = (*m_expressions)[i]) {
e->inferAndCheck(ar, Type::Some, false);
}
}
return Type::Object;
}
///////////////////////////////////////////////////////////////////////////////
void QueryOrderby::outputCodeModel(CodeGenerator &cg) {
if (this->getKindOf() == Expression::KindOfOrderbyClause) {
cg.printObjectHeader("OrderbyClause", 2);
} else {
cg.printObjectHeader("QueryExpression", 2);
}
cg.printPropertyHeader("clauses");
m_expressions->outputCodeModel(cg);
cg.printPropertyHeader("sourceLocation");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
void QueryOrderby::outputPHP(CodeGenerator &cg, AnalysisResultPtr ar) {
if (this->getKindOf() == Expression::KindOfOrderbyClause) {
cg_printf("orderby ");
}
for (unsigned int i = 0; i < m_expressions->getCount(); i++) {
if (ExpressionPtr e = (*m_expressions)[i]) {
e->outputPHP(cg, ar);
if (i > 0) cg_printf(" ");
}
}
}
-89
Ver Arquivo
@@ -1,89 +0,0 @@
/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP 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.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#ifndef incl_HPHP_QUERY_EXPRESSION_H_
#define incl_HPHP_QUERY_EXPRESSION_H_
#include "hphp/compiler/expression/expression.h"
#include "hphp/compiler/expression/expression_list.h"
#include "hphp/runtime/base/static-string-table.h"
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
DECLARE_BOOST_TYPES(QueryOrderby);
class QueryOrderby : public Expression {
public:
DECLARE_EXPRESSION_VIRTUAL_FUNCTIONS;
protected:
explicit QueryOrderby(EXPRESSION_CONSTRUCTOR_BASE_PARAMETERS);
ExpressionListPtr m_expressions;
};
DECLARE_BOOST_TYPES(QueryExpression);
class QueryExpression : public QueryOrderby {
public:
QueryExpression(EXPRESSION_CONSTRUCTOR_PARAMETERS,
ExpressionPtr head, ExpressionPtr body);
QueryExpression(EXPRESSION_CONSTRUCTOR_PARAMETERS,
ExpressionListPtr clauses);
virtual ExpressionPtr clone() {
QueryExpressionPtr exp(new QueryExpression(*this));
Expression::deepCopy(exp);
exp->m_expressions = Clone(m_expressions);
exp->m_queryargs = Clone(m_queryargs);
exp->m_querystr = m_querystr;
return exp;
}
ExpressionListPtr getClauses() const { return m_expressions; }
ExpressionListPtr getQueryArguments();
StringData* getQueryString();
private:
void serializeQueryExpression();
ExpressionListPtr m_queryargs;
StringData* m_querystr;
};
DECLARE_BOOST_TYPES(OrderbyClause);
class OrderbyClause : public QueryOrderby {
public:
OrderbyClause(EXPRESSION_CONSTRUCTOR_PARAMETERS, ExpressionPtr orderings)
: QueryOrderby(EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES(OrderbyClause)) {
assert(orderings && orderings->is(Expression::KindOfExpressionList));
m_expressions = static_pointer_cast<ExpressionList>(orderings);
}
virtual ExpressionPtr clone() {
OrderbyClausePtr exp(new OrderbyClause(*this));
Expression::deepCopy(exp);
exp->m_expressions = Clone(m_expressions);
return exp;
}
ExpressionListPtr getOrderings() const { return m_expressions; }
};
///////////////////////////////////////////////////////////////////////////////
}
#endif // incl_HPHP_QUERY_EXPRESSION_H_
+30 -42
Ver Arquivo
@@ -387,39 +387,36 @@ std::string ScalarExpression::getIdentifier() const {
///////////////////////////////////////////////////////////////////////////////
void ScalarExpression::outputCodeModel(CodeGenerator &cg) {
switch (m_type) {
case T_NS_C:
case T_LINE:
case T_TRAIT_C:
case T_CLASS_C:
case T_METHOD_C:
case T_FUNC_C: {
cg.printObjectHeader("SimpleVariableExpression", 2);
std::string varName;
switch (m_type) {
case T_NS_C: varName = "__NAMESPACE__"; break;
case T_LINE: varName = "__LINE__"; break;
case T_TRAIT_C: varName = "__TRAIT__"; break;
case T_CLASS_C: varName = "__CLASS__"; break;
case T_METHOD_C: varName = "__METHOD__"; break;
case T_FUNC_C: varName = "__FUNCTION__"; break;
default: break;
}
cg.printPropertyHeader("variableName");
cg.printValue(varName);
cg.printPropertyHeader("sourceLocation");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
return;
}
default:
break;
}
cg.printObjectHeader("ScalarExpression", 2);
cg.printPropertyHeader("value");
cg.printValue(m_originalValue);
cg.printPropertyHeader("sourceLocation");
switch (m_type) {
case T_CONSTANT_ENCAPSED_STRING:
case T_ENCAPSED_AND_WHITESPACE:
case T_STRING:
case T_NUM_STRING:
cg.printValue(m_value);
break;
case T_LNUMBER:
case T_COMPILER_HALT_OFFSET:
cg.printValue((int64_t)strtoll(m_value.c_str(), nullptr, 0));
break;
case T_LINE:
cg.printValue(String(m_translated).toInt64());
break;
case T_TRAIT_C:
case T_CLASS_C:
case T_NS_C:
case T_METHOD_C:
case T_FUNC_C:
cg.printValue(m_translated);
break;
case T_DNUMBER:
cg.printValue(String(m_value).toDouble());
break;
default:
assert(false);
}
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
@@ -501,7 +498,7 @@ Variant ScalarExpression::getVariant() const {
return String(m_value);
case T_LNUMBER:
case T_COMPILER_HALT_OFFSET:
return getIntValue();
return strtoll(m_value.c_str(), nullptr, 0);
case T_LINE:
return String(m_translated).toInt64();
case T_TRAIT_C:
@@ -540,7 +537,7 @@ bool ScalarExpression::getString(const std::string *&s) const {
bool ScalarExpression::getInt(int64_t &i) const {
if (m_type == T_LNUMBER || m_type == T_COMPILER_HALT_OFFSET) {
i = getIntValue();
i = strtoll(m_value.c_str(), nullptr, 0);
return true;
} else if (m_type == T_LINE) {
i = getLocation() ? getLocation()->line1 : 0;
@@ -566,12 +563,3 @@ void ScalarExpression::setCompilerHaltOffset(int64_t ofs) {
m_value = ss.str();
m_originalValue = ss.str();
}
int64_t ScalarExpression::getIntValue() const {
// binary number syntax "0b" is not supported by strtoll
if (m_value.compare(0, 2, "0b") == 0) {
return strtoll(m_value.c_str() + 2, nullptr, 2);
}
return strtoll(m_value.c_str(), nullptr, 0);
}
@@ -87,8 +87,6 @@ private:
std::string m_translated;
bool m_quoted;
std::string m_comment; // for inlined constant name
int64_t getIntValue() const;
};
///////////////////////////////////////////////////////////////////////////////
@@ -545,9 +545,7 @@ void SimpleFunctionCall::analyzeProgram(AnalysisResultPtr ar) {
}
}
if (!ok) {
if (m_classScope || !Unit::lookupFunc(String(m_name).get())) {
Compiler::Error(Compiler::UnknownFunction, shared_from_this());
}
Compiler::Error(Compiler::UnknownFunction, shared_from_this());
}
}
}
@@ -1287,11 +1285,11 @@ void SimpleFunctionCall::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("SimpleFunctionCallExpression", 3);
cg.printPropertyHeader("functionName");
}
cg.printValue(m_origName);
m_nameExp->outputCodeModel(cg);
cg.printPropertyHeader("arguments");
cg.printExpressionVector(m_params);
cg.printPropertyHeader("sourceLocation");
cg.printLocation(this->getLocation());
cg.printPropertyHeader("location");
cg.printLocation(m_nameExp->getLocation());
cg.printObjectFooter();
}
@@ -1634,3 +1632,4 @@ ExpressionPtr hphp_opt_is_callable(CodeGenerator *cg,
}
}
@@ -1,147 +0,0 @@
/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP 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.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#include "hphp/compiler/expression/simple_query_clause.h"
#include "hphp/compiler/analysis/code_error.h"
#include "hphp/runtime/base/complex-types.h"
using namespace HPHP;
///////////////////////////////////////////////////////////////////////////////
// constructors/destructors
SimpleQueryClause::SimpleQueryClause
(EXPRESSION_CONSTRUCTOR_BASE_PARAMETERS,
const std::string &identifier, ExpressionPtr expression)
: Expression(EXPRESSION_CONSTRUCTOR_BASE_PARAMETER_VALUES) {
m_identifier = identifier;
m_expression = expression;
}
ExpressionPtr SimpleQueryClause::clone() {
assert(false);
return nullptr;
}
///////////////////////////////////////////////////////////////////////////////
// parser functions
///////////////////////////////////////////////////////////////////////////////
// static analysis functions
void SimpleQueryClause::analyzeProgram(AnalysisResultPtr ar) {
m_expression->analyzeProgram(ar);
}
ConstructPtr SimpleQueryClause::getNthKid(int n) const {
switch (n) {
case 0:
return m_expression;
default:
assert(false);
break;
}
return ConstructPtr();
}
int SimpleQueryClause::getKidCount() const {
return 1;
}
void SimpleQueryClause::setNthKid(int n, ConstructPtr cp) {
switch (n) {
case 0:
m_expression = dynamic_pointer_cast<Expression>(cp);
break;
default:
break;
}
}
TypePtr SimpleQueryClause::inferTypes(AnalysisResultPtr ar,
TypePtr type, bool coerce) {
m_expression->inferAndCheck(ar, Type::Some, false);
return Type::Object;
}
///////////////////////////////////////////////////////////////////////////////
void SimpleQueryClause::outputCodeModel(CodeGenerator &cg) {
switch (this->getKindOf()) {
case Expression::KindOfFromClause:
cg.printObjectHeader("FromClause", 3);
cg.printPropertyHeader("identifier");
cg.printValue(m_identifier);
cg.printPropertyHeader("collection");
break;
case Expression::KindOfLetClause:
cg.printObjectHeader("LetClause", 3);
cg.printPropertyHeader("identifier");
cg.printValue(m_identifier);
cg.printPropertyHeader("expression");
break;
case Expression::KindOfIntoClause:
cg.printObjectHeader("IntoClause", 3);
cg.printPropertyHeader("identifier");
cg.printValue(m_identifier);
cg.printPropertyHeader("query");
break;
case Expression::KindOfWhereClause:
cg.printObjectHeader("WhereClause", 2);
cg.printPropertyHeader("condition");
break;
case Expression::KindOfSelectClause:
cg.printObjectHeader("SelectClause", 2);
cg.printPropertyHeader("expression");
break;
default:
assert(false);
break;
}
m_expression->outputCodeModel(cg);
cg.printPropertyHeader("sourceLocation");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
void SimpleQueryClause::outputPHP(
CodeGenerator &cg, AnalysisResultPtr ar) {
switch (this->getKindOf()) {
case Expression::KindOfFromClause:
cg_printf("from %s in ", m_identifier.c_str());
break;
case Expression::KindOfLetClause:
cg_printf("let %s in ", m_identifier.c_str());
break;
case Expression::KindOfIntoClause:
cg_printf("into %s ", m_identifier.c_str());
break;
case Expression::KindOfWhereClause:
cg_printf("where ");
break;
case Expression::KindOfSelectClause:
cg_printf("select ");
break;
default:
assert(false);
break;
}
m_expression->outputPHP(cg, ar);
}
@@ -1,151 +0,0 @@
/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP 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.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#ifndef incl_HPHP_SIMPLE_QUERY_CLAUSE_H_
#define incl_HPHP_SIMPLE_QUERY_CLAUSE_H_
#include "hphp/compiler/expression/expression.h"
#include "hphp/compiler/expression/expression_list.h"
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
DECLARE_BOOST_TYPES(SimpleQueryClause);
class SimpleQueryClause : public Expression {
public:
DECLARE_EXPRESSION_VIRTUAL_FUNCTIONS;
std::string getIdentifier() const { return m_identifier; }
ExpressionPtr getExpression() { return m_expression; }
void setExpression(ExpressionPtr value) { m_expression = value; }
protected:
SimpleQueryClause(EXPRESSION_CONSTRUCTOR_BASE_PARAMETERS,
const std::string &identifier, ExpressionPtr collection);
std::string m_identifier;
ExpressionPtr m_expression;
};
DECLARE_BOOST_TYPES(FromClause);
class FromClause : public SimpleQueryClause {
public:
FromClause(EXPRESSION_CONSTRUCTOR_PARAMETERS,
const std::string &identifier, ExpressionPtr collection)
: SimpleQueryClause(
EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES(FromClause),
identifier, collection) {
}
virtual ExpressionPtr clone() {
FromClausePtr exp(new FromClause(*this));
Expression::deepCopy(exp);
exp->m_identifier = m_identifier;
exp->m_expression = Clone(m_expression);
return exp;
}
};
DECLARE_BOOST_TYPES(LetClause);
class LetClause : public SimpleQueryClause {
public:
LetClause(EXPRESSION_CONSTRUCTOR_PARAMETERS,
const std::string &identifier, ExpressionPtr expression)
: SimpleQueryClause(
EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES(LetClause),
identifier, expression) {
}
virtual ExpressionPtr clone() {
LetClausePtr exp(new LetClause(*this));
Expression::deepCopy(exp);
exp->m_identifier = m_identifier;
exp->m_expression = Clone(m_expression);
return exp;
}
};
DECLARE_BOOST_TYPES(WhereClause);
class WhereClause : public SimpleQueryClause {
public:
WhereClause(EXPRESSION_CONSTRUCTOR_PARAMETERS,
ExpressionPtr condition)
: SimpleQueryClause(
EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES(WhereClause),
"", condition) {
}
virtual ExpressionPtr clone() {
WhereClausePtr exp(new WhereClause(*this));
Expression::deepCopy(exp);
exp->m_identifier = m_identifier;
exp->m_expression = Clone(m_expression);
return exp;
}
};
DECLARE_BOOST_TYPES(SelectClause);
class SelectClause : public SimpleQueryClause {
public:
SelectClause(EXPRESSION_CONSTRUCTOR_PARAMETERS,
ExpressionPtr expression)
: SimpleQueryClause(
EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES(SelectClause),
"", expression) {
}
virtual ExpressionPtr clone() {
SelectClausePtr exp(new SelectClause(*this));
Expression::deepCopy(exp);
exp->m_identifier = m_identifier;
exp->m_expression = Clone(m_expression);
return exp;
}
};
DECLARE_BOOST_TYPES(IntoClause);
class IntoClause : public SimpleQueryClause {
public:
IntoClause(EXPRESSION_CONSTRUCTOR_PARAMETERS,
const std::string &identifier, ExpressionPtr query)
: SimpleQueryClause(
EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES(IntoClause),
identifier, query) {
}
virtual ExpressionPtr clone() {
IntoClausePtr exp(new IntoClause(*this));
Expression::deepCopy(exp);
exp->m_identifier = m_identifier;
exp->m_expression = Clone(m_expression);
return exp;
}
};
///////////////////////////////////////////////////////////////////////////////
}
#endif // incl_HPHP_SIMPLE_QUERY_CLAUSE_H_
+1 -1
Ver Arquivo
@@ -313,7 +313,7 @@ void SimpleVariable::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("SimpleVariableExpression", 2);
cg.printPropertyHeader("variableName");
cg.printValue(m_name);
cg.printPropertyHeader("sourceLocation");
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
+4 -4
Ver Arquivo
@@ -169,13 +169,13 @@ bool StaticClassName::checkPresent() {
void StaticClassName::outputCodeModel(CodeGenerator &cg) {
if (isSelf()) {
cg.printValue("self");
cg.printf("self");
} else if (isParent()) {
cg.printValue("parent");
cg.printf("parent");
} else if (isStatic()) {
cg.printValue("static");
cg.printf("static");
} else {
cg.printValue(m_origClassName);
cg.printf("%s", m_origClassName.c_str());
}
}
@@ -340,7 +340,7 @@ bool StaticMemberExpression::canonCompare(ExpressionPtr e) const {
///////////////////////////////////////////////////////////////////////////////
void StaticMemberExpression::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("ClassPropertyExpression", 3);
cg.printObjectHeader("ClassPropertyExpression", 2);
cg.printPropertyHeader("className");
StaticClassName::outputCodeModel(cg);
if (m_exp->is(Expression::KindOfScalarExpression)) {
@@ -349,7 +349,7 @@ void StaticMemberExpression::outputCodeModel(CodeGenerator &cg) {
cg.printPropertyHeader("propertyExpression");
}
m_exp->outputCodeModel(cg);
cg.printPropertyHeader("sourceLocation");
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
+10 -41
Ver Arquivo
@@ -571,7 +571,6 @@ ExpressionPtr UnaryOpExpression::unneededHelper() {
///////////////////////////////////////////////////////////////////////////////
void UnaryOpExpression::outputCodeModel(CodeGenerator &cg) {
auto numProps = m_exp == nullptr ? 2 : 3;
switch (m_op) {
case T_UNSET:
case T_EXIT:
@@ -579,7 +578,7 @@ void UnaryOpExpression::outputCodeModel(CodeGenerator &cg) {
case T_ISSET:
case T_EMPTY:
case T_EVAL: {
cg.printObjectHeader("SimpleFunctionCallExpression", numProps);
cg.printObjectHeader("SimpleFunctionCallExpression", 3);
std::string funcName;
switch (m_op) {
case T_UNSET: funcName = "unset"; break;
@@ -592,11 +591,11 @@ void UnaryOpExpression::outputCodeModel(CodeGenerator &cg) {
}
cg.printPropertyHeader("functionName");
cg.printValue(funcName);
if (m_exp != nullptr) {
cg.printPropertyHeader("arguments");
cg.printExpressionVector(m_exp);
}
cg.printPropertyHeader("sourceLocation");
cg.printPropertyHeader("arguments");
printf("V:6:\"Vector\":1:{");
m_exp->outputCodeModel(cg);
printf("}");
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
return;
@@ -605,38 +604,9 @@ void UnaryOpExpression::outputCodeModel(CodeGenerator &cg) {
break;
}
switch (m_op) {
case T_FILE:
case T_DIR:
case T_CLASS:
case T_FUNCTION: {
cg.printObjectHeader("SimpleVariableExpression", 2);
std::string varName;
switch (m_op) {
case T_FILE: varName = "__FILE__"; break;
case T_DIR: varName = "__DIR__"; break;
//case T_CLASS: varName = "class"; break;
//case T_FUNCTION: varName = "function"; break;
default:
assert(false); //fishing expedition. Are these cases dead?
break;
}
cg.printPropertyHeader("variableName");
cg.printValue(varName);
cg.printPropertyHeader("sourceLocation");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
return;
}
default:
break;
}
cg.printObjectHeader("UnaryOpExpression", numProps);
if (m_exp != nullptr) {
cg.printPropertyHeader("expression");
m_exp->outputCodeModel(cg);
}
cg.printObjectHeader("UnaryOpExpression", 3);
cg.printPropertyHeader("expression");
m_exp->outputCodeModel(cg);
cg.printPropertyHeader("operation");
int op = 0;
switch (m_op) {
@@ -659,7 +629,6 @@ void UnaryOpExpression::outputCodeModel(CodeGenerator &cg) {
case T_BOOL_CAST: op = PHP_BOOL_CAST_OP; break;
case T_UNSET_CAST: op = PHP_UNSET_CAST_OP; break;
case '@': op = PHP_ERROR_CONTROL_OP; break;
case T_PRINT: op = PHP_PRINT_OP; break;
case T_INCLUDE: op = PHP_INCLUDE_OP; break;
case T_INCLUDE_ONCE: op = PHP_INCLUDE_ONCE_OP; break;
case T_REQUIRE: op = PHP_REQUIRE_OP; break;
@@ -668,7 +637,7 @@ void UnaryOpExpression::outputCodeModel(CodeGenerator &cg) {
assert(false);
}
cg.printValue(op);
cg.printPropertyHeader("sourceLocation");
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
+6 -12
Ver Arquivo
@@ -61,31 +61,25 @@ TypePtr UserAttribute::inferTypes(AnalysisResultPtr ar, TypePtr type,
///////////////////////////////////////////////////////////////////////////////
void UserAttribute::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("Attribute", m_exp != nullptr ? 3 : 2);
cg.printObjectHeader("CodeAttribute", m_exp != nullptr ? 3 : 2);
cg.printPropertyHeader("attributeName");
cg.printValue(m_name);
if (m_exp != nullptr && m_exp->is(Expression::KindOfUnaryOpExpression)) {
UnaryOpExpressionPtr u(static_pointer_cast<UnaryOpExpression>(m_exp));
if (u->getOp() == T_ARRAY) {
ExpressionPtr ex = u->getExpression();
if (ex != nullptr) {
if (ex->is(Expression::KindOfExpressionList)) {
ExpressionListPtr el(static_pointer_cast<ExpressionList>(ex));
cg.printPropertyHeader("expressions");
cg.printExpressionVector(el);
} else {
assert(false);
}
} else {
ExpressionListPtr el;
if (ex->is(Expression::KindOfExpressionList)) {
ExpressionListPtr el(static_pointer_cast<ExpressionList>(ex));
cg.printPropertyHeader("expressions");
cg.printExpressionVector(el);
} else {
assert(false);
}
} else {
assert(false);
}
}
cg.printPropertyHeader("sourceLocation");
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
+1 -1
Ver Arquivo
@@ -106,7 +106,7 @@ void YieldExpression::outputCodeModel(CodeGenerator &cg) {
}
cg.printPropertyHeader("value");
m_valExp->outputCodeModel(cg);
cg.printPropertyHeader("sourceLocation");
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}

Alguns arquivos não foram exibidos porque demasiados arquivos foram alterados neste diff Mostrar Mais