2 Commits

Autor SHA1 Mensagem Data
hermanv b74a0da062 Add support for UTS #46, along the lines of Zend, to idn_to_ascii.
Removes the output errorCode parameter (that is not currently used anywhere, except in testing code that gets but ignores it). Adds the options, variant and
idna_info parameters that are present in the Zend version of idn_to_ascii. Implement the new functionality required by these parameters by using the UTS #46 API, if
present.
2013-02-19 07:48:43 -08:00
ptarjan e663cfb0fd make test filters consistent
Summary:
Here are all the lines in filters: https://phabricator.fb.com/P1981345

About 1/2 of them are removing the path. I thought about doing it by default but the easiest still seemed like an opt-in symlink. I re-used another script someone else wrote so if it misses some edge case lets just fix that script. I don't like the name of it since it is hard to remembrer what to symlink, but I guess ##ls##ing isn't too bad.

Done with:

    grep -l "^sed -e 's/[\]/\.\*hphp/hphp/g'$" * | xargs -I{} ln -sf filepath.filter {}
    grep -l "^sed -e 's, in \[^ \]\*hphp/, in hphp/,'$" * | xargs -I{} ln -sf filepath.filter {}
    grep -l "^sed -e 's/in [\]/\.\*hphp/in hphp/g'$" * | xargs -I{} ln -sf filepath.filter {}
    grep -l "^sed -e 's, \[^ \]\*hphp/, hphp/,g'$" * | xargs -I{} ln -sf filepath.filter {}
    grep -l "^sed -e 's/ in [\]/\.\*hphp\.\*$//g'$" * | xargs -I{} ln -sf filepath.filter {}
    grep -l "^sed -e 's, \[^ \]\*\(hphp/\.\*[\])\$, [\]1,g'$" * | xargs -I{} ln -sf filepath.filter {}
    grep -l "^sed -e 's, \[^ \]\*[\](hphp/\.\*[\])\$, [\]1,g'$" * | xargs -I{} ln -sf filepath.filter {}

then i did the rest by hand with:

    vim `find . -type f -name '*.filter'`

and then took all the test output as gospel (after looking it over of course):

    for i in `ls *.out`; do j=`echo $i | sed s/out/exp/`; mv $i $j; done

Test Plan:
make verify_quick

  $ grep sed `find . -type f -name '*.filter' ` | grep -v filepath
  ./closure.filter:sed -r -e 's,(Closure\$)([^$]*\$){3}[0-9_]*,\1,g'
  ./backup_cycle_collector.php.filter:exec sed -e 's/cpu\ time.*//g'
  ./perfctr.php.filter:sed -e '/int(.*/d'
  ./reflection.php.filter:sed -e 's/^\([ ]*object([^)]\+)\)#[0-9]\+/\1/g' | sed -e 's/^string.*"\/.*hphp/"hphp/g'
  ./Setprofile.php.filter:sed -e 's/.*hphp\//hphp\//g' -e 's/.*systemlib.*//g' -e 's/string(..) "[0-9]\+_[0-9]\+"/string() "XX_X"/'
  ./builtin_call.php.filter:sed -e '/SlowTimer/d'
  ./serialize.php.filter:sed -e 's/^\(object([^)]\+)\)#[0-9]\+/\1/g'
  ./properties.php.filter:sed -e 's/^\(object([^)]\+)\)#[0-9]\+/\1/g'
  ./PropU.php.filter:sed -e 's/^\(object([^)]\+)\)#[0-9]\+/\1/g'
  ./destructed_this.php.filter:exec sed -e's/.*string.*//g'
  ./bitop_types.php.filter:sed -e 's,to int in string on line [0-9]*,to int,g'
  ./debug_backtrace.php.filter:sed -e 's/string(.*) ".*\/hphp/string() "hphp/g'
  ./resurrect.php.filter:sed -e 's/^\(object([^)]\+)\)#[0-9]\+/\1/g'
  ./objiter.php.filter:sed -e 's/^\(object([^)]\+)\)#[0-9]\+/\1/g'
  ./magic-get-set.php.filter:sed -e 's/^\(object([^)]\+)\)#[0-9]\+/\1/g'
  ./clone.php.filter:sed -e 's/^\(object([^)]\+)\)#[0-9]\+/\1/g'
  ./setprofile_throw.php.filter:exec sed -e 's/hook threw.*//g'

Reviewers: jdelong, andrewparoski, mwilliams

Reviewed By: mwilliams

CC: hphp-diffs@lists, ps, mwilliams, ottoni, smith

Differential Revision: https://phabricator.fb.com/D708806
2013-02-19 07:02:21 -08:00
41847 arquivos alterados com 1008182 adições e 2441053 exclusões
+14 -10
Ver Arquivo
@@ -1,5 +1,10 @@
*.[oad]
*.hhbc
/bin*-g
/bin*-O
/bin/*.so
/bin/hphp_options
/bin/systemlib.php
.mkdir
hphp.log
@@ -26,33 +31,32 @@ hphp.log
/hphp/runtime/tmp/run
/hphp/runtime/tmp/run.sh
/hphp/runtime/tmp/libtest.so
/hphp/hphp-build-info.cpp
/hphp/hphp-repo-schema.h
/hphp/runtime/vm/repo_schema.h
/hphp/runtime/base/compiler_id.h
/hphp/hphpi/gen
/hphp/hphpi/hphpi
/hphp/hhvm/gen
/hphp/hhvm/hhvm
*.ext_hhvm.cpp
*.ext_hhvm.h
/hphp/runtime/ext_hhvm/ext_hhvm_infotabs.cpp
/hphp/runtime/ext_hhvm/ext_hhvm_infotabs.h
/hphp/tools/shmw/shmw
/hphp/ffi/java/classes
/hphp/ffi/java/hphp_ffi_java.h
# Ignore all makefiles generated for fbcode's third-party repo
/bin/*.mk
!/bin/run.mk
CMakeFiles
CMakeCache.txt
cmake_install.cmake
install_manifest.txt
/output_gd/
/hphp/TAGS
/hphp/third_party/libzip/libzip.dylib
# Generated makefiles
/hphp/runtime/ext_hhvm/Makefile
/hphp/test/Makefile
-3
Ver Arquivo
@@ -1,3 +0,0 @@
[submodule "hphp/submodules/folly"]
path = hphp/submodules/folly
url = git://github.com/facebook/folly.git
-38
Ver Arquivo
@@ -1,38 +0,0 @@
language: cpp
compiler:
- gcc
before_script:
- time 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=""
# 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 -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
notifications:
email: false
irc: "chat.freenode.net#hhvm"
-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()
-13
Ver Arquivo
@@ -1,13 +0,0 @@
if (EDITLINE_LIBRARIES AND EDITLINE_INCLUDE_DIRS)
set (Editline_FIND_QUIETLY TRUE)
endif (EDITLINE_LIBRARIES AND EDITLINE_INCLUDE_DIRS)
find_path(EDITLINE_INCLUDE_DIRS NAMES editline/readline.h)
find_library(EDITLINE_LIBRARIES NAMES edit)
include (FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Editline DEFAULT_MSG
EDITLINE_LIBRARIES
EDITLINE_INCLUDE_DIRS)
mark_as_advanced(EDITLINE_INCLUDE_DIRS EDITLINE_LIBRARIES)
-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
)
-14
Ver Arquivo
@@ -56,20 +56,6 @@ if(ICU_INCLUDE_DIR AND ICU_LIBRARY)
set(ICU_I18N_FOUND 0)
set(ICU_I18N_LIBRARIES)
endif (ICU_I18N_LIBRARY)
# Look for the ICU data libraries
find_library(
ICU_DATA_LIBRARY
NAMES icudata cygicudata cygicudata32
DOC "Libraries to link against for ICU data")
mark_as_advanced(ICU_DATA_LIBRARY)
if (ICU_DATA_LIBRARY)
set(ICU_DATA_FOUND 1)
set(ICU_DATA_LIBRARIES ${ICU_DATA_LIBRARY})
else (ICU_DATA_LIBRARY)
set(ICU_DATA_FOUND 0)
set(ICU_DATA_LIBRARIES)
endif (ICU_DATA_LIBRARY)
else(ICU_INCLUDE_DIR AND ICU_LIBRARY)
set(ICU_FOUND 0)
set(ICU_I18N_FOUND 0)
-27
Ver Arquivo
@@ -1,27 +0,0 @@
# - Try to find libdl
# Once done this will define
#
# LIBDL_FOUND - system has libdl
# LIBDL_INCLUDE_DIRS - the libdl include directory
# LIBDL_LIBRARIES - Link these to use libdl
# LIBDL_NEEDS_UNDERSCORE - If extern "C" symbols are prefixed (BSD/Apple)
#
find_path (LIBDL_INCLUDE_DIRS NAMES dlfcn.h)
find_library (LIBDL_LIBRARIES NAMES dl)
include (FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibDL DEFAULT_MSG
LIBDL_LIBRARIES
LIBDL_INCLUDE_DIRS)
SET(CMAKE_REQUIRED_LIBRARIES dl)
INCLUDE(CheckCSourceRuns)
CHECK_C_SOURCE_RUNS("#include <dlfcn.h>
void testfunc() {}
int main() {
testfunc();
return dyslm(0, \"_testfunc\") != (void*)0;
}" LIBDL_NEEDS_UNDERSCORE)
mark_as_advanced(LIBDL_INCLUDE_DIRS LIBDL_LIBRARIES LIBDL_NEEDS_UNDERSCORE)
+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)
+1 -10
Ver Arquivo
@@ -51,14 +51,5 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibElf DEFAULT_MSG
LIBELF_LIBRARIES
LIBELF_INCLUDE_DIRS)
SET(CMAKE_REQUIRED_LIBRARIES elf)
INCLUDE(CheckCXXSourceCompiles)
CHECK_CXX_SOURCE_COMPILES("#include <libelf.h>
int main() {
Elf *e = (Elf*)0;
size_t sz;
elf_getshdrstrndx(e, &sz);
return 0;
}" ELF_GETSHDRSTRNDX)
mark_as_advanced(LIBELF_INCLUDE_DIRS LIBELF_LIBRARIES ELF_GETSHDRSTRNDX)
mark_as_advanced(LIBELF_INCLUDE_DIRS LIBELF_LIBRARIES)
-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)
-13
Ver Arquivo
@@ -1,13 +0,0 @@
if (LIBNUMA_LIBRARIES AND LIBNUMA_INCLUDE_DIRS)
set (LibNuma_FIND_QUIETLY TRUE)
endif (LIBNUMA_LIBRARIES AND LIBNUMA_INCLUDE_DIRS)
find_path(LIBNUMA_INCLUDE_DIRS NAMES numa.h)
find_library(LIBNUMA_LIBRARIES NAMES numa)
include (FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibNuma DEFAULT_MSG
LIBNUMA_LIBRARIES
LIBNUMA_INCLUDE_DIRS)
mark_as_advanced(LIBNUMA_INCLUDE_DIRS LIBNUMA_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)
+28
Ver Arquivo
@@ -0,0 +1,28 @@
#
# $Id$
#
# - Find libunwind
# Find libunwind
#
# LIBUNWIND_INCLUDE_DIR - where to find unwind.h and libunwind.h
# LIBUNWIND_LIBRARY - List of libraries when using libunwind
# LIBUNWIND_FOUND - True if libunwind found.
if(LIBUNWIND_INCLUDE_DIR)
# Already in cache, be silent
SET(LIBUNWIND_FIND_QUIETLY TRUE)
endif()
FIND_PATH(LIBUNWIND_INCLUDE_DIR libunwind.h)
if(NOT EXISTS "${LIBUNWIND_INCLUDE_DIR}/unwind.h")
message(FATAL_ERROR "libunwind.h found without matching unwind.h")
SET(LIBUNWIND_INCLUDE_DIR "")
endif()
FIND_LIBRARY(LIBUNWIND_LIBRARY unwind)
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBUNWIND DEFAULT_MSG LIBUNWIND_LIBRARY LIBUNWIND_INCLUDE_DIR)
MARK_AS_ADVANCED(LIBUNWIND_LIBRARY LIBUNWIND_INCLUDE_DIR)
+1 -1
Ver Arquivo
@@ -29,7 +29,7 @@
#-------------- FIND MYSQL_INCLUDE_DIR ------------------
FIND_PATH(MYSQL_INCLUDE_DIR mysql.h
FIND_PATH(MYSQL_INCLUDE_DIR mysql/mysql.h
$ENV{MYSQL_INCLUDE_DIR}
$ENV{MYSQL_DIR}/include
/usr/include/mysql
-27
Ver Arquivo
@@ -1,27 +0,0 @@
# - Try to find libpthread
#
# Once done this will define
#
# LIBPTHREAD_FOUND - system has libpthread
# LIBPTHREAD_INCLUDE_DIRS - the libpthread include directory
# LIBPTHREAD_LIBRARIES - Link these to use libpthread
# LIBPTHREAD_DEFINITIONS - Compiler switches required for using libpthread
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
#
if (LIBPTHREAD_LIBRARIES AND LIBPTHREAD_INCLUDE_DIRS)
set (LIBPTHREAD_FIND_QUIETLY TRUE)
endif (LIBPTHREAD_LIBRARIES AND LIBPTHREAD_INCLUDE_DIRS)
find_path (LIBPTHREAD_INCLUDE_DIRS NAMES pthread.h)
find_library (LIBPTHREAD_LIBRARIES NAMES pthread)
include (FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBPTHREAD DEFAULT_MSG
LIBPTHREAD_LIBRARIES LIBPTHREAD_INCLUDE_DIRS)
mark_as_advanced(LIBPTHREAD_INCLUDE_DIRS LIBPTHREAD_LIBRARIES LIBPTHREAD_FOUND)
-28
Ver Arquivo
@@ -1,28 +0,0 @@
# folly-config.h is a generated file from autotools
# We need to do the equivalent checks here and use
# add_definitions as needed
add_definitions(-DFOLLY_NO_CONFIG=1)
INCLUDE(CheckCXXSourceCompiles)
CHECK_CXX_SOURCE_COMPILES("
extern \"C\" void (*test_ifunc(void))() { return 0; }
void func() __attribute__((ifunc(\"test_ifunc\")));
" FOLLY_IFUNC)
if (FOLLY_IFUNC)
add_definitions("-DHAVE_IFUNC=1")
endif()
set(CMAKE_REQUIRED_LIBRARIES rt)
include(CheckFunctionExists)
CHECK_FUNCTION_EXISTS("clock_gettime" HAVE_CLOCK_GETTIME)
if (HAVE_CLOCK_GETTIME)
add_definitions("-DFOLLY_HAVE_CLOCK_GETTIME=1")
endif()
set(CMAKE_REQUIRED_LIBRARIES)
find_path(FEATURES_H_INCLUDE_DIR NAMES features.h)
if (FEATURES_H_INCLUDE_DIR)
include_directories("${FEATURES_H_INCLUDE_DIR}")
add_definitions("-DFOLLY_HAVE_FEATURES_H=1")
endif()
-56
Ver Arquivo
@@ -1,56 +0,0 @@
if(CMAKE_COMPILER_IS_GNUCC)
INCLUDE(CheckCSourceCompiles)
CHECK_C_SOURCE_COMPILES("#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
#if GCC_VERSION < 40700
#error Not GCC 4.7.0+
#endif
int main() { return 0; }" HAVE_GCC_47)
if (NOT HAVE_GCC_47)
message(FATAL_ERROR "Need at least GCC 4.7")
endif()
CHECK_C_SOURCE_COMPILES("#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
#if GCC_VERSION < 40800
#error Not GCC 4.8.0+
#endif
int main() { return 0; }" HAVE_GCC_48)
endif()
set(FREEBSD FALSE)
set(LINUX FALSE)
if("${CMAKE_SYSTEM_NAME}" STREQUAL "FreeBSD")
set(FREEBSD TRUE)
endif()
if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
set(LINUX TRUE)
endif()
if($ENV{CXX} MATCHES "icpc")
set(CMAKE_C_FLAGS "-no-ipo -fp-model precise -wd584 -wd1418 -wd1918 -wd383 -wd869 -wd981 -wd424 -wd1419 -wd444 -wd271 -wd2259 -wd1572 -wd1599 -wd82 -wd177 -wd593 -w")
set(CMAKE_CXX_FLAGS "-no-ipo -fp-model precise -wd584 -wd1418 -wd1918 -wd383 -wd869 -wd981 -wd424 -wd1419 -wd444 -wd271 -wd2259 -wd1572 -wd1599 -wd82 -wd177 -wd593 -fno-omit-frame-pointer -ftemplate-depth-180 -Wall -Woverloaded-virtual -Wno-deprecated -w1 -Wno-strict-aliasing -Wno-write-strings -Wno-invalid-offsetof -fno-operator-names")
else()
set(GNUCC_48_OPT "")
if(HAVE_GCC_48)
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")
endif()
if(CMAKE_COMPILER_IS_GNUCC)
set(CMAKE_C_FLAGS_RELEASE "-O3")
endif()
if(CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS_RELEASE "-O3")
endif()
+76 -158
Ver Arquivo
@@ -17,25 +17,16 @@
include(CheckFunctionExists)
# libdl
find_package(LibDL)
if (LIBDL_INCLUDE_DIRS)
add_definitions("-DHAVE_LIBDL")
include_directories(${LIBDL_INCLUDE_DIRS})
if (LIBDL_NEEDS_UNDERSCORE)
add_definitions("-DLIBDL_NEEDS_UNDERSCORE")
endif()
# boost checks
find_package(Boost 1.37.0 COMPONENTS system;program_options;filesystem REQUIRED)
if (BOOST_VERSION EQUAL 104200)
# Boost bug #3942 prevents us using 1.42
message(FATAL_ERROR "Boost 1.42 is not compatible with HipHop")
endif()
# boost checks
find_package(Boost 1.48.0 COMPONENTS system program_options filesystem regex REQUIRED)
include_directories(${Boost_INCLUDE_DIRS})
link_directories(${Boost_LIBRARY_DIRS})
# Boost 1.49 supports a better flat_multimap, but 1.48 is good enough
if (Boost_VERSION GREATER 104899)
add_definitions("-DHAVE_BOOST1_49")
endif()
# features.h
FIND_PATH(FEATURES_HEADER features.h)
@@ -53,6 +44,10 @@ if (LIBINOTIFY_INCLUDE_DIR)
include_directories(${LIBINOTIFY_INCLUDE_DIR})
endif()
# unwind checks
find_package(Libunwind REQUIRED)
include_directories(${LIBUNWIND_INCLUDE_DIR})
# iconv checks
find_package(Libiconv REQUIRED)
include_directories(${LIBICONV_INCLUDE_DIR})
@@ -90,46 +85,29 @@ include_directories(${LIBEVENT_INCLUDE_DIR})
set(CMAKE_REQUIRED_LIBRARIES "${LIBEVENT_LIB}")
CHECK_FUNCTION_EXISTS("evhttp_bind_socket_with_fd" HAVE_CUSTOM_LIBEVENT)
if(HAVE_CUSTOM_LIBEVENT)
message("Using custom LIBEVENT")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAVE_CUSTOM_LIBEVENT")
endif()
if (NOT HAVE_CUSTOM_LIBEVENT)
unset(HAVE_CUSTOM_LIBEVENT CACHE)
unset(LIBEVENT_INCLUDE_DIR CACHE)
unset(LIBEVENT_LIB CACHE)
unset(LibEvent_FOUND CACHE)
message(FATAL_ERROR "Custom libevent is required with HipHop patches")
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")
find_package(GD REQUIRED)
if (WANT_FB_LIBMCC)
add_definitions(-DHPHP_WITH_LIBMCC)
message(FATAL_ERROR Need to add libmcc and libch for linking)
else ()
# nothing for now
endif()
# 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
@@ -165,7 +143,16 @@ include_directories("${HPHP_HOME}/hphp/third_party/libmbfl/filter")
include_directories("${HPHP_HOME}/hphp/third_party/lz4")
include_directories("${HPHP_HOME}/hphp/third_party/double-conversion/src")
include_directories("${HPHP_HOME}/hphp/third_party/folly")
include_directories("${HPHP_HOME}/hphp/third_party/libzip")
FIND_LIBRARY(XHP_LIB xhp)
FIND_PATH(XHP_INCLUDE_DIR xhp_preprocess.hpp)
if (XHP_LIB AND XHP_INCLUDE_DIR)
include_directories(${XHP_INCLUDE_DIR})
set(SKIP_BUNDLED_XHP ON)
else()
include_directories("${HPHP_HOME}/hphp/third_party/xhp/xhp")
endif()
# ICU
find_package(ICU REQUIRED)
@@ -179,6 +166,9 @@ if (ICU_FOUND)
include_directories(${ICU_INCLUDE_DIRS})
endif (ICU_FOUND)
# (google heap OR cpu profiler) AND libunwind
FIND_LIBRARY(UNWIND_LIB unwind)
# jemalloc/tmalloc and profiler
if (USE_GOOGLE_HEAP_PROFILER OR USE_GOOGLE_CPU_PROFILER)
FIND_LIBRARY(GOOGLE_PROFILER_LIB profiler)
@@ -203,35 +193,17 @@ if (USE_GOOGLE_HEAP_PROFILER AND GOOGLE_PROFILER_LIB)
endif()
endif()
if (USE_JEMALLOC AND NOT GOOGLE_TCMALLOC_ENABLED)
FIND_LIBRARY(JEMALLOC_LIB NAMES jemalloc)
FIND_PATH(JEMALLOC_INCLUDE_DIR NAMES jemalloc/jemalloc.h)
if (JEMALLOC_INCLUDE_DIR AND JEMALLOC_LIB)
include_directories(${JEMALLOC_INCLUDE_DIR})
set (CMAKE_REQUIRED_INCLUDES ${JEMALLOC_INCLUDE_DIR})
INCLUDE(CheckCXXSourceCompiles)
CHECK_CXX_SOURCE_COMPILES("
#include <jemalloc/jemalloc.h>
int main(void) {
#if !defined(JEMALLOC_VERSION_MAJOR) || (JEMALLOC_VERSION_MAJOR < 3)
# error \"jemalloc version >= 3.0.0 required\"
#endif
return 0;
}" JEMALLOC_VERSION_3)
set (CMAKE_REQUIRED_INCLUDES)
if (JEMALLOC_VERSION_3)
message(STATUS "Found jemalloc: ${JEMALLOC_LIB}")
set(JEMALLOC_ENABLED 1)
else()
message(STATUS "Found jemalloc, but it was too old")
endif()
if (USE_JEMALLOC AND NOT GOOGLE_TCMALLOC_ENABLED
AND NOT CMAKE_BUILD_TYPE STREQUAL Debug)
FIND_LIBRARY(JEMALLOC_LIB jemalloc)
if (JEMALLOC_LIB)
message(STATUS "Found jemalloc: ${JEMALLOC_LIB}")
set(JEMALLOC_ENABLED 1)
endif()
endif()
if (USE_TCMALLOC AND NOT JEMALLOC_ENABLED AND NOT GOOGLE_TCMALLOC_ENABLED)
if (USE_TCMALLOC AND NOT JEMALLOC_ENABLED AND NOT GOOGLE_TCMALLOC_ENABLED
AND NOT CMAKE_BUILD_TYPE STREQUAL Debug)
FIND_LIBRARY(GOOGLE_TCMALLOC_MIN_LIB tcmalloc_minimal)
if (GOOGLE_TCMALLOC_MIN_LIB)
message(STATUS "Found minimal tcmalloc: ${GOOGLE_TCMALLOC_MIN_LIB}")
@@ -298,36 +270,17 @@ include_directories(${LDAP_INCLUDE_DIR})
find_package(Ncurses REQUIRED)
include_directories(${NCURSES_INCLUDE_PATH})
# libpthreads
find_package(PThread REQUIRED)
include_directories(${LIBPTHREAD_INCLUDE_DIRS})
# Either Readline or Editline (for hphpd)
find_package(Readline)
find_package(Editline)
if (READLINE_INCLUDE_DIR)
include_directories(${READLINE_INCLUDE_DIR})
elseif (EDITLINE_INCLUDE_DIRS)
add_definitions("-DUSE_EDITLINE")
include_directories(${EDITLINE_INCLUDE_DIRS})
else()
message(FATAL_ERROR "Could not find Readline or Editline")
endif()
find_package(Readline REQUIRED)
include_directories(${READLINE_INCLUDE_DIR})
find_package(CClient REQUIRED)
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})
if (ELF_GETSHDRSTRNDX)
add_definitions("-DHAVE_ELF_GETSHDRSTRNDX")
endif()
CONTAINS_STRING("${CCLIENT_INCLUDE_PATH}/utf8.h" U8T_DECOMPOSE RECENT_CCLIENT)
if (NOT RECENT_CCLIENT)
@@ -335,35 +288,29 @@ 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)
add_definitions(-DSKIP_IMAP_GSS=1)
endif()
CONTAINS_STRING("${CCLIENT_INCLUDE_PATH}/linkage.h" auth_gss CCLIENT_NEEDS_PAM)
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 (CCLIENT_NEEDS_PAM)
find_package(Libpam REQUIRED)
include_directories(${PAM_INCLUDE_PATH})
else()
add_definitions(-DSKIP_IMAP_GSS=1)
endif()
if (NOT CCLIENT_HAS_SSL)
add_definitions(-DSKIP_IMAP_SSL=1)
endif()
FIND_LIBRARY(CRYPT_LIB NAMES xcrypt crypt crypto)
if (LINUX OR FREEBSD)
FIND_LIBRARY (CRYPT_LIB NAMES xcrypt crypt)
FIND_LIBRARY (RT_LIB rt)
elseif (APPLE)
FIND_LIBRARY (CRYPT_LIB crypto)
FIND_LIBRARY (ICONV_LIB iconv)
endif()
if (LINUX)
@@ -397,14 +344,6 @@ if (FREEBSD)
endif()
endif()
if (APPLE)
find_library(LIBINTL_LIBRARIES NAMES intl libintl)
if (LIBINTL_INCLUDE_DIR)
include_directories(${LIBINTL_INCLUDE_DIR})
endif()
find_library(KERBEROS_LIB NAMES gssapi_krb5)
endif()
#find_package(BISON REQUIRED)
#find_package(FLEX REQUIRED)
@@ -416,10 +355,6 @@ include_directories(${HPHP_HOME}/hphp)
include_directories(${HPHP_HOME}/hphp/system/gen)
macro(hphp_link target)
if (LIBDL_LIBRARIES)
target_link_libraries(${target} ${LIBDL_LIBRARIES})
endif ()
if (GOOGLE_HEAP_PROFILER_ENABLED OR GOOGLE_CPU_PROFILER_ENABLED)
target_link_libraries(${target} ${GOOGLE_PROFILER_LIB})
endif()
@@ -435,9 +370,10 @@ macro(hphp_link target)
endif()
target_link_libraries(${target} ${Boost_LIBRARIES})
target_link_libraries(${target} ${LIBUNWIND_LIBRARY})
target_link_libraries(${target} ${MYSQL_CLIENT_LIBS})
target_link_libraries(${target} ${PCRE_LIBRARY})
target_link_libraries(${target} ${ICU_DATA_LIBRARIES} ${ICU_I18N_LIBRARIES} ${ICU_LIBRARIES})
target_link_libraries(${target} ${ICU_LIBRARIES} ${ICU_I18N_LIBRARIES})
target_link_libraries(${target} ${LIBEVENT_LIB})
target_link_libraries(${target} ${CURL_LIBRARIES})
target_link_libraries(${target} ${LIBGLOG_LIBRARY})
@@ -468,16 +404,9 @@ if (FREEBSD)
target_link_libraries(${target} ${EXECINFO_LIB})
endif()
if (APPLE)
target_link_libraries(${target} ${LIBINTL_LIBRARIES})
target_link_libraries(${target} ${KERBEROS_LIB})
endif()
target_link_libraries(${target} ${BFD_LIB})
target_link_libraries(${target} ${BINUTIL_LIB})
if (${LIBPTHREAD_LIBRARIES})
target_link_libraries(${target} ${LIBPTHREAD_LIBRARIES})
endif()
target_link_libraries(${target} pthread)
target_link_libraries(${target} ${TBB_LIBRARIES})
target_link_libraries(${target} ${OPENSSL_LIBRARIES})
target_link_libraries(${target} ${ZLIB_LIBRARIES})
@@ -488,29 +417,18 @@ 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})
target_link_libraries(${target} ${LIBMEMCACHED_LIBRARY})
target_link_libraries(${target} ${CRYPT_LIB})
if (LINUX OR FREEBSD)
target_link_libraries(${target} ${CRYPT_LIB})
target_link_libraries(${target} ${RT_LIB})
elseif (APPLE)
target_link_libraries(${target} ${CRYPTO_LIB})
target_link_libraries(${target} ${ICONV_LIB})
endif()
target_link_libraries(${target} timelib)
@@ -518,21 +436,21 @@ endif()
target_link_libraries(${target} lz4)
target_link_libraries(${target} double-conversion)
target_link_libraries(${target} folly)
target_link_libraries(${target} zip_static)
if (SKIP_BUNDLED_XHP)
target_link_libraries(${target} ${XHP_LIB})
else()
target_link_libraries(${target} xhp)
endif()
target_link_libraries(${target} afdt)
target_link_libraries(${target} mbfl)
if (READLINE_LIBRARY)
target_link_libraries(${target} ${READLINE_LIBRARY})
elseif (EDITLINE_LIBRARIES)
target_link_libraries(${target} ${EDITLINE_LIBRARIES})
endif()
target_link_libraries(${target} ${READLINE_LIBRARY})
target_link_libraries(${target} ${NCURSES_LIBRARY})
target_link_libraries(${target} ${CCLIENT_LIBRARY})
if (PAM_LIBRARY)
if (CCLIENT_NEEDS_PAM)
target_link_libraries(${target} ${PAM_LIBRARY})
endif()
-78
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)
@@ -88,60 +67,3 @@ macro(MYSQL_SOCKET_SEARCH)
set(MYSQL_UNIX_SOCK_ADDR ${MYSQL_SOCK} CACHE STRING "Path to MySQL Socket")
endif()
endmacro()
function(embed_systemlib TARGET DEST SOURCE SECTNAME)
if (APPLE)
target_link_libraries(${TARGET} -Wl,-sectcreate,__text,${SECTNAME},${SOURCE})
else()
add_custom_command(TARGET ${TARGET} POST_BUILD
COMMAND "objcopy"
ARGS "--add-section" "${SECTNAME}=${SOURCE}" ${DEST}
COMMENT "Embedding ${SOURCE} in ${TARGET} as ${SECTNAME}")
endif()
# Add the systemlib file to the "LINK_DEPENDS" for the systemlib, this will cause it
# to be relinked and the systemlib re-embedded
set_property(TARGET ${TARGET} APPEND PROPERTY LINK_DEPENDS ${SOURCE})
endfunction(embed_systemlib)
function(embed_all_systemlibs TARGET DEST)
embed_systemlib(${TARGET} ${DEST} ${HPHP_HOME}/hphp/system/systemlib.php systemlib)
auto_sources(SYSTEMLIBS "ext_*.php" "RECURSE" "${HPHP_HOME}/hphp/runtime")
foreach(SLIB ${SYSTEMLIBS})
get_filename_component(SLIB_BN ${SLIB} "NAME_WE")
string(LENGTH ${SLIB_BN} SLIB_BN_LEN)
math(EXPR SLIB_BN_REL_LEN "${SLIB_BN_LEN} - 4")
string(SUBSTRING ${SLIB_BN} 4 ${SLIB_BN_REL_LEN} SLIB_EXTNAME)
string(MD5 SLIB_HASH_NAME ${SLIB_EXTNAME})
string(SUBSTRING ${SLIB_HASH_NAME} 0 12 SLIB_HASH_NAME_SHORT)
embed_systemlib(${TARGET} ${DEST} ${SLIB} "ext.${SLIB_HASH_NAME_SHORT}")
endforeach()
endfunction(embed_all_systemlibs)
# Custom install function that doesn't relink, instead it uses chrpath to change it, if
# it's available, otherwise, it leaves the chrpath alone
function(HHVM_INSTALL TARGET DEST)
get_target_property(LOC ${TARGET} LOCATION)
get_target_property(TY ${TARGET} TYPE)
if (FOUND_CHRPATH)
get_target_property(RPATH ${TARGET} INSTALL_RPATH)
if (NOT RPATH STREQUAL "RPATH-NOTFOUND")
if (RPATH STREQUAL "")
install(CODE "execute_process(COMMAND \"${CHRPATH}\" \"-d\" \"${LOC}\" ERROR_QUIET)")
else()
install(CODE "execute_process(COMMAND \"${CHRPATH}\" \"-r\" \"${RPATH}\" \"${LOC}\" ERROR_QUIET)")
endif()
endif()
endif()
install(CODE "FILE(INSTALL DESTINATION \"\${CMAKE_INSTALL_PREFIX}/${DEST}\" TYPE ${TY} FILES \"${LOC}\")")
endfunction(HHVM_INSTALL)
function(HHVM_EXTENSION EXTNAME)
list(REMOVE_AT ARGV 0)
add_library(${EXTNAME} SHARED ${ARGV})
set_target_properties(${EXTNAME} PROPERTIES PREFIX "")
set_target_properties(${EXTNAME} PROPERTIES SUFFIX ".so")
endfunction()
function(HHVM_SYSTEMLIB EXTNAME SOURCE_FILE)
embed_systemlib(${EXTNAME} "${EXTNAME}.so" ${SOURCE_FILE} systemlib)
endfunction()
+67 -74
Ver Arquivo
@@ -1,37 +1,5 @@
include(Options)
# Do this until cmake has a define for ARMv8
INCLUDE(CheckCXXSourceCompiles)
CHECK_CXX_SOURCE_COMPILES("
#ifndef __AARCH64EL__
#error Not ARMv8
#endif
int main() { return 0; }" IS_AARCH64)
if (APPLE OR IS_AARCH64)
set(HHVM_ANCHOR_SYMS -Wl,-u,_register_libevent_server)
else()
set(ENABLE_FASTCGI 1)
set(HHVM_ANCHOR_SYMS -Wl,-uregister_libevent_server,-uregister_fastcgi_server)
endif()
set(HHVM_LINK_LIBRARIES
hphp_analysis
hphp_runtime_static
ext_hhvm_static
hphp_system
hphp_parser
hphp_zend
hphp_util
hphp_hhbbc
vixl neo
${HHVM_ANCHOR_SYMS})
if(ENABLE_FASTCGI)
LIST(APPEND HHVM_LINK_LIBRARIES hphp_thrift)
LIST(APPEND HHVM_LINK_LIBRARIES hphp_proxygen)
endif()
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release")
endif()
@@ -40,13 +8,29 @@ IF(NOT DEFINED CMAKE_PREFIX_PATH)
message(STATUS "CMAKE_PREFIX_PATH was missing, proceeding anyway")
endif()
# Look for the chrpath tool so we can warn if it's not there
find_program(CHRPATH chrpath)
IF (CHRPATH STREQUAL "CHRPATH-NOTFOUND")
SET(FOUND_CHRPATH OFF)
message(WARNING "chrpath not found, rpath will not be stripped from installed binaries")
else()
SET(FOUND_CHRPATH ON)
if(CMAKE_COMPILER_IS_GNUCC)
INCLUDE(CheckCSourceCompiles)
CHECK_C_SOURCE_COMPILES("#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
#if GCC_VERSION < 40400
#error Need GCC 4.4.0+
#endif
int main() { return 0; }" HAVE_GCC_44)
if(NOT HAVE_GCC_44)
message(FATAL_ERROR "Need at least GCC 4.4")
endif()
endif()
set(FREEBSD FALSE)
set(LINUX FALSE)
if("${CMAKE_SYSTEM_NAME}" STREQUAL "FreeBSD")
set(FREEBSD TRUE)
endif()
if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
set(LINUX TRUE)
endif()
LIST(APPEND CMAKE_PREFIX_PATH "$ENV{CMAKE_PREFIX_PATH}")
@@ -58,23 +42,30 @@ if(APPLE)
endif()
endif()
include(HPHPCompiler)
include(HPHPFunctions)
include(HPHPFindLibs)
add_definitions(-D_REENTRANT=1 -D_PTHREADS=1 -D__STDC_FORMAT_MACROS -DFOLLY_HAVE_WEAK_SYMBOLS=1)
if (LINUX)
add_definitions(-D_GNU_SOURCE)
endif()
add_definitions(-D_GNU_SOURCE -D_REENTRANT=1 -D_PTHREADS=1)
add_definitions(-DHHVM_LIB_PATH_DEFAULT="${HPHP_HOME}/bin")
if(${CMAKE_BUILD_TYPE} MATCHES "Release")
add_definitions(-DRELEASE=1)
add_definitions(-DNDEBUG)
message("Generating Release build")
else()
add_definitions(-DDEBUG)
message("Generating DEBUG build")
endif()
if(INFINITE_LOOP_DETECTION)
add_definitions(-DINFINITE_LOOP_DETECTION=1)
endif()
if(INFINITE_RECURSION_DETECTION)
add_definitions(-DINFINITE_RECURSION_DETECTION=1)
endif()
if(REQUEST_TIMEOUT_DETECTION)
add_definitions(-DREQUEST_TIMEOUT_DETECTION=1)
endif()
if(ENABLE_LATE_STATIC_BINDING)
add_definitions(-DENABLE_LATE_STATIC_BINDING=1)
endif()
if(DEBUG_MEMORY_LEAK)
@@ -93,6 +84,10 @@ if(HOTPROFILER)
add_definitions(-DHOTPROFILER=1)
endif()
if(HOTPROFILER_NO_BUILTIN)
add_definitions(-DHOTPROFILER_NO_BUILTIN=1)
endif()
if(EXECUTION_PROFILER)
add_definitions(-DEXECUTION_PROFILER=1)
endif()
@@ -105,33 +100,31 @@ if(APPLE OR FREEBSD)
add_definitions(-DSKIP_USER_CHANGE=1)
endif()
if(APPLE)
# We have to be a little more permissive in some cases.
add_definitions(-fpermissive)
# Skip deprecation warnings in OpenSSL.
add_definitions(-DMAC_OS_X_VERSION_MIN_REQUIRED=MAC_OS_X_VERSION_10_6)
# Just assume we have sched.h
add_definitions(-DFOLLY_HAVE_SCHED_H=1)
# Enable weak linking
add_definitions(-DMACOSX_DEPLOYMENT_TARGET=10.6)
endif()
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)
# later versions of binutils don't play well without automake
add_definitions(-DPACKAGE=hhvm -DPACKAGE_VERSION=Release)
execute_process(COMMAND git describe --all --long --abbrev=40 --always
OUTPUT_VARIABLE _COMPILER_ID OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET)
if (_COMPILER_ID)
add_definitions(-DCOMPILER_ID="${_COMPILER_ID}")
endif()
IF($ENV{CXX} MATCHES "icpc")
set(CMAKE_C_FLAGS "-no-ipo -fp-model precise -wd584 -wd1418 -wd1918 -wd383 -wd869 -wd981 -wd424 -wd1419 -wd444 -wd271 -wd2259 -wd1572 -wd1599 -wd82 -wd177 -wd593 -w")
set(CMAKE_CXX_FLAGS "-no-ipo -fp-model precise -wd584 -wd1418 -wd1918 -wd383 -wd869 -wd981 -wd424 -wd1419 -wd444 -wd271 -wd2259 -wd1572 -wd1599 -wd82 -wd177 -wd593 -fno-omit-frame-pointer -ftemplate-depth-120 -Wall -Woverloaded-virtual -Wno-deprecated -w1 -Wno-strict-aliasing -Wno-write-strings -Wno-invalid-offsetof -fno-operator-names")
else()
set(CMAKE_C_FLAGS "-w")
set(CMAKE_CXX_FLAGS "-fno-gcse -fno-omit-frame-pointer -ftemplate-depth-120 -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++0x -Werror=format-security -Wno-unused-result -Wno-sign-compare")
endif()
IF(CMAKE_COMPILER_IS_GNUCC)
SET (CMAKE_C_FLAGS_RELEASE "-O3")
ENDIF()
IF(CMAKE_COMPILER_IS_GNUCXX)
SET (CMAKE_CXX_FLAGS_RELEASE "-O3")
ENDIF()
include_directories(${HPHP_HOME}/hphp)
include_directories(${HPHP_HOME}/hphp/lib/system/gen)
+9 -3
Ver Arquivo
@@ -1,18 +1,24 @@
#set(CMAKE_BUILD_TYPE Debug)
option(ENABLE_LATE_STATIC_BINDING "Enable Late Static Binding" ON)
option(INFINITE_LOOP_DETECTION "Enable Infinite Loop Detection" ON)
option(INFINITE_RECURSION_DETECTION "Enable Infinite Recursion Detection" ON)
option(REQUEST_TIMEOUT_DETECTION "Enable Timeout Detection" ON)
option(ALWAYS_ASSERT "Enabled asserts in a release build" OFF)
option(DEBUG_MEMORY_LEAK "Allow easier debugging of memory leaks" OFF)
option(DEBUG_APC_LEAK "Allow easier debugging of apc leaks" OFF)
option(HOTPROFILER "Enable support for the hot-profiler" OFF)
option(HOTPROFILER_NO_BUILTIN "Don't consider builtins for the hot-profiler" OFF)
option(EXECUTION_PROFILER "Enable the execution profiler" OFF)
option(ENABLE_FULL_SETLINE "Enable full setline function for debugger and code-coverage" OFF)
option(WANT_FB_LIBMCC "want FB Memcache" OFF)
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)
+22 -12
Ver Arquivo
@@ -1,18 +1,18 @@
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.7 FATAL_ERROR)
PROJECT(hphp C CXX ASM)
CMAKE_MINIMUM_REQUIRED(VERSION 2.6.4 FATAL_ERROR)
PROJECT(hphp C CXX)
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("Building for HPHPc")
endif()
-18
Ver Arquivo
@@ -1,18 +0,0 @@
# Contributing to HipHop
We'd love to have your help in making HipHop better. If you run into problems, please open an [issue](http://github.com/facebook/hiphop-php/issues), or better yet, fork us and send a pull request.
If you want to help but don't know where to start, try fixing some of the [Zend tests that don't pass](hphp/test/zend/bad). You can run them with [hphp/test/run](hphp/test/run). When they work, move them to [zend/good](hphp/test/zend/good) and send a pull request.
All the open issues tagged [Zend incompatibility](https://github.com/facebook/hiphop-php/issues?labels=zend+incompatibility&page=1&state=open) are real issues reported by the community in existing PHP code and [frameworks](https://github.com/facebook/hiphop-php/wiki/OSS-PHP-Frameworks-Unit-Testing:-General) that could use some attention.
## Submitting Pull Requests
Before changes can be accepted a [Contributor Licensing Agreement](http://developers.facebook.com/opensource/cla) ([pdf](https://github.com/facebook/hiphop-php/raw/master/hphp/doc/FB_Individual_CLA.pdf) - print, sign, scan, link) must be signed.
Please add appropriate test cases as you make changes; see [here](hphp/test) for more information. Travis-CI is integrated with this GitHub project and will provide test results automatically on all pulls.
## Additional Resources
* IRC:[#hhvm on freenode](http://webchat.freenode.net/?channels=hhvm)
* [Issue tracker](http://github.com/facebook/hiphop-php/issues)
+54 -26
Ver Arquivo
@@ -1,46 +1,74 @@
# HHVM [![Build Status](https://travis-ci.org/facebook/hhvm.png?branch=master)](https://travis-ci.org/facebook/hhvm)
# HipHop for PHP
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.
HipHop is a high performance PHP toolchain. Currently supported platforms are Linux and FreeBSD. There is no OS X support.
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.
* [Developer Mailing List](http://groups.google.com/group/hiphop-php-dev)
* [Wiki](http://wiki.github.com/facebook/hiphop-php)
* [Issue Tracker](http://github.com/facebook/hiphop-php/issues)
## FAQ
## Required Packages
Our [FAQ](https://github.com/facebook/hhvm/wiki/FAQ) has answers to many common questions about HHVM, from [general questions](https://github.com/facebook/hhvm/wiki/FAQ#general) to questions geared towards those that want to [use](https://github.com/facebook/hhvm/wiki/FAQ#users) or [contribute](https://github.com/facebook/hhvm/wiki/FAQ#contributors) to HHVM.
The latest information is available on the [wiki](http://wiki.github.com/facebook/hiphop-php/building-and-installing)
## Installing
* cmake *2.6 is the minimum version*
* g++/gcc *4.3 is the minimum version*
* Boost *1.37 is the minimum version*
* flex
* bison
* re2c
* libmysql
* libxml2
* libmcrypt
* libicu *4.2 is the minimum version*
* openssl
* binutils
* libcap
* gd
* zlib
* tbb *Intel's Thread Building Blocks*
* [Oniguruma](http://www.geocities.jp/kosako3/oniguruma/)
* libpcre
* libexpat
* libmemcached
* google-glog (http://code.google.com/p/google-glog/)
You can install a [prebuilt package](https://github.com/facebook/hhvm/wiki#installing-pre-built-packages-for-hhvm) or [compile from source](https://github.com/facebook/hhvm/wiki#building-hhvm).
The following packages have had slight modifications added to them. Patches are provided and should be made against the current source copies.
## Running
* [libcurl](http://curl.haxx.se/download.html)
* src/third_party/libcurl.fb-changes.diff
* [libevent 1.4](http://www.monkey.org/~provos/libevent/)
* src/third_party/libevent-1.4.13.fb-changes.diff OR src/third_party/libevent-1.4.14.fb-changes.diff
You can run standalone programs just by passing them to hhvm: `hhvm my_script.php`.
## Installation
HHVM bundles in a webserver. So if you want to run on port 80 in the current directory:
You may need to point CMake to the location of your custom libcurl and libevent, or to any other libraries which needed to be installed. The *CMAKE_PREFIX_PATH* variable is used to hint to the location.
```
sudo hhvm -m server
```
export CMAKE_PREFIX_PATH=/home/user
For anything more complicated, you'll want to make a [config.hdf](https://github.com/facebook/hhvm/wiki/Runtime-options#server) and run `sudo hhvm -m server -c config.hdf`.
To build HipHop, use the following:
## Contributing
Linux:
We'd love to have your help in making HHVM better.
cd /home/user/dev
git clone git://github.com/facebook/hiphop-php.git
cd hiphop-php
git submodule init
git submodule update
export HPHP_HOME=`pwd`
export HPHP_LIB=`pwd`/bin
cmake .
Before changes can be accepted a [Contributor License Agreement](http://developers.facebook.com/opensource/cla) ([pdf](https://github.com/facebook/hhvm/raw/master/hphp/doc/FB_Individual_CLA.pdf) - print, sign, scan, link) must be signed.
If you are using FreeBSD instead use export - setenv
If you run into problems, please open an [issue](http://github.com/facebook/hhvm/issues), or better yet, [fork us and send a pull request](https://github.com/facebook/hhvm/pulls). Join us on [#hhvm on freenode](http://webchat.freenode.net/?channels=hhvm).
Once this is done you can generate the build file. This will return you to the shell. Finally, to build, run `make`. If any errors occur, it may be required to remove the CMakeCache.txt directory in the checkout.
If you want to help but don't know where to start, try fixing some of the [Zend tests that don't pass](hphp/test/zend/bad). You can run them with [hphp/test/run](hphp/test/run). When they work, move them to [zend/good](hphp/test/zend/good) and send a pull request.
make
All the open issues tagged [Zend incompatibility](https://github.com/facebook/hhvm/issues?labels=zend+incompatibility&page=1&state=open) are real issues reported by the community in existing PHP code and [frameworks](https://github.com/facebook/hhvm/wiki/OSS-PHP-Frameworks-Unit-Testing:-General) that could use some attention. Please add appropriate test cases as you make changes; see [here](hphp/test) for more information. Travis-CI is integrated with this GitHub project and will provide test results automatically on all pulls.
## Contributing to HipHop
HipHop is licensed under the PHP and Zend licenses except as otherwise noted.
Before changes can be accepted a [Contributors Licensing Agreement](http://developers.facebook.com/opensource/cla) must be signed and returned.
## License
## Running HipHop
HHVM is licensed under the PHP and Zend licenses except as otherwise noted.
## Reporting Crashes
See [Reporting Crashes](https://github.com/facebook/hhvm/wiki/Reporting-Crashes) for helpful tips on how to report crashes in an actionable manner.
Please see [the wiki page](http://wiki.github.com/facebook/hiphop-php/running-hiphop)
+1
Ver Arquivo
@@ -0,0 +1 @@
This file just exists to keep the bin/ directory in git.
+5590
Ver Arquivo
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
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
-126
Ver Arquivo
@@ -1,126 +0,0 @@
#########################################
#
# Install all the dependencies for HipHop
#
#########################################
SCRIPT_NAME='./configure_ubuntu_12.04.sh'
if [ "$0" != "$SCRIPT_NAME" ]; then
echo "Run the script from the hiphop-php directory like:"
echo " $SCRIPT_NAME"
exit 1
fi
if [ "x${TRAVIS}" != "x" ]; then
# Collect some stats for use in tuning build later on
free
CPUS=`cat /proc/cpuinfo | grep -E '^processor' | tail -1 | cut -d : -f 2`
CPUS=`expr ${CPUS} + 1`
echo "CPUs: ${CPUS}"
fi
export CMAKE_PREFIX_PATH=`/bin/pwd`/..
# 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
sudo add-apt-repository -y ppa:apt-fast/stable
sudo apt-get -y update
sudo apt-get -y install apt-fast
# install the actual dependencies
sudo apt-fast -y update
sudo apt-fast -y install git-core cmake g++ libboost1.48-dev libmysqlclient-dev \
libxml2-dev libmcrypt-dev libicu-dev openssl build-essential binutils-dev \
libcap-dev libgd2-xpm-dev zlib1g-dev libtbb-dev libonig-dev libpcre3-dev \
autoconf libtool libcurl4-openssl-dev libboost-regex1.48-dev libboost-system1.48-dev \
libboost-program-options1.48-dev libboost-filesystem1.48-dev libboost-thread1.48-dev \
wget memcached libreadline-dev libncurses-dev libmemcached-dev libbz2-dev \
libc-client2007e-dev php5-mcrypt php5-imagick libgoogle-perftools-dev \
libcloog-ppl0 libelf-dev libdwarf-dev libunwind7-dev subversion &
git clone git://github.com/libevent/libevent.git --quiet &
git clone git://github.com/bagder/curl.git --quiet &
svn checkout http://google-glog.googlecode.com/svn/trunk/ google-glog --quiet &
wget http://www.canonware.com/download/jemalloc/jemalloc-3.0.0.tar.bz2 --quiet &
# init submodules
git submodule update --init
# wait until all background processes finished
FAIL=0
for job in `jobs -p`
do
echo "waiting for background job $job"
wait $job || let "FAIL+=1"
done
if [ "$FAIL" == "0" ];
then
echo "all downloads finished"
else
echo "$FAIL errors while downloading!"
exit 100
fi
# Leave this install till after the main parallel package install above
# since it adds a non-12.04 package repo and we don't want to
# pull EVERYTHING in, just the newer gcc compiler (and toolchain)
GCC_VER=4.7
if [ "x${TRAVIS}" != "x" ]; then
GCC_VER=4.8
fi
sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
sudo apt-get -y update
sudo apt-get -y install gcc-${GCC_VER} g++-${GCC_VER}
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-${GCC_VER} 60 \
--slave /usr/bin/g++ g++ /usr/bin/g++-${GCC_VER}
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.6 40 \
--slave /usr/bin/g++ g++ /usr/bin/g++-4.6
sudo update-alternatives --set gcc /usr/bin/gcc-${GCC_VER}
# libevent
cd libevent
git checkout release-1.4.14b-stable
cat ../hphp/third_party/libevent-1.4.14.fb-changes.diff | patch -p1
./autogen.sh
./configure --prefix=$CMAKE_PREFIX_PATH
make
make install
cd ..
# curl
cd curl
./buildconf
./configure --prefix=$CMAKE_PREFIX_PATH
make
make install
cd ..
# glog
cd google-glog
./configure --prefix=$CMAKE_PREFIX_PATH
make
make install
cd ..
# jemaloc
tar xjvf jemalloc-3.0.0.tar.bz2
cd jemalloc-3.0.0
./configure --prefix=$CMAKE_PREFIX_PATH
make
make install
cd ..
# cleanup
rm -rf libevent curl google-glog jemalloc-3.0.0.tar.bz2 jemalloc-3.0.0
# hphp
cmake .
echo "-------------------------------------------------------------------------"
echo "Done. Now run:"
echo " CMAKE_PREFIX_PATH=\`pwd\`/.. make"
-26
Ver Arquivo
@@ -1,26 +0,0 @@
# HHVM build results
*.hhbc
*.[oa]
/hhvm/hhvm
/hhvm/hphp
# vim swapfiles
.*.swp
.*.swo
# tags files
*/tags
*/TAGS
# logs
*.log
# git patch files
*.diff
# OS X
.DS_Store
._.DS_Store
# gdb
.gdb_history
+159 -21
Ver Arquivo
@@ -16,12 +16,127 @@
#
include(HPHPSetup)
include(FollySetup)
include(ExtZendCompat)
add_definitions("-DHHVM")
if ("$ENV{USE_HHVM}" STREQUAL "1")
# 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)
if ("$ENV{USE_HPHPC}" STREQUAL "1")
message(FATAL_ERROR "Both USE_HHVM and USE_HPHPC are set, you may only select one")
endif()
else()
# HPHPc Build
SET(USE_HHVM FALSE)
ADD_DEFINITIONS("-DHHVM_PATH=\"\"")
if (NOT "$ENV{USE_HPHPC}" STREQUAL "1")
message(FATAL_ERROR "You must select which version of HipHop to build by setting either USE_HHVM=1 or USE_HPHPC=1 in your environment")
endif()
endif()
set(RECURSIVE_SOURCE_SUBDIRS runtime/base runtime/eval runtime/ext runtime/vm system/gen system/lib util)
foreach (dir ${RECURSIVE_SOURCE_SUBDIRS})
auto_sources(files "*.cpp" "RECURSE" "${CMAKE_CURRENT_SOURCE_DIR}/${dir}")
list(APPEND CXX_SOURCES ${files})
auto_sources(files "*.c" "RECURSE" "${CMAKE_CURRENT_SOURCE_DIR}/${dir}")
list(APPEND C_SOURCES ${files})
endforeach(dir ${RECURSIVE_SOURCE_SUBDIRS})
# Disable hardware counters off of Linux
if(NOT LINUX)
add_definitions(-DNO_HARDWARE_COUNTERS)
list(REMOVE_ITEM CXX_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/runtime/base/hardware_counter.cpp)
endif()
# remove ext_hhvm, util/tests, and runtime/vm/translator/test
foreach (file ${CXX_SOURCES})
if (${file} MATCHES "ext_hhvm")
list(REMOVE_ITEM CXX_SOURCES ${file})
endif()
if (${file} MATCHES "util/test")
list(REMOVE_ITEM CXX_SOURCES ${file})
endif()
if (${file} MATCHES "runtime/vm/translator/test")
list(REMOVE_ITEM CXX_SOURCES ${file})
endif()
if (${file} MATCHES "runtime/vm/translator/hopt/test")
list(REMOVE_ITEM CXX_SOURCES ${file})
endif()
endforeach(file ${CXX_SOURCES})
# remove ext/sep for hhvm
if (USE_HHVM)
foreach (file ${CXX_SOURCES})
if (${file} MATCHES "ext/sep")
list(REMOVE_ITEM CXX_SOURCES ${file})
endif()
endforeach(file ${CXX_SOURCES})
endif(USE_HHVM)
if (EXISTS "${hphp_SOURCE_DIR}/HPHP_EXCLUDE_FILES.txt")
FILE(READ ${hphp_SOURCE_DIR}/HPHP_EXCLUDE_FILES.txt HPHP_EXCLUDE_FILES)
STRING(REGEX REPLACE "[\n\r]" ";" HPHP_EXCLUDE_FILES "${HPHP_EXCLUDE_FILES}")
else ()
SET(HPHP_EXCLUDE_FILES)
endif ()
foreach (t ${HPHP_EXCLUDE_FILES})
string(SUBSTRING ${t} 0 1 T_FIRST_CHAR)
if (${T_FIRST_CHAR} STREQUAL "D")
string(REGEX REPLACE "^[D]" "" SKIP_DIR "${t}")
file(TO_CMAKE_PATH "${hphp_SOURCE_DIR}/${SKIP_DIR}" SKIP_DIR)
string(LENGTH "${SKIP_DIR}" SKIP_DIR_LENGTH)
message(STATUS "Let's remove ${SKIP_DIR}")
foreach (file ${CXX_SOURCES})
string(LENGTH "${file}" FILE_LENGTH)
if (${FILE_LENGTH} GREATER ${SKIP_DIR_LENGTH})
string(SUBSTRING ${file} 0 ${SKIP_DIR_LENGTH} FILE_PATH)
if (${FILE_PATH} STREQUAL ${SKIP_DIR})
list(REMOVE_ITEM CXX_SOURCES ${file})
endif ()
endif ()
endforeach(file ${CXX_SOURCES})
elseif (${T_FIRST_CHAR} STREQUAL "#")
# doing nothing since this is a comment
else ()
list(FIND CXX_SOURCES "${hphp_SOURCE_DIR}/${t}" FOUND_T)
if (FOUND_T GREATER -1)
LIST(REMOVE_AT CXX_SOURCES ${FOUND_T})
endif()
endif ()
endforeach(t ${HPHP_EXCLUDE_FILES})
#FLEX_TARGET(HphpScanner ${CMAKE_CURRENT_SOURCE_DIR}/runtime/eval/parser/hphp.x ${CMAKE_CURRENT_SOURCE_DIR}/runtime/eval/parser/lex.eval_.cpp COMPILE_FLAGS " -w -i -Peval_")
#BISON_TARGET(HphpParser ${CMAKE_CURRENT_SOURCE_DIR}/runtime/eval/parser/hphp.y ${CMAKE_CURRENT_SOURCE_DIR}/runtime/eval/parser/hphp.tab.cpp COMPILE_FLAGS " -v -d -p eval_")
#ADD_FLEX_BISON_DEPENDENCY(HphpScanner HphpParser)
# required to remove warning when a file is there twice
#list(REMOVE_ITEM CXX_SOURCES ${FLEX_HphpScanner_OUTPUTS} ${BISON_HphpParser_OUTPUTS})
#list(APPEND CXX_SOURCES ${FLEX_HphpScanner_OUTPUTS} ${BISON_HphpParser_OUTPUTS})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin")
#add_library(sqlite3 STATIC "${CMAKE_CURRENT_SOURCE_DIR}/third_party/libsqlite3/sqlite3.c")
#auto_sources(TIMELIB_SOURCES "*.c" "RECURSE" "${CMAKE_CURRENT_SOURCE_DIR}/third_party/timelib")
#add_library(timelib STATIC ${TIMELIB_SOURCES})
if (NOT SKIP_BUNDLED_XHP)
add_subdirectory(third_party/xhp/xhp)
endif()
add_subdirectory(third_party/libafdt)
add_subdirectory(third_party/libmbfl)
@@ -30,29 +145,52 @@ add_subdirectory(third_party/timelib)
add_subdirectory(third_party/lz4)
add_subdirectory(third_party/double-conversion)
add_subdirectory(third_party/folly)
add_subdirectory(third_party/libzip)
if(ENABLE_FASTCGI)
add_subdirectory(third_party/ti)
add_subdirectory(third_party/thrift)
endif()
add_subdirectory(vixl)
add_subdirectory(neo)
add_subdirectory(parser)
add_subdirectory(zend)
add_subdirectory(util)
foreach (CXX_FILE ${CXX_SOURCES})
if(${CXX_FILE} MATCHES ".no.cpp$")
SET_SOURCE_FILES_PROPERTIES(
${CXX_FILE}
PROPERTIES
COMPILE_FLAGS -O0
)
endif()
endforeach()
add_custom_command(
OUTPUT runtime/base/compiler_id.h
COMMAND hphp/tools/generate_compiler_id.sh
DEPENDS ${CXX_SOURCES} ${C_SOURCES}
WORKING_DIRECTORY ${HPHP_HOME}
COMMENT "Generating Compiler ID"
VERBATIM)
add_custom_command(
OUTPUT runtime/vm/repo_schema.h
COMMAND hphp/tools/generate_repo_schema.sh
DEPENDS ${CXX_SOURCES} ${C_SOURCES}
WORKING_DIRECTORY ${HPHP_HOME}
COMMENT "Generating Repo Schema ID"
VERBATIM)
ADD_LIBRARY(hphp_runtime_static STATIC runtime/vm/repo_schema.h runtime/base/compiler_id.h ${CXX_SOURCES} ${C_SOURCES})
#ADD_LIBRARY(hphp_runtime SHARED ${C_SOURCES} ${CXX_SOURCES})
SET_TARGET_PROPERTIES(hphp_runtime_static PROPERTIES OUTPUT_NAME "hphp_runtime")
SET_TARGET_PROPERTIES(hphp_runtime_static PROPERTIES PREFIX "lib")
#SET_TARGET_PROPERTIES(hphp_runtime PROPERTIES CLEAN_DIRECT_OUTPUT 1)
SET_TARGET_PROPERTIES(hphp_runtime_static PROPERTIES CLEAN_DIRECT_OUTPUT 1)
SET(CMAKE_CXX_ARCHIVE_APPEND "<CMAKE_AR> q <TARGET> <LINK_FLAGS> <OBJECTS>")
hphp_link(hphp_runtime_static)
add_subdirectory(hhbbc)
add_subdirectory(compiler)
add_subdirectory(runtime)
add_subdirectory(runtime/ext_hhvm)
add_subdirectory(system)
if (USE_HHVM)
add_subdirectory(runtime/ext_hhvm)
endif()
add_subdirectory(hhvm)
if (NOT "$ENV{HPHP_NOTEST}" STREQUAL "1")
add_subdirectory(test)
endif ()
# Keep this last
add_subdirectory(tools/hphpize)
-212
Ver Arquivo
@@ -1,212 +0,0 @@
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()
- ASAN clean
- Support dynamically loadable extensions
- Support loading mini-systemlibs from extensions
"Tabasco" 30-Sep-2013
- Fix issues with __toString() functions that return non-string values
- Don't allow mock classes to extend collection classes
- Smarter memory allocation and scheduling for NUMA systems
- Improve profiler performance in the jit
- Fix several Zend compatibility issues
- Fix several bugs uncovered by ASAN
- Add collection support to array_keys, array_values, and array_combine
- Return a set-like array from Set::toArray
- Add to(Vector|Map|StableMap|Set) methods to collections
- Collections convert to boolean false when empty
- get_class_vars invokes the autoloader when necessary
- Rework the Zend compatibility layer to be more robust
- Allow traits to implement interfaces
- Support arbitrary expressions inside empty()
"Bobotie" 16-Sep-2013
- 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.
- Implement str_getcsv, and fix some fgetcsv related issues.
- [IPv6] Fix stream_socket_recvfrom & stream_socket_sendto.
- [IPv6] Fix socket_sentto_recvfrom_ipv6_udp Zend compatibility.
- Optimize closure invocation and __invoke (~3x faster to invoke)
- Import gettext extension
- string and object allocation optimizations (reduced memory usage for both)
- Import YAML extension
- Import ftp extension
"Kimchi" 2-Sep-2013
- 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
- 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
- Fix ArrayIterator constructor PHP compatibility
- Enable building against libmemcached 1.0.8
- Debugger: $_ not cleared but still printed after exception
- Fix clone of SplPriorityQueue
- Debugger: Fix bugs when multiple threads hit the same breakpoint
- Fix several namespace bugs
- Several PHP compatibility fixes for ArrayObject and ArrayIterator
- Fix list assignment with collection literals
- support "tuple(...)" in initializer expressions
- HHVM should compile with libmemcached 1.0.9+
- Support "(new Vector {..})->method()" style syntax
- use trigger_error in PHP for Redis user errors
- multiple simplexml fixes
- fixed serialize/unserialize for SplObjectStorage
- Implement ReflectionParameter::IsCallable()
"Achiote" 19-Aug-2013
- Async stack traces in the debugger via the "wa" command
- Fix late static binding in static closures
- Fix breakpoints on generators
- Add SplObserver and SplSubject interfaces
- Update Iterable interface and add toArray() method
- Allow __get for undefined properties
- Implement get_included_files()
- Limit use of huge pages
"Churrasco" 05-Aug-2013
- Implement stream_is_local
- Implement read support for .phar
- Implement assert with string arguments
- Implement RecursiveArrayIterator
- Implement php_strip_whitespace()
- Support for timeouts in cli mode
- Closure allocation optimizations (~2x faster to allocate a closure)
- Implement Redis session handler
- New memory profiler, hhprof, with pprof compatible output
- Update isset($string[$k]) and empty($string[$k) to PHP 5.5 semantics
- Fixed a few parser bugs
- Fixed a few bugs with token_get_all()
- Fix (string)$obj semantics when __toString() is not defined
"Tamale" 22-Jul-2013
- Optimize vector-shaped Arrays (arrays with keys in range 0..size-1)
- Enable HHBC by default in debug builds
- Implement SplObjectStorage::getInfo()
- Initial rough draft of xhpast2, a replacement for xhpast
- fix compilation on Ubuntu 13.04
- OSX changes, next round
- Modify PHP's ext/standard/math/tests/(pow|abs).phpt to be HHVM friendly
- add XHP comment syntax based on http://www.w3.org/TR/REC-xml/#sec-comments
"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
- Prototype heap tracing framework & Heap profiler
- Better JIT code generation for Mod and Div
- Fixes to enable compilation with clang
- Support for yield k => v
- Make HHVM's command line parsing closer to PHP
- Implement Redis extension
- Implement LimitIterator from SPL
- add SessionHandler from PHP 5.4
- Numerous Debugger fixes and new developer docs for Debugger
- Ported many extension tests to PHP
-1
Ver Arquivo
@@ -49,4 +49,3 @@ add_definitions(-DALWAYS_ASSERT=1)
ADD_LIBRARY(hphp_analysis STATIC ${CXX_SOURCES} ${C_SOURCES})
target_link_libraries(hphp_analysis ${Boost_LIBRARIES})
add_dependencies(hphp_analysis hphp_parser)
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+9 -9
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -14,10 +14,10 @@
+----------------------------------------------------------------------+
*/
#ifndef incl_HPHP_ALIAS_MANAGER_H_
#define incl_HPHP_ALIAS_MANAGER_H_
#ifndef __ALIAS_MANAGER_H__
#define __ALIAS_MANAGER_H__
#include "hphp/compiler/expression/expression.h"
#include <compiler/expression/expression.h>
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
@@ -88,7 +88,7 @@ class AliasManager {
enum { SameAccess, SameLValueAccess, InterfAccess,
DisjointAccess, NotAccess };
explicit AliasManager(int opt);
AliasManager(int opt);
~AliasManager();
void clear();
@@ -141,7 +141,7 @@ class AliasManager {
enum { FallThrough, CondBranch, Branch, Converge };
enum { NoCopyProp = 1, NoDeadStore = 2 };
struct CondStackElem {
explicit CondStackElem(size_t s = 0) : m_size(s), m_exprs() {}
CondStackElem(size_t s = 0) : m_size(s), m_exprs() {}
size_t m_size;
ExpressionPtrList m_exprs;
};
@@ -154,7 +154,7 @@ class AliasManager {
class LoopInfo {
public:
explicit LoopInfo(StatementPtr s);
LoopInfo(StatementPtr s);
StatementPtr m_stmt;
StatementPtrVec m_inner;
@@ -205,7 +205,7 @@ class AliasManager {
StatementPtr canonicalizeRecur(StatementPtr e, int &ret);
void invalidateChainRoots(StatementPtr s);
void nullSafeDisableCSE(StatementPtr parent, ExpressionPtr kid);
void nullSafeDisableCSE(StatementPtr parent, int kid);
void disableCSE(StatementPtr s);
void createCFG(MethodStatementPtr m);
void deleteCFG();
@@ -276,4 +276,4 @@ class AliasManager {
///////////////////////////////////////////////////////////////////////////////
}
#endif // incl_HPHP_ALIAS_MANAGER_H_
#endif // __ALIAS_MANAGER_H__
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+294 -75
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -14,20 +14,19 @@
+----------------------------------------------------------------------+
*/
#ifndef incl_HPHP_ANALYSIS_RESULT_H_
#define incl_HPHP_ANALYSIS_RESULT_H_
#ifndef __ANALYSIS_RESULT_H__
#define __ANALYSIS_RESULT_H__
#include "hphp/compiler/code_generator.h"
#include "hphp/compiler/analysis/code_error.h"
#include "hphp/compiler/option.h"
#include "hphp/compiler/analysis/block_scope.h"
#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 <compiler/code_generator.h>
#include <compiler/analysis/code_error.h>
#include <compiler/option.h>
#include <compiler/analysis/block_scope.h>
#include <compiler/analysis/symbol_table.h>
#include <compiler/analysis/function_container.h>
#include <compiler/package.h>
#include "hphp/util/string-bag.h"
#include "hphp/util/thread-local.h"
#include <util/string_bag.h>
#include <util/thread_local.h>
#include <boost/graph/adjacency_list.hpp>
#include <tbb/concurrent_hash_map.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);
@@ -92,12 +91,12 @@ public:
class Locker {
public:
explicit Locker(const AnalysisResult *ar) :
Locker(const AnalysisResult *ar) :
m_ar(const_cast<AnalysisResult*>(ar)),
m_mutex(m_ar->getMutex()) {
m_mutex.lock();
}
explicit Locker(AnalysisResultConstPtr ar) :
Locker(AnalysisResultConstPtr ar) :
m_ar(const_cast<AnalysisResult*>(ar.get())),
m_mutex(m_ar->getMutex()) {
m_mutex.lock();
@@ -149,10 +148,8 @@ public:
void addEntryPoint(const std::string &name);
void addEntryPoints(const std::vector<std::string> &names);
void addNSFallbackFunc(ConstructPtr c, FileScopePtr fs);
void addSystemFunction(FunctionScopeRawPtr fs);
void addSystemClass(ClassScopeRawPtr cs);
void loadBuiltinFunctions();
void loadBuiltins();
void analyzeProgram(bool system = false);
void analyzeIncludes();
void analyzeProgramFinal();
@@ -169,6 +166,28 @@ public:
void inferTypes();
void postOptimize();
/**
* Scalar array handling.
*/
int registerScalarArray(bool insideScalarArray, FileScopePtr scope,
ExpressionPtr pairs, int &hash, int &index,
std::string &text);
int checkScalarArray(const std::string &text, int &index);
int getScalarArrayId(const std::string &text);
void outputCPPNamedScalarArrays(const std::string &file);
std::string getScalarArrayCompressedText();
std::string getScalarArrayName(int hash, int index);
std::string getScalarVarArrayName(int hash, int index);
int checkScalarVarInteger(int64 val, int &index);
std::string getScalarVarIntegerName(int hash, int index);
void outputCPPNamedScalarVarIntegers(const std::string &file);
int checkScalarVarDouble(double dval, int &index);
std::string getScalarVarDoubleName(int hash, int index);
void outputCPPNamedScalarVarDoubles(const std::string &file);
/**
* Force all class variables to be variants, since l-val or reference
* of dynamic properties are used.
@@ -191,6 +210,30 @@ public:
* Code generation functions.
*/
bool outputAllPHP(CodeGenerator::Output output);
void outputAllCPP(CodeGenerator::Output output, int clusterCount,
const std::string *compileDir);
void outputCPPSystemImplementations(CodeGenerator &cg);
void getCPPFileRunDecls(CodeGenerator &cg, Type2SymbolSetMap &type2names);
void getCPPRedeclaredFunctionDecl(CodeGenerator &cg,
Type2SymbolSetMap &type2names);
void getCPPRedeclaredClassDecl(CodeGenerator &cg,
Type2SymbolSetMap &type2names);
void outputCPPRedeclaredClassImpl(CodeGenerator &cg);
void getCPPDynamicConstantDecl(CodeGenerator &cg,
Type2SymbolSetMap &type2names);
void outputCPPDynamicConstantImpl(CodeGenerator &cg);
void outputCPPScalarArrayDecl(CodeGenerator &cg);
void outputCPPScalarArrayImpl(CodeGenerator &cg);
void outputCPPScalarArrayInit(CodeGenerator &cg, int fileCount, int part);
void outputCPPScalarArrayId(CodeGenerator &cg, int id, int hash, int index,
bool scalarVariant = false);
void getCPPClassStaticInitializerFlags(CodeGenerator &cg,
Type2SymbolSetMap &type2names);
void getCPPClassDeclaredFlags(CodeGenerator &cg,
Type2SymbolSetMap &type2names);
void outputCPPFiniteDouble(CodeGenerator &cg, double dval);
/**
* Parser creates a FileScope upon parsing a new file.
@@ -239,22 +282,12 @@ public:
ClassScopePtr findClass(const std::string &className) const;
ClassScopePtr findClass(const std::string &className,
FindClassBy by);
/*
* Returns: whether the given name is the name of any type aliases
* in the whole program.
*/
bool isTypeAliasName(const std::string& name) const {
return m_typeAliasNames.count(name);
}
/**
* Find all the redeclared classes by the name, excluding system classes.
* Note that system classes cannot be redeclared.
*/
const ClassScopePtrVec &findRedeclaredClasses(
const std::string &className) const;
/**
* Find all the classes by the name, including system classes.
*/
@@ -285,36 +318,72 @@ public:
return m_outputPath;
}
/**
* PHP source info functions.
*/
void recordSourceInfo(const std::string &file, int line, LocationPtr loc);
void recordClassSource(const std::string &clsname, LocationPtr loc,
const std::string &filename);
void recordFunctionSource(const std::string &funcname, LocationPtr loc,
const std::string &filename);
/**
* Literal string to String precomputation
*/
std::string getLiteralStringName(int64_t hash, int index, bool iproxy = false);
std::string getLitVarStringName(int64_t hash, int index, bool iproxy = false);
std::string getLiteralStringName(int64 hash, int index, bool iproxy = false);
std::string getLitVarStringName(int64 hash, int index, bool iproxy = false);
int getLiteralStringId(const std::string &s, int &index);
/**
* Profiling runtime parameter type
*/
std::string getFuncId(ClassScopePtr cls, FunctionScopePtr func);
std::string getParamRTTIEntryKey(ClassScopePtr cls,
FunctionScopePtr func,
const std::string &paramName);
void addParamRTTIEntry(ClassScopePtr cls,
FunctionScopePtr func,
const std::string &paramName);
int getParamRTTIEntryId(ClassScopePtr cls,
FunctionScopePtr func,
const std::string &paramName);
void addRTTIFunction(const std::string &id);
void cloneRTTIFuncs(const char *RTTIDirectory);
std::vector<const char *> &getFuncTableBucket(FunctionScopePtr func);
/**
* Generate default implementation for separable extension classes.
*/
void outputCPPSepExtensionImpl(const std::string &filename);
void outputCPPClusterImpl(CodeGenerator &cg, const FileScopePtrVec &files);
void outputCPPFileImpl(CodeGenerator &cg, FileScopePtr fs);
void addPregeneratedCPP(const std::string &name, std::string &code);
const std::string &getPregeneratedCPP(const std::string &name);
std::set<std::string> m_variableTableFunctions;
std::set<int> m_concatLengths;
int m_arrayLitstrKeyMaxSize;
int m_arrayIntegerKeyMaxSize;
std::string getHashedName(int64_t hash, int index, const char *prefix,
void setSystem() { m_system = true; }
bool isSystem() const { return m_system; }
void setSepExtension() { m_sepExtension = true; }
bool isSepExtension() { return m_sepExtension; }
std::string getHashedName(int64 hash, int index, const char *prefix,
bool longName = false);
void addNamedLiteralVarString(const std::string &s);
void addNamedScalarVarArray(const std::string &s);
StringToClassScopePtrVecMap getExtensionClasses();
void addInteger(int64_t n);
void addInteger(int64 n);
private:
Package *m_package;
bool m_parseOnDemand;
std::vector<std::string> m_parseOnDemandDirs;
std::set<std::pair<ConstructPtr, FileScopePtr> > m_nsFallbackFuncs;
Phase m_phase;
StringToFileScopePtrMap m_files;
FileScopePtrVec m_fileScopes;
@@ -330,31 +399,76 @@ private:
StringToFileScopePtrMap m_constDecs;
std::set<std::string> m_constRedeclared;
// Map names of class aliases to the class names they will alias.
// Only in WholeProgram mode. See markRedeclaringClasses.
std::multimap<std::string,std::string> m_classAliases;
// Names of type aliases.
std::set<std::string> m_typeAliasNames;
bool m_classForcedVariants[2];
StatementPtrVec m_stmts;
StatementPtr m_stmt;
std::string m_outputPath;
std::map<std::string, int> m_scalarArrays;
Mutex m_namedScalarArraysMutex;
std::map<int, std::vector<std::string> > m_namedScalarArrays;
std::set<std::string> m_namedScalarVarArrays;
int m_scalarArraysCounter;
std::vector<ExpressionPtr> m_scalarArrayIds;
Mutex m_namedScalarVarIntegersMutex;
std::map<int, std::vector<std::string> > m_namedScalarVarIntegers;
Mutex m_allIntegersMutex;
std::set<int64> m_allIntegers;
Mutex m_namedScalarVarDoublesMutex;
std::map<int, std::vector<std::string> > m_namedScalarVarDoubles;
std::map<std::string, int> m_paramRTTIs;
std::set<std::string> m_rttiFuncs;
int m_paramRTTICounter;
public:
struct ScalarArrayExp {
int id;
int len;
ExpressionPtr exp;
};
void outputCPPDynamicTables(CodeGenerator::Output output);
void outputCPPClassMapFile(CodeGenerator::Output output);
void outputCPPSourceInfos();
void outputCPPNameMaps();
void outputRTTIMetaData(const char *filename);
void outputCPPClassMap(CodeGenerator &cg, CodeGenerator::Output);
void outputCPPSystem();
void outputCPPSepExtensionMake();
void outputFFI(std::vector<std::string> &additionalCPPs);
void repartitionLargeCPP(const std::vector<std::string> &filenames,
const std::vector<std::string> &additionals);
void outputCPPUtilDecl(CodeGenerator::Output output);
void outputCPPUtilImpl(CodeGenerator::Output output);
void outputCPPGlobalDeclarations();
void outputCPPMain();
void outputCPPScalarArrays(bool system);
void outputCPPGlobalVariablesMethods();
void outputCPPGlobalState();
AnalysisResultPtr shared_from_this() {
return static_pointer_cast<AnalysisResult>
return boost::static_pointer_cast<AnalysisResult>
(BlockScope::shared_from_this());
}
AnalysisResultConstPtr shared_from_this() const {
return static_pointer_cast<const AnalysisResult>
return boost::static_pointer_cast<const AnalysisResult>
(BlockScope::shared_from_this());
}
private:
int m_scalarArraySortedAvgLen;
int m_scalarArraySortedIndex;
int m_scalarArraySortedSumLen;
std::vector<ScalarArrayExp> m_scalarArraySorted;
int m_scalarArrayCompressedTextSize;
bool m_pregenerating, m_pregenerated;
BlockScopePtrVec m_ignoredScopes;
typedef boost::adjacency_list<boost::setS, boost::vecS> Graph;
@@ -364,17 +478,39 @@ private:
Graph m_depGraph;
typedef std::map<vertex_descriptor, FileScopePtr> VertexToFileScopePtrMap;
VertexToFileScopePtrMap m_fileVertMap;
void getTrueDeps(FileScopePtr f,
std::map<std::string, FileScopePtr> &trueDeps);
void clusterByFileSizes(StringToFileScopePtrVecMap &clusters,
int clusterCount);
void renameStaticNames(std::map<int, std::vector<std::string> > &names,
const char *file, const char *prefix);
typedef std::map<std::string, std::string> StringMap;
Mutex m_pregenMapMutex;
StringMap m_pregenMap;
typedef std::map<int, LocationPtr> SourceLocationMap;
typedef std::map<std::string, SourceLocationMap> SourceInfo;
Mutex m_sourceInfoMutex;
SourceInfo m_sourceInfos;
SourceInfo m_sourceInfoPregen;
std::map<std::string, std::set<std::pair<std::string, int> > > m_clsNameMap;
std::map<std::string, std::set<std::pair<std::string, int> > > m_funcNameMap;
Mutex m_namedStringLiteralsMutex;
std::map<int, std::vector<std::string> > m_namedStringLiterals;
std::set<std::string> m_namedVarStringLiterals;
int m_funcTableSize;
CodeGenerator::MapIntToStringVec m_funcTable;
bool m_system;
bool m_sepExtension;
/**
* Checks whether the file is in one of the on-demand parsing directories.
*/
bool inParseOnDemandDirs(const std::string &filename) const;
/*
* Find the names of all functions and classes in the program; mark
* functions with duplicate names as redeclaring, but duplicate
* classes aren't yet marked. See markRedeclaringClasses.
*/
void collectFunctionsAndClasses(FileScopePtr fs);
/**
@@ -383,35 +519,118 @@ private:
*/
void canonicalizeSymbolOrder();
/*
* After all the class names have been collected and symbol order is
* canonicalized, this passes through and marks duplicate class
* names as redeclaring.
*/
void markRedeclaringClasses();
/**
* Checks circular class derivations that can cause stack overflows for
* subsequent analysis. Also checks to make sure no two redundant parents.
*/
void checkClassDerivations();
void resolveNSFallbackFuncs();
/**
* Creates the global function table. Needs to be called before generating
* cpp code for each toplevel function.
*/
void createGlobalFuncTable();
void outputCPPScalarArrays(CodeGenerator &cg, int fileCount, int part);
void collectCPPGlobalSymbols(StringPairSetVec &symbols,
CodeGenerator &cg);
void outputCPPGlobalStateFileHeader(CodeGenerator &cg);
void outputCPPGlobalStateBegin(CodeGenerator &cg, const char *section);
void outputCPPGlobalStateEnd(CodeGenerator &cg, const char *section);
void outputCPPGlobalStateSection(CodeGenerator &cg,
const StringPairSet &names,
const char *section,
const char *prefix = "g->",
const char *name_prefix = "");
void outputCPPClassIncludes(CodeGenerator &cg);
void outputCPPExtClassImpl(CodeGenerator &cg);
void outputCPPDynamicTablesHeader(CodeGenerator &cg,
bool includeGlobalVars = true,
bool includes = true,
bool noNamespace = false);
void outputCPPGlobalImplementations(CodeGenerator &cg);
void preGenerateCPP(CodeGenerator::Output output,
const FileScopePtrVec &files, int threadCount);
void movePregeneratedSourceInfo(const std::string &source,
const std::string &target, int offset);
int getFileSize(FileScopePtr fs);
void repartitionCPP(const std::string &filename, int64 targetSize,
bool insideHPHP, bool force);
void outputCPPFFIStubs();
void outputHSFFIStubs();
/**
* Outputs Java stubs.
*
* Each PHP file becomes a Java package, in which the HphpMain class
* contains all the toplevel function definitions, and the rest of the
* classes are one-to-one corresponding to the php classes declared in
* that file.
*/
void outputJavaFFIStubs();
/**
* Outputs one .h file that declares all the Java native method stubs,
* avoiding javah for performance reason.
*/
void outputJavaFFICppDecl();
/**
* Outputs one .cpp file that implements all the native methods declared
* in the Java classes generated by outputJavaFFIStubs().
*/
void outputJavaFFICppImpl();
void outputSwigFFIStubs();
void outputHexBuffer(CodeGenerator &cg, const char *name,
const char *buf, int len);
void outputCPPNamedLiteralStrings(bool genStatic, const std::string &file);
void outputCPPSepExtensionIncludes(CodeGenerator &cg);
void outputCPPInvokeFileHeader(CodeGenerator &cg);
void outputCPPEvalHook(CodeGenerator &cg);
void outputCPPDefaultInvokeFile(CodeGenerator &cg, const char *file);
void outputArrayCreateDecl(CodeGenerator &cg);
void outputArrayCreateImpl(CodeGenerator &cg);
void outputCPPHashTableInvokeFile(CodeGenerator &cg,
const std::vector<const char*> &entries,
bool needEvalHook);
void outputCPPDynamicClassTables(CodeGenerator::Output output);
void outputCPPDynamicConstantTable(CodeGenerator::Output output);
void outputCPPHashTableGetConstant(CodeGenerator &cg, bool system,
const std::map<std::string, TypePtr> &constMap,
const hphp_string_map<bool> &dyns);
void cloneRTTIFuncs(const StringToFunctionScopePtrMap &functions,
const StringToFunctionScopePtrVecMap *redecFunctions);
void outputInitLiteralVarStrings(CodeGenerator &cg, int fileIndex,
std::vector<int> &litVarStrFileIndices,
std::vector<std::pair<int, int> > &litVarStrs);
void outputInitLiteralVarStrings();
void outputStringProxyData(CodeGenerator &cg,
int fileIndex, std::vector<std::string> &lStrings,
std::vector<std::pair<std::string, int> > &bStrings);
void outputVarStringProxyData(CodeGenerator &cg,
int fileIndex, std::vector<std::pair<int, int> > &litVarStrs);
public:
static DECLARE_THREAD_LOCAL(BlockScopeRawPtr, s_currentScopeThreadLocal);
static DECLARE_THREAD_LOCAL(BlockScopeRawPtrFlagsHashMap,
s_changedScopesMapThreadLocal);
#ifdef HPHP_INSTRUMENT_PROCESS_PARALLEL
static std::atomic<int> s_NumDoJobCalls;
static int s_NumDoJobCalls;
static ConcurrentBlockScopeRawPtrIntHashMap s_DoJobUniqueScopes;
static std::atomic<int> s_NumForceRerunGlobal;
static std::atomic<int> s_NumReactivateGlobal;
static std::atomic<int> s_NumForceRerunUseKinds;
static std::atomic<int> s_NumReactivateUseKinds;
static int s_NumForceRerunGlobal;
static int s_NumReactivateGlobal;
static int s_NumForceRerunUseKinds;
static int s_NumReactivateUseKinds;
#endif /* HPHP_INSTRUMENT_PROCESS_PARALLEL */
private:
@@ -435,13 +654,13 @@ private:
class RescheduleException : public Exception {
public:
explicit RescheduleException(BlockScopeRawPtr scope) :
Exception(), m_scope(scope) {}
RescheduleException(BlockScopeRawPtr scope) :
Exception(false), m_scope(scope) {}
BlockScopeRawPtr &getScope() { return m_scope; }
#ifdef HPHP_INSTRUMENT_TYPE_INF
static std::atomic<int> s_NumReschedules;
static std::atomic<int> s_NumForceRerunSelfCaller;
static std::atomic<int> s_NumRetTypesChanged;
static int s_NumReschedules;
static int s_NumForceRerunSelfCaller;
static int s_NumRetTypesChanged;
#endif /* HPHP_INSTRUMENT_TYPE_INF */
private:
BlockScopeRawPtr m_scope;
@@ -449,7 +668,7 @@ private:
class SetCurrentScope {
public:
explicit SetCurrentScope(BlockScopeRawPtr scope) {
SetCurrentScope(BlockScopeRawPtr scope) {
assert(!((*AnalysisResult::s_currentScopeThreadLocal).get()));
*AnalysisResult::s_currentScopeThreadLocal = scope;
scope->setInVisitScopes(true);
@@ -535,9 +754,9 @@ private:
}
}
#else
explicit BaseTryLock(BlockScopeRawPtr scopeToLock,
bool lockCondition = true,
bool profile = true)
BaseTryLock(BlockScopeRawPtr scopeToLock,
bool lockCondition = true,
bool profile = true)
: m_profiler(profile),
m_mutex(scopeToLock->getInferTypesMutex()),
m_acquired(false) {
@@ -572,8 +791,8 @@ public:
bool profile = true) :
BaseTryLock(scopeToLock, fromFunction, fromLine, true, profile) {}
#else
explicit TryLock(BlockScopeRawPtr scopeToLock,
bool profile = true) :
TryLock(BlockScopeRawPtr scopeToLock,
bool profile = true) :
BaseTryLock(scopeToLock, true, profile) {}
#endif /* HPHP_INSTRUMENT_TYPE_INF */
};
@@ -631,4 +850,4 @@ public:
///////////////////////////////////////////////////////////////////////////////
}
#endif // incl_HPHP_ANALYSIS_RESULT_H_
#endif // __ANALYSIS_RESULT_H__
+6 -6
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -14,8 +14,8 @@
+----------------------------------------------------------------------+
*/
#include "hphp/compiler/analysis/ast_walker.h"
#include "hphp/compiler/statement/statement.h"
#include <compiler/analysis/ast_walker.h>
#include <compiler/statement/statement.h>
using namespace HPHP;
@@ -23,17 +23,17 @@ using namespace HPHP;
bool FunctionWalker::SkipRecurse(ConstructPtr cp) {
StatementPtr s(
dynamic_pointer_cast<Statement>(cp));
boost::dynamic_pointer_cast<Statement>(cp));
return SkipRecurse(s);
}
bool FunctionWalker::SkipRecurse(ConstructConstPtr cp) {
StatementConstPtr s(
dynamic_pointer_cast<const Statement>(cp));
boost::dynamic_pointer_cast<const Statement>(cp));
return SkipRecurse(s);
}
bool FunctionWalker::SkipRecurse(ConstructRawPtr cp) {
StatementRawPtr s(
dynamic_pointer_cast<Statement>(cp));
boost::dynamic_pointer_cast<Statement>(cp));
return SkipRecurse(s);
}
+8 -8
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -14,11 +14,11 @@
+----------------------------------------------------------------------+
*/
#ifndef incl_HPHP_AST_WALKER_H_
#define incl_HPHP_AST_WALKER_H_
#ifndef __AST_WALKER_H__
#define __AST_WALKER_H__
#include "hphp/compiler/hphp.h"
#include "hphp/compiler/construct.h"
#include <compiler/hphp.h>
#include <compiler/construct.h>
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
@@ -26,7 +26,7 @@ namespace HPHP {
class AstWalkerState {
public:
AstWalkerState() : index(0) {}
explicit AstWalkerState(ConstructRawPtr c) : cp(c), index(0) {}
AstWalkerState(ConstructRawPtr c) : cp(c), index(0) {}
friend bool operator==(const AstWalkerState &s1,
const AstWalkerState &s2) {
@@ -40,7 +40,7 @@ public:
class AstWalkerStateVec : public std::vector<AstWalkerState> {
public:
AstWalkerStateVec() {}
explicit AstWalkerStateVec(ConstructRawPtr cp) {
AstWalkerStateVec(ConstructRawPtr cp) {
push_back(AstWalkerState(cp));
}
};
@@ -132,4 +132,4 @@ public:
///////////////////////////////////////////////////////////////////////////////
}
#endif // incl_HPHP_AST_WALKER_H_
#endif // __AST_WALKER_H__
+3 -3
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -15,8 +15,8 @@
*/
#include <stdlib.h>
#include "hphp/compiler/analysis/bit_set_vec.h"
#include "hphp/compiler/analysis/data_flow.h"
#include <compiler/analysis/bit_set_vec.h>
#include <compiler/analysis/data_flow.h>
using namespace HPHP;
+2 -2
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -19,7 +19,7 @@
#include <limits.h>
#include <stddef.h>
#include "hphp/util/assertions.h"
#include "util/assertions.h"
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
+22 -32
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -14,17 +14,16 @@
+----------------------------------------------------------------------+
*/
#include <compiler/expression/expression.h>
#include "hphp/compiler/analysis/block_scope.h"
#include "hphp/compiler/analysis/analysis_result.h"
#include "hphp/compiler/expression/expression.h"
#include "hphp/compiler/statement/statement_list.h"
#include "hphp/compiler/analysis/variable_table.h"
#include "hphp/compiler/analysis/constant_table.h"
#include "hphp/compiler/analysis/class_scope.h"
#include "hphp/compiler/analysis/function_scope.h"
#include "hphp/compiler/analysis/file_scope.h"
#include <compiler/analysis/block_scope.h>
#include <compiler/analysis/analysis_result.h>
#include <compiler/statement/statement_list.h>
#include <compiler/analysis/variable_table.h>
#include <compiler/analysis/constant_table.h>
#include <compiler/analysis/class_scope.h>
#include <compiler/analysis/function_scope.h>
#include <compiler/analysis/file_scope.h>
using namespace HPHP;
@@ -90,29 +89,13 @@ AnalysisResultRawPtr BlockScope::getContainingProgram() {
return AnalysisResultRawPtr((AnalysisResult*)bs);
}
FunctionScopeRawPtr BlockScope::getContainingNonClosureFunction() {
BlockScope *bs = this;
// walk out through all the closures
while (bs && bs->is(BlockScope::FunctionScope)) {
HPHP::FunctionScope *fs = static_cast<HPHP::FunctionScope*>(bs);
if (!fs->isClosure()) {
return FunctionScopeRawPtr(fs);
}
bs = bs->m_outerScope.get();
}
return FunctionScopeRawPtr();
}
ClassScopeRawPtr BlockScope::getContainingClass() {
BlockScope *bs = getContainingNonClosureFunction().get();
if (!bs) {
bs = this;
}
if (bs && bs->is(BlockScope::FunctionScope)) {
BlockScope *bs = this;
if (bs->is(BlockScope::FunctionScope)) {
bs = bs->m_outerScope.get();
}
if (!bs || !bs->is(BlockScope::ClassScope)) {
return ClassScopeRawPtr();
if (bs && !bs->is(BlockScope::ClassScope)) {
bs = 0;
}
return ClassScopeRawPtr((HPHP::ClassScope*)bs);
}
@@ -155,7 +138,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;
@@ -240,6 +225,11 @@ void BlockScope::outputPHP(CodeGenerator &cg, AnalysisResultPtr ar) {
m_variables->outputPHP(cg, ar);
}
void BlockScope::outputCPP(CodeGenerator &cg, AnalysisResultPtr ar) {
m_constants->outputCPP(cg, ar);
m_variables->outputCPP(cg, ar);
}
int BlockScope::ScopeCompare::cmp(const BlockScopeRawPtr &p1,
const BlockScopeRawPtr &p2) const {
int d1 = p1->m_kind - p2->m_kind;
+11 -10
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -14,14 +14,14 @@
+----------------------------------------------------------------------+
*/
#ifndef incl_HPHP_BLOCK_SCOPE_H_
#define incl_HPHP_BLOCK_SCOPE_H_
#ifndef __BLOCK_SCOPE_H__
#define __BLOCK_SCOPE_H__
#include "hphp/compiler/hphp.h"
#include <compiler/hphp.h>
#include "hphp/util/bits.h"
#include "hphp/util/lock.h"
#include "hphp/runtime/base/macros.h"
#include <util/bits.h>
#include <util/lock.h>
#include <runtime/base/macros.h>
#include <tbb/concurrent_hash_map.h>
@@ -66,7 +66,7 @@ typedef SimpleMutex InferTypesMutex;
* Base class of ClassScope and FunctionScope.
*/
class BlockScope : private boost::noncopyable,
public std::enable_shared_from_this<BlockScope> {
public boost::enable_shared_from_this<BlockScope> {
public:
enum KindOf {
ClassScope,
@@ -178,7 +178,6 @@ public:
VariableTablePtr getVariables() { return m_variables;}
ConstantTablePtr getConstants() { return m_constants;}
ClassScopeRawPtr getContainingClass();
FunctionScopeRawPtr getContainingNonClosureFunction();
FunctionScopeRawPtr getContainingFunction() const {
return FunctionScopeRawPtr(is(FunctionScope) ?
(HPHP::FunctionScope*)this : 0);
@@ -219,7 +218,9 @@ public:
/**
* Code gen
*/
virtual void outputCPPDef(CodeGenerator &cg) {}
virtual void outputPHP(CodeGenerator &cg, AnalysisResultPtr ar);
virtual void outputCPP(CodeGenerator &cg, AnalysisResultPtr ar);
virtual bool inPseudoMain() const {
return false;
@@ -366,4 +367,4 @@ public:
///////////////////////////////////////////////////////////////////////////////
}
#endif // incl_HPHP_BLOCK_SCOPE_H_
#endif // __BLOCK_SCOPE_H__
-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_
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+226 -48
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -14,20 +14,19 @@
+----------------------------------------------------------------------+
*/
#ifndef incl_HPHP_CLASS_SCOPE_H_
#define incl_HPHP_CLASS_SCOPE_H_
#ifndef __CLASS_SCOPE_H__
#define __CLASS_SCOPE_H__
#include "hphp/compiler/analysis/block_scope.h"
#include "hphp/compiler/analysis/function_container.h"
#include "hphp/compiler/statement/class_statement.h"
#include "hphp/compiler/statement/method_statement.h"
#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/compiler/option.h"
#include <compiler/analysis/block_scope.h>
#include <compiler/analysis/function_container.h>
#include <compiler/statement/class_statement.h>
#include <compiler/statement/method_statement.h>
#include <compiler/statement/trait_prec_statement.h>
#include <compiler/statement/trait_alias_statement.h>
#include <compiler/expression/user_attribute.h>
#include <util/json.h>
#include <util/case_insensitive.h>
#include <compiler/option.h>
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
@@ -125,6 +124,7 @@ public:
void checkDerivation(AnalysisResultPtr ar, hphp_string_iset &seen);
const std::string &getOriginalParent() const { return m_parent; }
std::string getHeaderFilename();
/**
* Returns topmost parent class that has the method.
@@ -170,11 +170,14 @@ public:
return m_derivedByDynamic;
}
/* Whether this class is brought in by a separable extension */
void setSepExtension() { m_sep = true;}
bool isSepExtension() const { return m_sep;}
/**
* 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 {
@@ -209,7 +212,7 @@ public:
bool forInvoke = false);
/**
* Whether or not we can directly call ObjectData::o_invoke() when lookup
* Whether or not we can directly call c_ObjectData::o_invoke() when lookup
* in this class fails. If false, we need to call parent::o_invoke(), which
* may be redeclared or may have private methods that need to check class
* context.
@@ -289,6 +292,62 @@ public:
ClassScopePtr getParentScope(AnalysisResultConstPtr ar) const;
void addUsedLiteralStringHeader(const std::string &s) {
m_usedLiteralStringsHeader.insert(s);
}
void addUsedLitVarStringHeader(const std::string &s) {
m_usedLitVarStringsHeader.insert(s);
}
void addUsedScalarVarInteger(int64 i) {
m_usedScalarVarIntegers.insert(i);
}
std::set<int64> &getUsedScalarVarIntegers() {
return m_usedScalarVarIntegers;
}
void addUsedScalarVarIntegerHeader(int64 i) {
m_usedScalarVarIntegersHeader.insert(i);
}
void addUsedScalarVarDouble(double d) {
m_usedScalarVarDoubles.insert(d);
}
std::set<double> &getUsedScalarVarDoubles() {
return m_usedScalarVarDoubles;
}
void addUsedScalarVarDoubleHeader(double d) {
m_usedScalarVarDoublesHeader.insert(d);
}
void addUsedDefaultValueScalarArray(const std::string &s) {
m_usedDefaultValueScalarArrays.insert(s);
}
void addUsedDefaultValueScalarVarArray(const std::string &s) {
m_usedDefaultValueScalarVarArrays.insert(s);
}
void addUsedConstHeader(const std::string &s) {
m_usedConstsHeader.insert(s);
}
void addUsedClassConstHeader(ClassScopeRawPtr cls, const std::string &s) {
m_usedClassConstsHeader.insert(CodeGenerator::UsedClassConst(cls, s));
}
void addUsedClassHeader(ClassScopeRawPtr s) {
m_usedClassesHeader.insert(s);
}
void addUsedClassFullHeader(ClassScopeRawPtr s) {
m_usedClassesFullHeader.insert(s);
}
void addUsedTrait(const std::string &s) {
if (!usesTrait(s)) {
m_usedTraitNames.push_back(s);
@@ -303,37 +362,55 @@ 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);
/**
* Output class meta info for g_class_map.
*/
void outputCPPClassMap(CodeGenerator &cg, AnalysisResultPtr ar);
/**
* Serialize the iface, not everything.
*/
void serialize(JSON::CodeError::OutputStream &out) const;
void serialize(JSON::DocTarget::OutputStream &out) const;
static void outputCPPHashTableClasses
(CodeGenerator &cg, const StringToClassScopePtrVecMap &classScopes,
const std::vector<const char*> &classes);
static void outputCPPClassVarInitImpl(
CodeGenerator &cg, const StringToClassScopePtrVecMap &classScopes,
const std::vector<const char *> &classes);
void outputCPPDynamicClassDecl(CodeGenerator &cg);
void outputCPPDynamicClassImpl(CodeGenerator &cg, AnalysisResultPtr ar);
static void outputCPPDynamicClassCreateDecl(CodeGenerator &cg);
static void outputCPPDynamicClassCreateImpl
(CodeGenerator &cg, const StringToClassScopePtrVecMap &classScopes,
const std::vector<const char*> &classes);
static void outputCPPGetCallInfoStaticMethodImpl
(CodeGenerator &cg, const StringToClassScopePtrVecMap &classScopes,
const std::vector<const char*> &classes);
static void outputCPPGetStaticPropertyImpl
(CodeGenerator &cg, const StringToClassScopePtrVecMap &classScopes,
const std::vector<const char*> &classes);
static void outputCPPGetClassConstantImpl
(CodeGenerator &cg, const StringToClassScopePtrVecMap &classScopes);
static void outputCPPGetClassPropTableImpl
(CodeGenerator &cg, AnalysisResultPtr ar,
const StringToClassScopePtrVecMap &classScopes,
bool extension = false);
bool isInterface() const { return m_kindOf == KindOfInterface; }
bool isFinal() const { return m_kindOf == KindOfFinalClass ||
m_kindOf == KindOfTrait; }
@@ -342,6 +419,32 @@ public:
bool isTrait() const { return m_kindOf == KindOfTrait; }
bool hasProperty(const std::string &name) const;
bool hasConst(const std::string &name) const;
void outputCPPDef(CodeGenerator &cg);
void outputCPPHeader(AnalysisResultPtr ar,
CodeGenerator::Output output);
void outputCPPForwardHeader(CodeGenerator &cg,AnalysisResultPtr ar);
void outputCPPJumpTableDecl(CodeGenerator &cg, AnalysisResultPtr ar);
void outputMethodWrappers(CodeGenerator &cg, AnalysisResultPtr ar);
/**
* This prints out all the support methods (invoke, create, destructor,
* etc.)
* This is here instead of ClassStatement because I want to be able to call
* these for extension classes that don't have a statement.
*/
void outputCPPSupportMethodsImpl(CodeGenerator &cg, AnalysisResultPtr ar);
std::string getClassPropTableId(AnalysisResultPtr ar);
/**
* These output wrappers for class methods so that class definitions don't
* have to be used in generating global jump tables.
*/
void outputCPPGlobalTableWrappersDecl(CodeGenerator &cg,
AnalysisResultPtr ar);
void outputCPPGlobalTableWrappersImpl(CodeGenerator &cg,
AnalysisResultPtr ar);
static bool NeedStaticArray(ClassScopePtr cls, FunctionScopePtr func);
void inheritedMagicMethods(ClassScopePtr super);
@@ -358,12 +461,40 @@ public:
m_parent = "";
}
void outputCPPStaticMethodWrappers(CodeGenerator &cg, AnalysisResultPtr ar,
std::set<std::string> &done,
const char *cls);
/**
* Override function container
*/
bool addFunction(AnalysisResultConstPtr ar,
FunctionScopePtr funcScope);
void outputVolatileCheckBegin(CodeGenerator &cg,
AnalysisResultPtr ar,
BlockScopePtr bs,
const std::string &name);
void outputVolatileCheckEnd(CodeGenerator &cg);
static void OutputVolatileCheckBegin(CodeGenerator &cg,
AnalysisResultPtr ar,
BlockScopePtr bs,
const std::string &origName);
static void OutputVolatileCheckEnd(CodeGenerator &cg);
static void OutputVolatileCheck(CodeGenerator &cg, AnalysisResultPtr ar,
BlockScopePtr bs,
const std::string &origName, bool noThrow);
/**
* Whether or not the specified jump table is empty.
*/
bool hasAllJumpTables() const {
return m_emptyJumpTables.empty();
}
bool hasJumpTable(JumpTableName name) const {
return m_emptyJumpTables.find(name) == m_emptyJumpTables.end();
}
void setNeedsCppCtor(bool needsCppCtor) {
m_needsCppCtor = needsCppCtor;
}
@@ -380,19 +511,33 @@ public:
return m_needsInit;
}
bool needsEnableDestructor(AnalysisResultConstPtr ar) const;
bool canSkipCreateMethod(AnalysisResultConstPtr ar) const;
bool checkHasPropTable(AnalysisResultConstPtr ar);
const StringData* getFatalMessage() const {
return m_fatal_error_msg;
}
struct IndexedSym {
IndexedSym(int i, int p, const Symbol *s) :
origIndex(i), privIndex(p), sym(s) {}
void setFatal(const AnalysisTimeFatalException& fatal) {
assert(m_fatal_error_msg == nullptr);
m_fatal_error_msg = makeStaticString(fatal.getMessage());
assert(m_fatal_error_msg != nullptr);
}
int origIndex;
int privIndex;
const Symbol *sym;
};
struct ClassPropTableInfo {
ClassScopeRawPtr cls;
std::vector<int> actualIndex[3];
std::vector<int> privateIndex[3];
std::map<int, std::vector<IndexedSym> > syms[3];
};
typedef std::map<std::string, ClassPropTableInfo>
ClassPropTableMap;
protected:
void findJumpTableMethods(CodeGenerator &cg, AnalysisResultPtr ar,
std::vector<const char *> &funcs);
bool hasJumpTableMethods(CodeGenerator &cg, AnalysisResultPtr ar);
private:
// need to maintain declaration order for ClassInfo map
FunctionScopePtrVec m_functionsVec;
@@ -401,9 +546,20 @@ private:
mutable std::vector<std::string> m_bases;
UserAttributeMap m_userAttributes;
std::set<JumpTableName> m_emptyJumpTables;
std::set<std::string> m_usedLiteralStringsHeader;
std::set<std::string> m_usedLitVarStringsHeader;
std::set<int64> m_usedScalarVarIntegers;
std::set<int64> m_usedScalarVarIntegersHeader;
std::set<double> m_usedScalarVarDoubles;
std::set<double> m_usedScalarVarDoublesHeader;
std::set<std::string> m_usedDefaultValueScalarArrays;
std::set<std::string> m_usedDefaultValueScalarVarArrays;
std::set<std::string> m_usedConstsHeader;
CodeGenerator::UsedClassConstSet m_usedClassConstsHeader;
CodeGenerator::ClassScopeSet m_usedClassesHeader;
CodeGenerator::ClassScopeSet m_usedClassesFullHeader;
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;
@@ -429,6 +585,7 @@ private:
typedef std::list<TraitMethod> TraitMethodList;
typedef std::map<std::string, TraitMethodList> MethodToTraitListMap;
typedef std::map<std::string, std::string> GeneratorRenameMap;
MethodToTraitListMap m_importMethToTraitMap;
typedef std::map<std::string, MethodStatementPtr> ImportedMethodMap;
@@ -445,6 +602,7 @@ private:
unsigned m_volatile:1; // for class_exists
unsigned m_persistent:1;
unsigned m_derivedByDynamic:1;
unsigned m_sep:1;
unsigned m_needsCppCtor:1;
unsigned m_needsInit:1;
// m_knownBases has a bit for each base class saying whether
@@ -452,15 +610,10 @@ private:
// for classes with more than 31 bases, bit 31 is set iff
// 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;
mutable unsigned m_needsEnableDestructor:2;
void addImportTraitMethod(const TraitMethod &traitMethod,
const std::string &methName);
void informClosuresAboutScopeClone(ConstructPtr root,
FunctionScopePtr outerScope,
AnalysisResultPtr ar);
void setImportTraitMethodModifiers(const std::string &methName,
ClassScopePtr traitCls,
@@ -469,14 +622,16 @@ private:
MethodStatementPtr importTraitMethod(const TraitMethod& traitMethod,
AnalysisResultPtr ar,
std::string methName,
GeneratorRenameMap& genRenameMap,
const ImportedMethodMap &
importedTraitMethods);
void importTraitProperties(AnalysisResultPtr ar);
void findTraitMethodsToImport(AnalysisResultPtr ar, ClassScopePtr trait);
void relinkGeneratorMethods(AnalysisResultPtr ar,
ImportedMethodMap& importedMethods);
void importTraitRequirements(AnalysisResultPtr ar, ClassScopePtr trait);
void findTraitMethodsToImport(AnalysisResultPtr ar, ClassScopePtr trait);
MethodStatementPtr findTraitMethod(AnalysisResultPtr ar,
ClassScopePtr trait,
@@ -498,8 +653,31 @@ private:
bool hasMethod(const std::string &methodName) const;
const std::string& getNewGeneratorName(FunctionScopePtr genFuncScope,
GeneratorRenameMap& genRenameMap);
void renameCreateContinuationCalls(AnalysisResultPtr ar, ConstructPtr c,
ImportedMethodMap &importedMethods);
std::string getBaseHeaderFilename();
void outputCPPMethodInvokeBareObjectSupport(
CodeGenerator &cg, AnalysisResultPtr ar,
FunctionScopePtr func, bool fewArgs);
void outputCPPMethodInvokeTable
(CodeGenerator &cg, AnalysisResultPtr ar,
const std::vector <const char*> &keys,
const StringToFunctionScopePtrMap &funcScopes, bool fewArgs,
bool staticOnly);
void outputCPPMethodInvokeTableSupport(CodeGenerator &cg,
AnalysisResultPtr ar, const std::vector<const char*> &keys,
const StringToFunctionScopePtrMap &funcScopes, bool fewArgs);
hphp_const_char_imap<int> m_implemented;
ClassScopePtr getNextParentWithProp(AnalysisResultPtr ar);
};
///////////////////////////////////////////////////////////////////////////////
}
#endif // incl_HPHP_CLASS_SCOPE_H_
#endif // __CLASS_SCOPE_H__
+9 -9
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -14,13 +14,13 @@
+----------------------------------------------------------------------+
*/
#include "hphp/compiler/analysis/code_error.h"
#include "hphp/compiler/analysis/file_scope.h"
#include "hphp/compiler/parser/parser.h"
#include "hphp/compiler/construct.h"
#include "hphp/compiler/option.h"
#include "hphp/util/exception.h"
#include "hphp/util/lock.h"
#include <compiler/analysis/code_error.h>
#include <compiler/analysis/file_scope.h>
#include <compiler/parser/parser.h>
#include <compiler/construct.h>
#include <compiler/option.h>
#include <util/exception.h>
#include <util/lock.h>
using namespace HPHP::JSON;
@@ -79,7 +79,7 @@ std::vector<const char *> &CodeErrors::getErrorTexts() {
if (ErrorTexts.empty()) {
ErrorTexts.resize(ErrorCount);
#define CODE_ERROR_ENTRY(x) ErrorTexts[x] = #x;
#include "hphp/compiler/analysis/core_code_error.inc"
#include "compiler/analysis/core_code_error.inc"
#undef CODE_ERROR_ENTRY
}
return ErrorTexts;
+7 -7
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -14,11 +14,11 @@
+----------------------------------------------------------------------+
*/
#ifndef incl_HPHP_COMPILER_ERROR_H_
#define incl_HPHP_COMPILER_ERROR_H_
#ifndef __COMPILER_ERROR_H__
#define __COMPILER_ERROR_H__
#include "hphp/compiler/analysis/type.h"
#include "hphp/compiler/json.h"
#include <compiler/analysis/type.h>
#include <util/json.h>
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
@@ -31,7 +31,7 @@ namespace Compiler {
enum ErrorType {
#define CODE_ERROR_ENTRY(x) x,
#include "hphp/compiler/analysis/core_code_error.inc"
#include "compiler/analysis/core_code_error.inc"
#undef CODE_ERROR_ENTRY
ErrorCount,
NoError
@@ -79,4 +79,4 @@ bool HasError(); // any error
///////////////////////////////////////////////////////////////////////////////
}}
#endif // incl_HPHP_COMPILER_ERROR_H_
#endif // __COMPILER_ERROR_H__
+195 -13
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -14,18 +14,18 @@
+----------------------------------------------------------------------+
*/
#include "hphp/compiler/analysis/constant_table.h"
#include "hphp/compiler/analysis/analysis_result.h"
#include "hphp/compiler/analysis/code_error.h"
#include "hphp/compiler/analysis/type.h"
#include "hphp/compiler/code_generator.h"
#include "hphp/compiler/expression/expression.h"
#include "hphp/compiler/expression/scalar_expression.h"
#include "hphp/compiler/option.h"
#include "hphp/util/util.h"
#include "hphp/util/hash.h"
#include "hphp/compiler/analysis/class_scope.h"
#include "hphp/runtime/base/complex-types.h"
#include <compiler/analysis/constant_table.h>
#include <compiler/analysis/analysis_result.h>
#include <compiler/analysis/code_error.h>
#include <compiler/analysis/type.h>
#include <compiler/code_generator.h>
#include <compiler/expression/expression.h>
#include <compiler/expression/scalar_expression.h>
#include <compiler/option.h>
#include <util/util.h>
#include <util/hash.h>
#include <compiler/analysis/class_scope.h>
#include <runtime/base/complex_types.h>
using namespace HPHP;
@@ -251,3 +251,185 @@ void ConstantTable::outputPHP(CodeGenerator &cg, AnalysisResultPtr ar) {
}
}
}
void ConstantTable::getCPPDynamicDecl(CodeGenerator &cg,
AnalysisResultPtr ar,
Type2SymbolSetMap &type2names) {
const char *prefix = Option::ConstantPrefix;
string classId;
const char *fmt = "";
ClassScopePtr scope = getClassScope();
if (scope) {
prefix = Option::ClassConstantPrefix;
classId = scope->getId();
fmt = Option::IdPrefix.c_str();
}
bool system = cg.getOutput() == CodeGenerator::SystemCPP;
SymbolSet &symbols = type2names["Variant"];
BOOST_FOREACH(Symbol *sym, m_symbolVec) {
if (sym->declarationSet() && sym->isDynamic() &&
system == sym->isSystem()) {
string tmp = string(prefix) + classId + fmt +
CodeGenerator::FormatLabel(sym->getName());
if (Type::IsMappedToVariant(sym->getFinalType())) {
symbols.insert(tmp);
} else {
type2names[sym->getFinalType()->getCPPDecl(ar, BlockScopeRawPtr())].
insert(tmp);
}
}
}
}
void ConstantTable::outputCPPDynamicImpl(CodeGenerator &cg,
AnalysisResultPtr ar) {
BOOST_FOREACH(Symbol *sym, m_symbolVec) {
if (sym->declarationSet() && sym->isDynamic()) {
cg_printf("%s%s = \"%s\";\n", Option::ConstantPrefix,
CodeGenerator::FormatLabel(sym->getName()).c_str(),
CodeGenerator::EscapeLabel(sym->getName()).c_str());
}
}
}
void ConstantTable::collectCPPGlobalSymbols(StringPairSet &symbols,
CodeGenerator &cg,
AnalysisResultPtr ar) {
BOOST_FOREACH(Symbol *sym, m_symbolVec) {
if (sym->declarationSet() && sym->isDynamic()) {
string varname = Option::ConstantPrefix +
CodeGenerator::FormatLabel(sym->getName());
symbols.insert(StringPair(varname, varname));
}
}
}
void ConstantTable::outputCPP(CodeGenerator &cg, AnalysisResultPtr ar,
bool newline /* = true */) const {
bool printed = false;
BOOST_FOREACH(Symbol *sym, m_symbolVec) {
if (outputCPP(cg, ar, sym)) printed = true;
}
if (newline && printed) {
cg_printf("\n");
}
}
bool ConstantTable::outputCPP(CodeGenerator &cg, AnalysisResultPtr ar,
const Symbol *sym) const {
bool decl = true;
if (cg.getContext() == CodeGenerator::CppConstantsDecl) {
decl = false;
}
if (!const_cast<Symbol*>(sym)->checkDefined() ||
sym->isDynamic()) {
return false;
}
if (sym->isSystem() && cg.getOutput() != CodeGenerator::SystemCPP) {
return false;
}
const string &name = sym->getName();
ConstructPtr value = sym->getValue();
cg_printf(decl ? "extern const " : "const ");
TypePtr type = sym->getFinalType();
bool isString = type->is(Type::KindOfString);
if (isString) {
cg_printf("StaticString");
} else {
type->outputCPPDecl(cg, ar, getBlockScope());
}
ClassScope *cls = dynamic_cast<ClassScope*>(&m_blockScope);
if (decl) {
if (!cls) {
cg_printf(" %s%s", Option::ConstantPrefix,
CodeGenerator::FormatLabel(name).c_str());
} else {
cg_printf(" %s%s%s%s", Option::ClassConstantPrefix,
cls->getId().c_str(),
Option::IdPrefix.c_str(),
CodeGenerator::FormatLabel(name).c_str());
}
} else {
if (!cls) {
cg_printf(" %s%s", Option::ConstantPrefix,
CodeGenerator::FormatLabel(name).c_str());
} else {
cg_printf(" %s%s%s%s", Option::ClassConstantPrefix,
cls->getId().c_str(),
Option::IdPrefix.c_str(),
CodeGenerator::FormatLabel(name).c_str());
}
cg_printf(isString ? "(" : " = ");
if (value) {
ExpressionPtr exp = dynamic_pointer_cast<Expression>(value);
if (isString && exp->isScalar()) {
ScalarExpressionPtr scalarExp =
dynamic_pointer_cast<ScalarExpression>(exp);
if (scalarExp) {
cg_printf("LITSTR_INIT(%s)",
scalarExp->getCPPLiteralString().c_str());
} else {
Variant v;
exp->getScalarValue(v);
cg_printf("LITSTR_INIT(\"%s\")",
CodeGenerator::EscapeLabel(v.toString().data()).c_str());
}
} else {
exp->outputCPP(cg, ar);
}
} else {
cg_printf("\"%s\"", CodeGenerator::EscapeLabel(name).c_str());
}
if (isString) {
cg_printf(")");
}
}
cg_printf(";\n");
return true;
}
bool ConstantTable::outputSingleConstant(CodeGenerator &cg,
AnalysisResultPtr ar,
const std::string &name) const {
const Symbol *sym = getSymbol(name);
return sym && outputCPP(cg, ar, sym);
}
void ConstantTable::outputCPPConstantSymbol(CodeGenerator &cg,
AnalysisResultPtr ar,
Symbol *sym) {
ClassScopeRawPtr cls = getClassScope();
if (sym->valueSet() &&
(cls || (!sym->isDynamic() &&
!ar->isConstantRedeclared(sym->getName())))) {
ExpressionPtr value = dynamic_pointer_cast<Expression>(sym->getValue());
Variant v;
if (value && value->getScalarValue(v)) {
int len;
string output = getEscapedText(v, len);
cg_printf("\"%s\", (const char *)%d, \"%s\",\n",
CodeGenerator::EscapeLabel(sym->getName()).c_str(),
len, output.c_str());
} else if (cls) {
cg_printf("\"%s\", (const char *)&%s%s, NULL,\n",
CodeGenerator::EscapeLabel(sym->getName()).c_str(),
Option::ClassStaticsCallbackPrefix, cls->getId().c_str());
} else {
cg_printf("\"%s\", (const char *)0, NULL,\n",
CodeGenerator::EscapeLabel(sym->getName()).c_str());
}
}
}
void ConstantTable::outputCPPClassMap(CodeGenerator &cg,
AnalysisResultPtr ar,
bool last /* = true */) {
for (unsigned int i = 0; i < m_symbolVec.size(); i++) {
outputCPPConstantSymbol(cg, ar, m_symbolVec[i]);
}
if (last) cg_printf("NULL,\n");
}
+27 -7
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -14,11 +14,11 @@
+----------------------------------------------------------------------+
*/
#ifndef incl_HPHP_CONSTANT_TABLE_H_
#define incl_HPHP_CONSTANT_TABLE_H_
#ifndef __CONSTANT_TABLE_H__
#define __CONSTANT_TABLE_H__
#include "hphp/compiler/analysis/symbol_table.h"
#include "hphp/compiler/analysis/block_scope.h"
#include <compiler/analysis/symbol_table.h>
#include <compiler/analysis/block_scope.h>
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
@@ -37,7 +37,7 @@ DECLARE_BOOST_TYPES(ClassScope);
*/
class ConstantTable : public SymbolTable {
public:
explicit ConstantTable(BlockScope &blockScope);
ConstantTable(BlockScope &blockScope);
/**
* Whether defining something to be non-scalar value or redeclared, or
@@ -81,6 +81,22 @@ public:
* Generate all constant declarations for this symbol table.
*/
void outputPHP(CodeGenerator &cg, AnalysisResultPtr ar);
void outputCPP(CodeGenerator &cg, AnalysisResultPtr ar,
bool newline = true) const;
void getCPPDynamicDecl(CodeGenerator &cg, AnalysisResultPtr ar,
Type2SymbolSetMap &type2names);
void outputCPPDynamicImpl(CodeGenerator &cg, AnalysisResultPtr ar);
bool outputSingleConstant(CodeGenerator &cg, AnalysisResultPtr ar,
const std::string &name) const;
void collectCPPGlobalSymbols(StringPairSet &symbols, CodeGenerator &cg,
AnalysisResultPtr ar);
/**
* Generate all class constants in class info map.
*/
void outputCPPClassMap(CodeGenerator &cg, AnalysisResultPtr ar,
bool last = true);
bool isRecursivelyDeclared(AnalysisResultConstPtr ar,
const std::string &name) const;
@@ -99,8 +115,12 @@ private:
ClassScopeRawPtr findBase(AnalysisResultConstPtr ar,
const std::string &name,
const std::vector<std::string> &bases) const;
bool outputCPP(CodeGenerator &cg, AnalysisResultPtr ar,
const Symbol *sym) const;
void outputCPPConstantSymbol(CodeGenerator &cg, AnalysisResultPtr ar,
Symbol *sym);
};
///////////////////////////////////////////////////////////////////////////////
}
#endif // incl_HPHP_CONSTANT_TABLE_H_
#endif // __CONSTANT_TABLE_H__
+92 -108
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -13,32 +13,32 @@
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#include "hphp/compiler/analysis/control_flow.h"
#include "compiler/analysis/ast_walker.h"
#include "compiler/analysis/control_flow.h"
#include "compiler/analysis/data_flow.h"
#include "compiler/expression/expression.h"
#include "compiler/expression/binary_op_expression.h"
#include "compiler/expression/unary_op_expression.h"
#include "compiler/expression/qop_expression.h"
#include "compiler/statement/statement.h"
#include "compiler/statement/method_statement.h"
#include "compiler/statement/statement_list.h"
#include "compiler/statement/if_branch_statement.h"
#include "compiler/statement/for_statement.h"
#include "compiler/statement/while_statement.h"
#include "compiler/statement/do_statement.h"
#include "compiler/statement/foreach_statement.h"
#include "compiler/statement/switch_statement.h"
#include "compiler/statement/break_statement.h"
#include "compiler/statement/try_statement.h"
#include "compiler/statement/finally_statement.h"
#include "compiler/statement/label_statement.h"
#include "compiler/statement/goto_statement.h"
#include "compiler/statement/case_statement.h"
#include <boost/graph/depth_first_search.hpp>
#include "hphp/compiler/analysis/ast_walker.h"
#include "hphp/compiler/analysis/data_flow.h"
#include "hphp/compiler/expression/expression.h"
#include "hphp/compiler/expression/binary_op_expression.h"
#include "hphp/compiler/expression/unary_op_expression.h"
#include "hphp/compiler/expression/qop_expression.h"
#include "hphp/compiler/statement/statement.h"
#include "hphp/compiler/statement/method_statement.h"
#include "hphp/compiler/statement/statement_list.h"
#include "hphp/compiler/statement/if_branch_statement.h"
#include "hphp/compiler/statement/for_statement.h"
#include "hphp/compiler/statement/while_statement.h"
#include "hphp/compiler/statement/do_statement.h"
#include "hphp/compiler/statement/foreach_statement.h"
#include "hphp/compiler/statement/switch_statement.h"
#include "hphp/compiler/statement/break_statement.h"
#include "hphp/compiler/statement/try_statement.h"
#include "hphp/compiler/statement/finally_statement.h"
#include "hphp/compiler/statement/label_statement.h"
#include "hphp/compiler/statement/goto_statement.h"
#include "hphp/compiler/statement/case_statement.h"
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
@@ -64,8 +64,8 @@ typedef hphp_hash_map<ConstructRawPtr, ControlBlock*,
class ControlFlowBuilder : public FunctionWalker {
public:
explicit ControlFlowBuilder(ControlFlowGraph *g) :
m_graph(g), m_pass(0), m_cur(0), m_head(0) {}
ControlFlowBuilder(ControlFlowGraph *g, bool isGenerator) :
m_graph(g), m_pass(0), m_isGenerator(isGenerator), m_cur(0), m_head(0) {}
int before(ConstructRawPtr cp);
int after(ConstructRawPtr cp);
@@ -161,6 +161,7 @@ private:
ControlFlowGraph *m_graph;
AstWalkerStateVec m_state;
int m_pass;
bool m_isGenerator;
ControlBlock *m_cur;
ControlBlock *m_head;
@@ -181,7 +182,7 @@ public:
class dfs_dump : public boost::default_dfs_visitor {
public:
explicit dfs_dump(AnalysisResultConstPtr ar) : m_ar(ar) {}
dfs_dump(AnalysisResultConstPtr ar) : m_ar(ar) {}
void discover_vertex(ControlFlowGraph::vertex_descriptor u,
const ControlFlowGraph &g) {
@@ -245,7 +246,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();
@@ -329,10 +329,9 @@ int ControlFlowBuilder::before(ConstructRawPtr cp) {
}
case Statement::KindOfForStatement: {
ForStatementPtr fs(static_pointer_cast<ForStatement>(s));
ConstructRawPtr body(fs->getBody());
ConstructRawPtr cond(fs->getCondExp());
ConstructRawPtr incr(fs->getIncExp());
ConstructRawPtr cond(s->getNthKid(ForStatement::CondExpr));
ConstructRawPtr body(s->getNthKid(ForStatement::BodyStmt));
ConstructRawPtr incr(s->getNthKid(ForStatement::IncExpr));
if (cond) addEdge(cond, AfterConstruct, s, AfterConstruct);
ConstructRawPtr end = incr ? incr : body ? body : cond;
ConstructRawPtr start = cond ? cond : body ? body : incr;
@@ -342,9 +341,8 @@ int ControlFlowBuilder::before(ConstructRawPtr cp) {
}
case Statement::KindOfWhileStatement: {
WhileStatementPtr ws(static_pointer_cast<WhileStatement>(s));
ConstructRawPtr body(ws->getBody());
ConstructRawPtr cond(ws->getCondExp());
ConstructRawPtr cond(s->getNthKid(WhileStatement::CondExpr));
ConstructRawPtr body(s->getNthKid(WhileStatement::BodyStmt));
addEdge(cond, AfterConstruct, s, AfterConstruct);
addEdge(body ? body : cond, AfterConstruct, cond, BeforeConstruct);
noFallThrough(s);
@@ -352,16 +350,15 @@ int ControlFlowBuilder::before(ConstructRawPtr cp) {
}
case Statement::KindOfDoStatement: {
DoStatementPtr ds(static_pointer_cast<DoStatement>(s));
addEdge(ds->getCondExp(), AfterConstruct, s, BeforeConstruct);
ConstructRawPtr cond(s->getNthKid(DoStatement::CondExpr));
addEdge(cond, AfterConstruct, s, BeforeConstruct);
break;
}
case Statement::KindOfForEachStatement: {
ForEachStatementPtr fs(static_pointer_cast<ForEachStatement>(s));
ConstructRawPtr body(fs->getBody());
ConstructRawPtr name(fs->getNameExp());
ConstructRawPtr value(fs->getValueExp());
ConstructRawPtr body(s->getNthKid(ForEachStatement::BodyStmt));
ConstructRawPtr name(s->getNthKid(ForEachStatement::NameExpr));
ConstructRawPtr value(s->getNthKid(ForEachStatement::ValueExpr));
ConstructRawPtr begin = name ? name : value;
ConstructRawPtr end = body ? body : value;
addEdge(end, AfterConstruct, begin, BeforeConstruct);
@@ -417,7 +414,7 @@ int ControlFlowBuilder::before(ConstructRawPtr cp) {
case Statement::KindOfReturnStatement: {
setEdge(s, AfterConstruct, root(), AfterConstruct);
noFallThrough(s);
if (!m_isGenerator) noFallThrough(s);
/*
* Since almost anything in php /might/ throw, we
* approximate, and add edges from the beginning and
@@ -453,31 +450,23 @@ int ControlFlowBuilder::before(ConstructRawPtr cp) {
} else {
ConstructRawPtr kid;
switch (l->getKindOf()) {
case Statement::KindOfForEachStatement: {
ForEachStatementPtr fs(static_pointer_cast<ForEachStatement>(l));
kid = fs->getNameExp();
case Statement::KindOfForEachStatement:
kid = l->getNthKid(ForEachStatement::NameExpr);
if (!kid) {
kid = fs->getValueExp();
kid = l->getNthKid(ForEachStatement::ValueExpr);
}
break;
}
case Statement::KindOfForStatement: {
ForStatementPtr fs(static_pointer_cast<ForStatement>(l));
kid = fs->getIncExp();
if (!kid) kid = fs->getCondExp();
if (!kid) kid = fs->getBody();
case Statement::KindOfForStatement:
kid = l->getNthKid(ForStatement::IncExpr);
if (!kid) kid = l->getNthKid(ForStatement::CondExpr);
if (!kid) kid = l->getNthKid(ForStatement::BodyStmt);
break;
}
case Statement::KindOfWhileStatement: {
WhileStatementPtr ws(static_pointer_cast<WhileStatement>(l));
kid = ws->getCondExp();
case Statement::KindOfWhileStatement:
kid = l->getNthKid(WhileStatement::CondExpr);
break;
}
case Statement::KindOfDoStatement: {
DoStatementPtr ds(static_pointer_cast<DoStatement>(l));
kid = ds->getCondExp();
case Statement::KindOfDoStatement:
kid = l->getNthKid(DoStatement::CondExpr);
break;
}
default:
always_assert(0);
}
@@ -498,7 +487,6 @@ int ControlFlowBuilder::before(ConstructRawPtr cp) {
}
case Statement::KindOfEchoStatement:
case Statement::KindOfTypedefStatement:
break;
default:
@@ -507,36 +495,36 @@ int ControlFlowBuilder::before(ConstructRawPtr cp) {
} else {
ExpressionPtr e(dynamic_pointer_cast<Expression>(cp));
switch (e->getKindOf()) {
case Expression::KindOfBinaryOpExpression: {
BinaryOpExpressionPtr b(static_pointer_cast<BinaryOpExpression>(e));
if (b->isShortCircuitOperator()) {
ConstructPtr trueBranch, falseBranch;
ConstructLocation tLoc, fLoc;
getTrueFalseBranches(0, trueBranch, tLoc, falseBranch, fLoc);
assert(trueBranch);
assert(falseBranch);
if (b->isLogicalOrOperator()) {
addEdge(b->getExp1(), AfterConstruct, trueBranch, tLoc);
} else {
addEdge(b->getExp1(), AfterConstruct, falseBranch, fLoc);
case Expression::KindOfBinaryOpExpression:
{
BinaryOpExpressionPtr b(
static_pointer_cast<BinaryOpExpression>(e));
if (b->isShortCircuitOperator()) {
ConstructPtr trueBranch, falseBranch;
ConstructLocation tLoc, fLoc;
getTrueFalseBranches(0, trueBranch, tLoc, falseBranch, fLoc);
assert(trueBranch);
assert(falseBranch);
if (b->isLogicalOrOperator()) {
addEdge(e->getNthExpr(0), AfterConstruct, trueBranch, tLoc);
} else {
addEdge(e->getNthExpr(0), AfterConstruct, falseBranch, fLoc);
}
}
}
break;
}
case Expression::KindOfQOpExpression: {
QOpExpressionPtr q(static_pointer_cast<QOpExpression>(e));
if (ExpressionPtr e1 = q->getYes()) {
addEdge(q->getCondition(), AfterConstruct,
q->getNo(), BeforeConstruct);
case Expression::KindOfQOpExpression:
if (ExpressionPtr e1 = e->getNthExpr(1)) {
addEdge(e->getNthExpr(0), AfterConstruct,
e->getNthExpr(2), BeforeConstruct);
addEdge(e1, AfterConstruct,
q->getNo(), AfterConstruct);
e->getNthExpr(2), AfterConstruct);
noFallThrough(e1);
} else {
addEdge(q->getCondition(), AfterConstruct,
q->getNo(), AfterConstruct);
addEdge(e->getNthExpr(0), AfterConstruct,
e->getNthExpr(2), AfterConstruct);
}
break;
}
default:
break;
}
@@ -598,36 +586,32 @@ void ControlFlowBuilder::getTrueFalseBranches(
ConstructPtr c(top(level));
if (StatementPtr s = dynamic_pointer_cast<Statement>(c)) {
StatementPtr kidBody;
int kidBodyIdx = -1;
switch (s->getKindOf()) {
case Statement::KindOfForStatement: {
case Statement::KindOfForStatement:
// examine which context we're in
ForStatementPtr fs(static_pointer_cast<ForStatement>(s));
ConstructPtr kid(top(level - 1));
if (kid == fs->getInitExp()) {
; // just do the default case
} else if (kid == fs->getCondExp()) {
kidBody = fs->getBody();
goto loop_stmt;
} else if (kid == fs->getIncExp()) {
; // just do the default case
} else {
assert(false);
{
ConstructPtr kid(top(level - 1));
if (kid == s->getNthKid(ForStatement::InitExpr)) {
; // just do the default case
} else if (kid == s->getNthKid(ForStatement::CondExpr)) {
kidBodyIdx = ForStatement::BodyStmt;
goto loop_stmt;
} else if (kid == s->getNthKid(ForStatement::IncExpr)) {
; // just do the default case
} else {
assert(false);
}
}
break;
}
case Statement::KindOfWhileStatement: {
WhileStatementPtr ws(static_pointer_cast<WhileStatement>(s));
kidBody = ws->getBody();
case Statement::KindOfWhileStatement:
kidBodyIdx = WhileStatement::BodyStmt;
goto loop_stmt;
}
case Statement::KindOfDoStatement: {
DoStatementPtr ds(static_pointer_cast<DoStatement>(s));
kidBody = ds->getBody();
}
case Statement::KindOfDoStatement:
kidBodyIdx = DoStatement::BodyStmt;
loop_stmt:
if (!trueBranch) {
trueBranch = kidBody;
trueBranch = s->getNthKid(kidBodyIdx);
tLoc = BeforeConstruct;
}
if (!falseBranch) {
@@ -868,7 +852,7 @@ ControlFlowGraph *ControlFlowGraph::buildControlFlow(MethodStatementPtr m) {
ControlFlowGraph *graph = new ControlFlowGraph;
graph->m_stmt = m;
ControlFlowBuilder cfb(graph);
ControlFlowBuilder cfb(graph, m->getOrigGeneratorFunc());
cfb.run(m->getStmts());
graph->m_nextDfn = 1;
depth_first_visit(*graph, cfb.head(),
+8 -13
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -14,17 +14,17 @@
+----------------------------------------------------------------------+
*/
#ifndef incl_HPHP_CONTROL_FLOW_H_
#define incl_HPHP_CONTROL_FLOW_H_
#ifndef __CONTROL_FLOW_H__
#define __CONTROL_FLOW_H__
#include <boost/graph/properties.hpp>
#include <boost/graph/adjacency_iterator.hpp>
#include <boost/graph/adjacency_list.hpp>
#include "hphp/compiler/hphp.h"
#include <compiler/hphp.h>
#include "hphp/compiler/analysis/ast_walker.h"
#include "hphp/compiler/analysis/bit_set_vec.h"
#include <compiler/analysis/ast_walker.h>
#include <compiler/analysis/bit_set_vec.h>
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
@@ -65,8 +65,6 @@ struct graph_traits<HPHP::ControlFlowGraph> {
typedef int vertices_size_type;
typedef int edges_size_type;
typedef std::list<HPHP::ControlEdge*>::size_type degree_size_type;
static vertex_descriptor null_vertex() { return nullptr; }
};
template<>
@@ -311,10 +309,7 @@ inline void put(boost::vertex_color_t c,
class ControlFlowGraphWalker : public FunctionWalker {
public:
explicit ControlFlowGraphWalker(ControlFlowGraph *g)
: m_block(0)
, m_graph(*g)
{}
ControlFlowGraphWalker(ControlFlowGraph *g) : m_block(0), m_graph(*g) {}
template <class T>
void walk(T &t) {
std::pair<ControlFlowGraph::vertex_iterator,
@@ -338,4 +333,4 @@ protected:
///////////////////////////////////////////////////////////////////////////////
}
#endif // incl_HPHP_CONTROL_FLOW_H_
#endif // __CONTROL_FLOW_H__
+1 -2
Ver Arquivo
@@ -37,11 +37,10 @@ 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)
CODE_ERROR_ENTRY(InvalidInstantiation)
CODE_ERROR_ENTRY(InvalidYield)
CODE_ERROR_ENTRY(InvalidAwait)
CODE_ERROR_ENTRY(BadDefaultValueType)
CODE_ERROR_ENTRY(InvalidMethodDefinition)
+15 -16
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -14,12 +14,12 @@
+----------------------------------------------------------------------+
*/
#include "hphp/compiler/analysis/data_flow.h"
#include "compiler/analysis/data_flow.h"
#include "hphp/compiler/expression/expression.h"
#include "hphp/compiler/expression/simple_variable.h"
#include "hphp/compiler/expression/binary_op_expression.h"
#include "hphp/compiler/expression/list_assignment.h"
#include "compiler/expression/expression.h"
#include "compiler/expression/simple_variable.h"
#include "compiler/expression/binary_op_expression.h"
#include "compiler/expression/list_assignment.h"
using namespace HPHP;
using std::pair;
@@ -221,16 +221,16 @@ void DataFlow::ComputePartialDying(const ControlFlowGraph &g) {
// DataFlowWalker
int DataFlowWalker::after(ConstructRawPtr cp) {
if (ExpressionRawPtr e = dynamic_pointer_cast<Expression>(cp)) {
if (ExpressionRawPtr e = boost::dynamic_pointer_cast<Expression>(cp)) {
switch (e->getKindOf()) {
case Expression::KindOfSimpleVariable:
if (!static_pointer_cast<SimpleVariable>(
if (!boost::static_pointer_cast<SimpleVariable>(
e)->getAlwaysStash()) {
return WalkContinue;
}
break;
case Expression::KindOfBinaryOpExpression:
if (static_pointer_cast<BinaryOpExpression>(
if (boost::static_pointer_cast<BinaryOpExpression>(
e)->isShortCircuitOperator()) {
break;
}
@@ -246,7 +246,7 @@ int DataFlowWalker::after(ConstructRawPtr cp) {
for (int i = 0, nk = e->getKidCount(); i < nk; i++) {
ExpressionPtr k = e->getNthExpr(i);
if (k && k->is(Expression::KindOfSimpleVariable) &&
!static_pointer_cast<SimpleVariable>(
!boost::static_pointer_cast<SimpleVariable>(
k)->getAlwaysStash()) {
process(k);
}
@@ -260,13 +260,13 @@ int DataFlowWalker::after(ConstructRawPtr cp) {
}
int DataFlowWalker::afterEach(ConstructRawPtr cur, int i, ConstructRawPtr kid) {
if (ExpressionRawPtr k = dynamic_pointer_cast<Expression>(kid)) {
if (ExpressionRawPtr k = boost::dynamic_pointer_cast<Expression>(kid)) {
if (k->is(Expression::KindOfSimpleVariable) &&
!static_pointer_cast<SimpleVariable>(k)->getAlwaysStash()) {
if (ExpressionRawPtr e = dynamic_pointer_cast<Expression>(cur)) {
!boost::static_pointer_cast<SimpleVariable>(k)->getAlwaysStash()) {
if (ExpressionRawPtr e = boost::dynamic_pointer_cast<Expression>(cur)) {
switch (e->getKindOf()) {
case Expression::KindOfBinaryOpExpression:
if (!static_pointer_cast<BinaryOpExpression>(
if (!boost::static_pointer_cast<BinaryOpExpression>(
e)->isShortCircuitOperator()) {
return WalkContinue;
}
@@ -350,13 +350,12 @@ void DataFlowWalker::process(ExpressionPtr e, bool doAccessChains) {
case Expression::KindOfAssignmentExpression:
case Expression::KindOfBinaryOpExpression:
case Expression::KindOfUnaryOpExpression: {
ExpressionPtr var = e->getStoreVariable();
ExpressionPtr var = e->getNthExpr(0);
if (var && var->getContext() & (Expression::AssignmentLHS|
Expression::OprLValue)) {
processAccessChain(var);
processAccess(var);
}
// fall through
}
default:
processAccess(e);
+7 -7
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -14,11 +14,11 @@
+----------------------------------------------------------------------+
*/
#ifndef incl_HPHP_DATA_FLOW_H_
#define incl_HPHP_DATA_FLOW_H_
#ifndef __DATA_FLOW_H__
#define __DATA_FLOW_H__
#include "hphp/compiler/analysis/bit_set_vec.h"
#include "hphp/compiler/analysis/control_flow.h"
#include <compiler/analysis/bit_set_vec.h>
#include <compiler/analysis/control_flow.h>
namespace HPHP {
@@ -91,7 +91,7 @@ private:
class DataFlowWalker : public ControlFlowGraphWalker {
public:
explicit DataFlowWalker(ControlFlowGraph *g) : ControlFlowGraphWalker(g) {}
DataFlowWalker(ControlFlowGraph *g) : ControlFlowGraphWalker(g) {}
template<class T>
void walk(T &t) { ControlFlowGraphWalker::walk(t); }
@@ -107,4 +107,4 @@ public:
///////////////////////////////////////////////////////////////////////////////
}
#endif // incl_HPHP_DATA_FLOW_H_
#endif // __DATA_FLOW_H__
+12 -12
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -14,15 +14,15 @@
+----------------------------------------------------------------------+
*/
#ifndef incl_HPHP_DEPTH_FIRST_VISITOR_H_
#define incl_HPHP_DEPTH_FIRST_VISITOR_H_
#ifndef __DEPTH_FIRST_VISITOR_H__
#define __DEPTH_FIRST_VISITOR_H__
#include "hphp/compiler/analysis/analysis_result.h"
#include "hphp/compiler/analysis/ast_walker.h"
#include "hphp/compiler/analysis/block_scope.h"
#include <compiler/analysis/analysis_result.h>
#include <compiler/analysis/ast_walker.h>
#include <compiler/analysis/block_scope.h>
#include "hphp/compiler/expression/expression.h"
#include "hphp/compiler/statement/statement.h"
#include <compiler/expression/expression.h>
#include <compiler/statement/statement.h>
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
@@ -64,12 +64,12 @@ public:
}
StatementPtr visitStmtRecur(StatementPtr stmt) {
BlockScopeRawPtr scope = dynamic_pointer_cast<LoopStatement>(stmt) ?
BlockScopeRawPtr scope = boost::dynamic_pointer_cast<LoopStatement>(stmt) ?
stmt->getScope() : BlockScopeRawPtr();
for (int i = 0, n = stmt->getKidCount(); i < n; i++) {
if (ConstructPtr kid = stmt->getNthKid(i)) {
if (StatementPtr s = dynamic_pointer_cast<Statement>(kid)) {
if (StatementPtr s = boost::dynamic_pointer_cast<Statement>(kid)) {
if (FunctionWalker::SkipRecurse(s)) continue;
if (scope) scope->incLoopNestedLevel();
if (StatementPtr rep = visitStmtRecur(s)) {
@@ -78,7 +78,7 @@ public:
}
if (scope) scope->decLoopNestedLevel();
} else {
ExpressionPtr e = dynamic_pointer_cast<Expression>(kid);
ExpressionPtr e = boost::dynamic_pointer_cast<Expression>(kid);
if (ExpressionPtr rep = visitExprRecur(e)) {
stmt->setNthKid(i, rep);
stmt->getScope()->addUpdates(BlockScope::UseKindCaller);
@@ -230,4 +230,4 @@ private:
///////////////////////////////////////////////////////////////////////////////
}
#endif // incl_HPHP_DEPTH_FIRST_VISITOR_H_
#endif // __DEPTH_FIRST_VISITOR_H__
+9 -9
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -14,12 +14,12 @@
+----------------------------------------------------------------------+
*/
#include "hphp/compiler/analysis/alias_manager.h"
#include "hphp/compiler/analysis/dictionary.h"
#include "hphp/compiler/expression/expression.h"
#include "hphp/compiler/statement/statement.h"
#include "hphp/compiler/statement/method_statement.h"
#include "hphp/compiler/statement/statement_list.h"
#include <compiler/analysis/alias_manager.h>
#include <compiler/analysis/dictionary.h>
#include <compiler/expression/expression.h>
#include <compiler/statement/statement.h>
#include <compiler/statement/method_statement.h>
#include <compiler/statement/statement_list.h>
using namespace HPHP;
using std::vector;
@@ -39,11 +39,11 @@ void Dictionary::build(MethodStatementPtr m) {
void Dictionary::build(StatementPtr stmt) {
for (int i = 0, n = stmt->getKidCount(); i < n; i++) {
if (ConstructPtr kid = stmt->getNthKid(i)) {
if (StatementPtr s = dynamic_pointer_cast<Statement>(kid)) {
if (StatementPtr s = boost::dynamic_pointer_cast<Statement>(kid)) {
if (FunctionWalker::SkipRecurse(s)) continue;
build(s);
} else {
ExpressionPtr e = dynamic_pointer_cast<Expression>(kid);
ExpressionPtr e = boost::dynamic_pointer_cast<Expression>(kid);
build(e);
}
}
+7 -7
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -14,11 +14,11 @@
+----------------------------------------------------------------------+
*/
#ifndef incl_HPHP_DICTIONARY_H_
#define incl_HPHP_DICTIONARY_H_
#ifndef __DICTIONARY_H__
#define __DICTIONARY_H__
#include "hphp/compiler/hphp.h"
#include "hphp/compiler/analysis/data_flow.h"
#include <compiler/hphp.h>
#include <compiler/analysis/data_flow.h>
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
@@ -32,7 +32,7 @@ class Dictionary {
public:
typedef std::vector<ExpressionPtr> IdMap;
explicit Dictionary(AliasManager &am);
Dictionary(AliasManager &am);
void build(MethodStatementPtr s);
void build(StatementPtr s);
void build(ExpressionPtr s);
@@ -78,4 +78,4 @@ private:
///////////////////////////////////////////////////////////////////////////////
}
#endif // incl_HPHP_DICTIONARY_H_
#endif // __DICTIONARY_H__
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+125 -382
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -14,23 +14,18 @@
+----------------------------------------------------------------------+
*/
#ifndef incl_HPHP_COMPILER_EMITTER_H_
#define incl_HPHP_COMPILER_EMITTER_H_
#ifndef __COMPILER_EMITTER_H__
#define __COMPILER_EMITTER_H__
#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"
#include <compiler/expression/expression.h>
#include <compiler/statement/statement.h>
#include <compiler/statement/use_trait_statement.h>
#include <compiler/statement/trait_prec_statement.h>
#include <compiler/statement/trait_alias_statement.h>
#include "hphp/runtime/vm/func.h"
#include "hphp/runtime/vm/unit.h"
#include "hphp/util/hash.h"
#include <deque>
#include <utility>
#include <runtime/vm/func.h>
#include <runtime/vm/unit.h>
#include <util/hash.h>
namespace HPHP {
@@ -45,12 +40,20 @@ DECLARE_BOOST_TYPES(SimpleFunctionCall);
DECLARE_BOOST_TYPES(SwitchStatement);
DECLARE_BOOST_TYPES(ForEachStatement);
class StaticClassName;
class HhbcExtFuncInfo;
class HhbcExtClassInfo;
namespace Compiler {
///////////////////////////////////////////////////////////////////////////////
using VM::Offset;
using VM::Func;
using VM::Class;
using VM::Unit;
using VM::InvalidAbsoluteOffset;
using VM::Opcode;
using VM::Id;
using namespace VM;
// Forward declarations.
class Label;
class EmitterVisitor;
@@ -93,13 +96,6 @@ public:
Id str;
Label* dest;
};
struct IterPair {
IterPair(IterKind k, Id i) : kind(k), id(i) {}
IterKind kind;
Id id;
};
#define O(name, imm, pop, push, flags) \
void name(imm);
#define NA
@@ -111,20 +107,18 @@ 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>&
#define IVA int32_t
#define LA int32_t
#define IA int32_t
#define I64A int64_t
#define IVA int32
#define HA int32
#define IA int32
#define I64A int64
#define DA double
#define SA const StringData*
#define AA ArrayData*
#define BA Label&
#define OA(type) type
#define VSA std::vector<std::string>&
#define OA unsigned char
OPCODES
#undef O
#undef NA
@@ -135,9 +129,8 @@ public:
#undef MA
#undef BLA
#undef SLA
#undef ILA
#undef IVA
#undef LA
#undef HA
#undef IA
#undef I64A
#undef DA
@@ -145,7 +138,6 @@ public:
#undef AA
#undef BA
#undef OA
#undef VSA
private:
ConstructPtr m_node;
UnitEmitter& m_ue;
@@ -208,7 +200,7 @@ private:
DataType dt; // META_DATA_TYPE
} metaData;
const StringData* className;
int64_t intval; // used for L and I symbolic flavors
int64 intval; // used for L and I symbolic flavors
// If intval is an unnamed local temporary, this offset is the start
// of the region we are using it (which we will need to have a
@@ -245,7 +237,7 @@ public:
std::string pretty() const;
void push(char sym);
void setInt(int64_t v);
void setInt(int64 v);
void setString(const StringData* s);
void setKnownCls(const StringData* s, bool nonNull);
void setNotRef();
@@ -282,7 +274,7 @@ public:
ClassBaseType getClsBaseType(int index) const;
int getLoc(int index) const;
int64_t getInt(int index) const;
int64 getInt(int index) const;
Offset getUnnamedLocStart(int index) const;
void pushFDesc();
@@ -292,7 +284,7 @@ public:
class Label {
public:
Label() : m_off(InvalidAbsoluteOffset) {}
explicit Label(Emitter& e) : m_off(InvalidAbsoluteOffset) {
Label(Emitter& e) : m_off(InvalidAbsoluteOffset) {
set(e);
}
Offset getAbsoluteOffset() const { return m_off; }
@@ -323,138 +315,15 @@ public:
class Funclet {
public:
explicit Funclet(Thunklet* body)
: m_body(body) {
}
Funclet(Thunklet* body, Label* entry) : m_body(body), m_entry(entry) {}
Thunklet* m_body;
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;
};
DECLARE_BOOST_TYPES(Region);
/*
* Region 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.
*/
class Region {
public:
enum Kind {
// Top-level (global) context.
Global,
// Function body / method body entry.
FuncBody,
// Entry for finally fault funclets emitted after the body of
// a function
FaultFunclet,
// Region by a finally clause
TryFinally,
// Finally block entry (begins after catches ends after finally)
Finally,
// Loop or switch statement.
LoopOrSwitch,
};
typedef Emitter::IterPair IterPair;
typedef std::vector<IterPair> IterVec;
Region(Region::Kind kind, RegionPtr parent);
// Helper for establishing the maximal depth of break / continue
// control targets that are allocated.
int getBreakContinueDepth();
// Returns the maximal break / continue depth admissable (aka the
// number of nested loops).
int getMaxBreakContinueDepth();
int getMaxState();
// 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; }
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;
// Only used for loop / break kind of entries.
Id m_iterId;
IterKind m_iterKind;
// 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
// 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;
// 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 parent entry.
RegionPtr m_parent;
Label* m_entry;
};
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(UnitEmitter& ue);
~EmitterVisitor();
bool visit(ConstructPtr c);
@@ -462,10 +331,9 @@ public:
void visitKids(ConstructPtr c);
void visit(FileScopePtr file);
void assignLocalVariableIds(FunctionScopePtr fs);
void assignFinallyVariableIds();
void fixReturnType(Emitter& e, FunctionCallPtr fn,
Func* builtinFunc = nullptr);
bool isBuiltinCall = false);
typedef std::vector<int> IndexChain;
void visitListAssignmentLHS(Emitter& e, ExpressionPtr exp,
IndexChain& indexChain,
std::vector<IndexChain*>& chainList);
@@ -479,10 +347,9 @@ public:
}
bool evalStackIsUnknown() { return m_evalStackIsUnknown; }
void popEvalStack(char symFlavor, int arg = -1, int pos = -1);
void popSymbolicLocal(Op opcode, int arg = -1, int pos = -1);
void popEvalStackMMany();
void popSymbolicLocal(Opcode opcode, int arg = -1, int pos = -1);
void popEvalStackLMany();
void popEvalStackMany(int len, char symFlavor);
void popEvalStackCVMany(int len);
void pushEvalStack(char symFlavor);
void peekEvalStack(char symFlavor, int depthActual);
void pokeEvalStack(char symFlavor, int depthActual);
@@ -492,51 +359,40 @@ public:
recordJumpTarget(target, m_evalStack);
}
void restoreJumpTargetEvalStack();
void recordCall();
bool isJumpTarget(Offset target);
void setPrevOpcode(Op op) { m_prevOpcode = op; }
Op getPrevOpcode() const { return m_prevOpcode; }
void setPrevOpcode(Opcode op) { m_prevOpcode = op; }
Opcode getPrevOpcode() const { return m_prevOpcode; }
bool currentPositionIsReachable() {
return (m_ue.bcPos() == m_curFunc->base()
|| isJumpTarget(m_ue.bcPos())
|| (instrFlags(getPrevOpcode()) & TF) == 0);
}
FuncEmitter* getFuncEmitter() { return m_curFunc; }
Id getStateLocal() {
assert(m_stateLocal >= 0);
return m_stateLocal;
}
Id getRetLocal() {
assert(m_retLocal >= 0);
return m_retLocal;
}
class IncludeTimeFatalException : public Exception {
public:
ConstructPtr m_node;
bool m_parseFatal;
IncludeTimeFatalException(ConstructPtr node, const char* fmt, ...)
: Exception(), m_node(node), m_parseFatal(false) {
: Exception(), m_node(node) {
va_list ap; va_start(ap, fmt); format(fmt, ap); va_end(ap);
}
virtual ~IncludeTimeFatalException() throw() {}
EXCEPTION_COMMON_IMPL(IncludeTimeFatalException);
void setParseFatal(bool b = true) { m_parseFatal = b; }
};
void pushIterScope(Id id, IterKind kind) {
m_pendingIters.emplace_back(id, kind);
enum IterKind {
KindOfIter = 0,
KindOfMIter = 1
};
void pushIterScope(Id id, bool itRef = false) {
IterKind itKind = itRef ? KindOfMIter : KindOfIter;
m_pendingIters.push_back(std::pair<Id,IterKind>(id,itKind));
}
void popIterScope() { m_pendingIters.pop_back(); }
private:
typedef std::pair<StringData*, bool> ClosureUseVar; // (name, byRef)
typedef std::vector<ClosureUseVar> ClosureUseVarVec;
typedef std::vector<std::pair<Id,IterKind> > PendingIterVec;
typedef std::pair<StringData*, ExpressionPtr> NonScalarPair;
typedef std::vector<NonScalarPair> NonScalarVec;
typedef std::pair<Id, int> StrCase;
class PostponedMeth {
public:
PostponedMeth(MethodStatementPtr m, FuncEmitter* fe, bool top,
@@ -547,7 +403,6 @@ private:
bool m_top;
ClosureUseVarVec* m_closureUseVars;
};
class PostponedCtor {
public:
PostponedCtor(InterfaceStatementPtr is, FuncEmitter* fe)
@@ -555,7 +410,8 @@ private:
InterfaceStatementPtr m_is;
FuncEmitter* m_fe;
};
typedef std::pair<StringData*, ExpressionPtr> NonScalarPair;
typedef std::vector<NonScalarPair> NonScalarVec;
class PostponedNonScalars {
public:
PostponedNonScalars(InterfaceStatementPtr is, FuncEmitter* fe,
@@ -568,7 +424,6 @@ private:
FuncEmitter* m_fe;
NonScalarVec* m_vec;
};
class PostponedClosureCtor {
public:
PostponedClosureCtor(ClosureUseVarVec& v, ClosureExpressionPtr e,
@@ -578,12 +433,37 @@ private:
ClosureExpressionPtr m_expr;
FuncEmitter* m_fe;
};
class CatchRegion {
class ControlTargets {
public:
CatchRegion(Offset start, Offset end) : m_start(start),
ControlTargets(Id itId, bool itRef, Label& brkTarg, Label& cntTarg,
Label& brkHand, Label& cntHand) :
m_itId(itId), m_itRef(itRef), m_brkTarg(brkTarg), m_cntTarg(cntTarg),
m_brkHand(brkHand), m_cntHand(cntHand) {}
Id m_itId;
bool m_itRef;
Label& m_brkTarg; // Jump here for "break;" (after doing IterFree)
Label& m_cntTarg; // Jump here for "continue;"
Label& m_brkHand; // Push N and jump here for "break N;"
Label& m_cntHand; // Push N and jump here for "continue N;"
};
class ControlTargetPusher {
public:
ControlTargetPusher(EmitterVisitor* e, Id itId, bool itRef, Label& brkTarg,
Label& cntTarg, Label& brkHand, Label& cntHand) : m_e(e) {
e->m_contTargets.push_front(ControlTargets(itId, itRef, brkTarg, cntTarg,
brkHand, cntHand));
}
~ControlTargetPusher() {
m_e->m_contTargets.pop_front();
}
private:
EmitterVisitor* m_e;
};
class ExnHandlerRegion {
public:
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;
@@ -594,27 +474,15 @@ private:
std::set<StringData*, string_data_lt> m_names;
std::vector<std::pair<StringData*, Label*> > m_catchLabels;
};
class FaultRegion {
public:
FaultRegion(Offset start,
Offset end,
Label* func,
Id iterId,
IterKind kind)
: m_start(start)
, m_end(end)
, m_func(func)
, m_iterId(iterId)
, m_iterKind(kind) {}
FaultRegion(Offset start, Offset end, Id iterId)
: m_start(start), m_end(end), m_iterId(iterId) {}
Offset m_start;
Offset m_end;
Label* m_func;
Id m_iterId;
IterKind m_iterKind;
Label m_func;
};
class FPIRegion {
public:
FPIRegion(Offset start, Offset end, Offset fpOff)
@@ -623,10 +491,10 @@ private:
Offset m_end;
Offset m_fpOff;
};
typedef std::pair<Id, int> StrCase;
struct SwitchState : private boost::noncopyable {
SwitchState() : nonZeroI(-1), defI(-1) {}
std::map<int64_t, int> cases; // a map from int (or litstr id) to case index
std::map<int64, int> cases; // a map from int (or litstr id) to case index
std::vector<StrCase> caseOrder; // for string switches, a list of the
// <litstr id, case index> in the order
// they appear in the source
@@ -634,13 +502,12 @@ private:
int defI;
};
private:
static const size_t kMinStringSwitchCases = 8;
UnitEmitter& m_ue;
FuncEmitter* m_curFunc;
FileScopePtr m_file;
Op m_prevOpcode;
Opcode m_prevOpcode;
std::deque<PostponedMeth> m_postponedMeths;
std::deque<PostponedCtor> m_postponedCtors;
@@ -649,44 +516,33 @@ private:
std::deque<PostponedNonScalars> m_postponedCinits;
std::deque<PostponedClosureCtor> m_postponedClosureCtors;
PendingIterVec m_pendingIters;
hphp_hash_map<std::string,FuncEmitter*> m_generatorEmitted;
hphp_hash_set<std::string> m_nonTopGeneratorEmitted;
hphp_hash_set<std::string> m_topMethodEmitted;
typedef std::map<const StringData*, Label*, string_data_lt> LabelMap;
LabelMap m_methLabels;
SymbolicStack m_evalStack;
bool m_evalStackIsUnknown;
hphp_hash_map<Offset, SymbolicStack> m_jumpTargetEvalStacks;
int m_actualStackHighWater;
int m_fdescHighWater;
typedef tbb::concurrent_hash_map<const StringData*, int,
StringDataHashCompare> EmittedClosures;
static EmittedClosures s_emittedClosures;
std::deque<Funclet*> m_funclets;
std::map<StatementPtr, Funclet*> m_memoizedFunclets;
std::deque<CatchRegion*> m_catchRegions;
int m_closureCounter; // used to uniquify closures' mangled names
std::deque<ControlTargets> m_contTargets;
std::deque<Funclet> m_funclets;
std::deque<ExnHandlerRegion*> m_exnHandlers;
std::deque<FaultRegion*> m_faultRegions;
std::deque<FPIRegion*> m_fpiRegions;
std::vector<Array> m_staticArrays;
std::vector<HphpArray*> 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
Id m_stateLocal;
Id m_retLocal;
std::map<StringData*, Label, string_data_lt> m_gotoLabels;
MetaInfoBuilder m_metaInfo;
public:
Label& topBreakHandler() { return m_contTargets.front().m_brkHand; }
Label& topContHandler() { return m_contTargets.front().m_cntHand; }
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 {
@@ -698,20 +554,25 @@ public:
void emitAGet(Emitter& e);
void emitCGetL2(Emitter& e);
void emitCGetL3(Emitter& e);
void emitPushL(Emitter& e);
void emitCGet(Emitter& e);
void emitVGet(Emitter& e);
void emitIsset(Emitter& e);
void emitIsType(Emitter& e, IsTypeOp op);
void emitIsNull(Emitter& e);
void emitIsArray(Emitter& e);
void emitIsObject(Emitter& e);
void emitIsString(Emitter& e);
void emitIsInt(Emitter& e);
void emitIsDouble(Emitter& e);
void emitIsBool(Emitter& e);
void emitEmpty(Emitter& e);
void emitUnset(Emitter& e, ExpressionPtr exp = ExpressionPtr());
void emitVisitAndUnset(Emitter& e, ExpressionPtr exp);
void emitUnset(Emitter& e);
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 emitFreePendingIters(Emitter& e);
void emitConvertToCellIfVar(Emitter& e);
void emitConvertToCellOrLoc(Emitter& e);
void emitConvertSecondToCell(Emitter& e);
@@ -721,10 +582,8 @@ public:
template<class Expr> void emitVirtualClassBase(Emitter&, Expr* node);
void emitResolveClsBase(Emitter& e, int pos);
void emitClsIfSPropBase(Emitter& e);
Id emitVisitAndSetUnnamedL(Emitter& e, ExpressionPtr exp);
Id emitSetUnnamedL(Emitter& e);
void emitPushAndFreeUnnamedL(Emitter& e, Id tempLocal, Offset start);
void emitContinuationSwitch(Emitter& e, int ncase);
Label* getContinuationGotoLabel(StatementPtr s);
void emitContinuationSwitch(Emitter& e, SwitchStatementPtr s);
DataType analyzeSwitch(SwitchStatementPtr s, SwitchState& state);
void emitIntegerSwitch(Emitter& e, SwitchStatementPtr s,
std::vector<Label>& caseLabels, Label& done,
@@ -751,32 +610,6 @@ public:
void postponeSinit(InterfaceStatementPtr m, FuncEmitter* fe, NonScalarVec* v);
void postponeCinit(InterfaceStatementPtr m, FuncEmitter* fe, NonScalarVec* v);
void emitPostponedMeths();
void bindUserAttributes(MethodStatementPtr meth,
FuncEmitter *fe,
bool &allowOverride);
void bindNativeFunc(MethodStatementPtr meth, FuncEmitter *fe);
void emitMethodMetadata(MethodStatementPtr meth,
ClosureUseVarVec* useVars,
bool top);
void fillFuncEmitterParams(FuncEmitter* fe,
ExpressionListPtr params,
bool builtin = false);
void emitMethodPrologue(Emitter& e, MethodStatementPtr meth);
void emitMethod(MethodStatementPtr meth);
std::pair<FuncEmitter*,bool> createFuncEmitterForGeneratorBody(
MethodStatementPtr meth,
FuncEmitter* fe,
vector<FuncEmitter*>& top_fes);
void emitAsyncMethod(MethodStatementPtr meth);
void emitGeneratorCreate(MethodStatementPtr meth);
void emitGeneratorBody(MethodStatementPtr meth);
void emitConstMethodCallNoParams(Emitter& e, string name);
void emitCreateStaticWaitHandle(Emitter& e, std::string cls,
std::function<void()> emitParam);
void emitSetFuncGetArgs(Emitter& e);
void emitMethodDVInitializers(Emitter& e,
MethodStatementPtr& meth,
Label& topOfBody);
void emitPostponedCtors();
void emitPostponedPSinit(PostponedNonScalars& p, bool pinit);
void emitPostponedPinits();
@@ -796,133 +629,43 @@ public:
};
bool emitCallUserFunc(Emitter& e, SimpleFunctionCallPtr node);
Func* canEmitBuiltinCall(const std::string& name, int numParams);
void emitFuncCall(Emitter& e, FunctionCallPtr node,
const char* nameOverride = nullptr,
ExpressionListPtr paramsOverride = nullptr);
bool canEmitBuiltinCall(FunctionCallPtr fn, const std::string& name,
int numParams);
void emitFuncCall(Emitter& e, FunctionCallPtr node);
void emitFuncCallArg(Emitter& e, ExpressionPtr exp, int paramId);
void emitBuiltinCallArg(Emitter& e, ExpressionPtr exp, int paramId,
bool byRef);
void emitBuiltinDefaultArg(Emitter& e, Variant& v, DataType t, int paramId);
void emitClass(Emitter& e, ClassScopePtr cNode, bool topLevel);
void emitTypedef(Emitter& e, TypedefStatementPtr);
void emitForeachListAssignment(Emitter& e,
ListAssignmentPtr la,
int vLocalId);
PreClass::Hoistable emitClass(Emitter& e, ClassScopePtr cNode,
bool topLevel);
void emitBreakHandler(Emitter& e, Label& brkTarg, Label& cntTarg,
Label& brkHand, Label& cntHand, Id iter = -1,
IterKind itKind = KindOfIter);
void emitForeach(Emitter& e, ForEachStatementPtr fe);
void emitRestoreErrorReporting(Emitter& e, Id oldLevelLoc);
void emitMakeUnitFatal(Emitter& e,
const char* msg,
FatalOp k = FatalOp::Runtime);
void emitMakeUnitFatal(Emitter& e, const std::string& message);
// 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);
Funclet* getFunclet(StatementPtr stmt);
void addFunclet(Thunklet* body, Label* entry);
void emitFunclets(Emitter& e);
struct FaultIterInfo {
Id iterId;
IterKind kind;
};
void newFaultRegion(Offset start,
Offset end,
Label* entry,
FaultIterInfo = FaultIterInfo { -1, KindOfIter });
void newFaultRegion(StatementPtr stmt,
Offset start,
Offset end,
Label* entry,
FaultIterInfo = FaultIterInfo { -1, KindOfIter });
void
newFaultRegionAndFunclet(Offset start,
Offset end,
Thunklet* t,
FaultIterInfo = FaultIterInfo { -1, KindOfIter });
void
newFaultRegionAndFunclet(StatementPtr stmt,
Offset start,
Offset end,
Thunklet* t,
FaultIterInfo = FaultIterInfo { -1, KindOfIter });
void newFaultRegion(Offset start, Offset end, Thunklet* t, Id iter = -1);
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);
StringData* newClosureName();
void initScalar(TypedValue& tvVal, ExpressionPtr val);
bool requiresDeepInit(ExpressionPtr initExpr) const;
void emitClassTraitPrecRule(PreClassEmitter* pce, TraitPrecStatementPtr rule);
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);
extern "C" {
String hphp_compiler_serialize_code_model_for(String code, String prefix);
Unit* hphp_compiler_parse(const char* code, int codeLen, const MD5& md5,
const char* filename);
Unit* hphp_build_native_func_unit(const HhbcExtFuncInfo* builtinFuncs,
@@ -935,4 +678,4 @@ extern "C" {
}
}
#endif // incl_HPHP_COMPILER_EMITTER_H_
#endif // __COMPILER_EMITTER_H__
+9 -9
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -14,14 +14,14 @@
+----------------------------------------------------------------------+
*/
#include "hphp/compiler/analysis/expr_dict.h"
#include "hphp/compiler/analysis/alias_manager.h"
#include <compiler/analysis/alias_manager.h>
#include <compiler/analysis/expr_dict.h>
#include "hphp/compiler/expression/expression.h"
#include "hphp/compiler/expression/assignment_expression.h"
#include <compiler/expression/expression.h>
#include <compiler/expression/assignment_expression.h>
#include "hphp/compiler/statement/statement.h"
#include "hphp/compiler/statement/method_statement.h"
#include <compiler/statement/statement.h>
#include <compiler/statement/method_statement.h>
using namespace HPHP;
using std::vector;
@@ -59,7 +59,7 @@ void ExprDict::getTypes(ExpressionPtr e, TypePtrIdxPairVec &types) {
class TypeFunc { public:
bool operator()(const TypePtrIdxPair& entry) const {
return entry.first != nullptr;
return entry.first;
}
};
static TypeFunc s_type_func;
@@ -313,7 +313,7 @@ void ExprDict::updateAccess(ExpressionPtr e) {
BitOps::set_bit(aid, m_altered, true);
}
if (!(cls & Expression::Store) ||
a != e->getStoreVariable()) {
a != e->getNthExpr(0)) {
a->clearAvailable();
m_avlAccess[i] = m_avlAccess[--n];
m_avlAccess.resize(n);
+7 -7
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -14,10 +14,10 @@
+----------------------------------------------------------------------+
*/
#ifndef incl_HPHP_EXPR_DICT_H_
#define incl_HPHP_EXPR_DICT_H_
#ifndef __EXPR_DICT_H__
#define __EXPR_DICT_H__
#include "hphp/compiler/analysis/dictionary.h"
#include <compiler/analysis/dictionary.h>
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
@@ -27,7 +27,7 @@ typedef std::vector<TypePtrIdxPair> TypePtrIdxPairVec;
class ExprDict : public Dictionary {
public:
explicit ExprDict(AliasManager &am);
ExprDict(AliasManager &am);
/* Building the dictionary */
void build(MethodStatementPtr m);
void visit(ExpressionPtr e);
@@ -43,8 +43,8 @@ public:
TypePtr propagateType(ExpressionPtr e);
void getTypes(ExpressionPtr e, TypePtrIdxPairVec &types);
private:
/**
* types is filled with (type assertion, canon id for that type assertion)
* tuples
@@ -94,4 +94,4 @@ private:
///////////////////////////////////////////////////////////////////////////////
}
#endif // incl_HPHP_EXPR_DICT_H_
#endif // __EXPR_DICT_H__
+591 -143
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -13,40 +13,38 @@
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#include "hphp/compiler/analysis/file_scope.h"
#include <compiler/analysis/file_scope.h>
#include <compiler/analysis/code_error.h>
#include <compiler/analysis/analysis_result.h>
#include <compiler/analysis/class_scope.h>
#include <compiler/statement/statement_list.h>
#include <compiler/statement/exp_statement.h>
#include <compiler/option.h>
#include <compiler/analysis/constant_table.h>
#include <compiler/analysis/function_scope.h>
#include <sys/stat.h>
#include "folly/ScopeGuard.h"
#include <compiler/parser/parser.h>
#include <util/logger.h>
#include <util/util.h>
#include <util/base.h>
#include <compiler/expression/expression_list.h>
#include <compiler/statement/function_statement.h>
#include <compiler/analysis/variable_table.h>
#include <compiler/expression/simple_function_call.h>
#include <compiler/expression/include_expression.h>
#include <compiler/expression/user_attribute.h>
#include <runtime/base/complex_types.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"
#include "hphp/compiler/statement/exp_statement.h"
#include "hphp/compiler/option.h"
#include "hphp/compiler/analysis/constant_table.h"
#include "hphp/compiler/analysis/function_scope.h"
#include "hphp/compiler/parser/parser.h"
#include "hphp/util/logger.h"
#include "hphp/util/util.h"
#include "hphp/util/deprecated/base.h"
#include "hphp/compiler/expression/expression_list.h"
#include "hphp/compiler/statement/function_statement.h"
#include "hphp/compiler/analysis/variable_table.h"
#include "hphp/compiler/expression/simple_function_call.h"
#include "hphp/compiler/expression/include_expression.h"
#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 +66,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;
@@ -80,7 +73,8 @@ FunctionScopePtr FileScope::setTree(AnalysisResultConstPtr ar,
return createPseudoMain(ar);
}
void FileScope::cleanupForError(AnalysisResultConstPtr ar) {
void FileScope::cleanupForError(AnalysisResultConstPtr ar,
int line, const string &msg) {
for (StringToClassScopePtrVecMap::const_iterator iter = m_classes.begin();
iter != m_classes.end(); ++iter) {
BOOST_FOREACH(ClassScopePtr cls, iter->second) {
@@ -96,49 +90,25 @@ void FileScope::cleanupForError(AnalysisResultConstPtr ar) {
StringToClassScopePtrVecMap().swap(m_classes);
m_pseudoMain.reset();
m_tree.reset();
}
template <class Meth>
void makeFatalMeth(FileScope& file,
AnalysisResultConstPtr ar,
const std::string& msg,
int line,
Meth meth) {
LocationPtr loc(new Location());
LabelScopePtr labelScope(new LabelScope());
loc->file = file.getName().c_str();
loc->file = m_fileName.c_str();
loc->first(line, 0);
loc->last(line, 0);
BlockScopePtr scope;
ExpressionListPtr args(new ExpressionList(scope, loc));
args->addElement(Expression::MakeScalarExpression(ar, scope, loc, msg));
SimpleFunctionCallPtr e(
new SimpleFunctionCall(scope, loc, "throw_fatal", false, args,
ExpressionPtr()));
meth(e);
ExpStatementPtr exp(new ExpStatement(scope, labelScope, loc, e));
StatementListPtr stmts(new StatementList(scope, labelScope, loc));
new SimpleFunctionCall(scope, loc, "throw_fatal", args, ExpressionPtr()));
e->setThrowFatal();
ExpStatementPtr exp(new ExpStatement(scope, loc, e));
StatementListPtr stmts(new StatementList(scope, loc));
stmts->addElement(exp);
FunctionScopePtr fs = file.setTree(ar, stmts);
fs->setOuterScope(file.shared_from_this());
FunctionScopePtr fs = setTree(ar, stmts);
fs->setOuterScope(shared_from_this());
fs->getStmt()->resetScope(fs);
fs->getStmt()->setLocation(loc);
file.setOuterScope(const_cast<AnalysisResult*>(ar.get())->shared_from_this());
}
void FileScope::makeFatal(AnalysisResultConstPtr ar,
const std::string& msg,
int line) {
auto meth = [](SimpleFunctionCallPtr e) { e->setThrowFatal(); };
makeFatalMeth(*this, ar, msg, line, meth);
}
void FileScope::makeParseFatal(AnalysisResultConstPtr ar,
const std::string& msg,
int line) {
auto meth = [](SimpleFunctionCallPtr e) { e->setThrowParseFatal(); };
makeFatalMeth(*this, ar, msg, line, meth);
setOuterScope(const_cast<AnalysisResult*>(ar.get())->shared_from_this());
}
bool FileScope::addFunction(AnalysisResultConstPtr ar,
@@ -222,6 +192,13 @@ int FileScope::getGlobalAttribute() const {
return m_attributes.back();
}
bool FileScope::needPseudoMainVariables() const {
VariableTablePtr variables = m_pseudoMain->getVariables();
return
variables->getAttribute(VariableTable::ContainsDynamicVariable) ||
variables->getSymbols().size() > 0;
}
///////////////////////////////////////////////////////////////////////////////
ExpressionPtr FileScope::getEffectiveImpl(AnalysisResultConstPtr ar) const {
@@ -229,6 +206,20 @@ ExpressionPtr FileScope::getEffectiveImpl(AnalysisResultConstPtr ar) const {
return ExpressionPtr();
}
bool FileScope::canUseDummyPseudoMain(AnalysisResultConstPtr ar) const {
if (!m_pseudoMain) {
return false;
}
assert(!m_pseudoMain->isVolatile());
if (!Option::GenerateDummyPseudoMain ||
Option::KeepStatementsWithNoEffect) {
return false;
}
ExpressionPtr exp = getEffectiveImpl(ar);
Variant val;
return (exp && exp->getScalarValue(val) && val.same(true));
}
///////////////////////////////////////////////////////////////////////////////
void FileScope::declareConstant(AnalysisResultPtr ar, const string &name) {
@@ -247,6 +238,7 @@ void FileScope::addConstant(const string &name, TypePtr type,
void FileScope::addIncludeDependency(AnalysisResultPtr ar,
const string &file, bool byInlined) {
ar->addIncludeDependency(shared_from_this(), file);
if (byInlined) m_usedIncludesInline.insert(file);
}
void FileScope::addClassDependency(AnalysisResultPtr ar,
const string &classname) {
@@ -255,6 +247,7 @@ void FileScope::addClassDependency(AnalysisResultPtr ar,
void FileScope::addFunctionDependency(AnalysisResultPtr ar,
const string &funcname, bool byInlined) {
ar->addFunctionDependency(shared_from_this(), funcname);
if (byInlined) m_usedFuncsInline.insert(funcname);
}
void FileScope::addConstantDependency(AnalysisResultPtr ar,
const string &decname) {
@@ -262,10 +255,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) {
@@ -330,80 +322,80 @@ bool FileScope::insertClassUtil(AnalysisResultPtr ar,
void FileScope::analyzeIncludesHelper(AnalysisResultPtr ar) {
m_includeState = 1;
SCOPE_EXIT { m_includeState = 2; };
if (m_pseudoMain) {
StatementList &stmts = *getStmt();
bool hoistOnly = false;
for (int i = 0, n = stmts.getCount(); i < n; i++) {
StatementPtr s = stmts[i];
if (!s) continue;
if (s->is(Statement::KindOfClassStatement) ||
s->is(Statement::KindOfInterfaceStatement)) {
if (!m_pseudoMain) return;
StatementList &stmts = *getStmt();
bool hoistOnly = false;
for (int i = 0, n = stmts.getCount(); i < n; i++) {
StatementPtr s = stmts[i];
if (!s) continue;
if (s->is(Statement::KindOfClassStatement) ||
s->is(Statement::KindOfInterfaceStatement)) {
ClassScopeRawPtr cls(
static_pointer_cast<InterfaceStatement>(s)->getClassScope());
if (hoistOnly) {
const string &parent = cls->getOriginalParent();
if (cls->getBases().size() > (parent.empty() ? 0 : 1)) {
continue;
ClassScopeRawPtr cls(
static_pointer_cast<InterfaceStatement>(s)->getClassScope());
if (hoistOnly) {
const string &parent = cls->getOriginalParent();
if (cls->getBases().size() > (parent.empty() ? 0 : 1)) {
continue;
}
if (!parent.empty()) {
ClassScopeRawPtr c = ar->findClass(parent);
if (!c || (c->isVolatile() &&
!resolveClass(c) && !checkClass(parent))) {
continue;
}
}
}
if (!parent.empty()) {
ClassScopeRawPtr c = ar->findClass(parent);
if (!c || (c->isVolatile() &&
!resolveClass(c) && !checkClass(parent))) {
if (cls->isVolatile()) {
insertClassUtil(ar, cls, true);
}
continue;
}
if (s->is(Statement::KindOfFunctionStatement)) {
FunctionScopeRawPtr func(
static_pointer_cast<FunctionStatement>(s)->getFunctionScope());
if (func->isVolatile()) m_providedDefs.insert(func);
continue;
}
if (!hoistOnly && s->is(Statement::KindOfExpStatement)) {
ExpressionRawPtr exp(
static_pointer_cast<ExpStatement>(s)->getExpression());
if (exp && exp->is(Expression::KindOfIncludeExpression)) {
FileScopeRawPtr fs(
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) {
m_providedDefs.insert(bs);
}
continue;
}
}
}
if (cls->isVolatile()) {
insertClassUtil(ar, cls, true);
}
continue;
hoistOnly = true;
}
if (s->is(Statement::KindOfFunctionStatement)) {
FunctionScopeRawPtr func(
static_pointer_cast<FunctionStatement>(s)->getFunctionScope());
if (func->isVolatile()) m_providedDefs.insert(func);
continue;
}
if (!hoistOnly && s->is(Statement::KindOfExpStatement)) {
ExpressionRawPtr exp(
static_pointer_cast<ExpStatement>(s)->getExpression());
if (exp && exp->is(Expression::KindOfIncludeExpression)) {
FileScopeRawPtr fs(
static_pointer_cast<IncludeExpression>(exp)->getIncludedFile(ar));
if (fs && fs->m_includeState != 1) {
if (!fs->m_includeState) {
fs->analyzeIncludesHelper(ar);
}
BOOST_FOREACH(BlockScopeRawPtr bs, fs->m_providedDefs) {
m_providedDefs.insert(bs);
}
continue;
}
}
}
hoistOnly = true;
}
m_includeState = 2;
}
void FileScope::analyzeIncludes(AnalysisResultPtr ar) {
if (!m_includeState) {
if (!m_privateInclude && !m_includeState) {
analyzeIncludesHelper(ar);
}
}
void FileScope::visit(AnalysisResultPtr ar,
void (*cb)(AnalysisResultPtr, StatementPtr, void*),
void *data) {
void *data)
{
if (m_pseudoMain) {
cb(ar, m_pseudoMain->getStmt(), data);
}
@@ -418,15 +410,11 @@ const string &FileScope::pseudoMainName() {
FunctionScopePtr FileScope::createPseudoMain(AnalysisResultConstPtr ar) {
StatementListPtr st = m_tree;
LabelScopePtr labelScope(new LabelScope());
FunctionStatementPtr f
(new FunctionStatement(BlockScopePtr(),
labelScope,
LocationPtr(),
ModifierExpressionPtr(),
(new FunctionStatement(BlockScopePtr(), LocationPtr(),
false, pseudoMainName(),
ExpressionListPtr(), TypeAnnotationPtr(),
st, 0, "", ExpressionListPtr()));
ExpressionListPtr(), st, 0, "",
ExpressionListPtr()));
f->setFileLevel();
FunctionScopePtr pseudoMain(
new HPHP::FunctionScope(ar, true,
@@ -458,18 +446,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 +471,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 +507,455 @@ void FileScope::serialize(JSON::DocTarget::OutputStream &out) const {
ms.done();
}
void FileScope::outputCPPHelper(CodeGenerator &cg, AnalysisResultPtr ar,
bool classes /* = true */) {
if (classes) {
for (StringToClassScopePtrVecMap::iterator it = m_classes.begin();
it != m_classes.end(); ++it) {
BOOST_FOREACH(ClassScopePtr cls, it->second) {
cls->getStmt()->outputCPP(cg, ar);
}
}
}
for (StringToFunctionScopePtrMap::iterator it = m_functions.begin();
it != m_functions.end(); ++it) {
FunctionScopePtr func = it->second;
if (func->isLocalRedeclaring()) {
BOOST_FOREACH(func, m_redeclaredFunctions->find(it->first)->second) {
func->getStmt()->outputCPP(cg, ar);
}
} else {
func->getStmt()->outputCPP(cg, ar);
}
}
}
void FileScope::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) {
assert(cg.getContext() == CodeGenerator::CppImplementation);
cg.setContext(CodeGenerator::CppConstantsDecl);
getConstants()->outputCPP(cg, ar);
cg.setContext(CodeGenerator::CppImplementation);
cg_printf("/* preface starts */\n");
for (StringToFunctionScopePtrMap::iterator it = m_functions.begin();
it != m_functions.end(); ++it) {
FunctionScopePtr func = it->second;
if (func->isLocalRedeclaring()) {
BOOST_FOREACH(func, m_redeclaredFunctions->find(it->first)->second) {
func->outputCPPPreface(cg, ar);
}
} else {
func->outputCPPPreface(cg, ar);
}
}
BOOST_FOREACH(FunctionScopeRawPtr closure, m_usedClosures) {
closure->outputCPPPreface(cg, ar);
}
for (StringToClassScopePtrVecMap::iterator it = m_classes.begin();
it != m_classes.end(); ++it) {
BOOST_FOREACH(ClassScopePtr cls, it->second) {
const FunctionScopePtrVec &funcs = cls->getFunctionsVec();
for (int i = 0, size = funcs.size(); i < size; ++i) {
FunctionScopePtr func = funcs[i];
func->outputCPPPreface(cg, ar);
}
}
}
cg_printf("/* preface finishes */\n");
outputCPPHelper(cg, ar);
if (Option::GenerateCPPMacros) {
bool hasRedec;
outputCPPJumpTableSupport(cg, ar, m_redeclaredFunctions, hasRedec);
if (Option::EnableEval >= Option::LimitedEval) {
outputCPPJumpTableEvalSupport(cg, ar, m_redeclaredFunctions, hasRedec);
}
outputCPPCallInfoTableSupport(cg, ar, m_redeclaredFunctions, hasRedec);
outputCPPHelperClassAllocSupport(cg, ar, m_redeclaredFunctions);
for (StringToClassScopePtrVecMap::iterator it = m_classes.begin();
it != m_classes.end(); ++it) {
BOOST_FOREACH(ClassScopePtr cls, it->second) {
if (!cls->isInterface()) {
cls->outputCPPDynamicClassImpl(cg, ar);
}
}
}
}
}
void FileScope::outputCPPPseudoMain(CodeGenerator &cg, AnalysisResultPtr ar) {
assert(cg.getContext() == CodeGenerator::CppPseudoMain);
outputCPPHelper(cg, ar, false);
}
void FileScope::outputCPPForwardDeclarations(CodeGenerator &cg,
AnalysisResultPtr ar) {
cg.setContext(CodeGenerator::CppForwardDeclaration);
BOOST_FOREACH(ClassScopeRawPtr cls, m_usedClassesFullHeader) {
if (cls->isUserClass()) {
cg_printInclude(cls->getHeaderFilename());
}
}
bool first = true;
BOOST_FOREACH(const string &str, m_usedLiteralStringsHeader) {
int index = -1;
int stringId = cg.checkLiteralString(str, index, ar, BlockScopePtr());
always_assert(index != -1);
string lisnam = ar->getLiteralStringName(stringId, index);
if (!cg.ensureInNamespace() && first) cg_printf("\n");
first = false;
if (Option::UseStaticStringProxy) {
string proxyNam = ar->getLiteralStringName(stringId, index, true);
cg_printf("extern StaticStringProxy %s;\n", proxyNam.c_str());
cg_printf("#ifndef %s\n", lisnam.c_str());
cg_printf("#define %s (*(StaticString *)(&%s))\n",
lisnam.c_str(), proxyNam.c_str());
cg_printf("#endif\n");
} else {
cg_printf("extern StaticString %s;\n", lisnam.c_str());
}
}
first = true;
BOOST_FOREACH(const int64 &val, m_usedScalarVarIntegersHeader) {
int index = -1;
int hash = ar->checkScalarVarInteger(val, index);
always_assert(index != -1);
string name = ar->getScalarVarIntegerName(hash, index);
if (!cg.ensureInNamespace() && first) cg_printf("\n");
first = false;
cg_printf("extern const VarNR &%s;\n", name.c_str());
}
first = true;
BOOST_FOREACH(const double &val, m_usedScalarVarDoublesHeader) {
int index = -1;
int hash = ar->checkScalarVarDouble(val, index);
always_assert(index != -1);
string name = ar->getScalarVarDoubleName(hash, index);
if (!cg.ensureInNamespace() && first) cg_printf("\n");
first = false;
cg_printf("extern const VarNR &%s;\n", name.c_str());
}
first = true;
BOOST_FOREACH(const string &str, m_usedLitVarStringsHeader) {
int index = -1;
int stringId = cg.checkLiteralString(str, index, ar, BlockScopePtr());
always_assert(index != -1);
string lisnam = ar->getLitVarStringName(stringId, index);
if (!cg.ensureInNamespace() && first) cg_printf("\n");
first = false;
if (Option::UseStaticStringProxy) {
string proxyName = ar->getLitVarStringName(stringId, index, true);
cg_printf("extern VariantProxy %s;\n", proxyName.c_str());
cg_printf("#ifndef %s\n", lisnam.c_str());
cg_printf("#define %s (*(Variant *)&%s)\n",
lisnam.c_str(), proxyName.c_str());
cg_printf("#endif\n");
} else {
cg_printf("extern VarNR %s;\n", lisnam.c_str());
}
}
first = true;
BOOST_FOREACH(const string &str, m_usedDefaultValueScalarArrays) {
int index = -1;
int hash = ar->checkScalarArray(str, index);
always_assert(hash != -1 && index != -1);
string name = ar->getScalarArrayName(hash, index);
if (!cg.ensureInNamespace() && first) cg_printf("\n");
first = false;
cg_printf("extern StaticArray %s;\n", name.c_str());
}
first = true;
BOOST_FOREACH(const string &str, m_usedDefaultValueScalarVarArrays) {
int index = -1;
int hash = ar->checkScalarArray(str, index);
always_assert(hash != -1 && index != -1);
string name = ar->getScalarVarArrayName(hash, index);
if (!cg.ensureInNamespace() && first) cg_printf("\n");
first = false;
cg_printf("extern VarNR %s;\n", name.c_str());
}
first = true;
BOOST_FOREACH(const string &str, m_usedConstsHeader) {
BlockScopeConstPtr block = ar->findConstantDeclarer(str);
always_assert(block);
ConstantTableConstPtr constants = block->getConstants();
if (!cg.ensureInNamespace() && first) cg_printf("\n");
first = false;
constants->outputSingleConstant(cg, ar, str);
}
first = true;
BOOST_FOREACH(const CodeGenerator::UsedClassConst& item,
m_usedClassConstsHeader) {
ClassScopePtr cls = item.first;
if (!cg.ensureInNamespace() && first) cg_printf("\n");
first = false;
cls->getConstants()->outputSingleConstant(cg, ar, item.second);
}
BOOST_FOREACH(ClassScopeRawPtr usedClass, m_usedClassesHeader) {
if (!cg.ensureInNamespace() && first) cg_printf("\n");
first = false;
usedClass->outputForwardDeclaration(cg);
}
cg.ensureOutOfNamespace();
}
void FileScope::outputCPPDeclarations(CodeGenerator &cg,
AnalysisResultPtr ar) {
cg.printSection("Declarations");
cg.setContext(CodeGenerator::CppDeclaration);
if (cg.getOutput() == CodeGenerator::MonoCPP) {
cg.namespaceBegin();
outputCPPHelper(cg, ar);
cg.namespaceEnd();
} else {
std::set<FileScopePtr> done;
done.insert(shared_from_this());
// Class declarations cunningly expressed as includes so I don't
// have to worry about inheritance dependencies.
for (StringToClassScopePtrVecMap::iterator it = m_classes.begin();
it != m_classes.end(); ++it) {
BOOST_FOREACH(ClassScopePtr cls, it->second) {
cg_printInclude(cls->getHeaderFilename());
}
}
BOOST_FOREACH(string name, m_usedFuncsInline) {
FunctionScopePtr func = ar->findFunction(name);
if (func) {
FileScopePtr fs = func->getContainingFile();
if (fs && done.find(fs) == done.end()) {
done.insert(fs);
cg_printInclude(fs->outputFilebase());
}
}
}
BOOST_FOREACH(string name, m_usedIncludesInline) {
FileScopePtr fs = ar->findFileScope(name);
if (fs && done.find(fs) == done.end()) {
done.insert(fs);
cg_printInclude(fs->outputFilebase());
}
}
cg.namespaceBegin();
cg.setContext(CodeGenerator::CppForwardDeclaration);
cg.printSection("Includes and Functions", false);
outputCPPHelper(cg, ar, false); // function forward declarations
cg.setContext(CodeGenerator::CppDeclaration);
outputCPPHelper(cg, ar, false); // function declarations (only inline)
cg.printSection("Constants");
if (cg.getOutput() != CodeGenerator::MonoCPP) {
getConstants()->outputCPP(cg, ar, false);
} else {
cg_printf("// (omitted in MonoCPP mode)\n");
}
cg.namespaceEnd();
}
}
void FileScope::outputCPPForwardStaticDecl(CodeGenerator &cg,
AnalysisResultPtr ar) {
string header = outputFilebase() + ".fws.h";
cg.headerBegin(header);
cg.namespaceBegin();
cg.printSection("1. Static Strings", false);
string str;
BOOST_FOREACH(str, m_usedLiteralStrings) {
if (m_usedLiteralStringsHeader.find(str) !=
m_usedLiteralStringsHeader.end()) {
continue;
}
int index = -1;
int stringId = cg.checkLiteralString(str, index, ar, BlockScopePtr());
always_assert(index != -1);
string lisnam = ar->getLiteralStringName(stringId, index);
if (Option::UseStaticStringProxy) {
string proxyNam = ar->getLiteralStringName(stringId, index, true);
cg_printf("extern StaticStringProxy %s;\n", proxyNam.c_str());
cg_printf("#ifndef %s\n", lisnam.c_str());
cg_printf("#define %s (*(StaticString *)(&%s))\n",
lisnam.c_str(), proxyNam.c_str());
cg_printf("#endif\n");
} else {
cg_printf("extern StaticString %s;\n", lisnam.c_str());
}
}
cg_printf("\n");
cg.printSection("2. Static Arrays", false);
BOOST_FOREACH(str, m_usedScalarArrays) {
if (m_usedDefaultValueScalarArrays.find(str) !=
m_usedDefaultValueScalarArrays.end()) {
continue;
}
int index = -1;
int hash = ar->checkScalarArray(str, index);
always_assert(hash != -1 && index != -1);
string name = ar->getScalarArrayName(hash, index);
cg_printf("extern StaticArray %s;\n", name.c_str());
}
if (Option::UseScalarVariant) {
cg_printf("\n");
cg.printSection("3. Static Variants", false);
int64 val;
BOOST_FOREACH(val, m_usedScalarVarIntegers) {
if (m_usedScalarVarIntegersHeader.find(val) !=
m_usedScalarVarIntegersHeader.end()) {
continue;
}
int index = -1;
int hash = ar->checkScalarVarInteger(val, index);
always_assert(index != -1);
string name = ar->getScalarVarIntegerName(hash, index);
cg_printf("extern const VarNR &%s;\n", name.c_str());
}
cg_printf("\n");
double dval;
BOOST_FOREACH(dval, m_usedScalarVarDoubles) {
if (m_usedScalarVarDoublesHeader.find(dval) !=
m_usedScalarVarDoublesHeader.end()) {
continue;
}
int index = -1;
int hash = ar->checkScalarVarDouble(dval, index);
always_assert(index != -1);
string name = ar->getScalarVarDoubleName(hash, index);
cg_printf("extern const VarNR &%s;\n", name.c_str());
}
cg_printf("\n");
BOOST_FOREACH(str, m_usedLitVarStrings) {
if (m_usedLitVarStringsHeader.find(str) !=
m_usedLitVarStringsHeader.end()) {
continue;
}
int index = -1;
int stringId = cg.checkLiteralString(str, index, ar, BlockScopePtr());
always_assert(index != -1);
string lisnam = ar->getLitVarStringName(stringId, index);
if (Option::UseStaticStringProxy) {
string proxyName = ar->getLitVarStringName(stringId, index, true);
cg_printf("extern VariantProxy %s;\n", proxyName.c_str());
cg_printf("#ifndef %s\n", lisnam.c_str());
cg_printf("#define %s (*(Variant *)&%s)\n",
lisnam.c_str(), proxyName.c_str());
cg_printf("#endif\n");
} else {
cg_printf("extern VarNR %s;\n", lisnam.c_str());
}
}
cg_printf("\n");
BOOST_FOREACH(str, m_usedScalarVarArrays) {
if (m_usedDefaultValueScalarVarArrays.find(str) !=
m_usedDefaultValueScalarVarArrays.end()) {
continue;
}
int index = -1;
int hash = ar->checkScalarArray(str, index);
always_assert(hash != -1 && index != -1);
string name = ar->getScalarVarArrayName(hash, index);
cg_printf("extern VarNR %s;\n", name.c_str());
}
cg_printf("\n");
}
cg.namespaceEnd();
cg_printf("\n");
cg.headerEnd(header);
}
void FileScope::outputCPPDeclHeader(CodeGenerator &cg, AnalysisResultPtr ar) {
cg.setFileOrClassHeader(true);
string header = outputFilebase() + ".h";
cg.headerBegin(header);
if (Option::GenerateCppLibCode ||
cg.getOutput() == CodeGenerator::SystemCPP) {
cg.printBasicIncludes();
}
outputCPPForwardDeclarations(cg, ar);
outputCPPDeclarations(cg, ar);
cg.headerEnd(header);
}
void FileScope::outputCPPClassHeaders(AnalysisResultPtr ar,
CodeGenerator::Output output) {
ClassScopePtr cls;
for (StringToClassScopePtrVecMap::iterator it = m_classes.begin();
it != m_classes.end(); ++it) {
BOOST_FOREACH(ClassScopePtr cls, it->second) {
cls->outputCPPHeader(ar, output);
}
}
}
void FileScope::outputCPPFFI(CodeGenerator &cg,
AnalysisResultPtr ar) {
cg.setContext(CodeGenerator::CppFFIDecl);
cg.useStream(CodeGenerator::PrimaryStream);
outputCPPHelper(cg, ar, true);
cg.useStream(CodeGenerator::ImplFile);
cg.setContext(CodeGenerator::CppFFIImpl);
cg_printInclude(outputFilebase() + ".h");
outputCPPHelper(cg, ar, true);
}
void FileScope::outputHSFFI(CodeGenerator &cg,
AnalysisResultPtr ar) {
cg.setContext(CodeGenerator::HsFFI);
outputCPPHelper(cg, ar, false);
}
void FileScope::outputJavaFFI(CodeGenerator &cg, AnalysisResultPtr ar) {
// first, generate methods in HphpMain.java
for (StringToFunctionScopePtrMap::iterator it = m_functions.begin();
it != m_functions.end(); ++it) {
FunctionScopePtr func = it->second;
if (func->isLocalRedeclaring()) {
BOOST_FOREACH(func, m_redeclaredFunctions->find(it->first)->second) {
func->getStmt()->outputCPP(cg, ar);
}
} else {
func->getStmt()->outputCPP(cg, ar);
}
}
// for each php class or interface, generate a Java file
for (StringToClassScopePtrVecMap::iterator it = m_classes.begin();
it != m_classes.end(); ++it) {
BOOST_FOREACH(ClassScopePtr cls, it->second) {
cls->getStmt()->outputCPP(cg, ar);
}
}
}
void FileScope::outputJavaFFICPPStub(CodeGenerator &cg,
AnalysisResultPtr ar) {
if (cg.getContext() == CodeGenerator::JavaFFICppImpl) {
// java_stubs.h doesn't need the extra include
cg_printInclude(outputFilebase() + ".h");
}
outputCPPHelper(cg, ar, true);
}
void FileScope::outputSwigFFIStubs(CodeGenerator &cg, AnalysisResultPtr ar) {
// currently only support toplevel functions
outputCPPHelper(cg, ar, false);
}
+138 -59
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -14,20 +14,16 @@
+----------------------------------------------------------------------+
*/
#ifndef incl_HPHP_FILE_SCOPE_H_
#define incl_HPHP_FILE_SCOPE_H_
#ifndef __FILE_SCOPE_H__
#define __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 <compiler/analysis/block_scope.h>
#include <compiler/analysis/function_container.h>
#include <compiler/analysis/code_error.h>
#include <compiler/code_generator.h>
#include <boost/graph/adjacency_list.hpp>
#include "hphp/compiler/json.h"
#include "hphp/util/md5.h"
#include <util/json.h>
#include <runtime/base/md5.h>
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
@@ -52,8 +48,8 @@ public:
ContainsDynamicVariable = 0x001,
ContainsLDynamicVariable = 0x002,
VariableArgument = 0x004,
ContainsExtract = 0x008, // contains call to extract()
ContainsCompact = 0x010, // contains call to compact()
ContainsExtract = 0x008, // need special VariableTable
ContainsCompact = 0x010, // need RVariableTable + exists()
ContainsReference = 0x020, // returns ref or has ref parameters
ReferenceVariableArgument = 0x040, // like sscanf or fscanf
ContainsUnset = 0x080, // need special handling
@@ -63,8 +59,7 @@ public:
MixedVariableArgument = 0x800, // variable args, may or may not be ref'd
IsFoldable = 0x1000,// function can be constant folded
NeedsActRec = 0x2000,// builtin function needs ActRec
AllowOverride = 0x4000,// allow override of systemlib or builtin
NeedsFinallyLocals = 0x8000,
IgnoreRedefinition = 0x4000,// ignore redefinition of builtin function
};
typedef boost::adjacency_list<boost::setS, boost::vecS> Graph;
@@ -80,7 +75,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;
@@ -106,22 +100,88 @@ public:
*/
ExpressionPtr getEffectiveImpl(AnalysisResultConstPtr ar) const;
bool canUseDummyPseudoMain(AnalysisResultConstPtr ar) const;
/**
* Parser functions. Parser only deals with a FileScope object, and these
* are the only functions a parser calls upon analysis results.
*/
FunctionScopePtr setTree(AnalysisResultConstPtr ar, StatementListPtr tree);
void cleanupForError(AnalysisResultConstPtr ar);
void makeFatal(AnalysisResultConstPtr ar,
const std::string& msg, int line);
void makeParseFatal(AnalysisResultConstPtr ar,
const std::string& msg, int line);
void cleanupForError(AnalysisResultConstPtr ar,
int line, const std::string &msg);
bool addFunction(AnalysisResultConstPtr ar, FunctionScopePtr funcScope);
bool addClass(AnalysisResultConstPtr ar, ClassScopePtr classScope);
const StringToFunctionScopePtrVecMap *getRedecFunctions() {
return m_redeclaredFunctions;
}
void addUsedClosure(FunctionScopeRawPtr closure) {
m_usedClosures.insert(closure);
}
void addUsedLiteralString(std::string s) {
m_usedLiteralStrings.insert(s);
}
void addUsedLitVarString(std::string s) {
m_usedLitVarStrings.insert(s);
}
std::set<std::string> &getUsedLiteralStrings() {
return m_usedLiteralStrings;
}
std::set<std::string> &getUsedLitVarStrings() {
return m_usedLitVarStrings;
}
void addUsedLiteralStringHeader(std::string s) {
m_usedLiteralStringsHeader.insert(s);
}
void addUsedLitVarStringHeader(std::string s) {
m_usedLitVarStringsHeader.insert(s);
}
void addUsedScalarVarInteger(int64 i) {
m_usedScalarVarIntegers.insert(i);
}
std::set<int64> &getUsedScalarVarIntegers() {
return m_usedScalarVarIntegers;
}
void addUsedScalarVarIntegerHeader(int64 i) {
m_usedScalarVarIntegersHeader.insert(i);
}
void addUsedScalarVarDouble(double d) {
m_usedScalarVarDoubles.insert(d);
}
std::set<double> &getUsedScalarVarDoubles() {
return m_usedScalarVarDoubles;
}
void addUsedScalarVarDoubleHeader(double d) {
m_usedScalarVarDoublesHeader.insert(d);
}
void addUsedScalarArray(std::string s) {
m_usedScalarArrays.insert(s);
}
void addUsedScalarVarArray(std::string s) {
m_usedScalarVarArrays.insert(s);
}
void addUsedDefaultValueScalarArray(std::string s) {
m_usedDefaultValueScalarArrays.insert(s);
}
void addUsedDefaultValueScalarVarArray(std::string s) {
m_usedDefaultValueScalarVarArrays.insert(s);
}
void addUsedConstHeader(const std::string &s) {
m_usedConstsHeader.insert(s);
}
void addUsedClassConstHeader(ClassScopeRawPtr cls, const std::string &s) {
m_usedClassConstsHeader.insert(CodeGenerator::UsedClassConst(cls, s));
}
void addUsedClassHeader(ClassScopeRawPtr s) {
m_usedClassesHeader.insert(s);
}
void addUsedClassFullHeader(ClassScopeRawPtr s) {
m_usedClassesFullHeader.insert(s);
}
/**
* For separate compilation
@@ -144,27 +204,6 @@ public:
void addConstantDependency(AnalysisResultPtr ar,
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)
)
);
}
std::multimap<std::string,std::string> const& getClassAliases() const {
return m_classAliasMap;
}
void addTypeAliasName(const std::string& name) {
m_typeAliasNames.insert(boost::to_lower_copy(name));
}
std::set<std::string> const& getTypeAliasNames() const {
return m_typeAliasNames;
}
/**
* Called only by World
*/
@@ -173,8 +212,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);
@@ -190,22 +231,47 @@ public:
const std::string &pseudoMainName();
void outputFileCPP(AnalysisResultPtr ar, CodeGenerator &cg);
bool load();
bool needPseudoMainVariables() const;
std::string outputFilebase() const;
void addPseudoMainVariable(const std::string &name) {
m_pseudoMainVariables.insert(name);
}
std::set<std::string> &getPseudoMainVariables() {
return m_pseudoMainVariables;
}
FunctionScopeRawPtr getPseudoMain() const {
return m_pseudoMain;
}
void outputCPPForwardStaticDecl(CodeGenerator &cg, AnalysisResultPtr ar);
void outputCPPDeclHeader(CodeGenerator &cg, AnalysisResultPtr ar);
void outputCPPForwardDeclarations(CodeGenerator &cg, AnalysisResultPtr ar);
void outputCPPDeclarations(CodeGenerator &cg, AnalysisResultPtr ar);
void outputCPPClassHeaders(AnalysisResultPtr ar,
CodeGenerator::Output output);
void outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar);
void outputCPPPseudoMain(CodeGenerator &cg, AnalysisResultPtr ar);
void outputCPPFFI(CodeGenerator &cg, AnalysisResultPtr ar);
void outputHSFFI(CodeGenerator &cg, AnalysisResultPtr ar);
void outputJavaFFI(CodeGenerator &cg, AnalysisResultPtr ar);
void outputJavaFFICPPStub(CodeGenerator &cg, AnalysisResultPtr ar);
void outputSwigFFIStubs(CodeGenerator &cg, AnalysisResultPtr ar);
FileScopePtr shared_from_this() {
return static_pointer_cast<FileScope>
return boost::static_pointer_cast<FileScope>
(BlockScope::shared_from_this());
}
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;
@@ -216,23 +282,36 @@ private:
vertex_descriptor m_vertex;
std::set<FunctionScopeRawPtr> m_usedClosures;
std::set<std::string> m_usedFuncsInline;
CodeGenerator::ClassScopeSet m_usedClassesHeader;
CodeGenerator::ClassScopeSet m_usedClassesFullHeader;
std::set<std::string> m_usedConstsHeader;
CodeGenerator::UsedClassConstSet m_usedClassConstsHeader;
std::set<std::string> m_usedIncludesInline;
std::set<std::string> m_usedLiteralStrings;
std::set<std::string> m_usedLitVarStrings;
std::set<std::string> m_usedLiteralStringsHeader;
std::set<std::string> m_usedLitVarStringsHeader;
std::set<int64> m_usedScalarVarIntegers;
std::set<int64> m_usedScalarVarIntegersHeader;
std::set<double> m_usedScalarVarDoubles;
std::set<double> m_usedScalarVarDoublesHeader;
std::set<std::string> m_usedScalarArrays;
std::set<std::string> m_usedScalarVarArrays;
std::set<std::string> m_usedDefaultValueScalarArrays;
std::set<std::string> m_usedDefaultValueScalarVarArrays;
std::string m_pseudoMainName;
std::set<std::string> m_pseudoMainVariables;
BlockScopeSet m_providedDefs;
std::set<std::string> m_redecBases;
// Map from class alias names to the class they are aliased to.
// This is only needed in WholeProgram mode.
std::multimap<std::string,std::string> m_classAliasMap;
// Set of names that are on the left hand side of type alias
// declarations. We need this to make sure we don't mark classes
// with the same name Unique.
std::set<std::string> m_typeAliasNames;
FunctionScopePtr createPseudoMain(AnalysisResultConstPtr ar);
void setFileLevel(StatementListPtr stmt);
void outputCPPHelper(CodeGenerator &cg, AnalysisResultPtr ar,
bool classes = true);
};
///////////////////////////////////////////////////////////////////////////////
}
#endif // incl_HPHP_FILE_SCOPE_H_
#endif // __FILE_SCOPE_H__
+413 -11
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -14,16 +14,16 @@
+----------------------------------------------------------------------+
*/
#include "hphp/compiler/analysis/function_container.h"
#include "hphp/compiler/analysis/analysis_result.h"
#include "hphp/compiler/analysis/function_scope.h"
#include "hphp/compiler/analysis/class_scope.h"
#include "hphp/compiler/analysis/file_scope.h"
#include "hphp/compiler/analysis/code_error.h"
#include "hphp/compiler/statement/statement_list.h"
#include "hphp/compiler/option.h"
#include "hphp/util/util.h"
#include "hphp/util/hash.h"
#include <compiler/analysis/function_container.h>
#include <compiler/analysis/analysis_result.h>
#include <compiler/analysis/function_scope.h>
#include <compiler/analysis/class_scope.h>
#include <compiler/analysis/file_scope.h>
#include <compiler/analysis/code_error.h>
#include <compiler/statement/statement_list.h>
#include <compiler/option.h>
#include <util/util.h>
#include <util/hash.h>
using namespace HPHP;
@@ -78,3 +78,405 @@ void FunctionContainer::getFunctionsFlattened(
}
}
}
class FunctionIterator {
public:
FunctionIterator(const StringToFunctionScopePtrVecMap &mmap,
bool &hasRedec) : m_mmap(&mmap), m_smap(0),
m_miter(mmap.begin()),
m_hasRedec(hasRedec) {
setup();
}
FunctionIterator(const StringToFunctionScopePtrMap &smap,
const StringToFunctionScopePtrVecMap *mmap,
bool &hasRedec) : m_mmap(mmap), m_smap(&smap),
m_siter(smap.begin()),
m_hasRedec(hasRedec) {
setup();
}
bool ready() const {
if (m_smap) {
return m_siter != m_smap->end();
} else {
return m_miter != m_mmap->end();
}
}
bool firstInner() const {
if (m_smap && !m_siter->second->isLocalRedeclaring()) {
return true;
}
return m_innerIter == m_miter->second.begin();
}
void next() {
if (m_smap && !m_siter->second->isLocalRedeclaring()) {
++m_siter;
setup();
return;
}
++m_innerIter;
if (m_innerIter == m_miter->second.end()) {
if (m_smap) {
++m_siter;
} else {
++m_miter;
}
setup();
}
}
const string &name() const {
return m_smap ? m_siter->first : m_miter->first;
}
FunctionScopePtr get() const {
return m_smap && !m_siter->second->isLocalRedeclaring() ?
m_siter->second : *m_innerIter;
}
private:
const StringToFunctionScopePtrVecMap *m_mmap;
const StringToFunctionScopePtrMap *m_smap;
StringToFunctionScopePtrVecMap::const_iterator m_miter;
FunctionScopePtrVec::const_iterator m_innerIter;
StringToFunctionScopePtrMap::const_iterator m_siter;
bool &m_hasRedec;
void setup() {
if (ready()) {
if (m_smap) {
if (!m_siter->second->isRedeclaring()) {
return;
}
m_hasRedec = true;
if (!m_siter->second->isLocalRedeclaring()) {
return;
}
m_miter = m_mmap->find(m_siter->first);
} else {
if (m_miter->second.size() != 1) {
m_hasRedec = true;
}
}
m_innerIter = m_miter->second.begin();
}
}
};
void FunctionContainer::outputCPPJumpTableSupportMethod
(CodeGenerator &cg, AnalysisResultPtr ar, FunctionScopePtr func,
const char *funcPrefix) {
string name = func->getId();
const char *cname = name.c_str();
string origName = !func->inPseudoMain() ? func->getOriginalName() :
("run_init::" + func->getContainingFile()->getName());
cg_printf("Variant");
if (Option::FunctionSections.find(origName) !=
Option::FunctionSections.end()) {
string funcSection = Option::FunctionSections[origName];
if (!funcSection.empty()) {
cg_printf(" __attribute__ ((section (\".text.%s\")))",
funcSection.c_str());
}
}
cg_indentBegin(" %s%s(void *extra, int count, "
"INVOKE_FEW_ARGS_IMPL_ARGS) {\n",
Option::InvokeFewArgsPrefix, cname);
func->outputCPPDynamicInvoke(cg, ar, funcPrefix, cname, false, true);
cg_indentEnd("}\n");
cg_indentBegin("Variant %s%s(void *extra, CArrRef params) {\n",
Option::InvokePrefix, cname);
if (func->getMaxParamCount() <= Option::InvokeFewArgsCount &&
!func->isVariableArgument()) {
if (Option::InvokeWithSpecificArgs && !func->getMaxParamCount() &&
!ar->isSystem() && !ar->isSepExtension()) {
// For functions with no parameter, we can combine the i_ wrapper and
// the ifa_ wrapper.
cg_printf("return ((CallInfo::FuncInvoker0Args)&%s%s)(extra, 0);\n",
Option::InvokeFewArgsPrefix, cname);
} else {
cg_printf("return invoke_func_few_handler(extra, params, &%s%s);\n",
Option::InvokeFewArgsPrefix, cname);
}
} else {
FunctionScope::OutputCPPDynamicInvokeCount(cg);
func->outputCPPDynamicInvoke(cg, ar, funcPrefix, cname);
}
cg_indentEnd("}\n");
}
void
FunctionContainer::outputCPPHelperClassAllocSupport(
CodeGenerator &cg, AnalysisResultPtr ar,
const StringToFunctionScopePtrVecMap *redec) {
bool hasRedeclared;
for (FunctionIterator fit(m_functions, redec, hasRedeclared); fit.ready();
fit.next()) {
FunctionScopePtr func = fit.get();
func->outputCPPHelperClassAlloc(cg, ar);
}
}
void FunctionContainer::outputCPPJumpTableSupport(
CodeGenerator &cg, AnalysisResultPtr ar,
const StringToFunctionScopePtrVecMap *redec, bool &hasRedeclared,
vector<const char *> *funcs /* = NULL */) {
bool systemcpp = cg.getOutput() == CodeGenerator::SystemCPP;
const char *funcPrefix = Option::FunctionPrefix;
if (systemcpp) funcPrefix = Option::BuiltinFunctionPrefix;
// output invoke support methods
for (FunctionIterator fit(m_functions, redec, hasRedeclared); fit.ready();
fit.next()) {
FunctionScopePtr func = fit.get();
if (func->inPseudoMain() || !(systemcpp || func->isDynamic())) continue;
if (funcs && fit.firstInner()) {
funcs->push_back(fit.name().c_str());
}
outputCPPJumpTableSupportMethod(cg, ar, func, funcPrefix);
}
}
void FunctionContainer::outputCPPCallInfoTableSupport(
CodeGenerator &cg, AnalysisResultPtr ar,
const StringToFunctionScopePtrVecMap *redec, bool &hasRedeclared,
vector<const char *> *funcs /* = NULL */) {
bool systemcpp = cg.getOutput() == CodeGenerator::SystemCPP;
for (FunctionIterator fit(m_functions, redec, hasRedeclared); fit.ready();
fit.next()) {
FunctionScopePtr func = fit.get();
if (func->inPseudoMain() || !(systemcpp || func->isDynamic())) continue;
if (funcs && fit.firstInner()) {
funcs->push_back(fit.name().c_str());
}
func->outputCPPCallInfo(cg, ar);
}
}
void FunctionContainer::outputCPPJumpTableEvalSupport(
CodeGenerator &cg, AnalysisResultPtr ar,
const StringToFunctionScopePtrVecMap *redec,
bool &hasRedeclared) {
bool systemcpp = cg.getOutput() == CodeGenerator::SystemCPP;
// output invoke support methods
for (FunctionIterator fit(m_functions, redec, hasRedeclared); fit.ready();
fit.next()) {
FunctionScopePtr func = fit.get();
if (func->inPseudoMain() ||
(!systemcpp && (!func->isUserFunction() ||
!(func->isSepExtension() || func->isDynamic())))) {
continue;
}
string sname = func->getId();
}
}
void FunctionContainer::outputGetCallInfoHeader(CodeGenerator &cg,
const char *suffix,
bool needGlobals) {
cg_indentBegin("bool get_call_info%s(const CallInfo *&ci, void *&extra, "
"const char *s, strhash_t hash) {\n", suffix ? suffix : "");
if (needGlobals) cg.printDeclareGlobals();
cg_printf("extra = NULL;\n");
if (!suffix && (!Option::DynamicInvokeFunctions.empty() ||
Option::EnableEval == Option::FullEval)) {
cg_printf("const char *ss = get_renamed_function(s);\n");
cg_printf("if (ss != s) { s = ss; hash = -1;};\n");
}
}
void FunctionContainer::outputGetCallInfoTail(CodeGenerator &cg,
bool system) {
if (system) {
cg_printf("return false;\n");
} else {
cg_printf("return get_call_info_builtin(ci, extra, s, hash);\n");
}
cg_indentEnd("}\n");
}
void FunctionContainer::outputCPPHashTableGetCallInfo(
CodeGenerator &cg, bool system, bool noEval,
const StringToFunctionScopePtrMap *functions,
const vector<const char *> &funcs) {
assert(cg.getCurrentIndentation() == 0);
const char text1[] =
"\n"
"struct hashNodeFunc {\n"
" strhash_t hash;\n"
" bool offset;\n"
" bool end;\n"
" const char *name;\n"
" const void *data;\n"
"};\n"
"static const hashNodeFunc funcBuckets[] = {\n";
const char text3[] =
"static inline const hashNodeFunc *"
"findFunc(const char *name, strhash_t hash) {\n"
" const hashNodeFunc *p = funcMapTable[hash & %d];\n"
" if (UNLIKELY(!p)) return NULL;\n"
" do {\n"
" if (LIKELY(p->hash == hash) && (LIKELY(p->name==name)||"
"LIKELY(!strcasecmp(p->name, name)))) return p;\n"
" } while (!p++->end);\n"
" return NULL;\n"
"}\n"
"\n";
const char text4[] =
" if (hash < 0) hash = hash_string(s);\n"
" const hashNodeFunc *p = findFunc(s, hash);\n"
" if (LIKELY(p!=0)) {\n"
" if (UNLIKELY(p->offset)) {\n"
" DECLARE_GLOBAL_VARIABLES(g);\n"
" const char *addr = (const char *)g + (int64)p->data;\n"
" ci = *(const CallInfo **)addr;\n"
" return ci != 0;\n"
" } else {\n"
" ci = (const CallInfo *)p->data;\n"
" return true;\n"
" }\n"
" }\n";
const char text4s[] =
" if (hash < 0) hash = hash_string(s);\n"
" const hashNodeFunc *p = findFunc(s, hash);\n"
" if (LIKELY(p!=0)) {\n"
" ci = (const CallInfo *)p->data;\n"
" return true;\n"
" }\n";
int numEntries = funcs.size();
if (!noEval && numEntries > 0) {
JumpTable jt(cg, funcs, true, true, true, true);
cg_print(text1);
vector<int> offsets;
int prev = -1;
for (int n = 0; jt.ready(); ++n, jt.next()) {
int cur = jt.current();
if (prev != cur) {
while (++prev != cur) {
offsets.push_back(-1);
}
offsets.push_back(n);
}
const char *name = jt.key();
StringToFunctionScopePtrMap::const_iterator iterFuncs =
functions->find(name);
assert(iterFuncs != functions->end());
// We have assumptions that function names do not contain ".."
// (e.g., call_user_func0 ~ call_user_func6)
always_assert(!strstr(name, ".."));
FunctionScopePtr func = iterFuncs->second;
cg_printf(" {" STRHASH_FMT ",%d,%d,\"%s\",",
hash_string_i(name),
(int)func->isRedeclaring(), (int)jt.last(),
CodeGenerator::EscapeLabel(name).c_str());
if (func->isRedeclaring()) {
always_assert(!system);
string lname(CodeGenerator::FormatLabel(name));
cg_printf("(const void *)(offsetof(GlobalVariables, GCI(%s)))",
lname.c_str());
} else {
cg_printf("&%s%s",
Option::CallInfoPrefix, func->getId().c_str());
}
cg_printf("},\n");
}
cg_printf("};\n");
cg_indentBegin("static const hashNodeFunc *funcMapTable[] = {\n");
for (int i = 0, e = jt.size(), s = offsets.size(); i < e; i++) {
int o = i < s ? offsets[i] : -1;
if (o < 0) {
cg_printf("0,");
} else {
cg_printf("funcBuckets+%d,", o);
}
if ((i & 7) == 7) cg_printf("\n");
}
cg_printf("\n");
cg_indentEnd("};\n");
cg_printf(text3, jt.size() - 1);
}
outputGetCallInfoHeader(cg, system ? "_builtin" : noEval ? "_no_eval" : 0,
false);
cg_indentEnd();
if (numEntries > 0) {
cg_print(system ? text4s : text4);
}
cg_indentBegin(" ");
outputGetCallInfoTail(cg, system);
}
void FunctionContainer::outputCPPCodeInfoTable(
CodeGenerator &cg, AnalysisResultPtr ar, bool useSwitch,
const StringToFunctionScopePtrMap &functions) {
bool needGlobals = false;
vector<const char *> funcs;
bool system = cg.getOutput() == CodeGenerator::SystemCPP;
if (system) {
outputCPPCallInfoTableSupport(cg, ar, 0, needGlobals, nullptr);
}
for (StringToFunctionScopePtrMap::const_iterator iter = functions.begin(),
end = functions.end(); iter != end; ++iter) {
FunctionScopePtr func = iter->second;
if (!func->inPseudoMain() &&
(system || func->isDynamic() || func->isSepExtension())) {
funcs.push_back(iter->first.c_str());
if (!system && !func->isRedeclaring() && !func->isSepExtension()) {
cg_printf("extern const CallInfo %s%s;\n",
Option::CallInfoPrefix, func->getId().c_str());
}
}
}
if (!useSwitch) {
outputCPPHashTableGetCallInfo(cg, system, false, &functions, funcs);
if (!system) {
outputCPPHashTableGetCallInfo(cg, system, true, &functions, funcs);
}
return;
}
if (!system) cg_printf("static ");
outputGetCallInfoHeader(cg, system ? "_builtin" : "_impl", needGlobals);
for (JumpTable fit(cg, funcs, true, true, false); fit.ready(); fit.next()) {
const char *name = fit.key();
StringToFunctionScopePtrMap::const_iterator iterFuncs =
functions.find(name);
assert(iterFuncs != functions.end());
cg_indentBegin("HASH_GUARD(" STRHASH_FMT ", %s) {\n",
hash_string_i(name),
CodeGenerator::EscapeLabel(name).c_str());
if (iterFuncs->second->isRedeclaring()) {
string lname(CodeGenerator::FormatLabel(name));
cg_printf("ci = &g->GCI(%s)->ci;\n", lname.c_str());
} else {
cg_printf("ci = &%s%s;\n", Option::CallInfoPrefix,
iterFuncs->second->getId().c_str());
}
cg_printf("return true;\n");
cg_indentEnd("}\n");
}
outputGetCallInfoTail(cg, system);
if (system) return;
outputGetCallInfoHeader(cg, 0, false);
cg_printf("return get_call_info_impl(ci, extra, s, hash);\n");
cg_indentEnd("}\n");
outputGetCallInfoHeader(cg, "_no_eval", false);
cg_printf("return get_call_info_impl(ci, extra, s, hash);\n");
cg_indentEnd("}\n");
}
+40 -6
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -14,17 +14,18 @@
+----------------------------------------------------------------------+
*/
#ifndef incl_HPHP_FUNCTION_CONTAINER_H_
#define incl_HPHP_FUNCTION_CONTAINER_H_
#ifndef __FUNCTION_CONTAINER_H__
#define __FUNCTION_CONTAINER_H__
#include "hphp/compiler/hphp.h"
#include <compiler/hphp.h>
#include <compiler/util/jump_table.h>
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);
@@ -42,18 +43,51 @@ public:
void countReturnTypes(std::map<std::string, int> &counts,
const StringToFunctionScopePtrVecMap *redec);
/**
* Code generation functions.
*/
void outputCPPJumpTable(CodeGenerator &cg, AnalysisResultPtr ar,
const StringToFunctionScopePtrVecMap *redec);
const StringToFunctionScopePtrMap &getFunctions() const {
return m_functions;
}
void getFunctionsFlattened(const StringToFunctionScopePtrVecMap *redec,
FunctionScopePtrVec &funcs,
bool excludePseudoMains = false) const;
void outputCPPCodeInfoTable(
CodeGenerator &cg, AnalysisResultPtr ar, bool useSwitch,
const StringToFunctionScopePtrMap &functions);
protected:
// name => functions. Order of declaration
StringToFunctionScopePtrMap m_functions;
void outputCPPJumpTableSupport(CodeGenerator &cg, AnalysisResultPtr ar,
const StringToFunctionScopePtrVecMap *redec,
bool &hasRedeclared,
std::vector<const char *> *funcs = nullptr);
void outputCPPJumpTableEvalSupport(
CodeGenerator &cg, AnalysisResultPtr ar,
const StringToFunctionScopePtrVecMap *redec, bool &hasRedeclared);
void outputCPPCallInfoTableSupport(
CodeGenerator &cg, AnalysisResultPtr ar,
const StringToFunctionScopePtrVecMap *redec,
bool &hasRedeclared, std::vector<const char *> *funcs = nullptr);
void outputCPPJumpTableSupportMethod(CodeGenerator &cg, AnalysisResultPtr ar,
FunctionScopePtr func,
const char *funcPrefix);
void outputCPPHelperClassAllocSupport(
CodeGenerator &cg, AnalysisResultPtr ar,
const StringToFunctionScopePtrVecMap *redec);
private:
void outputGetCallInfoHeader(CodeGenerator &cg, const char *suffix,
bool needGlobals);
void outputGetCallInfoTail(CodeGenerator &cg, bool system);
void outputCPPHashTableGetCallInfo(
CodeGenerator &cg, bool system, bool noEval,
const StringToFunctionScopePtrMap *functions,
const std::vector<const char *> &funcs);
};
///////////////////////////////////////////////////////////////////////////////
}
#endif // incl_HPHP_FUNCTION_CONTAINER_H_
#endif // __FUNCTION_CONTAINER_H__
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+152 -55
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -14,16 +14,15 @@
+----------------------------------------------------------------------+
*/
#ifndef incl_HPHP_FUNCTION_SCOPE_H_
#define incl_HPHP_FUNCTION_SCOPE_H_
#ifndef __FUNCTION_SCOPE_H__
#define __FUNCTION_SCOPE_H__
#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 <compiler/expression/user_attribute.h>
#include <compiler/analysis/block_scope.h>
#include <compiler/option.h>
#include "hphp/util/hash-map-typedefs.h"
#include "hphp/parser/parser.h"
#include <util/json.h>
#include <util/parser/parser.h>
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
@@ -74,7 +73,7 @@ public:
FunctionScope(FunctionScopePtr orig, AnalysisResultConstPtr ar,
const std::string &name, const std::string &originalName,
StatementPtr stmt, ModifierExpressionPtr modifiers, bool user);
StatementPtr stmt, ModifierExpressionPtr modifiers);
/**
* System functions.
@@ -85,25 +84,22 @@ public:
void setParamName(int index, const std::string &name);
void setParamDefault(int index, const char* value, int64_t len,
const std::string &text);
CStrRef getParamDefault(int index);
void setRefParam(int index);
bool hasRefParam(int max) const;
void addModifier(int mod);
bool hasUserAttr(const char *attr) const;
/**
* What kind of function this is.
*/
bool isUserFunction() const { return !m_system && !isNative(); }
bool isSystem() const { return m_system; }
bool isUserFunction() const { return !m_system;}
bool isDynamic() const { return m_dynamic; }
bool isPublic() const;
bool isProtected() const;
bool isPrivate() const;
bool isStatic() const;
bool isAbstract() const;
bool isNative() const;
bool isFinal() const;
bool isMagic() const;
bool isRefParam(int index) const;
@@ -113,18 +109,23 @@ public:
bool hasImpl() const;
void setDirectInvoke() { m_directInvoke = true; }
bool hasDirectInvoke() const { return m_directInvoke; }
bool isZendParamMode() const;
bool mayContainThis();
bool isClosure() const;
bool isGenerator() const { return m_generator; }
void setGenerator(bool f) { m_generator = f; }
int allocYieldLabel();
int getYieldLabelCount() const;
int getYieldLabelGeneration() const;
void resetYieldLabelCount();
bool isAsync() const { return m_async; }
void setAsync(bool f) { m_async = f; }
bool isGenerator() const;
bool isGeneratorFromClosure() const;
bool hasGeneratorAsBody() const;
MethodStatementRawPtr getOrigGenStmt() const;
FunctionScopeRawPtr getOrigGenFS() const;
void setNeedsRefTemp() { m_needsRefTemp = true; }
bool needsRefTemp() const { return m_needsRefTemp; }
void setNeedsObjTemp() { m_needsObjTemp = true; }
bool needsObjTemp() const { return m_needsObjTemp; }
void setNeedsCheckMem() { m_needsCheckMem = true; }
bool needsCheckMem() const { return m_needsCheckMem; }
void setClosureGenerator() { m_closureGenerator = true; }
bool isClosureGenerator() const {
assert(!m_closureGenerator || isClosure());
return m_closureGenerator;
}
bool needsClassParam();
void setInlineSameContext(bool f) { m_inlineSameContext = f; }
@@ -160,6 +161,7 @@ public:
}
virtual std::string getId() const;
std::string getInjectionId() const;
int getRedeclaringId() const {
return m_redeclaring;
@@ -174,13 +176,6 @@ public:
m_volatile = false;
}
/**
* Tell this function about another outer scope that contains it.
*/
void addClonedTraitOuterScope(FunctionScopePtr scope) {
m_clonedTraitOuterScope.push_back(scope);
}
/**
* Get/set original name of the function, without case being lowered.
*/
@@ -223,12 +218,10 @@ public:
void setNeedsActRec();
/*
* If this is a builtin (C++ or PHP) and can be redefined
* If this is a builtin and can be redefined
*/
bool allowOverride() const;
void setAllowOverride();
bool needsFinallyLocals() const;
bool ignoreRedefinition() const;
void setIgnoreRedefinition();
/**
* Whether this function is a runtime helper function
@@ -244,10 +237,16 @@ public:
* Whether this function contains a usage of $this
*/
bool containsThis() const { return m_containsThis;}
void setContainsThis(bool f = true);
void setContainsThis(bool f=true) { m_containsThis = f;}
bool containsBareThis() const { return m_containsBareThis; }
bool containsRefThis() const { return m_containsBareThis & 2; }
void setContainsBareThis(bool f, bool ref = false);
void setContainsBareThis(bool f, bool ref = false) {
if (f) {
m_containsBareThis |= ref ? 2 : 1;
} else {
m_containsBareThis = 0;
}
}
/**
* How many parameters a caller should provide.
*/
@@ -257,8 +256,6 @@ public:
/**
* What is the inferred type of this function's return.
* Note that for generators and async functions, this is different
* from what caller actually gets when calling the function.
*/
void pushReturnType();
void setReturnType(AnalysisResultConstPtr ar, TypePtr type);
@@ -272,6 +269,9 @@ public:
void clearRetExprs();
void fixRetExprs();
bool needsTypeCheckWrapper() const;
const char *getPrefix(AnalysisResultPtr ar, ExpressionListPtr params);
void setOptFunction(FunctionOptPtr fn) { m_optFunction = fn; }
FunctionOptPtr getOptFunction() const { return m_optFunction; }
@@ -313,6 +313,10 @@ public:
bool isInlined() const { return m_inlineable; }
void disableInline() { m_inlineable = false; }
/* Whether this function is brought in by a separable extension */
void setSepExtension() { m_sep = true;}
bool isSepExtension() const { return m_sep;}
/* Whether we need to worry about the named return value optimization
for this function */
void setNRVOFix(bool flag) { m_nrvoFix = flag; }
@@ -348,6 +352,92 @@ public:
* Override BlockScope::outputPHP() to generate return type.
*/
virtual void outputPHP(CodeGenerator &cg, AnalysisResultPtr ar);
/**
* Override to preface with call temps.
*/
virtual void outputCPP(CodeGenerator &cg, AnalysisResultPtr ar);
/**
* Generate parameter declaration.
*/
void outputCPPParamsDecl(CodeGenerator &cg, AnalysisResultPtr ar,
ExpressionListPtr params, bool showDefault);
/**
* This one is a special version that doesn't require a params expression.
* It's for use with extension functions. It only works for the
* implementation since it ignores optional arguments.
*/
void outputCPPParamsImpl(CodeGenerator &cg, AnalysisResultPtr ar);
/**
* If inside this function, we have to make a call to an implementation
* function that has the same signature, how does the parameter list
* look like?
*/
void outputCPPParamsCall(CodeGenerator &cg, AnalysisResultPtr ar,
bool aggregateParams);
/**
* How does a caller prepare parameters.
*/
static void OutputCPPArguments(ExpressionListPtr params,
FunctionScopePtr func,
CodeGenerator &cg, AnalysisResultPtr ar,
int extraArg, bool variableArgument,
int extraArgArrayId = -1,
int extraArgArrayHash = -1,
int extraArgArrayIndex = -1,
bool ignoreFuncParamTypes = false);
/**
* Only generate arguments that have effects. This is for keeping those
* parameters around when generating a error-raising function call, so to
* avoid "unused" variable compiler warnings.
*/
static void OutputCPPEffectiveArguments(ExpressionListPtr params,
CodeGenerator &cg,
AnalysisResultPtr ar);
/**
* Generate invoke proxy.
*/
static void OutputCPPDynamicInvokeCount(CodeGenerator &cg);
void outputCPPDynamicInvoke(CodeGenerator &cg, AnalysisResultPtr ar,
const char *funcPrefix,
const char *name,
bool voidWrapperOff = false,
bool fewArgs = false,
bool ret = true,
const char *extraArg = nullptr,
bool constructor = false,
const char *instance = nullptr,
const char *class_name = "");
void outputCPPDef(CodeGenerator &cg);
/**
* ...so ClassStatement can call them for classes that don't have
* constructors defined
*/
void outputCPPCreateDecl(CodeGenerator &cg, AnalysisResultPtr ar);
void outputCPPCreateImpl(CodeGenerator &cg, AnalysisResultPtr ar);
/**
* output functions
*/
void outputCPPClassMap(CodeGenerator &cg, AnalysisResultPtr ar);
void outputMethodWrapper(CodeGenerator &cg, AnalysisResultPtr ar,
const char *clsToConstruct);
/**
* Output CallInfo instance for this function.
*/
void outputCPPCallInfo(CodeGenerator &cg, AnalysisResultPtr ar);
void outputCPPPreface(CodeGenerator &cg, AnalysisResultPtr ar);
void outputCPPHelperClassAlloc(CodeGenerator &cg,
AnalysisResultPtr ar);
/**
* Serialize the iface, not everything.
*/
@@ -389,7 +479,7 @@ public:
ReadWriteMutex &getInlineMutex() { return m_inlineMutex; }
DECLARE_EXTENDED_BOOST_TYPES(FunctionInfo);
DECLARE_BOOST_TYPES(FunctionInfo);
static void RecordFunctionInfo(std::string fname, FunctionScopePtr func);
@@ -397,11 +487,8 @@ public:
class FunctionInfo {
public:
explicit FunctionInfo(int rva = -1)
: m_maybeStatic(false)
, m_maybeRefReturn(false)
, m_refVarArg(rva)
{}
FunctionInfo(int rva = -1) : m_maybeStatic(false), m_maybeRefReturn(false),
m_refVarArg(rva) { }
bool isRefParam(int p) const {
if (m_refVarArg >= 0 && p >= m_refVarArg) return true;
@@ -431,6 +518,14 @@ public:
};
private:
bool outputCPPArrayCreate(CodeGenerator &cg,
AnalysisResultPtr ar,
int m_maxParam);
void outputCPPSubClassParam(CodeGenerator &cg,
AnalysisResultPtr ar,
ParameterExpressionPtr param);
void init(AnalysisResultConstPtr ar);
static StringToFunctionInfoPtrMap s_refParamInfo;
@@ -441,7 +536,7 @@ private:
std::vector<std::string> m_paramNames;
TypePtrVec m_paramTypes;
TypePtrVec m_paramTypeSpecs;
std::vector<std::string> m_paramDefaults;
std::vector<String> m_paramDefaults;
std::vector<std::string> m_paramDefaultTexts;
std::vector<bool> m_refs;
TypePtr m_returnType;
@@ -464,6 +559,7 @@ private:
unsigned m_magicMethod : 1;
unsigned m_system : 1;
unsigned m_inlineable : 1;
unsigned m_sep : 1;
unsigned m_containsThis : 1; // contains a usage of $this?
unsigned m_containsBareThis : 2; // $this outside object-context,
// 2 if in reference context
@@ -472,8 +568,10 @@ private:
unsigned m_inlineSameContext : 1;
unsigned m_contextSensitive : 1;
unsigned m_directInvoke : 1;
unsigned m_generator : 1;
unsigned m_async : 1;
unsigned m_needsRefTemp : 1;
unsigned m_needsObjTemp : 1;
unsigned m_needsCheckMem : 1;
unsigned m_closureGenerator : 1;
unsigned m_noLSB : 1;
unsigned m_nextLSB : 1;
unsigned m_hasTry : 1;
@@ -484,16 +582,15 @@ private:
StatementPtr m_stmtCloned; // cloned method body stmt
int m_inlineIndex;
FunctionOptPtr m_optFunction;
int outputCPPInvokeArgCountCheck(CodeGenerator &cg, AnalysisResultPtr ar,
bool ret, bool constructor, int maxCount);
ExpressionPtrVec m_retExprsToFix;
ExpressionListPtr m_closureVars;
ExpressionListPtr m_closureValues;
ReadWriteMutex m_inlineMutex;
unsigned m_nextID; // used when cloning generators for traits
int m_yieldLabelCount; // number of allocated yield labels
int m_yieldLabelGen; // generation counter for yield labels
std::list<FunctionScopeRawPtr> m_clonedTraitOuterScope;
};
///////////////////////////////////////////////////////////////////////////////
}
#endif // incl_HPHP_FUNCTION_SCOPE_H_
#endif // __FUNCTION_SCOPE_H__
-59
Ver Arquivo
@@ -1,59 +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_LABEL_SCOPE_H_
#define incl_HPHP_LABEL_SCOPE_H_
#include "hphp/compiler/hphp.h"
#include "hphp/util/deprecated/base.h"
#include <vector>
#include <string>
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
class Statement;
DECLARE_BOOST_TYPES(Statement);
class LabelScope {
public:
class LabelInfo {
public:
LabelInfo(StatementPtr s, const std::string& name)
: m_stmt(s), m_name(name) {}
StatementPtr getStatement() const { return m_stmt; }
const std::string& getName() const { return m_name; }
private:
StatementPtr m_stmt;
std::string m_name;
};
const std::vector<LabelInfo>& getLabels() const { return m_labels; }
void addLabel(StatementPtr s, const std::string& label) {
m_labels.push_back(LabelInfo(s, label));
}
private:
std::vector<LabelInfo> m_labels;
};
///////////////////////////////////////////////////////////////////////////////
}
#endif // incl_HPHP_LABEL_SCOPE_H_
-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
+34 -20
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -14,21 +14,20 @@
+----------------------------------------------------------------------+
*/
#include "hphp/compiler/analysis/live_dict.h"
#include <compiler/analysis/alias_manager.h>
#include <compiler/analysis/function_scope.h>
#include <compiler/analysis/live_dict.h>
#include <compiler/analysis/variable_table.h>
#include "hphp/compiler/analysis/alias_manager.h"
#include "hphp/compiler/analysis/function_scope.h"
#include "hphp/compiler/analysis/variable_table.h"
#include <compiler/expression/expression.h>
#include <compiler/expression/assignment_expression.h>
#include <compiler/expression/simple_variable.h>
#include "hphp/compiler/expression/expression.h"
#include "hphp/compiler/expression/assignment_expression.h"
#include "hphp/compiler/expression/simple_variable.h"
#include "hphp/compiler/statement/statement.h"
#include "hphp/compiler/statement/block_statement.h"
#include "hphp/compiler/statement/exp_statement.h"
#include "hphp/compiler/statement/method_statement.h"
#include "hphp/compiler/statement/statement_list.h"
#include <compiler/statement/statement.h>
#include <compiler/statement/block_statement.h>
#include <compiler/statement/exp_statement.h>
#include <compiler/statement/method_statement.h>
#include <compiler/statement/statement_list.h>
using namespace HPHP;
using std::vector;
@@ -327,10 +326,10 @@ void LiveDict::updateAccess(ExpressionPtr e) {
}
struct Colorizer {
explicit Colorizer(int w) : toNode(w) {}
Colorizer(int w) : toNode(w) {}
struct NodeInfo {
explicit NodeInfo(int index) : originalIndex(index), size(0), color(-1) {}
NodeInfo(int index) : originalIndex(index), size(0), color(-1) {}
int originalIndex;
int size;
int color;
@@ -360,7 +359,7 @@ struct Colorizer {
class NodeCmp {
public:
explicit NodeCmp(const Colorizer *c) : m_c(c) {}
NodeCmp(const Colorizer *c) : m_c(c) {}
bool operator()(int a, int b) {
const NodeInfo &n1 = m_c->nodes[a];
const NodeInfo &n2 = m_c->nodes[b];
@@ -462,10 +461,25 @@ bool LiveDict::color(TypePtr type) {
if (Type::SameType(type, e->getCPPType())) {
SimpleVariablePtr sv(
static_pointer_cast<SimpleVariable>(e));
bool isGenParam = false;
if (sv->getFunctionScope()->isGenerator()) {
// do not allow coalescing of symbols which are parameters/use vars
// in the generator (sym->isParameter() will be false b/c we are in
// the scope of the generator function)
FunctionScopeRawPtr origScope(sv->getFunctionScope()->getOrigGenFS());
assert(origScope);
Symbol *origSym =
origScope->getVariables()->getSymbol(sv->getName());
if (origSym &&
(origSym->isParameter() || origSym->isClosureVar())) {
isGenParam = true;
}
}
Symbol *sym = sv->getSymbol();
if (sym &&
!sym->isGlobal() &&
!sym->isParameter() &&
!isGenParam &&
!sym->isClosureVar() &&
!sym->isStatic() &&
!e->isThis()) {
@@ -609,8 +623,9 @@ public:
always_assert(e && e->is(Expression::KindOfSimpleVariable));
SimpleVariablePtr sv(static_pointer_cast<SimpleVariable>(e));
Symbol *sym = sv->getSymbol();
bool inGen = sv->getFunctionScope()->isGenerator();
if (!sym || sym->isGlobal() || sym->isStatic() || sym->isParameter() ||
sym->isClosureVar() || sv->isThis()) {
sym->isClosureVar() || sv->isThis() || inGen) {
continue;
}
@@ -623,8 +638,7 @@ public:
e->setLocation(sub->getLocation());
e->setBlockScope(sub->getScope());
ExpStatementPtr exp(
new ExpStatement(sub->getScope(), sub->getLabelScope(),
sub->getLocation(), e));
new ExpStatement(sub->getScope(), sub->getLocation(), e));
sl->insertElement(exp, ix);
}
}
+6 -6
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -14,10 +14,10 @@
+----------------------------------------------------------------------+
*/
#ifndef incl_HPHP_LIVE_DICT_H_
#define incl_HPHP_LIVE_DICT_H_
#ifndef __LIVE_DICT_H__
#define __LIVE_DICT_H__
#include "hphp/compiler/analysis/dictionary.h"
#include <compiler/analysis/dictionary.h>
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
@@ -26,7 +26,7 @@ namespace HPHP {
class LiveDict : public Dictionary {
public:
explicit LiveDict(AliasManager &am) : Dictionary(am) {}
LiveDict(AliasManager &am) : Dictionary(am) {}
/* Building the dictionary */
void build(MethodStatementPtr m);
void visit(ExpressionPtr e);
@@ -53,4 +53,4 @@ private:
///////////////////////////////////////////////////////////////////////////////
}
#endif // incl_HPHP_LIVE_DICT_H_
#endif // __LIVE_DICT_H__
+20 -23
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -14,17 +14,19 @@
+----------------------------------------------------------------------+
*/
#include "hphp/compiler/analysis/peephole.h"
#include "hphp/compiler/analysis/emitter.h"
#include "hphp/runtime/vm/preclass-emit.h"
#include "compiler/analysis/peephole.h"
#include "compiler/analysis/emitter.h"
namespace HPHP { namespace Compiler {
using VM::FuncEmitter;
using VM::UnitEmitter;
using VM::Offset;
static void collapseJmp(Offset* offsetPtr, Op* instr, Op* start) {
static void collapseJmp(Offset* offsetPtr, Opcode* instr, Opcode* start) {
if (offsetPtr) {
Op* dest = instr + *offsetPtr;
while (isUnconditionalJmp(*dest) && dest != instr) {
Opcode* dest = instr + *offsetPtr;
while (*dest == OpJmp && dest != instr) {
dest = start + instrJumpTarget(start, dest - start);
}
*offsetPtr = dest - instr;
@@ -43,10 +45,10 @@ Peephole::Peephole(UnitEmitter &ue, MetaInfoBuilder& metaInfo)
buildJumpTargets();
// Scan the bytecode linearly.
Op* start = (Op*)ue.m_bc;
Op* prev = start;
Op* cur = prev + instrLen(prev);
Op* end = start + ue.m_bclen;
Opcode* start = ue.m_bc;
Opcode* prev = start;
Opcode* cur = prev + instrLen(prev);
Opcode* end = start + ue.m_bclen;
/*
* TODO(1086005): we should try to minimize use of CGetL2/CGetL3.
@@ -91,10 +93,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:
@@ -162,19 +164,14 @@ void Peephole::buildJumpTargets() {
}
// all jump targets are targets
for (Offset pos = 0; pos < (Offset)m_ue.m_bclen;
pos += instrLen((Op*)&m_ue.m_bc[pos])) {
Op* instr = (Op*)&m_ue.m_bc[pos];
pos += instrLen(&m_ue.m_bc[pos])) {
Opcode* instr = &m_ue.m_bc[pos];
if (isSwitch(*instr)) {
foreachSwitchTarget(instr, [&](Offset& o) {
m_jumpTargets.insert(pos + o);
});
} else if (*instr == OpIterBreak) {
uint32_t veclen = *(uint32_t *)(instr + 1);
assert(veclen > 0);
Offset target = *(Offset *)((uint32_t *)(instr + 1) + 2 * veclen + 1);
m_jumpTargets.insert(pos + target);
} else {
Offset target = instrJumpTarget((Op*)m_ue.m_bc, pos);
Offset target = instrJumpTarget(m_ue.m_bc, pos);
if (target != InvalidAbsoluteOffset) {
m_jumpTargets.insert(target);
}
+7 -7
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -34,8 +34,8 @@
#ifndef incl_HPHP_COMPILER_ANALYSIS_PEEPHOLE_H_
#define incl_HPHP_COMPILER_ANALYSIS_PEEPHOLE_H_
#include "hphp/runtime/vm/unit.h"
#include "hphp/runtime/vm/func.h"
#include "runtime/vm/unit.h"
#include "runtime/vm/func.h"
namespace HPHP { namespace Compiler {
@@ -43,14 +43,14 @@ class MetaInfoBuilder;
class Peephole {
public:
Peephole(UnitEmitter& ue, MetaInfoBuilder& metaInfo);
Peephole(VM::UnitEmitter& ue, MetaInfoBuilder& metaInfo);
private:
void buildFuncTargets(FuncEmitter* fe);
void buildFuncTargets(VM::FuncEmitter* fe);
void buildJumpTargets();
UnitEmitter& m_ue;
hphp_hash_set<Offset> m_jumpTargets;
VM::UnitEmitter& m_ue;
hphp_hash_set<VM::Offset> m_jumpTargets;
};
}}
+29 -29
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -14,22 +14,22 @@
+----------------------------------------------------------------------+
*/
#include "hphp/compiler/analysis/ref_dict.h"
#include "hphp/compiler/analysis/alias_manager.h"
#include "hphp/compiler/analysis/function_scope.h"
#include <compiler/analysis/alias_manager.h>
#include <compiler/analysis/function_scope.h>
#include <compiler/analysis/ref_dict.h>
#include "hphp/compiler/expression/expression.h"
#include "hphp/compiler/expression/assignment_expression.h"
#include "hphp/compiler/expression/binary_op_expression.h"
#include "hphp/compiler/expression/simple_variable.h"
#include <compiler/expression/expression.h>
#include <compiler/expression/assignment_expression.h>
#include <compiler/expression/binary_op_expression.h>
#include <compiler/expression/simple_variable.h>
#include "hphp/compiler/statement/statement.h"
#include "hphp/compiler/statement/block_statement.h"
#include "hphp/compiler/statement/exp_statement.h"
#include "hphp/compiler/statement/method_statement.h"
#include "hphp/compiler/statement/statement_list.h"
#include <compiler/statement/statement.h>
#include <compiler/statement/block_statement.h>
#include <compiler/statement/exp_statement.h>
#include <compiler/statement/method_statement.h>
#include <compiler/statement/statement_list.h>
#include "hphp/parser/hphp.tab.hpp"
#include <util/parser/hphp.tab.hpp>
using namespace HPHP;
using std::vector;
@@ -74,10 +74,10 @@ void RefDict::visit(ExpressionPtr e) {
SimpleVariablePtr ptr(static_pointer_cast<SimpleVariable>(e));
if (ptr->isSuperGlobal() || ptr->isThis()) {
// don't both recording for super globals or this
// don't both recording for super globals or this
return;
}
// Good to go
if (m_am.insertForDict(e)) {
record(e);
@@ -129,7 +129,7 @@ void RefDict::updateParams() {
bool isRef;
if (sym->isParameter()) {
ExpressionListPtr methodParams = m_method_stmt->getParams();
ExpressionPtr paramExprPtr =
ExpressionPtr paramExprPtr =
(*methodParams)[sym->getParameterIndex()];
paramType = paramExprPtr->getType();
isRef = m_method_stmt->isRef(sym->getParameterIndex());
@@ -160,7 +160,7 @@ void RefDict::updateParams() {
void RefDict::updateAccess(ExpressionPtr e) {
always_assert(!e->getScope()->inPseudoMain());
int eid = e->getCanonID();
int context = e->getContext();
@@ -204,7 +204,7 @@ void RefDict::updateAccess(ExpressionPtr e) {
context & Expression::UnsetContext) {
BitOps::set_bit(eid, m_referenced, false);
BitOps::set_bit(eid, m_killed, true);
}
}
if (first_pass) return;
@@ -215,7 +215,7 @@ void RefDict::updateAccess(ExpressionPtr e) {
// we dealt with this node as a store expression
return;
}
int cls = e->getExprClass();
bool isRhsNeeded = false;
@@ -227,7 +227,7 @@ void RefDict::updateAccess(ExpressionPtr e) {
if (cls & Expression::Store) {
// we care about two cases here
switch (e->getKindOf()) {
case Expression::KindOfAssignmentExpression:
case Expression::KindOfAssignmentExpression:
// $x = ...
{
AssignmentExpressionPtr assign(
@@ -254,7 +254,7 @@ void RefDict::updateAccess(ExpressionPtr e) {
break;
}
}
bool isLhsSimpleVar = false;
bool isLhsDynamic = false;
bool isRefd = false;
@@ -343,20 +343,20 @@ void RefDict::updateAccess(ExpressionPtr e) {
// unset($x);
BitOps::set_bit(eid, m_obj, false);
BitOps::set_bit(eid, m_noobj, true);
} else if (isRefd ||
} else if (isRefd ||
((context & Expression::Declaration) == Expression::Declaration)) {
// if a simple variable has isRefd, then we need to mark it
// as potentially containing an object.
// also, if the simple variable is in global context
// also, if the simple variable is in global context
// then we also mark it as potentially containing an object
BitOps::set_bit(eid, m_obj, true);
BitOps::set_bit(eid, m_noobj, false);
}
}
}
if (isRefd) {
// do a scan for every simple variable referenced value
// in the dictionary and mark it as potentially
// do a scan for every simple variable referenced value
// in the dictionary and mark it as potentially
// containing an object (in the bit vector)
for (int i = size(); i--; ) {
if (ExpressionPtr e = get(i)) {
@@ -372,8 +372,8 @@ void RefDict::updateAccess(ExpressionPtr e) {
}
int RefDictWalker::after(ConstructRawPtr cp) {
if (SimpleVariableRawPtr s =
dynamic_pointer_cast<SimpleVariable>(cp)) {
if (SimpleVariableRawPtr s =
boost::dynamic_pointer_cast<SimpleVariable>(cp)) {
if (int id = s->getCanonID()) {
if (first_pass) {
if (s->isAvailable() && m_block->getBit(DataFlow::PRefIn, id)) {
+7 -7
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -14,17 +14,17 @@
+----------------------------------------------------------------------+
*/
#ifndef incl_HPHP_REF_DICT_H_
#define incl_HPHP_REF_DICT_H_
#ifndef __REF_DICT_H__
#define __REF_DICT_H__
#include "hphp/compiler/analysis/dictionary.h"
#include <compiler/analysis/dictionary.h>
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
class RefDict : public Dictionary {
public:
explicit RefDict(AliasManager &am) : Dictionary(am), first_pass(true) {}
RefDict(AliasManager &am) : Dictionary(am), first_pass(true) {}
/* Building the dictionary */
void build(MethodStatementPtr m);
@@ -52,7 +52,7 @@ private:
class RefDictWalker : public ControlFlowGraphWalker {
public:
explicit RefDictWalker(ControlFlowGraph *g) :
RefDictWalker(ControlFlowGraph *g) :
ControlFlowGraphWalker(g), first_pass(true) {}
void walk() { ControlFlowGraphWalker::walk(*this); }
int after(ConstructRawPtr cp);
@@ -63,4 +63,4 @@ private:
///////////////////////////////////////////////////////////////////////////////
}
#endif // incl_HPHP_REF_DICT_H_
#endif // __REF_DICT_H__
+47 -35
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -14,24 +14,23 @@
+----------------------------------------------------------------------+
*/
#include "hphp/compiler/analysis/symbol_table.h"
#include "hphp/compiler/analysis/type.h"
#include "hphp/compiler/analysis/analysis_result.h"
#include "hphp/compiler/analysis/class_scope.h"
#include "hphp/compiler/analysis/file_scope.h"
#include "hphp/compiler/analysis/function_scope.h"
#include <compiler/analysis/symbol_table.h>
#include <compiler/analysis/type.h>
#include <compiler/analysis/analysis_result.h>
#include <compiler/analysis/class_scope.h>
#include <compiler/analysis/file_scope.h>
#include <compiler/analysis/function_scope.h>
#include "hphp/compiler/expression/assignment_expression.h"
#include "hphp/compiler/expression/constant_expression.h"
#include "hphp/compiler/expression/expression_list.h"
#include "hphp/compiler/expression/parameter_expression.h"
#include "hphp/compiler/expression/simple_variable.h"
#include <compiler/expression/constant_expression.h>
#include <compiler/expression/expression_list.h>
#include <compiler/expression/parameter_expression.h>
#include <compiler/expression/simple_variable.h>
#include "hphp/runtime/base/class-info.h"
#include "hphp/runtime/base/complex-types.h"
#include "hphp/runtime/base/variable-serializer.h"
#include <runtime/base/class_info.h>
#include <runtime/base/complex_types.h>
#include <runtime/base/variable_serializer.h>
#include "hphp/util/logger.h"
#include <util/logger.h>
using namespace HPHP;
@@ -65,13 +64,13 @@ TypePtr Symbol::setType(AnalysisResultConstPtr ar, BlockScopeRawPtr scope,
// at this point, you *must* have a lock (if you are user scope)
if (scope->is(BlockScope::FunctionScope)) {
FunctionScopeRawPtr f =
static_pointer_cast<FunctionScope>(scope);
boost::static_pointer_cast<FunctionScope>(scope);
if (f->isUserFunction()) {
f->getInferTypesMutex().assertOwnedBySelf();
}
} else if (scope->is(BlockScope::ClassScope)) {
ClassScopeRawPtr c =
static_pointer_cast<ClassScope>(scope);
boost::static_pointer_cast<ClassScope>(scope);
if (c->isUserClass()) {
c->getInferTypesMutex().assertOwnedBySelf();
}
@@ -285,9 +284,9 @@ void Symbol::serializeParam(JSON::DocTarget::OutputStream &out) const {
assert(valueExp);
const string &init = ExtractInitializer(out.analysisResult(), valueExp);
if (!init.empty()) out << init;
else out << JSON::Null();
else out << JSON::Null;
} else {
out << JSON::Null();
out << JSON::Null;
}
ms.done();
@@ -296,18 +295,20 @@ void Symbol::serializeParam(JSON::DocTarget::OutputStream &out) const {
static inline std::string ExtractDocComment(ExpressionPtr e) {
if (!e) return "";
switch (e->getKindOf()) {
case Expression::KindOfAssignmentExpression: {
AssignmentExpressionPtr ae(static_pointer_cast<AssignmentExpression>(e));
return ExtractDocComment(ae->getVariable());
}
case Expression::KindOfSimpleVariable: {
SimpleVariablePtr sv(static_pointer_cast<SimpleVariable>(e));
return sv->getDocComment();
}
case Expression::KindOfConstantExpression: {
ConstantExpressionPtr ce(static_pointer_cast<ConstantExpression>(e));
return ce->getDocComment();
}
case Expression::KindOfAssignmentExpression:
return ExtractDocComment(e->getNthExpr(0));
case Expression::KindOfSimpleVariable:
{
SimpleVariablePtr sv(
static_pointer_cast<SimpleVariable>(e));
return sv->getDocComment();
}
case Expression::KindOfConstantExpression:
{
ConstantExpressionPtr ce(
static_pointer_cast<ConstantExpression>(e));
return ce->getDocComment();
}
default: return "";
}
return "";
@@ -336,9 +337,9 @@ void Symbol::serializeClassVar(JSON::DocTarget::OutputStream &out) const {
assert(initExp);
const string &init = ExtractInitializer(out.analysisResult(), initExp);
if (!init.empty()) out << init;
else out << JSON::Null();
else out << JSON::Null;
} else {
out << JSON::Null();
out << JSON::Null;
}
const string &docs = ExtractDocComment(
@@ -520,6 +521,17 @@ ConstructPtr SymbolTable::getValue(const std::string &name) const {
return ConstructPtr();
}
void SymbolTable::setSepExtension(const std::string &name) {
genSymbol(name, m_const)->setSep();
}
bool SymbolTable::isSepExtension(const std::string &name) const {
if (const Symbol *sym = getSymbol(name)) {
return sym->isSep();
}
return false;
}
TypePtr SymbolTable::setType(AnalysisResultConstPtr ar, const std::string &name,
TypePtr type, bool coerced) {
return setType(ar, genSymbol(name, m_const), type, coerced);
@@ -584,7 +596,7 @@ void SymbolTable::countTypes(std::map<std::string, int> &counts) {
}
string SymbolTable::getEscapedText(Variant v, int &len) {
VariableSerializer vs(VariableSerializer::Type::Serialize);
VariableSerializer vs(VariableSerializer::Serialize);
String str = vs.serialize(v, true);
len = str.length();
string output = Util::escapeStringForCPP(str.data(), len);
+20 -20
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -14,14 +14,13 @@
+----------------------------------------------------------------------+
*/
#ifndef incl_HPHP_SYMBOL_TABLE_H_
#define incl_HPHP_SYMBOL_TABLE_H_
#ifndef __SYMBOL_TABLE_H__
#define __SYMBOL_TABLE_H__
#include "hphp/compiler/hphp.h"
#include "hphp/compiler/json.h"
#include "hphp/util/util.h"
#include "hphp/util/lock.h"
#include "hphp/util/hash-map-typedefs.h"
#include <compiler/hphp.h>
#include <util/json.h>
#include <util/util.h>
#include <util/lock.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);
@@ -75,7 +74,9 @@ public:
void setReplaced() { m_flags.m_replaced = true; }
bool valueSet() const { return m_flags.m_value_set; }
bool isSystem() const { return m_flags.m_system; }
bool isSep() const { return m_flags.m_sep; }
void setSystem() { m_flags.m_system = true; }
void setSep() { m_flags.m_sep = true; }
bool isConstant() const { return m_flags.m_constant; }
void setConstant() { m_flags.m_constant = true; }
@@ -184,7 +185,7 @@ private:
std::string m_name;
unsigned int m_hash;
union {
uint32_t m_flags_val;
unsigned m_flags_val;
struct {
/* internal */
unsigned m_declaration_set : 1;
@@ -195,6 +196,7 @@ private:
/* common */
unsigned m_system : 1;
unsigned m_sep : 1;
/* ConstantTable */
unsigned m_dynamic : 1;
@@ -225,13 +227,7 @@ private:
unsigned m_stashedVal : 1;
unsigned m_reseated : 1;
} m_flags;
};
static_assert(
sizeof(m_flags_val) == sizeof(m_flags),
"m_flags_val must cover all the flags");
ConstructPtr m_declaration;
ConstructPtr m_value;
TypePtr m_coerced;
@@ -248,7 +244,7 @@ private:
class SymParamWrapper : public JSON::DocTarget::ISerializable {
public:
explicit SymParamWrapper(const Symbol* sym) : m_sym(sym) {
SymParamWrapper(const Symbol* sym) : m_sym(sym) {
assert(sym);
}
virtual void serialize(JSON::DocTarget::OutputStream &out) const {
@@ -260,7 +256,7 @@ private:
class SymClassVarWrapper : public JSON::DocTarget::ISerializable {
public:
explicit SymClassVarWrapper(const Symbol* sym) : m_sym(sym) {
SymClassVarWrapper(const Symbol* sym) : m_sym(sym) {
assert(sym);
}
virtual void serialize(JSON::DocTarget::OutputStream &out) const {
@@ -273,7 +269,7 @@ private:
/**
* Base class of VariableTable and ConstantTable.
*/
class SymbolTable : public std::enable_shared_from_this<SymbolTable>,
class SymbolTable : public boost::enable_shared_from_this<SymbolTable>,
public JSON::CodeError::ISerializable {
public:
static Mutex AllSymbolTablesMutex;
@@ -339,6 +335,10 @@ public:
ConstructPtr getDeclaration(const std::string &name) const;
ConstructPtr getValue(const std::string &name) const;
/* Whether this constant is brought in by a separable extension */
void setSepExtension(const std::string &name);
bool isSepExtension(const std::string &name) const;
/**
* How big of a hash table for generate C++ switch statements.
*/
@@ -382,4 +382,4 @@ private:
///////////////////////////////////////////////////////////////////////////////
}
#endif // incl_HPHP_SYMBOL_TABLE_H_
#endif // __SYMBOL_TABLE_H__
+117 -69
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -14,14 +14,12 @@
+----------------------------------------------------------------------+
*/
#include "hphp/compiler/analysis/type.h"
#include "hphp/compiler/code_generator.h"
#include "hphp/compiler/analysis/analysis_result.h"
#include "hphp/compiler/analysis/class_scope.h"
#include "hphp/compiler/analysis/file_scope.h"
#include "hphp/compiler/expression/expression.h"
#include "hphp/runtime/base/builtin-functions.h"
#include "hphp/runtime/vm/runtime.h"
#include <compiler/analysis/type.h>
#include <compiler/code_generator.h>
#include <compiler/analysis/analysis_result.h>
#include <compiler/analysis/class_scope.h>
#include <compiler/analysis/file_scope.h>
#include <compiler/expression/expression.h>
#include <boost/format.hpp>
using namespace HPHP;
@@ -37,7 +35,6 @@ TypePtr Type::Double (new Type(Type::KindOfDouble ));
TypePtr Type::String (new Type(Type::KindOfString ));
TypePtr Type::Array (new Type(Type::KindOfArray ));
TypePtr Type::Object (new Type(Type::KindOfObject ));
TypePtr Type::Resource (new Type(Type::KindOfResource ));
TypePtr Type::Variant (new Type(Type::KindOfVariant ));
TypePtr Type::Numeric (new Type(Type::KindOfNumeric ));
@@ -52,65 +49,38 @@ TypePtr Type::Any (new Type(Type::KindOfAny ));
TypePtr Type::Some (new Type(Type::KindOfSome ));
Type::TypePtrMap Type::s_TypeHintTypes;
Type::TypePtrMap Type::s_HHTypeHintTypes;
void Type::InitTypeHintMap() {
assert(s_TypeHintTypes.empty());
assert(s_HHTypeHintTypes.empty());
s_TypeHintTypes["array"] = Type::Array;
s_TypeHintTypes["resource"] = Type::Resource;
s_TypeHintTypes["callable"] = Type::Variant;
s_HHTypeHintTypes["array"] = Type::Array;
s_HHTypeHintTypes["bool"] = Type::Boolean;
s_HHTypeHintTypes["boolean"] = Type::Boolean;
s_HHTypeHintTypes["int"] = Type::Int64;
s_HHTypeHintTypes["integer"] = Type::Int64;
s_HHTypeHintTypes["real"] = Type::Double;
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;
if (Option::EnableHipHopSyntax) {
s_TypeHintTypes["bool"] = Type::Boolean;
s_TypeHintTypes["boolean"] = Type::Boolean;
s_TypeHintTypes["int"] = Type::Int64;
s_TypeHintTypes["integer"] = Type::Int64;
s_TypeHintTypes["real"] = Type::Double;
s_TypeHintTypes["double"] = Type::Double;
s_TypeHintTypes["float"] = Type::Double;
s_TypeHintTypes["string"] = Type::String;
}
}
const Type::TypePtrMap &Type::GetTypeHintTypes(bool hhType) {
return hhType ? s_HHTypeHintTypes : s_TypeHintTypes;
const Type::TypePtrMap &Type::GetTypeHintTypes() {
return s_TypeHintTypes;
}
void Type::ResetTypeHintTypes() {
s_TypeHintTypes.clear();
s_HHTypeHintTypes.clear();
}
TypePtr Type::CreateObjectType(const std::string &clsname) {
// For interfaces that support primitive types, we're pessimistic and
// we treat it as a Variant
if (interface_supports_array(clsname) ||
interface_supports_string(clsname) ||
interface_supports_int(clsname) ||
interface_supports_double(clsname)) {
return Type::Variant;
}
return TypePtr(new Type(KindOfObject, clsname));
TypePtr Type::CreateObjectType(const std::string &classname) {
return TypePtr(new Type(KindOfObject, classname));
}
TypePtr Type::GetType(KindOf kindOf, const std::string &clsname /* = "" */) {
TypePtr Type::GetType(KindOf kindOf,
const std::string &clsname /* = "" */) {
assert(kindOf);
if (!clsname.empty()) {
// For interfaces that support primitive types we're pessimistic and
// we treat it as a Variant
if (interface_supports_array(clsname) ||
interface_supports_string(clsname) ||
interface_supports_int(clsname) ||
interface_supports_double(clsname)) {
return Type::Variant;
}
return TypePtr(new Type(kindOf, clsname));
}
if (!clsname.empty()) return TypePtr(new Type(kindOf, clsname));
switch (kindOf) {
case KindOfBoolean: return Type::Boolean;
@@ -121,7 +91,6 @@ TypePtr Type::GetType(KindOf kindOf, const std::string &clsname /* = "" */) {
case KindOfArray: return Type::Array;
case KindOfVariant: return Type::Variant;
case KindOfObject: return Type::Object;
case KindOfResource: return Type::Resource;
case KindOfNumeric: return Type::Numeric;
case KindOfPrimitive: return Type::Primitive;
case KindOfPlusOperand: return Type::PlusOperand;
@@ -208,7 +177,6 @@ bool Type::IsMappedToVariant(TypePtr t) {
case KindOfString :
case KindOfArray :
case KindOfObject :
case KindOfResource:
return false;
default: break;
}
@@ -277,8 +245,7 @@ TypePtr Type::Coerce(AnalysisResultConstPtr ar, TypePtr type1, TypePtr type2) {
if (type1->m_kindOf == KindOfVoid &&
(type2->m_kindOf == KindOfString ||
type2->m_kindOf == KindOfArray ||
type2->m_kindOf == KindOfObject ||
type2->m_kindOf == KindOfResource)) {
type2->m_kindOf == KindOfObject)) {
return type2;
}
if (type2->m_kindOf == KindOfSome ||
@@ -413,7 +380,6 @@ bool Type::HasFastCastMethod(TypePtr t) {
case Type::KindOfString:
case Type::KindOfArray:
case Type::KindOfObject:
case Type::KindOfResource:
return true;
default: break;
}
@@ -459,9 +425,6 @@ string Type::GetFastCastMethod(
case Type::KindOfObject:
type = "Obj";
break;
case Type::KindOfResource:
type = "Res";
break;
default:
type = ""; // make the compiler happy
assert(false);
@@ -557,13 +520,11 @@ bool Type::isSpecificObject() const {
}
bool Type::isNonConvertibleType() const {
return m_kindOf == KindOfObject || m_kindOf == KindOfResource ||
m_kindOf == KindOfArray;
return m_kindOf == KindOfObject || m_kindOf == KindOfArray;
}
bool Type::isNoObjectInvolved() const {
if (couldBe(KindOfObject)
|| couldBe(KindOfResource)
|| couldBe(KindOfArray))
return false;
else
@@ -628,6 +589,37 @@ ClassScopePtr Type::getClass(AnalysisResultConstPtr ar,
return cls;
}
string Type::getCPPDecl(AnalysisResultConstPtr ar,
BlockScopeRawPtr scope,
CodeGenerator *cg /* = 0 */) {
switch (m_kindOf) {
case KindOfBoolean: return "bool";
case KindOfInt32: return "int";
case KindOfInt64: return "int64";
case KindOfDouble: return "double";
case KindOfString: return "String";
case KindOfArray: return "Array";
case KindOfObject:{
ClassScopePtr cls(getClass(ar, scope));
if (!cls) return "Object";
if (cg && cg->isFileOrClassHeader() && scope) {
if (scope->getContainingClass()) {
scope->getContainingClass()->addUsedClassHeader(cls);
} else if (scope->getContainingFile()) {
scope->getContainingFile()->addUsedClassHeader(cls);
}
}
return Option::SmartPtrPrefix + cls->getId();
}
case KindOfNumeric: return "Numeric";
case KindOfPrimitive: return "Primitive";
case KindOfPlusOperand: return "PlusOperand";
case KindOfSequence: return "Sequence";
default:
return "Variant";
}
}
DataType Type::getDataType() const {
switch (m_kindOf) {
case KindOfBoolean: return HPHP::KindOfBoolean;
@@ -637,7 +629,6 @@ DataType Type::getDataType() const {
case KindOfString: return HPHP::KindOfString;
case KindOfArray: return HPHP::KindOfArray;
case KindOfObject: return HPHP::KindOfObject;
case KindOfResource: return HPHP::KindOfResource;
case KindOfNumeric:
case KindOfPrimitive:
case KindOfPlusOperand:
@@ -655,11 +646,70 @@ DataType Type::getHhvmDataType() const {
}
}
void Type::outputCPPDecl(CodeGenerator &cg, AnalysisResultConstPtr ar,
BlockScopeRawPtr scope) {
cg_print(getCPPDecl(ar, scope, &cg).c_str());
}
void Type::outputCPPFastObjectCast(CodeGenerator &cg,
AnalysisResultConstPtr ar,
BlockScopeRawPtr scope,
bool isConst) {
assert(isSpecificObject());
ClassScopePtr cls(getClass(ar, scope));
assert(cls);
const string &cppClsName = cls->getId();
cg_printf("(%s%s%s&)",
isConst ? "const " : "",
Option::SmartPtrPrefix,
cppClsName.c_str());
}
void Type::outputCPPCast(CodeGenerator &cg, AnalysisResultConstPtr ar,
BlockScopeRawPtr scope) {
switch (m_kindOf) {
case KindOfBoolean: cg_printf("toBoolean"); break;
case KindOfInt32: cg_printf("toInt32"); break;
case KindOfInt64: cg_printf("toInt64"); break;
case KindOfDouble: cg_printf("toDouble"); break;
case KindOfString: cg_printf("toString"); break;
case KindOfArray: cg_printf("toArray"); break;
case KindOfNumeric: cg_printf("Numeric"); break;
case KindOfPrimitive: cg_printf("Primitive"); break;
case KindOfPlusOperand: cg_printf("PlusOperand"); break;
case KindOfSequence: cg_printf("Sequence"); break;
case KindOfObject: {
ClassScopePtr cls(getClass(ar, scope));
if (!cls) {
cg_printf("toObject");
} else {
cg_printf("%s%s", Option::SmartPtrPrefix, cls->getId().c_str());
}
break;
}
default:
cg_printf("Variant");
break;
}
}
const char *Type::getCPPInitializer() {
switch (m_kindOf) {
case KindOfBoolean: return "false";
case KindOfInt32:
case KindOfInt64: return "0";
case KindOfNumeric:
case KindOfPrimitive:
case KindOfPlusOperand: return "0";
case KindOfDouble: return "0.0";
default: return nullptr;
}
}
std::string Type::getPHPName() {
switch (m_kindOf) {
case KindOfArray: return "array";
case KindOfObject: return m_name;
case KindOfResource: return "resource";
default: break;
}
return "";
@@ -677,7 +727,6 @@ std::string Type::toString() const {
case KindOfSome: return "Some";
case KindOfAny: return "Any";
case KindOfObject: return string("Object - ") + m_name;
case KindOfResource: return "Resource";
case KindOfNumeric: return "Numeric";
case KindOfPrimitive: return "Primitive";
case KindOfPlusOperand: return "PlusOperand";
@@ -726,7 +775,6 @@ void Type::serialize(JSON::DocTarget::OutputStream &out) const {
}
break;
}
case KindOfResource: s = "resource"; break;
case KindOfNumeric: s = "numeric"; break;
case KindOfPrimitive: s = "primitive"; break;
case KindOfPlusOperand: s = "any"; break;
+36 -13
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -14,13 +14,13 @@
+----------------------------------------------------------------------+
*/
#ifndef incl_HPHP_TYPE_H_
#define incl_HPHP_TYPE_H_
#ifndef __TYPE_H__
#define __TYPE_H__
#include "hphp/compiler/hphp.h"
#include "hphp/compiler/json.h"
#include "hphp/util/functional.h"
#include "hphp/runtime/base/types.h"
#include <compiler/hphp.h>
#include <util/json.h>
#include <util/case_insensitive.h>
#include <runtime/base/types.h>
class TestCodeRun;
@@ -53,7 +53,6 @@ public:
static const KindOf KindOfString = 0x0080;
static const KindOf KindOfArray = 0x0100;
static const KindOf KindOfObject = 0x0200; // with classname
static const KindOf KindOfResource = 0x0400;
static const KindOf KindOfVariant = 0xFFFF;
/* This bit tells coerce that if the other type
@@ -89,7 +88,6 @@ public:
static TypePtr String;
static TypePtr Array;
static TypePtr Object;
static TypePtr Resource;
static TypePtr Variant;
static TypePtr Numeric;
@@ -104,7 +102,7 @@ public:
static TypePtr Some;
typedef hphp_string_imap<TypePtr> TypePtrMap;
static const TypePtrMap &GetTypeHintTypes(bool hhType);
static const TypePtrMap &GetTypeHintTypes();
/**
* Uncertain types: types that are ambiguous yet.
@@ -203,7 +201,7 @@ public:
/**
* KindOf testing.
*/
explicit Type(KindOf kindOf);
Type(KindOf kindOf);
bool is(KindOf kindOf) const { return m_kindOf == kindOf;}
bool isExactType() const { return IsExactType(m_kindOf); }
bool mustBe(KindOf kindOf) const { return !(m_kindOf & ~kindOf); }
@@ -227,9 +225,35 @@ public:
ClassScopePtr getClass(AnalysisResultConstPtr ar,
BlockScopeRawPtr scope) const;
/**
* Generate type specifier in C++.
*/
std::string getCPPDecl(AnalysisResultConstPtr ar,
BlockScopeRawPtr scope,
CodeGenerator *cg = 0);
DataType getDataType() const;
DataType getHhvmDataType() const;
void outputCPPDecl(CodeGenerator &cg, AnalysisResultConstPtr ar,
BlockScopeRawPtr scope);
/**
* Generate type conversion in C++.
*/
void outputCPPFastObjectCast(CodeGenerator &cg,
AnalysisResultConstPtr ar,
BlockScopeRawPtr scope,
bool isConst);
void outputCPPCast(CodeGenerator &cg, AnalysisResultConstPtr ar,
BlockScopeRawPtr scope);
/**
* Generate variable initialization code.
*/
const char *getCPPInitializer();
/**
* Type hint names in PHP.
*/
@@ -269,7 +293,6 @@ private:
static void ResetTypeHintTypes();
static TypePtrMap s_TypeHintTypes;
static TypePtrMap s_HHTypeHintTypes;
const KindOf m_kindOf;
const std::string m_name;
@@ -277,4 +300,4 @@ private:
///////////////////////////////////////////////////////////////////////////////
}
#endif // incl_HPHP_TYPE_H_
#endif // __TYPE_H__
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+61 -10
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -14,13 +14,12 @@
+----------------------------------------------------------------------+
*/
#ifndef incl_HPHP_VARIABLE_TABLE_H_
#define incl_HPHP_VARIABLE_TABLE_H_
#ifndef __VARIABLE_TABLE_H__
#define __VARIABLE_TABLE_H__
#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"
#include <compiler/analysis/symbol_table.h>
#include <compiler/statement/statement.h>
#include <compiler/analysis/class_scope.h>
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
@@ -101,7 +100,7 @@ public:
}
public:
explicit VariableTable(BlockScope &blockScope);
VariableTable(BlockScope &blockScope);
/**
* Get/set attributes.
@@ -138,6 +137,15 @@ public:
virtual bool isInherited(const std::string &name) const;
const char *getVariablePrefix(const std::string &name) const;
const char *getVariablePrefix(const Symbol *sym) const;
std::string getVariableName(AnalysisResultConstPtr ar,
const std::string &name) const;
std::string getVariableName(AnalysisResultConstPtr ar,
const Symbol *sym) const;
std::string getGlobalVariableName(AnalysisResultConstPtr ar,
const std::string &name) const;
void getLocalVariableNames(std::vector<std::string> &syms) const;
/**
@@ -281,6 +289,33 @@ public:
* Generate all variable declarations for this symbol table.
*/
void outputPHP(CodeGenerator &cg, AnalysisResultPtr ar);
void outputCPP(CodeGenerator &cg, AnalysisResultPtr ar);
bool outputCPPPropertyDecl(CodeGenerator &cg, AnalysisResultPtr ar,
bool dynamicObject = false);
void outputCPPClassMap(CodeGenerator &cg, AnalysisResultPtr ar);
void outputCPPStaticVariables(CodeGenerator &cg, AnalysisResultPtr ar);
void outputCPPStaticLocals(CodeGenerator &cg, AnalysisResultPtr ar,
bool forInitList);
void outputCPPGlobalVariablesDtorIncludes(CodeGenerator &cg,
AnalysisResultPtr ar);
void outputCPPGlobalVariablesDtor(CodeGenerator &cg);
void outputCPPGVHashTableGetImpl(CodeGenerator &cg, AnalysisResultPtr ar);
void outputCPPGlobalVariablesGetImpl(CodeGenerator &cg,
AnalysisResultPtr ar);
void outputCPPGVHashTableExists(CodeGenerator &cg, AnalysisResultPtr ar);
void outputCPPGlobalVariablesExists(CodeGenerator &cg,
AnalysisResultPtr ar);
void outputCPPGVHashTableGetIndex(CodeGenerator &cg,
AnalysisResultPtr ar);
void outputCPPGlobalVariablesGetIndex(CodeGenerator &cg,
AnalysisResultPtr ar);
void outputCPPGlobalVariablesMethods(CodeGenerator &cg,
AnalysisResultPtr ar);
void collectCPPGlobalSymbols(StringPairSetVec &symbols, CodeGenerator &cg,
AnalysisResultPtr ar);
/**
* Whether or not the specified jump table is empty.
*/
@@ -297,7 +332,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
@@ -348,10 +383,26 @@ private:
TypePtr type, bool coerce);
virtual void dumpStats(std::map<std::string, int> &typeCounts);
void outputCPPGlobalVariablesHeader(CodeGenerator &cg,
AnalysisResultPtr ar);
void outputCPPGlobalVariablesImpl(CodeGenerator &cg, AnalysisResultPtr ar);
void outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar);
void outputCPPVariableTable(CodeGenerator &cg, AnalysisResultPtr ar,
const char *paramPrefix);
bool outputCPPJumpTable(CodeGenerator &cg, AnalysisResultPtr ar,
const char *prefix, bool defineHash,
bool variantOnly, StaticSelection staticVar,
JumpTableType type = JumpReturn,
PrivateSelection privateVar = NonPrivate,
bool *declaredGlobals = nullptr);
bool outputCPPPrivateSelector(CodeGenerator &cg, AnalysisResultPtr ar,
const char *op, const char *args);
void outputCPPVariableInit(CodeGenerator &cg, AnalysisResultPtr ar,
bool inPseudoMain, const std::string &name);
void checkSystemGVOrder(SymbolSet &variants, unsigned int max);
};
///////////////////////////////////////////////////////////////////////////////
}
#endif // incl_HPHP_VARIABLE_TABLE_H_
#endif // __VARIABLE_TABLE_H__
+456 -269
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -14,27 +14,24 @@
+----------------------------------------------------------------------+
*/
#include "hphp/compiler/builtin_symbols.h"
#include "hphp/compiler/analysis/analysis_result.h"
#include "hphp/compiler/statement/statement_list.h"
#include "hphp/compiler/analysis/type.h"
#include "hphp/compiler/analysis/function_scope.h"
#include "hphp/compiler/analysis/class_scope.h"
#include "hphp/compiler/expression/modifier_expression.h"
#include "hphp/compiler/expression/simple_function_call.h"
#include "hphp/compiler/option.h"
#include "hphp/compiler/parser/parser.h"
#include "hphp/compiler/analysis/file_scope.h"
#include "hphp/compiler/analysis/variable_table.h"
#include "hphp/compiler/analysis/constant_table.h"
#include "hphp/parser/hphp.tab.hpp"
#include "hphp/runtime/base/class-info.h"
#include "hphp/runtime/base/program-functions.h"
#include "hphp/runtime/base/array-iterator.h"
#include "hphp/runtime/base/execution-context.h"
#include "hphp/runtime/base/thread-init-fini.h"
#include "hphp/util/logger.h"
#include "hphp/util/util.h"
#include <compiler/builtin_symbols.h>
#include <compiler/analysis/analysis_result.h>
#include <compiler/statement/statement_list.h>
#include <compiler/analysis/type.h>
#include <compiler/analysis/function_scope.h>
#include <compiler/analysis/class_scope.h>
#include <compiler/expression/modifier_expression.h>
#include <compiler/option.h>
#include <compiler/parser/parser.h>
#include <compiler/analysis/file_scope.h>
#include <compiler/analysis/variable_table.h>
#include <compiler/analysis/constant_table.h>
#include <util/parser/hphp.tab.hpp>
#include <runtime/base/class_info.h>
#include <runtime/base/program_functions.h>
#include <runtime/base/array/array_iterator.h>
#include <util/logger.h>
#include <util/util.h>
#include <dlfcn.h>
using namespace HPHP;
@@ -49,8 +46,39 @@ using namespace HPHP;
///////////////////////////////////////////////////////////////////////////////
bool BuiltinSymbols::Loaded = false;
bool BuiltinSymbols::NoSuperGlobals = false;
StringBag BuiltinSymbols::s_strings;
AnalysisResultPtr BuiltinSymbols::s_systemAr;
namespace HPHP {
#define EXT_TYPE 4
#include <system/ext.inc>
#undef EXT_TYPE
}
const char *BuiltinSymbols::ExtensionFunctions[] = {
#define S(n) (const char *)n
#define T(t) (const char *)Type::KindOf ## t
#define EXT_TYPE 0
#include <system/ext.inc>
nullptr,
};
#undef EXT_TYPE
const char *BuiltinSymbols::ExtensionConsts[] = {
#define EXT_TYPE 1
#include <system/ext.inc>
nullptr,
};
#undef EXT_TYPE
const char *BuiltinSymbols::ExtensionClasses[] = {
#define EXT_TYPE 2
#include <system/ext.inc>
nullptr,
};
#undef EXT_TYPE
StringToFunctionScopePtrMap BuiltinSymbols::s_functions;
const char *const BuiltinSymbols::GlobalNames[] = {
"HTTP_RAW_POST_DATA",
@@ -72,7 +100,6 @@ const char *BuiltinSymbols::SystemClasses[] = {
"exception",
"arrayaccess",
"iterator",
"collections",
"reflection",
"splobjectstorage",
"directory",
@@ -85,7 +112,11 @@ const char *BuiltinSymbols::SystemClasses[] = {
nullptr
};
StringToClassScopePtrMap BuiltinSymbols::s_classes;
VariableTablePtr BuiltinSymbols::s_variables;
ConstantTablePtr BuiltinSymbols::s_constants;
StringToTypePtrMap BuiltinSymbols::s_superGlobals;
void *BuiltinSymbols::s_handle_main = nullptr;
///////////////////////////////////////////////////////////////////////////////
@@ -94,307 +125,462 @@ int BuiltinSymbols::NumGlobalNames() {
sizeof(BuiltinSymbols::GlobalNames[0]);
}
static TypePtr typePtrFromDataType(DataType dt, TypePtr unknown) {
switch (dt) {
case KindOfNull: return Type::Null;
case KindOfBoolean: return Type::Boolean;
case KindOfInt64: return Type::Int64;
case KindOfDouble: return Type::Double;
case KindOfString: return Type::String;
case KindOfArray: return Type::Array;
case KindOfObject: return Type::Object;
case KindOfResource: return Type::Resource;
case KindOfUnknown:
default:
return unknown;
void BuiltinSymbols::ParseExtFunctions(AnalysisResultPtr ar, const char **p,
bool sep) {
while (*p) {
FunctionScopePtr f = ParseExtFunction(ar, p);
if (sep) {
f->setSepExtension();
}
assert(!s_functions[f->getName()]);
s_functions[f->getName()] = f;
}
}
const StaticString
s_fb_call_user_func_safe("fb_call_user_func_safe"),
s_fb_call_user_func_safe_return("fb_call_user_func_safe_return"),
s_fb_call_user_func_array_safe("fb_call_user_func_array_safe"),
s_is_callable("is_callable"),
s_call_user_func_array("call_user_func_array");
FunctionScopePtr BuiltinSymbols::ImportFunctionScopePtr(AnalysisResultPtr ar,
ClassInfo *cls, ClassInfo::MethodInfo *method) {
int attrs = method->attribute;
bool isMethod = cls != ClassInfo::GetSystem();
FunctionScopePtr f(new FunctionScope(isMethod,
method->name.data(),
attrs & ClassInfo::IsReference));
int reqCount = 0, totalCount = 0;
for(auto it = method->parameters.begin();
it != method->parameters.end(); ++it) {
const ClassInfo::ParameterInfo *pinfo = *it;
if (!pinfo->value || !pinfo->value[0]) {
++reqCount;
}
++totalCount;
}
f->setParamCounts(ar, reqCount, totalCount);
int idx = 0;
for(auto it = method->parameters.begin();
it != method->parameters.end(); ++it, ++idx) {
const ClassInfo::ParameterInfo *pinfo = *it;
f->setParamName(idx, pinfo->name);
if (pinfo->attribute & ClassInfo::IsReference) {
f->setRefParam(idx);
}
f->setParamType(ar, idx, typePtrFromDataType(pinfo->argType, Type::Any));
if (pinfo->valueLen) {
f->setParamDefault(idx, pinfo->value, pinfo->valueLen,
std::string(pinfo->valueText, pinfo->valueTextLen));
void BuiltinSymbols::ParseExtConsts(AnalysisResultPtr ar, const char **p,
bool sep) {
while (*p) {
const char *name = *p++;
TypePtr type = ParseType(p);
s_constants->add(name, type, ExpressionPtr(), ar, ConstructPtr());
if (sep) {
s_constants->setSepExtension(name);
}
}
}
if (method->returnType != KindOfNull) {
f->setReturnType(ar, typePtrFromDataType(method->returnType,
Type::Variant));
TypePtr BuiltinSymbols::ParseType(const char **&p) {
const char *clsname = nullptr;
Type::KindOf ktype = (Type::KindOf)(long)(*p++);
if (ktype == CLASS_TYPE) {
clsname = *p++;
}
TypePtr type;
if (clsname) {
type = Type::CreateObjectType(clsname);
} else if (ktype != Type::KindOfVoid) {
type = Type::GetType(ktype);
}
return type;
}
void BuiltinSymbols::ParseExtClasses(AnalysisResultPtr ar, const char **p,
bool sep) {
while (*p) {
// Parse name
const char *cname = *p++;
// Parse parent
const char *cparent = *p++;
if (!cparent) cparent = "";
// Parse list of interfaces
vector<string> ifaces;
while (*p) ifaces.push_back(*p++);
p++;
// Parse methods
FunctionScopePtrVec methods;
while (*p) {
FunctionScopePtr fs = ParseExtFunction(ar, p, true);
if (sep) {
fs->setSepExtension();
}
int flags = (int)(int64)(*p++);
if (flags & ClassInfo::IsAbstract) {
fs->addModifier(T_ABSTRACT);
}
int vismod = 0;
if (flags & ClassInfo::IsProtected) {
vismod = T_PROTECTED;
} else if (flags & ClassInfo::IsPrivate) {
vismod = T_PRIVATE;
}
fs->addModifier(vismod);
if (flags & ClassInfo::IsStatic) {
fs->addModifier(T_STATIC);
}
methods.push_back(fs);
}
if (cparent && *cparent && (ifaces.empty() || ifaces[0] != cparent)) {
ifaces.insert(ifaces.begin(), cparent);
}
ClassScopePtr cl(new ClassScope(ar, cname, cparent, ifaces, methods));
for (uint i = 0; i < methods.size(); ++i) {
methods[i]->setOuterScope(cl);
}
p++;
// Parse properties
while (*p) {
int flags = (int)(int64)(*p++);
ModifierExpressionPtr modifiers(
new ModifierExpression(BlockScopePtr(), LocationPtr()));
if (flags & ClassInfo::IsProtected) {
modifiers->add(T_PROTECTED);
} else if (flags & ClassInfo::IsPrivate) {
modifiers->add(T_PRIVATE);
}
if (flags & ClassInfo::IsStatic) {
modifiers->add(T_STATIC);
}
const char *name = *p++;
TypePtr type = ParseType(p);
cl->getVariables()->add(name, type, false, ar, ExpressionPtr(), modifiers);
}
p++;
// Parse consts
while (*p) {
const char *name = *p++;
TypePtr type = ParseType(p);
cl->getConstants()->add(name, type, ExpressionPtr(), ar, ConstructPtr());
}
p++;
int flags = (int)(int64)(*p++);
cl->setClassInfoAttribute(flags);
if (flags & ClassInfo::HasDocComment) {
cl->setDocComment(*p++);
}
cl->setSystem();
if (sep) {
cl->setSepExtension();
}
s_classes[cl->getName()] = cl;
}
}
FunctionScopePtr BuiltinSymbols::ParseExtFunction(AnalysisResultPtr ar,
const char** &p, bool method /* = false */) {
const char *name = *p++;
TypePtr retType = ParseType(p);
bool reference = *p++;
int minParam = -1;
int maxParam = 0;
const char **arg = p;
while (*arg) {
/* name */ arg++;
ParseType(arg);
const char *argDefault = *arg++;
/* const char *argDefaultLen = */ arg++;
/* const char *argDefaultText = */ arg++;
/* bool argReference = */ arg++;
if (argDefault && minParam < 0) {
minParam = maxParam;
}
maxParam++;
}
if (minParam < 0) minParam = maxParam;
FunctionScopePtr f(new FunctionScope(method, name, reference));
f->setParamCounts(ar, minParam, maxParam);
if (retType) {
f->setReturnType(ar, retType);
}
f->setClassInfoAttribute(attrs);
f->setDocComment(method->docComment);
int index = 0;
const char *paramName = nullptr;
while ((paramName = *p++ /* argName */)) {
TypePtr argType = ParseType(p);
const char *argDefault = *p++;
const char *argDefaultLen = *p++;
const char *argDefaultText = *p++;
bool argReference = *p++;
if (!isMethod && (attrs & ClassInfo::HasOptFunction)) {
// Legacy optimization functions
if (method->name.same(s_fb_call_user_func_safe) ||
method->name.same(s_fb_call_user_func_safe_return) ||
method->name.same(s_fb_call_user_func_array_safe)) {
f->setOptFunction(hphp_opt_fb_call_user_func);
} else if (method->name.same(s_is_callable)) {
f->setOptFunction(hphp_opt_is_callable);
} else if (method->name.same(s_call_user_func_array)) {
f->setOptFunction(hphp_opt_call_user_func);
}
f->setParamName(index, paramName);
if (argReference) f->setRefParam(index);
f->setParamType(ar, index, argType);
if (argDefault) f->setParamDefault(index, argDefault,
(int64_t)argDefaultLen,
argDefaultText);
index++;
}
if (isMethod) {
if (attrs & ClassInfo::IsProtected) {
f->addModifier(T_PROTECTED);
} else if (attrs & ClassInfo::IsPrivate) {
f->addModifier(T_PRIVATE);
}
if (attrs & ClassInfo::IsStatic) {
f->addModifier(T_STATIC);
}
int flags = (int)(int64)(*p++);
f->setClassInfoAttribute(flags);
if (flags & ClassInfo::HasDocComment) {
f->setDocComment(*p++);
}
if (flags & ClassInfo::HasOptFunction) {
f->setOptFunction((FunctionOptPtr)(*p++));
}
// This block of code is not needed, if BlockScope directly takes flags.
if (attrs & ClassInfo::MixedVariableArguments) {
if (flags & ClassInfo::MixedVariableArguments) {
f->setVariableArgument(-1);
} else if (attrs & ClassInfo::RefVariableArguments) {
} else if (flags & ClassInfo::RefVariableArguments) {
f->setVariableArgument(1);
} else if (attrs & ClassInfo::VariableArguments) {
} else if (flags & ClassInfo::VariableArguments) {
f->setVariableArgument(0);
}
if (attrs & ClassInfo::NoEffect) {
if (flags & ClassInfo::NoEffect) {
f->setNoEffect();
}
if (attrs & ClassInfo::FunctionIsFoldable) {
if (flags & ClassInfo::FunctionIsFoldable) {
f->setIsFoldable();
}
if (attrs & ClassInfo::ContextSensitive) {
if (flags & ClassInfo::ContextSensitive) {
f->setContextSensitive(true);
}
if (attrs & ClassInfo::NeedsActRec) {
if (flags & ClassInfo::NeedsActRec) {
f->setNeedsActRec();
}
if ((attrs & ClassInfo::AllowOverride) && !isMethod) {
f->setAllowOverride();
if ((flags & ClassInfo::IgnoreRedefinition) && !method) {
f->setIgnoreRedefinition();
}
FunctionScope::RecordFunctionInfo(f->getName(), f);
return f;
}
void BuiltinSymbols::ImportExtFunctions(AnalysisResultPtr ar,
ClassInfo *cls) {
const ClassInfo::MethodVec &methods = cls->getMethodsVec();
for (auto it = methods.begin(); it != methods.end(); ++it) {
if (((*it)->attribute & ClassInfo::ZendCompat) &&
!Option::EnableZendCompat) {
continue;
FunctionScopePtr BuiltinSymbols::ParseHelperFunction(AnalysisResultPtr ar,
const char** &p) {
FunctionScopePtr f = ParseExtFunction(ar, p);
f->setHelperFunction();
return f;
}
bool BuiltinSymbols::LoadSepExtensionSymbols(AnalysisResultPtr ar,
const std::string &name,
const std::string &soname) {
string mapname = name + "_map";
const char ***symbols = nullptr;
// If we linked with .a, the symbol is already in main program.
if (s_handle_main == nullptr) {
s_handle_main = dlopen(nullptr, RTLD_NOW | RTLD_GLOBAL);
if (!s_handle_main) {
const char *error = dlerror();
Logger::Error("Unable to load main program's symbols: %s",
error ? error : "(unknown)");
}
FunctionScopePtr f = ImportFunctionScopePtr(ar, cls, *it);
ar->addSystemFunction(f);
}
}
void BuiltinSymbols::ImportExtMethods(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);
vec.push_back(f);
if (s_handle_main) {
symbols = (const char ***)dlsym(s_handle_main, mapname.c_str());
}
}
void BuiltinSymbols::ImportExtProperties(AnalysisResultPtr ar,
VariableTablePtr dest,
ClassInfo *cls) {
ClassInfo::PropertyVec src = cls->getPropertiesVec();
for (auto it = src.begin(); it != src.end(); ++it) {
ClassInfo::PropertyInfo *pinfo = *it;
int attrs = pinfo->attribute;
ModifierExpressionPtr modifiers(
new ModifierExpression(BlockScopePtr(), LocationPtr()));
if (attrs & ClassInfo::IsPrivate) {
modifiers->add(T_PRIVATE);
} else if (attrs & ClassInfo::IsProtected) {
modifiers->add(T_PROTECTED);
// Otherwise, look for .so to load it.
void *handle = nullptr;
if (!symbols) {
handle = dlopen(soname.c_str(), RTLD_NOW | RTLD_GLOBAL);
if (!handle) {
const char *error = dlerror();
Logger::Error("Unable to load %s: %s", soname.c_str(),
error ? error : "(unknown)");
return false;
}
if (attrs & ClassInfo::IsStatic) {
modifiers->add(T_STATIC);
symbols = (const char ***)dlsym(handle, mapname.c_str());
if (!symbols) {
Logger::Error("Unable to find %s in %s", mapname.c_str(),
soname.c_str());
dlclose(handle);
return false;
}
dest->add(pinfo->name.data(),
typePtrFromDataType(pinfo->type, Type::Variant),
false, ar, ExpressionPtr(), modifiers);
}
ParseExtFunctions(ar, symbols[0], true);
ParseExtConsts (ar, symbols[1], true);
ParseExtClasses (ar, symbols[2], true);
if (handle) {
/*
Not closing for now, because it may have set an object allocator,
which would then fail next time its used.
I think the object allocators should be fixed instead - one per size,
rather than one per class, then this issue wouldnt occur
*/
// dlclose(handle);
}
return true;
}
void BuiltinSymbols::ImportExtConstants(AnalysisResultPtr ar,
ConstantTablePtr dest,
ClassInfo *cls) {
ClassInfo::ConstantVec src = cls->getConstantsVec();
for (auto it = src.begin(); it != src.end(); ++it) {
// We make an assumption that if the constant is a callback type
// (e.g. STDIN, STDOUT, STDERR) then it will return an Object.
// And that if it's deferred (SID, PHP_SAPI, etc.) it'll be a String.
ClassInfo::ConstantInfo *cinfo = *it;
dest->add(cinfo->name.data(),
cinfo->isDeferred() ?
(cinfo->isCallback() ? Type::Object : Type::String) :
typePtrFromDataType(cinfo->getValue().getType(), Type::Variant),
ExpressionPtr(), ar, ConstructPtr());
}
}
ClassScopePtr BuiltinSymbols::ImportClassScopePtr(AnalysisResultPtr ar,
ClassInfo *cls) {
FunctionScopePtrVec methods;
ImportExtMethods(ar, methods, cls);
ClassInfo::InterfaceVec ifaces = cls->getInterfacesVec();
String parent = cls->getParentClass();
std::vector<std::string> stdIfaces;
if (!parent.empty() && (ifaces.empty() || ifaces[0] != parent)) {
stdIfaces.push_back(parent.data());
}
for (auto it = ifaces.begin(); it != ifaces.end(); ++it) {
stdIfaces.push_back(it->data());
}
ClassScopePtr cl(new ClassScope(ar, cls->getName().data(), parent.data(),
stdIfaces, methods));
for (uint i = 0; i < methods.size(); ++i) {
methods[i]->setOuterScope(cl);
}
ImportExtProperties(ar, cl->getVariables(), cls);
ImportExtConstants(ar, cl->getConstants(), cls);
int attrs = cls->getAttribute();
cl->setClassInfoAttribute(attrs);
cl->setDocComment(cls->getDocComment());
cl->setSystem();
return cl;
}
void BuiltinSymbols::ImportExtClasses(AnalysisResultPtr ar) {
const ClassInfo::ClassMap &classes = ClassInfo::GetClassesMap();
for (auto it = classes.begin(); it != classes.end(); ++it) {
const ClassInfo *info = it->second;
if ((info->getAttribute() & ClassInfo::ZendCompat) &&
!Option::EnableZendCompat) {
continue;
void BuiltinSymbols::Parse(AnalysisResultPtr ar,
const std::string& phpBaseName,
const std::string& phpFileName) {
const char *baseName = s_strings.add(phpBaseName.c_str());
const char *fileName = s_strings.add(phpFileName.c_str());
try {
Scanner scanner(fileName, Option::ScannerType);
Compiler::Parser parser(scanner, baseName, ar);
if (!parser.parse()) {
Logger::Error("Unable to parse file %s: %s", fileName,
parser.getMessage().c_str());
assert(false);
}
ClassScopePtr cl = ImportClassScopePtr(ar, it->second);
ar->addSystemClass(cl);
} catch (FileOpenException &e) {
Logger::Error("%s", e.getMessage().c_str());
}
}
bool BuiltinSymbols::Load(AnalysisResultPtr ar) {
bool BuiltinSymbols::Load(AnalysisResultPtr ar, bool extOnly /* = false */) {
if (Loaded) return true;
Loaded = true;
if (g_context.isNull()) init_thread_locals();
ClassInfo::Load();
// load extension functions first, so system/classes may call them
ParseExtFunctions(ar, ExtensionFunctions, false);
AnalysisResultPtr ar2 = AnalysisResultPtr(new AnalysisResult());
s_variables = VariableTablePtr(new VariableTable(*ar2.get()));
s_constants = ConstantTablePtr(new ConstantTable(*ar2.get()));
// load extension functions first, so system/php may call them
ImportExtFunctions(ar, ClassInfo::GetSystem());
ConstantTablePtr cns = ar->getConstants();
// load extension constants, classes and dynamics
ImportExtConstants(ar, cns, ClassInfo::GetSystem());
ImportExtClasses(ar);
Array constants = ClassInfo::GetSystemConstants();
LocationPtr loc(new Location);
for (ArrayIter it = constants.begin(); it; ++it) {
CVarRef key = it.first();
if (!key.isString()) continue;
std::string name = key.toCStrRef().data();
if (cns->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);
TypePtr t =
value.isNull() ? Type::Null :
value.isBoolean() ? Type::Boolean :
value.isInteger() ? Type::Int64 :
value.isDouble() ? Type::Double :
value.isArray() ? Type::Array : Type::Variant;
cns->add(key.toCStrRef().data(), t, e, ar, e);
}
for (int i = 0, n = NumGlobalNames(); i < n; ++i) {
ar->getVariables()->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);
// Systemlib files were all parsed by hphp_process_init
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);
// parse all PHP files under system/classes
if (!extOnly) {
ar = AnalysisResultPtr(new AnalysisResult());
ar->loadBuiltinFunctions();
string slib = systemlib_path();
if (slib.empty()) {
for (const char **cls = SystemClasses; *cls; cls++) {
string phpBaseName = "/system/classes/";
phpBaseName += *cls;
phpBaseName += ".php";
Parse(ar, phpBaseName, Option::GetSystemRoot() + phpBaseName);
}
} else {
Parse(ar, slib, slib);
}
ar->analyzeProgram(true);
ar->inferTypes();
const StringToFileScopePtrMap &files = ar->getAllFiles();
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];
}
}
} else {
NoSuperGlobals = true;
}
const auto& functions = file.second->getFunctions();
for (const auto& func : functions) {
func.second->setSystem();
ar->addSystemFunction(func.second);
FunctionScope::RecordFunctionInfo(func.first, func.second);
// load extension constants, classes and dynamics
ParseExtConsts(ar, ExtensionConsts, false);
ParseExtClasses(ar, ExtensionClasses, false);
for (unsigned int i = 0; i < Option::SepExtensions.size(); i++) {
Option::SepExtensionOptions &options = Option::SepExtensions[i];
string soname = options.soname;
if (soname.empty()) {
soname = string("lib") + options.name + ".so";
}
if (!options.lib_path.empty()) {
soname = options.lib_path + "/" + soname;
}
if (!LoadSepExtensionSymbols(ar, options.name, soname)) {
return false;
}
}
if (!extOnly) {
Array constants = ClassInfo::GetSystemConstants();
LocationPtr loc(new Location);
for (ArrayIter it = constants.begin(); it; ++it) {
CVarRef key = it.first();
if (!key.isString()) continue;
std::string name = key.toCStrRef().data();
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(ar2, ar2, loc, value);
TypePtr t =
value.isNull() ? Type::Null :
value.isBoolean() ? Type::Boolean :
value.isInteger() ? Type::Int64 :
value.isDouble() ? Type::Double :
value.isArray() ? Type::Array : Type::Variant;
s_constants->add(key.toCStrRef().data(), t, e, ar2, e);
}
s_variables = ar2->getVariables();
for (int i = 0, n = NumGlobalNames(); i < n; ++i) {
s_variables->add(GlobalNames[i], Type::Variant, false, ar,
ConstructPtr(), ModifierExpressionPtr());
}
}
s_constants->setDynamic(ar, "SID", true);
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::ScannerType);
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);
for (StringToFunctionScopePtrMap::const_iterator it = s_functions.begin();
it != s_functions.end(); ++it) {
if (functions.find(it->first) == functions.end()) {
functions[it->first] = it->second;
FunctionScope::RecordFunctionInfo(it->first, it->second);
}
}
}
void BuiltinSymbols::LoadClasses(AnalysisResultPtr ar,
StringToClassScopePtrMap &classes) {
assert(Loaded);
classes.insert(s_classes.begin(), s_classes.end());
// we are adding these builtin functions, so that user-defined functions
// will not overwrite them with their own file and line number information
for (StringToClassScopePtrMap::const_iterator iter =
s_classes.begin(); iter != s_classes.end(); ++iter) {
const StringToFunctionScopePtrMap &funcs = iter->second->getFunctions();
for (StringToFunctionScopePtrMap::const_iterator iter =
funcs.begin(); iter != funcs.end(); ++iter) {
FunctionScope::RecordFunctionInfo(iter->first, iter->second);
}
}
}
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;
@@ -410,6 +596,7 @@ void BuiltinSymbols::LoadSuperGlobals() {
}
bool BuiltinSymbols::IsSuperGlobal(const std::string &name) {
if (NoSuperGlobals) return false;
return s_superGlobals.find(name) != s_superGlobals.end();
}
+46 -29
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -14,29 +14,28 @@
+----------------------------------------------------------------------+
*/
#ifndef incl_HPHP_BUILTIN_SYMBOLS_H_
#define incl_HPHP_BUILTIN_SYMBOLS_H_
#ifndef __BUILTIN_SYMBOLS_H__
#define __BUILTIN_SYMBOLS_H__
#include "hphp/compiler/hphp.h"
#include "hphp/util/string-bag.h"
#include "hphp/runtime/base/class-info.h"
#include <compiler/hphp.h>
#include <util/string_bag.h>
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 NoSuperGlobals; // for SystemCPP bootstraping only
static bool Load(AnalysisResultPtr ar);
static bool Load(AnalysisResultPtr ar, bool extOnly = false);
static void LoadFunctions(AnalysisResultPtr ar,
StringToFunctionScopePtrMap &functions);
@@ -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,35 +60,48 @@ 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 const char *const GlobalNames[];
static int NumGlobalNames();
private:
static StringBag s_strings;
static const char *ExtensionFunctions[];
static const char *ExtensionClasses[];
static const char *ExtensionConsts[];
static const char *ExtensionDeclaredDynamic[];
static const char *SystemClasses[];
static AnalysisResultPtr LoadGlobalSymbols(const char *fileName);
static void Parse(AnalysisResultPtr ar,
const std::string& phpBaseName,
const std::string& phpFileName);
static StringToTypePtrMap s_superGlobals;
static std::set<std::string> s_declaredDynamic;
static FunctionScopePtr ImportFunctionScopePtr(AnalysisResultPtr ar,
ClassInfo *cls,
ClassInfo::MethodInfo *method);
static void ImportExtFunctions(AnalysisResultPtr ar,
ClassInfo *cls);
static void ImportExtMethods(AnalysisResultPtr ar,
FunctionScopePtrVec &vec,
ClassInfo *cls);
static void ImportExtProperties(AnalysisResultPtr ar,
VariableTablePtr dest,
ClassInfo *cls);
static void ImportExtConstants(AnalysisResultPtr ar,
ConstantTablePtr dest,
ClassInfo *cls);
static ClassScopePtr ImportClassScopePtr(AnalysisResultPtr ar,
ClassInfo *cls);
static void ImportExtClasses(AnalysisResultPtr ar);
static void *s_handle_main;
static bool LoadSepExtensionSymbols(AnalysisResultPtr ar,
const std::string &name,
const std::string &soname);
static TypePtr ParseType(const char **&p);
static void ParseExtFunctions(AnalysisResultPtr ar, const char **p,
bool sep);
static void ParseExtConsts(AnalysisResultPtr ar, const char **p, bool sep);
static void ParseExtClasses(AnalysisResultPtr ar, const char **p, bool sep);
static void ParseExtDynamics(AnalysisResultPtr ar, const char **p, bool sep);
static FunctionScopePtr ParseExtFunction(AnalysisResultPtr ar,
const char** &p, bool method = false);
static FunctionScopePtr ParseHelperFunction(AnalysisResultPtr ar,
const char** &p);
};
///////////////////////////////////////////////////////////////////////////////
}
#endif // incl_HPHP_BUILTIN_SYMBOLS_H_
#endif // __BUILTIN_SYMBOLS_H__
+248 -182
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -14,18 +14,17 @@
+----------------------------------------------------------------------+
*/
#include "hphp/compiler/code_generator.h"
#include "hphp/compiler/code_model_enums.h"
#include "hphp/compiler/statement/statement_list.h"
#include "hphp/compiler/expression/expression_list.h"
#include "hphp/compiler/option.h"
#include "hphp/compiler/analysis/file_scope.h"
#include "hphp/compiler/analysis/function_scope.h"
#include "hphp/compiler/analysis/analysis_result.h"
#include "hphp/compiler/analysis/variable_table.h"
#include "hphp/runtime/base/zend-printf.h"
#include "hphp/util/util.h"
#include "hphp/util/hash.h"
#include <stdarg.h>
#include <compiler/code_generator.h>
#include <compiler/statement/statement_list.h>
#include <compiler/option.h>
#include <compiler/analysis/file_scope.h>
#include <compiler/analysis/function_scope.h>
#include <compiler/analysis/analysis_result.h>
#include <compiler/analysis/variable_table.h>
#include <util/util.h>
#include <util/hash.h>
#include <boost/format.hpp>
#include <boost/scoped_array.hpp>
@@ -62,7 +61,8 @@ CodeGenerator::CodeGenerator(std::ostream *primary,
Output output /* = PickledPHP */,
const std::string *filename /* = NULL */)
: m_out(nullptr), m_output(output),
m_context(NoContext), m_itemIndex(-1) {
m_hoistedClasses(0), m_collectHoistedClasses(false),
m_context(NoContext), m_insideScalarArray(false), m_itemIndex(-1) {
for (int i = 0; i < StreamCount; i++) {
m_streams[i] = nullptr;
m_indentation[i] = 0;
@@ -140,6 +140,46 @@ void CodeGenerator::indentEnd() {
m_indentation[m_curStream]--;
}
bool CodeGenerator::wrapExpressionBegin() {
if (!m_wrappedExpression[m_curStream]) {
m_wrappedExpression[m_curStream] = true;
m_referenceTempsUsed[m_curStream] = false;
m_localId[m_curStream] = 0;
setInExpression(true);
indentBegin("{\n");
return true;
}
return false;
}
bool CodeGenerator::wrapExpressionEnd() {
if (m_wrappedExpression[m_curStream]) {
if (m_referenceTempsUsed[m_curStream]) {
printf("%s.unset();\n", m_referenceTemps[m_curStream].c_str());
}
m_wrappedExpression[m_curStream] = false;
indentEnd("}\n");
return true;
}
return false;
}
void CodeGenerator::genReferenceTemp(ConstructPtr cp) {
string &rt = m_referenceTemps[m_curStream];
rt = (string)Option::TempPrefix + "_ref";
printf("Variant %s;\n", rt.c_str());
}
const string &CodeGenerator::getReferenceTemp() {
static string empty = "";
if (m_wrappedExpression[m_curStream] &&
!m_referenceTemps[m_curStream].empty()) {
m_referenceTempsUsed[m_curStream] = true;
return m_referenceTemps[m_curStream];
}
return empty;
}
bool CodeGenerator::inComments() const {
return m_inComments[m_curStream] > 0;
}
@@ -208,6 +248,20 @@ bool CodeGenerator::ensureOutOfNamespace() {
return true;
}
void CodeGenerator::headerBegin(const std::string &file) {
string formatted = getFormattedName(file);
printf("\n");
printf("#ifndef __GENERATED_%s__\n", formatted.c_str());
printf("#define __GENERATED_%s__\n", formatted.c_str());
printf("\n");
}
void CodeGenerator::headerEnd(const std::string &file) {
string formatted = getFormattedName(file);
printf("\n");
printf("#endif // __GENERATED_%s__\n", formatted.c_str());
}
void CodeGenerator::ifdefBegin(bool ifdef, const char *fmt, ...) {
printf(ifdef ? "#ifdef " : "#ifndef ");
va_list ap; va_start(ap, fmt); print(fmt, ap); va_end(ap);
@@ -220,6 +274,59 @@ void CodeGenerator::ifdefEnd(const char *fmt, ...) {
printf("\n");
}
void CodeGenerator::printInclude(const std::string &file) {
assert(!file.empty());
string formatted = file;
if (file[0] != '"' && file[0] != '<') {
if (file.substr(file.length() - 2) != ".h") {
formatted += ".h";
}
formatted = string("<") + formatted + '>';
}
printf("%s %s\n", HASH_INCLUDE, formatted.c_str());
}
void CodeGenerator::printBasicIncludes() {
if (Option::GenerateCPPMain) {
printInclude("<runtime/base/hphp.h>");
printInclude(string(Option::SystemFilePrefix) +
"literal_strings_remap.h");
printInclude(string(Option::SystemFilePrefix) +
"scalar_arrays_remap.h");
if (Option::UseScalarVariant) {
printInclude(string(Option::SystemFilePrefix) +
"scalar_integers_remap.h");
}
printInclude(string(Option::SystemFilePrefix) + "global_variables.h");
if (Option::GenArrayCreate) {
printInclude(string(Option::SystemFilePrefix) + "cpputil.h");
}
} else if (getOutput() == CodeGenerator::SystemCPP) {
printInclude("<runtime/base/hphp_system.h>");
printInclude(string("system/gen/") + Option::SystemFilePrefix +
"literal_strings_remap.h");
printInclude(string("system/gen/") + Option::SystemFilePrefix +
"scalar_arrays_remap.h");
}
}
void CodeGenerator::printDeclareGlobals() {
if (getOutput() == SystemCPP) {
printf("DECLARE_SYSTEM_GLOBALS(g);\n");
} else {
printf("DECLARE_GLOBAL_VARIABLES(g);\n");
}
}
void CodeGenerator::printStartOfJumpTable(int tableSize) {
if (Util::isPowerOfTwo(tableSize)) {
indentBegin("switch (hash & %d) {\n", tableSize-1);
} else {
indentBegin("switch (hash %% %d) {\n", tableSize);
}
}
void CodeGenerator::printDocComment(const std::string comment) {
if (comment.empty()) return;
string escaped;
@@ -235,6 +342,24 @@ void CodeGenerator::printDocComment(const std::string comment) {
printf("\n");
}
void CodeGenerator::printImplStarter() {
printf("%s\n", STARTER_MARKER);
}
void CodeGenerator::printImplSplitter() {
printf("%s\n", SPLITTER_MARKER);
}
const char *CodeGenerator::getGlobals(AnalysisResultPtr ar) {
if (m_context == CppParameterDefaultValueDecl ||
m_context == CppParameterDefaultValueImpl) {
return (m_output == CodeGenerator::SystemCPP) ?
"get_system_globals()" : "get_global_variables()";
}
if (m_output == CodeGenerator::SystemCPP) return "get_system_globals()";
return "g";
}
std::string CodeGenerator::FormatLabel(const std::string &name) {
string ret;
ret.reserve(name.size());
@@ -398,6 +523,14 @@ int CodeGenerator::callInfoTop() {
return m_callInfos.back();
}
bool CodeGenerator::getInsideScalarArray() {
return m_insideScalarArray;
}
void CodeGenerator::setInsideScalarArray(bool flag) {
m_insideScalarArray = flag;
}
void CodeGenerator::addLabelId(const char *name, int labelId) {
if (!strcmp(name, "break")) {
m_breakLabelIds.insert(labelId);
@@ -419,177 +552,110 @@ bool CodeGenerator::findLabelId(const char *name, int labelId) {
return false;
}
int CodeGenerator::checkLiteralString(const std::string &str, int &index,
AnalysisResultPtr ar, BlockScopePtr bs,
bool scalarVariant /* = false */) {
always_assert(getContext() != CodeGenerator::CppConstantsDecl &&
getContext() != CodeGenerator::CppClassConstantsImpl);
int stringId = ar->getLiteralStringId(str, index);
if (m_literalScope) {
bs = m_literalScope;
}
if (bs && bs != ar) {
FileScopePtr fs = bs->getContainingFile();
if (fs) {
fs->addUsedLiteralString(str);
if (scalarVariant) fs->addUsedLitVarString(str);
if (isFileOrClassHeader()) {
ClassScopePtr cs = bs->getContainingClass();
if (cs) {
cs->addUsedLiteralStringHeader(str);
if (scalarVariant) cs->addUsedLitVarStringHeader(str);
} else {
fs->addUsedLiteralStringHeader(str);
if (scalarVariant) fs->addUsedLitVarStringHeader(str);
}
}
}
}
return stringId;
}
string CodeGenerator::printNamedString(const string &str,
const string &escaped, AnalysisResultPtr ar, BlockScopeRawPtr bs,
bool print) {
int index = -1;
bool scalarVariant = !print;
int stringId = checkLiteralString(str, index, ar, bs, scalarVariant);
always_assert(index >= 0);
string lisnam = ar->getLiteralStringName(stringId, index);
if (print) {
printf("NAMSTR(%s, \"%s\")", lisnam.c_str(), escaped.c_str());
}
return lisnam;
}
string CodeGenerator::printString(const string &str, AnalysisResultPtr ar,
BlockScopeRawPtr bs,
bool stringWrapper /* = true */) {
bool isBinary = false;
string escaped = EscapeLabel(str, &isBinary);
if (bs) {
return printNamedString(str, escaped, ar, bs, true);
}
if (isBinary) {
if (stringWrapper) {
printf("String(\"%s\", %d, AttachLiteral)",
escaped.c_str(), (int)str.length());
} else {
printf("\"%s\", %d", escaped.c_str(), (int)str.length());
}
} else {
printf("\"%s\"", escaped.c_str());
}
return "";
}
string CodeGenerator::printString(const std::string &str, AnalysisResultPtr ar,
ConstructPtr cs,
bool stringWrapper /* = true */) {
return printString(str, ar, (BlockScopePtr)cs->getScope(), stringWrapper);
}
void CodeGenerator::beginHoistedClasses() {
m_hoistedClasses = new std::set<string,stdltistr>();
m_collectHoistedClasses = true;
}
void CodeGenerator::endHoistedClasses() {
delete m_hoistedClasses;
m_hoistedClasses = 0;
}
void CodeGenerator::collectHoistedClasses(bool flag) {
m_collectHoistedClasses = flag;
}
void CodeGenerator::addHoistedClass(const string &cls) {
if (m_hoistedClasses && m_collectHoistedClasses) {
m_hoistedClasses->insert(cls);
}
}
bool CodeGenerator::checkHoistedClass(const string &cls) {
if (m_hoistedClasses) {
if (m_hoistedClasses->find(cls) != m_hoistedClasses->end()) {
return true;
}
addHoistedClass(cls);
}
return false;
}
int CodeGenerator::ClassScopeCompare::cmp(const ClassScopeRawPtr &p1,
const ClassScopeRawPtr &p2) const {
int d = p1->getRedeclaringId() - p2->getRedeclaringId();
if (d) return d;
return strcasecmp(p1->getName().c_str(), p2->getName().c_str());
}
void CodeGenerator::printObjectHeader(const std::string className,
int numProperties) {
std::string prefixedClassName;
prefixedClassName.append(m_astPrefix);
prefixedClassName.append(className);
m_astClassNames.push_back(prefixedClassName);
printf("O:%d:\"%s\":%d:{",
(int)prefixedClassName.length(), prefixedClassName.c_str(), numProperties);
}
void CodeGenerator::printObjectFooter() {
printf("}");
m_astClassNames.pop_back();
}
void CodeGenerator::printPropertyHeader(const std::string propertyName) {
auto prefixedClassName = m_astClassNames.back();
auto len = 2+prefixedClassName.length()+propertyName.length();
printf("s:%d:\"", (int)len);
*m_out << (char)0;
printf("%s", prefixedClassName.c_str());
*m_out << (char)0;
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)) {
*m_out << "NAN";
} else if (std::isinf(v)) {
if (v < 0) *m_out << '-';
*m_out << "INF";
} else {
char *buf;
if (v == 0.0) v = 0.0; // so to avoid "-0" output
vspprintf(&buf, 0, "%.*H", 14, v);
m_out->write(buf, strlen(buf));
free(buf);
}
*m_out << ';';
}
void CodeGenerator::printValue(int32_t value) {
printf("i:%d;", value);
}
void CodeGenerator::printValue(int64_t value) {
printf("i:%" PRId64 ";", value);
}
void CodeGenerator::printValue(std::string value) {
printf("s:%d:\"", (int)value.length());
getStream()->write(value.c_str(), value.length());
printf("\";");
}
void CodeGenerator::printModifierVector(std::string value) {
printf("V:9:\"HH\\Vector\":1:{");
printObjectHeader("Modifier", 1);
printPropertyHeader("name");
printValue(value);
printObjectFooter();
printf("}");
}
void CodeGenerator::printTypeExpression(std::string value) {
printObjectHeader("TypeExpression", 1);
printPropertyHeader("name");
printValue(value);
printObjectFooter();
}
void CodeGenerator::printExpression(ExpressionPtr expression, bool isRef) {
if (isRef) {
printObjectHeader("UnaryOpExpression", 3);
printPropertyHeader("expression");
expression->outputCodeModel(*this);
printPropertyHeader("operation");
printValue(PHP_REFERENCE_OP);
printPropertyHeader("sourceLocation");
printLocation(expression->getLocation());
printObjectFooter();
} else {
expression->outputCodeModel(*this);
}
}
void CodeGenerator::printExpressionVector(ExpressionListPtr el) {
auto count = el == nullptr ? 0 : el->getCount();
printf("V:9:\"HH\\Vector\":%d:{", count);
if (count > 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("}");
}
}
void CodeGenerator::printAsBlock(StatementPtr s) {
if (s != nullptr && s->is(Statement::KindOfBlockStatement)) {
s->outputCodeModel(*this);
} else {
auto numProps = s == nullptr ? 1 : 2;
printObjectHeader("BlockStatement", numProps);
printPropertyHeader("statements");
printStatementVector(s);
if (s != nullptr) {
printPropertyHeader("sourceLocation");
printLocation(s->getLocation());
}
printObjectFooter();
}
}
void CodeGenerator::printStatementVector(StatementListPtr sl) {
printf("V:9:\"HH\\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);
printPropertyHeader("startLine");
printValue(location->line0);
printPropertyHeader("endLine");
printValue(location->line1);
printPropertyHeader("startColumn");
printValue(location->char0);
printPropertyHeader("endColumn");
printValue(location->char1);
printObjectFooter();
}
+64 -49
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -14,26 +14,22 @@
+----------------------------------------------------------------------+
*/
#ifndef incl_HPHP_CODE_GENERATOR_H_
#define incl_HPHP_CODE_GENERATOR_H_
#ifndef __CODE_GENERATOR_H__
#define __CODE_GENERATOR_H__
#include "hphp/compiler/hphp.h"
#include <compiler/hphp.h>
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
DECLARE_BOOST_TYPES(AnalysisResult);
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);
DECLARE_BOOST_TYPES(Location);
DECLARE_BOOST_TYPES(Expression);
DECLARE_BOOST_TYPES(ExpressionList);
class CodeGenerator {
public:
@@ -49,7 +45,6 @@ public:
SystemCPP, // special mode for generating builtin classes
TextHHBC, // HHBC dump in human-readable format
BinaryHHBC, // serialized HHBC
CodeModel, // serialized Code Model classes
};
enum Stream {
@@ -136,8 +131,8 @@ public:
public:
CodeGenerator() {} // only for creating a dummy code generator
explicit CodeGenerator(std::ostream *primary, Output output = PickledPHP,
const std::string *filename = nullptr);
CodeGenerator(std::ostream *primary, Output output = PickledPHP,
const std::string *filename = nullptr);
/**
* ...if it was passed in from constructor.
@@ -168,6 +163,17 @@ public:
void indentEnd(const char *fmt, ...) ATTRIBUTE_PRINTF(2,3);
void indentEnd();
void printRaw(const char *msg) { print(msg, false);}
bool wrapExpressionBegin();
bool wrapExpressionEnd();
void genReferenceTemp(ConstructPtr scope);
void clearRefereceTemp() { m_referenceTemps[m_curStream].clear(); }
const std::string &getReferenceTemp();
bool hasReferenceTemp() const {
return !m_referenceTemps[m_curStream].empty();
}
void setReferenceTempUsed(bool flag) {
m_referenceTempsUsed[m_curStream] = flag;
}
/**
* Pre-formatted outputs.
*/
@@ -177,9 +183,17 @@ public:
void namespaceEnd();
bool ensureInNamespace();
bool ensureOutOfNamespace();
void headerBegin(const std::string &file);
void headerEnd(const std::string &file);
void ifdefBegin(bool ifdef, const char *fmt, ...) ATTRIBUTE_PRINTF(3,4);
void ifdefEnd(const char *fmt, ...) ATTRIBUTE_PRINTF(2,3);
void printInclude(const std::string &file);
void printBasicIncludes();
void printDeclareGlobals();
void printStartOfJumpTable(int tableSize);
void printDocComment(const std::string comment);
void printImplStarter(); // end of includes
void printImplSplitter(); // marker to split .cpp into smaller files
const char *getGlobals(AnalysisResultPtr ar);
static std::string FormatLabel(const std::string &name);
static std::string EscapeLabel(const std::string &name, bool *binary = nullptr);
@@ -254,13 +268,31 @@ public:
m_loopStatement = loop;
}
void setInsideScalarArray(bool flag);
bool getInsideScalarArray();
void setFileOrClassHeader(bool value) { m_inFileOrClassHeader = value; }
bool isFileOrClassHeader() { return m_inFileOrClassHeader; }
void beginHoistedClasses();
void endHoistedClasses();
void collectHoistedClasses(bool flag);
void addHoistedClass(const std::string &cls);
bool checkHoistedClass(const std::string &cls);
void setScalarVariant() { m_scalarVariant = true; }
bool hasScalarVariant() { return m_scalarVariant; }
void clearScalarVariant() { m_scalarVariant = false; }
void setInitListFirstElem() { m_initListFirstElem = true; }
bool hasInitListFirstElem() { return m_initListFirstElem; }
void clearInitListFirstElem() { m_initListFirstElem = false; }
const StringToClassScopePtrVecMap &getClasses() const { return m_classes; }
void addClass(const std::string &name, ClassScopePtr cls) {
m_classes[name].push_back(cls);
}
void clearClasses() { m_classes.clear(); }
bool insertDeclaredClosure(const FunctionScope *f) {
return m_declaredClosures.insert(f).second;
}
@@ -270,37 +302,12 @@ public:
FileScopeRawPtr getLiteralScope() const {
return m_literalScope;
}
/**
* Support for printing AST nodes in PHP serialize() format.
*/
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);
void printValue(std::string value);
void printModifierVector(std::string value);
void printTypeExpression(std::string value);
void printExpression(ExpressionPtr expression, bool isRef);
void printExpressionVector(ExpressionListPtr el);
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:
std::string m_filename;
Stream m_curStream;
std::ostream *m_streams[StreamCount];
std::ostream *m_out;
Output m_output;
std::string m_astPrefix;
std::vector<std::string> m_astClassNames;
bool m_verbose;
int m_indentation[StreamCount];
@@ -314,6 +321,8 @@ private:
bool m_inFileOrClassHeader;
bool m_inNamespace;
int m_localId[StreamCount];
std::set<std::string, stdltistr> *m_hoistedClasses;
bool m_collectHoistedClasses;
static int s_idLambda;
std::map<std::string, int> m_idCounters;
@@ -323,6 +332,7 @@ private:
std::set<int> m_contLabelIds; // continue labels referenced
std::deque<int> m_callInfos;
LoopStatementPtr m_loopStatement;
bool m_insideScalarArray;
StringToClassScopePtrVecMap m_classes;
std::set<const FunctionScope*> m_declaredClosures;
FileScopeRawPtr m_literalScope;
@@ -338,23 +348,28 @@ private:
public: void print(const char *msg, bool indent = true);
private:
void print(const char *fmt, va_list ap) ATTRIBUTE_PRINTF(2,0);
void print(const char *fmt, va_list ap);
void printSubstring(const char *start, int length);
void printIndent();
std::string getFormattedName(const std::string &file);
};
#define cg_printf cg.printf
#define m_cg_printf m_cg.printf
#define cg_print cg.print
#define m_cg_print m_cg.print
#define cg_indentBegin cg.indentBegin
#define m_cg_indentBegin m_cg.indentBegin
#define cg_indentEnd cg.indentEnd
#define m_cg_indentEnd cg.indentEnd
#define cg_printInclude cg.printInclude
#define cg_printString cg.printString
#define STR(x) #x
#define XSTR(x) STR(x)
#define FLANN(stream,func,nl) (Option::FlAnnotate ? \
stream.printf("/* %s:" XSTR(__LINE__) "*/" nl, __func__): \
void()), stream.func
#define cg_printf FLANN(cg,printf,"")
#define m_cg_printf FLANN(m_cg,printf,"")
#define cg_print FLANN(cg,print,"")
#define m_cg_print FLANN(m_cg,print,"")
#define cg_indentBegin FLANN(cg,indentBegin,"")
#define m_cg_indentBegin FLANN(m_cg,indentBegin,"")
#define cg_indentEnd FLANN(cg,indentEnd,"")
#define m_cg_indentEnd FLANN(m_cg,indentEnd,"")
#define cg_printInclude FLANN(cg,printInclude,"\n")
#define cg_printString FLANN(cg,printString,"")
///////////////////////////////////////////////////////////////////////////////
}
#endif // incl_HPHP_CODE_GENERATOR_H_
#endif // __CODE_GENERATOR_H__
-117
Ver Arquivo
@@ -1,117 +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. |
+----------------------------------------------------------------------+
*/
// This file is @generated by tools/code-model/GenerateEnums.sh
#ifndef incl_HPHP_CODE_MODEL_ENUMS_H_
#define incl_HPHP_CODE_MODEL_ENUMS_H_
namespace HPHP {
/** The kinds of operations that IBinaryOpExpressions can perform. */
enum CodeModelBinaryOperator {
PHP_AND_ASSIGN = 1,
PHP_AND = 2,
PHP_ARRAY_ELEMENT = 3,
PHP_ARRAY_PAIR = 4,
PHP_ASSIGNMENT = 5,
PHP_BOOLEAN_AND = 6,
PHP_BOOLEAN_OR = 7,
PHP_CAST = 8,
PHP_CONCAT_ASSIGN = 9,
PHP_CONCAT = 10,
PHP_DIVIDE_ASSIGN = 11,
PHP_DIVIDE = 12,
PHP_INSTANCEOF = 13,
PHP_IS_EQUAL = 14,
PHP_IS_GREATER = 15,
PHP_IS_GREATER_OR_EQUAL = 16,
PHP_IS_IDENTICAL = 17,
PHP_IS_NOT_IDENTICAL = 18,
PHP_IS_NOT_EQUAL = 19,
PHP_IS_SMALLER = 20,
PHP_IS_SMALLER_OR_EQUAL = 21,
PHP_LOGICAL_AND = 22,
PHP_LOGICAL_OR = 23,
PHP_LOGICAL_XOR = 24,
PHP_MINUS_ASSIGN = 25,
PHP_MINUS = 26,
PHP_MODULUS_ASSIGN = 27,
PHP_MODULUS = 28,
PHP_MULTIPLY_ASSIGN = 29,
PHP_MULTIPLY = 30,
PHP_OR_ASSIGN = 31,
PHP_OR = 32,
PHP_PLUS_ASSIGN = 33,
PHP_PLUS = 34,
PHP_SHIFT_LEFT_ASSIGN = 35,
PHP_SHIFT_LEFT = 36,
PHP_SHIFT_RIGHT_ASSIGN = 37,
PHP_SHIFT_RIGHT = 38,
PHP_XOR_ASSIGN = 39,
PHP_XOR = 40,
};
/** The kinds of operations that IUnaryOpExpressions can perform. */
enum CodeModelUnaryOperator {
PHP_ARRAY_CAST_OP = 1,
PHP_ARRAY_APPEND_POINT_OP = 2,
PHP_AWAIT_OP = 3,
PHP_BOOL_CAST_OP = 4,
PHP_BITWISE_NOT_OP = 5,
PHP_CLONE_OP = 6,
PHP_DYNAMIC_VARIABLE_OP = 7,
PHP_ERROR_CONTROL_OP = 8,
PHP_FLOAT_CAST_OP = 9,
PHP_INCLUDE_OP = 10,
PHP_INCLUDE_ONCE_OP = 11,
PHP_INT_CAST_OP = 12,
PHP_MINUS_OP = 13,
PHP_NOT_OP = 14,
PHP_OBJECT_CAST_OP = 15,
PHP_PLUS_OP = 16,
PHP_POST_DECREMENT_OP = 17,
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,
};
/** Enumerates the kinds of type declaration statements. */
enum CodeModelTypeKind {
PHP_CLASS = 1,
PHP_INTERFACE = 2,
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_
+285 -102
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -14,45 +14,41 @@
+----------------------------------------------------------------------+
*/
#include "hphp/compiler/compiler.h"
#include "hphp/compiler/package.h"
#include "hphp/compiler/analysis/analysis_result.h"
#include "hphp/compiler/analysis/alias_manager.h"
#include "hphp/compiler/analysis/code_error.h"
#include "hphp/compiler/analysis/emitter.h"
#include "hphp/compiler/analysis/type.h"
#include "hphp/compiler/analysis/symbol_table.h"
#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/logger.h"
#include "hphp/util/db-conn.h"
#include "hphp/util/exception.h"
#include "hphp/util/process.h"
#include "hphp/util/util.h"
#include "hphp/util/timer.h"
#include "hphp/util/hdf.h"
#include "hphp/util/async-func.h"
#include "hphp/util/current-executable.h"
#include "hphp/runtime/base/program-functions.h"
#include "hphp/runtime/base/externals.h"
#include "hphp/runtime/base/thread-init-fini.h"
#include "hphp/runtime/vm/repo.h"
#include "hphp/system/systemlib.h"
#include "hphp/util/repo-schema.h"
#include "hphp/hhvm/process-init.h"
#include <sys/types.h>
#include <sys/wait.h>
#include <dlfcn.h>
#include <boost/program_options/options_description.hpp>
#include <boost/program_options/positional_options.hpp>
#include <boost/program_options/variables_map.hpp>
#include <boost/program_options/parsers.hpp>
#include <compiler/package.h>
#include <compiler/analysis/analysis_result.h>
#include <compiler/analysis/alias_manager.h>
#include <compiler/analysis/code_error.h>
#include <compiler/analysis/emitter.h>
#include <compiler/analysis/type.h>
#include <util/json.h>
#include <util/logger.h>
#include <compiler/analysis/symbol_table.h>
#include <compiler/option.h>
#include <compiler/parser/parser.h>
#include <compiler/builtin_symbols.h>
#include <util/db_conn.h>
#include <util/exception.h>
#include <util/process.h>
#include <util/util.h>
#include <util/timer.h>
#include <util/hdf.h>
#include <util/async_func.h>
#include <runtime/base/memory/smart_allocator.h>
#include <runtime/base/externals.h>
#include <runtime/base/thread_init_fini.h>
#include <runtime/base/compiler_id.h>
#include <runtime/vm/repo.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <dlfcn.h>
#include <system/lib/systemlib.h>
#include <compiler/compiler.h>
using namespace boost::program_options;
using std::cout;
@@ -63,6 +59,7 @@ struct CompilerOptions {
string target;
string format;
string outputDir;
string outputFile;
string syncDir;
vector<string> config;
string configDir;
@@ -83,6 +80,8 @@ struct CompilerOptions {
vector<string> cfiles;
vector<string> cmodules;
bool parseOnDemand;
vector<string> parseOnDemandDirs; // parse these directories on-demand
// when parseOnDemand=false
string program;
string programArgs;
string branch;
@@ -91,15 +90,23 @@ struct CompilerOptions {
bool keepTempDir;
string dbStats;
bool noTypeInference;
bool noMinInclude;
bool noMetaInfo;
int logLevel;
bool force;
int clusterCount;
int optimizeLevel;
string filecache;
string rttiDirectory;
string javaRoot;
bool generateFFI;
bool dump;
string docjson;
bool coredump;
bool nofork;
bool fl_annotate;
string optimizations;
string ppp;
};
///////////////////////////////////////////////////////////////////////////////
@@ -117,8 +124,7 @@ public:
struct stat sb;
stat(m_name, &sb);
Logger::Info("%" PRId64" MB %s saved",
(int64_t)sb.st_size/(1024*1024), m_name);
Logger::Info("%dMB %s saved", (int64)sb.st_size/(1024*1024), m_name);
}
private:
@@ -138,9 +144,13 @@ int phpTarget(const CompilerOptions &po, AnalysisResultPtr ar);
void hhbcTargetInit(const CompilerOptions &po, AnalysisResultPtr ar);
int hhbcTarget(const CompilerOptions &po, AnalysisResultPtr ar,
AsyncFileCacheSaver &fcThread);
int cppTarget(const CompilerOptions &po, AnalysisResultPtr ar,
AsyncFileCacheSaver &fcThread, bool allowSys = true);
int runTargetCheck(const CompilerOptions &po, AnalysisResultPtr ar,
AsyncFileCacheSaver &fcThread);
int buildTarget(const CompilerOptions &po);
int runTarget(const CompilerOptions &po);
int generateSepExtCpp(const CompilerOptions &po, AnalysisResultPtr ar);
///////////////////////////////////////////////////////////////////////////////
@@ -150,10 +160,6 @@ int compiler_main(int argc, char **argv) {
try {
Hdf empty;
RuntimeOption::Load(empty);
initialize_repo();
// we need to initialize pcre cache table very early
pcre_init();
CompilerOptions po;
#ifdef FACEBOOK
@@ -180,7 +186,11 @@ int compiler_main(int argc, char **argv) {
}
}
if (ret == 0) {
if (po.target == "run") {
if (po.target == "cpp") {
if (po.format == "exe" || po.format == "lib") {
ret = buildTarget(po);
}
} else if (po.target == "run") {
ret = runTarget(po);
}
}
@@ -192,10 +202,6 @@ int compiler_main(int argc, char **argv) {
return ret;
} catch (Exception &e) {
Logger::Error("Exception: %s\n", e.getMessage().c_str());
} catch (const FailedAssertion& fa) {
fa.print();
StackTraceNoHeap::AddExtraLogging("Assertion failure", fa.summary);
abort();
} catch (std::exception &e) {
Logger::Error("std::exception: %s\n", e.what());
} catch (...) {
@@ -218,6 +224,8 @@ int prepareOptions(CompilerOptions &po, int argc, char **argv) {
"analyze | "
"php | "
"hhbc | "
"cpp | "
"sep-ext-cpp | "
"filecache | "
"run (default)")
("format,f", value<string>(&po.format),
@@ -226,7 +234,11 @@ int prepareOptions(CompilerOptions &po, int argc, char **argv) {
"php: trimmed (default) | inlined | pickled | typeinfo |"
" <any combination of them by any separator>; \n"
"hhbc: binary (default) | text; \n"
"cpp: cluster (default) | file | sys | exe | lib; \n"
"run: cluster (default) | file")
("cluster-count", value<int>(&po.clusterCount)->default_value(0),
"Cluster by file sizes and output roughly these many number of files. "
"Use 0 for no clustering.")
("input-dir", value<string>(&po.inputDir), "input directory")
("program", value<string>(&po.program)->default_value("program"),
"final program name to use")
@@ -273,6 +285,7 @@ int prepareOptions(CompilerOptions &po, int argc, char **argv) {
("branch", value<string>(&po.branch), "SVN branch")
("revision", value<int>(&po.revision), "SVN revision")
("output-dir,o", value<string>(&po.outputDir), "output directory")
("output-file", value<string>(&po.outputFile), "output file")
("sync-dir", value<string>(&po.syncDir),
"Files will be created in this directory first, then sync with output "
"directory without overwriting identical files. Great for incremental "
@@ -289,6 +302,13 @@ int prepareOptions(CompilerOptions &po, int argc, char **argv) {
("no-type-inference",
value<bool>(&po.noTypeInference)->default_value(false),
"turn off type inference for C++ code generation")
("no-min-include",
value<bool>(&po.noMinInclude)->default_value(false),
"turn off minimium include analysis when target is \"analyze\"")
("no-meta-info",
value<bool>(&po.noMetaInfo)->default_value(false),
"do not generate class map, function jump table and macros "
"when generating code; good for demo purposes")
("config,c", value<vector<string> >(&po.config)->composing(),
"config file name")
("config-dir", value<string>(&po.configDir),
@@ -307,6 +327,14 @@ int prepareOptions(CompilerOptions &po, int argc, char **argv) {
("file-cache",
value<string>(&po.filecache),
"if specified, generate a static file cache with this file name")
("rtti-directory", value<string>(&po.rttiDirectory)->default_value(""),
"the directory of rtti profiling data")
("java-root",
value<string>(&po.javaRoot)->default_value("php"),
"the root package of generated Java FFI classes")
("generate-ffi",
value<bool>(&po.generateFFI)->default_value(false),
"generate ffi stubs")
("dump",
value<bool>(&po.dump)->default_value(false),
"dump the program graph")
@@ -320,11 +348,24 @@ int prepareOptions(CompilerOptions &po, int argc, char **argv) {
value<bool>(&po.nofork)->default_value(false),
"forking is needed for large compilation to release memory before g++"
"compilation. turning off forking can help gdb debugging.")
("fl-annotate",
value<bool>(&po.fl_annotate)->default_value(false),
"Annotate emitted source with compiler file-line info")
("opts",
value<string>(&po.optimizations)->default_value(""),
"Set optimizations to enable/disable")
("ppp",
value<string>(&po.ppp)->default_value(""),
"Preprocessed partition configuration. To speed up distcc compilation, "
"bin/ppp.php can pre-compute better partition between different .cpp "
"files according to preprocessed file sizes, instead of original file "
"sizes (default). Run bin/ppp.php to generate an HDF configuration file "
"to specify here.")
#ifdef COMPILER_ID
("compiler-id", "display the git hash for the compiler id")
#endif
("repo-schema", "display the repo schema id used by this app")
("taint-status", "check if the compiler was built with taint enabled")
;
positional_options_description p;
@@ -334,7 +375,7 @@ int prepareOptions(CompilerOptions &po, int argc, char **argv) {
store(command_line_parser(argc, argv).options(desc).positional(p).run(),
vm);
notify(vm);
} catch (const unknown_option& e) {
} catch (unknown_option e) {
Logger::Error("Error in command line: %s\n\n", e.what());
cout << desc << "\n";
return -1;
@@ -344,8 +385,8 @@ int prepareOptions(CompilerOptions &po, int argc, char **argv) {
return 1;
}
if (vm.count("version")) {
#ifdef HHVM_VERSION
#undef HHVM_VERSION
#ifdef HPHP_VERSION
#undef HPHP_VERSION
#endif
#ifdef HPHP_COMPILER_STR
@@ -358,25 +399,37 @@ int prepareOptions(CompilerOptions &po, int argc, char **argv) {
#define HPHP_COMPILER_STR "HipHop Compiler v"
#endif
#define HHVM_VERSION(v) cout << HPHP_COMPILER_STR #v << "\n";
#include "../version" // nolint
#define HPHP_VERSION(v) cout << HPHP_COMPILER_STR #v << "\n";
#include "../version"
cout << "Compiler: " << kCompilerId << "\n";
cout << "Repo schema: " << kRepoSchemaId << "\n";
#ifdef COMPILER_ID
cout << "Compiler: " << COMPILER_ID << "\n";
#endif
cout << "Repo schema: " << VM::Repo::kSchemaId << "\n";
return 1;
}
#ifdef COMPILER_ID
if (vm.count("compiler-id")) {
cout << kCompilerId << "\n";
cout << COMPILER_ID << "\n";
return 1;
}
#endif
if (vm.count("repo-schema")) {
cout << kRepoSchemaId << "\n";
cout << VM::Repo::kSchemaId << "\n";
return 1;
}
if ((po.target == "hhbc" || po.target == "run") &&
if (vm.count("taint-status")) {
#ifdef TAINTED
cout << TAINTED << "\n";
#endif
return 1;
}
if (hhvm &&
(po.target == "hhbc" || po.target == "run") &&
po.format.find("exe") == string::npos) {
if (po.program == "program") {
po.program = "hhvm.hhbc";
@@ -392,6 +445,14 @@ int prepareOptions(CompilerOptions &po, int argc, char **argv) {
Logger::LogLevel = Logger::LogInfo;
}
// config and system
Option::GenerateCPPMain = true;
if (po.noMetaInfo) {
Option::GenerateCPPMetaInfo = false;
Option::GenerateCPPMacros = false;
}
Option::FlAnnotate = po.fl_annotate;
Hdf config;
for (vector<string>::const_iterator it = po.config.begin();
it != po.config.end(); ++it) {
@@ -443,36 +504,50 @@ int prepareOptions(CompilerOptions &po, int argc, char **argv) {
(Util::format_pattern(po.excludeStaticPatterns[i], true));
}
if (po.target == "hhbc" || po.target == "run") {
if (po.target == "cpp" && po.format == "sys") {
BuiltinSymbols::NoSuperGlobals = true; // so to generate super globals
Option::AnalyzePerfectVirtuals = false;
}
Option::SystemGen = (po.target == "cpp" && po.format == "sys") ;
if (hhvm && (po.target == "hhbc" || po.target == "run")) {
Option::OutputHHBC = true;
Option::AnalyzePerfectVirtuals = false;
}
Option::ProgramName = po.program;
Option::PreprocessedPartitionConfig = po.ppp;
if (po.format.empty()) {
if (po.target == "php") {
if (po.target == "cpp") {
po.format = "cluster";
} else if (po.target == "php") {
po.format = "trimmed";
} else if (po.target == "run") {
po.format = "binary";
} else if (po.target == "hhbc") {
po.format = hhvm ? "binary" : "cluster";
} else if (hhvm && po.target == "hhbc") {
po.format = "binary";
}
}
if (!po.docjson.empty()) {
if (po.target != "run" &&
po.target != "hhbc" &&
if (po.target != "cpp" &&
po.target != "run" &&
po.target != "analyze") {
Logger::Error(
"Cannot generate doc JSON file unless target is "
"'hhbc', 'run', or 'analyze'");
"'cpp', 'run', or 'analyze'");
} else {
Option::DocJson = po.docjson;
}
}
if (po.optimizeLevel == -1) {
po.optimizeLevel = 1;
if (Option::OutputHHBC) {
po.optimizeLevel = 1;
} else {
po.optimizeLevel = 1;
}
}
// we always do pre/post opt no matter the opt level
@@ -481,10 +556,15 @@ int prepareOptions(CompilerOptions &po, int argc, char **argv) {
if (po.optimizeLevel == 0) {
// --optimize-level=0 is equivalent to --opts=none
po.optimizations = "none";
Option::ParseTimeOpts = false;
if (Option::OutputHHBC) {
Option::ParseTimeOpts = false;
}
}
initialize_hhbbc_options();
if (po.generateFFI) {
Option::GenerateFFI = true;
Option::JavaFFIRootPackage = po.javaRoot;
}
return 0;
}
@@ -517,7 +597,6 @@ int process(const CompilerOptions &po) {
return lintTarget(po);
}
register_process_init();
init_thread_locals();
Timer timer(Timer::WallTime);
@@ -527,7 +606,9 @@ int process(const CompilerOptions &po) {
Package package(po.inputDir.c_str());
ar = package.getAnalysisResult();
hhbcTargetInit(po, ar);
if (hhvm && (po.target == "hhbc" || po.target == "run")) {
hhbcTargetInit(po, ar);
}
std::string errs;
if (!AliasManager::parseOptimizations(po.optimizations, errs)) {
@@ -540,21 +621,20 @@ int process(const CompilerOptions &po) {
BuiltinSymbols::LoadSuperGlobals();
ClassInfo::Load();
if (po.format == "sys") ar->setSystem();
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 (!BuiltinSymbols::Load(ar,
(po.target == "cpp" && po.format == "sys")
|| (po.target == "hhbc" && !Option::WholeProgram)
)) {
return false;
}
if (po.target == "hhbc" && !Option::WholeProgram) {
// We're trying to produce the same bytecode as runtime parsing.
// There's nothing to do.
BuiltinSymbols::NoSuperGlobals = false;
} else {
if (!BuiltinSymbols::Load(ar)) {
return false;
}
ar->loadBuiltins();
}
}
@@ -602,7 +682,6 @@ int process(const CompilerOptions &po) {
return 1;
}
if (Option::WholeProgram || po.target == "analyze") {
Timer timer(Timer::WallTime, "analyzeProgram");
ar->analyzeProgram();
}
}
@@ -623,12 +702,17 @@ int process(const CompilerOptions &po) {
ret = analyzeTarget(po, ar);
} else if (po.target == "php") {
ret = phpTarget(po, ar);
} else if (po.target == "hhbc") {
} else if (hhvm && po.target == "hhbc") {
ret = hhbcTarget(po, ar, fileCacheThread);
} else if (po.target == "cpp") {
ret = cppTarget(po, ar, fileCacheThread);
} else if (po.target == "run") {
ret = runTargetCheck(po, ar, fileCacheThread);
} else if (po.target == "filecache") {
// do nothing
} else if (po.target == "sep-ext-cpp") {
ar->setSepExtension();
ret = generateSepExtCpp(po, ar);
} else {
Logger::Error("Unknown target: %s", po.target.c_str());
return 1;
@@ -656,7 +740,7 @@ int process(const CompilerOptions &po) {
int runId = package.saveStatsToDB(server, seconds, po.branch,
po.revision);
package.commitStats(server, runId);
} catch (const DatabaseException& e) {
} catch (DatabaseException e) {
Logger::Error("%s", e.what());
}
} else {
@@ -681,7 +765,7 @@ int lintTarget(const CompilerOptions &po) {
for (unsigned int i = 0; i < po.inputs.size(); i++) {
string filename = po.inputDir + "/" + po.inputs[i];
try {
Scanner scanner(filename.c_str(), Option::GetScannerType());
Scanner scanner(filename.c_str(), Option::ScannerType);
Compiler::Parser parser(scanner, filename.c_str(),
AnalysisResultPtr(new AnalysisResult()));
if (!parser.parse()) {
@@ -807,16 +891,11 @@ 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";
RuntimeOption::EnableHipHopSyntax = Option::EnableHipHopSyntax;
RuntimeOption::EnableZendCompat = Option::EnableZendCompat;
RuntimeOption::EvalJitEnableRenameFunction = Option::JitEnableRenameFunction;
// Turn off commits, because we don't want systemlib to get included
RuntimeOption::RepoCommit = false;
}
int hhbcTarget(const CompilerOptions &po, AnalysisResultPtr ar,
@@ -848,7 +927,7 @@ int hhbcTarget(const CompilerOptions &po, AnalysisResultPtr ar,
/* without this, emitClass allows classes with interfaces to be
hoistable */
SystemLib::s_inited = true;
RuntimeOption::RepoCommit = true;
Option::AutoInline = -1;
if (po.optimizeLevel > 0) {
@@ -875,11 +954,11 @@ int hhbcTarget(const CompilerOptions &po, AnalysisResultPtr ar,
*/
string exe = po.outputDir + '/' + po.program;
string repo = "repo=" + exe + ".hhbc";
string buf = current_executable_path();
if (buf.empty()) return -1;
char buf[PATH_MAX];
if (!realpath("/proc/self/exe", buf)) return -1;
const char *argv[] = { "objcopy", "--add-section", repo.c_str(),
buf.c_str(), exe.c_str(), 0 };
buf, exe.c_str(), 0 };
string out;
ret = Process::Exec(argv[0], argv, nullptr, out, nullptr) ? 0 : 1;
}
@@ -889,10 +968,114 @@ int hhbcTarget(const CompilerOptions &po, AnalysisResultPtr ar,
///////////////////////////////////////////////////////////////////////////////
int cppTarget(const CompilerOptions &po, AnalysisResultPtr ar,
AsyncFileCacheSaver &fcThread, bool allowSys /* = true */) {
int ret = 0;
int clusterCount = po.clusterCount;
// format
CodeGenerator::Output format = CodeGenerator::InvalidOutput;
if (po.format == "file") {
clusterCount = 0;
format = CodeGenerator::FileCPP;
} else if (po.format == "cluster") {
format = CodeGenerator::ClusterCPP;
} else if (po.format == "sys" && allowSys) {
clusterCount = 0;
format = CodeGenerator::SystemCPP;
ar->setSystem();
} else if (po.format == "exe" || po.format == "lib") {
format = CodeGenerator::ClusterCPP;
}
if (format == CodeGenerator::InvalidOutput) {
Logger::Error("Unknown format for CPP target: %s", po.format.c_str());
return 1;
}
if (!Option::RTTIOutputFile.empty()) {
if (!po.rttiDirectory.empty()) {
Option::UseRTTIProfileData = true;
ar->cloneRTTIFuncs(po.rttiDirectory.c_str());
} else {
Option::GenRTTIProfileData = true;
}
}
ret = analyzeTarget(po, ar);
{
Timer timer(Timer::WallTime, "creating CPP files");
if (po.syncDir.empty()) {
ar->setOutputPath(po.outputDir);
ar->outputAllCPP(format, clusterCount, nullptr);
} else {
ar->setOutputPath(po.syncDir);
ar->outputAllCPP(format, clusterCount, &po.outputDir);
if (!po.filecache.empty()) {
fcThread.waitForEnd();
}
Util::syncdir(po.outputDir, po.syncDir);
boost::filesystem::remove_all(po.syncDir);
}
}
return ret;
}
///////////////////////////////////////////////////////////////////////////////
int generateSepExtCpp(const CompilerOptions &po, AnalysisResultPtr ar) {
ar->outputCPPSepExtensionImpl(po.outputFile);
return 0;
}
///////////////////////////////////////////////////////////////////////////////
int buildTarget(const CompilerOptions &po) {
const char *HPHP_HOME = getenv("HPHP_HOME");
if (!HPHP_HOME || !*HPHP_HOME) {
throw Exception("Environment variable HPHP_HOME is not set.");
}
string cmd = string(HPHP_HOME) + "/hphp/legacy/run.sh";
string flags;
if (getenv("RELEASE")) flags += "RELEASE=1 ";
if (getenv("SHOW_LINK")) flags += "SHOW_LINK=1 ";
if (getenv("SHOW_COMPILE")) flags += "SHOW_COMPILE=1 ";
if (po.format == "lib") flags += "HPHP_BUILD_LIBRARY=1 ";
if (Option::GenerateFFI) flags += "HPHP_BUILD_FFI=1 ";
const char *argv[] = {"", po.outputDir.c_str(),
po.program.c_str(), flags.c_str(), nullptr};
if (getenv("SHOW_COMPILE")) {
Logger::Info ("Compile command: %s %s %s", po.outputDir.c_str(),
po.program.c_str(), flags.c_str());
}
Timer timer(Timer::WallTime, "compiling and linking CPP files");
string out, err;
bool ret = Process::Exec(cmd.c_str(), argv, nullptr, out, &err);
if (getenv("SHOW_COMPILE")) {
Logger::Info("%s", out.c_str());
} else {
Logger::Verbose("%s", out.c_str());
}
if (!err.empty()) {
Logger::Error("%s", err.c_str());
}
if (!ret) {
return 1;
}
return 0;
}
int runTargetCheck(const CompilerOptions &po, AnalysisResultPtr ar,
AsyncFileCacheSaver &fcThread) {
// generate code
if (hhbcTarget(po, ar, fcThread)) {
if (po.format == "sep") return 1;
if (hhvm ?
hhbcTarget(po, ar, fcThread) :
cppTarget(po, ar, fcThread, false)) {
return 1;
}
@@ -906,7 +1089,10 @@ int runTargetCheck(const CompilerOptions &po, AnalysisResultPtr ar,
}
int runTarget(const CompilerOptions &po) {
int ret = 0;
int ret = hhvm ? 0 : buildTarget(po);
if (ret) {
return ret;
}
// If there are more than one input files, we need one extra arg to run.
// If it's missing, we will stop right here, with compiled code.
@@ -917,21 +1103,18 @@ int runTarget(const CompilerOptions &po) {
// run the executable
string cmd;
if (po.format.find("exe") == string::npos) {
string buf = current_executable_path();
if (buf.empty()) return -1;
if (hhvm && po.format.find("exe") == string::npos) {
char buf[PATH_MAX];
if (!realpath("/proc/self/exe", buf)) return -1;
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;
cmd += string(" --file ") +
(po.inputs.size() == 1 ? po.inputs[0] : "") +
" " + po.programArgs;
Logger::Info("running executable: %s", cmd.c_str());
(po.inputs.size() == 1 ? po.inputs[0] : "") + po.programArgs;
Logger::Info("running executable %s...", cmd.c_str());
ret = Util::ssystem(cmd.c_str());
if (ret && ret != -1) ret = 1;
+1 -1
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
+20 -35
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -14,21 +14,21 @@
+----------------------------------------------------------------------+
*/
#include "hphp/compiler/construct.h"
#include "hphp/compiler/parser/parser.h"
#include "hphp/util/util.h"
#include <compiler/construct.h>
#include <compiler/parser/parser.h>
#include <util/util.h>
#include "hphp/compiler/analysis/file_scope.h"
#include "hphp/compiler/analysis/function_scope.h"
#include "hphp/compiler/analysis/class_scope.h"
#include "hphp/compiler/analysis/analysis_result.h"
#include "hphp/compiler/analysis/ast_walker.h"
#include <compiler/analysis/file_scope.h>
#include <compiler/analysis/function_scope.h>
#include <compiler/analysis/class_scope.h>
#include <compiler/analysis/analysis_result.h>
#include <compiler/analysis/ast_walker.h>
#include "hphp/compiler/statement/function_statement.h"
#include <compiler/statement/function_statement.h>
#include "hphp/compiler/expression/simple_function_call.h"
#include "hphp/compiler/expression/simple_variable.h"
#include "hphp/compiler/expression/closure_expression.h"
#include <compiler/expression/simple_function_call.h>
#include <compiler/expression/simple_variable.h>
#include <compiler/expression/closure_expression.h>
#include <iomanip>
using namespace HPHP;
@@ -44,7 +44,7 @@ void Construct::resetScope(BlockScopeRawPtr scope, bool resetOrigScope) {
setBlockScope(scope);
if (resetOrigScope) {
ExpressionPtr expr =
dynamic_pointer_cast<Expression>(shared_from_this());
boost::dynamic_pointer_cast<Expression>(shared_from_this());
if (expr) {
expr->setOriginalScope(scope);
}
@@ -313,7 +313,7 @@ void Construct::dumpNode(int spc) {
}
std::cout << "-> 0x" << std::hex << std::setfill('0')
<< std::setw(10) << (int64_t)this << std::dec;
<< std::setw(10) << (int64)this << std::dec;
std::cout << " " << name << "(" << type << ") ";
if (id) {
@@ -322,12 +322,12 @@ void Construct::dumpNode(int spc) {
if (idPtr) {
std::cout << "idp=0x" <<
std::hex << std::setfill('0') << std::setw(10) <<
(int64_t)idPtr.get() << " ";
(int64)idPtr.get() << " ";
}
if (idCsePtr) {
std::cout << "idcsep=0x" <<
std::hex << std::setfill('0') << std::setw(10) <<
(int64_t)idCsePtr.get() << " ";
(int64)idCsePtr.get() << " ";
}
if (value != "") {
@@ -439,7 +439,7 @@ public:
// HACK: dump the closure function as a "child" of the
// closure expression
ClosureExpressionPtr c =
dynamic_pointer_cast<ClosureExpression>(cp);
boost::dynamic_pointer_cast<ClosureExpression>(cp);
if (c) {
c->getClosureFunction()->dump(m_spc, m_ar);
}
@@ -454,8 +454,7 @@ private:
void Construct::dump(int spc, AnalysisResultConstPtr ar) {
ConstructDumper cd(spc, ar);
cd.walk(AstWalkerStateVec(ConstructRawPtr(this)),
ConstructRawPtr(), ConstructRawPtr());
cd.walk(ConstructRawPtr(this), ConstructRawPtr(), ConstructRawPtr());
}
void Construct::dump(int spc, AnalysisResultConstPtr ar, bool functionOnly,
@@ -469,23 +468,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());
}
+16 -24
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -14,13 +14,13 @@
+----------------------------------------------------------------------+
*/
#ifndef incl_HPHP_CONSTRUCT_H_
#define incl_HPHP_CONSTRUCT_H_
#ifndef __CONSTRUCT_H__
#define __CONSTRUCT_H__
#include "hphp/compiler/json.h"
#include "hphp/compiler/code_generator.h"
#include "hphp/compiler/analysis/code_error.h"
#include "hphp/compiler/analysis/block_scope.h"
#include <util/json.h>
#include <compiler/code_generator.h>
#include <compiler/analysis/code_error.h>
#include <compiler/analysis/block_scope.h>
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
@@ -67,7 +67,7 @@ public:
/**
* Base class of Expression and Statement.
*/
class Construct : public std::enable_shared_from_this<Construct>,
class Construct : public boost::enable_shared_from_this<Construct>,
public JSON::CodeError::ISerializable {
protected:
Construct(BlockScopePtr scope, LocationPtr loc);
@@ -178,10 +178,7 @@ public:
return m_blockScope->getContainingClass();
}
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);
void parseTimeFatal(Compiler::ErrorType error, const char *fmt, ...);
virtual int getLocalEffects() const { return UnknownEffect;}
int getChildrenEffects() const;
int getContainedEffects() const;
@@ -189,16 +186,15 @@ public:
virtual bool kidUnused(int i) const { return false; }
template<typename T>
static std::shared_ptr<T> Clone(std::shared_ptr<T> constr) {
static boost::shared_ptr<T> Clone(boost::shared_ptr<T> constr) {
if (constr) {
return dynamic_pointer_cast<T>(constr->clone());
return boost::dynamic_pointer_cast<T>(constr->clone());
}
return std::shared_ptr<T>();
return boost::shared_ptr<T>();
}
template<typename T>
std::shared_ptr<T> Clone(std::shared_ptr<T> constr,
BlockScopePtr scope) {
boost::shared_ptr<T> Clone(boost::shared_ptr<T> constr, BlockScopePtr scope) {
if (constr) {
constr = constr->clone();
constr->resetScope(scope);
@@ -246,15 +242,11 @@ public:
const AstWalkerStateVec &start,
ConstructPtr endBefore, ConstructPtr endAfter);
/**
* Generates a serialized Code Model corresponding to this AST.
*/
virtual void outputCodeModel(CodeGenerator &cg) = 0;
/**
* Called when generating code.
*/
virtual void outputPHP(CodeGenerator &cg, AnalysisResultPtr ar) = 0;
virtual void outputCPP(CodeGenerator &cg, AnalysisResultPtr ar) = 0;
/**
* Implements JSON::CodeError::ISerializable.
@@ -323,7 +315,7 @@ public:
int getLocalEffects() const { return m_localEffects; }
virtual void effectsCallback() = 0;
protected:
explicit LocalEffectsContainer(Construct::Effect localEffect) :
LocalEffectsContainer(Construct::Effect localEffect) :
m_localEffects(localEffect) {}
LocalEffectsContainer() :
m_localEffects(0) {}
@@ -342,4 +334,4 @@ protected:
///////////////////////////////////////////////////////////////////////////////
}
#endif // incl_HPHP_CONSTRUCT_H_
#endif // __CONSTRUCT_H__
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -14,18 +14,17 @@
+----------------------------------------------------------------------+
*/
#include "hphp/compiler/expression/array_element_expression.h"
#include "hphp/compiler/expression/simple_variable.h"
#include "hphp/compiler/expression/scalar_expression.h"
#include "hphp/compiler/analysis/variable_table.h"
#include "hphp/compiler/analysis/code_error.h"
#include "hphp/compiler/code_model_enums.h"
#include "hphp/compiler/option.h"
#include "hphp/compiler/expression/static_member_expression.h"
#include "hphp/compiler/analysis/function_scope.h"
#include "hphp/parser/hphp.tab.hpp"
#include "hphp/runtime/base/complex-types.h"
#include "hphp/runtime/base/builtin-functions.h"
#include <compiler/expression/array_element_expression.h>
#include <compiler/expression/simple_variable.h>
#include <compiler/expression/scalar_expression.h>
#include <compiler/analysis/variable_table.h>
#include <compiler/analysis/code_error.h>
#include <compiler/option.h>
#include <compiler/expression/static_member_expression.h>
#include <compiler/analysis/function_scope.h>
#include <util/parser/hphp.tab.hpp>
#include <runtime/base/complex_types.h>
#include <runtime/base/builtin_functions.h>
using namespace HPHP;
@@ -80,7 +79,8 @@ void ArrayElementExpression::setContext(Context context) {
if (m_variable->is(Expression::KindOfObjectPropertyExpression)) {
m_variable->clearContext(Expression::NoLValueWrapper);
}
// special case for $GLOBALS[], we do not need lvalue wrapper
// special case for $GLOBALS[], see the if (m_global) check in
// ArrayElementExpression::outputCPPImpl, we do not need lvalue wrapper
if (m_variable->is(Expression::KindOfSimpleVariable)) {
SimpleVariablePtr var =
dynamic_pointer_cast<SimpleVariable>(m_variable);
@@ -168,6 +168,16 @@ void ArrayElementExpression::analyzeProgram(AnalysisResultPtr ar) {
m_variable->analyzeProgram(ar);
if (m_offset) m_offset->analyzeProgram(ar);
if (ar->getPhase() == AnalysisResult::AnalyzeFinal) {
if (!m_global && (m_context & AccessContext) &&
!(m_context & (LValue|RefValue|DeepReference|
UnsetContext|RefParameter|InvokeArgument))) {
TypePtr type = m_variable->getActualType();
if (!type ||
(!type->is(Type::KindOfString) && !type->is(Type::KindOfArray))) {
FunctionScopePtr scope = getFunctionScope();
if (scope && !needsCSE()) scope->setNeedsRefTemp();
}
}
if (m_global) {
if (getContext() & (LValue|RefValue|DeepReference)) {
setContext(NoLValueWrapper);
@@ -182,6 +192,8 @@ void ArrayElementExpression::analyzeProgram(AnalysisResultPtr ar) {
shared_from_this());
}
}
FunctionScopePtr scope = getFunctionScope();
if (scope) scope->setNeedsCheckMem();
} else {
TypePtr at(m_variable->getActualType());
TypePtr et(m_variable->getExpectedType());
@@ -218,10 +230,10 @@ int ArrayElementExpression::getKidCount() const {
void ArrayElementExpression::setNthKid(int n, ConstructPtr cp) {
switch (n) {
case 0:
m_variable = dynamic_pointer_cast<Expression>(cp);
m_variable = boost::dynamic_pointer_cast<Expression>(cp);
break;
case 1:
m_offset = dynamic_pointer_cast<Expression>(cp);
m_offset = boost::dynamic_pointer_cast<Expression>(cp);
break;
default:
assert(false);
@@ -246,14 +258,6 @@ ExpressionPtr ArrayElementExpression::preOptimize(AnalysisResultConstPtr ar) {
return replaceValue(makeConstant(ar, "null"));
}
if (m_offset->isScalar() && m_offset->getScalarValue(o)) {
if (v.isString()) {
if (!o.isInteger() ||
o.toInt64Val() < 0 ||
o.toInt64Val() >= v.toCStrRef().size()) {
// warnings should be raised...
return ExpressionPtr();
}
}
try {
g_context->setThrowAllErrors(true);
Variant res = v.rvalAt(
@@ -389,42 +393,6 @@ ExpressionPtr ArrayElementExpression::unneeded() {
return Expression::unneeded();
}
///////////////////////////////////////////////////////////////////////////////
void ArrayElementExpression::outputCodeModel(CodeGenerator &cg) {
if (Option::ConvertSuperGlobals && m_global && !m_dynamicGlobal &&
getScope() && (getScope()->is(BlockScope::ProgramScope) ||
getScope()-> getVariables()->
isConvertibleSuperGlobal(m_globalName))) {
cg.printObjectHeader("SimpleVariableExpression", 2);
cg.printPropertyHeader("name");
cg.printValue(m_globalName);
cg.printPropertyHeader("sourceLocation");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
} else if (m_offset) {
cg.printObjectHeader("BinaryOpExpression", 4);
cg.printPropertyHeader("expression1");
m_variable->outputCodeModel(cg);
cg.printPropertyHeader("expression2");
cg.printExpression(m_offset, false);
cg.printPropertyHeader("operation");
cg.printValue(PHP_ARRAY_ELEMENT);
cg.printPropertyHeader("sourceLocation");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
} else {
cg.printObjectHeader("UnaryOpExpression", 3);
cg.printPropertyHeader("expression");
m_variable->outputCodeModel(cg);
cg.printPropertyHeader("operation");
cg.printValue(PHP_ARRAY_APPEND_POINT_OP);
cg.printPropertyHeader("sourceLocation");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -442,3 +410,209 @@ void ArrayElementExpression::outputPHP(CodeGenerator &cg,
cg_printf("]");
}
}
bool ArrayElementExpression::preOutputCPP(CodeGenerator &cg,
AnalysisResultPtr ar, int state) {
return preOutputOffsetLHS(cg, ar, state);
}
void ArrayElementExpression::outputCPPImpl(CodeGenerator &cg,
AnalysisResultPtr ar) {
if (m_global) {
if (!m_globalName.empty()) {
VariableTablePtr variables = getScope()->getVariables();
string name = variables->getGlobalVariableName(ar, m_globalName);
cg_printf("g->%s", name.c_str());
} else {
cg_printf("((LVariableTable *)g)->get(");
m_offset->outputCPP(cg, ar);
cg_printf(")");
}
} else {
TypePtr type = m_variable->getType();
if (hasContext(UnsetContext)) {
cg_printf("unsetLval(");
m_variable->outputCPP(cg, ar);
cg_printf(", ");
} else {
if (m_variable->is(Expression::KindOfScalarExpression) ||
(type && (type->isInteger() ||
type->is(Type::KindOfDouble) ||
type->is(Type::KindOfObject) ||
type->is(Type::KindOfBoolean)))) {
cg_printf(type && type->is(Type::KindOfString) ? "((String)" :
"((Variant)");
m_variable->outputCPP(cg, ar);
cg_printf(")");
} else {
m_variable->outputCPP(cg, ar);
}
}
if (m_offset) {
bool lvalAt = false;
bool rvalAt = false;
bool byRef = false;
bool arrRef = false;
const char *sep = ", AccessFlags::";
bool isArrayType = type && type->is(Type::KindOfArray);
bool isStringType = type && type->is(Type::KindOfString);
bool isRealChainRoot = isChainRoot() && hasCPPCseTemp();
TypePtr t;
bool hasCseStore = isRealChainRoot && GetCseTempInfo(
ar,
static_pointer_cast<Expression>(shared_from_this()),
t);
if (hasContext(UnsetContext)) {
// do nothing
} else if (hasContext(InvokeArgument) && cg.callInfoTop() != -1) {
assert(!isRealChainRoot); // TODO: handle this case
cg_printf(".argvalAt(cit%d->isRef(%d), ", cg.callInfoTop(), m_argNum);
} else if (m_context & (LValue|RefValue|DeepReference)) {
// if we see an array access element in LValue context, the
// type inference pass will never infer its type to be a string
assert(!isStringType);
if (isRealChainRoot && !isArrayType) {
// chain roots for non array types (variants) should call
// lvalRef()
cg_printf(".lvalRef(");
} else {
cg_printf(".lvalAt(");
}
lvalAt = true;
} else {
byRef =
((m_context & AccessContext) || isRealChainRoot) && !isStringType;
arrRef = byRef && isArrayType;
cg_printf(".rval%s%s(",
arrRef || !byRef ? "At" : "", byRef ? "Ref" : "");
rvalAt = true;
}
m_offset->outputCPP(cg, ar);
if (!isStringType) {
if (rvalAt) {
if (byRef && !arrRef) {
string tmp;
if (hasCseStore) {
tmp = string(Option::CseTempStoragePrefix) + m_cppCseTemp;
} else {
tmp = cg.getReferenceTemp();
}
cg_printf(", %s", tmp.empty() ? "Variant()" : tmp.c_str());
}
if (!hasContext(ExistContext)) {
cg_printf(", AccessFlags::Error"); // raise undefined index error
sep = "_";
}
} else if (lvalAt) {
if (hasCseStore && !isArrayType) {
cg_printf(", %s%s",
Option::CseTempStoragePrefix, m_cppCseTemp.c_str());
}
if (hasContext(AccessContext)) {
// Dont copy the array if the element is an object, or
// is referenced.
// This is safe in AccessContext (the parent is an ArrayElement,
// or an ObjectProperty) because applying [] to an object will
// either invoke OffsetGet, or fatal, and modifications to a
// referenced element would be reflected in all copies
// of the array anyway.
cg_printf(", AccessFlags::CheckExist");
sep = "_";
}
}
ScalarExpressionPtr sc =
dynamic_pointer_cast<ScalarExpression>(m_offset);
if (!hasContext(UnsetContext) && sc && sc->isLiteralString()) {
String s(sc->getLiteralString());
int64 n;
if (!s.get()->isStrictlyInteger(n)) {
if (lvalAt || rvalAt) {
cg_printf("%sKey", sep);
} else {
cg_printf(", true"); // skip toKey() at run time
}
}
}
}
cg_printf(")");
} else {
cg_printf(".lvalAt()");
}
}
}
void ArrayElementExpression::outputCPPExistTest(CodeGenerator &cg,
AnalysisResultPtr ar, int op) {
switch (op) {
case T_ISSET: cg_printf("isset("); break;
case T_EMPTY: cg_printf("empty("); break;
default: assert(false);
}
if (m_global) {
if (!m_globalName.empty()) {
VariableTablePtr variables = getScope()->getVariables();
string name = variables->getGlobalVariableName(ar, m_globalName);
cg_printf("g->%s", name.c_str());
} else {
cg_printf("((LVariableTable *)g)->get(");
m_offset->outputCPP(cg, ar);
cg_printf(")");
}
} else {
m_variable->outputCPP(cg, ar);
cg_printf(", ");
m_offset->outputCPP(cg, ar);
ScalarExpressionPtr sc =
dynamic_pointer_cast<ScalarExpression>(m_offset);
if (sc) {
if (sc->isLiteralString()) {
String s(sc->getLiteralString());
int64 n;
if (!s.get()->isStrictlyInteger(n)) {
cg_printf(", true"); // skip toKey() at run time
}
}
}
}
cg_printf(")");
}
void ArrayElementExpression::outputCPPUnset(CodeGenerator &cg,
AnalysisResultPtr ar) {
if (isSuperGlobal()) {
Expression::outputCPPUnset(cg, ar);
} else {
TypePtr expected = m_variable->getExpectedType();
TypePtr implemented = m_variable->getImplementedType();
bool wrap = false;
if (TypePtr t = m_variable->getActualType()) {
if (t->is(Type::KindOfObject)) {
if (!m_variable->getImplementedType() ||
!m_variable->getImplementedType()->is(Type::KindOfVariant)) {
cg_printf("((Variant)(");
wrap = true;
}
m_variable->setImplementedType(TypePtr());
m_variable->setExpectedType(TypePtr());
}
}
m_variable->outputCPP(cg, ar);
if (wrap) cg_printf("))");
m_variable->setExpectedType(expected);
m_variable->setImplementedType(implemented);
cg_printf(".weakRemove(");
m_offset->outputCPP(cg, ar);
ScalarExpressionPtr sc =
dynamic_pointer_cast<ScalarExpression>(m_offset);
if (sc && sc->isLiteralString()) {
String s(sc->getLiteralString());
int64 n;
if (!s->isStrictlyInteger(n)) {
cg_printf(", true");
}
}
cg_printf(")");
}
}
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -14,10 +14,10 @@
+----------------------------------------------------------------------+
*/
#ifndef incl_HPHP_ARRAY_ELEMENT_EXPRESSION_H_
#define incl_HPHP_ARRAY_ELEMENT_EXPRESSION_H_
#ifndef __ARRAY_ELEMENT_EXPRESSION_H__
#define __ARRAY_ELEMENT_EXPRESSION_H__
#include "hphp/compiler/expression/expression.h"
#include <compiler/expression/expression.h>
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
@@ -56,6 +56,11 @@ public:
bool appendClass(ExpressionPtr cls,
AnalysisResultConstPtr ar, FileScopePtr file);
virtual void outputCPPExistTest(CodeGenerator &cg, AnalysisResultPtr ar,
int op);
virtual void outputCPPUnset(CodeGenerator &cg, AnalysisResultPtr ar);
bool preOutputCPP(CodeGenerator &cg, AnalysisResultPtr ar, int state);
virtual bool canonCompare(ExpressionPtr e) const;
private:
@@ -70,4 +75,4 @@ private:
///////////////////////////////////////////////////////////////////////////////
}
#endif // incl_HPHP_ARRAY_ELEMENT_EXPRESSION_H_
#endif // __ARRAY_ELEMENT_EXPRESSION_H__
+51 -27
Ver Arquivo
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 2010- 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 |
@@ -14,11 +14,10 @@
+----------------------------------------------------------------------+
*/
#include "hphp/compiler/expression/array_pair_expression.h"
#include "hphp/compiler/expression/scalar_expression.h"
#include "hphp/compiler/expression/unary_op_expression.h"
#include "hphp/compiler/code_model_enums.h"
#include "hphp/parser/hphp.tab.hpp"
#include <compiler/expression/array_pair_expression.h>
#include <compiler/expression/scalar_expression.h>
#include <compiler/expression/unary_op_expression.h>
#include <util/parser/hphp.tab.hpp>
using namespace HPHP;
@@ -95,10 +94,10 @@ int ArrayPairExpression::getKidCount() const {
void ArrayPairExpression::setNthKid(int n, ConstructPtr cp) {
switch (n) {
case 0:
m_name = dynamic_pointer_cast<Expression>(cp);
m_name = boost::dynamic_pointer_cast<Expression>(cp);
break;
case 1:
m_value = dynamic_pointer_cast<Expression>(cp);
m_value = boost::dynamic_pointer_cast<Expression>(cp);
break;
default:
assert(false);
@@ -123,29 +122,17 @@ bool ArrayPairExpression::canonCompare(ExpressionPtr e) const {
return m_ref == a->m_ref;
}
///////////////////////////////////////////////////////////////////////////////
void ArrayPairExpression::outputCodeModel(CodeGenerator &cg) {
if (m_name) {
cg.printObjectHeader("BinaryOpExpression", 4);
cg.printPropertyHeader("expression1");
m_name->outputCodeModel(cg);
cg.printPropertyHeader("expression2");
cg.printExpression(m_value, m_ref);
cg.printPropertyHeader("operation");
cg.printValue(PHP_ARRAY_PAIR);
cg.printPropertyHeader("sourceLocation");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
} else {
cg.printExpression(m_value, m_ref);
}
return;
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
void ArrayPairExpression::preOutputStash(CodeGenerator &cg,
AnalysisResultPtr ar,
int state) {
if (m_name) m_name->preOutputStash(cg, ar, state);
m_value->preOutputStash(cg, ar, state);
}
void ArrayPairExpression::outputPHP(CodeGenerator &cg, AnalysisResultPtr ar) {
if (m_name) {
m_name->outputPHP(cg, ar);
@@ -154,3 +141,40 @@ void ArrayPairExpression::outputPHP(CodeGenerator &cg, AnalysisResultPtr ar) {
if (m_ref) cg_printf("&");
m_value->outputPHP(cg, ar);
}
void ArrayPairExpression::outputCPPImpl(CodeGenerator &cg,
AnalysisResultPtr ar) {
bool keyConverted = false;
if (m_name) {
keyConverted = outputCPPName(cg, ar);
cg_printf(", ");
}
m_value->outputCPP(cg, ar);
if (m_name && keyConverted && !m_collection) {
cg_printf(", true");
}
}
bool ArrayPairExpression::outputCPPName(CodeGenerator &cg,
AnalysisResultPtr ar) {
assert(m_name);
ScalarExpressionPtr sc = dynamic_pointer_cast<ScalarExpression>(m_name);
if (sc) {
if (sc->isLiteralString()) {
string s = sc->getLiteralString();
int64 res;
if (is_strictly_integer(s.c_str(), s.size(), res)) {
cg_printf("%sL", s.c_str());
} else {
m_name->outputCPP(cg, ar);
}
return true;
}
if (sc->isLiteralInteger()) {
m_name->outputCPP(cg, ar);
return true;
}
}
m_name->outputCPP(cg, ar);
return false;
}

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